From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NSIgp-0007n5-Fb for qemu-devel@nongnu.org; Tue, 05 Jan 2010 18:19:51 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1NSIgl-0007gy-Px for qemu-devel@nongnu.org; Tue, 05 Jan 2010 18:19:51 -0500 Received: from [199.232.76.173] (port=35325 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NSIgl-0007gh-Kz for qemu-devel@nongnu.org; Tue, 05 Jan 2010 18:19:47 -0500 Received: from mail-fx0-f222.google.com ([209.85.220.222]:54407) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1NSIgj-0008JO-Ur for qemu-devel@nongnu.org; Tue, 05 Jan 2010 18:19:47 -0500 Received: by mail-fx0-f222.google.com with SMTP id 22so19469351fxm.2 for ; Tue, 05 Jan 2010 15:19:45 -0800 (PST) Received: from localhost ([127.0.0.1] helo=[192.168.1.2]) by skyserv with esmtp (Exim 4.71) (envelope-from ) id 1NSIgh-0001m1-KQ for qemu-devel@nongnu.org; Wed, 06 Jan 2010 02:19:43 +0300 From: "Igor V. Kovalenko" Date: Wed, 06 Jan 2010 02:19:43 +0300 Message-ID: <20100105231943.6526.42311.stgit@skyserv> In-Reply-To: <20100105231558.6526.44483.stgit@skyserv> References: <20100105231558.6526.44483.stgit@skyserv> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Subject: [Qemu-devel] [PATCH 8/9] sparc64: interrupt trap handling List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org From: Igor V. Kovalenko 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 --- cpu-exec.c | 40 ++++++++++++++++++++++------------------ hw/sun4u.c | 52 +++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 59 insertions(+), 33 deletions(-) diff --git a/cpu-exec.c b/cpu-exec.c index af4595b..65192c1 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -449,24 +449,28 @@ 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; - } - } else if (interrupt_request & CPU_INTERRUPT_TIMER) { - //do_interrupt(0, 0, 0, 0, 0); - env->interrupt_request &= ~CPU_INTERRUPT_TIMER; - } + if ((interrupt_request & CPU_INTERRUPT_HARD)) { + if (cpu_interrupts_enabled(env)) { + int pil = env->interrupt_index & 0xf; + int type = env->interrupt_index & 0xf0; + + if (((type == TT_EXTINT) && (pil > env->psrpil)) || + type != TT_EXTINT) { + //env->interrupt_request &= ~CPU_INTERRUPT_HARD; + if (env->interrupt_index > 0) { + env->exception_index = env->interrupt_index; + do_interrupt(env); + next_tb = 0; + } + } + } + } + else if (interrupt_request & CPU_INTERRUPT_TIMER) { + env->interrupt_request &= ~CPU_INTERRUPT_TIMER; +#if !defined(CONFIG_USER_ONLY) + cpu_check_irqs(env); +#endif + } #elif defined(TARGET_ARM) if (interrupt_request & CPU_INTERRUPT_FIQ && !(env->uncached_cpsr & CPSR_F)) { diff --git a/hw/sun4u.c b/hw/sun4u.c index 9d46f08..84a8043 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -233,29 +233,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_TM | SOFTINT_SM)); + + /* check if TM or SM in SOFTINT are set + setting these also causes interrupt 14 */ + if (env->softint & (SOFTINT_TM | SOFTINT_SM)) + 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); - cpu_interrupt(env, CPU_INTERRUPT_HARD); - } + 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); } }