From: Igor Kovalenko <igor.v.kovalenko@gmail.com>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH] sparc64: trap handling corrections
Date: Sun, 12 Jul 2009 03:03:30 +0400 [thread overview]
Message-ID: <b2fa41d60907111603h666deedchdd709c705d4f688a@mail.gmail.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 658 bytes --]
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.
Timer interrupt would require attention later when timers
start to tick (currently timers are not really functional).
Signed-off-by: igor.v.kovalenko@gmail.com
--
Kind regards,
Igor V. Kovalenko
[-- Attachment #2: sparc64-trap --]
[-- Type: application/octet-stream, Size: 8840 bytes --]
Index: qemu-trunk/target-sparc/cpu.h
===================================================================
--- qemu-trunk.orig/target-sparc/cpu.h
+++ qemu-trunk/target-sparc/cpu.h
@@ -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 */
@@ -348,6 +355,8 @@ typedef struct CPUSPARCState {
uint64_t fprs;
uint64_t tick_cmpr, stick_cmpr;
void *tick, *stick;
+#define TICK_NPT_MASK 0x8000000000000000ULL
+#define TICK_SOFTINT_DISABLE 0x8000000000000000ULL
uint64_t gsr;
uint32_t gl; // UA2005
/* UA 2005 hyperprivileged registers */
@@ -356,6 +365,10 @@ typedef struct CPUSPARCState {
uint32_t softint;
#define SOFTINT_TIMER 1
#define SOFTINT_STIMER (1 << 16)
+#define SOFTINT_INTRMASK (0xFFFE)
+#define SOFTINT_TM (1 << 0)
+#define SOFTINT_SM (1 << 16)
+#define SOFTINT_REG_MASK (SOFTINT_SM|SOFTINT_INTRMASK|SOFTINT_TM)
#endif
sparc_def_t *def;
} CPUSPARCState;
@@ -378,12 +391,21 @@ void gen_intermediate_code_init(CPUSPARC
/* 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 +447,7 @@ static inline int cpu_cwp_dec(CPUSPARCSt
}
#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 +458,16 @@ static inline int cpu_cwp_dec(CPUSPARCSt
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); \
+ } while (0)
+#endif
#ifdef TARGET_SPARC64
#define GET_CCR(env) (((env->xcc >> 20) << 4) | ((env->psr & PSR_ICC) >> 20))
Index: qemu-trunk/target-sparc/exec.h
===================================================================
--- qemu-trunk.orig/target-sparc/exec.h
+++ qemu-trunk/target-sparc/exec.h
@@ -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);
}
Index: qemu-trunk/target-sparc/helper.c
===================================================================
--- qemu-trunk.orig/target-sparc/helper.c
+++ qemu-trunk/target-sparc/helper.c
@@ -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;
Index: qemu-trunk/target-sparc/op_helper.c
===================================================================
--- qemu-trunk.orig/target-sparc/op_helper.c
+++ qemu-trunk/target-sparc/op_helper.c
@@ -3225,8 +3225,14 @@ static inline void change_pstate(uint64_
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_
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,7 +3397,8 @@ 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)) {
+ //if (!(env->def->features & CPU_FEATURE_GL))
+ {
switch (intno) {
case TT_IVEC:
change_pstate(PS_PEF | PS_PRIV | PS_IG);
Index: qemu-trunk/cpu-exec.c
===================================================================
--- qemu-trunk.orig/cpu-exec.c
+++ qemu-trunk/cpu-exec.c
@@ -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,14 +486,19 @@ 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(TARGET_SPARC64) &&*/ !defined(CONFIG_USER_ONLY)
cpu_check_irqs(env);
#endif
next_tb = 0;
}
} else if (interrupt_request & CPU_INTERRUPT_TIMER) {
- //do_interrupt(0, 0, 0, 0, 0);
env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
+#if !defined(CONFIG_USER_ONLY)
+ cpu_check_irqs(env);
+#endif
+ env->exception_index = env->interrupt_index;
+ do_interrupt(env);
+ next_tb = 0;
}
#elif defined(TARGET_ARM)
if (interrupt_request & CPU_INTERRUPT_FIQ
next reply other threads:[~2009-07-11 23:03 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-07-11 23:03 Igor Kovalenko [this message]
2009-07-12 8:09 ` [Qemu-devel] [PATCH] sparc64: trap handling corrections Blue Swirl
2009-07-12 8:35 ` Igor Kovalenko
2009-07-12 8:53 ` Blue Swirl
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=b2fa41d60907111603h666deedchdd709c705d4f688a@mail.gmail.com \
--to=igor.v.kovalenko@gmail.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).