aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm/vmx.c
diff options
context:
space:
mode:
authorYang, Sheng <sheng.yang@intel.com>2007-09-12 06:03:11 -0400
committerAvi Kivity <avi@qumranet.com>2007-10-13 04:18:26 -0400
commit6e5d865c0b9679b00b5e5f0754c9fc2b6b9894d6 (patch)
tree1b8133926578a16f8849143da5a7d5a6d9e67b24 /drivers/kvm/vmx.c
parent2a8067f17b8442ecce0b14e134823020ff33b4fa (diff)
KVM: VMX: Use shadow TPR/cr8 for 64-bits guests
This patch enables TPR shadow of VMX on CR8 access. 64bit Windows using CR8 access TPR frequently. The TPR shadow can improve the performance of access TPR by not causing vmexit. Signed-off-by: Sheng Yang <sheng.yang@intel.com> Signed-off-by: Yaozu (Eddie) Dong <eddie.dong@intel.com> Signed-off-by: Qing He <qing.he@intel.com> Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm/vmx.c')
-rw-r--r--drivers/kvm/vmx.c65
1 files changed, 61 insertions, 4 deletions
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index 6c371ea21046..5c2c6e71abf2 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -170,6 +170,16 @@ static inline int is_external_interrupt(u32 intr_info)
170 == (INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK); 170 == (INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK);
171} 171}
172 172
173static inline int cpu_has_vmx_tpr_shadow(void)
174{
175 return (vmcs_config.cpu_based_exec_ctrl & CPU_BASED_TPR_SHADOW);
176}
177
178static inline int vm_need_tpr_shadow(struct kvm *kvm)
179{
180 return ((cpu_has_vmx_tpr_shadow()) && (irqchip_in_kernel(kvm)));
181}
182
173static int __find_msr_index(struct vcpu_vmx *vmx, u32 msr) 183static int __find_msr_index(struct vcpu_vmx *vmx, u32 msr)
174{ 184{
175 int i; 185 int i;
@@ -888,10 +898,19 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
888 CPU_BASED_USE_IO_BITMAPS | 898 CPU_BASED_USE_IO_BITMAPS |
889 CPU_BASED_MOV_DR_EXITING | 899 CPU_BASED_MOV_DR_EXITING |
890 CPU_BASED_USE_TSC_OFFSETING; 900 CPU_BASED_USE_TSC_OFFSETING;
901#ifdef CONFIG_X86_64
902 opt = CPU_BASED_TPR_SHADOW;
903#else
891 opt = 0; 904 opt = 0;
905#endif
892 if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS, 906 if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS,
893 &_cpu_based_exec_control) < 0) 907 &_cpu_based_exec_control) < 0)
894 return -EIO; 908 return -EIO;
909#ifdef CONFIG_X86_64
910 if ((_cpu_based_exec_control & CPU_BASED_TPR_SHADOW))
911 _cpu_based_exec_control &= ~CPU_BASED_CR8_LOAD_EXITING &
912 ~CPU_BASED_CR8_STORE_EXITING;
913#endif
895 914
896 min = 0; 915 min = 0;
897#ifdef CONFIG_X86_64 916#ifdef CONFIG_X86_64
@@ -1384,6 +1403,7 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
1384 int ret = 0; 1403 int ret = 0;
1385 unsigned long kvm_vmx_return; 1404 unsigned long kvm_vmx_return;
1386 u64 msr; 1405 u64 msr;
1406 u32 exec_control;
1387 1407
1388 if (!init_rmode_tss(vmx->vcpu.kvm)) { 1408 if (!init_rmode_tss(vmx->vcpu.kvm)) {
1389 ret = -ENOMEM; 1409 ret = -ENOMEM;
@@ -1459,8 +1479,16 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
1459 /* Control */ 1479 /* Control */
1460 vmcs_write32(PIN_BASED_VM_EXEC_CONTROL, 1480 vmcs_write32(PIN_BASED_VM_EXEC_CONTROL,
1461 vmcs_config.pin_based_exec_ctrl); 1481 vmcs_config.pin_based_exec_ctrl);
1462 vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, 1482
1463 vmcs_config.cpu_based_exec_ctrl); 1483 exec_control = vmcs_config.cpu_based_exec_ctrl;
1484 if (!vm_need_tpr_shadow(vmx->vcpu.kvm)) {
1485 exec_control &= ~CPU_BASED_TPR_SHADOW;
1486#ifdef CONFIG_X86_64
1487 exec_control |= CPU_BASED_CR8_STORE_EXITING |
1488 CPU_BASED_CR8_LOAD_EXITING;
1489#endif
1490 }
1491 vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, exec_control);
1464 1492
1465 vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, 0); 1493 vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, 0);
1466 vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, 0); 1494 vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, 0);
@@ -1532,8 +1560,11 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
1532 vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0); /* 22.2.1 */ 1560 vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0); /* 22.2.1 */
1533 1561
1534#ifdef CONFIG_X86_64 1562#ifdef CONFIG_X86_64
1535 vmcs_writel(VIRTUAL_APIC_PAGE_ADDR, 0); 1563 vmcs_write64(VIRTUAL_APIC_PAGE_ADDR, 0);
1536 vmcs_writel(TPR_THRESHOLD, 0); 1564 if (vm_need_tpr_shadow(vmx->vcpu.kvm))
1565 vmcs_write64(VIRTUAL_APIC_PAGE_ADDR,
1566 page_to_phys(vmx->vcpu.apic->regs_page));
1567 vmcs_write32(TPR_THRESHOLD, 0);
1537#endif 1568#endif
1538 1569
1539 vmcs_writel(CR0_GUEST_HOST_MASK, ~0UL); 1570 vmcs_writel(CR0_GUEST_HOST_MASK, ~0UL);
@@ -1969,6 +2000,12 @@ static int handle_wrmsr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
1969 return 1; 2000 return 1;
1970} 2001}
1971 2002
2003static int handle_tpr_below_threshold(struct kvm_vcpu *vcpu,
2004 struct kvm_run *kvm_run)
2005{
2006 return 1;
2007}
2008
1972static void post_kvm_run_save(struct kvm_vcpu *vcpu, 2009static void post_kvm_run_save(struct kvm_vcpu *vcpu,
1973 struct kvm_run *kvm_run) 2010 struct kvm_run *kvm_run)
1974{ 2011{
@@ -2036,6 +2073,7 @@ static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu,
2036 [EXIT_REASON_PENDING_INTERRUPT] = handle_interrupt_window, 2073 [EXIT_REASON_PENDING_INTERRUPT] = handle_interrupt_window,
2037 [EXIT_REASON_HLT] = handle_halt, 2074 [EXIT_REASON_HLT] = handle_halt,
2038 [EXIT_REASON_VMCALL] = handle_vmcall, 2075 [EXIT_REASON_VMCALL] = handle_vmcall,
2076 [EXIT_REASON_TPR_BELOW_THRESHOLD] = handle_tpr_below_threshold
2039}; 2077};
2040 2078
2041static const int kvm_vmx_max_exit_handlers = 2079static const int kvm_vmx_max_exit_handlers =
@@ -2083,6 +2121,23 @@ static void vmx_flush_tlb(struct kvm_vcpu *vcpu)
2083{ 2121{
2084} 2122}
2085 2123
2124static void update_tpr_threshold(struct kvm_vcpu *vcpu)
2125{
2126 int max_irr, tpr;
2127
2128 if (!vm_need_tpr_shadow(vcpu->kvm))
2129 return;
2130
2131 if (!kvm_lapic_enabled(vcpu) ||
2132 ((max_irr = kvm_lapic_find_highest_irr(vcpu)) == -1)) {
2133 vmcs_write32(TPR_THRESHOLD, 0);
2134 return;
2135 }
2136
2137 tpr = (kvm_lapic_get_cr8(vcpu) & 0x0f) << 4;
2138 vmcs_write32(TPR_THRESHOLD, (max_irr > tpr) ? tpr >> 4 : max_irr >> 4);
2139}
2140
2086static void enable_irq_window(struct kvm_vcpu *vcpu) 2141static void enable_irq_window(struct kvm_vcpu *vcpu)
2087{ 2142{
2088 u32 cpu_based_vm_exec_control; 2143 u32 cpu_based_vm_exec_control;
@@ -2097,6 +2152,8 @@ static void vmx_intr_assist(struct kvm_vcpu *vcpu)
2097 u32 idtv_info_field, intr_info_field; 2152 u32 idtv_info_field, intr_info_field;
2098 int has_ext_irq, interrupt_window_open; 2153 int has_ext_irq, interrupt_window_open;
2099 2154
2155 update_tpr_threshold(vcpu);
2156
2100 has_ext_irq = kvm_cpu_has_interrupt(vcpu); 2157 has_ext_irq = kvm_cpu_has_interrupt(vcpu);
2101 intr_info_field = vmcs_read32(VM_ENTRY_INTR_INFO_FIELD); 2158 intr_info_field = vmcs_read32(VM_ENTRY_INTR_INFO_FIELD);
2102 idtv_info_field = vmcs_read32(IDT_VECTORING_INFO_FIELD); 2159 idtv_info_field = vmcs_read32(IDT_VECTORING_INFO_FIELD);