diff options
| author | Sheng Yang <sheng.yang@intel.com> | 2008-03-28 01:18:56 -0400 |
|---|---|---|
| committer | Avi Kivity <avi@qumranet.com> | 2008-04-27 05:00:52 -0400 |
| commit | 25c5f225beda4fbea878ed8b6203ab4ecc7de2d1 (patch) | |
| tree | b15dc6e9a311c556a9c5ed1ccbc0ed0830d24b23 | |
| parent | e976a2b997fc4ad70ccc53acfe62811c4aaec851 (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.c | 67 |
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 | ||
| 92 | static struct page *vmx_io_bitmap_a; | 92 | static struct page *vmx_io_bitmap_a; |
| 93 | static struct page *vmx_io_bitmap_b; | 93 | static struct page *vmx_io_bitmap_b; |
| 94 | static struct page *vmx_msr_bitmap; | ||
| 94 | 95 | ||
| 95 | static DECLARE_BITMAP(vmx_vpid_bitmap, VMX_NR_VPIDS); | 96 | static DECLARE_BITMAP(vmx_vpid_bitmap, VMX_NR_VPIDS); |
| 96 | static DEFINE_SPINLOCK(vmx_vpid_lock); | 97 | static 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 | ||
| 189 | static inline int cpu_has_vmx_msr_bitmap(void) | ||
| 190 | { | ||
| 191 | return (vmcs_config.cpu_based_exec_ctrl & CPU_BASED_USE_MSR_BITMAPS); | ||
| 192 | } | ||
| 193 | |||
| 188 | static inline int cpu_has_vmx_tpr_shadow(void) | 194 | static 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 | ||
| 1585 | void 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 | ||
| 2729 | static int __init vmx_init(void) | 2763 | static 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 | ||
| 2818 | out2: | ||
| 2819 | __free_page(vmx_msr_bitmap); | ||
| 2768 | out1: | 2820 | out1: |
| 2769 | __free_page(vmx_io_bitmap_b); | 2821 | __free_page(vmx_io_bitmap_b); |
| 2770 | out: | 2822 | out: |
| @@ -2774,6 +2826,7 @@ out: | |||
| 2774 | 2826 | ||
| 2775 | static void __exit vmx_exit(void) | 2827 | static 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 | ||
