aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWanpeng Li <wanpeng.li@hotmail.com>2016-09-21 19:43:25 -0400
committerRadim Krčmář <rkrcmar@redhat.com>2016-09-22 19:08:14 -0400
commitf6e90f9e0ee3df5010e7f378e669d6838b9a25bf (patch)
tree9053c7223a7e03ad5ad1abc3ba674749b0c6e501
parentc83b6d1594bfff8cdb95becb338b8fe9e3473c8d (diff)
KVM: VMX: Enable MSR-BASED TPR shadow even if APICv is inactive
I observed that kvmvapic(to optimize flexpriority=N or AMD) is used to boost TPR access when testing kvm-unit-test/eventinj.flat tpr case on my haswell desktop (w/ flexpriority, w/o APICv). Commit (8d14695f9542 x86, apicv: add virtual x2apic support) disable virtual x2apic mode completely if w/o APICv, and the author also told me that windows guest can't enter into x2apic mode when he developed the APICv feature several years ago. However, it is not truth currently, Interrupt Remapping and vIOMMU is added to qemu and the developers from Intel test windows 8 can work in x2apic mode w/ Interrupt Remapping enabled recently. This patch enables TPR shadow for virtual x2apic mode to boost windows guest in x2apic mode even if w/o APICv. Can pass the kvm-unit-test. Suggested-by: Radim Krčmář <rkrcmar@redhat.com> Suggested-by: Wincy Van <fanwenyi0529@gmail.com> Reviewed-by: Radim Krčmář <rkrcmar@redhat.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Radim Krčmář <rkrcmar@redhat.com> Cc: Wincy Van <fanwenyi0529@gmail.com> Cc: Yang Zhang <yang.zhang.wz@gmail.com> Signed-off-by: Wanpeng Li <wanpeng.li@hotmail.com> Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
-rw-r--r--arch/x86/kvm/vmx.c132
1 files changed, 94 insertions, 38 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 122047a5409c..5a5ab2062cb5 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -927,6 +927,8 @@ static unsigned long *vmx_msr_bitmap_legacy;
927static unsigned long *vmx_msr_bitmap_longmode; 927static unsigned long *vmx_msr_bitmap_longmode;
928static unsigned long *vmx_msr_bitmap_legacy_x2apic; 928static unsigned long *vmx_msr_bitmap_legacy_x2apic;
929static unsigned long *vmx_msr_bitmap_longmode_x2apic; 929static unsigned long *vmx_msr_bitmap_longmode_x2apic;
930static unsigned long *vmx_msr_bitmap_legacy_x2apic_apicv_inactive;
931static unsigned long *vmx_msr_bitmap_longmode_x2apic_apicv_inactive;
930static unsigned long *vmx_vmread_bitmap; 932static unsigned long *vmx_vmread_bitmap;
931static unsigned long *vmx_vmwrite_bitmap; 933static unsigned long *vmx_vmwrite_bitmap;
932 934
@@ -2524,10 +2526,17 @@ static void vmx_set_msr_bitmap(struct kvm_vcpu *vcpu)
2524 else if (cpu_has_secondary_exec_ctrls() && 2526 else if (cpu_has_secondary_exec_ctrls() &&
2525 (vmcs_read32(SECONDARY_VM_EXEC_CONTROL) & 2527 (vmcs_read32(SECONDARY_VM_EXEC_CONTROL) &
2526 SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE)) { 2528 SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE)) {
2527 if (is_long_mode(vcpu)) 2529 if (enable_apicv && kvm_vcpu_apicv_active(vcpu)) {
2528 msr_bitmap = vmx_msr_bitmap_longmode_x2apic; 2530 if (is_long_mode(vcpu))
2529 else 2531 msr_bitmap = vmx_msr_bitmap_longmode_x2apic;
2530 msr_bitmap = vmx_msr_bitmap_legacy_x2apic; 2532 else
2533 msr_bitmap = vmx_msr_bitmap_legacy_x2apic;
2534 } else {
2535 if (is_long_mode(vcpu))
2536 msr_bitmap = vmx_msr_bitmap_longmode_x2apic_apicv_inactive;
2537 else
2538 msr_bitmap = vmx_msr_bitmap_legacy_x2apic_apicv_inactive;
2539 }
2531 } else { 2540 } else {
2532 if (is_long_mode(vcpu)) 2541 if (is_long_mode(vcpu))
2533 msr_bitmap = vmx_msr_bitmap_longmode; 2542 msr_bitmap = vmx_msr_bitmap_longmode;
@@ -4682,28 +4691,49 @@ static void vmx_disable_intercept_for_msr(u32 msr, bool longmode_only)
4682 msr, MSR_TYPE_R | MSR_TYPE_W); 4691 msr, MSR_TYPE_R | MSR_TYPE_W);
4683} 4692}
4684 4693
4685static void vmx_enable_intercept_msr_read_x2apic(u32 msr) 4694static void vmx_enable_intercept_msr_read_x2apic(u32 msr, bool apicv_active)
4686{ 4695{
4687 __vmx_enable_intercept_for_msr(vmx_msr_bitmap_legacy_x2apic, 4696 if (apicv_active) {
4688 msr, MSR_TYPE_R); 4697 __vmx_enable_intercept_for_msr(vmx_msr_bitmap_legacy_x2apic,
4689 __vmx_enable_intercept_for_msr(vmx_msr_bitmap_longmode_x2apic, 4698 msr, MSR_TYPE_R);
4690 msr, MSR_TYPE_R); 4699 __vmx_enable_intercept_for_msr(vmx_msr_bitmap_longmode_x2apic,
4700 msr, MSR_TYPE_R);
4701 } else {
4702 __vmx_enable_intercept_for_msr(vmx_msr_bitmap_legacy_x2apic_apicv_inactive,
4703 msr, MSR_TYPE_R);
4704 __vmx_enable_intercept_for_msr(vmx_msr_bitmap_longmode_x2apic_apicv_inactive,
4705 msr, MSR_TYPE_R);
4706 }
4691} 4707}
4692 4708
4693static void vmx_disable_intercept_msr_read_x2apic(u32 msr) 4709static void vmx_disable_intercept_msr_read_x2apic(u32 msr, bool apicv_active)
4694{ 4710{
4695 __vmx_disable_intercept_for_msr(vmx_msr_bitmap_legacy_x2apic, 4711 if (apicv_active) {
4696 msr, MSR_TYPE_R); 4712 __vmx_disable_intercept_for_msr(vmx_msr_bitmap_legacy_x2apic,
4697 __vmx_disable_intercept_for_msr(vmx_msr_bitmap_longmode_x2apic, 4713 msr, MSR_TYPE_R);
4698 msr, MSR_TYPE_R); 4714 __vmx_disable_intercept_for_msr(vmx_msr_bitmap_longmode_x2apic,
4715 msr, MSR_TYPE_R);
4716 } else {
4717 __vmx_disable_intercept_for_msr(vmx_msr_bitmap_legacy_x2apic_apicv_inactive,
4718 msr, MSR_TYPE_R);
4719 __vmx_disable_intercept_for_msr(vmx_msr_bitmap_longmode_x2apic_apicv_inactive,
4720 msr, MSR_TYPE_R);
4721 }
4699} 4722}
4700 4723
4701static void vmx_disable_intercept_msr_write_x2apic(u32 msr) 4724static void vmx_disable_intercept_msr_write_x2apic(u32 msr, bool apicv_active)
4702{ 4725{
4703 __vmx_disable_intercept_for_msr(vmx_msr_bitmap_legacy_x2apic, 4726 if (apicv_active) {
4704 msr, MSR_TYPE_W); 4727 __vmx_disable_intercept_for_msr(vmx_msr_bitmap_legacy_x2apic,
4705 __vmx_disable_intercept_for_msr(vmx_msr_bitmap_longmode_x2apic, 4728 msr, MSR_TYPE_W);
4706 msr, MSR_TYPE_W); 4729 __vmx_disable_intercept_for_msr(vmx_msr_bitmap_longmode_x2apic,
4730 msr, MSR_TYPE_W);
4731 } else {
4732 __vmx_disable_intercept_for_msr(vmx_msr_bitmap_legacy_x2apic_apicv_inactive,
4733 msr, MSR_TYPE_W);
4734 __vmx_disable_intercept_for_msr(vmx_msr_bitmap_longmode_x2apic_apicv_inactive,
4735 msr, MSR_TYPE_W);
4736 }
4707} 4737}
4708 4738
4709static bool vmx_get_enable_apicv(void) 4739static bool vmx_get_enable_apicv(void)
@@ -6364,22 +6394,32 @@ static __init int hardware_setup(void)
6364 if (!vmx_msr_bitmap_legacy_x2apic) 6394 if (!vmx_msr_bitmap_legacy_x2apic)
6365 goto out2; 6395 goto out2;
6366 6396
6397 vmx_msr_bitmap_legacy_x2apic_apicv_inactive =
6398 (unsigned long *)__get_free_page(GFP_KERNEL);
6399 if (!vmx_msr_bitmap_legacy_x2apic_apicv_inactive)
6400 goto out3;
6401
6367 vmx_msr_bitmap_longmode = (unsigned long *)__get_free_page(GFP_KERNEL); 6402 vmx_msr_bitmap_longmode = (unsigned long *)__get_free_page(GFP_KERNEL);
6368 if (!vmx_msr_bitmap_longmode) 6403 if (!vmx_msr_bitmap_longmode)
6369 goto out3; 6404 goto out4;
6370 6405
6371 vmx_msr_bitmap_longmode_x2apic = 6406 vmx_msr_bitmap_longmode_x2apic =
6372 (unsigned long *)__get_free_page(GFP_KERNEL); 6407 (unsigned long *)__get_free_page(GFP_KERNEL);
6373 if (!vmx_msr_bitmap_longmode_x2apic) 6408 if (!vmx_msr_bitmap_longmode_x2apic)
6374 goto out4; 6409 goto out5;
6410
6411 vmx_msr_bitmap_longmode_x2apic_apicv_inactive =
6412 (unsigned long *)__get_free_page(GFP_KERNEL);
6413 if (!vmx_msr_bitmap_longmode_x2apic_apicv_inactive)
6414 goto out6;
6375 6415
6376 vmx_vmread_bitmap = (unsigned long *)__get_free_page(GFP_KERNEL); 6416 vmx_vmread_bitmap = (unsigned long *)__get_free_page(GFP_KERNEL);
6377 if (!vmx_vmread_bitmap) 6417 if (!vmx_vmread_bitmap)
6378 goto out6; 6418 goto out7;
6379 6419
6380 vmx_vmwrite_bitmap = (unsigned long *)__get_free_page(GFP_KERNEL); 6420 vmx_vmwrite_bitmap = (unsigned long *)__get_free_page(GFP_KERNEL);
6381 if (!vmx_vmwrite_bitmap) 6421 if (!vmx_vmwrite_bitmap)
6382 goto out7; 6422 goto out8;
6383 6423
6384 memset(vmx_vmread_bitmap, 0xff, PAGE_SIZE); 6424 memset(vmx_vmread_bitmap, 0xff, PAGE_SIZE);
6385 memset(vmx_vmwrite_bitmap, 0xff, PAGE_SIZE); 6425 memset(vmx_vmwrite_bitmap, 0xff, PAGE_SIZE);
@@ -6398,7 +6438,7 @@ static __init int hardware_setup(void)
6398 6438
6399 if (setup_vmcs_config(&vmcs_config) < 0) { 6439 if (setup_vmcs_config(&vmcs_config) < 0) {
6400 r = -EIO; 6440 r = -EIO;
6401 goto out8; 6441 goto out9;
6402 } 6442 }
6403 6443
6404 if (boot_cpu_has(X86_FEATURE_NX)) 6444 if (boot_cpu_has(X86_FEATURE_NX))
@@ -6465,20 +6505,35 @@ static __init int hardware_setup(void)
6465 vmx_msr_bitmap_legacy, PAGE_SIZE); 6505 vmx_msr_bitmap_legacy, PAGE_SIZE);
6466 memcpy(vmx_msr_bitmap_longmode_x2apic, 6506 memcpy(vmx_msr_bitmap_longmode_x2apic,
6467 vmx_msr_bitmap_longmode, PAGE_SIZE); 6507 vmx_msr_bitmap_longmode, PAGE_SIZE);
6508 memcpy(vmx_msr_bitmap_legacy_x2apic_apicv_inactive,
6509 vmx_msr_bitmap_legacy, PAGE_SIZE);
6510 memcpy(vmx_msr_bitmap_longmode_x2apic_apicv_inactive,
6511 vmx_msr_bitmap_longmode, PAGE_SIZE);
6468 6512
6469 set_bit(0, vmx_vpid_bitmap); /* 0 is reserved for host */ 6513 set_bit(0, vmx_vpid_bitmap); /* 0 is reserved for host */
6470 6514
6515 /*
6516 * enable_apicv && kvm_vcpu_apicv_active()
6517 */
6471 for (msr = 0x800; msr <= 0x8ff; msr++) 6518 for (msr = 0x800; msr <= 0x8ff; msr++)
6472 vmx_disable_intercept_msr_read_x2apic(msr); 6519 vmx_disable_intercept_msr_read_x2apic(msr, true);
6473 6520
6474 /* TMCCT */ 6521 /* TMCCT */
6475 vmx_enable_intercept_msr_read_x2apic(0x839); 6522 vmx_enable_intercept_msr_read_x2apic(0x839, true);
6476 /* TPR */ 6523 /* TPR */
6477 vmx_disable_intercept_msr_write_x2apic(0x808); 6524 vmx_disable_intercept_msr_write_x2apic(0x808, true);
6478 /* EOI */ 6525 /* EOI */
6479 vmx_disable_intercept_msr_write_x2apic(0x80b); 6526 vmx_disable_intercept_msr_write_x2apic(0x80b, true);
6480 /* SELF-IPI */ 6527 /* SELF-IPI */
6481 vmx_disable_intercept_msr_write_x2apic(0x83f); 6528 vmx_disable_intercept_msr_write_x2apic(0x83f, true);
6529
6530 /*
6531 * (enable_apicv && !kvm_vcpu_apicv_active()) ||
6532 * !enable_apicv
6533 */
6534 /* TPR */
6535 vmx_disable_intercept_msr_read_x2apic(0x808, false);
6536 vmx_disable_intercept_msr_write_x2apic(0x808, false);
6482 6537
6483 if (enable_ept) { 6538 if (enable_ept) {
6484 kvm_mmu_set_mask_ptes(VMX_EPT_READABLE_MASK, 6539 kvm_mmu_set_mask_ptes(VMX_EPT_READABLE_MASK,
@@ -6525,14 +6580,18 @@ static __init int hardware_setup(void)
6525 6580
6526 return alloc_kvm_area(); 6581 return alloc_kvm_area();
6527 6582
6528out8: 6583out9:
6529 free_page((unsigned long)vmx_vmwrite_bitmap); 6584 free_page((unsigned long)vmx_vmwrite_bitmap);
6530out7: 6585out8:
6531 free_page((unsigned long)vmx_vmread_bitmap); 6586 free_page((unsigned long)vmx_vmread_bitmap);
6587out7:
6588 free_page((unsigned long)vmx_msr_bitmap_longmode_x2apic_apicv_inactive);
6532out6: 6589out6:
6533 free_page((unsigned long)vmx_msr_bitmap_longmode_x2apic); 6590 free_page((unsigned long)vmx_msr_bitmap_longmode_x2apic);
6534out4: 6591out5:
6535 free_page((unsigned long)vmx_msr_bitmap_longmode); 6592 free_page((unsigned long)vmx_msr_bitmap_longmode);
6593out4:
6594 free_page((unsigned long)vmx_msr_bitmap_legacy_x2apic_apicv_inactive);
6536out3: 6595out3:
6537 free_page((unsigned long)vmx_msr_bitmap_legacy_x2apic); 6596 free_page((unsigned long)vmx_msr_bitmap_legacy_x2apic);
6538out2: 6597out2:
@@ -6548,7 +6607,9 @@ out:
6548static __exit void hardware_unsetup(void) 6607static __exit void hardware_unsetup(void)
6549{ 6608{
6550 free_page((unsigned long)vmx_msr_bitmap_legacy_x2apic); 6609 free_page((unsigned long)vmx_msr_bitmap_legacy_x2apic);
6610 free_page((unsigned long)vmx_msr_bitmap_legacy_x2apic_apicv_inactive);
6551 free_page((unsigned long)vmx_msr_bitmap_longmode_x2apic); 6611 free_page((unsigned long)vmx_msr_bitmap_longmode_x2apic);
6612 free_page((unsigned long)vmx_msr_bitmap_longmode_x2apic_apicv_inactive);
6552 free_page((unsigned long)vmx_msr_bitmap_legacy); 6613 free_page((unsigned long)vmx_msr_bitmap_legacy);
6553 free_page((unsigned long)vmx_msr_bitmap_longmode); 6614 free_page((unsigned long)vmx_msr_bitmap_longmode);
6554 free_page((unsigned long)vmx_io_bitmap_b); 6615 free_page((unsigned long)vmx_io_bitmap_b);
@@ -8439,12 +8500,7 @@ static void vmx_set_virtual_x2apic_mode(struct kvm_vcpu *vcpu, bool set)
8439 return; 8500 return;
8440 } 8501 }
8441 8502
8442 /* 8503 if (!cpu_has_vmx_virtualize_x2apic_mode())
8443 * There is not point to enable virtualize x2apic without enable
8444 * apicv
8445 */
8446 if (!cpu_has_vmx_virtualize_x2apic_mode() ||
8447 !kvm_vcpu_apicv_active(vcpu))
8448 return; 8504 return;
8449 8505
8450 if (!cpu_need_tpr_shadow(vcpu)) 8506 if (!cpu_need_tpr_shadow(vcpu))