From 2aae2b8e0abd58e76d616bcbe93c6966d06d0188 Mon Sep 17 00:00:00 2001 From: "Igor V. Kovalenko" Date: Sat, 22 May 2010 14:52:24 +0400 Subject: [PATCH] sparc64: fix pstate privilege bits - refactor code to handle hpstate only if available for current cpu - conditionally set hypervisor bit in hpstate register - reorder softmmu indices so user accessable ones go first, translation context macros supervisor() and hypervisor() adjusted as well - disable sparcv8 registers for TARGET_SPARC64 - fix cpu_mmu_index to use sparcv9 bits only Signed-off-by: Igor V. Kovalenko Signed-off-by: Blue Swirl --- target-sparc/cpu.h | 63 ++++++++++++++++++++++++++++------------ target-sparc/helper.c | 4 +-- target-sparc/op_helper.c | 24 +++++++-------- target-sparc/translate.c | 4 +-- 4 files changed, 58 insertions(+), 37 deletions(-) diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index 27b020b541..4fd58e9c38 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -92,12 +92,14 @@ #define PSR_CARRY_SHIFT 20 #define PSR_CARRY (1 << PSR_CARRY_SHIFT) #define PSR_ICC (PSR_NEG|PSR_ZERO|PSR_OVF|PSR_CARRY) +#if !defined(TARGET_SPARC64) #define PSR_EF (1<<12) #define PSR_PIL 0xf00 #define PSR_S (1<<7) #define PSR_PS (1<<6) #define PSR_ET (1<<5) #define PSR_CWP 0x1f +#endif #define CC_SRC (env->cc_src) #define CC_SRC2 (env->cc_src2) @@ -341,14 +343,16 @@ typedef struct CPUSPARCState { uint32_t wim; /* window invalid mask */ #endif target_ulong tbr; /* trap base register */ +#if !defined(TARGET_SPARC64) int psrs; /* supervisor mode (extracted from PSR) */ int psrps; /* previous supervisor mode */ -#if !defined(TARGET_SPARC64) int psret; /* enable traps */ #endif uint32_t psrpil; /* interrupt blocking level */ uint32_t pil_in; /* incoming interrupt level bitmap */ +#if !defined(TARGET_SPARC64) int psref; /* enable fpu */ +#endif target_ulong version; int interrupt_index; uint32_t nwindows; @@ -508,21 +512,41 @@ int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc); #define CPU_SAVE_VERSION 6 /* MMU modes definitions */ -#define MMU_MODE0_SUFFIX _user -#define MMU_MODE1_SUFFIX _kernel -#ifdef TARGET_SPARC64 -#define MMU_MODE2_SUFFIX _hypv -#define MMU_MODE3_SUFFIX _nucleus -#define MMU_MODE4_SUFFIX _user_secondary -#define MMU_MODE5_SUFFIX _kernel_secondary -#endif +#if defined (TARGET_SPARC64) #define MMU_USER_IDX 0 +#define MMU_MODE0_SUFFIX _user +#define MMU_USER_SECONDARY_IDX 1 +#define MMU_MODE1_SUFFIX _user_secondary +#define MMU_KERNEL_IDX 2 +#define MMU_MODE2_SUFFIX _kernel +#define MMU_KERNEL_SECONDARY_IDX 3 +#define MMU_MODE3_SUFFIX _kernel_secondary +#define MMU_NUCLEUS_IDX 4 +#define MMU_MODE4_SUFFIX _nucleus +#define MMU_HYPV_IDX 5 +#define MMU_MODE5_SUFFIX _hypv +#else +#define MMU_USER_IDX 0 +#define MMU_MODE0_SUFFIX _user #define MMU_KERNEL_IDX 1 -#define MMU_HYPV_IDX 2 -#ifdef TARGET_SPARC64 -#define MMU_NUCLEUS_IDX 3 -#define MMU_USER_SECONDARY_IDX 4 -#define MMU_KERNEL_SECONDARY_IDX 5 +#define MMU_MODE1_SUFFIX _kernel +#endif + +#if defined (TARGET_SPARC64) +static inline int cpu_has_hypervisor(CPUState *env1) +{ + return env1->def->features & CPU_FEATURE_HYPV; +} + +static inline int cpu_hypervisor_mode(CPUState *env1) +{ + return cpu_has_hypervisor(env1) && (env1->hpstate & HS_PRIV); +} + +static inline int cpu_supervisor_mode(CPUState *env1) +{ + return env1->pstate & PS_PRIV; +} #endif static inline int cpu_mmu_index(CPUState *env1) @@ -532,12 +556,13 @@ static inline int cpu_mmu_index(CPUState *env1) #elif !defined(TARGET_SPARC64) return env1->psrs; #else - if (!env1->psrs) - return MMU_USER_IDX; - else if ((env1->hpstate & HS_PRIV) == 0) - return MMU_KERNEL_IDX; - else + if (cpu_hypervisor_mode(env1)) { return MMU_HYPV_IDX; + } else if (cpu_supervisor_mode(env1)) { + return MMU_KERNEL_IDX; + } else { + return MMU_USER_IDX; + } #endif } diff --git a/target-sparc/helper.c b/target-sparc/helper.c index 4a494de357..538795f4f1 100644 --- a/target-sparc/helper.c +++ b/target-sparc/helper.c @@ -746,12 +746,12 @@ void cpu_reset(CPUSPARCState *env) #else #if !defined(TARGET_SPARC64) env->psret = 0; -#endif env->psrs = 1; env->psrps = 1; +#endif #ifdef TARGET_SPARC64 env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG; - env->hpstate = HS_PRIV; + env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0; env->tl = env->maxtl; cpu_tsptr(env)->tt = TT_POWER_ON_RESET; env->lsu = 0; diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c index d0bc27766e..28224b23dc 100644 --- a/target-sparc/op_helper.c +++ b/target-sparc/op_helper.c @@ -1404,11 +1404,7 @@ static target_ulong get_psr(void) (env->psrps? PSR_PS : 0) | (env->psret? PSR_ET : 0) | env->cwp; #else - return env->version | (env->psr & PSR_ICC) | - (env->psref? PSR_EF : 0) | - (env->psrpil << 8) | - (env->psrs? PSR_S : 0) | - (env->psrps? PSR_PS : 0) | env->cwp; + return env->psr & PSR_ICC; #endif } @@ -1427,17 +1423,19 @@ target_ulong cpu_get_psr(CPUState *env1) static void put_psr(target_ulong val) { env->psr = val & PSR_ICC; +#if !defined (TARGET_SPARC64) env->psref = (val & PSR_EF)? 1 : 0; env->psrpil = (val & PSR_PIL) >> 8; +#endif #if ((!defined (TARGET_SPARC64)) && !defined(CONFIG_USER_ONLY)) cpu_check_irqs(env); #endif +#if !defined (TARGET_SPARC64) env->psrs = (val & PSR_S)? 1 : 0; env->psrps = (val & PSR_PS)? 1 : 0; -#if !defined (TARGET_SPARC64) env->psret = (val & PSR_ET)? 1 : 0; -#endif set_cwp(val & PSR_CWP); +#endif env->cc_op = CC_OP_FLAGS; } @@ -2326,7 +2324,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) asi &= 0xff; if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0) - || ((env->def->features & CPU_FEATURE_HYPV) + || (cpu_has_hypervisor(env) && asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV))) raise_exception(TT_PRIV_ACT); @@ -2361,8 +2359,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) case 0xe2: // UA2007 Primary block init case 0xe3: // UA2007 Secondary block init if ((asi & 0x80) && (env->pstate & PS_PRIV)) { - if ((env->def->features & CPU_FEATURE_HYPV) - && env->hpstate & HS_PRIV) { + if (cpu_hypervisor_mode(env)) { switch(size) { case 1: ret = ldub_hypv(addr); @@ -2678,7 +2675,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) asi &= 0xff; if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0) - || ((env->def->features & CPU_FEATURE_HYPV) + || (cpu_has_hypervisor(env) && asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV))) raise_exception(TT_PRIV_ACT); @@ -2722,8 +2719,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) case 0xe2: // UA2007 Primary block init case 0xe3: // UA2007 Secondary block init if ((asi & 0x80) && (env->pstate & PS_PRIV)) { - if ((env->def->features & CPU_FEATURE_HYPV) - && env->hpstate & HS_PRIV) { + if (cpu_hypervisor_mode(env)) { switch(size) { case 1: stb_hypv(addr, val); @@ -3048,7 +3044,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) void helper_ldda_asi(target_ulong addr, int asi, int rd) { if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0) - || ((env->def->features & CPU_FEATURE_HYPV) + || (cpu_has_hypervisor(env) && asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV))) raise_exception(TT_PRIV_ACT); diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 8129b79d16..86096d2a4c 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -183,9 +183,9 @@ static void gen_op_store_QT0_fpr(unsigned int dst) #define hypervisor(dc) 0 #endif #else -#define supervisor(dc) (dc->mem_idx >= 1) +#define supervisor(dc) (dc->mem_idx >= MMU_KERNEL_IDX) #ifdef TARGET_SPARC64 -#define hypervisor(dc) (dc->mem_idx == 2) +#define hypervisor(dc) (dc->mem_idx == MMU_HYPV_IDX) #else #endif #endif