From patchwork Sun Jul 25 04:44:41 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aurelien Jarno X-Patchwork-Id: 59871 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 02C52B6F06 for ; Sun, 25 Jul 2010 14:47:14 +1000 (EST) Received: from localhost ([127.0.0.1]:49009 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Oct6F-0003br-IP for incoming@patchwork.ozlabs.org; Sun, 25 Jul 2010 00:46:07 -0400 Received: from [140.186.70.92] (port=44705 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Oct4v-0003E9-7O for qemu-devel@nongnu.org; Sun, 25 Jul 2010 00:44:46 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1Oct4t-0001KB-SN for qemu-devel@nongnu.org; Sun, 25 Jul 2010 00:44:45 -0400 Received: from hall.aurel32.net ([88.191.82.174]:54172) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1Oct4t-0001Ij-HR for qemu-devel@nongnu.org; Sun, 25 Jul 2010 00:44:43 -0400 Received: from aurel32 by hall.aurel32.net with local (Exim 4.69) (envelope-from ) id 1Oct4r-0002Ak-Lr; Sun, 25 Jul 2010 06:44:41 +0200 Date: Sun, 25 Jul 2010 06:44:41 +0200 From: Aurelien Jarno To: "Edgar E. Iglesias" Subject: Re: [Qemu-devel] [PATCH] MIPS interrupts and -icount Message-ID: <20100725044441.GD22478@hall.aurel32.net> References: <20100722113218.GC28205@edde.se.axis.com> <20100724225545.GD7190@ohm.aurel32.net> <20100725000754.GB25828@laped.lan> <20100725030807.GF7190@ohm.aurel32.net> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20100725030807.GF7190@ohm.aurel32.net> X-Mailer: Mutt 1.5.18 (2008-05-17) User-Agent: Mutt/1.5.18 (2008-05-17) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) Cc: qemu-devel@nongnu.org X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org On Sun, Jul 25, 2010 at 05:08:07AM +0200, Aurelien Jarno wrote: > On Sun, Jul 25, 2010 at 02:07:54AM +0200, Edgar E. Iglesias wrote: > > On Sun, Jul 25, 2010 at 12:55:45AM +0200, Aurelien Jarno wrote: > > > On Thu, Jul 22, 2010 at 01:32:18PM +0200, Edgar E. Iglesias wrote: > > > > Hi, > > > > > > > > I'm seeing an error when emulating MIPS guests with -icount. > > > > In cpu_interrupt: > > > > cpu_abort(env, "Raised interrupt while not in I/O function"); > > > > > > I am not able to reproduce the issue. Do you have more details how to > > > reproduce the problem? > > > > You need a machine with devices that raise the hw interrupts. I didn't > > see the error on the images on the wiki though. But I've got a machine > > here that trigs it easily. Will check if I can publish it and an image. > > > > That would be nice if you can share it. > > > > > It seems to me like the MIPS interrupt glue logic between interrupt > > > > controllers and the MIPS core is not modeled correctly. > > > > > > It seems indeed that sometimes interrupt are triggered while not in > > > I/O functions, your patch addresses part of the problem. > > > > > > > When hw interrupt pending bits in CP0_Cause are set, the CPU should > > > > see the hw interrupt line as active. The CPU may or may not take the > > > > interrupt based on internal state (global irq mask etc) but the glue > > > > logic shouldn't care about that. Am I missing something here? > > > > > > I don't think it is correct. On the real hardware, the interrupt line is > > > actually active only when all conditions are fulfilled. > > > > > > The thing to remember is that the interrupts are level triggered. So if > > > an interrupt is masked, it should be rejected by the CPU, but could be > > > triggered again as soon as the interrupt mask is changed. > > > > Agreed, that behaviour is what I'm trying to acheive. The problem now > > is that the the level triggered line, prior to CPU masking is beeing masked > > by external logic. IMO it shouldnt. See hw/mips_int.c and cpu-exec.c prior > > to the patch. > > Actually all depends if you consider the MIPS interrupt controller part > of the CPU or not. It could be entirely modeled in the CPU, that is in > cpu-exec.c or entirely modeled as a separate controller, that is in > mips_int.c. > If we choose having the interrupt controller as part of the CPU, which seems to be what you have chosen, the following patch should fix the remaining issues (and prepare the work for vector interrupt support): Acked-by: Edgar E. Iglesias Tested-by: Edgar E. Iglesias diff --git a/hw/mips_int.c b/hw/mips_int.c index 80488ba..477f6ab 100644 --- a/hw/mips_int.c +++ b/hw/mips_int.c @@ -54,3 +54,12 @@ void cpu_mips_irq_init_cpu(CPUState *env) env->irq[i] = qi[i]; } } + +void cpu_mips_soft_irq(CPUState *env, int irq, int level) +{ + if (irq < 0 || irq > 2) { + return; + } + + qemu_set_irq(env->irq[irq], level); +} diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 1578850..b8e6fee 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -597,6 +597,9 @@ void cpu_mips_store_compare (CPUState *env, uint32_t value); void cpu_mips_start_count(CPUState *env); void cpu_mips_stop_count(CPUState *env); +/* mips_int.c */ +void cpu_mips_soft_irq(CPUState *env, int irq, int level); + /* helper.c */ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw, int mmu_idx, int is_softmmu); diff --git a/target-mips/helper.h b/target-mips/helper.h index a6ba75d..cb13fb2 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -2,7 +2,6 @@ DEF_HELPER_2(raise_exception_err, void, i32, int) DEF_HELPER_1(raise_exception, void, i32) -DEF_HELPER_0(interrupt_restart, void) #ifdef TARGET_MIPS64 DEF_HELPER_3(ldl, tl, tl, tl, int) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index c963224..8482e69 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -46,18 +46,6 @@ void helper_raise_exception (uint32_t exception) helper_raise_exception_err(exception, 0); } -void helper_interrupt_restart (void) -{ - if (!(env->CP0_Status & (1 << CP0St_EXL)) && - !(env->CP0_Status & (1 << CP0St_ERL)) && - !(env->hflags & MIPS_HFLAG_DM) && - (env->CP0_Status & (1 << CP0St_IE)) && - (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask)) { - env->CP0_Cause &= ~(0x1f << CP0Ca_EC); - helper_raise_exception(EXCP_EXT_INTERRUPT); - } -} - #if !defined(CONFIG_USER_ONLY) static void do_restore_state (void *pc_ptr) { @@ -1346,6 +1334,7 @@ void helper_mtc0_cause (target_ulong arg1) { uint32_t mask = 0x00C00300; uint32_t old = env->CP0_Cause; + int i; if (env->insn_flags & ISA_MIPS32R2) mask |= 1 << CP0Ca_DC; @@ -1358,6 +1347,13 @@ void helper_mtc0_cause (target_ulong arg1) else cpu_mips_start_count(env); } + + /* Set/reset software interrupts */ + for (i = 0 ; i < 2 ; i++) { + if ((old ^ env->CP0_Cause) & (1 << (CP0Ca_IP + i))) { + cpu_mips_soft_irq(env, i, env->CP0_Cause & (1 << (CP0Ca_IP + i))); + } + } } void helper_mtc0_ebase (target_ulong arg1) diff --git a/target-mips/translate.c b/target-mips/translate.c index 7168273..6c72dee 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -5190,7 +5190,17 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int switch (sel) { case 0: save_cpu_state(ctx, 1); + /* Mark as an IO operation because we may trigger a software + interrupt. */ + if (use_icount) { + gen_io_start(); + } gen_helper_mtc0_cause(arg); + if (use_icount) { + gen_io_end(); + } + /* Stop translation as we may have triggered an intetrupt */ + ctx->bstate = BS_STOP; rn = "Cause"; break; default: @@ -12365,7 +12375,6 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, } else { switch (ctx.bstate) { case BS_STOP: - gen_helper_interrupt_restart(); gen_goto_tb(&ctx, 0, ctx.pc); break; case BS_NONE: @@ -12373,7 +12382,6 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, gen_goto_tb(&ctx, 0, ctx.pc); break; case BS_EXCP: - gen_helper_interrupt_restart(); tcg_gen_exit_tb(0); break; case BS_BRANCH: