aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm/vmx.c
diff options
context:
space:
mode:
authorYang, Sheng <sheng.yang@intel.com>2007-07-29 04:07:42 -0400
committerAvi Kivity <avi@qumranet.com>2007-10-13 04:18:20 -0400
commit1c3d14fe0ab75337a3f6c06b6bc18bcbc2b3d0bc (patch)
treef3d2533b5250e8405af14f99c2810bb3ead1a06c /drivers/kvm/vmx.c
parentfb3f0f51d92d1496f9628ca6f0fb06a48dc9ed2a (diff)
KVM: VMX: Improve the method of writing vmcs control
Put cpu feature detecting part in hardware_setup, and stored the vmcs condition in global variable for further check. [glommer: fix for some i386-only machines not supporting CR8 load/store exiting] Signed-off-by: Sheng Yang <sheng.yang@intel.com> Signed-off-by: Glauber de Oliveira Costa <gcosta@redhat.com> Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm/vmx.c')
-rw-r--r--drivers/kvm/vmx.c147
1 files changed, 102 insertions, 45 deletions
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index df5787823309..18f9b0b3fb1f 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -71,18 +71,17 @@ static DEFINE_PER_CPU(struct vmcs *, current_vmcs);
71static struct page *vmx_io_bitmap_a; 71static struct page *vmx_io_bitmap_a;
72static struct page *vmx_io_bitmap_b; 72static struct page *vmx_io_bitmap_b;
73 73
74#ifdef CONFIG_X86_64
75#define HOST_IS_64 1
76#else
77#define HOST_IS_64 0
78#endif
79#define EFER_SAVE_RESTORE_BITS ((u64)EFER_SCE) 74#define EFER_SAVE_RESTORE_BITS ((u64)EFER_SCE)
80 75
81static struct vmcs_descriptor { 76static struct vmcs_config {
82 int size; 77 int size;
83 int order; 78 int order;
84 u32 revision_id; 79 u32 revision_id;
85} vmcs_descriptor; 80 u32 pin_based_exec_ctrl;
81 u32 cpu_based_exec_ctrl;
82 u32 vmexit_ctrl;
83 u32 vmentry_ctrl;
84} vmcs_config;
86 85
87#define VMX_SEGMENT_FIELD(seg) \ 86#define VMX_SEGMENT_FIELD(seg) \
88 [VCPU_SREG_##seg] = { \ 87 [VCPU_SREG_##seg] = { \
@@ -839,14 +838,93 @@ static void hardware_disable(void *garbage)
839 asm volatile (ASM_VMX_VMXOFF : : : "cc"); 838 asm volatile (ASM_VMX_VMXOFF : : : "cc");
840} 839}
841 840
842static __init void setup_vmcs_descriptor(void) 841static __init int adjust_vmx_controls(u32 ctl_min, u32 ctl_opt,
842 u32 msr, u32* result)
843{
844 u32 vmx_msr_low, vmx_msr_high;
845 u32 ctl = ctl_min | ctl_opt;
846
847 rdmsr(msr, vmx_msr_low, vmx_msr_high);
848
849 ctl &= vmx_msr_high; /* bit == 0 in high word ==> must be zero */
850 ctl |= vmx_msr_low; /* bit == 1 in low word ==> must be one */
851
852 /* Ensure minimum (required) set of control bits are supported. */
853 if (ctl_min & ~ctl)
854 return -1;
855
856 *result = ctl;
857 return 0;
858}
859
860static __init int setup_vmcs_config(void)
843{ 861{
844 u32 vmx_msr_low, vmx_msr_high; 862 u32 vmx_msr_low, vmx_msr_high;
863 u32 min, opt;
864 u32 _pin_based_exec_control = 0;
865 u32 _cpu_based_exec_control = 0;
866 u32 _vmexit_control = 0;
867 u32 _vmentry_control = 0;
868
869 min = PIN_BASED_EXT_INTR_MASK | PIN_BASED_NMI_EXITING;
870 opt = 0;
871 if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PINBASED_CTLS,
872 &_pin_based_exec_control) < 0)
873 return -1;
874
875 min = CPU_BASED_HLT_EXITING |
876#ifdef CONFIG_X86_64
877 CPU_BASED_CR8_LOAD_EXITING |
878 CPU_BASED_CR8_STORE_EXITING |
879#endif
880 CPU_BASED_USE_IO_BITMAPS |
881 CPU_BASED_MOV_DR_EXITING |
882 CPU_BASED_USE_TSC_OFFSETING;
883 opt = 0;
884 if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS,
885 &_cpu_based_exec_control) < 0)
886 return -1;
887
888 min = 0;
889#ifdef CONFIG_X86_64
890 min |= VM_EXIT_HOST_ADDR_SPACE_SIZE;
891#endif
892 opt = 0;
893 if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_EXIT_CTLS,
894 &_vmexit_control) < 0)
895 return -1;
896
897 min = opt = 0;
898 if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_ENTRY_CTLS,
899 &_vmentry_control) < 0)
900 return -1;
845 901
846 rdmsr(MSR_IA32_VMX_BASIC, vmx_msr_low, vmx_msr_high); 902 rdmsr(MSR_IA32_VMX_BASIC, vmx_msr_low, vmx_msr_high);
847 vmcs_descriptor.size = vmx_msr_high & 0x1fff; 903
848 vmcs_descriptor.order = get_order(vmcs_descriptor.size); 904 /* IA-32 SDM Vol 3B: VMCS size is never greater than 4kB. */
849 vmcs_descriptor.revision_id = vmx_msr_low; 905 if ((vmx_msr_high & 0x1fff) > PAGE_SIZE)
906 return -1;
907
908#ifdef CONFIG_X86_64
909 /* IA-32 SDM Vol 3B: 64-bit CPUs always have VMX_BASIC_MSR[48]==0. */
910 if (vmx_msr_high & (1u<<16))
911 return -1;
912#endif
913
914 /* Require Write-Back (WB) memory type for VMCS accesses. */
915 if (((vmx_msr_high >> 18) & 15) != 6)
916 return -1;
917
918 vmcs_config.size = vmx_msr_high & 0x1fff;
919 vmcs_config.order = get_order(vmcs_config.size);
920 vmcs_config.revision_id = vmx_msr_low;
921
922 vmcs_config.pin_based_exec_ctrl = _pin_based_exec_control;
923 vmcs_config.cpu_based_exec_ctrl = _cpu_based_exec_control;
924 vmcs_config.vmexit_ctrl = _vmexit_control;
925 vmcs_config.vmentry_ctrl = _vmentry_control;
926
927 return 0;
850} 928}
851 929
852static struct vmcs *alloc_vmcs_cpu(int cpu) 930static struct vmcs *alloc_vmcs_cpu(int cpu)
@@ -855,12 +933,12 @@ static struct vmcs *alloc_vmcs_cpu(int cpu)
855 struct page *pages; 933 struct page *pages;
856 struct vmcs *vmcs; 934 struct vmcs *vmcs;
857 935
858 pages = alloc_pages_node(node, GFP_KERNEL, vmcs_descriptor.order); 936 pages = alloc_pages_node(node, GFP_KERNEL, vmcs_config.order);
859 if (!pages) 937 if (!pages)
860 return NULL; 938 return NULL;
861 vmcs = page_address(pages); 939 vmcs = page_address(pages);
862 memset(vmcs, 0, vmcs_descriptor.size); 940 memset(vmcs, 0, vmcs_config.size);
863 vmcs->revision_id = vmcs_descriptor.revision_id; /* vmcs revision id */ 941 vmcs->revision_id = vmcs_config.revision_id; /* vmcs revision id */
864 return vmcs; 942 return vmcs;
865} 943}
866 944
@@ -871,7 +949,7 @@ static struct vmcs *alloc_vmcs(void)
871 949
872static void free_vmcs(struct vmcs *vmcs) 950static void free_vmcs(struct vmcs *vmcs)
873{ 951{
874 free_pages((unsigned long)vmcs, vmcs_descriptor.order); 952 free_pages((unsigned long)vmcs, vmcs_config.order);
875} 953}
876 954
877static void free_kvm_area(void) 955static void free_kvm_area(void)
@@ -904,7 +982,8 @@ static __init int alloc_kvm_area(void)
904 982
905static __init int hardware_setup(void) 983static __init int hardware_setup(void)
906{ 984{
907 setup_vmcs_descriptor(); 985 if (setup_vmcs_config() < 0)
986 return -1;
908 return alloc_kvm_area(); 987 return alloc_kvm_area();
909} 988}
910 989
@@ -1275,17 +1354,6 @@ static int init_rmode_tss(struct kvm* kvm)
1275 return 1; 1354 return 1;
1276} 1355}
1277 1356
1278static void vmcs_write32_fixedbits(u32 msr, u32 vmcs_field, u32 val)
1279{
1280 u32 msr_high, msr_low;
1281
1282 rdmsr(msr, msr_low, msr_high);
1283
1284 val &= msr_high;
1285 val |= msr_low;
1286 vmcs_write32(vmcs_field, val);
1287}
1288
1289static void seg_setup(int seg) 1357static void seg_setup(int seg)
1290{ 1358{
1291 struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg]; 1359 struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
@@ -1382,20 +1450,10 @@ static int vmx_vcpu_setup(struct kvm_vcpu *vcpu)
1382 vmcs_write64(GUEST_IA32_DEBUGCTL, 0); 1450 vmcs_write64(GUEST_IA32_DEBUGCTL, 0);
1383 1451
1384 /* Control */ 1452 /* Control */
1385 vmcs_write32_fixedbits(MSR_IA32_VMX_PINBASED_CTLS, 1453 vmcs_write32(PIN_BASED_VM_EXEC_CONTROL,
1386 PIN_BASED_VM_EXEC_CONTROL, 1454 vmcs_config.pin_based_exec_ctrl);
1387 PIN_BASED_EXT_INTR_MASK /* 20.6.1 */ 1455 vmcs_write32(CPU_BASED_VM_EXEC_CONTROL,
1388 | PIN_BASED_NMI_EXITING /* 20.6.1 */ 1456 vmcs_config.cpu_based_exec_ctrl);
1389 );
1390 vmcs_write32_fixedbits(MSR_IA32_VMX_PROCBASED_CTLS,
1391 CPU_BASED_VM_EXEC_CONTROL,
1392 CPU_BASED_HLT_EXITING /* 20.6.2 */
1393 | CPU_BASED_CR8_LOAD_EXITING /* 20.6.2 */
1394 | CPU_BASED_CR8_STORE_EXITING /* 20.6.2 */
1395 | CPU_BASED_USE_IO_BITMAPS /* 20.6.2 */
1396 | CPU_BASED_MOV_DR_EXITING
1397 | CPU_BASED_USE_TSC_OFFSETING /* 21.3 */
1398 );
1399 1457
1400 vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, 0); 1458 vmcs_write32(PAGE_FAULT_ERROR_CODE_MASK, 0);
1401 vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, 0); 1459 vmcs_write32(PAGE_FAULT_ERROR_CODE_MATCH, 0);
@@ -1459,12 +1517,11 @@ static int vmx_vcpu_setup(struct kvm_vcpu *vcpu)
1459 1517
1460 setup_msrs(vcpu); 1518 setup_msrs(vcpu);
1461 1519
1462 vmcs_write32_fixedbits(MSR_IA32_VMX_EXIT_CTLS, VM_EXIT_CONTROLS, 1520 vmcs_write32(VM_EXIT_CONTROLS, vmcs_config.vmexit_ctrl);
1463 (HOST_IS_64 << 9)); /* 22.2,1, 20.7.1 */
1464 1521
1465 /* 22.2.1, 20.8.1 */ 1522 /* 22.2.1, 20.8.1 */
1466 vmcs_write32_fixedbits(MSR_IA32_VMX_ENTRY_CTLS, 1523 vmcs_write32(VM_ENTRY_CONTROLS, vmcs_config.vmentry_ctrl);
1467 VM_ENTRY_CONTROLS, 0); 1524
1468 vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0); /* 22.2.1 */ 1525 vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0); /* 22.2.1 */
1469 1526
1470#ifdef CONFIG_X86_64 1527#ifdef CONFIG_X86_64