From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1JJajR-000372-4s for qemu-devel@nongnu.org; Mon, 28 Jan 2008 15:37:29 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1JJajP-00035O-K4 for qemu-devel@nongnu.org; Mon, 28 Jan 2008 15:37:28 -0500 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1JJajP-00035H-9g for qemu-devel@nongnu.org; Mon, 28 Jan 2008 15:37:27 -0500 Received: from fmmailgate02.web.de ([217.72.192.227]) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1JJajO-0003kL-Op for qemu-devel@nongnu.org; Mon, 28 Jan 2008 15:37:27 -0500 Received: from smtp07.web.de (fmsmtp07.dlan.cinetic.de [172.20.5.215]) by fmmailgate02.web.de (Postfix) with ESMTP id 49381CD70193 for ; Mon, 28 Jan 2008 21:37:26 +0100 (CET) Received: from [88.65.245.10] (helo=[192.168.1.198]) by smtp07.web.de with asmtp (TLSv1:AES256-SHA:256) (WEB.DE 4.109 #226) id 1JJajN-0002AQ-00 for qemu-devel@nongnu.org; Mon, 28 Jan 2008 21:37:26 +0100 Message-ID: <479E3D05.6050002@web.de> Date: Mon, 28 Jan 2008 21:37:25 +0100 From: Jan Kiszka MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-15 Sender: jan.kiszka@web.de Content-Transfer-Encoding: quoted-printable Subject: [Qemu-devel] [PATCH] APIC: add NMI and SMI IPI support Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org While testing KGDB (yeah, it actually seem to make it into mainline!) under QEMU, I failed to get it running in SMP mode. Reason: NMI IPIs are not correctly handled by QEMU's emulated APIC. To overcome this, the patch below introduces a new interruption request, CPU_INTERRUPT_NMI, so that a VCPU can cleanly send this special interrupt to other VCPUs. It also introduces HF_NMI_MASK which shall ensure that NMIs are not recursively triggered, but I must confess that this particular property was not really tested yet. CPU_INTERRUPT_NMI is then trivially exploited by apic_bus_deliver to send out both NMIs and (for the sake of completeness - it's untested as well SMIs). With this patch applied, I'm finally able to run (and potentially debug) KGDB for Linux SMP guests. Jan --- cpu-all.h | 1 + cpu-exec.c | 6 ++++++ hw/apic.c | 8 +++++++- target-i386/cpu.h | 2 ++ target-i386/helper.c | 2 ++ 5 files changed, 18 insertions(+), 1 deletion(-) Index: b/hw/apic.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- a/hw/apic.c +++ b/hw/apic.c @@ -216,8 +216,14 @@ static void apic_bus_deliver(const uint3 break; =20 case APIC_DM_SMI: + foreach_apic(apic_iter, deliver_bitmask, + cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_SMI) ); + return; + case APIC_DM_NMI: - break; + foreach_apic(apic_iter, deliver_bitmask, + cpu_interrupt(apic_iter->cpu_env, CPU_INTERRUPT_NMI) ); + return; =20 case APIC_DM_INIT: /* normal INIT IPI sent to processors */ Index: b/cpu-all.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- a/cpu-all.h +++ b/cpu-all.h @@ -748,6 +748,7 @@ extern int code_copy_enabled; #define CPU_INTERRUPT_SMI 0x40 /* (x86 only) SMI interrupt pending */ #define CPU_INTERRUPT_DEBUG 0x80 /* Debug event occured. */ #define CPU_INTERRUPT_VIRQ 0x100 /* virtual interrupt pending. */ +#define CPU_INTERRUPT_NMI 0x200 /* NMI pending. */ =20 void cpu_interrupt(CPUState *s, int mask); void cpu_reset_interrupt(CPUState *env, int mask); Index: b/cpu-exec.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- a/cpu-exec.c +++ b/cpu-exec.c @@ -505,6 +505,12 @@ int cpu_exec(CPUState *env1) env->interrupt_request &=3D ~CPU_INTERRUPT_SMI; do_smm_enter(); BREAK_CHAIN; + } else if ((interrupt_request & CPU_INTERRUPT_NMI) &= & + !(env->hflags & HF_NMI_MASK)) { + env->interrupt_request &=3D ~CPU_INTERRUPT_NMI; + env->hflags |=3D HF_NMI_MASK; + do_interrupt(EXCP02_NMI, 0, 0, 0, 1); + BREAK_CHAIN; } else if ((interrupt_request & CPU_INTERRUPT_HARD) = && (env->eflags & IF_MASK || env->hflags & HF_HIF_M= ASK) && !(env->hflags & HF_INHIBIT_IRQ_MASK)) { Index: b/target-i386/cpu.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -148,6 +148,7 @@ #define HF_SMM_SHIFT 19 /* CPU in SMM mode */ #define HF_GIF_SHIFT 20 /* if set CPU takes interrupts */ #define HF_HIF_SHIFT 21 /* shadow copy of IF_MASK when in SVM */ +#define HF_NMI_SHIFT 22 /* CPU serving NMI */ =20 #define HF_CPL_MASK (3 << HF_CPL_SHIFT) #define HF_SOFTMMU_MASK (1 << HF_SOFTMMU_SHIFT) @@ -167,6 +168,7 @@ #define HF_SMM_MASK (1 << HF_SMM_SHIFT) #define HF_GIF_MASK (1 << HF_GIF_SHIFT) #define HF_HIF_MASK (1 << HF_HIF_SHIFT) +#define HF_NMI_MASK (1 << HF_NMI_SHIFT) =20 #define CR0_PE_MASK (1 << 0) #define CR0_MP_MASK (1 << 1) Index: b/target-i386/helper.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -2382,6 +2382,7 @@ void helper_iret_real(int shift) if (shift =3D=3D 0) eflags_mask &=3D 0xffff; load_eflags(new_eflags, eflags_mask); + env->hflags &=3D ~HF_NMI_MASK; } =20 static inline void validate_seg(int seg_reg, int cpl) @@ -2633,6 +2634,7 @@ void helper_iret_protected(int shift, in } else { helper_ret_protected(shift, 1, 0); } + env->hflags &=3D ~HF_NMI_MASK; #ifdef USE_KQEMU if (kqemu_is_ok(env)) { CC_OP =3D CC_OP_EFLAGS;