413 |
413 |
{
|
414 |
414 |
unsigned int i;
|
415 |
415 |
uint64_t context;
|
|
416 |
uint64_t sfsr = 0;
|
416 |
417 |
|
417 |
418 |
int is_user = (mmu_idx == MMU_USER_IDX ||
|
418 |
419 |
mmu_idx == MMU_USER_SECONDARY_IDX);
|
... | ... | |
427 |
428 |
case MMU_USER_IDX:
|
428 |
429 |
case MMU_KERNEL_IDX:
|
429 |
430 |
context = env->dmmu.mmu_primary_context & 0x1fff;
|
|
431 |
sfsr |= SFSR_CT_PRIMARY;
|
430 |
432 |
break;
|
431 |
433 |
case MMU_USER_SECONDARY_IDX:
|
432 |
434 |
case MMU_KERNEL_SECONDARY_IDX:
|
433 |
435 |
context = env->dmmu.mmu_secondary_context & 0x1fff;
|
|
436 |
sfsr |= SFSR_CT_SECONDARY;
|
434 |
437 |
break;
|
435 |
438 |
case MMU_NUCLEUS_IDX:
|
|
439 |
sfsr |= SFSR_CT_NUCLEUS;
|
|
440 |
/* FALLTHRU */
|
436 |
441 |
default:
|
437 |
442 |
context = 0;
|
438 |
443 |
break;
|
439 |
444 |
}
|
440 |
445 |
|
|
446 |
if (rw == 1) {
|
|
447 |
sfsr |= SFSR_WRITE_BIT;
|
|
448 |
}
|
|
449 |
|
441 |
450 |
for (i = 0; i < 64; i++) {
|
442 |
451 |
// ctx match, vaddr match, valid?
|
443 |
452 |
if (ultrasparc_tag_match(&env->dtlb[i], address, context, physical)) {
|
444 |
453 |
|
445 |
|
uint8_t fault_type = 0;
|
446 |
|
|
447 |
454 |
// access ok?
|
448 |
455 |
if (TTE_IS_PRIV(env->dtlb[i].tte) && is_user) {
|
449 |
|
fault_type |= 1; /* privilege violation */
|
|
456 |
sfsr |= SFSR_FT_PRIV_BIT; /* privilege violation */
|
450 |
457 |
env->exception_index = TT_DFAULT;
|
451 |
458 |
|
452 |
459 |
DPRINTF_MMU("DFAULT at %" PRIx64 " context %" PRIx64
|
... | ... | |
469 |
476 |
return 0;
|
470 |
477 |
}
|
471 |
478 |
|
472 |
|
if (env->dmmu.sfsr & 1) /* Fault status register */
|
473 |
|
env->dmmu.sfsr = 2; /* overflow (not read before
|
474 |
|
another fault) */
|
|
479 |
if (env->dmmu.sfsr & SFSR_VALID_BIT) { /* Fault status register */
|
|
480 |
sfsr |= SFSR_OW_BIT; /* overflow (not read before
|
|
481 |
another fault) */
|
|
482 |
}
|
475 |
483 |
|
476 |
|
env->dmmu.sfsr |= (is_user << 3) | ((rw == 1) << 2) | 1;
|
|
484 |
if (env->pstate & PS_PRIV) {
|
|
485 |
sfsr |= SFSR_PR_BIT;
|
|
486 |
}
|
477 |
487 |
|
478 |
|
env->dmmu.sfsr |= (fault_type << 7);
|
|
488 |
/* FIXME: ASI field in SFSR must be set */
|
|
489 |
env->dmmu.sfsr = sfsr | SFSR_VALID_BIT;
|
479 |
490 |
|
480 |
491 |
env->dmmu.sfar = address; /* Fault address register */
|
481 |
492 |
|
... | ... | |
488 |
499 |
DPRINTF_MMU("DMISS at %" PRIx64 " context %" PRIx64 "\n",
|
489 |
500 |
address, context);
|
490 |
501 |
|
|
502 |
/*
|
|
503 |
* On MMU misses:
|
|
504 |
* - UltraSPARC IIi: SFSR and SFAR unmodified
|
|
505 |
* - JPS1: SFAR updated and some fields of SFSR updated
|
|
506 |
*/
|
491 |
507 |
env->dmmu.tag_access = (address & ~0x1fffULL) | context;
|
492 |
508 |
env->exception_index = TT_DMISS;
|
493 |
509 |
return 1;
|
... | ... | |
524 |
540 |
address, context, physical)) {
|
525 |
541 |
// access ok?
|
526 |
542 |
if (TTE_IS_PRIV(env->itlb[i].tte) && is_user) {
|
527 |
|
if (env->immu.sfsr) /* Fault status register */
|
528 |
|
env->immu.sfsr = 2; /* overflow (not read before
|
529 |
|
another fault) */
|
530 |
|
env->immu.sfsr |= (is_user << 3) | 1;
|
|
543 |
/* Fault status register */
|
|
544 |
if (env->immu.sfsr & SFSR_VALID_BIT) {
|
|
545 |
env->immu.sfsr = SFSR_OW_BIT; /* overflow (not read before
|
|
546 |
another fault) */
|
|
547 |
} else {
|
|
548 |
env->immu.sfsr = 0;
|
|
549 |
}
|
|
550 |
if (env->pstate & PS_PRIV) {
|
|
551 |
env->immu.sfsr |= SFSR_PR_BIT;
|
|
552 |
}
|
|
553 |
if (env->tl > 0) {
|
|
554 |
env->immu.sfsr |= SFSR_CT_NUCLEUS;
|
|
555 |
}
|
|
556 |
|
|
557 |
/* FIXME: ASI field in SFSR must be set */
|
|
558 |
env->immu.sfsr |= SFSR_FT_PRIV_BIT | SFSR_VALID_BIT;
|
531 |
559 |
env->exception_index = TT_TFAULT;
|
532 |
560 |
|
533 |
561 |
env->immu.tag_access = (address & ~0x1fffULL) | context;
|