From patchwork Sat Sep 11 01:08:34 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Graf X-Patchwork-Id: 64481 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 1DDD6B70A6 for ; Sat, 11 Sep 2010 11:13:56 +1000 (EST) Received: from localhost ([127.0.0.1]:60775 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OuEew-00065e-Rc for incoming@patchwork.ozlabs.org; Fri, 10 Sep 2010 21:13:38 -0400 Received: from [140.186.70.92] (port=60301 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OuEa8-0003cR-1F for qemu-devel@nongnu.org; Fri, 10 Sep 2010 21:08:41 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1OuEa5-0003Ft-68 for qemu-devel@nongnu.org; Fri, 10 Sep 2010 21:08:39 -0400 Received: from cantor.suse.de ([195.135.220.2]:60329 helo=mx1.suse.de) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1OuEa4-0003FS-Ni for qemu-devel@nongnu.org; Fri, 10 Sep 2010 21:08:37 -0400 Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.221.2]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.suse.de (Postfix) with ESMTP id 1282C945D6; Sat, 11 Sep 2010 03:08:35 +0200 (CEST) From: Alexander Graf To: QEMU Developers Date: Sat, 11 Sep 2010 03:08:34 +0200 Message-Id: <1284167314-11594-3-git-send-email-agraf@suse.de> X-Mailer: git-send-email 1.6.0.2 In-Reply-To: <1284167314-11594-1-git-send-email-agraf@suse.de> References: <1284167314-11594-1-git-send-email-agraf@suse.de> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4-2.6 Cc: Thomas Monjalon , "Edgar E. Iglesias" Subject: [Qemu-devel] [PATCH 2/2] PPC: Redesign interrupt trigger path 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 According to the Book3S spec, the interrupt context starts with an MSR value that is rather simple. If we leave out the HV case, it's almost always 0. To reflect this, let's redesign the way that MSR value gets calculated. Using this, we also squash the bug where MSR_POW can slip through into the interrupt handler MSR. Reported-by: Thomas Monjalon Signed-off-by: Alexander Graf --- target-ppc/helper.c | 80 ++++++++++++++++++-------------------------------- 1 files changed, 29 insertions(+), 51 deletions(-) diff --git a/target-ppc/helper.c b/target-ppc/helper.c index d342b09..4febeb4 100644 --- a/target-ppc/helper.c +++ b/target-ppc/helper.c @@ -2074,18 +2074,24 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp) qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx " => %08x (%02x)\n", env->nip, excp, env->error_code); - msr = env->msr; - new_msr = msr; + + /* new srr1 value excluding must-be-zero bits */ + msr = env->msr & ~0x783f0000ULL; + + /* new interrupt handler msr */ + new_msr = env->msr & ((target_ulong)1 << MSR_ME); + + /* target registers */ srr0 = SPR_SRR0; srr1 = SPR_SRR1; asrr0 = -1; asrr1 = -1; + switch (excp) { case POWERPC_EXCP_NONE: /* Should never happen */ return; case POWERPC_EXCP_CRITICAL: /* Critical input */ - new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */ switch (excp_model) { case POWERPC_EXCP_40x: srr0 = SPR_40x_SRR2; @@ -2116,12 +2122,14 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp) env->halted = 1; env->interrupt_request |= CPU_INTERRUPT_EXITTB; } - new_msr &= ~((target_ulong)1 << MSR_RI); - new_msr &= ~((target_ulong)1 << MSR_ME); if (0) { /* XXX: find a suitable condition to enable the hypervisor mode */ new_msr |= (target_ulong)MSR_HVB; } + + /* machine check exceptions don't have ME set */ + new_msr &= ~((target_ulong)1 << MSR_ME); + /* XXX: should also have something loaded in DAR / DSISR */ switch (excp_model) { case POWERPC_EXCP_40x: @@ -2141,25 +2149,21 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp) case POWERPC_EXCP_DSI: /* Data storage exception */ LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]); - new_msr &= ~((target_ulong)1 << MSR_RI); if (lpes1 == 0) new_msr |= (target_ulong)MSR_HVB; goto store_next; case POWERPC_EXCP_ISI: /* Instruction storage exception */ LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx "\n", msr, env->nip); - new_msr &= ~((target_ulong)1 << MSR_RI); if (lpes1 == 0) new_msr |= (target_ulong)MSR_HVB; msr |= env->error_code; goto store_next; case POWERPC_EXCP_EXTERNAL: /* External input */ - new_msr &= ~((target_ulong)1 << MSR_RI); if (lpes0 == 1) new_msr |= (target_ulong)MSR_HVB; goto store_next; case POWERPC_EXCP_ALIGN: /* Alignment exception */ - new_msr &= ~((target_ulong)1 << MSR_RI); if (lpes1 == 0) new_msr |= (target_ulong)MSR_HVB; /* XXX: this is false */ @@ -2175,7 +2179,6 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp) env->error_code = 0; return; } - new_msr &= ~((target_ulong)1 << MSR_RI); if (lpes1 == 0) new_msr |= (target_ulong)MSR_HVB; msr |= 0x00100000; @@ -2185,19 +2188,16 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp) break; case POWERPC_EXCP_INVAL: LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip); - new_msr &= ~((target_ulong)1 << MSR_RI); if (lpes1 == 0) new_msr |= (target_ulong)MSR_HVB; msr |= 0x00080000; break; case POWERPC_EXCP_PRIV: - new_msr &= ~((target_ulong)1 << MSR_RI); if (lpes1 == 0) new_msr |= (target_ulong)MSR_HVB; msr |= 0x00040000; break; case POWERPC_EXCP_TRAP: - new_msr &= ~((target_ulong)1 << MSR_RI); if (lpes1 == 0) new_msr |= (target_ulong)MSR_HVB; msr |= 0x00020000; @@ -2210,7 +2210,6 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp) } goto store_current; case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ - new_msr &= ~((target_ulong)1 << MSR_RI); if (lpes1 == 0) new_msr |= (target_ulong)MSR_HVB; goto store_current; @@ -2227,23 +2226,19 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp) } } dump_syscall(env); - new_msr &= ~((target_ulong)1 << MSR_RI); lev = env->error_code; if (lev == 1 || (lpes0 == 0 && lpes1 == 0)) new_msr |= (target_ulong)MSR_HVB; goto store_next; case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ - new_msr &= ~((target_ulong)1 << MSR_RI); goto store_current; case POWERPC_EXCP_DECR: /* Decrementer exception */ - new_msr &= ~((target_ulong)1 << MSR_RI); if (lpes1 == 0) new_msr |= (target_ulong)MSR_HVB; goto store_next; case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ /* FIT on 4xx */ LOG_EXCP("FIT exception\n"); - new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */ goto store_next; case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ LOG_EXCP("WDT exception\n"); @@ -2255,13 +2250,10 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp) default: break; } - new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */ goto store_next; case POWERPC_EXCP_DTLB: /* Data TLB error */ - new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */ goto store_next; case POWERPC_EXCP_ITLB: /* Instruction TLB error */ - new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */ goto store_next; case POWERPC_EXCP_DEBUG: /* Debug interrupt */ switch (excp_model) { @@ -2278,7 +2270,6 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp) cpu_abort(env, "Debug exception is not implemented yet !\n"); goto store_next; case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable */ - new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */ goto store_current; case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */ /* XXX: TODO */ @@ -2291,7 +2282,6 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp) "is not implemented yet !\n"); goto store_next; case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */ - new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: TODO */ cpu_abort(env, "Performance counter exception is not implemented yet !\n"); @@ -2315,19 +2305,23 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp) "is not implemented yet !\n"); goto store_next; case POWERPC_EXCP_RESET: /* System reset exception */ - new_msr &= ~((target_ulong)1 << MSR_RI); + if (msr_pow) { + /* indicate that we resumed from power save mode */ + msr |= 0x10000; + } else { + new_msr &= ~((target_ulong)1 << MSR_ME); + } + if (0) { /* XXX: find a suitable condition to enable the hypervisor mode */ new_msr |= (target_ulong)MSR_HVB; } goto store_next; case POWERPC_EXCP_DSEG: /* Data segment exception */ - new_msr &= ~((target_ulong)1 << MSR_RI); if (lpes1 == 0) new_msr |= (target_ulong)MSR_HVB; goto store_next; case POWERPC_EXCP_ISEG: /* Instruction segment exception */ - new_msr &= ~((target_ulong)1 << MSR_RI); if (lpes1 == 0) new_msr |= (target_ulong)MSR_HVB; goto store_next; @@ -2335,9 +2329,9 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp) srr0 = SPR_HSRR0; srr1 = SPR_HSRR1; new_msr |= (target_ulong)MSR_HVB; + new_msr |= env->msr & ((target_ulong)1 << MSR_RI); goto store_next; case POWERPC_EXCP_TRACE: /* Trace exception */ - new_msr &= ~((target_ulong)1 << MSR_RI); if (lpes1 == 0) new_msr |= (target_ulong)MSR_HVB; goto store_next; @@ -2345,30 +2339,32 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp) srr0 = SPR_HSRR0; srr1 = SPR_HSRR1; new_msr |= (target_ulong)MSR_HVB; + new_msr |= env->msr & ((target_ulong)1 << MSR_RI); goto store_next; case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */ srr0 = SPR_HSRR0; srr1 = SPR_HSRR1; new_msr |= (target_ulong)MSR_HVB; + new_msr |= env->msr & ((target_ulong)1 << MSR_RI); goto store_next; case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */ srr0 = SPR_HSRR0; srr1 = SPR_HSRR1; new_msr |= (target_ulong)MSR_HVB; + new_msr |= env->msr & ((target_ulong)1 << MSR_RI); goto store_next; case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */ srr0 = SPR_HSRR0; srr1 = SPR_HSRR1; new_msr |= (target_ulong)MSR_HVB; + new_msr |= env->msr & ((target_ulong)1 << MSR_RI); goto store_next; case POWERPC_EXCP_VPU: /* Vector unavailable exception */ - new_msr &= ~((target_ulong)1 << MSR_RI); if (lpes1 == 0) new_msr |= (target_ulong)MSR_HVB; goto store_current; case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */ LOG_EXCP("PIT exception\n"); - new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */ goto store_next; case POWERPC_EXCP_IO: /* IO error exception */ /* XXX: TODO */ @@ -2384,7 +2380,6 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp) "is not implemented yet !\n"); goto store_next; case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ - new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */ if (lpes1 == 0) /* XXX: check this */ new_msr |= (target_ulong)MSR_HVB; switch (excp_model) { @@ -2403,7 +2398,6 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp) } break; case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ - new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */ if (lpes1 == 0) /* XXX: check this */ new_msr |= (target_ulong)MSR_HVB; switch (excp_model) { @@ -2422,7 +2416,6 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp) } break; case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ - new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */ if (lpes1 == 0) /* XXX: check this */ new_msr |= (target_ulong)MSR_HVB; switch (excp_model) { @@ -2526,7 +2519,6 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp) "is not implemented yet !\n"); goto store_next; case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */ - new_msr &= ~((target_ulong)1 << MSR_RI); if (lpes1 == 0) new_msr |= (target_ulong)MSR_HVB; /* XXX: TODO */ @@ -2580,23 +2572,11 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp) /* If we disactivated any translation, flush TLBs */ if (new_msr & ((1 << MSR_IR) | (1 << MSR_DR))) tlb_flush(env, 1); - /* reload MSR with correct bits */ - new_msr &= ~((target_ulong)1 << MSR_EE); - new_msr &= ~((target_ulong)1 << MSR_PR); - new_msr &= ~((target_ulong)1 << MSR_FP); - new_msr &= ~((target_ulong)1 << MSR_FE0); - new_msr &= ~((target_ulong)1 << MSR_SE); - new_msr &= ~((target_ulong)1 << MSR_BE); - new_msr &= ~((target_ulong)1 << MSR_FE1); - new_msr &= ~((target_ulong)1 << MSR_IR); - new_msr &= ~((target_ulong)1 << MSR_DR); -#if 0 /* Fix this: not on all targets */ - new_msr &= ~((target_ulong)1 << MSR_PMM); -#endif - if (msr_ile) + + if (msr_ile) { new_msr |= (target_ulong)1 << MSR_LE; - else - new_msr &= ~((target_ulong)1 << MSR_LE); + } + /* Jump to handler */ vector = env->excp_vectors[excp]; if (vector == (target_ulong)-1ULL) { @@ -2607,14 +2587,12 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp) #if defined(TARGET_PPC64) if (excp_model == POWERPC_EXCP_BOOKE) { if (!msr_icm) { - new_msr &= ~((target_ulong)1 << MSR_CM); vector = (uint32_t)vector; } else { new_msr |= (target_ulong)1 << MSR_CM; } } else { if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) { - new_msr &= ~((target_ulong)1 << MSR_SF); vector = (uint32_t)vector; } else { new_msr |= (target_ulong)1 << MSR_SF;