Skip to content

Commit 25c5f22

Browse files
Sheng Yangavikivity
authored andcommitted
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 <[email protected]> Signed-off-by: Avi Kivity <[email protected]>
1 parent e976a2b commit 25c5f22

File tree

1 file changed

+60
-7
lines changed

1 file changed

+60
-7
lines changed

arch/x86/kvm/vmx.c

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ static DEFINE_PER_CPU(struct vmcs *, current_vmcs);
9191

9292
static struct page *vmx_io_bitmap_a;
9393
static struct page *vmx_io_bitmap_b;
94+
static struct page *vmx_msr_bitmap;
9495

9596
static DECLARE_BITMAP(vmx_vpid_bitmap, VMX_NR_VPIDS);
9697
static DEFINE_SPINLOCK(vmx_vpid_lock);
@@ -185,6 +186,11 @@ static inline int is_external_interrupt(u32 intr_info)
185186
== (INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK);
186187
}
187188

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+
188194
static inline int cpu_has_vmx_tpr_shadow(void)
189195
{
190196
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)
10011007
CPU_BASED_MOV_DR_EXITING |
10021008
CPU_BASED_USE_TSC_OFFSETING;
10031009
opt = CPU_BASED_TPR_SHADOW |
1010+
CPU_BASED_USE_MSR_BITMAPS |
10041011
CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
10051012
if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS,
10061013
&_cpu_based_exec_control) < 0)
@@ -1575,6 +1582,30 @@ static void allocate_vpid(struct vcpu_vmx *vmx)
15751582
spin_unlock(&vmx_vpid_lock);
15761583
}
15771584

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+
15781609
/*
15791610
* Sets up the vmcs for emulated real mode.
15801611
*/
@@ -1592,6 +1623,9 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
15921623
vmcs_write64(IO_BITMAP_A, page_to_phys(vmx_io_bitmap_a));
15931624
vmcs_write64(IO_BITMAP_B, page_to_phys(vmx_io_bitmap_b));
15941625

1626+
if (cpu_has_vmx_msr_bitmap())
1627+
vmcs_write64(MSR_BITMAP, page_to_phys(vmx_msr_bitmap));
1628+
15951629
vmcs_write64(VMCS_LINK_POINTER, -1ull); /* 22.3.1.5 */
15961630

15971631
/* Control */
@@ -2728,7 +2762,7 @@ static struct kvm_x86_ops vmx_x86_ops = {
27282762

27292763
static int __init vmx_init(void)
27302764
{
2731-
void *iova;
2765+
void *va;
27322766
int r;
27332767

27342768
vmx_io_bitmap_a = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
@@ -2741,30 +2775,48 @@ static int __init vmx_init(void)
27412775
goto out;
27422776
}
27432777

2778+
vmx_msr_bitmap = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
2779+
if (!vmx_msr_bitmap) {
2780+
r = -ENOMEM;
2781+
goto out1;
2782+
}
2783+
27442784
/*
27452785
* Allow direct access to the PC debug port (it is often used for I/O
27462786
* delays, but the vmexits simply slow things down).
27472787
*/
2748-
iova = kmap(vmx_io_bitmap_a);
2749-
memset(iova, 0xff, PAGE_SIZE);
2750-
clear_bit(0x80, iova);
2788+
va = kmap(vmx_io_bitmap_a);
2789+
memset(va, 0xff, PAGE_SIZE);
2790+
clear_bit(0x80, va);
27512791
kunmap(vmx_io_bitmap_a);
27522792

2753-
iova = kmap(vmx_io_bitmap_b);
2754-
memset(iova, 0xff, PAGE_SIZE);
2793+
va = kmap(vmx_io_bitmap_b);
2794+
memset(va, 0xff, PAGE_SIZE);
27552795
kunmap(vmx_io_bitmap_b);
27562796

2797+
va = kmap(vmx_msr_bitmap);
2798+
memset(va, 0xff, PAGE_SIZE);
2799+
kunmap(vmx_msr_bitmap);
2800+
27572801
set_bit(0, vmx_vpid_bitmap); /* 0 is reserved for host */
27582802

27592803
r = kvm_init(&vmx_x86_ops, sizeof(struct vcpu_vmx), THIS_MODULE);
27602804
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);
27622812

27632813
if (bypass_guest_pf)
27642814
kvm_mmu_set_nonpresent_ptes(~0xffeull, 0ull);
27652815

27662816
return 0;
27672817

2818+
out2:
2819+
__free_page(vmx_msr_bitmap);
27682820
out1:
27692821
__free_page(vmx_io_bitmap_b);
27702822
out:
@@ -2774,6 +2826,7 @@ static int __init vmx_init(void)
27742826

27752827
static void __exit vmx_exit(void)
27762828
{
2829+
__free_page(vmx_msr_bitmap);
27772830
__free_page(vmx_io_bitmap_b);
27782831
__free_page(vmx_io_bitmap_a);
27792832

0 commit comments

Comments
 (0)