Subversion Repositories HelenOS

Rev

Rev 3635 | Rev 3766 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
740 jermar 1
/*
2071 jermar 2
 * Copyright (c) 2006 Jakub Jermar
740 jermar 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
 
1850 jermar 29
/** @addtogroup ia64mm 
1702 cejka 30
 * @{
31
 */
32
/** @file
33
 */
34
 
740 jermar 35
/*
36
 * TLB management.
37
 */
38
 
39
#include <mm/tlb.h>
901 jermar 40
#include <mm/asid.h>
902 jermar 41
#include <mm/page.h>
42
#include <mm/as.h>
818 vana 43
#include <arch/mm/tlb.h>
901 jermar 44
#include <arch/mm/page.h>
1210 vana 45
#include <arch/mm/vhpt.h>
819 vana 46
#include <arch/barrier.h>
900 jermar 47
#include <arch/interrupt.h>
928 vana 48
#include <arch/pal/pal.h>
49
#include <arch/asm.h>
900 jermar 50
#include <panic.h>
993 jermar 51
#include <print.h>
902 jermar 52
#include <arch.h>
1621 vana 53
#include <interrupt.h>
740 jermar 54
 
756 jermar 55
/** Invalidate all TLB entries. */
740 jermar 56
void tlb_invalidate_all(void)
57
{
1850 jermar 58
    ipl_t ipl;
59
    uintptr_t adr;
60
    uint32_t count1, count2, stride1, stride2;
928 vana 61
 
2745 decky 62
    unsigned int i, j;
928 vana 63
 
1850 jermar 64
    adr = PAL_PTCE_INFO_BASE();
65
    count1 = PAL_PTCE_INFO_COUNT1();
66
    count2 = PAL_PTCE_INFO_COUNT2();
67
    stride1 = PAL_PTCE_INFO_STRIDE1();
68
    stride2 = PAL_PTCE_INFO_STRIDE2();
928 vana 69
 
1850 jermar 70
    ipl = interrupts_disable();
928 vana 71
 
2745 decky 72
    for (i = 0; i < count1; i++) {
73
        for (j = 0; j < count2; j++) {
2082 decky 74
            asm volatile (
1850 jermar 75
                "ptc.e %0 ;;"
76
                :
77
                : "r" (adr)
78
            );
79
            adr += stride2;
928 vana 80
        }
1850 jermar 81
        adr += stride1;
82
    }
928 vana 83
 
1850 jermar 84
    interrupts_restore(ipl);
928 vana 85
 
1850 jermar 86
    srlz_d();
87
    srlz_i();
1210 vana 88
#ifdef CONFIG_VHPT
1850 jermar 89
    vhpt_invalidate_all();
1210 vana 90
#endif  
740 jermar 91
}
92
 
93
/** Invalidate entries belonging to an address space.
94
 *
95
 * @param asid Address space identifier.
96
 */
97
void tlb_invalidate_asid(asid_t asid)
98
{
935 vana 99
    tlb_invalidate_all();
740 jermar 100
}
818 vana 101
 
935 vana 102
 
1780 jermar 103
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt)
935 vana 104
{
944 vana 105
    region_register rr;
106
    bool restore_rr = false;
993 jermar 107
    int b = 0;
108
    int c = cnt;
944 vana 109
 
1780 jermar 110
    uintptr_t va;
993 jermar 111
    va = page;
947 vana 112
 
944 vana 113
    rr.word = rr_read(VA2VRN(va));
114
    if ((restore_rr = (rr.map.rid != ASID2RID(asid, VA2VRN(va))))) {
115
        /*
116
         * The selected region register does not contain required RID.
117
         * Save the old content of the register and replace the RID.
118
         */
119
        region_register rr0;
120
 
121
        rr0 = rr;
122
        rr0.map.rid = ASID2RID(asid, VA2VRN(va));
123
        rr_write(VA2VRN(va), rr0.word);
124
        srlz_d();
125
        srlz_i();
126
    }
127
 
993 jermar 128
    while(c >>= 1)
129
        b++;
130
    b >>= 1;
1780 jermar 131
    uint64_t ps;
944 vana 132
 
993 jermar 133
    switch (b) {
1850 jermar 134
    case 0: /*cnt 1-3*/
135
        ps = PAGE_WIDTH;
136
        break;
137
    case 1: /*cnt 4-15*/
138
        ps = PAGE_WIDTH+2;
139
        va &= ~((1<<ps)-1);
140
        break;
141
    case 2: /*cnt 16-63*/
142
        ps = PAGE_WIDTH+4;
143
        va &= ~((1<<ps)-1);
144
        break;
145
    case 3: /*cnt 64-255*/
146
        ps = PAGE_WIDTH+6;
147
        va &= ~((1<<ps)-1);
148
        break;
149
    case 4: /*cnt 256-1023*/
150
        ps = PAGE_WIDTH+8;
151
        va &= ~((1<<ps)-1);
152
        break;
153
    case 5: /*cnt 1024-4095*/
154
        ps = PAGE_WIDTH+10;
155
        va &= ~((1<<ps)-1);
156
        break;
157
    case 6: /*cnt 4096-16383*/
158
        ps = PAGE_WIDTH+12;
159
        va &= ~((1<<ps)-1);
160
        break;
161
    case 7: /*cnt 16384-65535*/
162
    case 8: /*cnt 65536-(256K-1)*/
163
        ps = PAGE_WIDTH+14;
164
        va &= ~((1<<ps)-1);
165
        break;
166
    default:
167
        ps=PAGE_WIDTH+18;
168
        va&=~((1<<ps)-1);
169
        break;
944 vana 170
    }
993 jermar 171
    for(; va<(page+cnt*(PAGE_SIZE)); va += (1<<ps)) {
2082 decky 172
        asm volatile (
947 vana 173
            "ptc.l %0,%1;;"
174
            :
993 jermar 175
            : "r" (va), "r" (ps<<2)
947 vana 176
        );
944 vana 177
    }
178
    srlz_d();
179
    srlz_i();
180
 
181
    if (restore_rr) {
182
        rr_write(VA2VRN(va), rr.word);
183
        srlz_d();
184
        srlz_i();
185
    }
935 vana 186
}
187
 
899 jermar 188
/** Insert data into data translation cache.
189
 *
190
 * @param va Virtual page address.
191
 * @param asid Address space identifier.
192
 * @param entry The rest of TLB entry as required by TLB insertion format.
193
 */
1780 jermar 194
void dtc_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry)
919 jermar 195
{
899 jermar 196
    tc_mapping_insert(va, asid, entry, true);
197
}
818 vana 198
 
899 jermar 199
/** Insert data into instruction translation cache.
200
 *
201
 * @param va Virtual page address.
202
 * @param asid Address space identifier.
203
 * @param entry The rest of TLB entry as required by TLB insertion format.
204
 */
1780 jermar 205
void itc_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry)
919 jermar 206
{
899 jermar 207
    tc_mapping_insert(va, asid, entry, false);
208
}
818 vana 209
 
899 jermar 210
/** Insert data into instruction or data translation cache.
211
 *
212
 * @param va Virtual page address.
213
 * @param asid Address space identifier.
214
 * @param entry The rest of TLB entry as required by TLB insertion format.
215
 * @param dtc If true, insert into data translation cache, use instruction translation cache otherwise.
216
 */
1780 jermar 217
void tc_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, bool dtc)
818 vana 218
{
219
    region_register rr;
899 jermar 220
    bool restore_rr = false;
818 vana 221
 
901 jermar 222
    rr.word = rr_read(VA2VRN(va));
223
    if ((restore_rr = (rr.map.rid != ASID2RID(asid, VA2VRN(va))))) {
899 jermar 224
        /*
225
         * The selected region register does not contain required RID.
226
         * Save the old content of the register and replace the RID.
227
         */
228
        region_register rr0;
818 vana 229
 
899 jermar 230
        rr0 = rr;
901 jermar 231
        rr0.map.rid = ASID2RID(asid, VA2VRN(va));
232
        rr_write(VA2VRN(va), rr0.word);
899 jermar 233
        srlz_d();
234
        srlz_i();
818 vana 235
    }
899 jermar 236
 
2082 decky 237
    asm volatile (
899 jermar 238
        "mov r8=psr;;\n"
900 jermar 239
        "rsm %0;;\n"            /* PSR_IC_MASK */
899 jermar 240
        "srlz.d;;\n"
241
        "srlz.i;;\n"
242
        "mov cr.ifa=%1\n"       /* va */
243
        "mov cr.itir=%2;;\n"        /* entry.word[1] */
244
        "cmp.eq p6,p7 = %4,r0;;\n"  /* decide between itc and dtc */
245
        "(p6) itc.i %3;;\n"
246
        "(p7) itc.d %3;;\n"
247
        "mov psr.l=r8;;\n"
248
        "srlz.d;;\n"
249
        :
900 jermar 250
        : "i" (PSR_IC_MASK), "r" (va), "r" (entry.word[1]), "r" (entry.word[0]), "r" (dtc)
251
        : "p6", "p7", "r8"
899 jermar 252
    );
253
 
254
    if (restore_rr) {
901 jermar 255
        rr_write(VA2VRN(va), rr.word);
819 vana 256
        srlz_d();
899 jermar 257
        srlz_i();
818 vana 258
    }
899 jermar 259
}
818 vana 260
 
899 jermar 261
/** Insert data into instruction translation register.
262
 *
263
 * @param va Virtual page address.
264
 * @param asid Address space identifier.
265
 * @param entry The rest of TLB entry as required by TLB insertion format.
266
 * @param tr Translation register.
267
 */
1780 jermar 268
void itr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, index_t tr)
899 jermar 269
{
270
    tr_mapping_insert(va, asid, entry, false, tr);
271
}
818 vana 272
 
899 jermar 273
/** Insert data into data translation register.
274
 *
275
 * @param va Virtual page address.
276
 * @param asid Address space identifier.
277
 * @param entry The rest of TLB entry as required by TLB insertion format.
278
 * @param tr Translation register.
279
 */
1780 jermar 280
void dtr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, index_t tr)
899 jermar 281
{
282
    tr_mapping_insert(va, asid, entry, true, tr);
818 vana 283
}
284
 
899 jermar 285
/** Insert data into instruction or data translation register.
286
 *
287
 * @param va Virtual page address.
288
 * @param asid Address space identifier.
289
 * @param entry The rest of TLB entry as required by TLB insertion format.
1708 jermar 290
 * @param dtr If true, insert into data translation register, use instruction translation register otherwise.
899 jermar 291
 * @param tr Translation register.
292
 */
1780 jermar 293
void tr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, bool dtr, index_t tr)
818 vana 294
{
295
    region_register rr;
899 jermar 296
    bool restore_rr = false;
818 vana 297
 
901 jermar 298
    rr.word = rr_read(VA2VRN(va));
299
    if ((restore_rr = (rr.map.rid != ASID2RID(asid, VA2VRN(va))))) {
899 jermar 300
        /*
301
         * The selected region register does not contain required RID.
302
         * Save the old content of the register and replace the RID.
303
         */
304
        region_register rr0;
818 vana 305
 
899 jermar 306
        rr0 = rr;
901 jermar 307
        rr0.map.rid = ASID2RID(asid, VA2VRN(va));
308
        rr_write(VA2VRN(va), rr0.word);
899 jermar 309
        srlz_d();
310
        srlz_i();
311
    }
818 vana 312
 
2082 decky 313
    asm volatile (
899 jermar 314
        "mov r8=psr;;\n"
900 jermar 315
        "rsm %0;;\n"            /* PSR_IC_MASK */
899 jermar 316
        "srlz.d;;\n"
317
        "srlz.i;;\n"
318
        "mov cr.ifa=%1\n"           /* va */         
319
        "mov cr.itir=%2;;\n"        /* entry.word[1] */
320
        "cmp.eq p6,p7=%5,r0;;\n"    /* decide between itr and dtr */
321
        "(p6) itr.i itr[%4]=%3;;\n"
322
        "(p7) itr.d dtr[%4]=%3;;\n"
323
        "mov psr.l=r8;;\n"
324
        "srlz.d;;\n"
325
        :
900 jermar 326
        : "i" (PSR_IC_MASK), "r" (va), "r" (entry.word[1]), "r" (entry.word[0]), "r" (tr), "r" (dtr)
327
        : "p6", "p7", "r8"
899 jermar 328
    );
329
 
330
    if (restore_rr) {
901 jermar 331
        rr_write(VA2VRN(va), rr.word);
819 vana 332
        srlz_d();
899 jermar 333
        srlz_i();
818 vana 334
    }
899 jermar 335
}
818 vana 336
 
901 jermar 337
/** Insert data into DTLB.
338
 *
1675 jermar 339
 * @param page Virtual page address including VRN bits.
340
 * @param frame Physical frame address.
901 jermar 341
 * @param dtr If true, insert into data translation register, use data translation cache otherwise.
342
 * @param tr Translation register if dtr is true, ignored otherwise.
343
 */
1780 jermar 344
void dtlb_kernel_mapping_insert(uintptr_t page, uintptr_t frame, bool dtr, index_t tr)
901 jermar 345
{
346
    tlb_entry_t entry;
347
 
348
    entry.word[0] = 0;
349
    entry.word[1] = 0;
350
 
351
    entry.p = true;         /* present */
352
    entry.ma = MA_WRITEBACK;
353
    entry.a = true;         /* already accessed */
354
    entry.d = true;         /* already dirty */
355
    entry.pl = PL_KERNEL;
356
    entry.ar = AR_READ | AR_WRITE;
357
    entry.ppn = frame >> PPN_SHIFT;
358
    entry.ps = PAGE_WIDTH;
359
 
360
    if (dtr)
361
        dtr_mapping_insert(page, ASID_KERNEL, entry, tr);
362
    else
363
        dtc_mapping_insert(page, ASID_KERNEL, entry);
364
}
365
 
1675 jermar 366
/** Purge kernel entries from DTR.
367
 *
368
 * Purge DTR entries used by the kernel.
369
 *
370
 * @param page Virtual page address including VRN bits.
371
 * @param width Width of the purge in bits.
372
 */
1780 jermar 373
void dtr_purge(uintptr_t page, count_t width)
1675 jermar 374
{
2082 decky 375
    asm volatile ("ptr.d %0, %1\n" : : "r" (page), "r" (width<<2));
1675 jermar 376
}
377
 
378
 
902 jermar 379
/** Copy content of PTE into data translation cache.
380
 *
381
 * @param t PTE.
382
 */
383
void dtc_pte_copy(pte_t *t)
384
{
385
    tlb_entry_t entry;
386
 
387
    entry.word[0] = 0;
388
    entry.word[1] = 0;
389
 
390
    entry.p = t->p;
391
    entry.ma = t->c ? MA_WRITEBACK : MA_UNCACHEABLE;
392
    entry.a = t->a;
393
    entry.d = t->d;
394
    entry.pl = t->k ? PL_KERNEL : PL_USER;
395
    entry.ar = t->w ? AR_WRITE : AR_READ;
396
    entry.ppn = t->frame >> PPN_SHIFT;
397
    entry.ps = PAGE_WIDTH;
398
 
399
    dtc_mapping_insert(t->page, t->as->asid, entry);
1210 vana 400
#ifdef CONFIG_VHPT
401
    vhpt_mapping_insert(t->page, t->as->asid, entry);
402
#endif  
902 jermar 403
}
404
 
405
/** Copy content of PTE into instruction translation cache.
406
 *
407
 * @param t PTE.
408
 */
409
void itc_pte_copy(pte_t *t)
410
{
411
    tlb_entry_t entry;
412
 
413
    entry.word[0] = 0;
414
    entry.word[1] = 0;
415
 
416
    ASSERT(t->x);
417
 
418
    entry.p = t->p;
419
    entry.ma = t->c ? MA_WRITEBACK : MA_UNCACHEABLE;
420
    entry.a = t->a;
421
    entry.pl = t->k ? PL_KERNEL : PL_USER;
422
    entry.ar = t->x ? (AR_EXECUTE | AR_READ) : AR_READ;
423
    entry.ppn = t->frame >> PPN_SHIFT;
424
    entry.ps = PAGE_WIDTH;
425
 
426
    itc_mapping_insert(t->page, t->as->asid, entry);
1210 vana 427
#ifdef CONFIG_VHPT
428
    vhpt_mapping_insert(t->page, t->as->asid, entry);
429
#endif  
902 jermar 430
}
431
 
432
/** Instruction TLB fault handler for faults with VHPT turned off.
433
 *
434
 * @param vector Interruption vector.
958 jermar 435
 * @param istate Structure with saved interruption state.
902 jermar 436
 */
1780 jermar 437
void alternate_instruction_tlb_fault(uint64_t vector, istate_t *istate)
899 jermar 438
{
902 jermar 439
    region_register rr;
1411 jermar 440
    rid_t rid;
1780 jermar 441
    uintptr_t va;
902 jermar 442
    pte_t *t;
443
 
958 jermar 444
    va = istate->cr_ifa;    /* faulting address */
1411 jermar 445
    rr.word = rr_read(VA2VRN(va));
446
    rid = rr.map.rid;
447
 
1044 jermar 448
    page_table_lock(AS, true);
902 jermar 449
    t = page_mapping_find(AS, va);
450
    if (t) {
451
        /*
452
         * The mapping was found in software page hash table.
453
         * Insert it into data translation cache.
454
         */
455
        itc_pte_copy(t);
1044 jermar 456
        page_table_unlock(AS, true);
902 jermar 457
    } else {
458
        /*
459
         * Forward the page fault to address space page fault handler.
460
         */
1044 jermar 461
        page_table_unlock(AS, true);
1411 jermar 462
        if (as_page_fault(va, PF_ACCESS_EXEC, istate) == AS_PF_FAULT) {
1735 decky 463
            fault_if_from_uspace(istate,"Page fault at %p",va);
2462 jermar 464
            panic("%s: va=%p, rid=%d, iip=%p\n", __func__, va, rid, istate->cr_iip);
902 jermar 465
        }
466
    }
899 jermar 467
}
818 vana 468
 
3635 vana 469
 
470
 
471
static int is_io_page_accessible(int page)
472
{
473
    if(TASK->arch.iomap) return bitmap_get(TASK->arch.iomap,page);
474
    else return 0;
475
}
476
 
477
#define IO_FRAME_BASE 0xFFFFC000000
478
 
479
/** There is special handling of memmaped lagacy io, because
480
 * of 4KB sized access
481
 * only for userspace
482
 *
483
 * @param va virtual address of page fault
484
 * @param istate Structure with saved interruption state.
485
 *
486
 *
487
 * @return 1 on success, 0 on fail
488
 */
489
static int try_memmap_io_insertion(uintptr_t va, istate_t *istate)
490
{
491
    if((va >= IO_OFFSET ) && (va < IO_OFFSET + (1<<IO_PAGE_WIDTH)))
492
        if(TASK){
493
 
494
            uint64_t io_page=(va &  ((1<<IO_PAGE_WIDTH)-1)) >> (USPACE_IO_PAGE_WIDTH);
495
            if(is_io_page_accessible(io_page)){
496
                uint64_t page,frame;
497
 
498
                page = IO_OFFSET + (1 << USPACE_IO_PAGE_WIDTH) * io_page;
499
                frame = IO_FRAME_BASE + (1 << USPACE_IO_PAGE_WIDTH) * io_page;
500
 
501
 
502
                tlb_entry_t entry;
503
 
504
                entry.word[0] = 0;
505
                entry.word[1] = 0;
506
 
507
                entry.p = true;         /* present */
508
                entry.ma = MA_UNCACHEABLE;     
509
                entry.a = true;         /* already accessed */
510
                entry.d = true;         /* already dirty */
511
                entry.pl = PL_USER;
512
                entry.ar = AR_READ | AR_WRITE;
3763 jermar 513
                entry.ppn = frame >> PPN_SHIFT;
3635 vana 514
                entry.ps = USPACE_IO_PAGE_WIDTH;
515
 
3763 jermar 516
                dtc_mapping_insert(page, TASK->as->asid, entry);
3635 vana 517
                return 1;
518
            }else {
519
                fault_if_from_uspace(istate,"IO access fault at %p",va);
520
                return 0;
521
            }      
522
        } else
523
            return 0;
524
    else
525
        return 0;
526
 
527
    return 0;
528
 
529
}
530
 
531
 
532
 
533
 
902 jermar 534
/** Data TLB fault handler for faults with VHPT turned off.
901 jermar 535
 *
536
 * @param vector Interruption vector.
958 jermar 537
 * @param istate Structure with saved interruption state.
901 jermar 538
 */
1780 jermar 539
void alternate_data_tlb_fault(uint64_t vector, istate_t *istate)
899 jermar 540
{
901 jermar 541
    region_register rr;
542
    rid_t rid;
1780 jermar 543
    uintptr_t va;
902 jermar 544
    pte_t *t;
901 jermar 545
 
958 jermar 546
    va = istate->cr_ifa;    /* faulting address */
901 jermar 547
    rr.word = rr_read(VA2VRN(va));
548
    rid = rr.map.rid;
549
    if (RID2ASID(rid) == ASID_KERNEL) {
550
        if (VA2VRN(va) == VRN_KERNEL) {
551
            /*
552
             * Provide KA2PA(identity) mapping for faulting piece of
553
             * kernel address space.
554
             */
902 jermar 555
            dtlb_kernel_mapping_insert(va, KA2PA(va), false, 0);
901 jermar 556
            return;
557
        }
558
    }
919 jermar 559
 
1044 jermar 560
    page_table_lock(AS, true);
902 jermar 561
    t = page_mapping_find(AS, va);
562
    if (t) {
563
        /*
1851 jermar 564
         * The mapping was found in the software page hash table.
902 jermar 565
         * Insert it into data translation cache.
566
         */
567
        dtc_pte_copy(t);
1044 jermar 568
        page_table_unlock(AS, true);
902 jermar 569
    } else {
3635 vana 570
        page_table_unlock(AS, true);
571
        if (try_memmap_io_insertion(va,istate)) return;
902 jermar 572
        /*
1851 jermar 573
         * Forward the page fault to the address space page fault handler.
902 jermar 574
         */
1411 jermar 575
        if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) {
1735 decky 576
            fault_if_from_uspace(istate,"Page fault at %p",va);
2462 jermar 577
            panic("%s: va=%p, rid=%d, iip=%p\n", __func__, va, rid, istate->cr_iip);
902 jermar 578
        }
579
    }
818 vana 580
}
581
 
902 jermar 582
/** Data nested TLB fault handler.
583
 *
584
 * This fault should not occur.
585
 *
586
 * @param vector Interruption vector.
958 jermar 587
 * @param istate Structure with saved interruption state.
902 jermar 588
 */
1780 jermar 589
void data_nested_tlb_fault(uint64_t vector, istate_t *istate)
899 jermar 590
{
2462 jermar 591
    panic("%s\n", __func__);
899 jermar 592
}
818 vana 593
 
902 jermar 594
/** Data Dirty bit fault handler.
595
 *
596
 * @param vector Interruption vector.
958 jermar 597
 * @param istate Structure with saved interruption state.
902 jermar 598
 */
1780 jermar 599
void data_dirty_bit_fault(uint64_t vector, istate_t *istate)
819 vana 600
{
1411 jermar 601
    region_register rr;
602
    rid_t rid;
1780 jermar 603
    uintptr_t va;
902 jermar 604
    pte_t *t;
1411 jermar 605
 
606
    va = istate->cr_ifa;    /* faulting address */
607
    rr.word = rr_read(VA2VRN(va));
608
    rid = rr.map.rid;
902 jermar 609
 
1044 jermar 610
    page_table_lock(AS, true);
1411 jermar 611
    t = page_mapping_find(AS, va);
902 jermar 612
    ASSERT(t && t->p);
1411 jermar 613
    if (t && t->p && t->w) {
902 jermar 614
        /*
615
         * Update the Dirty bit in page tables and reinsert
616
         * the mapping into DTC.
617
         */
618
        t->d = true;
619
        dtc_pte_copy(t);
1411 jermar 620
    } else {
621
        if (as_page_fault(va, PF_ACCESS_WRITE, istate) == AS_PF_FAULT) {
1735 decky 622
            fault_if_from_uspace(istate,"Page fault at %p",va);
2462 jermar 623
            panic("%s: va=%p, rid=%d, iip=%p\n", __func__, va, rid, istate->cr_iip);
1411 jermar 624
            t->d = true;
625
            dtc_pte_copy(t);
626
        }
902 jermar 627
    }
1044 jermar 628
    page_table_unlock(AS, true);
899 jermar 629
}
819 vana 630
 
902 jermar 631
/** Instruction access bit fault handler.
632
 *
633
 * @param vector Interruption vector.
958 jermar 634
 * @param istate Structure with saved interruption state.
902 jermar 635
 */
1780 jermar 636
void instruction_access_bit_fault(uint64_t vector, istate_t *istate)
899 jermar 637
{
1411 jermar 638
    region_register rr;
639
    rid_t rid;
1780 jermar 640
    uintptr_t va;
1411 jermar 641
    pte_t *t;  
902 jermar 642
 
1411 jermar 643
    va = istate->cr_ifa;    /* faulting address */
644
    rr.word = rr_read(VA2VRN(va));
645
    rid = rr.map.rid;
646
 
1044 jermar 647
    page_table_lock(AS, true);
1411 jermar 648
    t = page_mapping_find(AS, va);
902 jermar 649
    ASSERT(t && t->p);
1411 jermar 650
    if (t && t->p && t->x) {
902 jermar 651
        /*
652
         * Update the Accessed bit in page tables and reinsert
653
         * the mapping into ITC.
654
         */
655
        t->a = true;
656
        itc_pte_copy(t);
1411 jermar 657
    } else {
658
        if (as_page_fault(va, PF_ACCESS_EXEC, istate) == AS_PF_FAULT) {
1735 decky 659
            fault_if_from_uspace(istate,"Page fault at %p",va);
2462 jermar 660
            panic("%s: va=%p, rid=%d, iip=%p\n", __func__, va, rid, istate->cr_iip);
1411 jermar 661
            t->a = true;
662
            itc_pte_copy(t);
663
        }
902 jermar 664
    }
1044 jermar 665
    page_table_unlock(AS, true);
899 jermar 666
}
819 vana 667
 
902 jermar 668
/** Data access bit fault handler.
669
 *
670
 * @param vector Interruption vector.
958 jermar 671
 * @param istate Structure with saved interruption state.
902 jermar 672
 */
1780 jermar 673
void data_access_bit_fault(uint64_t vector, istate_t *istate)
899 jermar 674
{
1411 jermar 675
    region_register rr;
676
    rid_t rid;
1780 jermar 677
    uintptr_t va;
902 jermar 678
    pte_t *t;
679
 
1411 jermar 680
    va = istate->cr_ifa;    /* faulting address */
681
    rr.word = rr_read(VA2VRN(va));
682
    rid = rr.map.rid;
683
 
1044 jermar 684
    page_table_lock(AS, true);
1411 jermar 685
    t = page_mapping_find(AS, va);
902 jermar 686
    ASSERT(t && t->p);
687
    if (t && t->p) {
688
        /*
689
         * Update the Accessed bit in page tables and reinsert
690
         * the mapping into DTC.
691
         */
692
        t->a = true;
693
        dtc_pte_copy(t);
1411 jermar 694
    } else {
695
        if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) {
1735 decky 696
            fault_if_from_uspace(istate,"Page fault at %p",va);
2462 jermar 697
            panic("%s: va=%p, rid=%d, iip=%p\n", __func__, va, rid, istate->cr_iip);
1411 jermar 698
            t->a = true;
699
            itc_pte_copy(t);
700
        }
902 jermar 701
    }
1044 jermar 702
    page_table_unlock(AS, true);
819 vana 703
}
704
 
902 jermar 705
/** Page not present fault handler.
706
 *
707
 * @param vector Interruption vector.
958 jermar 708
 * @param istate Structure with saved interruption state.
902 jermar 709
 */
1780 jermar 710
void page_not_present(uint64_t vector, istate_t *istate)
819 vana 711
{
902 jermar 712
    region_register rr;
1411 jermar 713
    rid_t rid;
1780 jermar 714
    uintptr_t va;
902 jermar 715
    pte_t *t;
716
 
958 jermar 717
    va = istate->cr_ifa;    /* faulting address */
1411 jermar 718
    rr.word = rr_read(VA2VRN(va));
719
    rid = rr.map.rid;
720
 
1044 jermar 721
    page_table_lock(AS, true);
902 jermar 722
    t = page_mapping_find(AS, va);
723
    ASSERT(t);
724
 
725
    if (t->p) {
726
        /*
727
         * If the Present bit is set in page hash table, just copy it
728
         * and update ITC/DTC.
729
         */
730
        if (t->x)
731
            itc_pte_copy(t);
732
        else
733
            dtc_pte_copy(t);
1044 jermar 734
        page_table_unlock(AS, true);
902 jermar 735
    } else {
1044 jermar 736
        page_table_unlock(AS, true);
1411 jermar 737
        if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) {
1735 decky 738
            fault_if_from_uspace(istate,"Page fault at %p",va);
2462 jermar 739
            panic("%s: va=%p, rid=%d\n", __func__, va, rid);
902 jermar 740
        }
741
    }
819 vana 742
}
1702 cejka 743
 
1850 jermar 744
/** @}
1702 cejka 745
 */