public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
From: Eduardo Habkost <ehabkost@redhat.com>
To: Avi Kivity <avi@redhat.com>, Ingo Molnar <mingo@elte.hu>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>,
	Simon Horman <horms@verge.net.au>, Andrew Morton <akpm@osdl.org>,
	Vivek Goyal <vgoyal@redhat.com>, Haren Myneni <hbabu@us.ibm.com>,
	Andrey Borzenkov <arvidjaar@mail.ru>,
	mingo@redhat.com, "Rafael J. Wysocki" <rjw@sisk.pl>,
	Zachary Amsden <zach@vmware.com>,
	kexec@lists.infradead.org, kvm@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	Eduardo Habkost <ehabkost@redhat.com>
Subject: [PATCH 12/12] x86: disable VMX on all CPUs on reboot
Date: Mon, 17 Nov 2008 19:03:24 -0200	[thread overview]
Message-ID: <1226955804-16802-13-git-send-email-ehabkost@redhat.com> (raw)
In-Reply-To: <1226955804-16802-1-git-send-email-ehabkost@redhat.com>

On emergency_restart, we may need to use an NMI to disable virtualization
on all CPUs. We do that using nmi_shootdown_cpus() if VMX is enabled.

Note: With this patch, we will run the NMI stuff only when the CPU where
emergency_restart() was called has VMX enabled. This should work on most
cases because KVM enables VMX on all CPUs, but we may miss the small
window where KVM is doing that. Also, I don't know if all code using
VMX out there always enable VMX on all CPUs like KVM does. We have two
other alternatives for that:

a) Have an API that all code that enables VMX on any CPU should use
   to tell the kernel core that it is going to enable VMX on the CPUs.
b) Always call nmi_shootdown_cpus() if the CPU supports VMX. This is
   a bit intrusive and more risky, as it would run nmi_shootdown_cpus()
   on emergency_reboot() even on systems where virtualization is never
   enabled.


Finding a proper point to hook the nmi_shootdown_cpus() call isn't
trivial, as the non-emergency machine_restart() (that doesn't need the
NMI tricks) uses machine_emergency_restart() directly.

The solution to make this work without adding a new function or argument
to machine_ops was setting a 'reboot_emergency' flag that tells if
native_machine_emergency_restart() needs to do the virt cleanup or not.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 arch/x86/kernel/reboot.c |   63 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 6f05a28..a5f8c09 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -12,6 +12,7 @@
 #include <asm/proto.h>
 #include <asm/reboot_fixups.h>
 #include <asm/reboot.h>
+#include <asm/virtext.h>
 
 #ifdef CONFIG_X86_32
 # include <linux/dmi.h>
@@ -39,6 +40,13 @@ int reboot_force;
 static int reboot_cpu = -1;
 #endif
 
+/* This is set if we need to go through the 'emergency' path.
+ * When machine_emergency_restart() is called, we may be on
+ * an inconsistent state and won't be able to do a clean cleanup
+ */
+static int reboot_emergency;
+
+
 /* This is set by the PCI code if either type 1 or type 2 PCI is detected */
 bool port_cf9_safe = false;
 
@@ -359,6 +367,48 @@ static inline void kb_wait(void)
 	}
 }
 
+static void vmxoff_nmi(int cpu, struct die_args *args)
+{
+	cpu_emergency_vmxoff();
+}
+
+/* Use NMIs as IPIs to tell all CPUs to disable virtualization
+ */
+static void emergency_vmx_disable_all(void)
+{
+	/* Just make sure we won't change CPUs while doing this */
+	local_irq_disable();
+
+	/* We need to disable VMX on all CPUs before rebooting, otherwise
+	 * we risk hanging up the machine, because the CPU ignore INIT
+	 * signals when VMX is enabled.
+	 *
+	 * We can't take any locks and we may be on an inconsistent
+	 * state, so we use NMIs as IPIs to tell the other CPUs to disable
+	 * VMX and halt.
+	 * 
+	 * For safety, we will avoid running the nmi_shootdown_cpus()
+	 * stuff unnecessarily, but we don't have a way to check
+	 * if other CPUs have VMX enabled. So we will call it only if the
+	 * CPU we are running on has VMX enabled.
+	 *
+	 * We will miss cases where VMX is not enabled on all CPUs. This
+	 * shouldn't do much harm because KVM always enable VMX on all
+	 * CPUs anyway. But we can miss it on the small window where KVM
+	 * is still enabling VMX.
+	 */
+	if (cpu_has_vmx() && cpu_vmx_enabled()) {
+		/* Disable VMX on this CPU.
+		 */
+		cpu_vmxoff();
+
+		/* Halt and disable VMX on the other CPUs */
+		nmi_shootdown_cpus(vmxoff_nmi);
+
+	}
+}
+
+
 void __attribute__((weak)) mach_reboot_fixups(void)
 {
 }
@@ -367,6 +417,9 @@ static void native_machine_emergency_restart(void)
 {
 	int i;
 
+	if (reboot_emergency)
+		emergency_vmx_disable_all();
+
 	/* Tell the BIOS if we want cold or warm reboot */
 	*((unsigned short *)__va(0x472)) = reboot_mode;
 
@@ -473,13 +526,19 @@ void native_machine_shutdown(void)
 #endif
 }
 
+static void __machine_emergency_restart(int emergency)
+{
+	reboot_emergency = emergency;
+	machine_ops.emergency_restart();
+}
+
 static void native_machine_restart(char *__unused)
 {
 	printk("machine restart\n");
 
 	if (!reboot_force)
 		machine_shutdown();
-	machine_emergency_restart();
+	__machine_emergency_restart(0);
 }
 
 static void native_machine_halt(void)
@@ -523,7 +582,7 @@ void machine_shutdown(void)
 
 void machine_emergency_restart(void)
 {
-	machine_ops.emergency_restart();
+	__machine_emergency_restart(1);
 }
 
 void machine_restart(char *cmd)
-- 
1.5.5.GIT


  parent reply	other threads:[~2008-11-17 21:04 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-11-17 21:03 [PATCH 00/12] x86: disable virt on kdump and emergency_restart (v4) Eduardo Habkost
2008-11-17 21:03 ` [PATCH 07/12] x86: cpu_emergency_vmxoff() function Eduardo Habkost
2008-11-17 21:03 ` [PATCH 09/12] kvm: svm: move svm_hardware_disable() code to asm/virtext.h Eduardo Habkost
2008-11-17 21:03 ` Eduardo Habkost [this message]
     [not found] ` <1226955804-16802-1-git-send-email-ehabkost-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2008-11-17 21:03   ` [PATCH 01/12] kvm: vmx: move vmx.h to include/asm Eduardo Habkost
2008-11-17 21:03   ` [PATCH 02/12] kvm: svm: move svm.h " Eduardo Habkost
2008-11-17 21:03   ` [PATCH 03/12] kvm: vmx: move ASM_VMX_* definitions from asm/kvm_host.h to asm/vmx.h Eduardo Habkost
2008-11-17 21:03   ` [PATCH 04/12] kvm: vmx: move cpu_has_kvm_support() to an inline on asm/virtext.h Eduardo Habkost
2008-11-17 21:03   ` [PATCH 05/12] x86: asm/virtext.h: add cpu_vmxoff() inline function Eduardo Habkost
2008-11-17 21:03   ` [PATCH 06/12] kvm: vmx: extract kvm_cpu_vmxoff() from hardware_disable() Eduardo Habkost
2008-11-17 21:03   ` [PATCH 08/12] kvm: svm: move has_svm() code to asm/virtext.h Eduardo Habkost
2008-11-17 21:03   ` [PATCH 10/12] x86: cpu_emergency_svm_disable() function Eduardo Habkost
2008-11-17 21:03   ` [PATCH 11/12] kdump: forcibly disable VMX and SVM on machine_crash_shutdown() Eduardo Habkost
2008-11-18  8:15   ` [PATCH 00/12] x86: disable virt on kdump and emergency_restart (v4) Ingo Molnar
     [not found]     ` <20081118081501.GF17838-X9Un+BFzKDI@public.gmane.org>
2008-11-21 16:07       ` Avi Kivity
     [not found]         ` <4926DCC8.1040500-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2008-11-21 16:18           ` Ingo Molnar
2008-11-24 14:58           ` Eduardo Habkost

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1226955804-16802-13-git-send-email-ehabkost@redhat.com \
    --to=ehabkost@redhat.com \
    --cc=akpm@osdl.org \
    --cc=arvidjaar@mail.ru \
    --cc=avi@redhat.com \
    --cc=ebiederm@xmission.com \
    --cc=hbabu@us.ibm.com \
    --cc=horms@verge.net.au \
    --cc=kexec@lists.infradead.org \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=mingo@redhat.com \
    --cc=rjw@sisk.pl \
    --cc=vgoyal@redhat.com \
    --cc=zach@vmware.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox