mirror of
https://github.com/xemu-project/xemu.git
synced 2025-01-19 10:24:37 +00:00
sparc64: interrupt trap handling
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> Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
This commit is contained in:
parent
2df6c2d0de
commit
d532b26c9d
26
cpu-exec.c
26
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 (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) &&
|
||||
(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 (((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;
|
||||
|
46
hw/sun4u.c
46
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;
|
||||
int new_interrupt = TT_EXTINT | i;
|
||||
|
||||
env->interrupt_index = TT_EXTINT | i;
|
||||
if (old_interrupt != env->interrupt_index) {
|
||||
CPUIRQ_DPRINTF("Set CPU IRQ %d\n", 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user