lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20090701141845.GW6760@one.firstfloor.org>
Date:	Wed, 1 Jul 2009 16:18:45 +0200
From:	Andi Kleen <andi@...stfloor.org>
To:	Avi Kivity <avi@...hat.com>
Cc:	Andi Kleen <andi@...stfloor.org>, Andi Kleen <ak@...ux.intel.com>,
	Greg KH <gregkh@...e.de>,
	Stefan Lippers-Hollmann <s.L-H@....de>,
	linux-kernel@...r.kernel.org, ying.huang@...el.com,
	stable@...nel.org
Subject: Re: patch kvm-add-vt-x-machine-check-support.patch added to	2.6.30-stable tree

On Wed, Jul 01, 2009 at 04:41:54PM +0300, Avi Kivity wrote:
> Should be in struct vmx_vcpu; otherwise ack.

Done

---

KVM: Add VT-x machine check support v4

VT-x needs an explicit MC vector intercept to handle machine checks in the 
hypervisor.

It also has a special option to catch machine checks that happen
during VT entry.

Do these interceptions and forward them to the Linux machine check
handler. Make it always look like user space is interrupted because
the machine check handler treats kernel/user space differently.

Thanks to Huang Ying and Jiang Yunhong for help and testing.

Cc: ying.huang@...el.com

v2: Handle machine checks still in interrupt off context
to avoid problems on preemptible kernels.
v3: Handle old style 32bit and make fully standalone

Signed-off-by: Andi Kleen <ak@...ux.intel.com>

---
 arch/x86/include/asm/kvm_host.h     |    2 +
 arch/x86/include/asm/mce.h          |    2 +
 arch/x86/include/asm/vmx.h          |    1 
 arch/x86/kernel/cpu/mcheck/mce_32.c |    1 
 arch/x86/kernel/cpu/mcheck/mce_64.c |    1 
 arch/x86/kvm/vmx.c                  |   49 +++++++++++++++++++++++++++++++++---
 6 files changed, 53 insertions(+), 3 deletions(-)

Index: linux-2.6.30-ak/arch/x86/include/asm/vmx.h
===================================================================
--- linux-2.6.30-ak.orig/arch/x86/include/asm/vmx.h
+++ linux-2.6.30-ak/arch/x86/include/asm/vmx.h
@@ -247,6 +247,7 @@ enum vmcs_field {
 #define EXIT_REASON_MSR_READ            31
 #define EXIT_REASON_MSR_WRITE           32
 #define EXIT_REASON_MWAIT_INSTRUCTION   36
+#define EXIT_REASON_MCE_DURING_VMENTRY	 41
 #define EXIT_REASON_TPR_BELOW_THRESHOLD 43
 #define EXIT_REASON_APIC_ACCESS         44
 #define EXIT_REASON_EPT_VIOLATION       48
Index: linux-2.6.30-ak/arch/x86/kvm/vmx.c
===================================================================
--- linux-2.6.30-ak.orig/arch/x86/kvm/vmx.c
+++ linux-2.6.30-ak/arch/x86/kvm/vmx.c
@@ -32,6 +32,7 @@
 #include <asm/desc.h>
 #include <asm/vmx.h>
 #include <asm/virtext.h>
+#include <asm/mce.h>
 
 #define __ex(x) __kvm_handle_fault_on_reboot(x)
 
@@ -97,6 +98,8 @@ struct vcpu_vmx {
 	int soft_vnmi_blocked;
 	ktime_t entry_time;
 	s64 vnmi_blocked_time;
+
+	u32 exit_reason;
 };
 
 static inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vcpu)
@@ -478,7 +481,7 @@ static void update_exception_bitmap(stru
 {
 	u32 eb;
 
-	eb = (1u << PF_VECTOR) | (1u << UD_VECTOR);
+	eb = (1u << PF_VECTOR) | (1u << UD_VECTOR) | (1u << MC_VECTOR);
 	if (!vcpu->fpu_active)
 		eb |= 1u << NM_VECTOR;
 	if (vcpu->guest_debug & KVM_GUESTDBG_ENABLE) {
@@ -2585,6 +2588,35 @@ static int handle_rmode_exception(struct
 	return 0;
 }
 
+/*
+ * Trigger machine check on the host. We assume all the MSRs are already set up
+ * by the CPU and that we still run on the same CPU as the MCE occurred on.
+ * We pass a fake environment to the machine check handler because we want
+ * the guest to be always treated like user space, no matter what context
+ * it used internally.
+ */
+static void kvm_machine_check(void)
+{
+#ifdef CONFIG_X86_MCE
+	struct pt_regs regs = {
+		.cs = 3, /* Fake ring 3 no matter what the guest ran on */
+		.flags = X86_EFLAGS_IF,
+	};
+
+#ifdef CONFIG_X86_64
+	do_machine_check(&regs, 0);
+#else
+	machine_check_vector(&regs, 0);
+#endif
+#endif
+}
+
+static int handle_machine_check(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+	/* already handled by vcpu_run */
+	return 1;
+}
+
 static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -2596,6 +2628,10 @@ static int handle_exception(struct kvm_v
 	vect_info = vmx->idt_vectoring_info;
 	intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
 
+	ex_no = intr_info & INTR_INFO_VECTOR_MASK;
+	if (ex_no == MC_VECTOR)
+		return handle_machine_check(vcpu, kvm_run);
+
 	if ((vect_info & VECTORING_INFO_VALID_MASK) &&
 						!is_page_fault(intr_info))
 		printk(KERN_ERR "%s: unexpected, vectoring info 0x%x "
@@ -2648,7 +2684,6 @@ static int handle_exception(struct kvm_v
 		return 1;
 	}
 
-	ex_no = intr_info & INTR_INFO_VECTOR_MASK;
 	switch (ex_no) {
 	case DB_VECTOR:
 		dr6 = vmcs_readl(EXIT_QUALIFICATION);
@@ -3150,6 +3185,7 @@ static int (*kvm_vmx_exit_handlers[])(st
 	[EXIT_REASON_WBINVD]                  = handle_wbinvd,
 	[EXIT_REASON_TASK_SWITCH]             = handle_task_switch,
 	[EXIT_REASON_EPT_VIOLATION]	      = handle_ept_violation,
+	[EXIT_REASON_MCE_DURING_VMENTRY]      = handle_machine_check,
 };
 
 static const int kvm_vmx_max_exit_handlers =
@@ -3161,8 +3197,8 @@ static const int kvm_vmx_max_exit_handle
  */
 static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 {
-	u32 exit_reason = vmcs_read32(VM_EXIT_REASON);
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
+	u32 exit_reason = vmx->exit_reason;
 	u32 vectoring_info = vmx->idt_vectoring_info;
 
 	KVMTRACE_3D(VMEXIT, vcpu, exit_reason, (u32)kvm_rip_read(vcpu),
@@ -3512,6 +3548,13 @@ static void vmx_vcpu_run(struct kvm_vcpu
 
 	intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
 
+	vmx->exit_reason = vmcs_read32(VM_EXIT_REASON);
+
+	/* Handle machine checks before interrupts are enabled */
+	if ((vmx->exit_reason == EXIT_REASON_MCE_DURING_VMENTRY) ||
+		(intr_info & INTR_INFO_VECTOR_MASK) == MC_VECTOR)
+		kvm_machine_check();
+
 	/* We need to handle NMIs before interrupts are enabled */
 	if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR &&
 	    (intr_info & INTR_INFO_VALID_MASK)) {
Index: linux-2.6.30-ak/arch/x86/include/asm/kvm_host.h
===================================================================
--- linux-2.6.30-ak.orig/arch/x86/include/asm/kvm_host.h
+++ linux-2.6.30-ak/arch/x86/include/asm/kvm_host.h
@@ -371,6 +371,8 @@ struct kvm_vcpu_arch {
 	unsigned long dr6;
 	unsigned long dr7;
 	unsigned long eff_db[KVM_NR_DB_REGS];
+
+	u32 exit_reason;
 };
 
 struct kvm_mem_alias {
Index: linux-2.6.30-ak/arch/x86/include/asm/mce.h
===================================================================
--- linux-2.6.30-ak.orig/arch/x86/include/asm/mce.h
+++ linux-2.6.30-ak/arch/x86/include/asm/mce.h
@@ -153,5 +153,7 @@ extern void mcheck_init(struct cpuinfo_x
 
 extern void (*mce_threshold_vector)(void);
 
+extern void (*machine_check_vector)(struct pt_regs *, long error_code);
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_X86_MCE_H */
Index: linux-2.6.30-ak/arch/x86/kernel/cpu/mcheck/mce_32.c
===================================================================
--- linux-2.6.30-ak.orig/arch/x86/kernel/cpu/mcheck/mce_32.c
+++ linux-2.6.30-ak/arch/x86/kernel/cpu/mcheck/mce_32.c
@@ -29,6 +29,7 @@ static void unexpected_machine_check(str
 
 /* Call the installed machine check handler for this CPU setup. */
 void (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check;
+EXPORT_SYMBOL_GPL(machine_check_vector);
 
 /* This has to be run for each processor */
 void mcheck_init(struct cpuinfo_x86 *c)
Index: linux-2.6.30-ak/arch/x86/kernel/cpu/mcheck/mce_64.c
===================================================================
--- linux-2.6.30-ak.orig/arch/x86/kernel/cpu/mcheck/mce_64.c
+++ linux-2.6.30-ak/arch/x86/kernel/cpu/mcheck/mce_64.c
@@ -420,6 +420,7 @@ void do_machine_check(struct pt_regs * r
  out2:
 	atomic_dec(&mce_entry);
 }
+EXPORT_SYMBOL_GPL(do_machine_check);
 
 #ifdef CONFIG_X86_MCE_INTEL
 /***

-- 
ak@...ux.intel.com -- Speaking for myself only.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ