Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 340e01248478ba8b78a6d4d1809b1eff > files > 489

kvm-83-270.el5_11.src.rpm

From 45855ad8d98a0860d768cd4b34edcf3b7eefe582 Mon Sep 17 00:00:00 2001
From: Eduardo Habkost <ehabkost@redhat.com>
Date: Mon, 21 Sep 2009 14:25:20 -0300
Subject: [PATCH 3/3] KVM: VMX: Don't intercept MSR_KERNEL_GS_BASE (v2)

RH-Author: Eduardo Habkost <ehabkost@redhat.com>
Message-id: <20090918183736.GH3348@blackpad.lan.raisama.net>
Patchwork-id: 3454
O-Subject: [PATCH] KVM: VMX: Don't intercept MSR_KERNEL_GS_BASE (v2)
Bugzilla: 488130
RH-Acked-by: Chris Wright <chrisw@redhat.com>
RH-Acked-by: Juan Quintela <quintela@redhat.com>
RH-Acked-by: Gleb Natapov <gleb@redhat.com>
RH-Acked-by: Andrea Arcangeli <aarcange@redhat.com>

On Thu, Sep 17, 2009 at 08:15:22PM -0300, Eduardo Habkost wrote:
> On Fri, Sep 04, 2009 at 02:03:42PM -0300, Eduardo Habkost wrote:
> > (backport of upstream commit 5897297bc228fc3c85fdc421fd5c487f9a99821a)
> >
> > This was removed from the RHEL-5.4 queue a long time ago and postponed for
> > RHEL-5.5. Conclusion of the previous discussion was that we needed some
> > performance gain measurements.
>
>
> (late) self-NACK: this is breaking here. I am getting this when starting a guest:
>
> kvm_run: failed entry, reason 7
<snip>

Fixed patch below.

Interdiff:

> diff -u b/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
> --- b/arch/x86/kvm/vmx.c
> +++ b/arch/x86/kvm/vmx.c
> @@ -868,7 +868,7 @@
>                 else
>                         msr_bitmap = vmx_msr_bitmap_legacy;
>
> -		vmcs_write64(MSR_BITMAP, __pa(msr_bitmap));
> +		vmcs_write64(MSR_BITMAP, page_to_phys(msr_bitmap));
>         }
>  }

---------------------
From: Eduardo Habkost <ehabkost@redhat.com>
Date: Thu, 17 Sep 2009 14:06:06 -0300
Subject: [PATCH] KVM: VMX: Don't intercept MSR_KERNEL_GS_BASE (v2)

(backport of upstream commit 5897297bc228fc3c85fdc421fd5c487f9a99821a)

[ehabkost v2: fix backport to use page_to_phys() instead of __pa() when setting
              the guest MSR bitmap]

Upstream commit message:

    From: Avi Kivity <avi@redhat.com>

    Windows 2008 accesses this MSR often on context switch intensive workloads;
    since we run in guest context with the guest MSR value loaded (so swapgs can
    work correctly), we can simply disable interception of rdmsr/wrmsr for this
    MSR.

    A complication occurs since in legacy mode, we run with the host MSR value
    loaded. In this case we enable interception.  This means we need two MSR
    bitmaps, one for legacy mode and one for long mode.

    Signed-off-by: Avi Kivity <avi@redhat.com>

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
RH-Upstream-status: applied(kvm/master)
Bugzilla: 488130
---
 arch/x86/kvm/vmx.c |   62 +++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 47 insertions(+), 15 deletions(-)

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 arch/x86/kvm/vmx.c |   62 +++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 47 insertions(+), 15 deletions(-)

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 arch/x86/kvm/vmx.c |   62 +++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 47 insertions(+), 15 deletions(-)

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 6a553d3..45119d2 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -112,7 +112,8 @@ static DEFINE_PER_CPU(struct list_head, vcpus_on_cpu);
 
 static struct page *vmx_io_bitmap_a;
 static struct page *vmx_io_bitmap_b;
-static struct page *vmx_msr_bitmap;
+static struct page *vmx_msr_bitmap_legacy;
+static struct page *vmx_msr_bitmap_longmode;
 
 static DECLARE_BITMAP(vmx_vpid_bitmap, VMX_NR_VPIDS);
 static DEFINE_SPINLOCK(vmx_vpid_lock);
@@ -824,6 +825,7 @@ static void move_msr_up(struct vcpu_vmx *vmx, int from, int to)
 static void setup_msrs(struct vcpu_vmx *vmx)
 {
 	int save_nmsrs;
+	struct page *msr_bitmap;
 
 	vmx_load_host_state(vmx);
 	save_nmsrs = 0;
@@ -859,6 +861,15 @@ static void setup_msrs(struct vcpu_vmx *vmx)
 		__find_msr_index(vmx, MSR_KERNEL_GS_BASE);
 #endif
 	vmx->msr_offset_efer = __find_msr_index(vmx, MSR_EFER);
+
+	if (cpu_has_vmx_msr_bitmap()) {
+		if (is_long_mode(&vmx->vcpu))
+			msr_bitmap = vmx_msr_bitmap_longmode;
+		else
+			msr_bitmap = vmx_msr_bitmap_legacy;
+
+		vmcs_write64(MSR_BITMAP, page_to_phys(msr_bitmap));
+	}
 }
 
 /*
@@ -2090,7 +2101,7 @@ static void allocate_vpid(struct vcpu_vmx *vmx)
 	spin_unlock(&vmx_vpid_lock);
 }
 
-static void vmx_disable_intercept_for_msr(struct page *msr_bitmap, u32 msr)
+static void __vmx_disable_intercept_for_msr(struct page *msr_bitmap, u32 msr)
 {
 	void *va;
 
@@ -2114,6 +2125,13 @@ static void vmx_disable_intercept_for_msr(struct page *msr_bitmap, u32 msr)
 	kunmap(msr_bitmap);
 }
 
+static void vmx_disable_intercept_for_msr(u32 msr, bool longmode_only)
+{
+	if (!longmode_only)
+		__vmx_disable_intercept_for_msr(vmx_msr_bitmap_legacy, msr);
+	__vmx_disable_intercept_for_msr(vmx_msr_bitmap_longmode, msr);
+}
+
 /*
  * Sets up the vmcs for emulated real mode.
  */
@@ -2133,7 +2151,7 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
 	vmcs_write64(IO_BITMAP_B, page_to_phys(vmx_io_bitmap_b));
 
 	if (cpu_has_vmx_msr_bitmap())
-		vmcs_write64(MSR_BITMAP, page_to_phys(vmx_msr_bitmap));
+		vmcs_write64(MSR_BITMAP, page_to_phys(vmx_msr_bitmap_legacy));
 
 	vmcs_write64(VMCS_LINK_POINTER, -1ull); /* 22.3.1.5 */
 
@@ -3663,12 +3681,18 @@ static int __init vmx_init(void)
 		goto out;
 	}
 
-	vmx_msr_bitmap = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
-	if (!vmx_msr_bitmap) {
+	vmx_msr_bitmap_legacy = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
+	if (!vmx_msr_bitmap_legacy) {
 		r = -ENOMEM;
 		goto out1;
 	}
 
+	vmx_msr_bitmap_longmode = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
+	if (!vmx_msr_bitmap_longmode) {
+		r = -ENOMEM;
+		goto out2;
+	}
+
 	/*
 	 * Allow direct access to the PC debug port (it is often used for I/O
 	 * delays, but the vmexits simply slow things down).
@@ -3682,21 +3706,26 @@ static int __init vmx_init(void)
 	memset(va, 0xff, PAGE_SIZE);
 	kunmap(vmx_io_bitmap_b);
 
-	va = kmap(vmx_msr_bitmap);
+	va = kmap(vmx_msr_bitmap_legacy);
 	memset(va, 0xff, PAGE_SIZE);
-	kunmap(vmx_msr_bitmap);
+	kunmap(vmx_msr_bitmap_legacy);
+
+	va = kmap(vmx_msr_bitmap_longmode);
+	memset(va, 0xff, PAGE_SIZE);
+	kunmap(vmx_msr_bitmap_longmode);
 
 	set_bit(0, vmx_vpid_bitmap); /* 0 is reserved for host */
 
 	r = kvm_init(&vmx_x86_ops, sizeof(struct vcpu_vmx), THIS_MODULE);
 	if (r)
-		goto out2;
+		goto out3;
 
-	vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_FS_BASE);
-	vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_GS_BASE);
-	vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_IA32_SYSENTER_CS);
-	vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_IA32_SYSENTER_ESP);
-	vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_IA32_SYSENTER_EIP);
+	vmx_disable_intercept_for_msr(MSR_FS_BASE, false);
+	vmx_disable_intercept_for_msr(MSR_GS_BASE, false);
+	vmx_disable_intercept_for_msr(MSR_KERNEL_GS_BASE, true);
+	vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_CS, false);
+	vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_ESP, false);
+	vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP, false);
 
 	if (vm_need_ept()) {
 		bypass_guest_pf = 0;
@@ -3716,8 +3745,10 @@ static int __init vmx_init(void)
 
 	return 0;
 
+out3:
+	__free_page(vmx_msr_bitmap_longmode);
 out2:
-	__free_page(vmx_msr_bitmap);
+	__free_page(vmx_msr_bitmap_legacy);
 out1:
 	__free_page(vmx_io_bitmap_b);
 out:
@@ -3727,7 +3758,8 @@ out:
 
 static void __exit vmx_exit(void)
 {
-	__free_page(vmx_msr_bitmap);
+	__free_page(vmx_msr_bitmap_legacy);
+	__free_page(vmx_msr_bitmap_longmode);
 	__free_page(vmx_io_bitmap_b);
 	__free_page(vmx_io_bitmap_a);
 
-- 
1.6.3.rc4.29.g8146