* [Qemu-devel] [PATCH 0/9] sparc64: interrupts and tick timers v1
@ 2010-01-07 20:27 Igor V. Kovalenko
2010-01-07 20:27 ` [Qemu-devel] [PATCH 1/9] sparc64: change_pstate should have 32bit argument Igor V. Kovalenko
` (9 more replies)
0 siblings, 10 replies; 11+ messages in thread
From: Igor V. Kovalenko @ 2010-01-07 20:27 UTC (permalink / raw)
To: qemu-devel
The following series is a cleanup over previous one.
v0 -> v1: post-review changes
- dropped patch "clear exception_index with -1 val" (applied)
- new patch "change_pstate should have 32bit argument"
- cleanups for coding style and hexadecimal output convention
- wrpil is no-op for CONFIG_USER_ONLY
- restored PIL 15 as non-maskable interrupt level on sparcv8
- check for PSTATE.IE is replaced with call to cpu_interrupts_enabled()
- in patch "sparc64: interrupt trap handling"
cleaned up change in cpu_exec; since sparc64 does not use
CPU_INTERRUPT_TIMER now, corresponding code branch is unchanged
---
Igor V. Kovalenko (9):
sparc64: change_pstate should have 32bit argument
sparc64: trace pstate and global register set changes
sparc64: add PIL to cpu state dump
sparc64: use helper_wrpil to check pending irq on write
sparc64: check for pending irq when pil, pstate or softint is changed
sparc64: add macros to deal with softint and timer interrupt
sparc64: move cpu_interrupts_enabled to cpu.h
sparc64: interrupt trap handling
sparc64: reimplement tick timers
cpu-exec.c | 28 +++---
hw/sun4u.c | 225 +++++++++++++++++++++++++++++++++++++---------
target-sparc/cpu.h | 27 ++++++
target-sparc/exec.h | 13 ---
target-sparc/helper.c | 1
target-sparc/helper.h | 1
target-sparc/op_helper.c | 81 +++++++++++++++--
target-sparc/translate.c | 5 -
8 files changed, 300 insertions(+), 81 deletions(-)
--
Kind regards,
Igor V. Kovalenko
^ permalink raw reply [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH 1/9] sparc64: change_pstate should have 32bit argument
2010-01-07 20:27 [Qemu-devel] [PATCH 0/9] sparc64: interrupts and tick timers v1 Igor V. Kovalenko
@ 2010-01-07 20:27 ` Igor V. Kovalenko
2010-01-07 20:28 ` [Qemu-devel] [PATCH 2/9] sparc64: trace pstate and global register set changes Igor V. Kovalenko
` (8 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Igor V. Kovalenko @ 2010-01-07 20:27 UTC (permalink / raw)
To: qemu-devel
From: Igor V. Kovalenko <igor.v.kovalenko@gmail.com>
- pstate is 32bit variable, no need to pass 64bit value around
Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko@gmail.com>
---
target-sparc/op_helper.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index c63de07..fd3286d 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -3240,7 +3240,7 @@ target_ulong helper_popc(target_ulong val)
return ctpop64(val);
}
-static inline uint64_t *get_gregset(uint64_t pstate)
+static inline uint64_t *get_gregset(uint32_t pstate)
{
switch (pstate) {
default:
@@ -3255,9 +3255,9 @@ static inline uint64_t *get_gregset(uint64_t pstate)
}
}
-static inline void change_pstate(uint64_t new_pstate)
+static inline void change_pstate(uint32_t new_pstate)
{
- uint64_t pstate_regs, new_pstate_regs;
+ uint32_t pstate_regs, new_pstate_regs;
uint64_t *src, *dst;
if (env->def->features & CPU_FEATURE_GL) {
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH 2/9] sparc64: trace pstate and global register set changes
2010-01-07 20:27 [Qemu-devel] [PATCH 0/9] sparc64: interrupts and tick timers v1 Igor V. Kovalenko
2010-01-07 20:27 ` [Qemu-devel] [PATCH 1/9] sparc64: change_pstate should have 32bit argument Igor V. Kovalenko
@ 2010-01-07 20:28 ` Igor V. Kovalenko
2010-01-07 20:28 ` [Qemu-devel] [PATCH 3/9] sparc64: add PIL to cpu state dump Igor V. Kovalenko
` (7 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Igor V. Kovalenko @ 2010-01-07 20:28 UTC (permalink / raw)
To: qemu-devel
From: Igor V. Kovalenko <igor.v.kovalenko@gmail.com>
Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko@gmail.com>
---
target-sparc/op_helper.c | 20 ++++++++++++++++++++
1 files changed, 20 insertions(+), 0 deletions(-)
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index fd3286d..1d3adef 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -11,6 +11,7 @@
//#define DEBUG_UNASSIGNED
//#define DEBUG_ASI
//#define DEBUG_PCALL
+//#define DEBUG_PSTATE
#ifdef DEBUG_MMU
#define DPRINTF_MMU(fmt, ...) \
@@ -31,6 +32,13 @@
do { printf("ASI: " fmt , ## __VA_ARGS__); } while (0)
#endif
+#ifdef DEBUG_PSTATE
+#define DPRINTF_PSTATE(fmt, ...) \
+ do { printf("PSTATE: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF_PSTATE(fmt, ...) do {} while (0)
+#endif
+
#ifdef TARGET_SPARC64
#ifndef TARGET_ABI32
#define AM_CHECK(env1) ((env1)->pstate & PS_AM)
@@ -3244,6 +3252,12 @@ static inline uint64_t *get_gregset(uint32_t pstate)
{
switch (pstate) {
default:
+ DPRINTF_PSTATE("ERROR in get_gregset: active pstate bits=%x%s%s%s\n",
+ pstate,
+ (pstate & PS_IG) ? " IG" : "",
+ (pstate & PS_MG) ? " MG" : "",
+ (pstate & PS_AG) ? " AG" : "");
+ /* pass through to normal set of global registers */
case 0:
return env->bgregs;
case PS_AG:
@@ -3269,12 +3283,18 @@ static inline void change_pstate(uint32_t new_pstate)
new_pstate_regs = new_pstate & 0xc01;
if (new_pstate_regs != pstate_regs) {
+ DPRINTF_PSTATE("change_pstate: switching regs old=%x new=%x\n",
+ pstate_regs, new_pstate_regs);
// Switch global register bank
src = get_gregset(new_pstate_regs);
dst = get_gregset(pstate_regs);
memcpy32(dst, env->gregs);
memcpy32(env->gregs, src);
}
+ else {
+ DPRINTF_PSTATE("change_pstate: regs new=%x (unchanged)\n",
+ new_pstate_regs);
+ }
env->pstate = new_pstate;
}
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH 3/9] sparc64: add PIL to cpu state dump
2010-01-07 20:27 [Qemu-devel] [PATCH 0/9] sparc64: interrupts and tick timers v1 Igor V. Kovalenko
2010-01-07 20:27 ` [Qemu-devel] [PATCH 1/9] sparc64: change_pstate should have 32bit argument Igor V. Kovalenko
2010-01-07 20:28 ` [Qemu-devel] [PATCH 2/9] sparc64: trace pstate and global register set changes Igor V. Kovalenko
@ 2010-01-07 20:28 ` Igor V. Kovalenko
2010-01-07 20:28 ` [Qemu-devel] [PATCH 4/9] sparc64: use helper_wrpil to check pending irq on write Igor V. Kovalenko
` (6 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Igor V. Kovalenko @ 2010-01-07 20:28 UTC (permalink / raw)
To: qemu-devel
From: Igor V. Kovalenko <igor.v.kovalenko@gmail.com>
Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko@gmail.com>
---
target-sparc/helper.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index a06923a..e801474 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -1452,6 +1452,7 @@ void cpu_dump_state(CPUState *env, FILE *f,
#ifdef TARGET_SPARC64
cpu_fprintf(f, "pstate: 0x%08x ccr: 0x%02x asi: 0x%02x tl: %d fprs: %d\n",
env->pstate, GET_CCR(env), env->asi, env->tl, env->fprs);
+ cpu_fprintf(f, "pil=%x\n", env->psrpil);
cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate %d "
"cleanwin %d cwp %d\n",
env->cansave, env->canrestore, env->otherwin, env->wstate,
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH 4/9] sparc64: use helper_wrpil to check pending irq on write
2010-01-07 20:27 [Qemu-devel] [PATCH 0/9] sparc64: interrupts and tick timers v1 Igor V. Kovalenko
` (2 preceding siblings ...)
2010-01-07 20:28 ` [Qemu-devel] [PATCH 3/9] sparc64: add PIL to cpu state dump Igor V. Kovalenko
@ 2010-01-07 20:28 ` Igor V. Kovalenko
2010-01-07 20:28 ` [Qemu-devel] [PATCH 5/9] sparc64: check for pending irq when pil, pstate or softint is changed Igor V. Kovalenko
` (5 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Igor V. Kovalenko @ 2010-01-07 20:28 UTC (permalink / raw)
To: qemu-devel
From: Igor V. Kovalenko <igor.v.kovalenko@gmail.com>
Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko@gmail.com>
---
target-sparc/helper.h | 1 +
target-sparc/op_helper.c | 14 ++++++++++++++
target-sparc/translate.c | 5 +----
3 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index 4002b9e..6f103e7 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -5,6 +5,7 @@ DEF_HELPER_0(rett, void)
DEF_HELPER_1(wrpsr, void, tl)
DEF_HELPER_0(rdpsr, tl)
#else
+DEF_HELPER_1(wrpil, void, tl)
DEF_HELPER_1(wrpstate, void, tl)
DEF_HELPER_0(done, void)
DEF_HELPER_0(retry, void)
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 1d3adef..3d7f64c 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -3303,6 +3303,20 @@ void helper_wrpstate(target_ulong new_state)
change_pstate(new_state & 0xf3f);
}
+void helper_wrpil(target_ulong new_pil)
+{
+#if !defined(CONFIG_USER_ONLY)
+ DPRINTF_PSTATE("helper_wrpil old=%x new=%x\n",
+ env->psrpil, (uint32_t)new_pil);
+
+ env->psrpil = new_pil;
+
+ if (cpu_interrupts_enabled(env)) {
+ cpu_check_irqs(env);
+ }
+#endif
+}
+
void helper_done(void)
{
trap_state* tsptr = cpu_tsptr(env);
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index bf6df50..7e9f0cf 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -3371,10 +3371,7 @@ static void disas_sparc_insn(DisasContext * dc)
offsetof(CPUSPARCState, tl));
break;
case 8: // pil
- tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
- tcg_gen_st_i32(cpu_tmp32, cpu_env,
- offsetof(CPUSPARCState,
- psrpil));
+ gen_helper_wrpil(cpu_tmp0);
break;
case 9: // cwp
gen_helper_wrcwp(cpu_tmp0);
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH 5/9] sparc64: check for pending irq when pil, pstate or softint is changed
2010-01-07 20:27 [Qemu-devel] [PATCH 0/9] sparc64: interrupts and tick timers v1 Igor V. Kovalenko
` (3 preceding siblings ...)
2010-01-07 20:28 ` [Qemu-devel] [PATCH 4/9] sparc64: use helper_wrpil to check pending irq on write Igor V. Kovalenko
@ 2010-01-07 20:28 ` Igor V. Kovalenko
2010-01-07 20:28 ` [Qemu-devel] [PATCH 6/9] sparc64: add macros to deal with softint and timer interrupt Igor V. Kovalenko
` (4 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Igor V. Kovalenko @ 2010-01-07 20:28 UTC (permalink / raw)
To: qemu-devel
From: Igor V. Kovalenko <igor.v.kovalenko@gmail.com>
Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko@gmail.com>
---
target-sparc/op_helper.c | 41 ++++++++++++++++++++++++++++++++++++++---
1 files changed, 38 insertions(+), 3 deletions(-)
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 3d7f64c..381e6c4 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -3301,6 +3301,12 @@ static inline void change_pstate(uint32_t new_pstate)
void helper_wrpstate(target_ulong new_state)
{
change_pstate(new_state & 0xf3f);
+
+#if !defined(CONFIG_USER_ONLY)
+ if (cpu_interrupts_enabled(env)) {
+ cpu_check_irqs(env);
+ }
+#endif
}
void helper_wrpil(target_ulong new_pil)
@@ -3328,6 +3334,14 @@ void helper_done(void)
change_pstate((tsptr->tstate >> 8) & 0xf3f);
PUT_CWP64(env, tsptr->tstate & 0xff);
env->tl--;
+
+ DPRINTF_PSTATE("... helper_done tl=%d\n", env->tl);
+
+#if !defined(CONFIG_USER_ONLY)
+ if (cpu_interrupts_enabled(env)) {
+ cpu_check_irqs(env);
+ }
+#endif
}
void helper_retry(void)
@@ -3341,21 +3355,42 @@ void helper_retry(void)
change_pstate((tsptr->tstate >> 8) & 0xf3f);
PUT_CWP64(env, tsptr->tstate & 0xff);
env->tl--;
+
+ DPRINTF_PSTATE("... helper_retry tl=%d\n", env->tl);
+
+#if !defined(CONFIG_USER_ONLY)
+ if (cpu_interrupts_enabled(env)) {
+ cpu_check_irqs(env);
+ }
+#endif
+}
+
+static void do_modify_softint(const char* operation, uint32_t value)
+{
+ if (env->softint != value) {
+ env->softint = value;
+ DPRINTF_PSTATE(": %s new %08x\n", operation, env->softint);
+#if !defined(CONFIG_USER_ONLY)
+ if (cpu_interrupts_enabled(env)) {
+ cpu_check_irqs(env);
+ }
+#endif
+ }
}
void helper_set_softint(uint64_t value)
{
- env->softint |= (uint32_t)value;
+ do_modify_softint("helper_set_softint", env->softint | (uint32_t)value);
}
void helper_clear_softint(uint64_t value)
{
- env->softint &= (uint32_t)~value;
+ do_modify_softint("helper_clear_softint", env->softint & (uint32_t)~value);
}
void helper_write_softint(uint64_t value)
{
- env->softint = (uint32_t)value;
+ do_modify_softint("helper_write_softint", (uint32_t)value);
}
#endif
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH 6/9] sparc64: add macros to deal with softint and timer interrupt
2010-01-07 20:27 [Qemu-devel] [PATCH 0/9] sparc64: interrupts and tick timers v1 Igor V. Kovalenko
` (4 preceding siblings ...)
2010-01-07 20:28 ` [Qemu-devel] [PATCH 5/9] sparc64: check for pending irq when pil, pstate or softint is changed Igor V. Kovalenko
@ 2010-01-07 20:28 ` Igor V. Kovalenko
2010-01-07 20:28 ` [Qemu-devel] [PATCH 7/9] sparc64: move cpu_interrupts_enabled to cpu.h Igor V. Kovalenko
` (3 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Igor V. Kovalenko @ 2010-01-07 20:28 UTC (permalink / raw)
To: qemu-devel
From: Igor V. Kovalenko <igor.v.kovalenko@gmail.com>
Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko@gmail.com>
---
hw/sun4u.c | 1 -
target-sparc/cpu.h | 4 ++++
2 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 9d46f08..029e3ed 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -73,7 +73,6 @@
#define MAX_PILS 16
-#define TICK_INT_DIS 0x8000000000000000ULL
#define TICK_MAX 0x7fffffffffffffffULL
struct hwdef {
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 1fe4d0f..0f0e38c 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -394,6 +394,8 @@ typedef struct CPUSPARCState {
uint64_t fprs;
uint64_t tick_cmpr, stick_cmpr;
void *tick, *stick;
+#define TICK_NPT_MASK 0x8000000000000000ULL
+#define TICK_INT_DIS 0x8000000000000000ULL
uint64_t gsr;
uint32_t gl; // UA2005
/* UA 2005 hyperprivileged registers */
@@ -402,6 +404,8 @@ typedef struct CPUSPARCState {
uint32_t softint;
#define SOFTINT_TIMER 1
#define SOFTINT_STIMER (1 << 16)
+#define SOFTINT_INTRMASK (0xFFFE)
+#define SOFTINT_REG_MASK (SOFTINT_STIMER|SOFTINT_INTRMASK|SOFTINT_TIMER)
#endif
sparc_def_t *def;
} CPUSPARCState;
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH 7/9] sparc64: move cpu_interrupts_enabled to cpu.h
2010-01-07 20:27 [Qemu-devel] [PATCH 0/9] sparc64: interrupts and tick timers v1 Igor V. Kovalenko
` (5 preceding siblings ...)
2010-01-07 20:28 ` [Qemu-devel] [PATCH 6/9] sparc64: add macros to deal with softint and timer interrupt Igor V. Kovalenko
@ 2010-01-07 20:28 ` Igor V. Kovalenko
2010-01-07 20:28 ` [Qemu-devel] [PATCH 8/9] sparc64: interrupt trap handling Igor V. Kovalenko
` (2 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Igor V. Kovalenko @ 2010-01-07 20:28 UTC (permalink / raw)
To: qemu-devel
From: Igor V. Kovalenko <igor.v.kovalenko@gmail.com>
- to be used by cpu_check_irqs
Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko@gmail.com>
---
target-sparc/cpu.h | 13 +++++++++++++
target-sparc/exec.h | 13 -------------
2 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 0f0e38c..e5b282d 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -564,6 +564,19 @@ static inline int cpu_mmu_index(CPUState *env1)
#endif
}
+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_fpu_enabled(CPUState *env1)
{
#if defined(CONFIG_USER_ONLY)
diff --git a/target-sparc/exec.h b/target-sparc/exec.h
index e120d6f..3e021e9 100644
--- a/target-sparc/exec.h
+++ b/target-sparc/exec.h
@@ -24,19 +24,6 @@ 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) &&
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH 8/9] sparc64: interrupt trap handling
2010-01-07 20:27 [Qemu-devel] [PATCH 0/9] sparc64: interrupts and tick timers v1 Igor V. Kovalenko
` (6 preceding siblings ...)
2010-01-07 20:28 ` [Qemu-devel] [PATCH 7/9] sparc64: move cpu_interrupts_enabled to cpu.h Igor V. Kovalenko
@ 2010-01-07 20:28 ` Igor V. Kovalenko
2010-01-07 20:28 ` [Qemu-devel] [PATCH 9/9] sparc64: reimplement tick timers Igor V. Kovalenko
2010-01-08 18:16 ` [Qemu-devel] [PATCH 0/9] sparc64: interrupts and tick timers v1 Blue Swirl
9 siblings, 0 replies; 11+ messages in thread
From: Igor V. Kovalenko @ 2010-01-07 20:28 UTC (permalink / raw)
To: qemu-devel
From: Igor V. Kovalenko <igor.v.kovalenko@gmail.com>
cpu_check_irqs
- handle SOFTINT register TICK and STICK timer bits
- only check interrupt levels greater than PIL value
- handle preemption by higher level traps
cpu_exec
- handle CPU_INTERRUPT_HARD only if interrupts are enabled
- PIL 15 is not special level on sparcv9
Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko@gmail.com>
---
cpu-exec.c | 28 ++++++++++++++--------------
hw/sun4u.c | 48 +++++++++++++++++++++++++++++++++++-------------
target-sparc/cpu.h | 10 ++++++++++
3 files changed, 59 insertions(+), 27 deletions(-)
diff --git a/cpu-exec.c b/cpu-exec.c
index af4595b..4635be3 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -449,20 +449,20 @@ int cpu_exec(CPUState *env1)
next_tb = 0;
}
#elif defined(TARGET_SPARC)
- if ((interrupt_request & CPU_INTERRUPT_HARD) &&
- cpu_interrupts_enabled(env)) {
- int pil = env->interrupt_index & 15;
- int type = env->interrupt_index & 0xf0;
-
- if (((type == TT_EXTINT) &&
- (pil == 15 || pil > env->psrpil)) ||
- type != TT_EXTINT) {
- env->interrupt_request &= ~CPU_INTERRUPT_HARD;
- env->exception_index = env->interrupt_index;
- do_interrupt(env);
- env->interrupt_index = 0;
- next_tb = 0;
- }
+ if (interrupt_request & CPU_INTERRUPT_HARD) {
+ if (cpu_interrupts_enabled(env) &&
+ env->interrupt_index > 0) {
+ int pil = env->interrupt_index & 0xf;
+ int type = env->interrupt_index & 0xf0;
+
+ if (((type == TT_EXTINT) &&
+ cpu_pil_allowed(env, pil)) ||
+ type != TT_EXTINT) {
+ env->exception_index = env->interrupt_index;
+ do_interrupt(env);
+ next_tb = 0;
+ }
+ }
} else if (interrupt_request & CPU_INTERRUPT_TIMER) {
//do_interrupt(0, 0, 0, 0, 0);
env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 029e3ed..ae32878 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -232,29 +232,51 @@ void irq_info(Monitor *mon)
void cpu_check_irqs(CPUState *env)
{
- uint32_t pil = env->pil_in | (env->softint & ~SOFTINT_TIMER) |
- ((env->softint & SOFTINT_TIMER) << 14);
+ uint32_t pil = env->pil_in |
+ (env->softint & ~(SOFTINT_TIMER | SOFTINT_STIMER));
+
+ /* check if TM or SM in SOFTINT are set
+ setting these also causes interrupt 14 */
+ if (env->softint & (SOFTINT_TIMER | SOFTINT_STIMER)) {
+ pil |= 1 << 14;
+ }
+
+ if (!pil) {
+ if (env->interrupt_request & CPU_INTERRUPT_HARD) {
+ CPUIRQ_DPRINTF("Reset CPU IRQ (current interrupt %x)\n",
+ env->interrupt_index);
+ env->interrupt_index = 0;
+ cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+ }
+ return;
+ }
+
+ if (cpu_interrupts_enabled(env)) {
- if (pil && (env->interrupt_index == 0 ||
- (env->interrupt_index & ~15) == TT_EXTINT)) {
unsigned int i;
- for (i = 15; i > 0; i--) {
+ for (i = 15; i > env->psrpil; i--) {
if (pil & (1 << i)) {
int old_interrupt = env->interrupt_index;
-
- env->interrupt_index = TT_EXTINT | i;
- if (old_interrupt != env->interrupt_index) {
- CPUIRQ_DPRINTF("Set CPU IRQ %d\n", i);
+ int new_interrupt = TT_EXTINT | i;
+
+ if (env->tl > 0 && cpu_tsptr(env)->tt > new_interrupt) {
+ CPUIRQ_DPRINTF("Not setting CPU IRQ: TL=%d "
+ "current %x >= pending %x\n",
+ env->tl, cpu_tsptr(env)->tt, new_interrupt);
+ } else if (old_interrupt != new_interrupt) {
+ env->interrupt_index = new_interrupt;
+ CPUIRQ_DPRINTF("Set CPU IRQ %d old=%x new=%x\n", i,
+ old_interrupt, new_interrupt);
cpu_interrupt(env, CPU_INTERRUPT_HARD);
}
break;
}
}
- } else if (!pil && (env->interrupt_index & ~15) == TT_EXTINT) {
- CPUIRQ_DPRINTF("Reset CPU IRQ %d\n", env->interrupt_index & 15);
- env->interrupt_index = 0;
- cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+ } else {
+ CPUIRQ_DPRINTF("Interrupts disabled, pil=%08x pil_in=%08x softint=%08x "
+ "current interrupt %x\n",
+ pil, env->pil_in, env->softint, env->interrupt_index);
}
}
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index e5b282d..50859c7 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -577,6 +577,16 @@ static inline int cpu_interrupts_enabled(CPUState *env1)
return 0;
}
+static inline int cpu_pil_allowed(CPUState *env1, int pil)
+{
+#if !defined(TARGET_SPARC64)
+ /* level 15 is non-maskable on sparc v8 */
+ return pil == 15 || pil > env1->psrpil;
+#else
+ return pil > env1->psrpil;
+#endif
+}
+
static inline int cpu_fpu_enabled(CPUState *env1)
{
#if defined(CONFIG_USER_ONLY)
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH 9/9] sparc64: reimplement tick timers
2010-01-07 20:27 [Qemu-devel] [PATCH 0/9] sparc64: interrupts and tick timers v1 Igor V. Kovalenko
` (7 preceding siblings ...)
2010-01-07 20:28 ` [Qemu-devel] [PATCH 8/9] sparc64: interrupt trap handling Igor V. Kovalenko
@ 2010-01-07 20:28 ` Igor V. Kovalenko
2010-01-08 18:16 ` [Qemu-devel] [PATCH 0/9] sparc64: interrupts and tick timers v1 Blue Swirl
9 siblings, 0 replies; 11+ messages in thread
From: Igor V. Kovalenko @ 2010-01-07 20:28 UTC (permalink / raw)
To: qemu-devel
From: Igor V. Kovalenko <igor.v.kovalenko@gmail.com>
sparc64 timer has tick counter which can be set and read,
and tick compare value used as deadline to fire timer interrupt.
The timer is not used as periodic timer, instead deadline
is set each time new timer interrupt is needed.
This change implements sparc64 timers without
periodic timers. It is not complete yet,
cpu_tick_set_count does not really set counter value.
Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko@gmail.com>
---
hw/sun4u.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 146 insertions(+), 30 deletions(-)
diff --git a/hw/sun4u.c b/hw/sun4u.c
index ae32878..565b25d 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -40,6 +40,7 @@
//#define DEBUG_IRQ
//#define DEBUG_EBUS
+//#define DEBUG_TIMER
#ifdef DEBUG_IRQ
#define CPUIRQ_DPRINTF(fmt, ...) \
@@ -55,6 +56,13 @@
#define EBUS_DPRINTF(fmt, ...)
#endif
+#ifdef DEBUG_TIMER
+#define TIMER_DPRINTF(fmt, ...) \
+ do { printf("TIMER: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define TIMER_DPRINTF(fmt, ...)
+#endif
+
#define KERNEL_LOAD_ADDR 0x00404000
#define CMDLINE_ADDR 0x003ff000
#define INITRD_LOAD_ADDR 0x00300000
@@ -280,6 +288,12 @@ void cpu_check_irqs(CPUState *env)
}
}
+static void cpu_kick_irq(CPUState *env)
+{
+ env->halted = 0;
+ cpu_check_irqs(env);
+}
+
static void cpu_set_irq(void *opaque, int irq, int level)
{
CPUState *env = opaque;
@@ -301,6 +315,41 @@ typedef struct ResetData {
uint64_t prom_addr;
} ResetData;
+struct sun4u_timer
+{
+ const char *name;
+ uint32_t frequency;
+ int disabled;
+ uint64_t disabled_mask;
+ QEMUTimer *qtimer;
+};
+
+typedef struct sun4u_timer sun4u_timer;
+
+static sun4u_timer* sun4u_timer_create(const char* name, CPUState *env,
+ QEMUBHFunc *cb, uint32_t frequency,
+ uint64_t disabled_mask)
+{
+ sun4u_timer *timer;
+
+ timer = qemu_mallocz(sizeof (sun4u_timer));
+
+ timer->name = name;
+ timer->frequency = frequency;
+ timer->disabled = 1;
+ timer->disabled_mask = disabled_mask;
+
+ timer->qtimer = qemu_new_timer(vm_clock, cb, env);
+
+ return timer;
+}
+
+static void sun4u_timer_reset(sun4u_timer *timer)
+{
+ timer->disabled = 1;
+ qemu_del_timer(timer->qtimer);
+}
+
static void main_cpu_reset(void *opaque)
{
ResetData *s = (ResetData *)opaque;
@@ -308,15 +357,11 @@ static void main_cpu_reset(void *opaque)
static unsigned int nr_resets;
cpu_reset(env);
- env->tick_cmpr = TICK_INT_DIS | 0;
- ptimer_set_limit(env->tick, TICK_MAX, 1);
- ptimer_run(env->tick, 1);
- env->stick_cmpr = TICK_INT_DIS | 0;
- ptimer_set_limit(env->stick, TICK_MAX, 1);
- ptimer_run(env->stick, 1);
- env->hstick_cmpr = TICK_INT_DIS | 0;
- ptimer_set_limit(env->hstick, TICK_MAX, 1);
- ptimer_run(env->hstick, 1);
+
+ sun4u_timer_reset(env->tick);
+ sun4u_timer_reset(env->stick);
+ sun4u_timer_reset(env->hstick);
+
env->gregs[1] = 0; // Memory start
env->gregs[2] = ram_size; // Memory size
env->gregs[3] = 0; // Machine description XXX
@@ -333,44 +378,114 @@ static void tick_irq(void *opaque)
{
CPUState *env = opaque;
- if (!(env->tick_cmpr & TICK_INT_DIS)) {
- env->softint |= SOFTINT_TIMER;
- cpu_interrupt(env, CPU_INTERRUPT_TIMER);
+ sun4u_timer* timer = (sun4u_timer*) env->tick;
+
+ if (timer->disabled) {
+ CPUIRQ_DPRINTF("tick_irq: softint disabled\n");
+ return;
+ } else {
+ CPUIRQ_DPRINTF("tick: fire\n");
}
+
+ env->softint |= SOFTINT_TIMER;
+ cpu_kick_irq(env);
}
static void stick_irq(void *opaque)
{
CPUState *env = opaque;
- if (!(env->stick_cmpr & TICK_INT_DIS)) {
- env->softint |= SOFTINT_STIMER;
- cpu_interrupt(env, CPU_INTERRUPT_TIMER);
+ sun4u_timer* timer = (sun4u_timer*) env->stick;
+
+ if (timer->disabled) {
+ CPUIRQ_DPRINTF("stick_irq: softint disabled\n");
+ return;
+ } else {
+ CPUIRQ_DPRINTF("stick: fire\n");
}
+
+ env->softint |= SOFTINT_STIMER;
+ cpu_kick_irq(env);
}
static void hstick_irq(void *opaque)
{
CPUState *env = opaque;
- if (!(env->hstick_cmpr & TICK_INT_DIS)) {
- cpu_interrupt(env, CPU_INTERRUPT_TIMER);
+ sun4u_timer* timer = (sun4u_timer*) env->hstick;
+
+ if (timer->disabled) {
+ CPUIRQ_DPRINTF("hstick_irq: softint disabled\n");
+ return;
+ } else {
+ CPUIRQ_DPRINTF("hstick: fire\n");
}
+
+ env->softint |= SOFTINT_STIMER;
+ cpu_kick_irq(env);
}
void cpu_tick_set_count(void *opaque, uint64_t count)
{
- ptimer_set_count(opaque, -count);
+ sun4u_timer *timer = opaque;
+
+ uint64_t real_count = count & ~timer->disabled_mask;
+ timer->disabled = (count & timer->disabled_mask) ? 1 : 0;
+
+ TIMER_DPRINTF("%s (ignored) set_count count=0x%016lx (%s) p=%p\n",
+ timer->name, real_count, timer->disabled?"disabled":"enabled", opaque);
+
+ // TODO: save offset in our timer
}
uint64_t cpu_tick_get_count(void *opaque)
{
- return -ptimer_get_count(opaque);
+ sun4u_timer *timer = opaque;
+
+ uint64_t real_count = muldiv64(qemu_get_clock(vm_clock), timer->frequency,
+ get_ticks_per_sec());
+
+ TIMER_DPRINTF("%s get_count count=0x%016lx (%s) p=%p\n",
+ timer->name, real_count,
+ timer->disabled?"disabled":"enabled", opaque);
+
+ if (timer->disabled)
+ real_count |= timer->disabled_mask;
+
+ return real_count;
}
void cpu_tick_set_limit(void *opaque, uint64_t limit)
{
- ptimer_set_limit(opaque, -limit, 0);
+ sun4u_timer *timer = opaque;
+
+ int64_t now = qemu_get_clock(vm_clock);
+
+ int64_t real_limit = limit & ~timer->disabled_mask;
+ int64_t expires = muldiv64(now, timer->frequency,
+ get_ticks_per_sec()) & ~timer->disabled_mask;
+ int64_t current_tick = expires;
+ int64_t delta = real_limit - current_tick;
+ if (delta < 0)
+ delta = 1;
+
+ timer->disabled = (limit & timer->disabled_mask) ? 1 : 0;
+
+ TIMER_DPRINTF("%s set_limit limit=0x%016lx (%s) p=%p "
+ "called with limit=0x%016lx at 0x%016lx (delta=0x%016lx)\n",
+ timer->name, real_limit, timer->disabled?"disabled":"enabled",
+ opaque, limit, current_tick, delta);
+
+ if (!real_limit) {
+ TIMER_DPRINTF("%s set_limit limit=ZERO - not starting timer\n",
+ timer->name);
+ qemu_del_timer(timer->qtimer);
+ } else if (timer->disabled) {
+ qemu_del_timer(timer->qtimer);
+ } else {
+ qemu_mod_timer(timer->qtimer, now + muldiv64(delta, get_ticks_per_sec(),
+ timer->frequency));
+ }
}
static void ebus_mmio_mapfunc(PCIDevice *pci_dev, int region_num,
@@ -557,9 +672,12 @@ device_init(ram_register_devices);
static CPUState *cpu_devinit(const char *cpu_model, const struct hwdef *hwdef)
{
CPUState *env;
- QEMUBH *bh;
ResetData *reset_info;
+ uint32_t tick_frequency = 10*1000000;
+ uint32_t stick_frequency = 10*1000000;
+ uint32_t hstick_frequency = 10*1000000;
+
if (!cpu_model)
cpu_model = hwdef->default_cpu_model;
env = cpu_init(cpu_model);
@@ -567,17 +685,15 @@ static CPUState *cpu_devinit(const char *cpu_model, const struct hwdef *hwdef)
fprintf(stderr, "Unable to find Sparc CPU definition\n");
exit(1);
}
- bh = qemu_bh_new(tick_irq, env);
- env->tick = ptimer_init(bh);
- ptimer_set_period(env->tick, 1ULL);
- bh = qemu_bh_new(stick_irq, env);
- env->stick = ptimer_init(bh);
- ptimer_set_period(env->stick, 1ULL);
+ env->tick = sun4u_timer_create("tick", env, tick_irq,
+ tick_frequency, TICK_NPT_MASK);
+
+ env->stick = sun4u_timer_create("stick", env, stick_irq,
+ stick_frequency, TICK_INT_DIS);
- bh = qemu_bh_new(hstick_irq, env);
- env->hstick = ptimer_init(bh);
- ptimer_set_period(env->hstick, 1ULL);
+ env->hstick = sun4u_timer_create("hstick", env, hstick_irq,
+ hstick_frequency, TICK_INT_DIS);
reset_info = qemu_mallocz(sizeof(ResetData));
reset_info->env = env;
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] [PATCH 0/9] sparc64: interrupts and tick timers v1
2010-01-07 20:27 [Qemu-devel] [PATCH 0/9] sparc64: interrupts and tick timers v1 Igor V. Kovalenko
` (8 preceding siblings ...)
2010-01-07 20:28 ` [Qemu-devel] [PATCH 9/9] sparc64: reimplement tick timers Igor V. Kovalenko
@ 2010-01-08 18:16 ` Blue Swirl
9 siblings, 0 replies; 11+ messages in thread
From: Blue Swirl @ 2010-01-08 18:16 UTC (permalink / raw)
To: Igor V. Kovalenko; +Cc: qemu-devel
Thanks, applied all except 9/9.
On Thu, Jan 7, 2010 at 8:27 PM, Igor V. Kovalenko
<igor.v.kovalenko@gmail.com> wrote:
> The following series is a cleanup over previous one.
>
> v0 -> v1: post-review changes
> - dropped patch "clear exception_index with -1 val" (applied)
> - new patch "change_pstate should have 32bit argument"
> - cleanups for coding style and hexadecimal output convention
> - wrpil is no-op for CONFIG_USER_ONLY
> - restored PIL 15 as non-maskable interrupt level on sparcv8
> - check for PSTATE.IE is replaced with call to cpu_interrupts_enabled()
> - in patch "sparc64: interrupt trap handling"
> cleaned up change in cpu_exec; since sparc64 does not use
> CPU_INTERRUPT_TIMER now, corresponding code branch is unchanged
>
> ---
>
> Igor V. Kovalenko (9):
> sparc64: change_pstate should have 32bit argument
> sparc64: trace pstate and global register set changes
> sparc64: add PIL to cpu state dump
> sparc64: use helper_wrpil to check pending irq on write
> sparc64: check for pending irq when pil, pstate or softint is changed
> sparc64: add macros to deal with softint and timer interrupt
> sparc64: move cpu_interrupts_enabled to cpu.h
> sparc64: interrupt trap handling
> sparc64: reimplement tick timers
>
>
> cpu-exec.c | 28 +++---
> hw/sun4u.c | 225 +++++++++++++++++++++++++++++++++++++---------
> target-sparc/cpu.h | 27 ++++++
> target-sparc/exec.h | 13 ---
> target-sparc/helper.c | 1
> target-sparc/helper.h | 1
> target-sparc/op_helper.c | 81 +++++++++++++++--
> target-sparc/translate.c | 5 -
> 8 files changed, 300 insertions(+), 81 deletions(-)
>
> --
> Kind regards,
> Igor V. Kovalenko
>
>
>
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2010-01-08 18:16 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-01-07 20:27 [Qemu-devel] [PATCH 0/9] sparc64: interrupts and tick timers v1 Igor V. Kovalenko
2010-01-07 20:27 ` [Qemu-devel] [PATCH 1/9] sparc64: change_pstate should have 32bit argument Igor V. Kovalenko
2010-01-07 20:28 ` [Qemu-devel] [PATCH 2/9] sparc64: trace pstate and global register set changes Igor V. Kovalenko
2010-01-07 20:28 ` [Qemu-devel] [PATCH 3/9] sparc64: add PIL to cpu state dump Igor V. Kovalenko
2010-01-07 20:28 ` [Qemu-devel] [PATCH 4/9] sparc64: use helper_wrpil to check pending irq on write Igor V. Kovalenko
2010-01-07 20:28 ` [Qemu-devel] [PATCH 5/9] sparc64: check for pending irq when pil, pstate or softint is changed Igor V. Kovalenko
2010-01-07 20:28 ` [Qemu-devel] [PATCH 6/9] sparc64: add macros to deal with softint and timer interrupt Igor V. Kovalenko
2010-01-07 20:28 ` [Qemu-devel] [PATCH 7/9] sparc64: move cpu_interrupts_enabled to cpu.h Igor V. Kovalenko
2010-01-07 20:28 ` [Qemu-devel] [PATCH 8/9] sparc64: interrupt trap handling Igor V. Kovalenko
2010-01-07 20:28 ` [Qemu-devel] [PATCH 9/9] sparc64: reimplement tick timers Igor V. Kovalenko
2010-01-08 18:16 ` [Qemu-devel] [PATCH 0/9] sparc64: interrupts and tick timers v1 Blue Swirl
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).