Commit 5210977a8511fc0c4a8a1a68c01fa3b65e29edc0

Authored by Igor Kovalenko
Committed by Blue Swirl
1 parent 49e66373

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
cpu-exec.c
... ... @@ -475,7 +475,7 @@ int cpu_exec(CPUState *env1)
475 475 }
476 476 #elif defined(TARGET_SPARC)
477 477 if ((interrupt_request & CPU_INTERRUPT_HARD) &&
478   - (env->psret != 0)) {
  478 + cpu_interrupts_enabled(env)) {
479 479 int pil = env->interrupt_index & 15;
480 480 int type = env->interrupt_index & 0xf0;
481 481  
... ... @@ -486,7 +486,7 @@ int cpu_exec(CPUState *env1)
486 486 env->exception_index = env->interrupt_index;
487 487 do_interrupt(env);
488 488 env->interrupt_index = 0;
489   -#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
  489 +#if !defined(CONFIG_USER_ONLY)
490 490 cpu_check_irqs(env);
491 491 #endif
492 492 next_tb = 0;
... ...
target-sparc/cpu.h
... ... @@ -115,15 +115,18 @@ enum {
115 115 #define TBR_BASE_MASK 0xfffff000
116 116  
117 117 #if defined(TARGET_SPARC64)
118   -#define PS_IG (1<<11)
119   -#define PS_MG (1<<10)
  118 +#define PS_TCT (1<<12) /* UA2007, impl.dep. trap on control transfer */
  119 +#define PS_IG (1<<11) /* v9, zero on UA2007 */
  120 +#define PS_MG (1<<10) /* v9, zero on UA2007 */
  121 +#define PS_CLE (1<<9) /* UA2007 */
  122 +#define PS_TLE (1<<8) /* UA2007 */
120 123 #define PS_RMO (1<<7)
121   -#define PS_RED (1<<5)
122   -#define PS_PEF (1<<4)
123   -#define PS_AM (1<<3)
  124 +#define PS_RED (1<<5) /* v9, zero on UA2007 */
  125 +#define PS_PEF (1<<4) /* enable fpu */
  126 +#define PS_AM (1<<3) /* address mask */
124 127 #define PS_PRIV (1<<2)
125 128 #define PS_IE (1<<1)
126   -#define PS_AG (1<<0)
  129 +#define PS_AG (1<<0) /* v9, zero on UA2007 */
127 130  
128 131 #define FPRS_FEF (1<<2)
129 132  
... ... @@ -291,11 +294,15 @@ typedef struct CPUSPARCState {
291 294 float32 fpr[TARGET_FPREGS]; /* floating point registers */
292 295 uint32_t cwp; /* index of current register window (extracted
293 296 from PSR) */
  297 +#if !defined(TARGET_SPARC64) || defined(TARGET_ABI32)
294 298 uint32_t wim; /* window invalid mask */
  299 +#endif
295 300 target_ulong tbr; /* trap base register */
296 301 int psrs; /* supervisor mode (extracted from PSR) */
297 302 int psrps; /* previous supervisor mode */
  303 +#if !defined(TARGET_SPARC64)
298 304 int psret; /* enable traps */
  305 +#endif
299 306 uint32_t psrpil; /* interrupt blocking level */
300 307 uint32_t pil_in; /* incoming interrupt level bitmap */
301 308 int psref; /* enable fpu */
... ... @@ -378,12 +385,21 @@ void gen_intermediate_code_init(CPUSPARCState *env);
378 385 /* cpu-exec.c */
379 386 int cpu_sparc_exec(CPUSPARCState *s);
380 387  
  388 +#if !defined (TARGET_SPARC64)
381 389 #define GET_PSR(env) (env->version | (env->psr & PSR_ICC) | \
382 390 (env->psref? PSR_EF : 0) | \
383 391 (env->psrpil << 8) | \
384 392 (env->psrs? PSR_S : 0) | \
385 393 (env->psrps? PSR_PS : 0) | \
386 394 (env->psret? PSR_ET : 0) | env->cwp)
  395 +#else
  396 +#define GET_PSR(env) (env->version | (env->psr & PSR_ICC) | \
  397 + (env->psref? PSR_EF : 0) | \
  398 + (env->psrpil << 8) | \
  399 + (env->psrs? PSR_S : 0) | \
  400 + (env->psrps? PSR_PS : 0) | \
  401 + env->cwp)
  402 +#endif
387 403  
388 404 #ifndef NO_CPU_IO_DEFS
389 405 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)
425 441 }
426 442 #endif
427 443  
  444 +#if !defined (TARGET_SPARC64)
428 445 #define PUT_PSR(env, val) do { int _tmp = val; \
429 446 env->psr = _tmp & PSR_ICC; \
430 447 env->psref = (_tmp & PSR_EF)? 1 : 0; \
... ... @@ -435,6 +452,17 @@ static inline int cpu_cwp_dec(CPUSPARCState *env1, int cwp)
435 452 cpu_set_cwp(env, _tmp & PSR_CWP); \
436 453 CC_OP = CC_OP_FLAGS; \
437 454 } while (0)
  455 +#else
  456 +#define PUT_PSR(env, val) do { int _tmp = val; \
  457 + env->psr = _tmp & PSR_ICC; \
  458 + env->psref = (_tmp & PSR_EF)? 1 : 0; \
  459 + env->psrpil = (_tmp & PSR_PIL) >> 8; \
  460 + env->psrs = (_tmp & PSR_S)? 1 : 0; \
  461 + env->psrps = (_tmp & PSR_PS)? 1 : 0; \
  462 + cpu_set_cwp(env, _tmp & PSR_CWP); \
  463 + CC_OP = CC_OP_FLAGS; \
  464 + } while (0)
  465 +#endif
438 466  
439 467 #ifdef TARGET_SPARC64
440 468 #define GET_CCR(env) (((env->xcc >> 20) << 4) | ((env->psr & PSR_ICC) >> 20))
... ...
target-sparc/exec.h
... ... @@ -24,10 +24,23 @@ static inline void regs_to_env(void)
24 24 /* op_helper.c */
25 25 void do_interrupt(CPUState *env);
26 26  
  27 +static inline int cpu_interrupts_enabled(CPUState *env1)
  28 +{
  29 +#if !defined (TARGET_SPARC64)
  30 + if (env1->psret != 0)
  31 + return 1;
  32 +#else
  33 + if (env1->pstate & PS_IE)
  34 + return 1;
  35 +#endif
  36 +
  37 + return 0;
  38 +}
  39 +
27 40 static inline int cpu_has_work(CPUState *env1)
28 41 {
29 42 return (env1->interrupt_request & CPU_INTERRUPT_HARD) &&
30   - (env1->psret != 0);
  43 + cpu_interrupts_enabled(env1);
31 44 }
32 45  
33 46  
... ...
target-sparc/helper.c
... ... @@ -667,7 +667,9 @@ void cpu_reset(CPUSPARCState *env)
667 667  
668 668 tlb_flush(env, 1);
669 669 env->cwp = 0;
  670 +#ifndef TARGET_SPARC64
670 671 env->wim = 1;
  672 +#endif
671 673 env->regwptr = env->regbase + (env->cwp * 16);
672 674 #if defined(CONFIG_USER_ONLY)
673 675 #ifdef TARGET_SPARC64
... ... @@ -677,7 +679,9 @@ void cpu_reset(CPUSPARCState *env)
677 679 env->asi = 0x82; // Primary no-fault
678 680 #endif
679 681 #else
  682 +#if !defined(TARGET_SPARC64)
680 683 env->psret = 0;
  684 +#endif
681 685 env->psrs = 1;
682 686 env->psrps = 1;
683 687 CC_OP = CC_OP_FLAGS;
... ...
target-sparc/op_helper.c
... ... @@ -3225,8 +3225,14 @@ static inline void change_pstate(uint64_t new_pstate)
3225 3225 uint64_t pstate_regs, new_pstate_regs;
3226 3226 uint64_t *src, *dst;
3227 3227  
  3228 + if (env->def->features & CPU_FEATURE_GL) {
  3229 + // PS_AG is not implemented in this case
  3230 + new_pstate &= ~PS_AG;
  3231 + }
  3232 +
3228 3233 pstate_regs = env->pstate & 0xc01;
3229 3234 new_pstate_regs = new_pstate & 0xc01;
  3235 +
3230 3236 if (new_pstate_regs != pstate_regs) {
3231 3237 // Switch global register bank
3232 3238 src = get_gregset(new_pstate_regs);
... ... @@ -3239,8 +3245,7 @@ static inline void change_pstate(uint64_t new_pstate)
3239 3245  
3240 3246 void helper_wrpstate(target_ulong new_state)
3241 3247 {
3242   - if (!(env->def->features & CPU_FEATURE_GL))
3243   - change_pstate(new_state & 0xf3f);
  3248 + change_pstate(new_state & 0xf3f);
3244 3249 }
3245 3250  
3246 3251 void helper_done(void)
... ... @@ -3392,23 +3397,23 @@ void do_interrupt(CPUState *env)
3392 3397 env->tsptr->tpc = env->pc;
3393 3398 env->tsptr->tnpc = env->npc;
3394 3399 env->tsptr->tt = intno;
3395   - if (!(env->def->features & CPU_FEATURE_GL)) {
3396   - switch (intno) {
3397   - case TT_IVEC:
3398   - change_pstate(PS_PEF | PS_PRIV | PS_IG);
3399   - break;
3400   - case TT_TFAULT:
3401   - case TT_TMISS:
3402   - case TT_DFAULT:
3403   - case TT_DMISS:
3404   - case TT_DPROT:
3405   - change_pstate(PS_PEF | PS_PRIV | PS_MG);
3406   - break;
3407   - default:
3408   - change_pstate(PS_PEF | PS_PRIV | PS_AG);
3409   - break;
3410   - }
  3400 +
  3401 + switch (intno) {
  3402 + case TT_IVEC:
  3403 + change_pstate(PS_PEF | PS_PRIV | PS_IG);
  3404 + break;
  3405 + case TT_TFAULT:
  3406 + case TT_TMISS:
  3407 + case TT_DFAULT:
  3408 + case TT_DMISS:
  3409 + case TT_DPROT:
  3410 + change_pstate(PS_PEF | PS_PRIV | PS_MG);
  3411 + break;
  3412 + default:
  3413 + change_pstate(PS_PEF | PS_PRIV | PS_AG);
  3414 + break;
3411 3415 }
  3416 +
3412 3417 if (intno == TT_CLRWIN)
3413 3418 cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
3414 3419 else if ((intno & 0x1c0) == TT_SPILL)
... ...