#define MAX_NWINDOWS 32
#if !defined(TARGET_SPARC64)
-#define NB_MMU_MODES 2
+#define NB_MMU_MODES 3
#else
-#define NB_MMU_MODES 6
+#define NB_MMU_MODES 7
typedef struct trap_state {
uint64_t tpc;
uint64_t tnpc;
#define MMU_MODE4_SUFFIX _nucleus
#define MMU_HYPV_IDX 5
#define MMU_MODE5_SUFFIX _hypv
+#define MMU_PHYS_IDX 6
#else
#define MMU_USER_IDX 0
#define MMU_MODE0_SUFFIX _user
#define MMU_KERNEL_IDX 1
#define MMU_MODE1_SUFFIX _kernel
+#define MMU_PHYS_IDX 2
#endif
#if defined (TARGET_SPARC64)
}
#endif
-static inline int cpu_mmu_index(CPUSPARCState *env1, bool ifetch)
+static inline int cpu_mmu_index(CPUSPARCState *env, bool ifetch)
{
#if defined(CONFIG_USER_ONLY)
return MMU_USER_IDX;
#elif !defined(TARGET_SPARC64)
- return env1->psrs;
+ if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
+ return MMU_PHYS_IDX;
+ } else {
+ return env->psrs;
+ }
#else
- if (env1->tl > 0) {
+ /* IMMU or DMMU disabled. */
+ if (ifetch
+ ? (env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0
+ : (env->lsu & DMMU_E) == 0) {
+ return MMU_PHYS_IDX;
+ } else if (env->tl > 0) {
return MMU_NUCLEUS_IDX;
- } else if (cpu_hypervisor_mode(env1)) {
+ } else if (cpu_hypervisor_mode(env)) {
return MMU_HYPV_IDX;
- } else if (cpu_supervisor_mode(env1)) {
+ } else if (cpu_supervisor_mode(env)) {
return MMU_KERNEL_IDX;
} else {
return MMU_USER_IDX;
case 0: /* Control Register */
env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
(val & 0x00ffffff);
- /* Mappings generated during no-fault mode or MMU
- disabled mode are invalid in normal mode */
- if ((oldreg & (MMU_E | MMU_NF | env->def->mmu_bm)) !=
- (env->mmuregs[reg] & (MMU_E | MMU_NF | env->def->mmu_bm))) {
+ /* Mappings generated during no-fault mode
+ are invalid in normal mode. */
+ if ((oldreg ^ env->mmuregs[reg])
+ & (MMU_NF | env->def->mmu_bm)) {
tlb_flush(CPU(cpu), 1);
}
break;
/* XXX */
return;
case ASI_LSU_CONTROL: /* LSU */
- {
- uint64_t oldreg;
-
- oldreg = env->lsu;
- env->lsu = val & (DMMU_E | IMMU_E);
- /* Mappings generated during D/I MMU disabled mode are
- invalid in normal mode */
- if (oldreg != env->lsu) {
- DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
- oldreg, env->lsu);
-#ifdef DEBUG_MMU
- dump_mmu(stdout, fprintf, env);
-#endif
- tlb_flush(CPU(cpu), 1);
- }
- return;
- }
+ env->lsu = val & (DMMU_E | IMMU_E);
+ return;
case ASI_IMMU: /* I-MMU regs */
{
int reg = (addr >> 3) & 0xf;
is_user = mmu_idx == MMU_USER_IDX;
- if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
+ if (mmu_idx == MMU_PHYS_IDX) {
*page_size = TARGET_PAGE_SIZE;
/* Boot mode: instruction fetches are taken from PROM */
if (rw == 2 && (env->mmuregs[0] & env->def->mmu_bm)) {
unsigned int i;
uint64_t context;
uint64_t sfsr = 0;
-
- int is_user = (mmu_idx == MMU_USER_IDX ||
- mmu_idx == MMU_USER_SECONDARY_IDX);
-
- if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
- *physical = ultrasparc_truncate_physical(address);
- *prot = PAGE_READ | PAGE_WRITE;
- return 0;
- }
+ bool is_user = false;
switch (mmu_idx) {
+ case MMU_PHYS_IDX:
+ g_assert_not_reached();
case MMU_USER_IDX:
+ is_user = true;
+ /* fallthru */
case MMU_KERNEL_IDX:
context = env->dmmu.mmu_primary_context & 0x1fff;
sfsr |= SFSR_CT_PRIMARY;
break;
case MMU_USER_SECONDARY_IDX:
+ is_user = true;
+ /* fallthru */
case MMU_KERNEL_SECONDARY_IDX:
context = env->dmmu.mmu_secondary_context & 0x1fff;
sfsr |= SFSR_CT_SECONDARY;
CPUState *cs = CPU(sparc_env_get_cpu(env));
unsigned int i;
uint64_t context;
+ bool is_user = false;
- int is_user = (mmu_idx == MMU_USER_IDX ||
- mmu_idx == MMU_USER_SECONDARY_IDX);
-
- if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
- /* IMMU disabled */
- *physical = ultrasparc_truncate_physical(address);
- *prot = PAGE_EXEC;
- return 0;
+ switch (mmu_idx) {
+ case MMU_PHYS_IDX:
+ case MMU_USER_SECONDARY_IDX:
+ case MMU_KERNEL_SECONDARY_IDX:
+ g_assert_not_reached();
+ case MMU_USER_IDX:
+ is_user = true;
+ /* fallthru */
+ case MMU_KERNEL_IDX:
+ context = env->dmmu.mmu_primary_context & 0x1fff;
+ break;
+ default:
+ context = 0;
+ break;
}
if (env->tl == 0) {
}
}
+ if (mmu_idx == MMU_PHYS_IDX) {
+ *physical = ultrasparc_truncate_physical(address);
+ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+ return 0;
+ }
+
if (rw == 2) {
return get_physical_address_code(env, physical, prot, address,
mmu_idx);