Subversion Repositories HelenOS

Rev

Rev 1864 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1864 Rev 1865
Line 50... Line 50...
50
#include <arch/asm.h>
50
#include <arch/asm.h>
51
#include <symtab.h>
51
#include <symtab.h>
52
 
52
 
53
static void dtlb_pte_copy(pte_t *t, bool ro);
53
static void dtlb_pte_copy(pte_t *t, bool ro);
54
static void itlb_pte_copy(pte_t *t);
54
static void itlb_pte_copy(pte_t *t);
55
static void do_fast_data_access_mmu_miss_fault(istate_t *istate, const char *str);
-
 
56
static void do_fast_instruction_access_mmu_miss_fault(istate_t *istate, const char *str);
55
static void do_fast_instruction_access_mmu_miss_fault(istate_t *istate, const char *str);
-
 
56
static void do_fast_data_access_mmu_miss_fault(istate_t *istate, tlb_tag_access_reg_t tag, const char *str);
57
static void do_fast_data_access_protection_fault(istate_t *istate, const char *str);
57
static void do_fast_data_access_protection_fault(istate_t *istate, tlb_tag_access_reg_t tag, const char *str);
58
 
58
 
59
char *context_encoding[] = {
59
char *context_encoding[] = {
60
    "Primary",
60
    "Primary",
61
    "Secondary",
61
    "Secondary",
62
    "Nucleus",
62
    "Nucleus",
Line 211... Line 211...
211
    tlb_tag_access_reg_t tag;
211
    tlb_tag_access_reg_t tag;
212
    uintptr_t va;
212
    uintptr_t va;
213
    pte_t *t;
213
    pte_t *t;
214
 
214
 
215
    tag.value = dtlb_tag_access_read();
215
    tag.value = dtlb_tag_access_read();
216
    va = tag.vpn * PAGE_SIZE;
216
    va = tag.vpn << PAGE_WIDTH;
-
 
217
 
217
    if (tag.context == ASID_KERNEL) {
218
    if (tag.context == ASID_KERNEL) {
218
        if (!tag.vpn) {
219
        if (!tag.vpn) {
219
            /* NULL access in kernel */
220
            /* NULL access in kernel */
220
            do_fast_data_access_mmu_miss_fault(istate, __FUNCTION__);
221
            do_fast_data_access_mmu_miss_fault(istate, tag, __FUNCTION__);
221
        }
222
        }
222
        do_fast_data_access_mmu_miss_fault(istate, "Unexpected kernel page fault.");
223
        do_fast_data_access_mmu_miss_fault(istate, tag, "Unexpected kernel page fault.");
223
    }
224
    }
224
 
225
 
225
    page_table_lock(AS, true);
226
    page_table_lock(AS, true);
226
    t = page_mapping_find(AS, va);
227
    t = page_mapping_find(AS, va);
227
    if (t) {
228
    if (t) {
Line 236... Line 237...
236
        /*
237
        /*
237
         * Forward the page fault to the address space page fault handler.
238
         * Forward the page fault to the address space page fault handler.
238
         */    
239
         */    
239
        page_table_unlock(AS, true);
240
        page_table_unlock(AS, true);
240
        if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) {
241
        if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) {
241
            do_fast_data_access_mmu_miss_fault(istate, __FUNCTION__);
242
            do_fast_data_access_mmu_miss_fault(istate, tag, __FUNCTION__);
242
        }
243
        }
243
    }
244
    }
244
}
245
}
245
 
246
 
246
/** DTLB protection fault handler. */
247
/** DTLB protection fault handler. */
Line 249... Line 250...
249
    tlb_tag_access_reg_t tag;
250
    tlb_tag_access_reg_t tag;
250
    uintptr_t va;
251
    uintptr_t va;
251
    pte_t *t;
252
    pte_t *t;
252
 
253
 
253
    tag.value = dtlb_tag_access_read();
254
    tag.value = dtlb_tag_access_read();
254
    va = tag.vpn * PAGE_SIZE;
255
    va = tag.vpn << PAGE_WIDTH;
255
 
256
 
256
    page_table_lock(AS, true);
257
    page_table_lock(AS, true);
257
    t = page_mapping_find(AS, va);
258
    t = page_mapping_find(AS, va);
258
    if (t && PTE_WRITABLE(t)) {
259
    if (t && PTE_WRITABLE(t)) {
259
        /*
260
        /*
Line 269... Line 270...
269
        /*
270
        /*
270
         * Forward the page fault to the address space page fault handler.
271
         * Forward the page fault to the address space page fault handler.
271
         */    
272
         */    
272
        page_table_unlock(AS, true);
273
        page_table_unlock(AS, true);
273
        if (as_page_fault(va, PF_ACCESS_WRITE, istate) == AS_PF_FAULT) {
274
        if (as_page_fault(va, PF_ACCESS_WRITE, istate) == AS_PF_FAULT) {
274
            do_fast_data_access_protection_fault(istate, __FUNCTION__);
275
            do_fast_data_access_protection_fault(istate, tag, __FUNCTION__);
275
        }
276
        }
276
    }
277
    }
277
}
278
}
278
 
279
 
279
/** Print contents of both TLBs. */
280
/** Print contents of both TLBs. */
Line 309... Line 310...
309
 
310
 
310
    printf("TPC=%p, (%s)\n", istate->tpc, tpc_str);
311
    printf("TPC=%p, (%s)\n", istate->tpc, tpc_str);
311
    panic("%s\n", str);
312
    panic("%s\n", str);
312
}
313
}
313
 
314
 
314
void do_fast_data_access_mmu_miss_fault(istate_t *istate, const char *str)
315
void do_fast_data_access_mmu_miss_fault(istate_t *istate, tlb_tag_access_reg_t tag, const char *str)
315
{
316
{
316
    tlb_tag_access_reg_t tag;
-
 
317
    uintptr_t va;
317
    uintptr_t va;
318
    char *tpc_str = get_symtab_entry(istate->tpc);
318
    char *tpc_str = get_symtab_entry(istate->tpc);
319
 
319
 
320
    tag.value = dtlb_tag_access_read();
-
 
321
    va = tag.vpn * PAGE_SIZE;
320
    va = tag.vpn << PAGE_WIDTH;
322
 
321
 
323
    printf("Faulting page: %p, ASID=%d\n", va, tag.context);
322
    printf("Faulting page: %p, ASID=%d\n", va, tag.context);
324
    printf("TPC=%p, (%s)\n", istate->tpc, tpc_str);
323
    printf("TPC=%p, (%s)\n", istate->tpc, tpc_str);
325
    panic("%s\n", str);
324
    panic("%s\n", str);
326
}
325
}
327
 
326
 
328
void do_fast_data_access_protection_fault(istate_t *istate, const char *str)
327
void do_fast_data_access_protection_fault(istate_t *istate, tlb_tag_access_reg_t tag, const char *str)
329
{
328
{
330
    tlb_tag_access_reg_t tag;
-
 
331
    uintptr_t va;
329
    uintptr_t va;
332
    char *tpc_str = get_symtab_entry(istate->tpc);
330
    char *tpc_str = get_symtab_entry(istate->tpc);
333
 
331
 
334
    tag.value = dtlb_tag_access_read();
-
 
335
    va = tag.vpn * PAGE_SIZE;
332
    va = tag.vpn << PAGE_WIDTH;
336
 
333
 
337
    printf("Faulting page: %p, ASID=%d\n", va, tag.context);
334
    printf("Faulting page: %p, ASID=%d\n", va, tag.context);
338
    printf("TPC=%p, (%s)\n", istate->tpc, tpc_str);
335
    printf("TPC=%p, (%s)\n", istate->tpc, tpc_str);
339
    panic("%s\n", str);
336
    panic("%s\n", str);
340
}
337
}
Line 372... Line 369...
372
 *
369
 *
373
 * @param asid Address Space ID.
370
 * @param asid Address Space ID.
374
 */
371
 */
375
void tlb_invalidate_asid(asid_t asid)
372
void tlb_invalidate_asid(asid_t asid)
376
{
373
{
377
    tlb_context_reg_t sc_save, ctx;
374
    tlb_context_reg_t pc_save, ctx;
378
   
375
   
-
 
376
    /* switch to nucleus because we are mapped by the primary context */
-
 
377
    nucleus_enter();
-
 
378
   
379
    ctx.v = sc_save.v = mmu_secondary_context_read();
379
    ctx.v = pc_save.v = mmu_primary_context_read();
380
    ctx.context = asid;
380
    ctx.context = asid;
381
    mmu_secondary_context_write(ctx.v);
381
    mmu_primary_context_write(ctx.v);
-
 
382
   
-
 
383
    itlb_demap(TLB_DEMAP_CONTEXT, TLB_DEMAP_PRIMARY, 0);
-
 
384
    dtlb_demap(TLB_DEMAP_CONTEXT, TLB_DEMAP_PRIMARY, 0);
382
   
385
   
383
    itlb_demap(TLB_DEMAP_CONTEXT, TLB_DEMAP_SECONDARY, 0);
-
 
384
    dtlb_demap(TLB_DEMAP_CONTEXT, TLB_DEMAP_SECONDARY, 0);
386
    mmu_primary_context_write(pc_save.v);
385
   
387
   
386
    mmu_secondary_context_write(sc_save.v);
388
    nucleus_leave();
387
}
389
}
388
 
390
 
389
/** Invalidate all ITLB and DTLB entries for specified page range in specified address space.
391
/** Invalidate all ITLB and DTLB entries for specified page range in specified address space.
390
 *
392
 *
391
 * @param asid Address Space ID.
393
 * @param asid Address Space ID.
Line 393... Line 395...
393
 * @param cnt Number of ITLB and DTLB entries to invalidate.
395
 * @param cnt Number of ITLB and DTLB entries to invalidate.
394
 */
396
 */
395
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt)
397
void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt)
396
{
398
{
397
    int i;
399
    int i;
398
    tlb_context_reg_t sc_save, ctx;
400
    tlb_context_reg_t pc_save, ctx;
399
   
401
   
-
 
402
    /* switch to nucleus because we are mapped by the primary context */
-
 
403
    nucleus_enter();
-
 
404
   
400
    ctx.v = sc_save.v = mmu_secondary_context_read();
405
    ctx.v = pc_save.v = mmu_primary_context_read();
401
    ctx.context = asid;
406
    ctx.context = asid;
402
    mmu_secondary_context_write(ctx.v);
407
    mmu_primary_context_write(ctx.v);
403
   
408
   
404
    for (i = 0; i < cnt; i++) {
409
    for (i = 0; i < cnt; i++) {
405
        itlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_SECONDARY, page + i * PAGE_SIZE);
410
        itlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_PRIMARY, page + i * PAGE_SIZE);
406
        dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_SECONDARY, page + i * PAGE_SIZE);
411
        dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_PRIMARY, page + i * PAGE_SIZE);
407
    }
412
    }
408
   
413
   
409
    mmu_secondary_context_write(sc_save.v);
414
    mmu_primary_context_write(pc_save.v);
-
 
415
   
-
 
416
    nucleus_leave();
410
}
417
}
411
 
418
 
412
/** @}
419
/** @}
413
 */
420
 */