+struct vmcs_field_encoding {
+ uint8_t access_type : 1; /* 0 = full, 1 = high, (for accessing 64 bit fields on 32bit CPU) */
+ uint16_t index : 9;
+ uint8_t type : 2; /* 0=ctrl, 1=read-only, 2 = guest state, 3 = host state */
+ uint8_t rsvd1 : 1; /* MBZ */
+ uint8_t width : 2; /* 0 = 16bit, 1 = 64bit, 2 = 32bit, 3 = natural width */
+ uint32_t rsvd2 : 17;
+} __attribute__((packed));
+
typedef enum {
VMCS_GUEST_ES_SELECTOR = 0x00000800,
#include <palacios/vmm.h>
#include <palacios/vm_guest.h>
-// Intel VMX Specific MSRs
-#define VMX_FEATURE_CONTROL_MSR 0x0000003a
-#define VMX_BASIC_MSR 0x00000480
-#define VMX_PINBASED_CTLS_MSR 0x00000481
-#define VMX_PROCBASED_CTLS_MSR 0x00000482
-#define VMX_EXIT_CTLS_MSR 0x00000483
-#define VMX_ENTRY_CTLS_MSR 0x00000484
-#define VMX_MISC_MSR 0x00000485
-#define VMX_CR0_FIXED0_MSR 0x00000486
-#define VMX_CR0_FIXED1_MSR 0x00000487
-#define VMX_CR4_FIXED0_MSR 0x00000488
-#define VMX_CR4_FIXED1_MSR 0x00000489
-#define VMX_VMCS_ENUM_MSR 0x0000048A
#define VMX_SUCCESS 0
#define VMX_FAIL_INVALID 1
#define VMX_FAIL_VALID 2
#define VMM_ERROR 3
-#define FEATURE_CONTROL_LOCK 0x00000001
-#define FEATURE_CONTROL_VMXON 0x00000004
-#define FEATURE_CONTROL_VALID ( FEATURE_CONTROL_LOCK | FEATURE_CONTROL_VMXON )
-#define CPUID_1_ECX_VTXFLAG 0x00000020
struct vmx_pin_ctrls {
} __attribute__((packed));
} __attribute__((packed));
-struct vmx_basic_msr {
- uint32_t revision;
- uint_t regionSize : 13;
- uint_t rsvd1 : 4; // Always 0
- uint_t physWidth : 1;
- uint_t smm : 1; // Always 1
- uint_t memType : 4;
- uint_t rsvd2 : 10; // Always 0
-} __attribute__((packed));
typedef enum {
VMXASSIST_DISABLED,
--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2011, Jack Lange <jarusl@cs.northwestern.edu>
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+
+#ifndef __VMX_HW_INFO_H__
+#define __VMX_HW_INFO_H__
+
+#ifdef __V3VEE__
+
+
+#define VMX_BASIC_MSR 0x00000480
+#define VMX_PINBASED_CTLS_MSR 0x00000481
+#define VMX_PROCBASED_CTLS_MSR 0x00000482
+#define VMX_EXIT_CTLS_MSR 0x00000483
+#define VMX_ENTRY_CTLS_MSR 0x00000484
+#define VMX_MISC_MSR 0x00000485
+#define VMX_CR0_FIXED0_MSR 0x00000486
+#define VMX_CR0_FIXED1_MSR 0x00000487
+#define VMX_CR4_FIXED0_MSR 0x00000488
+#define VMX_CR4_FIXED1_MSR 0x00000489
+#define VMX_VMCS_ENUM_MSR 0x0000048A
+
+
+
+
+struct vmx_basic_msr {
+ union {
+ uint32_t lo;
+ uint32_t hi;
+ struct {
+ uint32_t revision;
+ uint32_t regionSize : 13;
+ uint8_t rsvd1 : 4; /* Always 0 */
+ uint8_t physWidth : 1; /* VMCS address field widths
+ (1=32bits, 0=natural width) */
+ uint8_t smm : 1; // Always 1
+ uint8_t memType : 4; /* 0 = UC, 6 = WriteBack */
+ uint8_t io_str_info : 1;
+ uint8_t def1_maybe_0 : 1; /* 1="Any VMX ctrls that default to 1 may be cleared to 0" */
+ uint32_t rsvd2 : 8; /* Always 0 */
+ } __attribute__((packed));
+ } __attribute__((packed));
+} __attribute__((packed));
+
+
+
+
+
+struct vmx_hw_info {
+ struct vmx_basic_msr basic_info;
+
+
+
+};
+
+
+int v3_init_vmx_hw();
+
+
+
+
+#endif
+
+#endif
-static inline int v3_enable_vmx(addr_t vmxon_ptr) {
- uint64_t vmxon_ptr_64 __attribute__((aligned(8))) = (uint64_t)vmxon_ptr;
- uint8_t ret_invalid = 0;
- __asm__ __volatile__ (
- VMXON_OPCODE
- EAX_06_MODRM
- "setnaeb %0;" // fail invalid (CF=1)
- : "=q"(ret_invalid)
- : "a"(&vmxon_ptr_64),"0"(ret_invalid)
- : "memory");
-
- if (ret_invalid) {
- return VMX_FAIL_INVALID;
- } else {
- return VMX_SUCCESS;
- }
-}
static inline int vmcs_clear(addr_t vmcs_ptr) {
uint64_t vmcs_ptr_64 __attribute__ ((aligned(8))) = (uint64_t)vmcs_ptr;
return VMX_SUCCESS;
}
+
+static inline int vmx_on(addr_t vmxon_ptr) {
+ uint64_t vmxon_ptr_64 __attribute__((aligned(8))) = (uint64_t)vmxon_ptr;
+ uint8_t ret_invalid = 0;
+
+ __asm__ __volatile__ (
+ VMXON_OPCODE
+ EAX_06_MODRM
+ "setnaeb %0;" // fail invalid (CF=1)
+ : "=q"(ret_invalid)
+ : "a"(&vmxon_ptr_64),"0"(ret_invalid)
+ : "memory");
+
+ if (ret_invalid) {
+ return VMX_FAIL_INVALID;
+ } else {
+ return VMX_SUCCESS;
+ }
+}
+
static inline int vmx_off() {
uint8_t ret_valid = 0;
uint8_t ret_invalid = 0;
return VMX_SUCCESS;
}
+
+static inline int enable_vmx() {
+#ifdef __V3_64BIT__
+ __asm__ __volatile__ (
+ "movq %%cr4, %%rbx;"
+ "orq $0x00002000, %%rbx;"
+ "movq %%rbx, %%cr4;"
+ :
+ :
+ : "%rbx"
+ );
+
+
+ __asm__ __volatile__ (
+ "movq %%cr0, %%rbx; "
+ "orq $0x00000020,%%rbx; "
+ "movq %%rbx, %%cr0;"
+ :
+ :
+ : "%rbx"
+ );
+#elif __V3_32BIT__
+ __asm__ __volatile__ (
+ "movl %%cr4, %%ecx;"
+ "orl $0x00002000, %%ecx;"
+ "movl %%ecx, %%cr4;"
+ :
+ :
+ : "%ecx"
+ );
+
+
+
+ __asm__ __volatile__ (
+ "movl %%cr0, %%ecx; "
+ "orl $0x00000020,%%ecx; "
+ "movl %%ecx, %%cr0;"
+ :
+ :
+ : "%ecx"
+ );
+
+#endif
+
+ return 0;
+}
+
+
+
+
+
#endif
#endif
vmx_io.o \
vmx_lowlevel.o \
vmx_msr.o \
+ vmx_hw_info.o \
vmcs.o \
vmx_ctrl_regs.o \
vmx_assist.o
#ifdef __V3_32BIT__
print_vmcs_field(VMCS_IO_BITMAP_A_ADDR_HIGH);
#endif
+
print_vmcs_field(VMCS_IO_BITMAP_B_ADDR);
#ifdef __V3_32BIT__
print_vmcs_field(VMCS_IO_BITMAP_B_ADDR_HIGH);
/*
* Returns the field length in bytes
+ * It doesn't get much uglier than this... Thanks Intel
*/
int v3_vmcs_get_field_len(vmcs_field_t field) {
- switch(field) {
- /* 16 bit Control Fields */
- 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:
- 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;
-
- /* 32 bit Control Fields */
- case VMCS_PIN_CTRLS:
- case VMCS_PROC_CTRLS:
- case VMCS_SEC_PROC_CTRLS:
- case VMCS_EXCP_BITMAP:
- case VMCS_PG_FAULT_ERR_MASK:
- case VMCS_PG_FAULT_ERR_MATCH:
- case VMCS_CR3_TGT_CNT:
- case VMCS_EXIT_CTRLS:
- case VMCS_EXIT_MSR_STORE_CNT:
- case VMCS_EXIT_MSR_LOAD_CNT:
- case VMCS_ENTRY_CTRLS:
- case VMCS_ENTRY_MSR_LOAD_CNT:
- case VMCS_ENTRY_INT_INFO:
- case VMCS_ENTRY_EXCP_ERR:
- case VMCS_ENTRY_INSTR_LEN:
- case VMCS_TPR_THRESHOLD:
- case VMCS_INSTR_ERR:
- case VMCS_EXIT_REASON:
- case VMCS_EXIT_INT_INFO:
- case VMCS_EXIT_INT_ERR:
- case VMCS_IDT_VECTOR_INFO:
- case VMCS_IDT_VECTOR_ERR:
- case VMCS_EXIT_INSTR_LEN:
- case VMCS_EXIT_INSTR_INFO:
- case VMCS_GUEST_ES_LIMIT:
- case VMCS_GUEST_CS_LIMIT:
- case VMCS_GUEST_SS_LIMIT:
- case VMCS_GUEST_DS_LIMIT:
- case VMCS_GUEST_FS_LIMIT:
- case VMCS_GUEST_GS_LIMIT:
- case VMCS_GUEST_LDTR_LIMIT:
- case VMCS_GUEST_TR_LIMIT:
- case VMCS_GUEST_GDTR_LIMIT:
- case VMCS_GUEST_IDTR_LIMIT:
- case VMCS_GUEST_ES_ACCESS:
- case VMCS_GUEST_CS_ACCESS:
- case VMCS_GUEST_SS_ACCESS:
- case VMCS_GUEST_DS_ACCESS:
- case VMCS_GUEST_FS_ACCESS:
- case VMCS_GUEST_GS_ACCESS:
- case VMCS_GUEST_LDTR_ACCESS:
- case VMCS_GUEST_TR_ACCESS:
- case VMCS_GUEST_INT_STATE:
- case VMCS_GUEST_ACTIVITY_STATE:
- case VMCS_GUEST_SMBASE:
- case VMCS_GUEST_SYSENTER_CS:
- case VMCS_HOST_SYSENTER_CS:
- return 4;
+ struct vmcs_field_encoding * enc = (struct vmcs_field_encoding *)&field;
-
- /* high bits of variable width fields
- * We can probably just delete most of these....
- */
- case VMCS_IO_BITMAP_A_ADDR_HIGH:
- case VMCS_IO_BITMAP_B_ADDR_HIGH:
- case VMCS_MSR_BITMAP_HIGH:
- case VMCS_EXIT_MSR_STORE_ADDR_HIGH:
- case VMCS_EXIT_MSR_LOAD_ADDR_HIGH:
- case VMCS_ENTRY_MSR_LOAD_ADDR_HIGH:
- case VMCS_EXEC_PTR_HIGH:
- case VMCS_TSC_OFFSET_HIGH:
- case VMCS_VAPIC_ADDR_HIGH:
- case VMCS_APIC_ACCESS_ADDR_HIGH:
- case VMCS_LINK_PTR_HIGH:
- case VMCS_GUEST_DBG_CTL_HIGH:
- case VMCS_GUEST_PERF_GLOBAL_CTRL_HIGH:
- case VMCS_HOST_PERF_GLOBAL_CTRL_HIGH:
- case VMCS_GUEST_EFER_HIGH:
+ switch (enc->width) {
+ case 0:
+ return 2;
+ case 1: {
+ if (enc->access_type == 1) {
+ return 4;
+ } else {
+#ifdef __V3_64BIT__
+ return 8;
+#else
+ return 4;
+#endif
+ }
+ }
+ case 2:
return 4;
-
- /* Natural Width Control Fields */
- case VMCS_IO_BITMAP_A_ADDR:
- case VMCS_IO_BITMAP_B_ADDR:
- case VMCS_MSR_BITMAP:
- case VMCS_EXIT_MSR_STORE_ADDR:
- case VMCS_EXIT_MSR_LOAD_ADDR:
- case VMCS_ENTRY_MSR_LOAD_ADDR:
- case VMCS_EXEC_PTR:
- case VMCS_TSC_OFFSET:
- case VMCS_VAPIC_ADDR:
- case VMCS_APIC_ACCESS_ADDR:
- case VMCS_LINK_PTR:
- case VMCS_GUEST_DBG_CTL:
- case VMCS_GUEST_PERF_GLOBAL_CTRL:
- case VMCS_HOST_PERF_GLOBAL_CTRL:
- case VMCS_CR0_MASK:
- case VMCS_CR4_MASK:
- case VMCS_CR0_READ_SHDW:
- case VMCS_CR4_READ_SHDW:
- case VMCS_CR3_TGT_VAL_0:
- case VMCS_CR3_TGT_VAL_1:
- case VMCS_CR3_TGT_VAL_2:
- case VMCS_CR3_TGT_VAL_3:
- case VMCS_EXIT_QUAL:
- case VMCS_IO_RCX:
- case VMCS_IO_RSI:
- case VMCS_IO_RDI:
- case VMCS_IO_RIP:
- case VMCS_GUEST_LINEAR_ADDR:
- case VMCS_GUEST_CR0:
- case VMCS_GUEST_CR3:
- case VMCS_GUEST_CR4:
- case VMCS_GUEST_ES_BASE:
- case VMCS_GUEST_CS_BASE:
- case VMCS_GUEST_SS_BASE:
- case VMCS_GUEST_DS_BASE:
- case VMCS_GUEST_FS_BASE:
- case VMCS_GUEST_GS_BASE:
- case VMCS_GUEST_LDTR_BASE:
- case VMCS_GUEST_TR_BASE:
- case VMCS_GUEST_GDTR_BASE:
- case VMCS_GUEST_IDTR_BASE:
- case VMCS_GUEST_DR7:
- case VMCS_GUEST_RSP:
- case VMCS_GUEST_RIP:
- case VMCS_GUEST_RFLAGS:
- case VMCS_GUEST_PENDING_DBG_EXCP:
- case VMCS_GUEST_SYSENTER_ESP:
- case VMCS_GUEST_SYSENTER_EIP:
- case VMCS_HOST_CR0:
- case VMCS_HOST_CR3:
- case VMCS_HOST_CR4:
- case VMCS_HOST_FS_BASE:
- case VMCS_HOST_GS_BASE:
- case VMCS_HOST_TR_BASE:
- case VMCS_HOST_GDTR_BASE:
- case VMCS_HOST_IDTR_BASE:
- case VMCS_HOST_SYSENTER_ESP:
- case VMCS_HOST_SYSENTER_EIP:
- case VMCS_HOST_RSP:
- case VMCS_HOST_RIP:
- case VMCS_GUEST_EFER:
+ case 3:
return sizeof(addr_t);
-
default:
PrintError("Invalid VMCS field: 0x%x\n", field);
return -1;
struct v3_vm_info * v3_create_vm(void * cfg, void * priv_data, char * name) {
struct v3_vm_info * vm = v3_config_guest(cfg, priv_data);
- V3_Print("CORE 0 RIP=%p\n", (void *)(addr_t)(vm->cores[0].rip));
-
-
if (vm == NULL) {
PrintError("Could not configure guest\n");
return NULL;
}
+ V3_Print("CORE 0 RIP=%p\n", (void *)(addr_t)(vm->cores[0].rip));
+
if (name == NULL) {
name = "[V3_VM]";
} else if (strlen(name) >= 128) {
#include <palacios/vmx_io.h>
#include <palacios/vmx_msr.h>
+#include <palacios/vmx_hw_info.h>
#ifndef CONFIG_DEBUG_VMX
#undef PrintDebug
#endif
-static addr_t host_vmcs_ptrs[CONFIG_MAX_CPUS] = { [0 ... CONFIG_MAX_CPUS - 1] = 0};
+/* These fields contain the hardware feature sets supported by the local CPU */
+static struct vmx_hw_info hw_info;
+
+
static addr_t active_vmcs_ptrs[CONFIG_MAX_CPUS] = { [0 ... CONFIG_MAX_CPUS - 1] = 0};
+static addr_t host_vmcs_ptrs[CONFIG_MAX_CPUS] = { [0 ... CONFIG_MAX_CPUS - 1] = 0};
extern int v3_vmx_launch(struct v3_gprs * vm_regs, struct guest_info * info, struct v3_ctrl_regs * ctrl_regs);
extern int v3_vmx_resume(struct v3_gprs * vm_regs, struct guest_info * info, struct v3_ctrl_regs * ctrl_regs);
static addr_t allocate_vmcs() {
- reg_ex_t msr;
struct vmcs_data * vmcs_page = NULL;
PrintDebug("Allocating page\n");
vmcs_page = (struct vmcs_data *)V3_VAddr(V3_AllocPages(1));
memset(vmcs_page, 0, 4096);
- v3_get_msr(VMX_BASIC_MSR, &(msr.e_reg.high), &(msr.e_reg.low));
-
- vmcs_page->revision = ((struct vmx_basic_msr*)&msr)->revision;
- PrintDebug("VMX Revision: 0x%x\n",vmcs_page->revision);
+ vmcs_page->revision = hw_info.basic_info.revision;
+ PrintDebug("VMX Revision: 0x%x\n", vmcs_page->revision);
return (addr_t)V3_PAddr((void *)vmcs_page);
}
}
+
+
+#define VMX_FEATURE_CONTROL_MSR 0x0000003a
+#define CPUID_VMX_FEATURES 0x00000005 /* LOCK and VMXON */
+#define CPUID_1_ECX_VTXFLAG 0x00000020
+
int v3_is_vmx_capable() {
v3_msr_t feature_msr;
uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
PrintDebug("MSRREGlow: 0x%.8x\n", feature_msr.lo);
- if ((feature_msr.lo & FEATURE_CONTROL_VALID) != FEATURE_CONTROL_VALID) {
+ if ((feature_msr.lo & CPUID_VMX_FEATURES) != CPUID_VMX_FEATURES) {
PrintDebug("VMX is locked -- enable in the BIOS\n");
return 0;
}
return 1;
}
-static int has_vmx_nested_paging() {
- /* We assume that both EPT and unrestricted guest mode (Intel's Virtual Real Mode)
- * are mutually assured. i.e. We have either both or neither.
- */
-
- return 0;
-}
void v3_init_vmx_cpu(int cpu_id) {
extern v3_cpu_arch_t v3_cpu_types[];
- struct v3_msr tmp_msr;
- uint64_t ret = 0;
-
- v3_get_msr(VMX_CR4_FIXED0_MSR, &(tmp_msr.hi), &(tmp_msr.lo));
-#ifdef __V3_64BIT__
- __asm__ __volatile__ (
- "movq %%cr4, %%rbx;"
- "orq $0x00002000, %%rbx;"
- "movq %%rbx, %0;"
- : "=m"(ret)
- :
- : "%rbx"
- );
-
- if ((~ret & tmp_msr.value) == 0) {
- __asm__ __volatile__ (
- "movq %0, %%cr4;"
- :
- : "q"(ret)
- );
- } else {
- PrintError("Invalid CR4 Settings!\n");
- return;
- }
-
- __asm__ __volatile__ (
- "movq %%cr0, %%rbx; "
- "orq $0x00000020,%%rbx; "
- "movq %%rbx, %%cr0;"
- :
- :
- : "%rbx"
- );
-#elif __V3_32BIT__
- __asm__ __volatile__ (
- "movl %%cr4, %%ecx;"
- "orl $0x00002000, %%ecx;"
- "movl %%ecx, %0;"
- : "=m"(ret)
- :
- : "%ecx"
- );
-
- if ((~ret & tmp_msr.value) == 0) {
- __asm__ __volatile__ (
- "movl %0, %%cr4;"
- :
- : "q"(ret)
- );
- } else {
- PrintError("Invalid CR4 Settings!\n");
- return;
+ if (cpu_id == 0) {
+ if (v3_init_vmx_hw(&hw_info) == -1) {
+ PrintError("Could not initialize VMX hardware features on cpu %d\n", cpu_id);
+ return;
+ }
}
- __asm__ __volatile__ (
- "movl %%cr0, %%ecx; "
- "orl $0x00000020,%%ecx; "
- "movl %%ecx, %%cr0;"
- :
- :
- : "%ecx"
- );
-
-#endif
- //
- // Should check and return Error here....
+ enable_vmx();
// Setup VMXON Region
PrintDebug("VMXON pointer: 0x%p\n", (void *)host_vmcs_ptrs[cpu_id]);
- if (v3_enable_vmx(host_vmcs_ptrs[cpu_id]) == VMX_SUCCESS) {
+ if (vmx_on(host_vmcs_ptrs[cpu_id]) == VMX_SUCCESS) {
PrintDebug("VMX Enabled\n");
} else {
PrintError("VMX initialization failure\n");
}
- if (has_vmx_nested_paging() == 1) {
- v3_cpu_types[cpu_id] = V3_VMX_EPT_CPU;
- } else {
- v3_cpu_types[cpu_id] = V3_VMX_CPU;
- }
+ v3_cpu_types[cpu_id] = V3_VMX_CPU;
+
}
--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2011, Jack Lange <jarusl@cs.northwestern.edu>
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#include <palacios/vmm.h>
+#include <palacios/vmm_lowlevel.h>
+#include <palacios/vmx_hw_info.h>
+
+
+// Intel VMX Feature MSRs
+
+#define VMX_BASIC_MSR 0x00000480
+#define VMX_PINBASED_CTLS_MSR 0x00000481
+#define VMX_PROCBASED_CTLS_MSR 0x00000482
+#define VMX_EXIT_CTLS_MSR 0x00000483
+#define VMX_ENTRY_CTLS_MSR 0x00000484
+#define VMX_MISC_MSR 0x00000485
+#define VMX_CR0_FIXED0_MSR 0x00000486
+#define VMX_CR0_FIXED1_MSR 0x00000487
+#define VMX_CR4_FIXED0_MSR 0x00000488
+#define VMX_CR4_FIXED1_MSR 0x00000489
+#define VMX_VMCS_ENUM_MSR 0x0000048A
+
+
+
+
+
+
+
+int v3_init_vmx_hw(struct vmx_hw_info * hw_info) {
+ // extern v3_cpu_arch_t v3_cpu_types[];
+
+ memset(hw_info, 0, sizeof(struct vmx_hw_info));
+
+ v3_get_msr(VMX_BASIC_MSR, &(hw_info->basic_info.hi), &(hw_info->basic_info.lo));
+
+
+
+ /*
+ if (has_vmx_nested_paging() == 1) {
+ v3_cpu_types[cpu_id] = V3_VMX_EPT_CPU;
+ } else {
+ v3_cpu_types[cpu_id] = V3_VMX_CPU;
+ }
+ */
+ return 0;
+}