#ifdef __V3VEE__
+
#define VMX_BASIC_MSR 0x00000480
#define VMX_PINBASED_CTLS_MSR 0x00000481
#define VMX_PROCBASED_CTLS_MSR 0x00000482
#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" */
} __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);
#include <palacios/vmm.h>
#include <palacios/vmm_lowlevel.h>
#include <palacios/vmx_hw_info.h>
-
+#include <palacios/vmm_msr.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
+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;
+}
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;
}