source: mainline/kernel/arch/ia64/src/mm/tlb.c@ 9aed144

lfn serial ticket/834-toolchain-update topic/fix-logger-deadlock topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 9aed144 was 9aed144, checked in by Jakub Jermar <jakub@…>, 15 years ago

Finish transition to lock-free page_mapping_find() in TLB miss handlers.

  • Simply drop the calls to page_table_lock/unlock() in ia64 and sparc64 TLB miss handlers.

As for why this is possible:

  • page_mapping_find() cannot race with page_table_remove() because page_mapping_find() is called only when interrupts are disabled, which prevents TLB shootdown from starting, which in turn prevents page_table_remove() from running
  • page_mapping_insert() will not negatively interfere with page_mapping_find() because page_mapping_insert() adds a fully initialized pte_t to the end of the hash bucket
  • Property mode set to 100644
File size: 18.6 KB
RevLine 
[36b01bb2]1/*
[df4ed85]2 * Copyright (c) 2006 Jakub Jermar
[36b01bb2]3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
[5bda2f3e]29/** @addtogroup ia64mm
[b45c443]30 * @{
31 */
32/** @file
33 */
34
[36b01bb2]35/*
36 * TLB management.
37 */
38
39#include <mm/tlb.h>
[a0d74fd]40#include <mm/asid.h>
[9ad03fe]41#include <mm/page.h>
42#include <mm/as.h>
[bc78c75]43#include <arch/mm/tlb.h>
[a0d74fd]44#include <arch/mm/page.h>
[68091bd]45#include <arch/mm/vhpt.h>
[89298e3]46#include <arch/barrier.h>
[2c49fbbe]47#include <arch/interrupt.h>
[7c322bd]48#include <arch/pal/pal.h>
49#include <arch/asm.h>
[2c49fbbe]50#include <panic.h>
[1065603e]51#include <print.h>
[9ad03fe]52#include <arch.h>
[a175a67]53#include <interrupt.h>
[36b01bb2]54
[5bda2f3e]55#define IO_FRAME_BASE 0xFFFFC000000
56
[ef67bab]57/** Invalidate all TLB entries. */
[36b01bb2]58void tlb_invalidate_all(void)
59{
[ee289cf0]60 ipl_t ipl;
61 uintptr_t adr;
62 uint32_t count1, count2, stride1, stride2;
[5bda2f3e]63
[6c441cf8]64 unsigned int i, j;
[5bda2f3e]65
[ee289cf0]66 adr = PAL_PTCE_INFO_BASE();
67 count1 = PAL_PTCE_INFO_COUNT1();
68 count2 = PAL_PTCE_INFO_COUNT2();
69 stride1 = PAL_PTCE_INFO_STRIDE1();
70 stride2 = PAL_PTCE_INFO_STRIDE2();
[5bda2f3e]71
[ee289cf0]72 ipl = interrupts_disable();
[5bda2f3e]73
[6c441cf8]74 for (i = 0; i < count1; i++) {
75 for (j = 0; j < count2; j++) {
[e7b7be3f]76 asm volatile (
[5bda2f3e]77 "ptc.e %[adr] ;;"
78 :: [adr] "r" (adr)
[ee289cf0]79 );
80 adr += stride2;
[7c322bd]81 }
[ee289cf0]82 adr += stride1;
83 }
[5bda2f3e]84
[ee289cf0]85 interrupts_restore(ipl);
[5bda2f3e]86
[ee289cf0]87 srlz_d();
88 srlz_i();
[5bda2f3e]89
[68091bd]90#ifdef CONFIG_VHPT
[ee289cf0]91 vhpt_invalidate_all();
[5bda2f3e]92#endif
[36b01bb2]93}
94
95/** Invalidate entries belonging to an address space.
96 *
[5bda2f3e]97 * @param asid Address space identifier.
98 *
[36b01bb2]99 */
100void tlb_invalidate_asid(asid_t asid)
101{
[a82500ce]102 tlb_invalidate_all();
[36b01bb2]103}
[bc78c75]104
[a82500ce]105
[98000fb]106void tlb_invalidate_pages(asid_t asid, uintptr_t page, size_t cnt)
[a82500ce]107{
[5bda2f3e]108 region_register_t rr;
[d0cf9de]109 bool restore_rr = false;
[1065603e]110 int b = 0;
111 int c = cnt;
[5bda2f3e]112
[7f1c620]113 uintptr_t va;
[1065603e]114 va = page;
[5bda2f3e]115
[d0cf9de]116 rr.word = rr_read(VA2VRN(va));
117 if ((restore_rr = (rr.map.rid != ASID2RID(asid, VA2VRN(va))))) {
118 /*
119 * The selected region register does not contain required RID.
120 * Save the old content of the register and replace the RID.
121 */
[5bda2f3e]122 region_register_t rr0;
123
[d0cf9de]124 rr0 = rr;
125 rr0.map.rid = ASID2RID(asid, VA2VRN(va));
126 rr_write(VA2VRN(va), rr0.word);
127 srlz_d();
128 srlz_i();
129 }
130
[5bda2f3e]131 while (c >>= 1)
[1065603e]132 b++;
133 b >>= 1;
[7f1c620]134 uint64_t ps;
[d0cf9de]135
[1065603e]136 switch (b) {
[666773c]137 case 0: /* cnt 1 - 3 */
[ee289cf0]138 ps = PAGE_WIDTH;
139 break;
[666773c]140 case 1: /* cnt 4 - 15 */
141 ps = PAGE_WIDTH + 2;
142 va &= ~((1 << ps) - 1);
[ee289cf0]143 break;
[666773c]144 case 2: /* cnt 16 - 63 */
145 ps = PAGE_WIDTH + 4;
146 va &= ~((1 << ps) - 1);
[ee289cf0]147 break;
[666773c]148 case 3: /* cnt 64 - 255 */
149 ps = PAGE_WIDTH + 6;
150 va &= ~((1 << ps) - 1);
[ee289cf0]151 break;
[666773c]152 case 4: /* cnt 256 - 1023 */
153 ps = PAGE_WIDTH + 8;
154 va &= ~((1 << ps) - 1);
[ee289cf0]155 break;
[666773c]156 case 5: /* cnt 1024 - 4095 */
157 ps = PAGE_WIDTH + 10;
158 va &= ~((1 << ps) - 1);
[ee289cf0]159 break;
[666773c]160 case 6: /* cnt 4096 - 16383 */
161 ps = PAGE_WIDTH + 12;
162 va &= ~((1 << ps) - 1);
[ee289cf0]163 break;
[666773c]164 case 7: /* cnt 16384 - 65535 */
165 case 8: /* cnt 65536 - (256K - 1) */
166 ps = PAGE_WIDTH + 14;
167 va &= ~((1 << ps) - 1);
[ee289cf0]168 break;
169 default:
[666773c]170 ps = PAGE_WIDTH + 18;
171 va &= ~((1 << ps) - 1);
[ee289cf0]172 break;
[d0cf9de]173 }
[5bda2f3e]174
175 for (; va < (page + cnt * PAGE_SIZE); va += (1 << ps))
176 asm volatile (
177 "ptc.l %[va], %[ps] ;;"
178 :: [va]"r" (va),
179 [ps] "r" (ps << 2)
180 );
181
[d0cf9de]182 srlz_d();
183 srlz_i();
184
185 if (restore_rr) {
186 rr_write(VA2VRN(va), rr.word);
187 srlz_d();
188 srlz_i();
189 }
[a82500ce]190}
191
[95042fd]192/** Insert data into data translation cache.
193 *
[5bda2f3e]194 * @param va Virtual page address.
195 * @param asid Address space identifier.
196 * @param entry The rest of TLB entry as required by TLB insertion
197 * format.
198 *
[95042fd]199 */
[7f1c620]200void dtc_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry)
[b994a60]201{
[95042fd]202 tc_mapping_insert(va, asid, entry, true);
203}
[bc78c75]204
[95042fd]205/** Insert data into instruction translation cache.
206 *
[5bda2f3e]207 * @param va Virtual page address.
208 * @param asid Address space identifier.
209 * @param entry The rest of TLB entry as required by TLB insertion
210 * format.
[95042fd]211 */
[7f1c620]212void itc_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry)
[b994a60]213{
[95042fd]214 tc_mapping_insert(va, asid, entry, false);
215}
[bc78c75]216
[95042fd]217/** Insert data into instruction or data translation cache.
218 *
[5bda2f3e]219 * @param va Virtual page address.
220 * @param asid Address space identifier.
221 * @param entry The rest of TLB entry as required by TLB insertion
222 * format.
223 * @param dtc If true, insert into data translation cache, use
224 * instruction translation cache otherwise.
225 *
[95042fd]226 */
[7f1c620]227void tc_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, bool dtc)
[bc78c75]228{
[5bda2f3e]229 region_register_t rr;
[95042fd]230 bool restore_rr = false;
[5bda2f3e]231
[a0d74fd]232 rr.word = rr_read(VA2VRN(va));
233 if ((restore_rr = (rr.map.rid != ASID2RID(asid, VA2VRN(va))))) {
[95042fd]234 /*
235 * The selected region register does not contain required RID.
236 * Save the old content of the register and replace the RID.
237 */
[5bda2f3e]238 region_register_t rr0;
239
[95042fd]240 rr0 = rr;
[a0d74fd]241 rr0.map.rid = ASID2RID(asid, VA2VRN(va));
242 rr_write(VA2VRN(va), rr0.word);
[89298e3]243 srlz_d();
[95042fd]244 srlz_i();
245 }
246
[e7b7be3f]247 asm volatile (
[5bda2f3e]248 "mov r8 = psr ;;\n"
249 "rsm %[mask] ;;\n" /* PSR_IC_MASK */
250 "srlz.d ;;\n"
251 "srlz.i ;;\n"
252 "mov cr.ifa = %[va]\n" /* va */
253 "mov cr.itir = %[word1] ;;\n" /* entry.word[1] */
254 "cmp.eq p6, p7 = %[dtc], r0 ;;\n" /* decide between itc and dtc */
255 "(p6) itc.i %[word0] ;;\n"
256 "(p7) itc.d %[word0] ;;\n"
257 "mov psr.l = r8 ;;\n"
258 "srlz.d ;;\n"
259 :: [mask] "i" (PSR_IC_MASK),
260 [va] "r" (va),
261 [word0] "r" (entry.word[0]),
262 [word1] "r" (entry.word[1]),
263 [dtc] "r" (dtc)
[2c49fbbe]264 : "p6", "p7", "r8"
[95042fd]265 );
266
267 if (restore_rr) {
[a0d74fd]268 rr_write(VA2VRN(va), rr.word);
[95042fd]269 srlz_d();
270 srlz_i();
[bc78c75]271 }
272}
273
[95042fd]274/** Insert data into instruction translation register.
275 *
[5bda2f3e]276 * @param va Virtual page address.
277 * @param asid Address space identifier.
278 * @param entry The rest of TLB entry as required by TLB insertion
279 * format.
280 * @param tr Translation register.
281 *
[95042fd]282 */
[5bda2f3e]283void itr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, size_t tr)
[bc78c75]284{
[95042fd]285 tr_mapping_insert(va, asid, entry, false, tr);
[bc78c75]286}
287
[95042fd]288/** Insert data into data translation register.
289 *
[5bda2f3e]290 * @param va Virtual page address.
291 * @param asid Address space identifier.
292 * @param entry The rest of TLB entry as required by TLB insertion
293 * format.
294 * @param tr Translation register.
295 *
[95042fd]296 */
[5bda2f3e]297void dtr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, size_t tr)
[95042fd]298{
299 tr_mapping_insert(va, asid, entry, true, tr);
300}
[bc78c75]301
[95042fd]302/** Insert data into instruction or data translation register.
303 *
[5bda2f3e]304 * @param va Virtual page address.
305 * @param asid Address space identifier.
306 * @param entry The rest of TLB entry as required by TLB insertion
307 * format.
308 * @param dtr If true, insert into data translation register, use
309 * instruction translation register otherwise.
310 * @param tr Translation register.
311 *
[95042fd]312 */
[5bda2f3e]313void tr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, bool dtr,
[98000fb]314 size_t tr)
[89298e3]315{
[5bda2f3e]316 region_register_t rr;
[95042fd]317 bool restore_rr = false;
[5bda2f3e]318
[a0d74fd]319 rr.word = rr_read(VA2VRN(va));
320 if ((restore_rr = (rr.map.rid != ASID2RID(asid, VA2VRN(va))))) {
[95042fd]321 /*
322 * The selected region register does not contain required RID.
323 * Save the old content of the register and replace the RID.
324 */
[5bda2f3e]325 region_register_t rr0;
326
[95042fd]327 rr0 = rr;
[a0d74fd]328 rr0.map.rid = ASID2RID(asid, VA2VRN(va));
329 rr_write(VA2VRN(va), rr0.word);
[89298e3]330 srlz_d();
[95042fd]331 srlz_i();
[89298e3]332 }
[5bda2f3e]333
[e7b7be3f]334 asm volatile (
[5bda2f3e]335 "mov r8 = psr ;;\n"
336 "rsm %[mask] ;;\n" /* PSR_IC_MASK */
337 "srlz.d ;;\n"
338 "srlz.i ;;\n"
339 "mov cr.ifa = %[va]\n" /* va */
340 "mov cr.itir = %[word1] ;;\n" /* entry.word[1] */
341 "cmp.eq p6, p7 = %[dtr], r0 ;;\n" /* decide between itr and dtr */
342 "(p6) itr.i itr[%[tr]] = %[word0] ;;\n"
343 "(p7) itr.d dtr[%[tr]] = %[word0] ;;\n"
344 "mov psr.l = r8 ;;\n"
345 "srlz.d ;;\n"
346 :: [mask] "i" (PSR_IC_MASK),
347 [va] "r" (va),
348 [word1] "r" (entry.word[1]),
349 [word0] "r" (entry.word[0]),
350 [tr] "r" (tr),
351 [dtr] "r" (dtr)
[2c49fbbe]352 : "p6", "p7", "r8"
[95042fd]353 );
354
355 if (restore_rr) {
[a0d74fd]356 rr_write(VA2VRN(va), rr.word);
[95042fd]357 srlz_d();
358 srlz_i();
359 }
[89298e3]360}
361
[a0d74fd]362/** Insert data into DTLB.
363 *
[5bda2f3e]364 * @param page Virtual page address including VRN bits.
365 * @param frame Physical frame address.
366 * @param dtr If true, insert into data translation register, use data
367 * translation cache otherwise.
368 * @param tr Translation register if dtr is true, ignored otherwise.
369 *
[a0d74fd]370 */
[5bda2f3e]371void dtlb_kernel_mapping_insert(uintptr_t page, uintptr_t frame, bool dtr,
[98000fb]372 size_t tr)
[a0d74fd]373{
374 tlb_entry_t entry;
375
376 entry.word[0] = 0;
377 entry.word[1] = 0;
378
[5bda2f3e]379 entry.p = true; /* present */
[a0d74fd]380 entry.ma = MA_WRITEBACK;
[5bda2f3e]381 entry.a = true; /* already accessed */
382 entry.d = true; /* already dirty */
[a0d74fd]383 entry.pl = PL_KERNEL;
384 entry.ar = AR_READ | AR_WRITE;
385 entry.ppn = frame >> PPN_SHIFT;
386 entry.ps = PAGE_WIDTH;
387
388 if (dtr)
389 dtr_mapping_insert(page, ASID_KERNEL, entry, tr);
390 else
391 dtc_mapping_insert(page, ASID_KERNEL, entry);
392}
393
[208259c]394/** Purge kernel entries from DTR.
395 *
396 * Purge DTR entries used by the kernel.
397 *
[5bda2f3e]398 * @param page Virtual page address including VRN bits.
399 * @param width Width of the purge in bits.
400 *
[208259c]401 */
[98000fb]402void dtr_purge(uintptr_t page, size_t width)
[208259c]403{
[5bda2f3e]404 asm volatile (
405 "ptr.d %[page], %[width]\n"
406 :: [page] "r" (page),
407 [width] "r" (width << 2)
408 );
[208259c]409}
410
411
[9ad03fe]412/** Copy content of PTE into data translation cache.
413 *
[5bda2f3e]414 * @param t PTE.
415 *
[9ad03fe]416 */
417void dtc_pte_copy(pte_t *t)
418{
419 tlb_entry_t entry;
[5bda2f3e]420
[9ad03fe]421 entry.word[0] = 0;
422 entry.word[1] = 0;
423
424 entry.p = t->p;
425 entry.ma = t->c ? MA_WRITEBACK : MA_UNCACHEABLE;
426 entry.a = t->a;
427 entry.d = t->d;
428 entry.pl = t->k ? PL_KERNEL : PL_USER;
429 entry.ar = t->w ? AR_WRITE : AR_READ;
430 entry.ppn = t->frame >> PPN_SHIFT;
431 entry.ps = PAGE_WIDTH;
432
433 dtc_mapping_insert(t->page, t->as->asid, entry);
[5bda2f3e]434
[68091bd]435#ifdef CONFIG_VHPT
436 vhpt_mapping_insert(t->page, t->as->asid, entry);
[5bda2f3e]437#endif
[9ad03fe]438}
439
440/** Copy content of PTE into instruction translation cache.
441 *
[5bda2f3e]442 * @param t PTE.
443 *
[9ad03fe]444 */
445void itc_pte_copy(pte_t *t)
446{
447 tlb_entry_t entry;
[5bda2f3e]448
[9ad03fe]449 entry.word[0] = 0;
450 entry.word[1] = 0;
451
452 ASSERT(t->x);
453
454 entry.p = t->p;
455 entry.ma = t->c ? MA_WRITEBACK : MA_UNCACHEABLE;
456 entry.a = t->a;
457 entry.pl = t->k ? PL_KERNEL : PL_USER;
458 entry.ar = t->x ? (AR_EXECUTE | AR_READ) : AR_READ;
459 entry.ppn = t->frame >> PPN_SHIFT;
460 entry.ps = PAGE_WIDTH;
461
462 itc_mapping_insert(t->page, t->as->asid, entry);
[5bda2f3e]463
[68091bd]464#ifdef CONFIG_VHPT
465 vhpt_mapping_insert(t->page, t->as->asid, entry);
[5bda2f3e]466#endif
[9ad03fe]467}
468
469/** Instruction TLB fault handler for faults with VHPT turned off.
470 *
[5bda2f3e]471 * @param vector Interruption vector.
472 * @param istate Structure with saved interruption state.
473 *
[9ad03fe]474 */
[7f1c620]475void alternate_instruction_tlb_fault(uint64_t vector, istate_t *istate)
[89298e3]476{
[7f1c620]477 uintptr_t va;
[9ad03fe]478 pte_t *t;
479
[5bda2f3e]480 va = istate->cr_ifa; /* faulting address */
481
[0ff03f3]482 t = page_mapping_find(AS, va, true);
[9ad03fe]483 if (t) {
484 /*
485 * The mapping was found in software page hash table.
486 * Insert it into data translation cache.
487 */
488 itc_pte_copy(t);
489 } else {
490 /*
491 * Forward the page fault to address space page fault handler.
492 */
[567807b1]493 if (as_page_fault(va, PF_ACCESS_EXEC, istate) == AS_PF_FAULT) {
[7e752b2]494 fault_if_from_uspace(istate, "Page fault at %p.",
495 (void *) va);
[c15b374]496 panic_memtrap(istate, PF_ACCESS_EXEC, va, NULL);
[9ad03fe]497 }
498 }
[95042fd]499}
[89298e3]500
[46321fb]501static int is_io_page_accessible(int page)
502{
[666773c]503 if (TASK->arch.iomap)
[38f6add]504 return bitmap_get(TASK->arch.iomap, page);
[666773c]505 else
506 return 0;
[46321fb]507}
508
[666773c]509/**
510 * There is special handling of memory mapped legacy io, because of 4KB sized
511 * access for userspace.
[46321fb]512 *
[5bda2f3e]513 * @param va Virtual address of page fault.
514 * @param istate Structure with saved interruption state.
515 *
516 * @return One on success, zero on failure.
[46321fb]517 *
518 */
519static int try_memmap_io_insertion(uintptr_t va, istate_t *istate)
520{
[666773c]521 if ((va >= IO_OFFSET ) && (va < IO_OFFSET + (1 << IO_PAGE_WIDTH))) {
522 if (TASK) {
523 uint64_t io_page = (va & ((1 << IO_PAGE_WIDTH) - 1)) >>
524 USPACE_IO_PAGE_WIDTH;
[5bda2f3e]525
[666773c]526 if (is_io_page_accessible(io_page)) {
527 uint64_t page, frame;
[5bda2f3e]528
[666773c]529 page = IO_OFFSET +
530 (1 << USPACE_IO_PAGE_WIDTH) * io_page;
531 frame = IO_FRAME_BASE +
532 (1 << USPACE_IO_PAGE_WIDTH) * io_page;
[5bda2f3e]533
[46321fb]534 tlb_entry_t entry;
[5bda2f3e]535
[46321fb]536 entry.word[0] = 0;
537 entry.word[1] = 0;
[5bda2f3e]538
539 entry.p = true; /* present */
540 entry.ma = MA_UNCACHEABLE;
541 entry.a = true; /* already accessed */
542 entry.d = true; /* already dirty */
[46321fb]543 entry.pl = PL_USER;
544 entry.ar = AR_READ | AR_WRITE;
[ef5de6d]545 entry.ppn = frame >> PPN_SHIFT;
[46321fb]546 entry.ps = USPACE_IO_PAGE_WIDTH;
[5bda2f3e]547
[ef5de6d]548 dtc_mapping_insert(page, TASK->as->asid, entry);
[46321fb]549 return 1;
[666773c]550 } else {
551 fault_if_from_uspace(istate,
[7e752b2]552 "IO access fault at %p.", (void *) va);
[666773c]553 }
554 }
555 }
[5bda2f3e]556
[46321fb]557 return 0;
558}
559
[9ad03fe]560/** Data TLB fault handler for faults with VHPT turned off.
[a0d74fd]561 *
[5bda2f3e]562 * @param vector Interruption vector.
563 * @param istate Structure with saved interruption state.
564 *
[a0d74fd]565 */
[7f1c620]566void alternate_data_tlb_fault(uint64_t vector, istate_t *istate)
[95042fd]567{
[93d66ef]568 if (istate->cr_isr.sp) {
569 /* Speculative load. Deffer the exception
570 until a more clever approach can be used.
571
572 Currently if we try to find the mapping
573 for the speculative load while in the kernel,
574 we might introduce a livelock because of
575 the possibly invalid values of the address. */
576 istate->cr_ipsr.ed = true;
577 return;
578 }
579
[5bda2f3e]580 uintptr_t va = istate->cr_ifa; /* faulting address */
[a0d74fd]581
[5bda2f3e]582 region_register_t rr;
[a0d74fd]583 rr.word = rr_read(VA2VRN(va));
[5bda2f3e]584 rid_t rid = rr.map.rid;
[a0d74fd]585 if (RID2ASID(rid) == ASID_KERNEL) {
586 if (VA2VRN(va) == VRN_KERNEL) {
587 /*
588 * Provide KA2PA(identity) mapping for faulting piece of
589 * kernel address space.
590 */
[9ad03fe]591 dtlb_kernel_mapping_insert(va, KA2PA(va), false, 0);
[a0d74fd]592 return;
593 }
594 }
[5bda2f3e]595
596
[0ff03f3]597 pte_t *entry = page_mapping_find(AS, va, true);
[5bda2f3e]598 if (entry) {
[9ad03fe]599 /*
[f47fd19]600 * The mapping was found in the software page hash table.
[9ad03fe]601 * Insert it into data translation cache.
602 */
[5bda2f3e]603 dtc_pte_copy(entry);
[9ad03fe]604 } else {
[666773c]605 if (try_memmap_io_insertion(va, istate))
606 return;
[5bda2f3e]607
[9ad03fe]608 /*
[5bda2f3e]609 * Forward the page fault to the address space page fault
[666773c]610 * handler.
[9ad03fe]611 */
[567807b1]612 if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) {
[7e752b2]613 fault_if_from_uspace(istate, "Page fault at %p.",
614 (void *) va);
[c15b374]615 panic_memtrap(istate, PF_ACCESS_UNKNOWN, va, NULL);
[9ad03fe]616 }
617 }
[95042fd]618}
[89298e3]619
[9ad03fe]620/** Data nested TLB fault handler.
621 *
622 * This fault should not occur.
623 *
[5bda2f3e]624 * @param vector Interruption vector.
625 * @param istate Structure with saved interruption state.
626 *
[9ad03fe]627 */
[7f1c620]628void data_nested_tlb_fault(uint64_t vector, istate_t *istate)
[95042fd]629{
[5bda2f3e]630 ASSERT(false);
[95042fd]631}
[89298e3]632
[9ad03fe]633/** Data Dirty bit fault handler.
634 *
[5bda2f3e]635 * @param vector Interruption vector.
636 * @param istate Structure with saved interruption state.
637 *
[9ad03fe]638 */
[7f1c620]639void data_dirty_bit_fault(uint64_t vector, istate_t *istate)
[95042fd]640{
[7f1c620]641 uintptr_t va;
[9ad03fe]642 pte_t *t;
[567807b1]643
[5bda2f3e]644 va = istate->cr_ifa; /* faulting address */
645
[0ff03f3]646 t = page_mapping_find(AS, va, true);
[5bda2f3e]647 ASSERT((t) && (t->p));
648 if ((t) && (t->p) && (t->w)) {
[9ad03fe]649 /*
650 * Update the Dirty bit in page tables and reinsert
651 * the mapping into DTC.
652 */
653 t->d = true;
654 dtc_pte_copy(t);
[567807b1]655 } else {
656 if (as_page_fault(va, PF_ACCESS_WRITE, istate) == AS_PF_FAULT) {
[7e752b2]657 fault_if_from_uspace(istate, "Page fault at %p.",
658 (void *) va);
[c15b374]659 panic_memtrap(istate, PF_ACCESS_WRITE, va, NULL);
[567807b1]660 }
[9ad03fe]661 }
[95042fd]662}
[89298e3]663
[9ad03fe]664/** Instruction access bit fault handler.
665 *
[5bda2f3e]666 * @param vector Interruption vector.
667 * @param istate Structure with saved interruption state.
668 *
[9ad03fe]669 */
[7f1c620]670void instruction_access_bit_fault(uint64_t vector, istate_t *istate)
[95042fd]671{
[7f1c620]672 uintptr_t va;
[5bda2f3e]673 pte_t *t;
674
675 va = istate->cr_ifa; /* faulting address */
676
[0ff03f3]677 t = page_mapping_find(AS, va, true);
[5bda2f3e]678 ASSERT((t) && (t->p));
679 if ((t) && (t->p) && (t->x)) {
[9ad03fe]680 /*
681 * Update the Accessed bit in page tables and reinsert
682 * the mapping into ITC.
683 */
684 t->a = true;
685 itc_pte_copy(t);
[567807b1]686 } else {
687 if (as_page_fault(va, PF_ACCESS_EXEC, istate) == AS_PF_FAULT) {
[7e752b2]688 fault_if_from_uspace(istate, "Page fault at %p.",
689 (void *) va);
[c15b374]690 panic_memtrap(istate, PF_ACCESS_EXEC, va, NULL);
[567807b1]691 }
[9ad03fe]692 }
[95042fd]693}
[89298e3]694
[9ad03fe]695/** Data access bit fault handler.
696 *
697 * @param vector Interruption vector.
[25d7709]698 * @param istate Structure with saved interruption state.
[5bda2f3e]699 *
[9ad03fe]700 */
[7f1c620]701void data_access_bit_fault(uint64_t vector, istate_t *istate)
[95042fd]702{
[7f1c620]703 uintptr_t va;
[9ad03fe]704 pte_t *t;
[5bda2f3e]705
706 va = istate->cr_ifa; /* faulting address */
707
[0ff03f3]708 t = page_mapping_find(AS, va, true);
[5bda2f3e]709 ASSERT((t) && (t->p));
710 if ((t) && (t->p)) {
[9ad03fe]711 /*
712 * Update the Accessed bit in page tables and reinsert
713 * the mapping into DTC.
714 */
715 t->a = true;
716 dtc_pte_copy(t);
[567807b1]717 } else {
718 if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) {
[7e752b2]719 fault_if_from_uspace(istate, "Page fault at %p.",
720 (void *) va);
[c15b374]721 panic_memtrap(istate, PF_ACCESS_UNKNOWN, va, NULL);
[567807b1]722 }
[9ad03fe]723 }
[89298e3]724}
725
[925be4e]726/** Data access rights fault handler.
727 *
728 * @param vector Interruption vector.
729 * @param istate Structure with saved interruption state.
[5bda2f3e]730 *
[925be4e]731 */
732void data_access_rights_fault(uint64_t vector, istate_t *istate)
733{
734 uintptr_t va;
735 pte_t *t;
[5bda2f3e]736
737 va = istate->cr_ifa; /* faulting address */
738
[925be4e]739 /*
740 * Assume a write to a read-only page.
741 */
[0ff03f3]742 t = page_mapping_find(AS, va, true);
[5bda2f3e]743 ASSERT((t) && (t->p));
[925be4e]744 ASSERT(!t->w);
745 if (as_page_fault(va, PF_ACCESS_WRITE, istate) == AS_PF_FAULT) {
[7e752b2]746 fault_if_from_uspace(istate, "Page fault at %p.",
747 (void *) va);
[c15b374]748 panic_memtrap(istate, PF_ACCESS_WRITE, va, NULL);
[925be4e]749 }
750}
751
[9ad03fe]752/** Page not present fault handler.
753 *
754 * @param vector Interruption vector.
[25d7709]755 * @param istate Structure with saved interruption state.
[5bda2f3e]756 *
[9ad03fe]757 */
[7f1c620]758void page_not_present(uint64_t vector, istate_t *istate)
[95042fd]759{
[7f1c620]760 uintptr_t va;
[9ad03fe]761 pte_t *t;
762
[5bda2f3e]763 va = istate->cr_ifa; /* faulting address */
764
[0ff03f3]765 t = page_mapping_find(AS, va, true);
[9ad03fe]766 ASSERT(t);
767
768 if (t->p) {
769 /*
770 * If the Present bit is set in page hash table, just copy it
771 * and update ITC/DTC.
772 */
773 if (t->x)
774 itc_pte_copy(t);
775 else
776 dtc_pte_copy(t);
777 } else {
[567807b1]778 if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) {
[7e752b2]779 fault_if_from_uspace(istate, "Page fault at %p.",
780 (void *) va);
[c15b374]781 panic_memtrap(istate, PF_ACCESS_UNKNOWN, va, NULL);
[9ad03fe]782 }
783 }
[95042fd]784}
[b45c443]785
[9979acb]786void tlb_arch_init(void)
787{
788}
789
790void tlb_print(void)
791{
792}
793
[ee289cf0]794/** @}
[b45c443]795 */
Note: See TracBrowser for help on using the repository browser.