[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [XEN] Simplify VMCS allocation (never bigger than a page).
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Node ID 0f9908c2c5c75d787d70a13b01506d1dca49290a # Parent f5fd563bcc84f5bb67ceb1031c127ce44515507a [XEN] Simplify VMCS allocation (never bigger than a page). Dynamically determine reserved bits in execution-control fields. Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> --- xen/arch/x86/hvm/vmx/vmcs.c | 135 +++++++++++++++++++++++++++++-------- xen/arch/x86/hvm/vmx/vmx.c | 47 +----------- xen/include/asm-x86/hvm/vmx/vmcs.h | 15 ++-- xen/include/asm-x86/hvm/vmx/vmx.h | 67 ------------------ 4 files changed, 124 insertions(+), 140 deletions(-) diff -r f5fd563bcc84 -r 0f9908c2c5c7 xen/arch/x86/hvm/vmx/vmcs.c --- a/xen/arch/x86/hvm/vmx/vmcs.c Mon Sep 25 17:45:28 2006 +0100 +++ b/xen/arch/x86/hvm/vmx/vmcs.c Mon Sep 25 17:46:08 2006 +0100 @@ -37,36 +37,119 @@ #include <xen/keyhandler.h> #include <asm/shadow.h> -static int vmcs_size; -static int vmcs_order; +/* Basic flags for Pin-based VM-execution controls. */ +#define MONITOR_PIN_BASED_EXEC_CONTROLS \ + ( PIN_BASED_EXT_INTR_MASK | \ + PIN_BASED_NMI_EXITING ) + +/* Basic flags for CPU-based VM-execution controls. */ +#ifdef __x86_64__ +#define MONITOR_CPU_BASED_EXEC_CONTROLS_SUBARCH \ + ( CPU_BASED_CR8_LOAD_EXITING | \ + CPU_BASED_CR8_STORE_EXITING ) +#else +#define MONITOR_CPU_BASED_EXEC_CONTROLS_SUBARCH 0 +#endif +#define MONITOR_CPU_BASED_EXEC_CONTROLS \ + ( MONITOR_CPU_BASED_EXEC_CONTROLS_SUBARCH | \ + CPU_BASED_HLT_EXITING | \ + CPU_BASED_INVDPG_EXITING | \ + CPU_BASED_MWAIT_EXITING | \ + CPU_BASED_MOV_DR_EXITING | \ + CPU_BASED_ACTIVATE_IO_BITMAP | \ + CPU_BASED_USE_TSC_OFFSETING ) + +/* Basic flags for VM-Exit controls. */ +#ifdef __x86_64__ +#define MONITOR_VM_EXIT_CONTROLS_SUBARCH VM_EXIT_IA32E_MODE +#else +#define MONITOR_VM_EXIT_CONTROLS_SUBARCH 0 +#endif +#define MONITOR_VM_EXIT_CONTROLS \ + ( MONITOR_VM_EXIT_CONTROLS_SUBARCH | \ + VM_EXIT_ACK_INTR_ON_EXIT ) + +/* Basic flags for VM-Entry controls. */ +#define MONITOR_VM_ENTRY_CONTROLS 0x00000000 + +/* Dynamic (run-time adjusted) execution control flags. */ +static u32 vmx_pin_based_exec_control; +static u32 vmx_cpu_based_exec_control; +static u32 vmx_vmexit_control; +static u32 vmx_vmentry_control; + static u32 vmcs_revision_id; +static u32 adjust_vmx_controls(u32 ctrls, u32 msr) +{ + u32 vmx_msr_low, vmx_msr_high; + + rdmsr(msr, vmx_msr_low, vmx_msr_high); + + /* Bit == 0 means must be zero. */ + BUG_ON(ctrls & ~vmx_msr_high); + + /* Bit == 1 means must be one. */ + ctrls |= vmx_msr_low; + + return ctrls; +} + void vmx_init_vmcs_config(void) { u32 vmx_msr_low, vmx_msr_high; - - if ( vmcs_size ) - return; + u32 _vmx_pin_based_exec_control; + u32 _vmx_cpu_based_exec_control; + u32 _vmx_vmexit_control; + u32 _vmx_vmentry_control; + + _vmx_pin_based_exec_control = + adjust_vmx_controls(MONITOR_PIN_BASED_EXEC_CONTROLS, + MSR_IA32_VMX_PINBASED_CTLS_MSR); + _vmx_cpu_based_exec_control = + adjust_vmx_controls(MONITOR_CPU_BASED_EXEC_CONTROLS, + MSR_IA32_VMX_PROCBASED_CTLS_MSR); + _vmx_vmexit_control = + adjust_vmx_controls(MONITOR_VM_EXIT_CONTROLS, + MSR_IA32_VMX_EXIT_CTLS_MSR); + _vmx_vmentry_control = + adjust_vmx_controls(MONITOR_VM_ENTRY_CONTROLS, + MSR_IA32_VMX_ENTRY_CTLS_MSR); rdmsr(MSR_IA32_VMX_BASIC_MSR, vmx_msr_low, vmx_msr_high); - vmcs_revision_id = vmx_msr_low; - - vmcs_size = vmx_msr_high & 0x1fff; - vmcs_order = get_order_from_bytes(vmcs_size); + if ( smp_processor_id() == 0 ) + { + vmcs_revision_id = vmx_msr_low; + vmx_pin_based_exec_control = _vmx_pin_based_exec_control; + vmx_cpu_based_exec_control = _vmx_cpu_based_exec_control; + vmx_vmexit_control = _vmx_vmexit_control; + vmx_vmentry_control = _vmx_vmentry_control; + } + else + { + BUG_ON(vmcs_revision_id != vmx_msr_low); + BUG_ON(vmx_pin_based_exec_control != _vmx_pin_based_exec_control); + BUG_ON(vmx_cpu_based_exec_control != _vmx_cpu_based_exec_control); + BUG_ON(vmx_vmexit_control != _vmx_vmexit_control); + BUG_ON(vmx_vmentry_control != _vmx_vmentry_control); + } + + /* IA-32 SDM Vol 3B: VMCS size is never greater than 4kB. */ + BUG_ON((vmx_msr_high & 0x1fff) > PAGE_SIZE); } static struct vmcs_struct *vmx_alloc_vmcs(void) { struct vmcs_struct *vmcs; - if ( (vmcs = alloc_xenheap_pages(vmcs_order)) == NULL ) + if ( (vmcs = alloc_xenheap_page()) == NULL ) { DPRINTK("Failed to allocate VMCS.\n"); return NULL; } - memset(vmcs, 0, vmcs_size); /* don't remove this */ + memset(vmcs, 0, PAGE_SIZE); vmcs->vmcs_revision_id = vmcs_revision_id; return vmcs; @@ -74,7 +157,7 @@ static struct vmcs_struct *vmx_alloc_vmc static void vmx_free_vmcs(struct vmcs_struct *vmcs) { - free_xenheap_pages(vmcs, vmcs_order); + free_xenheap_page(vmcs); } static void __vmx_clear_vmcs(void *info) @@ -156,12 +239,11 @@ static inline int construct_vmcs_control { int error = 0; - error |= __vmwrite(PIN_BASED_VM_EXEC_CONTROL, - MONITOR_PIN_BASED_EXEC_CONTROLS); - - error |= __vmwrite(VM_EXIT_CONTROLS, MONITOR_VM_EXIT_CONTROLS); - - error |= __vmwrite(VM_ENTRY_CONTROLS, MONITOR_VM_ENTRY_CONTROLS); + error |= __vmwrite(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_control); + + error |= __vmwrite(VM_EXIT_CONTROLS, vmx_vmexit_control); + + error |= __vmwrite(VM_ENTRY_CONTROLS, vmx_vmentry_control); error |= __vmwrite(IO_BITMAP_A, virt_to_maddr(arch_vmx->io_bitmap_a)); error |= __vmwrite(IO_BITMAP_B, virt_to_maddr(arch_vmx->io_bitmap_b)); @@ -246,9 +328,8 @@ static void vmx_do_launch(struct vcpu *v error |= __vmwrite(GUEST_CR0, cr0); cr0 &= ~X86_CR0_PG; error |= __vmwrite(CR0_READ_SHADOW, cr0); - error |= __vmwrite(CPU_BASED_VM_EXEC_CONTROL, - MONITOR_CPU_BASED_EXEC_CONTROLS); - v->arch.hvm_vcpu.u.vmx.exec_control = MONITOR_CPU_BASED_EXEC_CONTROLS; + error |= __vmwrite(CPU_BASED_VM_EXEC_CONTROL, vmx_cpu_based_exec_control); + v->arch.hvm_vcpu.u.vmx.exec_control = vmx_cpu_based_exec_control; __asm__ __volatile__ ("mov %%cr4,%0" : "=r" (cr4) : ); @@ -297,21 +378,21 @@ static inline int construct_init_vmcs_gu /* MSR */ error |= __vmwrite(VM_EXIT_MSR_LOAD_ADDR, 0); error |= __vmwrite(VM_EXIT_MSR_STORE_ADDR, 0); - error |= __vmwrite(VM_EXIT_MSR_STORE_COUNT, 0); error |= __vmwrite(VM_EXIT_MSR_LOAD_COUNT, 0); error |= __vmwrite(VM_ENTRY_MSR_LOAD_COUNT, 0); - /* interrupt */ + error |= __vmwrite(VM_ENTRY_INTR_INFO_FIELD, 0); - /* mask */ - error |= __vmwrite(CR0_GUEST_HOST_MASK, -1UL); - error |= __vmwrite(CR4_GUEST_HOST_MASK, -1UL); + + error |= __vmwrite(CR0_GUEST_HOST_MASK, ~0UL); + error |= __vmwrite(CR4_GUEST_HOST_MASK, ~0UL); error |= __vmwrite(PAGE_FAULT_ERROR_CODE_MASK, 0); error |= __vmwrite(PAGE_FAULT_ERROR_CODE_MATCH, 0); - /* TSC */ error |= __vmwrite(CR3_TARGET_COUNT, 0); + + error |= __vmwrite(GUEST_ACTIVITY_STATE, 0); /* Guest Selectors */ error |= __vmwrite(GUEST_ES_SELECTOR, GUEST_LAUNCH_DS); diff -r f5fd563bcc84 -r 0f9908c2c5c7 xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Mon Sep 25 17:45:28 2006 +0100 +++ b/xen/arch/x86/hvm/vmx/vmx.c Mon Sep 25 17:46:08 2006 +0100 @@ -684,21 +684,6 @@ static void vmx_init_ap_context(struct v void do_nmi(struct cpu_user_regs *); -static int check_vmx_controls(u32 ctrls, u32 msr) -{ - u32 vmx_msr_low, vmx_msr_high; - - rdmsr(msr, vmx_msr_low, vmx_msr_high); - if ( (ctrls < vmx_msr_low) || (ctrls > vmx_msr_high) ) - { - printk("Insufficient VMX capability 0x%x, " - "msr=0x%x,low=0x%8x,high=0x%x\n", - ctrls, msr, vmx_msr_low, vmx_msr_high); - return 0; - } - return 1; -} - static void vmx_init_hypercall_page(struct domain *d, void *hypercall_page) { char *p; @@ -791,7 +776,7 @@ int start_vmx(void) */ boot_cpu_data.x86_capability[4] = cpuid_ecx(1); - if (!(test_bit(X86_FEATURE_VMXE, &boot_cpu_data.x86_capability))) + if ( !test_bit(X86_FEATURE_VMXE, &boot_cpu_data.x86_capability) ) return 0; rdmsr(IA32_FEATURE_CONTROL_MSR, eax, edx); @@ -811,24 +796,11 @@ int start_vmx(void) IA32_FEATURE_CONTROL_MSR_ENABLE_VMXON, 0); } - if ( !check_vmx_controls(MONITOR_PIN_BASED_EXEC_CONTROLS, - MSR_IA32_VMX_PINBASED_CTLS_MSR) ) - return 0; - if ( !check_vmx_controls(MONITOR_CPU_BASED_EXEC_CONTROLS, - MSR_IA32_VMX_PROCBASED_CTLS_MSR) ) - return 0; - if ( !check_vmx_controls(MONITOR_VM_EXIT_CONTROLS, - MSR_IA32_VMX_EXIT_CTLS_MSR) ) - return 0; - if ( !check_vmx_controls(MONITOR_VM_ENTRY_CONTROLS, - MSR_IA32_VMX_ENTRY_CTLS_MSR) ) - return 0; - set_in_cr4(X86_CR4_VMXE); vmx_init_vmcs_config(); - - if(!smp_processor_id()) + + if ( smp_processor_id() == 0 ) setup_vmcs_dump(); if ( (vmcs = vmx_alloc_host_vmcs()) == NULL ) @@ -1519,7 +1491,7 @@ static int vmx_set_cr0(unsigned long val &v->arch.hvm_vmx.cpu_state); __vmread(VM_ENTRY_CONTROLS, &vm_entry_value); - vm_entry_value |= VM_ENTRY_CONTROLS_IA32E_MODE; + vm_entry_value |= VM_ENTRY_IA32E_MODE; __vmwrite(VM_ENTRY_CONTROLS, vm_entry_value); } #endif @@ -1573,7 +1545,7 @@ static int vmx_set_cr0(unsigned long val clear_bit(VMX_CPU_STATE_LMA_ENABLED, &v->arch.hvm_vmx.cpu_state); __vmread(VM_ENTRY_CONTROLS, &vm_entry_value); - vm_entry_value &= ~VM_ENTRY_CONTROLS_IA32E_MODE; + vm_entry_value &= ~VM_ENTRY_IA32E_MODE; __vmwrite(VM_ENTRY_CONTROLS, vm_entry_value); } } @@ -2296,15 +2268,8 @@ asmlinkage void vmx_vmexit_handler(struc domain_crash_synchronous(); break; case EXIT_REASON_PENDING_INTERRUPT: - /* - * Not sure exactly what the purpose of this is. The only bits set - * and cleared at this point are CPU_BASED_VIRTUAL_INTR_PENDING. - * (in io.c:{enable,disable}_irq_window(). So presumably we want to - * set it to the original value... - */ + /* Disable the interrupt window. */ v->arch.hvm_vcpu.u.vmx.exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING; - v->arch.hvm_vcpu.u.vmx.exec_control |= - (MONITOR_CPU_BASED_EXEC_CONTROLS & CPU_BASED_VIRTUAL_INTR_PENDING); __vmwrite(CPU_BASED_VM_EXEC_CONTROL, v->arch.hvm_vcpu.u.vmx.exec_control); break; diff -r f5fd563bcc84 -r 0f9908c2c5c7 xen/include/asm-x86/hvm/vmx/vmcs.h --- a/xen/include/asm-x86/hvm/vmx/vmcs.h Mon Sep 25 17:45:28 2006 +0100 +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h Mon Sep 25 17:46:08 2006 +0100 @@ -132,12 +132,16 @@ extern int vmcs_version; #define CPU_BASED_ACTIVATE_IO_BITMAP 0x02000000 #define CPU_BASED_MONITOR_EXITING 0x20000000 #define CPU_BASED_PAUSE_EXITING 0x40000000 -#define PIN_BASED_EXT_INTR_MASK 0x1 -#define PIN_BASED_NMI_EXITING 0x8 - + +#define PIN_BASED_EXT_INTR_MASK 0x00000001 +#define PIN_BASED_NMI_EXITING 0x00000008 + +#define VM_EXIT_IA32E_MODE 0x00000200 #define VM_EXIT_ACK_INTR_ON_EXIT 0x00008000 -#define VM_EXIT_HOST_ADD_SPACE_SIZE 0x00000200 - + +#define VM_ENTRY_IA32E_MODE 0x00000200 +#define VM_ENTRY_SMM 0x00000400 +#define VM_ENTRY_DEACT_DUAL_MONITOR 0x00000800 /* VMCS Encordings */ enum vmcs_field { @@ -217,6 +221,7 @@ enum vmcs_field { GUEST_LDTR_AR_BYTES = 0x00004820, GUEST_TR_AR_BYTES = 0x00004822, GUEST_INTERRUPTIBILITY_INFO = 0x00004824, + GUEST_ACTIVITY_STATE = 0x00004826, GUEST_SYSENTER_CS = 0x0000482A, HOST_IA32_SYSENTER_CS = 0x00004c00, CR0_GUEST_HOST_MASK = 0x00006000, diff -r f5fd563bcc84 -r 0f9908c2c5c7 xen/include/asm-x86/hvm/vmx/vmx.h --- a/xen/include/asm-x86/hvm/vmx/vmx.h Mon Sep 25 17:45:28 2006 +0100 +++ b/xen/include/asm-x86/hvm/vmx/vmx.h Mon Sep 25 17:46:08 2006 +0100 @@ -35,73 +35,6 @@ extern void set_guest_time(struct vcpu * extern void set_guest_time(struct vcpu *v, u64 gtime); extern unsigned int cpu_rev; - -/* - * Need fill bits for SENTER - */ - -#define MONITOR_PIN_BASED_EXEC_CONTROLS_RESERVED_VALUE 0x00000016 - -#define MONITOR_PIN_BASED_EXEC_CONTROLS \ - ( \ - MONITOR_PIN_BASED_EXEC_CONTROLS_RESERVED_VALUE | \ - PIN_BASED_EXT_INTR_MASK | \ - PIN_BASED_NMI_EXITING \ - ) - -#define MONITOR_CPU_BASED_EXEC_CONTROLS_RESERVED_VALUE 0x0401e172 - -#define _MONITOR_CPU_BASED_EXEC_CONTROLS \ - ( \ - MONITOR_CPU_BASED_EXEC_CONTROLS_RESERVED_VALUE | \ - CPU_BASED_HLT_EXITING | \ - CPU_BASED_INVDPG_EXITING | \ - CPU_BASED_MWAIT_EXITING | \ - CPU_BASED_MOV_DR_EXITING | \ - CPU_BASED_ACTIVATE_IO_BITMAP | \ - CPU_BASED_USE_TSC_OFFSETING \ - ) - -#define MONITOR_CPU_BASED_EXEC_CONTROLS_IA32E_MODE \ - ( \ - CPU_BASED_CR8_LOAD_EXITING | \ - CPU_BASED_CR8_STORE_EXITING \ - ) - -#define MONITOR_VM_EXIT_CONTROLS_RESERVED_VALUE 0x0003edff - -#define MONITOR_VM_EXIT_CONTROLS_IA32E_MODE 0x00000200 - -#define _MONITOR_VM_EXIT_CONTROLS \ - ( \ - MONITOR_VM_EXIT_CONTROLS_RESERVED_VALUE | \ - VM_EXIT_ACK_INTR_ON_EXIT \ - ) - -#if defined (__x86_64__) -#define MONITOR_CPU_BASED_EXEC_CONTROLS \ - ( \ - _MONITOR_CPU_BASED_EXEC_CONTROLS | \ - MONITOR_CPU_BASED_EXEC_CONTROLS_IA32E_MODE \ - ) -#define MONITOR_VM_EXIT_CONTROLS \ - ( \ - _MONITOR_VM_EXIT_CONTROLS | \ - MONITOR_VM_EXIT_CONTROLS_IA32E_MODE \ - ) -#else -#define MONITOR_CPU_BASED_EXEC_CONTROLS \ - _MONITOR_CPU_BASED_EXEC_CONTROLS - -#define MONITOR_VM_EXIT_CONTROLS \ - _MONITOR_VM_EXIT_CONTROLS -#endif - -#define VM_ENTRY_CONTROLS_RESERVED_VALUE 0x000011ff -#define VM_ENTRY_CONTROLS_IA32E_MODE 0x00000200 - -#define MONITOR_VM_ENTRY_CONTROLS \ - VM_ENTRY_CONTROLS_RESERVED_VALUE /* * Exit Reasons _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |