Commit 5210977a8511fc0c4a8a1a68c01fa3b65e29edc0
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
Showing
5 changed files
with
77 additions
and
27 deletions
cpu-exec.c
| @@ -475,7 +475,7 @@ int cpu_exec(CPUState *env1) | @@ -475,7 +475,7 @@ int cpu_exec(CPUState *env1) | ||
| 475 | } | 475 | } |
| 476 | #elif defined(TARGET_SPARC) | 476 | #elif defined(TARGET_SPARC) |
| 477 | if ((interrupt_request & CPU_INTERRUPT_HARD) && | 477 | if ((interrupt_request & CPU_INTERRUPT_HARD) && |
| 478 | - (env->psret != 0)) { | 478 | + cpu_interrupts_enabled(env)) { |
| 479 | int pil = env->interrupt_index & 15; | 479 | int pil = env->interrupt_index & 15; |
| 480 | int type = env->interrupt_index & 0xf0; | 480 | int type = env->interrupt_index & 0xf0; |
| 481 | 481 | ||
| @@ -486,7 +486,7 @@ int cpu_exec(CPUState *env1) | @@ -486,7 +486,7 @@ int cpu_exec(CPUState *env1) | ||
| 486 | env->exception_index = env->interrupt_index; | 486 | env->exception_index = env->interrupt_index; |
| 487 | do_interrupt(env); | 487 | do_interrupt(env); |
| 488 | env->interrupt_index = 0; | 488 | env->interrupt_index = 0; |
| 489 | -#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) | 489 | +#if !defined(CONFIG_USER_ONLY) |
| 490 | cpu_check_irqs(env); | 490 | cpu_check_irqs(env); |
| 491 | #endif | 491 | #endif |
| 492 | next_tb = 0; | 492 | next_tb = 0; |
target-sparc/cpu.h
| @@ -115,15 +115,18 @@ enum { | @@ -115,15 +115,18 @@ enum { | ||
| 115 | #define TBR_BASE_MASK 0xfffff000 | 115 | #define TBR_BASE_MASK 0xfffff000 |
| 116 | 116 | ||
| 117 | #if defined(TARGET_SPARC64) | 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 | #define PS_RMO (1<<7) | 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 | #define PS_PRIV (1<<2) | 127 | #define PS_PRIV (1<<2) |
| 125 | #define PS_IE (1<<1) | 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 | #define FPRS_FEF (1<<2) | 131 | #define FPRS_FEF (1<<2) |
| 129 | 132 | ||
| @@ -291,11 +294,15 @@ typedef struct CPUSPARCState { | @@ -291,11 +294,15 @@ typedef struct CPUSPARCState { | ||
| 291 | float32 fpr[TARGET_FPREGS]; /* floating point registers */ | 294 | float32 fpr[TARGET_FPREGS]; /* floating point registers */ |
| 292 | uint32_t cwp; /* index of current register window (extracted | 295 | uint32_t cwp; /* index of current register window (extracted |
| 293 | from PSR) */ | 296 | from PSR) */ |
| 297 | +#if !defined(TARGET_SPARC64) || defined(TARGET_ABI32) | ||
| 294 | uint32_t wim; /* window invalid mask */ | 298 | uint32_t wim; /* window invalid mask */ |
| 299 | +#endif | ||
| 295 | target_ulong tbr; /* trap base register */ | 300 | target_ulong tbr; /* trap base register */ |
| 296 | int psrs; /* supervisor mode (extracted from PSR) */ | 301 | int psrs; /* supervisor mode (extracted from PSR) */ |
| 297 | int psrps; /* previous supervisor mode */ | 302 | int psrps; /* previous supervisor mode */ |
| 303 | +#if !defined(TARGET_SPARC64) | ||
| 298 | int psret; /* enable traps */ | 304 | int psret; /* enable traps */ |
| 305 | +#endif | ||
| 299 | uint32_t psrpil; /* interrupt blocking level */ | 306 | uint32_t psrpil; /* interrupt blocking level */ |
| 300 | uint32_t pil_in; /* incoming interrupt level bitmap */ | 307 | uint32_t pil_in; /* incoming interrupt level bitmap */ |
| 301 | int psref; /* enable fpu */ | 308 | int psref; /* enable fpu */ |
| @@ -378,12 +385,21 @@ void gen_intermediate_code_init(CPUSPARCState *env); | @@ -378,12 +385,21 @@ void gen_intermediate_code_init(CPUSPARCState *env); | ||
| 378 | /* cpu-exec.c */ | 385 | /* cpu-exec.c */ |
| 379 | int cpu_sparc_exec(CPUSPARCState *s); | 386 | int cpu_sparc_exec(CPUSPARCState *s); |
| 380 | 387 | ||
| 388 | +#if !defined (TARGET_SPARC64) | ||
| 381 | #define GET_PSR(env) (env->version | (env->psr & PSR_ICC) | \ | 389 | #define GET_PSR(env) (env->version | (env->psr & PSR_ICC) | \ |
| 382 | (env->psref? PSR_EF : 0) | \ | 390 | (env->psref? PSR_EF : 0) | \ |
| 383 | (env->psrpil << 8) | \ | 391 | (env->psrpil << 8) | \ |
| 384 | (env->psrs? PSR_S : 0) | \ | 392 | (env->psrs? PSR_S : 0) | \ |
| 385 | (env->psrps? PSR_PS : 0) | \ | 393 | (env->psrps? PSR_PS : 0) | \ |
| 386 | (env->psret? PSR_ET : 0) | env->cwp) | 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 | #ifndef NO_CPU_IO_DEFS | 404 | #ifndef NO_CPU_IO_DEFS |
| 389 | static inline void memcpy32(target_ulong *dst, const target_ulong *src) | 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,6 +441,7 @@ static inline int cpu_cwp_dec(CPUSPARCState *env1, int cwp) | ||
| 425 | } | 441 | } |
| 426 | #endif | 442 | #endif |
| 427 | 443 | ||
| 444 | +#if !defined (TARGET_SPARC64) | ||
| 428 | #define PUT_PSR(env, val) do { int _tmp = val; \ | 445 | #define PUT_PSR(env, val) do { int _tmp = val; \ |
| 429 | env->psr = _tmp & PSR_ICC; \ | 446 | env->psr = _tmp & PSR_ICC; \ |
| 430 | env->psref = (_tmp & PSR_EF)? 1 : 0; \ | 447 | env->psref = (_tmp & PSR_EF)? 1 : 0; \ |
| @@ -435,6 +452,17 @@ static inline int cpu_cwp_dec(CPUSPARCState *env1, int cwp) | @@ -435,6 +452,17 @@ static inline int cpu_cwp_dec(CPUSPARCState *env1, int cwp) | ||
| 435 | cpu_set_cwp(env, _tmp & PSR_CWP); \ | 452 | cpu_set_cwp(env, _tmp & PSR_CWP); \ |
| 436 | CC_OP = CC_OP_FLAGS; \ | 453 | CC_OP = CC_OP_FLAGS; \ |
| 437 | } while (0) | 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 | #ifdef TARGET_SPARC64 | 467 | #ifdef TARGET_SPARC64 |
| 440 | #define GET_CCR(env) (((env->xcc >> 20) << 4) | ((env->psr & PSR_ICC) >> 20)) | 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,10 +24,23 @@ static inline void regs_to_env(void) | ||
| 24 | /* op_helper.c */ | 24 | /* op_helper.c */ |
| 25 | void do_interrupt(CPUState *env); | 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 | static inline int cpu_has_work(CPUState *env1) | 40 | static inline int cpu_has_work(CPUState *env1) |
| 28 | { | 41 | { |
| 29 | return (env1->interrupt_request & CPU_INTERRUPT_HARD) && | 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,7 +667,9 @@ void cpu_reset(CPUSPARCState *env) | ||
| 667 | 667 | ||
| 668 | tlb_flush(env, 1); | 668 | tlb_flush(env, 1); |
| 669 | env->cwp = 0; | 669 | env->cwp = 0; |
| 670 | +#ifndef TARGET_SPARC64 | ||
| 670 | env->wim = 1; | 671 | env->wim = 1; |
| 672 | +#endif | ||
| 671 | env->regwptr = env->regbase + (env->cwp * 16); | 673 | env->regwptr = env->regbase + (env->cwp * 16); |
| 672 | #if defined(CONFIG_USER_ONLY) | 674 | #if defined(CONFIG_USER_ONLY) |
| 673 | #ifdef TARGET_SPARC64 | 675 | #ifdef TARGET_SPARC64 |
| @@ -677,7 +679,9 @@ void cpu_reset(CPUSPARCState *env) | @@ -677,7 +679,9 @@ void cpu_reset(CPUSPARCState *env) | ||
| 677 | env->asi = 0x82; // Primary no-fault | 679 | env->asi = 0x82; // Primary no-fault |
| 678 | #endif | 680 | #endif |
| 679 | #else | 681 | #else |
| 682 | +#if !defined(TARGET_SPARC64) | ||
| 680 | env->psret = 0; | 683 | env->psret = 0; |
| 684 | +#endif | ||
| 681 | env->psrs = 1; | 685 | env->psrs = 1; |
| 682 | env->psrps = 1; | 686 | env->psrps = 1; |
| 683 | CC_OP = CC_OP_FLAGS; | 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,8 +3225,14 @@ static inline void change_pstate(uint64_t new_pstate) | ||
| 3225 | uint64_t pstate_regs, new_pstate_regs; | 3225 | uint64_t pstate_regs, new_pstate_regs; |
| 3226 | uint64_t *src, *dst; | 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 | pstate_regs = env->pstate & 0xc01; | 3233 | pstate_regs = env->pstate & 0xc01; |
| 3229 | new_pstate_regs = new_pstate & 0xc01; | 3234 | new_pstate_regs = new_pstate & 0xc01; |
| 3235 | + | ||
| 3230 | if (new_pstate_regs != pstate_regs) { | 3236 | if (new_pstate_regs != pstate_regs) { |
| 3231 | // Switch global register bank | 3237 | // Switch global register bank |
| 3232 | src = get_gregset(new_pstate_regs); | 3238 | src = get_gregset(new_pstate_regs); |
| @@ -3239,8 +3245,7 @@ static inline void change_pstate(uint64_t new_pstate) | @@ -3239,8 +3245,7 @@ static inline void change_pstate(uint64_t new_pstate) | ||
| 3239 | 3245 | ||
| 3240 | void helper_wrpstate(target_ulong new_state) | 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 | void helper_done(void) | 3251 | void helper_done(void) |
| @@ -3392,23 +3397,23 @@ void do_interrupt(CPUState *env) | @@ -3392,23 +3397,23 @@ void do_interrupt(CPUState *env) | ||
| 3392 | env->tsptr->tpc = env->pc; | 3397 | env->tsptr->tpc = env->pc; |
| 3393 | env->tsptr->tnpc = env->npc; | 3398 | env->tsptr->tnpc = env->npc; |
| 3394 | env->tsptr->tt = intno; | 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 | if (intno == TT_CLRWIN) | 3417 | if (intno == TT_CLRWIN) |
| 3413 | cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1)); | 3418 | cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1)); |
| 3414 | else if ((intno & 0x1c0) == TT_SPILL) | 3419 | else if ((intno & 0x1c0) == TT_SPILL) |