From: Andy Gogke Date: Wed, 15 Jul 2009 21:32:15 +0000 (-0500) Subject: Additional VMX support. Bootstrapping code added. X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=f8b365257743be47363da720f0261f5ed6441c57;hp=2de2dfce9b3673735569403294b0fb2a01884a8a;p=palacios.git Additional VMX support. Bootstrapping code added. --- diff --git a/palacios/include/palacios/vmcs.h b/palacios/include/palacios/vmcs.h index 9acdc20..392ddc3 100644 --- a/palacios/include/palacios/vmcs.h +++ b/palacios/include/palacios/vmcs.h @@ -28,208 +28,181 @@ #include - -/* 16 bit guest state */ -#define VMCS_GUEST_ES_SELECTOR 0x00000800 -#define VMCS_GUEST_CS_SELECTOR 0x00000802 -#define VMCS_GUEST_SS_SELECTOR 0x00000804 -#define VMCS_GUEST_DS_SELECTOR 0x00000806 -#define VMCS_GUEST_FS_SELECTOR 0x00000808 -#define VMCS_GUEST_GS_SELECTOR 0x0000080A -#define VMCS_GUEST_LDTR_SELECTOR 0x0000080C -#define VMCS_GUEST_TR_SELECTOR 0x0000080E - -/* 16 bit host state */ -#define VMCS_HOST_ES_SELECTOR 0x00000C00 -#define VMCS_HOST_CS_SELECTOR 0x00000C02 -#define VMCS_HOST_SS_SELECTOR 0x00000C04 -#define VMCS_HOST_DS_SELECTOR 0x00000C06 -#define VMCS_HOST_FS_SELECTOR 0x00000C08 -#define VMCS_HOST_GS_SELECTOR 0x00000C0A -#define VMCS_HOST_TR_SELECTOR 0x00000C0C - -/* 64 bit control fields */ -#define IO_BITMAP_A_ADDR 0x00002000 -#define IO_BITMAP_A_ADDR_HIGH 0x00002001 -#define IO_BITMAP_B_ADDR 0x00002002 -#define IO_BITMAP_B_ADDR_HIGH 0x00002003 -// Only with "Use MSR Bitmaps" enabled -#define MSR_BITMAPS 0x00002004 -#define MSR_BITMAPS_HIGH 0x00002005 -// -#define VM_EXIT_MSR_STORE_ADDR 0x00002006 -#define VM_EXIT_MSR_STORE_ADDR_HIGH 0x00002007 -#define VM_EXIT_MSR_LOAD_ADDR 0x00002008 -#define VM_EXIT_MSR_LOAD_ADDR_HIGH 0x00002009 -#define VM_ENTRY_MSR_LOAD_ADDR 0x0000200A -#define VM_ENTRY_MSR_LOAD_ADDR_HIGH 0x0000200B -#define VMCS_EXEC_PTR 0x0000200C -#define VMCS_EXEC_PTR_HIGH 0x0000200D -#define TSC_OFFSET 0x00002010 -#define TSC_OFFSET_HIGH 0x00002011 -// Only with "Use TPR Shadow" enabled -#define VIRT_APIC_PAGE_ADDR 0x00002012 -#define VIRT_APIC_PAGE_ADDR_HIGH 0x00002013 -// - - -/* 64 bit guest state fields */ -#define VMCS_LINK_PTR 0x00002800 -#define VMCS_LINK_PTR_HIGH 0x00002801 -#define GUEST_IA32_DEBUGCTL 0x00002802 -#define GUEST_IA32_DEBUGCTL_HIGH 0x00002803 -#define GUEST_IA32_PERF_GLOBAL_CTRL 0x00002808 -#define GUEST_IA32_PERF_GLOBAL_CTRL_HIGH 0x00002809 - -/* 32 bit control fields */ -#define PIN_VM_EXEC_CTRLS 0x00004000 -#define PROC_VM_EXEC_CTRLS 0x00004002 -#define EXCEPTION_BITMAP 0x00004004 -#define PAGE_FAULT_ERROR_MASK 0x00004006 -#define PAGE_FAULT_ERROR_MATCH 0x00004008 -#define CR3_TARGET_COUNT 0x0000400A -#define VM_EXIT_CTRLS 0x0000400C -#define VM_EXIT_MSR_STORE_COUNT 0x0000400E -#define VM_EXIT_MSR_LOAD_COUNT 0x00004010 -#define VM_ENTRY_CTRLS 0x00004012 -#define VM_ENTRY_MSR_LOAD_COUNT 0x00004014 -#define VM_ENTRY_INT_INFO_FIELD 0x00004016 -#define VM_ENTRY_EXCEPTION_ERROR 0x00004018 -#define VM_ENTRY_INSTR_LENGTH 0x0000401A -// Only with "Use TPR Shadow" Enabled -#define TPR_THRESHOLD 0x0000401C -// - - - - -/* 32 bit Read Only data fields */ -#define VM_INSTR_ERROR 0x00004400 -#define EXIT_REASON 0x00004402 -#define VM_EXIT_INT_INFO 0x00004404 -#define VM_EXIT_INT_ERROR 0x00004406 -#define IDT_VECTOR_INFO 0x00004408 -#define IDT_VECTOR_ERROR 0x0000440A -#define VM_EXIT_INSTR_LENGTH 0x0000440C -#define VMX_INSTR_INFO 0x0000440E - -/* 32 bit Guest state fields */ -#define GUEST_ES_LIMIT 0x00004800 -#define GUEST_CS_LIMIT 0x00004802 -#define GUEST_SS_LIMIT 0x00004804 -#define GUEST_DS_LIMIT 0x00004806 -#define GUEST_FS_LIMIT 0x00004808 -#define GUEST_GS_LIMIT 0x0000480A -#define GUEST_LDTR_LIMIT 0x0000480C -#define GUEST_TR_LIMIT 0x0000480E -#define GUEST_GDTR_LIMIT 0x00004810 -#define GUEST_IDTR_LIMIT 0x00004812 -#define GUEST_ES_ACCESS 0x00004814 -#define GUEST_CS_ACCESS 0x00004816 -#define GUEST_SS_ACCESS 0x00004818 -#define GUEST_DS_ACCESS 0x0000481A -#define GUEST_FS_ACCESS 0x0000481C -#define GUEST_GS_ACCESS 0x0000481E -#define GUEST_LDTR_ACCESS 0x00004820 -#define GUEST_TR_ACCESS 0x00004822 -#define GUEST_INT_STATE 0x00004824 -#define GUEST_ACTIVITY_STATE 0x00004826 -#define GUEST_SMBASE 0x00004828 -#define GUEST_IA32_SYSENTER_CS 0x0000482A - - -/* 32 bit host state field */ -#define HOST_IA32_SYSENTER_CS 0x00004C00 - -/* Natural Width Control Fields */ -#define CR0_GUEST_HOST_MASK 0x00006000 -#define CR4_GUEST_HOST_MASK 0x00006002 -#define CR0_READ_SHADOW 0x00006004 -#define CR4_READ_SHADOW 0x00006006 -#define CR3_TARGET_VALUE_0 0x00006008 -#define CR3_TARGET_VALUE_1 0x0000600A -#define CR3_TARGET_VALUE_2 0x0000600C -#define CR3_TARGET_VALUE_3 0x0000600E - - -/* Natural Width Read Only Fields */ -#define EXIT_QUALIFICATION 0x00006400 -#define IO_RCX 0x00006402 -#define IO_RSI 0x00006404 -#define IO_RDI 0x00006406 -#define IO_RIP 0x00006408 -#define GUEST_LINEAR_ADDR 0x0000640A - -/* Natural Width Guest State Fields */ -#define GUEST_CR0 0x00006800 -#define GUEST_CR3 0x00006802 -#define GUEST_CR4 0x00006804 -#define GUEST_ES_BASE 0x00006806 -#define GUEST_CS_BASE 0x00006808 -#define GUEST_SS_BASE 0x0000680A -#define GUEST_DS_BASE 0x0000680C -#define GUEST_FS_BASE 0x0000680E -#define GUEST_GS_BASE 0x00006810 -#define GUEST_LDTR_BASE 0x00006812 -#define GUEST_TR_BASE 0x00006814 -#define GUEST_GDTR_BASE 0x00006816 -#define GUEST_IDTR_BASE 0x00006818 -#define GUEST_DR7 0x0000681A -#define GUEST_RSP 0x0000681C -#define GUEST_RIP 0x0000681E -#define GUEST_RFLAGS 0x00006820 -#define GUEST_PENDING_DEBUG_EXCS 0x00006822 -#define GUEST_IA32_SYSENTER_ESP 0x00006824 -#define GUEST_IA32_SYSENTER_EIP 0x00006826 - - -/* Natural Width Host State Fields */ -#define HOST_CR0 0x00006C00 -#define HOST_CR3 0x00006C02 -#define HOST_CR4 0x00006C04 -#define HOST_FS_BASE 0x00006C06 -#define HOST_GS_BASE 0x00006C08 -#define HOST_TR_BASE 0x00006C0A -#define HOST_GDTR_BASE 0x00006C0C -#define HOST_IDTR_BASE 0x00006C0E -#define HOST_IA32_SYSENTER_ESP 0x00006C10 -#define HOST_IA32_SYSENTER_EIP 0x00006C12 -#define HOST_RSP 0x00006C14 -#define HOST_RIP 0x00006C16 - -/* Pin Based VM Execution Controls */ -/* INTEL MANUAL: 20-10 vol 3B */ -#define EXTERNAL_INTERRUPT_EXITING 0x00000001 -#define NMI_EXITING 0x00000008 -#define VIRTUAL_NMIS 0x00000020 - - -/* Processor Based VM Execution Controls */ -/* INTEL MANUAL: 20-11 vol. 3B */ -#define INTERRUPT_WINDOWS_EXIT 0x00000004 -#define USE_TSC_OFFSETTING 0x00000008 -#define HLT_EXITING 0x00000080 -#define INVLPG_EXITING 0x00000200 -#define MWAIT_EXITING 0x00000400 -#define RDPMC_EXITING 0x00000800 -#define RDTSC_EXITING 0x00001000 -#define CR8_LOAD_EXITING 0x00080000 -#define CR8_STORE_EXITING 0x00100000 -#define USE_TPR_SHADOW 0x00200000 -#define NMI_WINDOW_EXITING 0x00400000 -#define MOVDR_EXITING 0x00800000 -#define UNCONDITION_IO_EXITING 0x01000000 -#define USE_IO_BITMAPS 0x02000000 -#define USE_MSR_BITMAPS 0x10000000 -#define MONITOR_EXITING 0x20000000 -#define PAUSE_EXITING 0x40000000 - -/* VM-Exit Controls */ -/* INTEL MANUAL: 20-16 vol. 3B */ -#define HOST_ADDR_SPACE_SIZE 0x00000200 -#define ACK_IRQ_ON_EXIT 0x00008000 - - +typedef enum { + VMCS_GUEST_ES_SELECTOR = 0x00000800, + VMCS_GUEST_CS_SELECTOR = 0x00000802, + VMCS_GUEST_SS_SELECTOR = 0x00000804, + VMCS_GUEST_DS_SELECTOR = 0x00000806, + VMCS_GUEST_FS_SELECTOR = 0x00000808, + VMCS_GUEST_GS_SELECTOR = 0x0000080A, + VMCS_GUEST_LDTR_SELECTOR = 0x0000080C, + VMCS_GUEST_TR_SELECTOR = 0x0000080E, + /* 16 bit host state */ + VMCS_HOST_ES_SELECTOR = 0x00000C00, + VMCS_HOST_CS_SELECTOR = 0x00000C02, + VMCS_HOST_SS_SELECTOR = 0x00000C04, + VMCS_HOST_DS_SELECTOR = 0x00000C06, + VMCS_HOST_FS_SELECTOR = 0x00000C08, + VMCS_HOST_GS_SELECTOR = 0x00000C0A, + VMCS_HOST_TR_SELECTOR = 0x00000C0C, + /* 64 bit control fields */ + IO_BITMAP_A_ADDR = 0x00002000, + IO_BITMAP_A_ADDR_HIGH = 0x00002001, + IO_BITMAP_B_ADDR = 0x00002002, + IO_BITMAP_B_ADDR_HIGH = 0x00002003, + MSR_BITMAPS = 0x00002004, + MSR_BITMAPS_HIGH = 0x00002005, + VM_EXIT_MSR_STORE_ADDR = 0x00002006, + VM_EXIT_MSR_STORE_ADDR_HIGH = 0x00002007, + VM_EXIT_MSR_LOAD_ADDR = 0x00002008, + VM_EXIT_MSR_LOAD_ADDR_HIGH = 0x00002009, + VM_ENTRY_MSR_LOAD_ADDR = 0x0000200A, + VM_ENTRY_MSR_LOAD_ADDR_HIGH = 0x0000200B, + VMCS_EXEC_PTR = 0x0000200C, + VMCS_EXEC_PTR_HIGH = 0x0000200D, + TSC_OFFSET = 0x00002010, + TSC_OFFSET_HIGH = 0x00002011, + VIRT_APIC_PAGE_ADDR = 0x00002012, + VIRT_APIC_PAGE_ADDR_HIGH = 0x00002013, + /* 64 bit guest state fields */ + VMCS_LINK_PTR = 0x00002800, + VMCS_LINK_PTR_HIGH = 0x00002801, + GUEST_IA32_DEBUGCTL = 0x00002802, + GUEST_IA32_DEBUGCTL_HIGH = 0x00002803, + GUEST_IA32_PERF_GLOBAL_CTRL = 0x00002808, + GUEST_IA32_PERF_GLOBAL_CTRL_HIGH = 0x00002809, + /* 32 bit control fields */ + PIN_VM_EXEC_CTRLS = 0x00004000, + PROC_VM_EXEC_CTRLS = 0x00004002, + EXCEPTION_BITMAP = 0x00004004, + PAGE_FAULT_ERROR_MASK = 0x00004006, + PAGE_FAULT_ERROR_MATCH = 0x00004008, + CR3_TARGET_COUNT = 0x0000400A, + VM_EXIT_CTRLS = 0x0000400C, + VM_EXIT_MSR_STORE_COUNT = 0x0000400E, + VM_EXIT_MSR_LOAD_COUNT = 0x00004010, + VM_ENTRY_CTRLS = 0x00004012, + VM_ENTRY_MSR_LOAD_COUNT = 0x00004014, + VM_ENTRY_INT_INFO_FIELD = 0x00004016, + VM_ENTRY_EXCEPTION_ERROR = 0x00004018, + VM_ENTRY_INSTR_LENGTH = 0x0000401A, + TPR_THRESHOLD = 0x0000401C, + /* 32 bit Read Only data fields */ + VM_INSTR_ERROR = 0x00004400, + EXIT_REASON = 0x00004402, + VM_EXIT_INT_INFO = 0x00004404, + VM_EXIT_INT_ERROR = 0x00004406, + IDT_VECTOR_INFO = 0x00004408, + IDT_VECTOR_ERROR = 0x0000440A, + VM_EXIT_INSTR_LENGTH = 0x0000440C, + VMX_INSTR_INFO = 0x0000440E, + /* 32 bit Guest state fields */ + GUEST_ES_LIMIT = 0x00004800, + GUEST_CS_LIMIT = 0x00004802, + GUEST_SS_LIMIT = 0x00004804, + GUEST_DS_LIMIT = 0x00004806, + GUEST_FS_LIMIT = 0x00004808, + GUEST_GS_LIMIT = 0x0000480A, + GUEST_LDTR_LIMIT = 0x0000480C, + GUEST_TR_LIMIT = 0x0000480E, + GUEST_GDTR_LIMIT = 0x00004810, + GUEST_IDTR_LIMIT = 0x00004812, + GUEST_ES_ACCESS = 0x00004814, + GUEST_CS_ACCESS = 0x00004816, + GUEST_SS_ACCESS = 0x00004818, + GUEST_DS_ACCESS = 0x0000481A, + GUEST_FS_ACCESS = 0x0000481C, + GUEST_GS_ACCESS = 0x0000481E, + GUEST_LDTR_ACCESS = 0x00004820, + GUEST_TR_ACCESS = 0x00004822, + GUEST_INT_STATE = 0x00004824, + GUEST_ACTIVITY_STATE = 0x00004826, + GUEST_SMBASE = 0x00004828, + GUEST_IA32_SYSENTER_CS = 0x0000482A, + /* 32 bit host state field */ + HOST_IA32_SYSENTER_CS = 0x00004C00, + /* Natural Width Control Fields */ + CR0_GUEST_HOST_MASK = 0x00006000, + CR4_GUEST_HOST_MASK = 0x00006002, + CR0_READ_SHADOW = 0x00006004, + CR4_READ_SHADOW = 0x00006006, + CR3_TARGET_VALUE_0 = 0x00006008, + CR3_TARGET_VALUE_1 = 0x0000600A, + CR3_TARGET_VALUE_2 = 0x0000600C, + CR3_TARGET_VALUE_3 = 0x0000600E, + /* Natural Width Read Only Fields */ + EXIT_QUALIFICATION = 0x00006400, + IO_RCX = 0x00006402, + IO_RSI = 0x00006404, + IO_RDI = 0x00006406, + IO_RIP = 0x00006408, + GUEST_LINEAR_ADDR = 0x0000640A, + /* Natural Width Guest State Fields */ + GUEST_CR0 = 0x00006800, + GUEST_CR3 = 0x00006802, + GUEST_CR4 = 0x00006804, + GUEST_ES_BASE = 0x00006806, + GUEST_CS_BASE = 0x00006808, + GUEST_SS_BASE = 0x0000680A, + GUEST_DS_BASE = 0x0000680C, + GUEST_FS_BASE = 0x0000680E, + GUEST_GS_BASE = 0x00006810, + GUEST_LDTR_BASE = 0x00006812, + GUEST_TR_BASE = 0x00006814, + GUEST_GDTR_BASE = 0x00006816, + GUEST_IDTR_BASE = 0x00006818, + GUEST_DR7 = 0x0000681A, + GUEST_RSP = 0x0000681C, + GUEST_RIP = 0x0000681E, + GUEST_RFLAGS = 0x00006820, + GUEST_PENDING_DEBUG_EXCS = 0x00006822, + GUEST_IA32_SYSENTER_ESP = 0x00006824, + GUEST_IA32_SYSENTER_EIP = 0x00006826, + /* Natural Width Host State Fields */ + HOST_CR0 = 0x00006C00, + HOST_CR3 = 0x00006C02, + HOST_CR4 = 0x00006C04, + HOST_FS_BASE = 0x00006C06, + HOST_GS_BASE = 0x00006C08, + HOST_TR_BASE = 0x00006C0A, + HOST_GDTR_BASE = 0x00006C0C, + HOST_IDTR_BASE = 0x00006C0E, + HOST_IA32_SYSENTER_ESP = 0x00006C10, + HOST_IA32_SYSENTER_EIP = 0x00006C12, + HOST_RSP = 0x00006C14, + HOST_RIP = 0x00006C16, + /* Pin Based VM Execution Controls */ + /* INTEL MANUAL: 20-10 vol 3B */ + EXTERNAL_INTERRUPT_EXITING = 0x00000001, + NMI_EXITING = 0x00000008, + VIRTUAL_NMIS = 0x00000020, + /* Processor Based VM Execution Controls */ + /* INTEL MANUAL: 20-11 vol. 3B */ + INTERRUPT_WINDOWS_EXIT = 0x00000004, + USE_TSC_OFFSETTING = 0x00000008, + HLT_EXITING = 0x00000080, + INVLPG_EXITING = 0x00000200, + MWAIT_EXITING = 0x00000400, + RDPMC_EXITING = 0x00000800, + RDTSC_EXITING = 0x00001000, + CR8_LOAD_EXITING = 0x00080000, + CR8_STORE_EXITING = 0x00100000, + USE_TPR_SHADOW = 0x00200000, + NMI_WINDOW_EXITING = 0x00400000, + MOVDR_EXITING = 0x00800000, + UNCONDITION_IO_EXITING = 0x01000000, + USE_IO_BITMAPS = 0x02000000, + USE_MSR_BITMAPS = 0x10000000, + MONITOR_EXITING = 0x20000000, + PAUSE_EXITING = 0x40000000, + /* VM-Exit Controls */ + /* INTEL MANUAL: 20-16 vol. 3B */ + HOST_ADDR_SPACE_SIZE = 0x00000200, + ACK_IRQ_ON_EXIT = 0x00008000 +} vmcs_field_t; + +int vmcs_field_length(vmcs_field_t field); +char* vmcs_field_name(vmcs_field_t field); @@ -322,7 +295,7 @@ struct vmcs_segment_access { uint32_t rsvd2 : 15; } __attribute__((packed)); } __attribute__((packed)); -}__attribute__((packed);; +}__attribute__((packed)); struct vmcs_interrupt_state { diff --git a/palacios/include/palacios/vmx.h b/palacios/include/palacios/vmx.h index 4c04647..7d02053 100644 --- a/palacios/include/palacios/vmx.h +++ b/palacios/include/palacios/vmx.h @@ -108,3 +108,4 @@ int Do_VMM(struct VMXRegs regs); #endif // ! __V3VEE__ #endif + diff --git a/palacios/include/palacios/vmx_lowlevel.h b/palacios/include/palacios/vmx_lowlevel.h index b0bd7a5..fe8cf44 100644 --- a/palacios/include/palacios/vmx_lowlevel.h +++ b/palacios/include/palacios/vmx_lowlevel.h @@ -56,7 +56,8 @@ -static inline int v3_enable_vmx(uint64_t host_state) { +static inline int v3_enable_vmx(struct vmcs_data* vmxon_ptr) { + uint64_t vmxon_ptr_64 = (uint64_t)vmxon_ptr; uint8_t ret_invalid = 0; __asm__ __volatile__ ( @@ -64,7 +65,7 @@ static inline int v3_enable_vmx(uint64_t host_state) { EAX_06_MODRM "setnaeb %0;" // fail invalid (CF=1) : "=q"(ret_invalid) - : "a"(&host_state),"0"(ret_invalid) + : "a"(&vmxon_ptr_64),"0"(ret_invalid) : "memory"); if (ret_invalid) { @@ -76,7 +77,8 @@ static inline int v3_enable_vmx(uint64_t host_state) { // No vmcall necessary - is only executed by the guest -static inline int vmcs_clear(uint64_t addr) { +static inline int vmcs_clear(struct vmcs_data* vmcs_ptr) { + uint64_t vmcs_ptr_64 = (uint64_t)vmcs_ptr; uint8_t ret_valid = 0; uint8_t ret_invalid = 0; @@ -86,7 +88,7 @@ static inline int vmcs_clear(uint64_t addr) { "seteb %0;" // fail valid (ZF=1) "setnaeb %1;" // fail invalid (CF=1) : "=q"(ret_valid), "=q"(ret_invalid) - : "a"(&addr), "0"(ret_valid), "1"(ret_invalid) + : "a"(&vmcs_ptr_64), "0"(ret_valid), "1"(ret_invalid) : "memory"); CHECK_VMXFAIL(ret_valid, ret_invalid); @@ -113,8 +115,8 @@ static inline int vmcs_resume() { } -static inline int vmcs_load(vmcs_t * vmcs_ptr) { - uint64_t addr = (uint64_t)vmcs_ptr; +static inline int vmcs_load(struct vmcs_data* vmcs_ptr) { + uint64_t vmcs_ptr_64 = (uint64_t)vmcs_ptr; uint8_t ret_valid = 0; uint8_t ret_invalid = 0; @@ -124,7 +126,7 @@ static inline int vmcs_load(vmcs_t * vmcs_ptr) { "seteb %0;" // fail valid (ZF=1) "setnaeb %1;" // fail invalid (CF=1) : "=q"(ret_valid), "=q"(ret_invalid) - : "a"(&addr), "0"(ret_valid), "1"(ret_invalid) + : "a"(&vmcs_ptr_64), "0"(ret_valid), "1"(ret_invalid) : "memory"); CHECK_VMXFAIL(ret_valid, ret_invalid); @@ -132,23 +134,21 @@ static inline int vmcs_load(vmcs_t * vmcs_ptr) { return VMX_SUCCESS; } -static inline int vmcs_store(vmcs_t * vmcs_ptr) { - uint64_t addr = (uint64_t)vmcs_ptr; +static inline int vmcs_store(struct vmcs_data* vmcs_ptr) { + uint64_t vmcs_ptr_64 = (uint64_t)vmcs_ptr; __asm__ __volatile__ ( VMPTRSRT_OPCODE EAX_07_MODRM : - : "a"(&addr) + : "a"(&vmcs_ptr_64) : "memory"); return VMX_SUCCESS; } -/* According to Intel, vmread will return an architecure sized type - be sure that - * dst is at least 64-bits in IA-32e and 32 otherwise */ static inline int vmcs_read(addr_t vmcs_index, void * dst, int len) { - addr_t val = 0; + uint64_t val = 0; uint8_t ret_valid = 0; uint8_t ret_invalid = 0; @@ -165,7 +165,19 @@ static inline int vmcs_read(addr_t vmcs_index, void * dst, int len) { CHECK_VMXFAIL(ret_valid, ret_invalid); // TODO: Fix this, will have to do a cast because dst will be variable length - *dst = val; + switch(len) + { + case 2: + *((uint16_t*)dst) = (uint16_t)val; + break; + case 4: + *((uint32_t*)dst) = (uint32_t)val; + break; + case 8: + *((uint64_t*)dst) = (uint64_t)val; + break; + } + return VMX_SUCCESS; } diff --git a/palacios/src/palacios/vmcs.c b/palacios/src/palacios/vmcs.c index aa25f5e..35dc5e1 100644 --- a/palacios/src/palacios/vmcs.c +++ b/palacios/src/palacios/vmcs.c @@ -154,6 +154,512 @@ void print_vmcs_segment(char * name, vmcs_segment* seg) PrintDebug("\tAccess: %x\n", seg->access); } +/* + * Returns the field length in bytes + */ +int vmcs_field_length(vmcs_field_t field) +{ + switch(field) + { + case VMCS_GUEST_ES_SELECTOR: + case VMCS_GUEST_CS_SELECTOR: + case VMCS_GUEST_SS_SELECTOR: + case VMCS_GUEST_DS_SELECTOR: + case VMCS_GUEST_FS_SELECTOR: + case VMCS_GUEST_GS_SELECTOR: + case VMCS_GUEST_LDTR_SELECTOR: + case VMCS_GUEST_TR_SELECTOR: + /* 16 bit host state */ + case VMCS_HOST_ES_SELECTOR: + case VMCS_HOST_CS_SELECTOR: + case VMCS_HOST_SS_SELECTOR: + case VMCS_HOST_DS_SELECTOR: + case VMCS_HOST_FS_SELECTOR: + case VMCS_HOST_GS_SELECTOR: + case VMCS_HOST_TR_SELECTOR: + return 2; + /* 64 bit control fields */ + case IO_BITMAP_A_ADDR: + case IO_BITMAP_A_ADDR_HIGH: + case IO_BITMAP_B_ADDR: + case IO_BITMAP_B_ADDR_HIGH: + case MSR_BITMAPS: + case MSR_BITMAPS_HIGH: + case VM_EXIT_MSR_STORE_ADDR: + case VM_EXIT_MSR_STORE_ADDR_HIGH: + case VM_EXIT_MSR_LOAD_ADDR: + case VM_EXIT_MSR_LOAD_ADDR_HIGH: + case VM_ENTRY_MSR_LOAD_ADDR: + case VM_ENTRY_MSR_LOAD_ADDR_HIGH: + case VMCS_EXEC_PTR: + case VMCS_EXEC_PTR_HIGH: + case TSC_OFFSET: + case TSC_OFFSET_HIGH: + case VIRT_APIC_PAGE_ADDR: + case VIRT_APIC_PAGE_ADDR_HIGH: + /* 64 bit guest state fields */ + case VMCS_LINK_PTR: + case VMCS_LINK_PTR_HIGH: + case GUEST_IA32_DEBUGCTL: + case GUEST_IA32_DEBUGCTL_HIGH: + case GUEST_IA32_PERF_GLOBAL_CTRL: + case GUEST_IA32_PERF_GLOBAL_CTRL_HIGH: + return 8; + /* 32 bit control fields */ + case PIN_VM_EXEC_CTRLS: + case PROC_VM_EXEC_CTRLS: + case EXCEPTION_BITMAP: + case PAGE_FAULT_ERROR_MASK: + case PAGE_FAULT_ERROR_MATCH: + case CR3_TARGET_COUNT: + case VM_EXIT_CTRLS: + case VM_EXIT_MSR_STORE_COUNT: + case VM_EXIT_MSR_LOAD_COUNT: + case VM_ENTRY_CTRLS: + case VM_ENTRY_MSR_LOAD_COUNT: + case VM_ENTRY_INT_INFO_FIELD: + case VM_ENTRY_EXCEPTION_ERROR: + case VM_ENTRY_INSTR_LENGTH: + case TPR_THRESHOLD: + /* 32 bit Read Only data fields */ + case VM_INSTR_ERROR: + case EXIT_REASON: + case VM_EXIT_INT_INFO: + case VM_EXIT_INT_ERROR: + case IDT_VECTOR_INFO: + case IDT_VECTOR_ERROR: + case VM_EXIT_INSTR_LENGTH: + case VMX_INSTR_INFO: + /* 32 bit Guest state fields */ + case GUEST_ES_LIMIT: + case GUEST_CS_LIMIT: + case GUEST_SS_LIMIT: + case GUEST_DS_LIMIT: + case GUEST_FS_LIMIT: + case GUEST_GS_LIMIT: + case GUEST_LDTR_LIMIT: + case GUEST_TR_LIMIT: + case GUEST_GDTR_LIMIT: + case GUEST_IDTR_LIMIT: + case GUEST_ES_ACCESS: + case GUEST_CS_ACCESS: + case GUEST_SS_ACCESS: + case GUEST_DS_ACCESS: + case GUEST_FS_ACCESS: + case GUEST_GS_ACCESS: + case GUEST_LDTR_ACCESS: + case GUEST_TR_ACCESS: + case GUEST_INT_STATE: + case GUEST_ACTIVITY_STATE: + case GUEST_SMBASE: + case GUEST_IA32_SYSENTER_CS: + /* 32 bit host state field */ + case HOST_IA32_SYSENTER_CS: + return 4; + /* Natural Width Control Fields */ + case CR0_GUEST_HOST_MASK: + case CR4_GUEST_HOST_MASK: + case CR0_READ_SHADOW: + case CR4_READ_SHADOW: + case CR3_TARGET_VALUE_0: + case CR3_TARGET_VALUE_1: + case CR3_TARGET_VALUE_2: + case CR3_TARGET_VALUE_3: + /* Natural Width Read Only Fields */ + case EXIT_QUALIFICATION: + case IO_RCX: + case IO_RSI: + case IO_RDI: + case IO_RIP: + case GUEST_LINEAR_ADDR: + /* Natural Width Guest State Fields */ + case GUEST_CR0: + case GUEST_CR3: + case GUEST_CR4: + case GUEST_ES_BASE: + case GUEST_CS_BASE: + case GUEST_SS_BASE: + case GUEST_DS_BASE: + case GUEST_FS_BASE: + case GUEST_GS_BASE: + case GUEST_LDTR_BASE: + case GUEST_TR_BASE: + case GUEST_GDTR_BASE: + case GUEST_IDTR_BASE: + case GUEST_DR7: + case GUEST_RSP: + case GUEST_RIP: + case GUEST_RFLAGS: + case GUEST_PENDING_DEBUG_EXCS: + case GUEST_IA32_SYSENTER_ESP: + case GUEST_IA32_SYSENTER_EIP: + /* Natural Width Host State Fields */ + case HOST_CR0: + case HOST_CR3: + case HOST_CR4: + case HOST_FS_BASE: + case HOST_GS_BASE: + case HOST_TR_BASE: + case HOST_GDTR_BASE: + case HOST_IDTR_BASE: + case HOST_IA32_SYSENTER_ESP: + case HOST_IA32_SYSENTER_EIP: + case HOST_RSP: + case HOST_RIP: + /* Pin Based VM Execution Controls */ + /* INTEL MANUAL: 20-10 vol 3B */ + case EXTERNAL_INTERRUPT_EXITING: + case NMI_EXITING: + case VIRTUAL_NMIS: + /* Processor Based VM Execution Controls */ + /* INTEL MANUAL: 20-11 vol. 3B */ + case INTERRUPT_WINDOWS_EXIT: + case USE_TSC_OFFSETTING: + case HLT_EXITING: + case INVLPG_EXITING: + case MWAIT_EXITING: + case RDPMC_EXITING: + case RDTSC_EXITING: + case CR8_LOAD_EXITING: + case CR8_STORE_EXITING: + case USE_TPR_SHADOW: + case NMI_WINDOW_EXITING: + case MOVDR_EXITING: + case UNCONDITION_IO_EXITING: + case USE_IO_BITMAPS: + case USE_MSR_BITMAPS: + case MONITOR_EXITING: + case PAUSE_EXITING: + /* VM-Exit Controls */ + /* INTEL MANUAL: 20-16 vol. 3B */ + case HOST_ADDR_SPACE_SIZE: + case ACK_IRQ_ON_EXIT: +#ifdef __V3_64BIT__ + return 8; +#else + return 4; +#endif + default: + return -1; + } +} + +char* vmcs_field_name(vmcs_field_t field) +{ + case(field) + { + case VMCS_GUEST_ES_SELECTOR: + return "VMCS_GUEST_ES_SELECTOR"; + case VMCS_GUEST_CS_SELECTOR: + return "VMCS_GUEST_CS_SELECTOR"; + case VMCS_GUEST_SS_SELECTOR: + return "VMCS_GUEST_SS_SELECTOR"; + case VMCS_GUEST_DS_SELECTOR: + return "VMCS_GUEST_DS_SELECTOR"; + case VMCS_GUEST_FS_SELECTOR: + return "VMCS_GUEST_FS_SELECTOR"; + case VMCS_GUEST_GS_SELECTOR: + return "VMCS_GUEST_GS_SELECTOR"; + case VMCS_GUEST_LDTR_SELECTOR: + return "VMCS_GUEST_LDTR_SELECTOR"; + case VMCS_GUEST_TR_SELECTOR: + return "VMCS_GUEST_TR_SELECTOR"; + case VMCS_HOST_ES_SELECTOR: + return "VMCS_HOST_ES_SELECTOR"; + case VMCS_HOST_CS_SELECTOR: + return "VMCS_HOST_CS_SELECTOR"; + case VMCS_HOST_SS_SELECTOR: + return "VMCS_HOST_SS_SELECTOR"; + case VMCS_HOST_DS_SELECTOR: + return "VMCS_HOST_DS_SELECTOR"; + case VMCS_HOST_FS_SELECTOR: + return "VMCS_HOST_FS_SELECTOR"; + case VMCS_HOST_GS_SELECTOR: + return "VMCS_HOST_GS_SELECTOR"; + case VMCS_HOST_TR_SELECTOR: + return "VMCS_HOST_TR_SELECTOR"; + case IO_BITMAP_A_ADDR: + return "IO_BITMAP_A_ADDR"; + case IO_BITMAP_A_ADDR_HIGH: + return "IO_BITMAP_A_ADDR_HIGH"; + case IO_BITMAP_B_ADDR: + return "IO_BITMAP_B_ADDR"; + case IO_BITMAP_B_ADDR_HIGH: + return "IO_BITMAP_B_ADDR_HIGH"; + case MSR_BITMAPS: + return "MSR_BITMAPS"; + case MSR_BITMAPS_HIGH: + return "MSR_BITMAPS_HIGH"; + case VM_EXIT_MSR_STORE_ADDR: + return "VM_EXIT_MSR_STORE_ADDR"; + case VM_EXIT_MSR_STORE_ADDR_HIGH: + return "VM_EXIT_MSR_STORE_ADDR_HIGH"; + case VM_EXIT_MSR_LOAD_ADDR: + return "VM_EXIT_MSR_LOAD_ADDR"; + case VM_EXIT_MSR_LOAD_ADDR_HIGH: + return "VM_EXIT_MSR_LOAD_ADDR_HIGH"; + case VM_ENTRY_MSR_LOAD_ADDR: + return "VM_ENTRY_MSR_LOAD_ADDR"; + case VM_ENTRY_MSR_LOAD_ADDR_HIGH: + return "VM_ENTRY_MSR_LOAD_ADDR_HIGH"; + case VMCS_EXEC_PTR: + return "VMCS_EXEC_PTR"; + case VMCS_EXEC_PTR_HIGH: + return "VMCS_EXEC_PTR_HIGH"; + case TSC_OFFSET: + return "TSC_OFFSET"; + case TSC_OFFSET_HIGH: + return "TSC_OFFSET_HIGH"; + case VIRT_APIC_PAGE_ADDR: + return "VIRT_APIC_PAGE_ADDR"; + case VIRT_APIC_PAGE_ADDR_HIGH: + return "VIRT_APIC_PAGE_ADDR_HIGH"; + case VMCS_LINK_PTR: + return "VMCS_LINK_PTR"; + case VMCS_LINK_PTR_HIGH: + return "VMCS_LINK_PTR_HIGH"; + case GUEST_IA32_DEBUGCTL: + return "GUEST_IA32_DEBUGCTL"; + case GUEST_IA32_DEBUGCTL_HIGH: + return "GUEST_IA32_DEBUGCTL_HIGH"; + case GUEST_IA32_PERF_GLOBAL_CTRL: + return "GUEST_IA32_PERF_GLOBAL_CTRL"; + case GUEST_IA32_PERF_GLOBAL_CTRL_HIGH: + return "GUEST_IA32_PERF_GLOBAL_CTRL_HIGH"; + case PIN_VM_EXEC_CTRLS: + return "PIN_VM_EXEC_CTRLS"; + case PROC_VM_EXEC_CTRLS: + return "PROC_VM_EXEC_CTRLS"; + case EXCEPTION_BITMAP: + return "EXCEPTION_BITMAP"; + case PAGE_FAULT_ERROR_MASK: + return "PAGE_FAULT_ERROR_MASK"; + case PAGE_FAULT_ERROR_MATCH: + return "PAGE_FAULT_ERROR_MATCH"; + case CR3_TARGET_COUNT: + return "CR3_TARGET_COUNT"; + case VM_EXIT_CTRLS: + return "VM_EXIT_CTRLS"; + case VM_EXIT_MSR_STORE_COUNT: + return "VM_EXIT_MSR_STORE_COUNT"; + case VM_EXIT_MSR_LOAD_COUNT: + return "VM_EXIT_MSR_LOAD_COUNT"; + case VM_ENTRY_CTRLS: + return "VM_ENTRY_CTRLS"; + case VM_ENTRY_MSR_LOAD_COUNT: + return "VM_ENTRY_MSR_LOAD_COUNT"; + case VM_ENTRY_INT_INFO_FIELD: + return "VM_ENTRY_INT_INFO_FIELD"; + case VM_ENTRY_EXCEPTION_ERROR: + return "VM_ENTRY_EXCEPTION_ERROR"; + case VM_ENTRY_INSTR_LENGTH: + return "VM_ENTRY_INSTR_LENGTH"; + case TPR_THRESHOLD: + return "TPR_THRESHOLD"; + case VM_INSTR_ERROR: + return "VM_INSTR_ERROR"; + case EXIT_REASON: + return "EXIT_REASON"; + case VM_EXIT_INT_INFO: + return "VM_EXIT_INT_INFO"; + case VM_EXIT_INT_ERROR: + return "VM_EXIT_INT_ERROR"; + case IDT_VECTOR_INFO: + return "IDT_VECTOR_INFO"; + case IDT_VECTOR_ERROR: + return "IDT_VECTOR_ERROR"; + case VM_EXIT_INSTR_LENGTH: + return "VM_EXIT_INSTR_LENGTH"; + case VMX_INSTR_INFO: + return "VMX_INSTR_INFO"; + case GUEST_ES_LIMIT: + return "GUEST_ES_LIMIT"; + case GUEST_CS_LIMIT: + return "GUEST_CS_LIMIT"; + case GUEST_SS_LIMIT: + return "GUEST_SS_LIMIT"; + case GUEST_DS_LIMIT: + return "GUEST_DS_LIMIT"; + case GUEST_FS_LIMIT: + return "GUEST_FS_LIMIT"; + case GUEST_GS_LIMIT: + return "GUEST_GS_LIMIT"; + case GUEST_LDTR_LIMIT: + return "GUEST_LDTR_LIMIT"; + case GUEST_TR_LIMIT: + return "GUEST_TR_LIMIT"; + case GUEST_GDTR_LIMIT: + return "GUEST_GDTR_LIMIT"; + case GUEST_IDTR_LIMIT: + return "GUEST_IDTR_LIMIT"; + case GUEST_ES_ACCESS: + return "GUEST_ES_ACCESS"; + case GUEST_CS_ACCESS: + return "GUEST_CS_ACCESS"; + case GUEST_SS_ACCESS: + return "GUEST_SS_ACCESS"; + case GUEST_DS_ACCESS: + return "GUEST_DS_ACCESS"; + case GUEST_FS_ACCESS: + return "GUEST_FS_ACCESS"; + case GUEST_GS_ACCESS: + return "GUEST_GS_ACCESS"; + case GUEST_LDTR_ACCESS: + return "GUEST_LDTR_ACCESS"; + case GUEST_TR_ACCESS: + return "GUEST_TR_ACCESS"; + case GUEST_INT_STATE: + return "GUEST_INT_STATE"; + case GUEST_ACTIVITY_STATE: + return "GUEST_ACTIVITY_STATE"; + case GUEST_SMBASE: + return "GUEST_SMBASE"; + case GUEST_IA32_SYSENTER_CS: + return "GUEST_IA32_SYSENTER_CS"; + case HOST_IA32_SYSENTER_CS: + return "HOST_IA32_SYSENTER_CS"; + case CR0_GUEST_HOST_MASK: + return "CR0_GUEST_HOST_MASK"; + case CR4_GUEST_HOST_MASK: + return "CR4_GUEST_HOST_MASK"; + case CR0_READ_SHADOW: + return "CR0_READ_SHADOW"; + case CR4_READ_SHADOW: + return "CR4_READ_SHADOW"; + case CR3_TARGET_VALUE_0: + return "CR3_TARGET_VALUE_0"; + case CR3_TARGET_VALUE_1: + return "CR3_TARGET_VALUE_1"; + case CR3_TARGET_VALUE_2: + return "CR3_TARGET_VALUE_2"; + case CR3_TARGET_VALUE_3: + return "CR3_TARGET_VALUE_3"; + case EXIT_QUALIFICATION: + return "EXIT_QUALIFICATION"; + case IO_RCX: + return "IO_RCX"; + case IO_RSI: + return "IO_RSI"; + case IO_RDI: + return "IO_RDI"; + case IO_RIP: + return "IO_RIP"; + case GUEST_LINEAR_ADDR: + return "GUEST_LINEAR_ADDR"; + case GUEST_CR0: + return "GUEST_CR0"; + case GUEST_CR3: + return "GUEST_CR3"; + case GUEST_CR4: + return "GUEST_CR4"; + case GUEST_ES_BASE: + return "GUEST_ES_BASE"; + case GUEST_CS_BASE: + return "GUEST_CS_BASE"; + case GUEST_SS_BASE: + return "GUEST_SS_BASE"; + case GUEST_DS_BASE: + return "GUEST_DS_BASE"; + case GUEST_FS_BASE: + return "GUEST_FS_BASE"; + case GUEST_GS_BASE: + return "GUEST_GS_BASE"; + case GUEST_LDTR_BASE: + return "GUEST_LDTR_BASE"; + case GUEST_TR_BASE: + return "GUEST_TR_BASE"; + case GUEST_GDTR_BASE: + return "GUEST_GDTR_BASE"; + case GUEST_IDTR_BASE: + return "GUEST_IDTR_BASE"; + case GUEST_DR7: + return "GUEST_DR7"; + case GUEST_RSP: + return "GUEST_RSP"; + case GUEST_RIP: + return "GUEST_RIP"; + case GUEST_RFLAGS: + return "GUEST_RFLAGS"; + case GUEST_PENDING_DEBUG_EXCS: + return "GUEST_PENDING_DEBUG_EXCS"; + case GUEST_IA32_SYSENTER_ESP: + return "GUEST_IA32_SYSENTER_ESP"; + case GUEST_IA32_SYSENTER_EIP: + return "GUEST_IA32_SYSENTER_EIP"; + case HOST_CR0: + return "HOST_CR0"; + case HOST_CR3: + return "HOST_CR3"; + case HOST_CR4: + return "HOST_CR4"; + case HOST_FS_BASE: + return "HOST_FS_BASE"; + case HOST_GS_BASE: + return "HOST_GS_BASE"; + case HOST_TR_BASE: + return "HOST_TR_BASE"; + case HOST_GDTR_BASE: + return "HOST_GDTR_BASE"; + case HOST_IDTR_BASE: + return "HOST_IDTR_BASE"; + case HOST_IA32_SYSENTER_ESP: + return "HOST_IA32_SYSENTER_ESP"; + case HOST_IA32_SYSENTER_EIP: + return "HOST_IA32_SYSENTER_EIP"; + case HOST_RSP: + return "HOST_RSP"; + case HOST_RIP: + return "HOST_RIP"; + case EXTERNAL_INTERRUPT_EXITING: + return "EXTERNAL_INTERRUPT_EXITING"; + case NMI_EXITING: + return "NMI_EXITING"; + case VIRTUAL_NMIS: + return "VIRTUAL_NMIS"; + case INTERRUPT_WINDOWS_EXIT: + return "INTERRUPT_WINDOWS_EXIT"; + case USE_TSC_OFFSETTING: + return "USE_TSC_OFFSETTING"; + case HLT_EXITING: + return "HLT_EXITING"; + case INVLPG_EXITING: + return "INVLPG_EXITING"; + case MWAIT_EXITING: + return "MWAIT_EXITING"; + case RDPMC_EXITING: + return "RDPMC_EXITING"; + case RDTSC_EXITING: + return "RDTSC_EXITING"; + case CR8_LOAD_EXITING: + return "CR8_LOAD_EXITING"; + case CR8_STORE_EXITING: + return "CR8_STORE_EXITING"; + case USE_TPR_SHADOW: + return "USE_TPR_SHADOW"; + case NMI_WINDOW_EXITING: + return "NMI_WINDOW_EXITING"; + case MOVDR_EXITING: + return "MOVDR_EXITING"; + case UNCONDITION_IO_EXITING: + return "UNCONDITION_IO_EXITING"; + case USE_IO_BITMAPS: + return "USE_IO_BITMAPS"; + case USE_MSR_BITMAPS: + return "USE_MSR_BITMAPS"; + case MONITOR_EXITING: + return "MONITOR_EXITING"; + case PAUSE_EXITING: + return "PAUSE_EXITING"; + case HOST_ADDR_SPACE_SIZE: + return "HOST_ADDR_SPACE_SIZE"; + case ACK_IRQ_ON_EXIT: + return "ACK_IRQ_ON_EXIT"; + default: + return NULL; + } +} + + void PrintTrace_VMCSHostStateArea(struct VMCSHostStateArea * hostState) { PrintTrace("\n==> Host State Area\n"); PrintTrace("HOST_CR0: %x\n", (uint_t)hostState->cr0); diff --git a/palacios/src/palacios/vmx.c b/palacios/src/palacios/vmx.c index 8a315ce..d152e0b 100644 --- a/palacios/src/palacios/vmx.c +++ b/palacios/src/palacios/vmx.c @@ -75,6 +75,7 @@ uint_t myregs = 0; +static struct vmcs_data* vmxon_ptr; @@ -398,7 +399,9 @@ static vmcs_data* allocate_vmcs() { -static void init_vmcs_bios(vmcs_t * vmcs, struct guest_info * vm_info) { +static void init_vmcs_bios(struct guest_info * vm_info) +{ + } @@ -410,14 +413,14 @@ static int init_vmx_guest(struct guest_info * info, struct v3_vm_config * config struct vmx_data* data; PrintDebug("Allocating vmx_data\n"); - data = (struct vmx_data*)V3_Malloc(sizeof(vmx_data)); + data = (struct vmx_data*)V3_Malloc(sizeof(struct vmx_data)); PrintDebug("Allocating VMCS\n"); data->vmcs = allocate_vmcs(); info->vmm_data = (void*)data; - PrintDebug("Initializing VMCS (addr=%p)\n", (void *)info->vmm_data); - init_vmcs_bios((vmcs_t *)(info->vmm_data), info); + PrintDebug("Initializing VMCS (addr=%p)\n", info->vmm_data); + init_vmcs_bios((struct vmx_data*)(info->vmm_data), info); v3_post_config_guest(info, config_ptr); @@ -427,7 +430,23 @@ static int init_vmx_guest(struct guest_info * info, struct v3_vm_config * config -static int start_svm_guest(struct guest_info *info) { +static int start_vmx_guest(struct guest_info *info) { + struct vmx_data* vmx_data = (struct vmx_data*)info->vmm_data; + int vmx_ret; + + // Have to do a whole lot of flag setting here + vmx_ret = vmcs_clear(vmx_data->vmcs); + if(vmx_ret != VMX_SUCCESS) { + PrintDebug("VMCS Clear failed\n"); + return -1; + } + vmx_ret = vmcs_load(vmx_data->vmcs); + if(vmx_ret != VMX_SUCCESS) { + PrintDebug("Executing VMPTRLD\n"); + return -1; + } + + // Setup guest state return -1; } @@ -454,8 +473,8 @@ int v3_is_vmx_capable() { } } else { - PrintDebug("VMX not supported on this cpu\n"); - return 0; + PrintDebug("VMX not supported on this cpu\n"); + return 0; } return 1; @@ -490,15 +509,7 @@ static int setup_base_host_state() { void v3_init_vmx(struct v3_ctrl_ops * vm_ops) { v3_msr_t basic_msr; - // Setup the host state save area - void * host_state = V3_AllocPages(1); - - v3_get_msr(VMX_BASIC_MSR, &(basic_msr.hi), &(basic_msr.lo)); - *(uint32_t *)host_state = ((struct vmx_basic_msr *)basic_msr.value)->revision; - - PrintDebug("VMX revision: 0x%p\n", host_state); - __asm__ __volatile__ ( "movl %%cr4, %%ebx; " "orl %%ebx, 0x00002000; " @@ -514,19 +525,22 @@ void v3_init_vmx(struct v3_ctrl_ops * vm_ops) { "movl %%ebx, %%cr0" ); + // Setup VMXON Region + vmxon_ptr = allocate_vmcs(); + PrintDebug("VMX revision: 0x%p\n", (void*)vmxon_ptr); - if (v3_enable_vmx(host_state) == 0) { - PrintDebug("VMX Enabled\n"); + if (v3_enable_vmx(vmxon_ptr) == 0) { + PrintDebug("VMX Enabled\n"); } else { - PrintError("VMX initialization failure\n"); - return; + PrintError("VMX initialization failure\n"); + return; } if (has_vmx_nested_paging() == 1) { - v3_cpu_type = V3_VMX_EPT_CPU; + v3_cpu_type = V3_VMX_EPT_CPU; } else { - v3_cpu_type = V3_VMX_CPU; + v3_cpu_type = V3_VMX_CPU; } // Setup the VMX specific vmm operations diff --git a/palacios/src/palacios/vmx_lowlevel.asm b/palacios/src/palacios/vmx_lowlevel.asm index eefe3e3..94f7432 100644 --- a/palacios/src/palacios/vmx_lowlevel.asm +++ b/palacios/src/palacios/vmx_lowlevel.asm @@ -54,150 +54,6 @@ EXPORT SAFE_VM_LAUNCH EXPORT Init_VMCS_HostState EXPORT Init_VMCS_GuestState -; -; Enable_VMX - Turn on VMX -; -align 8 -Enable_VMX: - push ebp - mov ebp, esp - push ebx - mov ebx, cr4 - or ebx, dword 0x00002000 - mov cr4, ebx - mov ebx, cr0 - or ebx, dword 0x80000021 - mov cr0, ebx - vmxon [ebp+8] - pop ebx - pop ebp - mov eax, VMX_SUCCESS - jnc .return - mov eax, VMX_FAIL_INVALID -.return - ret - - -; -; VMREAD - read a value from a VMCS -; -align 8 -VMCS_READ: - push ebp - mov ebp, esp - push ecx - push ebx - - mov ecx, [ebp + 8] - mov ebx,[ebp + 12] -; lea ebx, ebp - vmread [ebx], ecx - - pop ebx - pop ecx - pop ebp - jz .error_code - jc .error - - mov eax, VMX_SUCCESS - jmp .return -.error - mov eax, VMX_FAIL_INVALID - jmp .return -.error_code - mov eax, VMX_FAIL_VALID -.return - ret - -; -; VMWRITE - write a value to a VMCS -align 8 -VMCS_WRITE: - push ebp - mov ebp, esp - push ebx - - mov eax, [ebp + 8] - mov ebx, [ebp + 12] - vmwrite eax, [ebx] - - pop ebx - pop ebp - jz .error_code - jc .error - - mov eax, VMX_SUCCESS - jmp .return -.error - mov eax, VMX_FAIL_INVALID - jmp .return -.error_code - mov eax, VMX_FAIL_VALID -.return - ret - -; -; VMCLEAR - Initializes a VMCS -; -align 8 -VMCS_CLEAR: - vmclear [esp+4] - jz .error_code - jc .error - - mov eax, VMX_SUCCESS - jmp .return -.error - mov eax, VMX_FAIL_INVALID - jmp .return -.error_code - mov eax, VMX_FAIL_VALID -.return - ret - - - -; -; VMCS_LOAD - load a VMCS -; -align 8 -VMCS_LOAD: - vmptrld [esp+4] - jz .error_code - jc .error - - mov eax, VMX_SUCCESS - jmp .return -.error - mov eax, VMX_FAIL_INVALID - jmp .return -.error_code - mov eax, VMX_FAIL_VALID -.return - ret - - - -; -; VMCS_STORE - Store a VMCS -; -align 8 -VMCS_STORE: - mov eax, [esp+4] - vmptrst [eax] - jz .error_code - jc .error - - mov eax, VMX_SUCCESS - jmp .return -.error - mov eax, VMX_FAIL_INVALID - jmp .return -.error_code - mov eax, VMX_FAIL_VALID -.return - ret - ; ; VMCS_LAUNCH @@ -755,7 +611,18 @@ InitHostSelectors: jz .error_code jc .error - mov ebx, VMCS_HOST_SS_SELECTOR + mov ebx, VMCS_HOST_SS_SELECTOR; + PrintDebug("VMX revision: 0x%p\n", (void*)vmxon_ptr); + + if (v3_enable_vmx(vmxon_ptr) == 0) { + PrintDebug("VMX Enabled\n"); + } else { + PrintError("VMX initialization failure\n"); + return; + } + + + mov eax, ss vmwrite ebx, eax jz .error_code