diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index 3ae3a12e19..e94b8f19d6 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -225,9 +225,9 @@ enum { #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; @@ -649,11 +649,13 @@ int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc); #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) @@ -673,18 +675,27 @@ static inline int cpu_supervisor_mode(CPUSPARCState *env1) } #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; diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c index 3c70766adf..667b962afe 100644 --- a/target-sparc/ldst_helper.c +++ b/target-sparc/ldst_helper.c @@ -887,10 +887,10 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, 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; @@ -1866,23 +1866,8 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val, /* 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; diff --git a/target-sparc/mmu_helper.c b/target-sparc/mmu_helper.c index 32b629fb0d..044e88c4c5 100644 --- a/target-sparc/mmu_helper.c +++ b/target-sparc/mmu_helper.c @@ -92,7 +92,7 @@ static int get_physical_address(CPUSPARCState *env, hwaddr *physical, 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)) { @@ -494,23 +494,21 @@ static int get_physical_address_data(CPUSPARCState *env, 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; @@ -613,15 +611,22 @@ static int get_physical_address_code(CPUSPARCState *env, 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) { @@ -700,6 +705,12 @@ static int get_physical_address(CPUSPARCState *env, hwaddr *physical, } } + 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);