sparc64: trap handling corrections

On Sun, Jul 12, 2009 at 12:09 PM, Blue Swirl<blauwirbel@gmail.com> wrote:
> On 7/12/09, Igor Kovalenko <igor.v.kovalenko@gmail.com> wrote:
>> Good trap handling is required to process interrupts.
>>  This patch fixes the following:
>>
>>  - sparc64 has no wim register
>>  - sparc64 has no psret register, use IE bit of pstate
>>   extract IE checking code to cpu_interrupts_enabled
>>  - alternate globals are not available if cpu has GL feature
>>   in this case bit AG of pstate is constant zero
>>  - write to pstate must actually write pstate
>>   even if cpu has GL feature
>>
>>  Also timer interrupt is handled using do_interrupt.
>
> A bit too much for one patch. Please also remove the code instead of
> commenting out.

I now excluded timer interrupt related part.
To my mind other changes are essentially tied together.

> PUT_PSR for Sparc64 needs CC_OP = CC_OP_FLAGS; like Sparc32.

Fixed, please find attached the updated version.

--
Kind regards,
Igor V. Kovalenko
This commit is contained in:
Igor Kovalenko 2009-07-12 12:35:31 +04:00 committed by Blue Swirl
parent 49e6637386
commit 5210977a85
5 changed files with 77 additions and 27 deletions

View File

@ -475,7 +475,7 @@ int cpu_exec(CPUState *env1)
}
#elif defined(TARGET_SPARC)
if ((interrupt_request & CPU_INTERRUPT_HARD) &&
(env->psret != 0)) {
cpu_interrupts_enabled(env)) {
int pil = env->interrupt_index & 15;
int type = env->interrupt_index & 0xf0;
@ -486,7 +486,7 @@ int cpu_exec(CPUState *env1)
env->exception_index = env->interrupt_index;
do_interrupt(env);
env->interrupt_index = 0;
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
#if !defined(CONFIG_USER_ONLY)
cpu_check_irqs(env);
#endif
next_tb = 0;

View File

@ -115,15 +115,18 @@ enum {
#define TBR_BASE_MASK 0xfffff000
#if defined(TARGET_SPARC64)
#define PS_IG (1<<11)
#define PS_MG (1<<10)
#define PS_TCT (1<<12) /* UA2007, impl.dep. trap on control transfer */
#define PS_IG (1<<11) /* v9, zero on UA2007 */
#define PS_MG (1<<10) /* v9, zero on UA2007 */
#define PS_CLE (1<<9) /* UA2007 */
#define PS_TLE (1<<8) /* UA2007 */
#define PS_RMO (1<<7)
#define PS_RED (1<<5)
#define PS_PEF (1<<4)
#define PS_AM (1<<3)
#define PS_RED (1<<5) /* v9, zero on UA2007 */
#define PS_PEF (1<<4) /* enable fpu */
#define PS_AM (1<<3) /* address mask */
#define PS_PRIV (1<<2)
#define PS_IE (1<<1)
#define PS_AG (1<<0)
#define PS_AG (1<<0) /* v9, zero on UA2007 */
#define FPRS_FEF (1<<2)
@ -291,11 +294,15 @@ typedef struct CPUSPARCState {
float32 fpr[TARGET_FPREGS]; /* floating point registers */
uint32_t cwp; /* index of current register window (extracted
from PSR) */
#if !defined(TARGET_SPARC64) || defined(TARGET_ABI32)
uint32_t wim; /* window invalid mask */
#endif
target_ulong tbr; /* trap base register */
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 */
int psref; /* enable fpu */
@ -378,12 +385,21 @@ void gen_intermediate_code_init(CPUSPARCState *env);
/* cpu-exec.c */
int cpu_sparc_exec(CPUSPARCState *s);
#if !defined (TARGET_SPARC64)
#define GET_PSR(env) (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->psret? PSR_ET : 0) | env->cwp)
#else
#define GET_PSR(env) (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)
#endif
#ifndef NO_CPU_IO_DEFS
static inline void memcpy32(target_ulong *dst, const target_ulong *src)
@ -425,6 +441,7 @@ static inline int cpu_cwp_dec(CPUSPARCState *env1, int cwp)
}
#endif
#if !defined (TARGET_SPARC64)
#define PUT_PSR(env, val) do { int _tmp = val; \
env->psr = _tmp & PSR_ICC; \
env->psref = (_tmp & PSR_EF)? 1 : 0; \
@ -435,6 +452,17 @@ static inline int cpu_cwp_dec(CPUSPARCState *env1, int cwp)
cpu_set_cwp(env, _tmp & PSR_CWP); \
CC_OP = CC_OP_FLAGS; \
} while (0)
#else
#define PUT_PSR(env, val) do { int _tmp = val; \
env->psr = _tmp & PSR_ICC; \
env->psref = (_tmp & PSR_EF)? 1 : 0; \
env->psrpil = (_tmp & PSR_PIL) >> 8; \
env->psrs = (_tmp & PSR_S)? 1 : 0; \
env->psrps = (_tmp & PSR_PS)? 1 : 0; \
cpu_set_cwp(env, _tmp & PSR_CWP); \
CC_OP = CC_OP_FLAGS; \
} while (0)
#endif
#ifdef TARGET_SPARC64
#define GET_CCR(env) (((env->xcc >> 20) << 4) | ((env->psr & PSR_ICC) >> 20))

View File

@ -24,10 +24,23 @@ static inline void regs_to_env(void)
/* op_helper.c */
void do_interrupt(CPUState *env);
static inline int cpu_interrupts_enabled(CPUState *env1)
{
#if !defined (TARGET_SPARC64)
if (env1->psret != 0)
return 1;
#else
if (env1->pstate & PS_IE)
return 1;
#endif
return 0;
}
static inline int cpu_has_work(CPUState *env1)
{
return (env1->interrupt_request & CPU_INTERRUPT_HARD) &&
(env1->psret != 0);
cpu_interrupts_enabled(env1);
}

View File

@ -667,7 +667,9 @@ void cpu_reset(CPUSPARCState *env)
tlb_flush(env, 1);
env->cwp = 0;
#ifndef TARGET_SPARC64
env->wim = 1;
#endif
env->regwptr = env->regbase + (env->cwp * 16);
#if defined(CONFIG_USER_ONLY)
#ifdef TARGET_SPARC64
@ -677,7 +679,9 @@ void cpu_reset(CPUSPARCState *env)
env->asi = 0x82; // Primary no-fault
#endif
#else
#if !defined(TARGET_SPARC64)
env->psret = 0;
#endif
env->psrs = 1;
env->psrps = 1;
CC_OP = CC_OP_FLAGS;

View File

@ -3225,8 +3225,14 @@ static inline void change_pstate(uint64_t new_pstate)
uint64_t pstate_regs, new_pstate_regs;
uint64_t *src, *dst;
if (env->def->features & CPU_FEATURE_GL) {
// PS_AG is not implemented in this case
new_pstate &= ~PS_AG;
}
pstate_regs = env->pstate & 0xc01;
new_pstate_regs = new_pstate & 0xc01;
if (new_pstate_regs != pstate_regs) {
// Switch global register bank
src = get_gregset(new_pstate_regs);
@ -3239,8 +3245,7 @@ static inline void change_pstate(uint64_t new_pstate)
void helper_wrpstate(target_ulong new_state)
{
if (!(env->def->features & CPU_FEATURE_GL))
change_pstate(new_state & 0xf3f);
change_pstate(new_state & 0xf3f);
}
void helper_done(void)
@ -3392,23 +3397,23 @@ void do_interrupt(CPUState *env)
env->tsptr->tpc = env->pc;
env->tsptr->tnpc = env->npc;
env->tsptr->tt = intno;
if (!(env->def->features & CPU_FEATURE_GL)) {
switch (intno) {
case TT_IVEC:
change_pstate(PS_PEF | PS_PRIV | PS_IG);
break;
case TT_TFAULT:
case TT_TMISS:
case TT_DFAULT:
case TT_DMISS:
case TT_DPROT:
change_pstate(PS_PEF | PS_PRIV | PS_MG);
break;
default:
change_pstate(PS_PEF | PS_PRIV | PS_AG);
break;
}
switch (intno) {
case TT_IVEC:
change_pstate(PS_PEF | PS_PRIV | PS_IG);
break;
case TT_TFAULT:
case TT_TMISS:
case TT_DFAULT:
case TT_DMISS:
case TT_DPROT:
change_pstate(PS_PEF | PS_PRIV | PS_MG);
break;
default:
change_pstate(PS_PEF | PS_PRIV | PS_AG);
break;
}
if (intno == TT_CLRWIN)
cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
else if ((intno & 0x1c0) == TT_SPILL)