mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-03-23 06:25:12 +00:00
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:
parent
9e60a8e432
commit
15eea419e5
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue