From: Jack Lange Date: Thu, 21 Apr 2011 23:57:18 +0000 (-0500) Subject: added hardware info for VMX X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=a233b06933d916e4767aa1186568c917df19a8a3;p=palacios.git added hardware info for VMX --- diff --git a/palacios/include/palacios/vmx_hw_info.h b/palacios/include/palacios/vmx_hw_info.h index baade9c..e130545 100644 --- a/palacios/include/palacios/vmx_hw_info.h +++ b/palacios/include/palacios/vmx_hw_info.h @@ -24,6 +24,7 @@ #ifdef __V3VEE__ + #define VMX_BASIC_MSR 0x00000480 #define VMX_PINBASED_CTLS_MSR 0x00000481 #define VMX_PROCBASED_CTLS_MSR 0x00000482 @@ -35,21 +36,28 @@ #define VMX_CR4_FIXED0_MSR 0x00000488 #define VMX_CR4_FIXED1_MSR 0x00000489 #define VMX_VMCS_ENUM_MSR 0x0000048A - +#define VMX_PROCBASED_CTLS2_MSR 0x0000048B +#define VMX_EPT_VPID_CAP_MSR 0x0000048C +#define VMX_TRUE_PINBASED_CTLS_MSR 0x0000048D +#define VMX_TRUE_PROCBASED_CTLS_MSR 0x0000048E +#define VMX_TRUE_EXIT_CTLS_MSR 0x0000048F +#define VMX_TRUE_ENTRY_CTLS_MSR 0x00000490 struct vmx_basic_msr { union { - uint32_t lo; - uint32_t hi; struct { - uint32_t revision; + uint32_t lo; + uint32_t hi; + } __attribute__((packed)); + + struct { uint32_t revision; uint32_t regionSize : 13; - uint8_t rsvd1 : 4; /* Always 0 */ + uint8_t rsvd1 : 3; /* Always 0 */ uint8_t physWidth : 1; /* VMCS address field widths (1=32bits, 0=natural width) */ - uint8_t smm : 1; // Always 1 + uint8_t smm : 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" */ @@ -59,18 +67,99 @@ struct vmx_basic_msr { } __attribute__((packed)); +struct vmx_misc_msr { + union { + struct { + uint32_t lo; + uint32_t hi; + } __attribute__((packed)); + + struct { + uint8_t tsc_multiple : 5; /* Bit position in TSC field that drives vmx timer step */ + uint8_t exits_store_LMA : 1; + uint8_t can_halt : 1; + uint8_t can_shtdown : 1; + uint8_t can_wait_for_sipi : 1; + uint8_t rsvd1 : 7; + uint16_t num_cr3_targets : 9; + uint8_t max_msr_cache_size : 3; /* (512 * (max_msr_cache_size + 1)) == max msr load/store list size */ + uint8_t SMM_ctrl_avail : 1; + uint8_t rsvd2 : 3; + uint32_t MSEG_rev_id; + } __attribute__((packed)); + } __attribute__((packed)); +} __attribute__((packed)); + + +struct vmx_ept_msr { + union { + struct { + uint32_t lo; + uint32_t hi; + } __attribute__((packed)); + + struct { + uint8_t exec_only_ok : 1; + uint8_t rsvd1 : 5; + uint8_t pg_walk_len4 : 1; /* support for a page walk of length 4 */ + uint8_t rsvd2 : 1; + uint8_t ept_uc_ok : 1; /* EPT page tables can be uncacheable */ + uint8_t rsvd3 : 5; + uint8_t ept_wb_ok : 1; /* EPT page tables can be writeback */ + uint8_t rsvd4 : 1; + uint8_t ept_2MB_ok : 1; /* 2MB EPT pages supported */ + uint8_t ept_1GB_ok : 1; /* 1GB EPT pages supported */ + uint8_t rsvd5 : 2; + uint8_t INVEPT_avail : 1; /* INVEPT instruction is available */ + uint8_t rsvd6 : 4; + uint8_t INVEPT_single_ctx_avail : 1; + uint8_t INVEPT_all_ctx_avail : 1; + uint8_t rsvd7 : 5; + uint8_t INVVPID_avail : 1; + uint8_t rsvd8 : 7; + uint8_t INVVPID_1addr_avail : 1; + uint8_t INVVPID_single_ctx_avail : 1; + uint8_t INVVPID_all_ctx_avail : 1; + uint8_t INVVPID_single_ctx_w_glbls_avail : 1; + uint32_t rsvd9 : 20; + } __attribute__((packed)); + } __attribute__((packed)); +}__attribute__((packed)); + + +struct vmx_ctrl_field { + uint32_t def_val; + uint32_t req_val; /* Required values: field_val & req_mask == req_val */ + uint32_t req_mask; /* If a mask bit is set it's value is restricted (i.e. the VMM cannot change it) */ +}; + + +struct vmx_cr_field { + uint64_t def_val; + uint64_t req_val; /* Required values: field_val & req_mask == req_val */ + uint64_t req_mask; /* If a mask bit is set it's value is restricted (i.e. the VMM cannot change it) */ +}; + struct vmx_hw_info { struct vmx_basic_msr basic_info; - + struct vmx_misc_msr misc_info; + struct vmx_ept_msr ept_info; + struct vmx_ctrl_field pin_ctrls; + struct vmx_ctrl_field proc_ctrls; + struct vmx_ctrl_field exit_ctrls; + struct vmx_ctrl_field entry_ctrls; + struct vmx_ctrl_field proc_ctrls_2; + struct vmx_cr_field cr0; + struct vmx_cr_field cr4; }; -int v3_init_vmx_hw(); +int v3_init_vmx_hw(struct vmx_hw_info * hw_info); diff --git a/palacios/src/palacios/vmx_hw_info.c b/palacios/src/palacios/vmx_hw_info.c index 90b055f..3220e52 100644 --- a/palacios/src/palacios/vmx_hw_info.c +++ b/palacios/src/palacios/vmx_hw_info.c @@ -20,23 +20,64 @@ #include #include #include - +#include // 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 +static int get_ex_ctrl_caps(struct vmx_hw_info * hw_info, struct vmx_ctrl_field * field, + uint32_t old_msr, uint32_t true_msr) { + uint32_t old_0; /* Bit is 1 => MB1 */ + uint32_t old_1; /* Bit is 0 => MBZ */ + uint32_t true_0; /* Bit is 1 => MB1 */ + uint32_t true_1; /* Bit is 0 => MBZ */ + + v3_get_msr(old_msr, &old_1, &old_0); + field->def_val = old_0; + + if (hw_info->basic_info.def1_maybe_0) { + v3_get_msr(true_msr, &true_1, &true_0); + } else { + true_0 = old_0; + true_1 = old_1; + } + + field->req_val = true_0; + field->req_mask = ~(true_1 ^ true_0); + + return 0; +} + + +static int get_ctrl_caps(struct vmx_ctrl_field * field, uint32_t msr) { + uint32_t mbz = 0; /* Bit is 0 => MBZ */ + uint32_t mb1 = 0; /* Bit is 1 => MB1 */ + + v3_get_msr(msr, &mbz, &mb1); + + field->def_val = mb1; + field->req_val = mb1; + field->req_mask = ~(mbz ^ mb1); + + return 0; +} + + + +static int get_cr_fields(struct vmx_cr_field * field, uint32_t fixed_1_msr, uint32_t fixed_0_msr) { + struct v3_msr mbz; /* Bit is 0 => MBZ */ + struct v3_msr mb1; /* Bit is 0 => MBZ */ + + v3_get_msr(fixed_1_msr, &(mbz.hi), &(mbz.lo)); + v3_get_msr(fixed_0_msr, &(mb1.hi), &(mb1.lo)); + + field->def_val = mb1.value; + field->req_val = mb1.value; + field->req_mask = ~(mbz.value ^ mb1.value); + + return 0; +} @@ -48,15 +89,25 @@ int v3_init_vmx_hw(struct vmx_hw_info * hw_info) { 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)); - + v3_get_msr(VMX_MISC_MSR, &(hw_info->misc_info.hi), &(hw_info->misc_info.lo)); + v3_get_msr(VMX_EPT_VPID_CAP_MSR, &(hw_info->ept_info.hi), &(hw_info->ept_info.lo)); + PrintError("BASIC_MSR: Lo: %x, Hi: %x\n", hw_info->basic_info.lo, hw_info->basic_info.hi); - /* - if (has_vmx_nested_paging() == 1) { - v3_cpu_types[cpu_id] = V3_VMX_EPT_CPU; - } else { - v3_cpu_types[cpu_id] = V3_VMX_CPU; + get_ex_ctrl_caps(hw_info, &(hw_info->pin_ctrls), VMX_PINBASED_CTLS_MSR, VMX_TRUE_PINBASED_CTLS_MSR); + get_ex_ctrl_caps(hw_info, &(hw_info->proc_ctrls), VMX_PROCBASED_CTLS_MSR, VMX_TRUE_PROCBASED_CTLS_MSR); + get_ex_ctrl_caps(hw_info, &(hw_info->exit_ctrls), VMX_EXIT_CTLS_MSR, VMX_TRUE_EXIT_CTLS_MSR); + get_ex_ctrl_caps(hw_info, &(hw_info->entry_ctrls), VMX_ENTRY_CTLS_MSR, VMX_TRUE_ENTRY_CTLS_MSR); + + /* Get secondary PROCBASED controls if secondary controls are available (optional or required) */ + /* Intel Manual 3B. Sect. G.3.3 */ + if ( ((hw_info->proc_ctrls.req_mask & 0x80000000) == 0) || + ((hw_info->proc_ctrls.req_val & 0x80000000) == 1) ) { + get_ctrl_caps(&(hw_info->proc_ctrls_2), VMX_PROCBASED_CTLS2_MSR); } - */ + + get_cr_fields(&(hw_info->cr0), VMX_CR0_FIXED1_MSR, VMX_CR0_FIXED0_MSR); + get_cr_fields(&(hw_info->cr4), VMX_CR4_FIXED1_MSR, VMX_CR4_FIXED0_MSR); + return 0; }