mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-24 03:59:52 +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. Tested-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
parent
2f9d35fc40
commit
af7a06bac7
@ -225,9 +225,9 @@ enum {
|
|||||||
#define MAX_NWINDOWS 32
|
#define MAX_NWINDOWS 32
|
||||||
|
|
||||||
#if !defined(TARGET_SPARC64)
|
#if !defined(TARGET_SPARC64)
|
||||||
#define NB_MMU_MODES 2
|
#define NB_MMU_MODES 3
|
||||||
#else
|
#else
|
||||||
#define NB_MMU_MODES 6
|
#define NB_MMU_MODES 7
|
||||||
typedef struct trap_state {
|
typedef struct trap_state {
|
||||||
uint64_t tpc;
|
uint64_t tpc;
|
||||||
uint64_t tnpc;
|
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_MODE4_SUFFIX _nucleus
|
||||||
#define MMU_HYPV_IDX 5
|
#define MMU_HYPV_IDX 5
|
||||||
#define MMU_MODE5_SUFFIX _hypv
|
#define MMU_MODE5_SUFFIX _hypv
|
||||||
|
#define MMU_PHYS_IDX 6
|
||||||
#else
|
#else
|
||||||
#define MMU_USER_IDX 0
|
#define MMU_USER_IDX 0
|
||||||
#define MMU_MODE0_SUFFIX _user
|
#define MMU_MODE0_SUFFIX _user
|
||||||
#define MMU_KERNEL_IDX 1
|
#define MMU_KERNEL_IDX 1
|
||||||
#define MMU_MODE1_SUFFIX _kernel
|
#define MMU_MODE1_SUFFIX _kernel
|
||||||
|
#define MMU_PHYS_IDX 2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined (TARGET_SPARC64)
|
#if defined (TARGET_SPARC64)
|
||||||
@ -673,18 +675,27 @@ static inline int cpu_supervisor_mode(CPUSPARCState *env1)
|
|||||||
}
|
}
|
||||||
#endif
|
#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)
|
#if defined(CONFIG_USER_ONLY)
|
||||||
return MMU_USER_IDX;
|
return MMU_USER_IDX;
|
||||||
#elif !defined(TARGET_SPARC64)
|
#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
|
#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;
|
return MMU_NUCLEUS_IDX;
|
||||||
} else if (cpu_hypervisor_mode(env1)) {
|
} else if (cpu_hypervisor_mode(env)) {
|
||||||
return MMU_HYPV_IDX;
|
return MMU_HYPV_IDX;
|
||||||
} else if (cpu_supervisor_mode(env1)) {
|
} else if (cpu_supervisor_mode(env)) {
|
||||||
return MMU_KERNEL_IDX;
|
return MMU_KERNEL_IDX;
|
||||||
} else {
|
} else {
|
||||||
return MMU_USER_IDX;
|
return MMU_USER_IDX;
|
||||||
|
@ -887,10 +887,10 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val,
|
|||||||
case 0: /* Control Register */
|
case 0: /* Control Register */
|
||||||
env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
|
env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
|
||||||
(val & 0x00ffffff);
|
(val & 0x00ffffff);
|
||||||
/* Mappings generated during no-fault mode or MMU
|
/* Mappings generated during no-fault mode
|
||||||
disabled mode are invalid in normal mode */
|
are invalid in normal mode. */
|
||||||
if ((oldreg & (MMU_E | MMU_NF | env->def->mmu_bm)) !=
|
if ((oldreg ^ env->mmuregs[reg])
|
||||||
(env->mmuregs[reg] & (MMU_E | MMU_NF | env->def->mmu_bm))) {
|
& (MMU_NF | env->def->mmu_bm)) {
|
||||||
tlb_flush(CPU(cpu), 1);
|
tlb_flush(CPU(cpu), 1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1866,23 +1866,8 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
|
|||||||
/* XXX */
|
/* XXX */
|
||||||
return;
|
return;
|
||||||
case ASI_LSU_CONTROL: /* LSU */
|
case ASI_LSU_CONTROL: /* LSU */
|
||||||
{
|
env->lsu = val & (DMMU_E | IMMU_E);
|
||||||
uint64_t oldreg;
|
return;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
case ASI_IMMU: /* I-MMU regs */
|
case ASI_IMMU: /* I-MMU regs */
|
||||||
{
|
{
|
||||||
int reg = (addr >> 3) & 0xf;
|
int reg = (addr >> 3) & 0xf;
|
||||||
|
@ -92,7 +92,7 @@ static int get_physical_address(CPUSPARCState *env, hwaddr *physical,
|
|||||||
|
|
||||||
is_user = mmu_idx == MMU_USER_IDX;
|
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;
|
*page_size = TARGET_PAGE_SIZE;
|
||||||
/* Boot mode: instruction fetches are taken from PROM */
|
/* Boot mode: instruction fetches are taken from PROM */
|
||||||
if (rw == 2 && (env->mmuregs[0] & env->def->mmu_bm)) {
|
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;
|
unsigned int i;
|
||||||
uint64_t context;
|
uint64_t context;
|
||||||
uint64_t sfsr = 0;
|
uint64_t sfsr = 0;
|
||||||
|
bool is_user = false;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (mmu_idx) {
|
switch (mmu_idx) {
|
||||||
|
case MMU_PHYS_IDX:
|
||||||
|
g_assert_not_reached();
|
||||||
case MMU_USER_IDX:
|
case MMU_USER_IDX:
|
||||||
|
is_user = true;
|
||||||
|
/* fallthru */
|
||||||
case MMU_KERNEL_IDX:
|
case MMU_KERNEL_IDX:
|
||||||
context = env->dmmu.mmu_primary_context & 0x1fff;
|
context = env->dmmu.mmu_primary_context & 0x1fff;
|
||||||
sfsr |= SFSR_CT_PRIMARY;
|
sfsr |= SFSR_CT_PRIMARY;
|
||||||
break;
|
break;
|
||||||
case MMU_USER_SECONDARY_IDX:
|
case MMU_USER_SECONDARY_IDX:
|
||||||
|
is_user = true;
|
||||||
|
/* fallthru */
|
||||||
case MMU_KERNEL_SECONDARY_IDX:
|
case MMU_KERNEL_SECONDARY_IDX:
|
||||||
context = env->dmmu.mmu_secondary_context & 0x1fff;
|
context = env->dmmu.mmu_secondary_context & 0x1fff;
|
||||||
sfsr |= SFSR_CT_SECONDARY;
|
sfsr |= SFSR_CT_SECONDARY;
|
||||||
@ -613,15 +611,22 @@ static int get_physical_address_code(CPUSPARCState *env,
|
|||||||
CPUState *cs = CPU(sparc_env_get_cpu(env));
|
CPUState *cs = CPU(sparc_env_get_cpu(env));
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
uint64_t context;
|
uint64_t context;
|
||||||
|
bool is_user = false;
|
||||||
|
|
||||||
int is_user = (mmu_idx == MMU_USER_IDX ||
|
switch (mmu_idx) {
|
||||||
mmu_idx == MMU_USER_SECONDARY_IDX);
|
case MMU_PHYS_IDX:
|
||||||
|
case MMU_USER_SECONDARY_IDX:
|
||||||
if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
|
case MMU_KERNEL_SECONDARY_IDX:
|
||||||
/* IMMU disabled */
|
g_assert_not_reached();
|
||||||
*physical = ultrasparc_truncate_physical(address);
|
case MMU_USER_IDX:
|
||||||
*prot = PAGE_EXEC;
|
is_user = true;
|
||||||
return 0;
|
/* fallthru */
|
||||||
|
case MMU_KERNEL_IDX:
|
||||||
|
context = env->dmmu.mmu_primary_context & 0x1fff;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
context = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (env->tl == 0) {
|
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) {
|
if (rw == 2) {
|
||||||
return get_physical_address_code(env, physical, prot, address,
|
return get_physical_address_code(env, physical, prot, address,
|
||||||
mmu_idx);
|
mmu_idx);
|
||||||
|
Loading…
Reference in New Issue
Block a user