target-sparc: Add MMU_PHYS_IDX

It's handy to have a mmu idx for physical addresses, so
that mmu disabled and physical access asis can use the
same path as normal accesses.

Backports commit af7a06bac7d3abb2da48ef3277d2a415772d2ae8 from qemu
This commit is contained in:
Richard Henderson 2018-02-28 12:24:11 -05:00 committed by Lioncash
parent 9e60a8e432
commit 15eea419e5
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
3 changed files with 53 additions and 45 deletions

View file

@ -221,9 +221,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 @@ static inline CPUSPARCState *cpu_init(struct uc_struct *uc, const char *cpu_mode
#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;

View file

@ -842,10 +842,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;
@ -1871,23 +1871,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;

View file

@ -90,7 +90,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,22 +494,21 @@ static int get_physical_address_data(CPUSPARCState *env,
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;
@ -612,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) {
@ -699,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);