aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSheng Yang <sheng.yang@intel.com>2008-03-28 01:18:56 -0400
committerAvi Kivity <avi@qumranet.com>2008-04-27 05:00:52 -0400
commit25c5f225beda4fbea878ed8b6203ab4ecc7de2d1 (patch)
treeb15dc6e9a311c556a9c5ed1ccbc0ed0830d24b23
parente976a2b997fc4ad70ccc53acfe62811c4aaec851 (diff)
KVM: VMX: Enable MSR Bitmap feature
MSR Bitmap controls whether the accessing of an MSR causes VM Exit. Eliminating exits on automatically saved and restored MSRs yields a small performance gain. Signed-off-by: Sheng Yang <sheng.yang@intel.com> Signed-off-by: Avi Kivity <avi@qumranet.com>
-rw-r--r--arch/x86/kvm/vmx.c67
1 files changed, 60 insertions, 7 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index cbca46acfac3..87eee7a7f16e 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -91,6 +91,7 @@ static DEFINE_PER_CPU(struct vmcs *, current_vmcs);
91 91
92static struct page *vmx_io_bitmap_a; 92static struct page *vmx_io_bitmap_a;
93static struct page *vmx_io_bitmap_b; 93static struct page *vmx_io_bitmap_b;
94static struct page *vmx_msr_bitmap;
94 95
95static DECLARE_BITMAP(vmx_vpid_bitmap, VMX_NR_VPIDS); 96static DECLARE_BITMAP(vmx_vpid_bitmap, VMX_NR_VPIDS);
96static DEFINE_SPINLOCK(vmx_vpid_lock); 97static DEFINE_SPINLOCK(vmx_vpid_lock);
@@ -185,6 +186,11 @@ static inline int is_external_interrupt(u32 intr_info)
185 == (INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK); 186 == (INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK);
186} 187}
187 188
189static inline int cpu_has_vmx_msr_bitmap(void)
190{
191 return (vmcs_config.cpu_based_exec_ctrl & CPU_BASED_USE_MSR_BITMAPS);
192}
193
188static inline int cpu_has_vmx_tpr_shadow(void) 194static inline int cpu_has_vmx_tpr_shadow(void)
189{ 195{
190 return (vmcs_config.cpu_based_exec_ctrl & CPU_BASED_TPR_SHADOW); 196 return (vmcs_config.cpu_based_exec_ctrl & CPU_BASED_TPR_SHADOW);
@@ -1001,6 +1007,7 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
1001 CPU_BASED_MOV_DR_EXITING | 1007 CPU_BASED_MOV_DR_EXITING |
1002 CPU_BASED_USE_TSC_OFFSETING; 1008 CPU_BASED_USE_TSC_OFFSETING;
1003 opt = CPU_BASED_TPR_SHADOW | 1009 opt = CPU_BASED_TPR_SHADOW |
1010 CPU_BASED_USE_MSR_BITMAPS |
1004 CPU_BASED_ACTIVATE_SECONDARY_CONTROLS; 1011 CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
1005 if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS, 1012 if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS,
1006 &_cpu_based_exec_control) < 0) 1013 &_cpu_based_exec_control) < 0)
@@ -1575,6 +1582,30 @@ static void allocate_vpid(struct vcpu_vmx *vmx)
1575 spin_unlock(&vmx_vpid_lock); 1582 spin_unlock(&vmx_vpid_lock);
1576} 1583}
1577 1584
1585void vmx_disable_intercept_for_msr(struct page *msr_bitmap, u32 msr)
1586{
1587 void *va;
1588
1589 if (!cpu_has_vmx_msr_bitmap())
1590 return;
1591
1592 /*
1593 * See Intel PRM Vol. 3, 20.6.9 (MSR-Bitmap Address). Early manuals
1594 * have the write-low and read-high bitmap offsets the wrong way round.
1595 * We can control MSRs 0x00000000-0x00001fff and 0xc0000000-0xc0001fff.
1596 */
1597 va = kmap(msr_bitmap);
1598 if (msr <= 0x1fff) {
1599 __clear_bit(msr, va + 0x000); /* read-low */
1600 __clear_bit(msr, va + 0x800); /* write-low */
1601 } else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) {
1602 msr &= 0x1fff;
1603 __clear_bit(msr, va + 0x400); /* read-high */
1604 __clear_bit(msr, va + 0xc00); /* write-high */
1605 }
1606 kunmap(msr_bitmap);
1607}
1608
1578/* 1609/*
1579 * Sets up the vmcs for emulated real mode. 1610 * Sets up the vmcs for emulated real mode.
1580 */ 1611 */
@@ -1592,6 +1623,9 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
1592 vmcs_write64(IO_BITMAP_A, page_to_phys(vmx_io_bitmap_a)); 1623 vmcs_write64(IO_BITMAP_A, page_to_phys(vmx_io_bitmap_a));
1593 vmcs_write64(IO_BITMAP_B, page_to_phys(vmx_io_bitmap_b)); 1624 vmcs_write64(IO_BITMAP_B, page_to_phys(vmx_io_bitmap_b));
1594 1625
1626 if (cpu_has_vmx_msr_bitmap())
1627 vmcs_write64(MSR_BITMAP, page_to_phys(vmx_msr_bitmap));
1628
1595 vmcs_write64(VMCS_LINK_POINTER, -1ull); /* 22.3.1.5 */ 1629 vmcs_write64(VMCS_LINK_POINTER, -1ull); /* 22.3.1.5 */
1596 1630
1597 /* Control */ 1631 /* Control */
@@ -2728,7 +2762,7 @@ static struct kvm_x86_ops vmx_x86_ops = {
2728 2762
2729static int __init vmx_init(void) 2763static int __init vmx_init(void)
2730{ 2764{
2731 void *iova; 2765 void *va;
2732 int r; 2766 int r;
2733 2767
2734 vmx_io_bitmap_a = alloc_page(GFP_KERNEL | __GFP_HIGHMEM); 2768 vmx_io_bitmap_a = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
@@ -2741,30 +2775,48 @@ static int __init vmx_init(void)
2741 goto out; 2775 goto out;
2742 } 2776 }
2743 2777
2778 vmx_msr_bitmap = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
2779 if (!vmx_msr_bitmap) {
2780 r = -ENOMEM;
2781 goto out1;
2782 }
2783
2744 /* 2784 /*
2745 * Allow direct access to the PC debug port (it is often used for I/O 2785 * Allow direct access to the PC debug port (it is often used for I/O
2746 * delays, but the vmexits simply slow things down). 2786 * delays, but the vmexits simply slow things down).
2747 */ 2787 */
2748 iova = kmap(vmx_io_bitmap_a); 2788 va = kmap(vmx_io_bitmap_a);
2749 memset(iova, 0xff, PAGE_SIZE); 2789 memset(va, 0xff, PAGE_SIZE);
2750 clear_bit(0x80, iova); 2790 clear_bit(0x80, va);
2751 kunmap(vmx_io_bitmap_a); 2791 kunmap(vmx_io_bitmap_a);
2752 2792
2753 iova = kmap(vmx_io_bitmap_b); 2793 va = kmap(vmx_io_bitmap_b);
2754 memset(iova, 0xff, PAGE_SIZE); 2794 memset(va, 0xff, PAGE_SIZE);
2755 kunmap(vmx_io_bitmap_b); 2795 kunmap(vmx_io_bitmap_b);
2756 2796
2797 va = kmap(vmx_msr_bitmap);
2798 memset(va, 0xff, PAGE_SIZE);
2799 kunmap(vmx_msr_bitmap);
2800
2757 set_bit(0, vmx_vpid_bitmap); /* 0 is reserved for host */ 2801 set_bit(0, vmx_vpid_bitmap); /* 0 is reserved for host */
2758 2802
2759 r = kvm_init(&vmx_x86_ops, sizeof(struct vcpu_vmx), THIS_MODULE); 2803 r = kvm_init(&vmx_x86_ops, sizeof(struct vcpu_vmx), THIS_MODULE);
2760 if (r) 2804 if (r)
2761 goto out1; 2805 goto out2;
2806
2807 vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_FS_BASE);
2808 vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_GS_BASE);
2809 vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_IA32_SYSENTER_CS);
2810 vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_IA32_SYSENTER_ESP);
2811 vmx_disable_intercept_for_msr(vmx_msr_bitmap, MSR_IA32_SYSENTER_EIP);
2762 2812
2763 if (bypass_guest_pf) 2813 if (bypass_guest_pf)
2764 kvm_mmu_set_nonpresent_ptes(~0xffeull, 0ull); 2814 kvm_mmu_set_nonpresent_ptes(~0xffeull, 0ull);
2765 2815
2766 return 0; 2816 return 0;
2767 2817
2818out2:
2819 __free_page(vmx_msr_bitmap);
2768out1: 2820out1:
2769 __free_page(vmx_io_bitmap_b); 2821 __free_page(vmx_io_bitmap_b);
2770out: 2822out:
@@ -2774,6 +2826,7 @@ out:
2774 2826
2775static void __exit vmx_exit(void) 2827static void __exit vmx_exit(void)
2776{ 2828{
2829 __free_page(vmx_msr_bitmap);
2777 __free_page(vmx_io_bitmap_b); 2830 __free_page(vmx_io_bitmap_b);
2778 __free_page(vmx_io_bitmap_a); 2831 __free_page(vmx_io_bitmap_a);
2779 2832