From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jan Kiszka Subject: Re: VMX: Host NMI triggering on NMI vmexit Date: Mon, 22 Sep 2008 12:54:22 +0200 Message-ID: <48D7795E.5080002@siemens.com> References: <48CF97F1.9090004@siemens.com> <48D429B1.6090105@redhat.com> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-15 Content-Transfer-Encoding: 7bit Cc: "Yang, Sheng" , kvm-devel To: Avi Kivity Return-path: Received: from gecko.sbs.de ([194.138.37.40]:18318 "EHLO gecko.sbs.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752047AbYIVKyl (ORCPT ); Mon, 22 Sep 2008 06:54:41 -0400 In-Reply-To: <48D429B1.6090105@redhat.com> Sender: kvm-owner@vger.kernel.org List-ID: Avi Kivity wrote: > Jan Kiszka wrote: >> Sheng, >> >> out of curiosity: vmx_vcpu_run invokes 'int $2' to trigger a host NMI if >> the VM exited due to an external NMI event. According to Intel specs I >> have, software-triggered NMIs do not block hardware NMIs. So are we >> facing the risk to receive another NMI while running the first handler? >> Or will the VM be left with the hardware blocking logic armed? Or does >> Linux not care about NMI handler re-entrance? >> > > All good questions. Usually this doesn't happen since NMI sources are > far apart (oprofile, watchdog). > > Maybe the answer is to generate the local nmi via an IPI-to-self command > to the local apic. Going this way leaves me with a few questions: Will it be OK for the related mainainers to export the required service? And is it safe to assume VMX == LAPIC available and usable? However, this is how it would look like. Yet untested, /me has to replace his host kernel first... Jan --- arch/x86/kernel/genapic_64.c | 1 + arch/x86/kernel/ipi.c | 1 + arch/x86/kvm/vmx.c | 6 +++--- 3 files changed, 5 insertions(+), 3 deletions(-) Index: b/arch/x86/kernel/genapic_64.c =================================================================== --- a/arch/x86/kernel/genapic_64.c +++ b/arch/x86/kernel/genapic_64.c @@ -65,6 +65,7 @@ void send_IPI_self(int vector) { __send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL); } +EXPORT_SYMBOL_GPL(send_IPI_self); int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) { Index: b/arch/x86/kernel/ipi.c =================================================================== --- a/arch/x86/kernel/ipi.c +++ b/arch/x86/kernel/ipi.c @@ -77,6 +77,7 @@ void send_IPI_self(int vector) { __send_IPI_shortcut(APIC_DEST_SELF, vector); } +EXPORT_SYMBOL_GPL(send_IPI_self); /* * This is used to send an IPI with no shorthand notation (the destination is Index: b/arch/x86/kvm/vmx.c =================================================================== --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -2488,7 +2488,7 @@ static int handle_exception(struct kvm_v set_bit(irq / BITS_PER_LONG, &vcpu->arch.irq_summary); } - if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) /* nmi */ + if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR) return 1; /* already handled by vmx_vcpu_run() */ if (is_no_device(intr_info)) { @@ -3321,10 +3321,10 @@ static void vmx_vcpu_run(struct kvm_vcpu intr_info = vmcs_read32(VM_EXIT_INTR_INFO); /* We need to handle NMIs before interrupts are enabled */ - if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200 && + if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR && (intr_info & INTR_INFO_VALID_MASK)) { KVMTRACE_0D(NMI, vcpu, handler); - asm("int $2"); + send_IPI_self(APIC_DM_NMI); } vmx_complete_interrupts(vmx);