ia64/xen-unstable
changeset 11625:0f9908c2c5c7
[XEN] Simplify VMCS allocation (never bigger than a page).
Dynamically determine reserved bits in execution-control
fields.
Signed-off-by: Keir Fraser <keir@xensource.com>
Dynamically determine reserved bits in execution-control
fields.
Signed-off-by: Keir Fraser <keir@xensource.com>
author | kfraser@localhost.localdomain |
---|---|
date | Mon Sep 25 17:46:08 2006 +0100 (2006-09-25) |
parents | f5fd563bcc84 |
children | 7de1715d185e |
files | xen/arch/x86/hvm/vmx/vmcs.c xen/arch/x86/hvm/vmx/vmx.c xen/include/asm-x86/hvm/vmx/vmcs.h xen/include/asm-x86/hvm/vmx/vmx.h |
line diff
1.1 --- a/xen/arch/x86/hvm/vmx/vmcs.c Mon Sep 25 17:45:28 2006 +0100 1.2 +++ b/xen/arch/x86/hvm/vmx/vmcs.c Mon Sep 25 17:46:08 2006 +0100 1.3 @@ -37,36 +37,119 @@ 1.4 #include <xen/keyhandler.h> 1.5 #include <asm/shadow.h> 1.6 1.7 -static int vmcs_size; 1.8 -static int vmcs_order; 1.9 +/* Basic flags for Pin-based VM-execution controls. */ 1.10 +#define MONITOR_PIN_BASED_EXEC_CONTROLS \ 1.11 + ( PIN_BASED_EXT_INTR_MASK | \ 1.12 + PIN_BASED_NMI_EXITING ) 1.13 + 1.14 +/* Basic flags for CPU-based VM-execution controls. */ 1.15 +#ifdef __x86_64__ 1.16 +#define MONITOR_CPU_BASED_EXEC_CONTROLS_SUBARCH \ 1.17 + ( CPU_BASED_CR8_LOAD_EXITING | \ 1.18 + CPU_BASED_CR8_STORE_EXITING ) 1.19 +#else 1.20 +#define MONITOR_CPU_BASED_EXEC_CONTROLS_SUBARCH 0 1.21 +#endif 1.22 +#define MONITOR_CPU_BASED_EXEC_CONTROLS \ 1.23 + ( MONITOR_CPU_BASED_EXEC_CONTROLS_SUBARCH | \ 1.24 + CPU_BASED_HLT_EXITING | \ 1.25 + CPU_BASED_INVDPG_EXITING | \ 1.26 + CPU_BASED_MWAIT_EXITING | \ 1.27 + CPU_BASED_MOV_DR_EXITING | \ 1.28 + CPU_BASED_ACTIVATE_IO_BITMAP | \ 1.29 + CPU_BASED_USE_TSC_OFFSETING ) 1.30 + 1.31 +/* Basic flags for VM-Exit controls. */ 1.32 +#ifdef __x86_64__ 1.33 +#define MONITOR_VM_EXIT_CONTROLS_SUBARCH VM_EXIT_IA32E_MODE 1.34 +#else 1.35 +#define MONITOR_VM_EXIT_CONTROLS_SUBARCH 0 1.36 +#endif 1.37 +#define MONITOR_VM_EXIT_CONTROLS \ 1.38 + ( MONITOR_VM_EXIT_CONTROLS_SUBARCH | \ 1.39 + VM_EXIT_ACK_INTR_ON_EXIT ) 1.40 + 1.41 +/* Basic flags for VM-Entry controls. */ 1.42 +#define MONITOR_VM_ENTRY_CONTROLS 0x00000000 1.43 + 1.44 +/* Dynamic (run-time adjusted) execution control flags. */ 1.45 +static u32 vmx_pin_based_exec_control; 1.46 +static u32 vmx_cpu_based_exec_control; 1.47 +static u32 vmx_vmexit_control; 1.48 +static u32 vmx_vmentry_control; 1.49 + 1.50 static u32 vmcs_revision_id; 1.51 1.52 +static u32 adjust_vmx_controls(u32 ctrls, u32 msr) 1.53 +{ 1.54 + u32 vmx_msr_low, vmx_msr_high; 1.55 + 1.56 + rdmsr(msr, vmx_msr_low, vmx_msr_high); 1.57 + 1.58 + /* Bit == 0 means must be zero. */ 1.59 + BUG_ON(ctrls & ~vmx_msr_high); 1.60 + 1.61 + /* Bit == 1 means must be one. */ 1.62 + ctrls |= vmx_msr_low; 1.63 + 1.64 + return ctrls; 1.65 +} 1.66 + 1.67 void vmx_init_vmcs_config(void) 1.68 { 1.69 u32 vmx_msr_low, vmx_msr_high; 1.70 + u32 _vmx_pin_based_exec_control; 1.71 + u32 _vmx_cpu_based_exec_control; 1.72 + u32 _vmx_vmexit_control; 1.73 + u32 _vmx_vmentry_control; 1.74 1.75 - if ( vmcs_size ) 1.76 - return; 1.77 + _vmx_pin_based_exec_control = 1.78 + adjust_vmx_controls(MONITOR_PIN_BASED_EXEC_CONTROLS, 1.79 + MSR_IA32_VMX_PINBASED_CTLS_MSR); 1.80 + _vmx_cpu_based_exec_control = 1.81 + adjust_vmx_controls(MONITOR_CPU_BASED_EXEC_CONTROLS, 1.82 + MSR_IA32_VMX_PROCBASED_CTLS_MSR); 1.83 + _vmx_vmexit_control = 1.84 + adjust_vmx_controls(MONITOR_VM_EXIT_CONTROLS, 1.85 + MSR_IA32_VMX_EXIT_CTLS_MSR); 1.86 + _vmx_vmentry_control = 1.87 + adjust_vmx_controls(MONITOR_VM_ENTRY_CONTROLS, 1.88 + MSR_IA32_VMX_ENTRY_CTLS_MSR); 1.89 1.90 rdmsr(MSR_IA32_VMX_BASIC_MSR, vmx_msr_low, vmx_msr_high); 1.91 1.92 - vmcs_revision_id = vmx_msr_low; 1.93 + if ( smp_processor_id() == 0 ) 1.94 + { 1.95 + vmcs_revision_id = vmx_msr_low; 1.96 + vmx_pin_based_exec_control = _vmx_pin_based_exec_control; 1.97 + vmx_cpu_based_exec_control = _vmx_cpu_based_exec_control; 1.98 + vmx_vmexit_control = _vmx_vmexit_control; 1.99 + vmx_vmentry_control = _vmx_vmentry_control; 1.100 + } 1.101 + else 1.102 + { 1.103 + BUG_ON(vmcs_revision_id != vmx_msr_low); 1.104 + BUG_ON(vmx_pin_based_exec_control != _vmx_pin_based_exec_control); 1.105 + BUG_ON(vmx_cpu_based_exec_control != _vmx_cpu_based_exec_control); 1.106 + BUG_ON(vmx_vmexit_control != _vmx_vmexit_control); 1.107 + BUG_ON(vmx_vmentry_control != _vmx_vmentry_control); 1.108 + } 1.109 1.110 - vmcs_size = vmx_msr_high & 0x1fff; 1.111 - vmcs_order = get_order_from_bytes(vmcs_size); 1.112 + /* IA-32 SDM Vol 3B: VMCS size is never greater than 4kB. */ 1.113 + BUG_ON((vmx_msr_high & 0x1fff) > PAGE_SIZE); 1.114 } 1.115 1.116 static struct vmcs_struct *vmx_alloc_vmcs(void) 1.117 { 1.118 struct vmcs_struct *vmcs; 1.119 1.120 - if ( (vmcs = alloc_xenheap_pages(vmcs_order)) == NULL ) 1.121 + if ( (vmcs = alloc_xenheap_page()) == NULL ) 1.122 { 1.123 DPRINTK("Failed to allocate VMCS.\n"); 1.124 return NULL; 1.125 } 1.126 1.127 - memset(vmcs, 0, vmcs_size); /* don't remove this */ 1.128 + memset(vmcs, 0, PAGE_SIZE); 1.129 vmcs->vmcs_revision_id = vmcs_revision_id; 1.130 1.131 return vmcs; 1.132 @@ -74,7 +157,7 @@ static struct vmcs_struct *vmx_alloc_vmc 1.133 1.134 static void vmx_free_vmcs(struct vmcs_struct *vmcs) 1.135 { 1.136 - free_xenheap_pages(vmcs, vmcs_order); 1.137 + free_xenheap_page(vmcs); 1.138 } 1.139 1.140 static void __vmx_clear_vmcs(void *info) 1.141 @@ -156,12 +239,11 @@ static inline int construct_vmcs_control 1.142 { 1.143 int error = 0; 1.144 1.145 - error |= __vmwrite(PIN_BASED_VM_EXEC_CONTROL, 1.146 - MONITOR_PIN_BASED_EXEC_CONTROLS); 1.147 + error |= __vmwrite(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_control); 1.148 1.149 - error |= __vmwrite(VM_EXIT_CONTROLS, MONITOR_VM_EXIT_CONTROLS); 1.150 + error |= __vmwrite(VM_EXIT_CONTROLS, vmx_vmexit_control); 1.151 1.152 - error |= __vmwrite(VM_ENTRY_CONTROLS, MONITOR_VM_ENTRY_CONTROLS); 1.153 + error |= __vmwrite(VM_ENTRY_CONTROLS, vmx_vmentry_control); 1.154 1.155 error |= __vmwrite(IO_BITMAP_A, virt_to_maddr(arch_vmx->io_bitmap_a)); 1.156 error |= __vmwrite(IO_BITMAP_B, virt_to_maddr(arch_vmx->io_bitmap_b)); 1.157 @@ -246,9 +328,8 @@ static void vmx_do_launch(struct vcpu *v 1.158 error |= __vmwrite(GUEST_CR0, cr0); 1.159 cr0 &= ~X86_CR0_PG; 1.160 error |= __vmwrite(CR0_READ_SHADOW, cr0); 1.161 - error |= __vmwrite(CPU_BASED_VM_EXEC_CONTROL, 1.162 - MONITOR_CPU_BASED_EXEC_CONTROLS); 1.163 - v->arch.hvm_vcpu.u.vmx.exec_control = MONITOR_CPU_BASED_EXEC_CONTROLS; 1.164 + error |= __vmwrite(CPU_BASED_VM_EXEC_CONTROL, vmx_cpu_based_exec_control); 1.165 + v->arch.hvm_vcpu.u.vmx.exec_control = vmx_cpu_based_exec_control; 1.166 1.167 __asm__ __volatile__ ("mov %%cr4,%0" : "=r" (cr4) : ); 1.168 1.169 @@ -297,22 +378,22 @@ static inline int construct_init_vmcs_gu 1.170 /* MSR */ 1.171 error |= __vmwrite(VM_EXIT_MSR_LOAD_ADDR, 0); 1.172 error |= __vmwrite(VM_EXIT_MSR_STORE_ADDR, 0); 1.173 - 1.174 error |= __vmwrite(VM_EXIT_MSR_STORE_COUNT, 0); 1.175 error |= __vmwrite(VM_EXIT_MSR_LOAD_COUNT, 0); 1.176 error |= __vmwrite(VM_ENTRY_MSR_LOAD_COUNT, 0); 1.177 - /* interrupt */ 1.178 + 1.179 error |= __vmwrite(VM_ENTRY_INTR_INFO_FIELD, 0); 1.180 - /* mask */ 1.181 - error |= __vmwrite(CR0_GUEST_HOST_MASK, -1UL); 1.182 - error |= __vmwrite(CR4_GUEST_HOST_MASK, -1UL); 1.183 + 1.184 + error |= __vmwrite(CR0_GUEST_HOST_MASK, ~0UL); 1.185 + error |= __vmwrite(CR4_GUEST_HOST_MASK, ~0UL); 1.186 1.187 error |= __vmwrite(PAGE_FAULT_ERROR_CODE_MASK, 0); 1.188 error |= __vmwrite(PAGE_FAULT_ERROR_CODE_MATCH, 0); 1.189 1.190 - /* TSC */ 1.191 error |= __vmwrite(CR3_TARGET_COUNT, 0); 1.192 1.193 + error |= __vmwrite(GUEST_ACTIVITY_STATE, 0); 1.194 + 1.195 /* Guest Selectors */ 1.196 error |= __vmwrite(GUEST_ES_SELECTOR, GUEST_LAUNCH_DS); 1.197 error |= __vmwrite(GUEST_SS_SELECTOR, GUEST_LAUNCH_DS);
2.1 --- a/xen/arch/x86/hvm/vmx/vmx.c Mon Sep 25 17:45:28 2006 +0100 2.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c Mon Sep 25 17:46:08 2006 +0100 2.3 @@ -684,21 +684,6 @@ static void vmx_init_ap_context(struct v 2.4 2.5 void do_nmi(struct cpu_user_regs *); 2.6 2.7 -static int check_vmx_controls(u32 ctrls, u32 msr) 2.8 -{ 2.9 - u32 vmx_msr_low, vmx_msr_high; 2.10 - 2.11 - rdmsr(msr, vmx_msr_low, vmx_msr_high); 2.12 - if ( (ctrls < vmx_msr_low) || (ctrls > vmx_msr_high) ) 2.13 - { 2.14 - printk("Insufficient VMX capability 0x%x, " 2.15 - "msr=0x%x,low=0x%8x,high=0x%x\n", 2.16 - ctrls, msr, vmx_msr_low, vmx_msr_high); 2.17 - return 0; 2.18 - } 2.19 - return 1; 2.20 -} 2.21 - 2.22 static void vmx_init_hypercall_page(struct domain *d, void *hypercall_page) 2.23 { 2.24 char *p; 2.25 @@ -791,7 +776,7 @@ int start_vmx(void) 2.26 */ 2.27 boot_cpu_data.x86_capability[4] = cpuid_ecx(1); 2.28 2.29 - if (!(test_bit(X86_FEATURE_VMXE, &boot_cpu_data.x86_capability))) 2.30 + if ( !test_bit(X86_FEATURE_VMXE, &boot_cpu_data.x86_capability) ) 2.31 return 0; 2.32 2.33 rdmsr(IA32_FEATURE_CONTROL_MSR, eax, edx); 2.34 @@ -811,24 +796,11 @@ int start_vmx(void) 2.35 IA32_FEATURE_CONTROL_MSR_ENABLE_VMXON, 0); 2.36 } 2.37 2.38 - if ( !check_vmx_controls(MONITOR_PIN_BASED_EXEC_CONTROLS, 2.39 - MSR_IA32_VMX_PINBASED_CTLS_MSR) ) 2.40 - return 0; 2.41 - if ( !check_vmx_controls(MONITOR_CPU_BASED_EXEC_CONTROLS, 2.42 - MSR_IA32_VMX_PROCBASED_CTLS_MSR) ) 2.43 - return 0; 2.44 - if ( !check_vmx_controls(MONITOR_VM_EXIT_CONTROLS, 2.45 - MSR_IA32_VMX_EXIT_CTLS_MSR) ) 2.46 - return 0; 2.47 - if ( !check_vmx_controls(MONITOR_VM_ENTRY_CONTROLS, 2.48 - MSR_IA32_VMX_ENTRY_CTLS_MSR) ) 2.49 - return 0; 2.50 - 2.51 set_in_cr4(X86_CR4_VMXE); 2.52 2.53 vmx_init_vmcs_config(); 2.54 - 2.55 - if(!smp_processor_id()) 2.56 + 2.57 + if ( smp_processor_id() == 0 ) 2.58 setup_vmcs_dump(); 2.59 2.60 if ( (vmcs = vmx_alloc_host_vmcs()) == NULL ) 2.61 @@ -1519,7 +1491,7 @@ static int vmx_set_cr0(unsigned long val 2.62 &v->arch.hvm_vmx.cpu_state); 2.63 2.64 __vmread(VM_ENTRY_CONTROLS, &vm_entry_value); 2.65 - vm_entry_value |= VM_ENTRY_CONTROLS_IA32E_MODE; 2.66 + vm_entry_value |= VM_ENTRY_IA32E_MODE; 2.67 __vmwrite(VM_ENTRY_CONTROLS, vm_entry_value); 2.68 } 2.69 #endif 2.70 @@ -1573,7 +1545,7 @@ static int vmx_set_cr0(unsigned long val 2.71 clear_bit(VMX_CPU_STATE_LMA_ENABLED, 2.72 &v->arch.hvm_vmx.cpu_state); 2.73 __vmread(VM_ENTRY_CONTROLS, &vm_entry_value); 2.74 - vm_entry_value &= ~VM_ENTRY_CONTROLS_IA32E_MODE; 2.75 + vm_entry_value &= ~VM_ENTRY_IA32E_MODE; 2.76 __vmwrite(VM_ENTRY_CONTROLS, vm_entry_value); 2.77 } 2.78 } 2.79 @@ -2296,15 +2268,8 @@ asmlinkage void vmx_vmexit_handler(struc 2.80 domain_crash_synchronous(); 2.81 break; 2.82 case EXIT_REASON_PENDING_INTERRUPT: 2.83 - /* 2.84 - * Not sure exactly what the purpose of this is. The only bits set 2.85 - * and cleared at this point are CPU_BASED_VIRTUAL_INTR_PENDING. 2.86 - * (in io.c:{enable,disable}_irq_window(). So presumably we want to 2.87 - * set it to the original value... 2.88 - */ 2.89 + /* Disable the interrupt window. */ 2.90 v->arch.hvm_vcpu.u.vmx.exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING; 2.91 - v->arch.hvm_vcpu.u.vmx.exec_control |= 2.92 - (MONITOR_CPU_BASED_EXEC_CONTROLS & CPU_BASED_VIRTUAL_INTR_PENDING); 2.93 __vmwrite(CPU_BASED_VM_EXEC_CONTROL, 2.94 v->arch.hvm_vcpu.u.vmx.exec_control); 2.95 break;
3.1 --- a/xen/include/asm-x86/hvm/vmx/vmcs.h Mon Sep 25 17:45:28 2006 +0100 3.2 +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h Mon Sep 25 17:46:08 2006 +0100 3.3 @@ -132,12 +132,16 @@ extern int vmcs_version; 3.4 #define CPU_BASED_ACTIVATE_IO_BITMAP 0x02000000 3.5 #define CPU_BASED_MONITOR_EXITING 0x20000000 3.6 #define CPU_BASED_PAUSE_EXITING 0x40000000 3.7 -#define PIN_BASED_EXT_INTR_MASK 0x1 3.8 -#define PIN_BASED_NMI_EXITING 0x8 3.9 + 3.10 +#define PIN_BASED_EXT_INTR_MASK 0x00000001 3.11 +#define PIN_BASED_NMI_EXITING 0x00000008 3.12 3.13 +#define VM_EXIT_IA32E_MODE 0x00000200 3.14 #define VM_EXIT_ACK_INTR_ON_EXIT 0x00008000 3.15 -#define VM_EXIT_HOST_ADD_SPACE_SIZE 0x00000200 3.16 3.17 +#define VM_ENTRY_IA32E_MODE 0x00000200 3.18 +#define VM_ENTRY_SMM 0x00000400 3.19 +#define VM_ENTRY_DEACT_DUAL_MONITOR 0x00000800 3.20 3.21 /* VMCS Encordings */ 3.22 enum vmcs_field { 3.23 @@ -217,6 +221,7 @@ enum vmcs_field { 3.24 GUEST_LDTR_AR_BYTES = 0x00004820, 3.25 GUEST_TR_AR_BYTES = 0x00004822, 3.26 GUEST_INTERRUPTIBILITY_INFO = 0x00004824, 3.27 + GUEST_ACTIVITY_STATE = 0x00004826, 3.28 GUEST_SYSENTER_CS = 0x0000482A, 3.29 HOST_IA32_SYSENTER_CS = 0x00004c00, 3.30 CR0_GUEST_HOST_MASK = 0x00006000,
4.1 --- a/xen/include/asm-x86/hvm/vmx/vmx.h Mon Sep 25 17:45:28 2006 +0100 4.2 +++ b/xen/include/asm-x86/hvm/vmx/vmx.h Mon Sep 25 17:46:08 2006 +0100 4.3 @@ -37,73 +37,6 @@ extern void set_guest_time(struct vcpu * 4.4 extern unsigned int cpu_rev; 4.5 4.6 /* 4.7 - * Need fill bits for SENTER 4.8 - */ 4.9 - 4.10 -#define MONITOR_PIN_BASED_EXEC_CONTROLS_RESERVED_VALUE 0x00000016 4.11 - 4.12 -#define MONITOR_PIN_BASED_EXEC_CONTROLS \ 4.13 - ( \ 4.14 - MONITOR_PIN_BASED_EXEC_CONTROLS_RESERVED_VALUE | \ 4.15 - PIN_BASED_EXT_INTR_MASK | \ 4.16 - PIN_BASED_NMI_EXITING \ 4.17 - ) 4.18 - 4.19 -#define MONITOR_CPU_BASED_EXEC_CONTROLS_RESERVED_VALUE 0x0401e172 4.20 - 4.21 -#define _MONITOR_CPU_BASED_EXEC_CONTROLS \ 4.22 - ( \ 4.23 - MONITOR_CPU_BASED_EXEC_CONTROLS_RESERVED_VALUE | \ 4.24 - CPU_BASED_HLT_EXITING | \ 4.25 - CPU_BASED_INVDPG_EXITING | \ 4.26 - CPU_BASED_MWAIT_EXITING | \ 4.27 - CPU_BASED_MOV_DR_EXITING | \ 4.28 - CPU_BASED_ACTIVATE_IO_BITMAP | \ 4.29 - CPU_BASED_USE_TSC_OFFSETING \ 4.30 - ) 4.31 - 4.32 -#define MONITOR_CPU_BASED_EXEC_CONTROLS_IA32E_MODE \ 4.33 - ( \ 4.34 - CPU_BASED_CR8_LOAD_EXITING | \ 4.35 - CPU_BASED_CR8_STORE_EXITING \ 4.36 - ) 4.37 - 4.38 -#define MONITOR_VM_EXIT_CONTROLS_RESERVED_VALUE 0x0003edff 4.39 - 4.40 -#define MONITOR_VM_EXIT_CONTROLS_IA32E_MODE 0x00000200 4.41 - 4.42 -#define _MONITOR_VM_EXIT_CONTROLS \ 4.43 - ( \ 4.44 - MONITOR_VM_EXIT_CONTROLS_RESERVED_VALUE | \ 4.45 - VM_EXIT_ACK_INTR_ON_EXIT \ 4.46 - ) 4.47 - 4.48 -#if defined (__x86_64__) 4.49 -#define MONITOR_CPU_BASED_EXEC_CONTROLS \ 4.50 - ( \ 4.51 - _MONITOR_CPU_BASED_EXEC_CONTROLS | \ 4.52 - MONITOR_CPU_BASED_EXEC_CONTROLS_IA32E_MODE \ 4.53 - ) 4.54 -#define MONITOR_VM_EXIT_CONTROLS \ 4.55 - ( \ 4.56 - _MONITOR_VM_EXIT_CONTROLS | \ 4.57 - MONITOR_VM_EXIT_CONTROLS_IA32E_MODE \ 4.58 - ) 4.59 -#else 4.60 -#define MONITOR_CPU_BASED_EXEC_CONTROLS \ 4.61 - _MONITOR_CPU_BASED_EXEC_CONTROLS 4.62 - 4.63 -#define MONITOR_VM_EXIT_CONTROLS \ 4.64 - _MONITOR_VM_EXIT_CONTROLS 4.65 -#endif 4.66 - 4.67 -#define VM_ENTRY_CONTROLS_RESERVED_VALUE 0x000011ff 4.68 -#define VM_ENTRY_CONTROLS_IA32E_MODE 0x00000200 4.69 - 4.70 -#define MONITOR_VM_ENTRY_CONTROLS \ 4.71 - VM_ENTRY_CONTROLS_RESERVED_VALUE 4.72 - 4.73 -/* 4.74 * Exit Reasons 4.75 */ 4.76 #define VMX_EXIT_REASONS_FAILED_VMENTRY 0x80000000