Revision b8e9fc06 target-sparc/helper.c
b/target-sparc/helper.c | ||
---|---|---|
30 | 30 |
//#define DEBUG_MMU |
31 | 31 |
//#define DEBUG_FEATURES |
32 | 32 |
|
33 |
#ifdef DEBUG_MMU |
|
34 |
#define DPRINTF_MMU(fmt, ...) \ |
|
35 |
do { printf("MMU: " fmt , ## __VA_ARGS__); } while (0) |
|
36 |
#else |
|
37 |
#define DPRINTF_MMU(fmt, ...) do {} while (0) |
|
38 |
#endif |
|
39 |
|
|
33 | 40 |
static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model); |
34 | 41 |
|
35 | 42 |
/* Sparc MMU emulation */ |
... | ... | |
451 | 458 |
|
452 | 459 |
for (i = 0; i < 64; i++) { |
453 | 460 |
// ctx match, vaddr match, valid? |
454 |
if (ultrasparc_tag_match(&env->dtlb[i], |
|
455 |
address, context, physical)) { |
|
461 |
if (ultrasparc_tag_match(&env->dtlb[i], address, context, physical)) { |
|
462 |
|
|
463 |
uint8_t fault_type = 0; |
|
464 |
|
|
456 | 465 |
// access ok? |
457 |
if (((env->dtlb[i].tte & 0x4) && is_user) ||
|
|
458 |
(!(env->dtlb[i].tte & 0x2) && (rw == 1))) {
|
|
459 |
uint8_t fault_type = 0;
|
|
466 |
if ((env->dtlb[i].tte & 0x4) && is_user) {
|
|
467 |
fault_type |= 1; /* privilege violation */
|
|
468 |
env->exception_index = TT_DFAULT;
|
|
460 | 469 |
|
461 |
if ((env->dtlb[i].tte & 0x4) && is_user) { |
|
462 |
fault_type |= 1; /* privilege violation */ |
|
463 |
} |
|
470 |
DPRINTF_MMU("DFAULT at %" PRIx64 " context %" PRIx64 |
|
471 |
" mmu_idx=%d tl=%d\n", |
|
472 |
address, context, mmu_idx, env->tl); |
|
473 |
} else if (!(env->dtlb[i].tte & 0x2) && (rw == 1)) { |
|
474 |
env->exception_index = TT_DPROT; |
|
464 | 475 |
|
465 |
if (env->dmmu.sfsr & 1) /* Fault status register */ |
|
466 |
env->dmmu.sfsr = 2; /* overflow (not read before |
|
476 |
DPRINTF_MMU("DPROT at %" PRIx64 " context %" PRIx64 |
|
477 |
" mmu_idx=%d tl=%d\n", |
|
478 |
address, context, mmu_idx, env->tl); |
|
479 |
} else { |
|
480 |
*prot = PAGE_READ; |
|
481 |
if (env->dtlb[i].tte & 0x2) |
|
482 |
*prot |= PAGE_WRITE; |
|
483 |
|
|
484 |
TTE_SET_USED(env->dtlb[i].tte); |
|
485 |
|
|
486 |
return 0; |
|
487 |
} |
|
488 |
|
|
489 |
if (env->dmmu.sfsr & 1) /* Fault status register */ |
|
490 |
env->dmmu.sfsr = 2; /* overflow (not read before |
|
467 | 491 |
another fault) */ |
468 | 492 |
|
469 |
env->dmmu.sfsr |= (is_user << 3) | ((rw == 1) << 2) | 1;
|
|
493 |
env->dmmu.sfsr |= (is_user << 3) | ((rw == 1) << 2) | 1; |
|
470 | 494 |
|
471 |
env->dmmu.sfsr |= (fault_type << 7);
|
|
495 |
env->dmmu.sfsr |= (fault_type << 7); |
|
472 | 496 |
|
473 |
env->dmmu.sfar = address; /* Fault address register */ |
|
474 |
env->exception_index = TT_DFAULT; |
|
475 |
#ifdef DEBUG_MMU |
|
476 |
printf("DFAULT at 0x%" PRIx64 "\n", address); |
|
477 |
#endif |
|
478 |
return 1; |
|
479 |
} |
|
480 |
*prot = PAGE_READ; |
|
481 |
if (env->dtlb[i].tte & 0x2) |
|
482 |
*prot |= PAGE_WRITE; |
|
483 |
TTE_SET_USED(env->dtlb[i].tte); |
|
484 |
return 0; |
|
497 |
env->dmmu.sfar = address; /* Fault address register */ |
|
498 |
return 1; |
|
485 | 499 |
} |
486 | 500 |
} |
487 |
#ifdef DEBUG_MMU |
|
488 |
printf("DMISS at 0x%" PRIx64 "\n", address); |
|
489 |
#endif |
|
501 |
|
|
502 |
DPRINTF_MMU("DMISS at %" PRIx64 " context %" PRIx64 "\n", |
|
503 |
address, context); |
|
504 |
|
|
490 | 505 |
env->dmmu.tag_access = (address & ~0x1fffULL) | context; |
491 | 506 |
env->exception_index = TT_DMISS; |
492 | 507 |
return 1; |
... | ... | |
528 | 543 |
another fault) */ |
529 | 544 |
env->immu.sfsr |= (is_user << 3) | 1; |
530 | 545 |
env->exception_index = TT_TFAULT; |
531 |
#ifdef DEBUG_MMU |
|
532 |
printf("TFAULT at 0x%" PRIx64 "\n", address); |
|
533 |
#endif |
|
546 |
|
|
547 |
DPRINTF_MMU("TFAULT at %" PRIx64 " context %" PRIx64 "\n", |
|
548 |
address, context); |
|
549 |
|
|
534 | 550 |
return 1; |
535 | 551 |
} |
536 | 552 |
*prot = PAGE_EXEC; |
... | ... | |
538 | 554 |
return 0; |
539 | 555 |
} |
540 | 556 |
} |
541 |
#ifdef DEBUG_MMU |
|
542 |
printf("TMISS at 0x%" PRIx64 "\n", address); |
|
543 |
#endif |
|
557 |
|
|
558 |
DPRINTF_MMU("TMISS at %" PRIx64 " context %" PRIx64 "\n", |
|
559 |
address, context); |
|
560 |
|
|
544 | 561 |
/* Context is stored in DMMU (dmmuregs[1]) also for IMMU */ |
545 | 562 |
env->immu.tag_access = (address & ~0x1fffULL) | context; |
546 | 563 |
env->exception_index = TT_TMISS; |
... | ... | |
578 | 595 |
virt_addr = address & TARGET_PAGE_MASK; |
579 | 596 |
vaddr = virt_addr + ((address & TARGET_PAGE_MASK) & |
580 | 597 |
(TARGET_PAGE_SIZE - 1)); |
581 |
#ifdef DEBUG_MMU |
|
582 |
printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64 |
|
583 |
"\n", address, paddr, vaddr); |
|
584 |
#endif |
|
598 |
|
|
599 |
DPRINTF_MMU("Translate at %" PRIx64 " -> %" PRIx64 "," |
|
600 |
" vaddr %" PRIx64 |
|
601 |
" mmu_idx=%d" |
|
602 |
" tl=%d" |
|
603 |
" primary context=%" PRIx64 |
|
604 |
" secondary context=%" PRIx64 |
|
605 |
"\n", |
|
606 |
address, paddr, vaddr, mmu_idx, env->tl, |
|
607 |
env->dmmu.mmu_primary_context, |
|
608 |
env->dmmu.mmu_secondary_context); |
|
609 |
|
|
585 | 610 |
tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size); |
586 | 611 |
return 0; |
587 | 612 |
} |
Also available in: Unified diff