X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmcs.c;h=e7f957088afea109d44e344f7ea0999521b69712;hb=cfcceed5890430afedcc544bd7dbb69e29dfd65a;hp=af8bc2e47c736bcefab577c689f82561fa5f0613;hpb=a1d3e2f36e9ef64ca62c611c4f0aa050726e186b;p=palacios.git diff --git a/palacios/src/palacios/vmcs.c b/palacios/src/palacios/vmcs.c index af8bc2e..e7f9570 100644 --- a/palacios/src/palacios/vmcs.c +++ b/palacios/src/palacios/vmcs.c @@ -20,7 +20,62 @@ #include #include #include +#include +#include +#include +#include +static void inline translate_v3_seg_to_access(struct v3_segment * v3_seg, + struct vmcs_segment_access * access) +{ + access->type = v3_seg->type; + access->desc_type = v3_seg->system; + access->dpl = v3_seg->dpl; + access->present = v3_seg->present; + access->avail = v3_seg->avail; + access->long_mode = v3_seg->long_mode; + access->db = v3_seg->db; + access->granularity = v3_seg->granularity; +} + +static void inline translate_access_to_v3_seg(struct vmcs_segment_access * access, + struct v3_segment * v3_seg) +{ + v3_seg->type = access->type; + v3_seg->system = access->desc_type; + v3_seg->dpl = access->dpl; + v3_seg->present = access->present; + v3_seg->avail = access->avail; + v3_seg->long_mode = access->long_mode; + v3_seg->db = access->db; + v3_seg->granularity = access->granularity; +} + + +static int inline check_vmcs_write(vmcs_field_t field, addr_t val) +{ + int ret = 0; + ret = vmcs_write(field, val); + + if (ret != VMX_SUCCESS) { + PrintError("VMWRITE error on %s!: %d\n", v3_vmcs_field_to_str(field), ret); + return 1; + } + + return 0; +} + +static int inline check_vmcs_read(vmcs_field_t field, void * val) +{ + int ret = 0; + ret = vmcs_read(field, val); + + if (ret != VMX_SUCCESS) { + PrintError("VMREAD error on %s!: %d\n", v3_vmcs_field_to_str(field), ret); + } + + return ret; +} // static const char * v3_vmcs_field_to_str(vmcs_field_t field); @@ -29,209 +84,639 @@ // Ignores "HIGH" addresses - 32 bit only for now // +int v3_update_vmcs_guest_state(struct guest_info * info) +{ + int vmx_ret = 0; + + vmx_ret |= check_vmcs_write(VMCS_GUEST_RIP, info->rip); + vmx_ret |= check_vmcs_write(VMCS_GUEST_RSP, info->vm_regs.rsp); + + + vmx_ret |= check_vmcs_write(VMCS_GUEST_CR0, info->ctrl_regs.cr0); + vmx_ret |= check_vmcs_write(VMCS_CR0_READ_SHDW, info->shdw_pg_state.guest_cr0); + vmx_ret |= check_vmcs_write(VMCS_GUEST_CR3, info->ctrl_regs.cr3); + vmx_ret |= check_vmcs_write(VMCS_GUEST_CR4, info->ctrl_regs.cr4); + vmx_ret |= check_vmcs_write(VMCS_GUEST_DR7, info->dbg_regs.dr7); + + vmx_ret |= check_vmcs_write(VMCS_GUEST_RFLAGS, info->ctrl_regs.rflags); + if (((struct vmx_data *)info->vmm_data)->ia32e_avail) { + vmx_ret |= check_vmcs_write(VMCS_GUEST_EFER, info->ctrl_regs.efer); + } + + + /*** Write VMCS Segments ***/ + struct vmcs_segment_access access; + + memset(&access, 0, sizeof(access)); + + /* CS Segment */ + translate_v3_seg_to_access(&(info->segments.cs), &access); + + vmx_ret |= check_vmcs_write(VMCS_GUEST_CS_BASE, info->segments.cs.base); + vmx_ret |= check_vmcs_write(VMCS_GUEST_CS_SELECTOR, info->segments.cs.selector); + vmx_ret |= check_vmcs_write(VMCS_GUEST_CS_LIMIT, info->segments.cs.limit); + vmx_ret |= check_vmcs_write(VMCS_GUEST_CS_ACCESS, access.value); + + /* SS Segment */ + memset(&access, 0, sizeof(access)); + translate_v3_seg_to_access(&(info->segments.ss), &access); + + vmx_ret |= check_vmcs_write(VMCS_GUEST_SS_BASE, info->segments.ss.base); + vmx_ret |= check_vmcs_write(VMCS_GUEST_SS_SELECTOR, info->segments.ss.selector); + vmx_ret |= check_vmcs_write(VMCS_GUEST_SS_LIMIT, info->segments.ss.limit); + vmx_ret |= check_vmcs_write(VMCS_GUEST_SS_ACCESS, access.value); + + /* DS Segment */ + memset(&access, 0, sizeof(access)); + translate_v3_seg_to_access(&(info->segments.ds), &access); + + vmx_ret |= check_vmcs_write(VMCS_GUEST_DS_BASE, info->segments.ds.base); + vmx_ret |= check_vmcs_write(VMCS_GUEST_DS_SELECTOR, info->segments.ds.selector); + vmx_ret |= check_vmcs_write(VMCS_GUEST_DS_LIMIT, info->segments.ds.limit); + vmx_ret |= check_vmcs_write(VMCS_GUEST_DS_ACCESS, access.value); + + + /* ES Segment */ + memset(&access, 0, sizeof(access)); + translate_v3_seg_to_access(&(info->segments.es), &access); + + vmx_ret |= check_vmcs_write(VMCS_GUEST_ES_BASE, info->segments.es.base); + vmx_ret |= check_vmcs_write(VMCS_GUEST_ES_SELECTOR, info->segments.es.selector); + vmx_ret |= check_vmcs_write(VMCS_GUEST_ES_LIMIT, info->segments.es.limit); + vmx_ret |= check_vmcs_write(VMCS_GUEST_ES_ACCESS, access.value); + + /* FS Segment */ + memset(&access, 0, sizeof(access)); + translate_v3_seg_to_access(&(info->segments.fs), &access); + + vmx_ret |= check_vmcs_write(VMCS_GUEST_FS_BASE, info->segments.fs.base); + vmx_ret |= check_vmcs_write(VMCS_GUEST_FS_SELECTOR, info->segments.fs.selector); + vmx_ret |= check_vmcs_write(VMCS_GUEST_FS_LIMIT, info->segments.fs.limit); + vmx_ret |= check_vmcs_write(VMCS_GUEST_FS_ACCESS, access.value); + + /* GS Segment */ + memset(&access, 0, sizeof(access)); + translate_v3_seg_to_access(&(info->segments.gs), &access); + + vmx_ret |= check_vmcs_write(VMCS_GUEST_GS_BASE, info->segments.gs.base); + vmx_ret |= check_vmcs_write(VMCS_GUEST_GS_SELECTOR, info->segments.gs.selector); + vmx_ret |= check_vmcs_write(VMCS_GUEST_GS_LIMIT, info->segments.gs.limit); + vmx_ret |= check_vmcs_write(VMCS_GUEST_GS_ACCESS, access.value); + + /* LDTR segment */ + memset(&access, 0, sizeof(access)); + translate_v3_seg_to_access(&(info->segments.ldtr), &access); + + vmx_ret |= check_vmcs_write(VMCS_GUEST_LDTR_BASE, info->segments.ldtr.base); + vmx_ret |= check_vmcs_write(VMCS_GUEST_LDTR_SELECTOR, info->segments.ldtr.selector); + vmx_ret |= check_vmcs_write(VMCS_GUEST_LDTR_LIMIT, info->segments.ldtr.limit); + vmx_ret |= check_vmcs_write(VMCS_GUEST_LDTR_ACCESS, access.value); + + /* TR Segment */ + memset(&access, 0, sizeof(access)); + translate_v3_seg_to_access(&(info->segments.tr), &access); + + vmx_ret |= check_vmcs_write(VMCS_GUEST_TR_BASE, info->segments.tr.base); + vmx_ret |= check_vmcs_write(VMCS_GUEST_TR_SELECTOR, info->segments.tr.selector); + vmx_ret |= check_vmcs_write(VMCS_GUEST_TR_LIMIT, info->segments.tr.limit); + vmx_ret |= check_vmcs_write(VMCS_GUEST_TR_ACCESS, access.value); + + /* GDTR Segment */ + + vmx_ret |= check_vmcs_write(VMCS_GUEST_GDTR_BASE, info->segments.gdtr.base); + vmx_ret |= check_vmcs_write(VMCS_GUEST_GDTR_LIMIT, info->segments.gdtr.limit); + + /* IDTR Segment*/ + vmx_ret |= check_vmcs_write(VMCS_GUEST_IDTR_BASE, info->segments.idtr.base); + vmx_ret |= check_vmcs_write(VMCS_GUEST_IDTR_LIMIT, info->segments.idtr.limit); + + return vmx_ret; + +} + +int v3_update_vmcs_ctrl_fields(struct guest_info * info) { + int vmx_ret = 0; + struct vmx_data * arch_data = (struct vmx_data *)(info->vmm_data); + + vmx_ret |= check_vmcs_write(VMCS_PIN_CTRLS, arch_data->pin_ctrls.value); + vmx_ret |= check_vmcs_write(VMCS_PROC_CTRLS, arch_data->pri_proc_ctrls.value); + + if (arch_data->pri_proc_ctrls.sec_ctrls) { + vmx_ret |= check_vmcs_write(VMCS_SEC_PROC_CTRLS, arch_data->sec_proc_ctrls.value); + } + + vmx_ret |= check_vmcs_write(VMCS_EXIT_CTRLS, arch_data->exit_ctrls.value); + vmx_ret |= check_vmcs_write(VMCS_ENTRY_CTRLS, arch_data->entry_ctrls.value); + + return vmx_ret; +} + +int v3_update_vmcs_host_state(struct guest_info * info) { + int vmx_ret = 0; + addr_t tmp; + struct vmx_data * arch_data = (struct vmx_data *)(info->vmm_data); + struct v3_msr tmp_msr; + + __asm__ __volatile__ ( "movq %%cr0, %0; " + : "=q"(tmp) + : + ); + vmx_ret |= check_vmcs_write(VMCS_HOST_CR0, tmp); + + + __asm__ __volatile__ ( "movq %%cr3, %0; " + : "=q"(tmp) + : + ); + vmx_ret |= check_vmcs_write(VMCS_HOST_CR3, tmp); + + + __asm__ __volatile__ ( "movq %%cr4, %0; " + : "=q"(tmp) + : + ); + vmx_ret |= check_vmcs_write(VMCS_HOST_CR4, tmp); + + + + vmx_ret |= check_vmcs_write(VMCS_HOST_GDTR_BASE, arch_data->host_state.gdtr.base); + vmx_ret |= check_vmcs_write(VMCS_HOST_IDTR_BASE, arch_data->host_state.idtr.base); + vmx_ret |= check_vmcs_write(VMCS_HOST_TR_BASE, arch_data->host_state.tr.base); + +#define FS_BASE_MSR 0xc0000100 +#define GS_BASE_MSR 0xc0000101 + + // FS.BASE MSR + v3_get_msr(FS_BASE_MSR, &(tmp_msr.hi), &(tmp_msr.lo)); + vmx_ret |= check_vmcs_write(VMCS_HOST_FS_BASE, tmp_msr.value); + + // GS.BASE MSR + v3_get_msr(GS_BASE_MSR, &(tmp_msr.hi), &(tmp_msr.lo)); + vmx_ret |= check_vmcs_write(VMCS_HOST_GS_BASE, tmp_msr.value); + + + + __asm__ __volatile__ ( "movq %%cs, %0; " + : "=q"(tmp) + : + ); + vmx_ret |= check_vmcs_write(VMCS_HOST_CS_SELECTOR, tmp); + + __asm__ __volatile__ ( "movq %%ss, %0; " + : "=q"(tmp) + : + ); + vmx_ret |= check_vmcs_write(VMCS_HOST_SS_SELECTOR, tmp); + + __asm__ __volatile__ ( "movq %%ds, %0; " + : "=q"(tmp) + : + ); + vmx_ret |= check_vmcs_write(VMCS_HOST_DS_SELECTOR, tmp); + + __asm__ __volatile__ ( "movq %%es, %0; " + : "=q"(tmp) + : + ); + vmx_ret |= check_vmcs_write(VMCS_HOST_ES_SELECTOR, tmp); + + __asm__ __volatile__ ( "movq %%fs, %0; " + : "=q"(tmp) + : + ); + vmx_ret |= check_vmcs_write(VMCS_HOST_FS_SELECTOR, tmp); + + __asm__ __volatile__ ( "movq %%gs, %0; " + : "=q"(tmp) + : + ); + vmx_ret |= check_vmcs_write(VMCS_HOST_GS_SELECTOR, tmp); + + vmx_ret |= check_vmcs_write(VMCS_HOST_TR_SELECTOR, arch_data->host_state.tr.selector); + + +#define SYSENTER_CS_MSR 0x00000174 +#define SYSENTER_ESP_MSR 0x00000175 +#define SYSENTER_EIP_MSR 0x00000176 + + // SYSENTER CS MSR + v3_get_msr(SYSENTER_CS_MSR, &(tmp_msr.hi), &(tmp_msr.lo)); + vmx_ret |= check_vmcs_write(VMCS_HOST_SYSENTER_CS, tmp_msr.lo); + + // SYSENTER_ESP MSR + v3_get_msr(SYSENTER_ESP_MSR, &(tmp_msr.hi), &(tmp_msr.lo)); + vmx_ret |= check_vmcs_write(VMCS_HOST_SYSENTER_ESP, tmp_msr.value); + + // SYSENTER_EIP MSR + v3_get_msr(SYSENTER_EIP_MSR, &(tmp_msr.hi), &(tmp_msr.lo)); + vmx_ret |= check_vmcs_write(VMCS_HOST_SYSENTER_EIP, tmp_msr.value); + + return vmx_ret; +} + + +int v3_load_vmcs_guest_state(struct guest_info * info) +{ + + int error = 0; + + check_vmcs_read(VMCS_GUEST_RIP, &(info->rip)); + check_vmcs_read(VMCS_GUEST_RSP, &(info->vm_regs.rsp)); + + check_vmcs_read(VMCS_GUEST_CR0, &(info->ctrl_regs.cr0)); + check_vmcs_read(VMCS_CR0_READ_SHDW, &(info->shdw_pg_state.guest_cr0)); + check_vmcs_read(VMCS_GUEST_CR3, &(info->ctrl_regs.cr3)); + check_vmcs_read(VMCS_GUEST_CR4, &(info->ctrl_regs.cr4)); + check_vmcs_read(VMCS_GUEST_DR7, &(info->dbg_regs.dr7)); + + check_vmcs_read(VMCS_GUEST_RFLAGS, &(info->ctrl_regs.rflags)); + if (((struct vmx_data *)info->vmm_data)->ia32e_avail) { + check_vmcs_read(VMCS_GUEST_EFER, &(info->ctrl_regs.efer)); + } + + // JRL: Add error checking + + struct vmcs_segment_access access; + memset(&access, 0, sizeof(access)); + + /* CS Segment */ + check_vmcs_read(VMCS_GUEST_CS_BASE, &(info->segments.cs.base)); + check_vmcs_read(VMCS_GUEST_CS_SELECTOR, &(info->segments.cs.selector)); + check_vmcs_read(VMCS_GUEST_CS_LIMIT, &(info->segments.cs.limit)); + check_vmcs_read(VMCS_GUEST_CS_ACCESS, &(access.value)); + + translate_access_to_v3_seg(&access, &(info->segments.cs)); + + /* SS Segment */ + check_vmcs_read(VMCS_GUEST_SS_BASE, &(info->segments.ss.base)); + check_vmcs_read(VMCS_GUEST_SS_SELECTOR, &(info->segments.ss.selector)); + check_vmcs_read(VMCS_GUEST_SS_LIMIT, &(info->segments.ss.limit)); + check_vmcs_read(VMCS_GUEST_SS_ACCESS, &(access.value)); + + translate_access_to_v3_seg(&access, &(info->segments.ss)); + + /* DS Segment */ + check_vmcs_read(VMCS_GUEST_DS_BASE, &(info->segments.ds.base)); + check_vmcs_read(VMCS_GUEST_DS_SELECTOR, &(info->segments.ds.selector)); + check_vmcs_read(VMCS_GUEST_DS_LIMIT, &(info->segments.ds.limit)); + check_vmcs_read(VMCS_GUEST_DS_ACCESS, &(access.value)); + + translate_access_to_v3_seg(&access, &(info->segments.ds)); + + /* ES Segment */ + check_vmcs_read(VMCS_GUEST_ES_BASE, &(info->segments.es.base)); + check_vmcs_read(VMCS_GUEST_ES_SELECTOR, &(info->segments.es.selector)); + check_vmcs_read(VMCS_GUEST_ES_LIMIT, &(info->segments.es.limit)); + check_vmcs_read(VMCS_GUEST_ES_ACCESS, &(access.value)); + + translate_access_to_v3_seg(&access, &(info->segments.es)); + + /* FS Segment */ + check_vmcs_read(VMCS_GUEST_FS_BASE, &(info->segments.fs.base)); + check_vmcs_read(VMCS_GUEST_FS_SELECTOR, &(info->segments.fs.selector)); + check_vmcs_read(VMCS_GUEST_FS_LIMIT, &(info->segments.fs.limit)); + check_vmcs_read(VMCS_GUEST_FS_ACCESS, &(access.value)); + + translate_access_to_v3_seg(&access, &(info->segments.fs)); + + /* GS Segment */ + check_vmcs_read(VMCS_GUEST_GS_BASE, &(info->segments.gs.base)); + check_vmcs_read(VMCS_GUEST_GS_SELECTOR, &(info->segments.gs.selector)); + check_vmcs_read(VMCS_GUEST_GS_LIMIT, &(info->segments.gs.limit)); + check_vmcs_read(VMCS_GUEST_GS_ACCESS, &(access.value)); + + translate_access_to_v3_seg(&access, &(info->segments.gs)); + + /* LDTR Segment */ + check_vmcs_read(VMCS_GUEST_LDTR_BASE, &(info->segments.ldtr.base)); + check_vmcs_read(VMCS_GUEST_LDTR_SELECTOR, &(info->segments.ldtr.selector)); + check_vmcs_read(VMCS_GUEST_LDTR_LIMIT, &(info->segments.ldtr.limit)); + check_vmcs_read(VMCS_GUEST_LDTR_ACCESS, &(access.value)); + + translate_access_to_v3_seg(&access, &(info->segments.ldtr)); + + /* TR Segment */ + check_vmcs_read(VMCS_GUEST_TR_BASE, &(info->segments.tr.base)); + check_vmcs_read(VMCS_GUEST_TR_SELECTOR, &(info->segments.tr.selector)); + check_vmcs_read(VMCS_GUEST_TR_LIMIT, &(info->segments.tr.limit)); + check_vmcs_read(VMCS_GUEST_TR_ACCESS, &(access.value)); + + translate_access_to_v3_seg(&access, &(info->segments.tr)); + + /* GDTR Segment */ + check_vmcs_read(VMCS_GUEST_GDTR_BASE, &(info->segments.gdtr.base)); + check_vmcs_read(VMCS_GUEST_GDTR_LIMIT, &(info->segments.gdtr.limit)); + + /* IDTR Segment */ + check_vmcs_read(VMCS_GUEST_IDTR_BASE, &(info->segments.idtr.base)); + check_vmcs_read(VMCS_GUEST_IDTR_LIMIT, &(info->segments.idtr.limit)); + + return error; +} static inline void print_vmcs_field(vmcs_field_t vmcs_index) { int len = v3_vmcs_get_field_len(vmcs_index); addr_t val; - if (vmcs_read(vmcs_index, &val, len) != VMX_SUCCESS) { - PrintError("VMCS_READ error for index %x\n", vmcs_index); + if (vmcs_read(vmcs_index, &val) != VMX_SUCCESS) { + PrintError("VMCS_READ error for %s\n", v3_vmcs_field_to_str(vmcs_index)); return; }; if (len == 2) { - PrintDebug("%s: %x\n", v3_vmcs_field_to_str(vmcs_index), (uint16_t)val); + PrintDebug("\t%s: 0x%.4x\n", v3_vmcs_field_to_str(vmcs_index), (uint16_t)val); } else if (len == 4) { - PrintDebug("%s: %x\n", v3_vmcs_field_to_str(vmcs_index), (uint32_t)val); + PrintDebug("\t%s: 0x%.8x\n", v3_vmcs_field_to_str(vmcs_index), (uint32_t)val); } else if (len == 8) { - PrintDebug("%s: %p\n", v3_vmcs_field_to_str(vmcs_index), (void *)(addr_t)val); + PrintDebug("\t%s: 0x%p\n", v3_vmcs_field_to_str(vmcs_index), (void *)(addr_t)val); } } -void v3_print_vmcs_guest_state() +static void print_guest_state() { - PrintDebug("\n===== VMCS Guest State =====\n"); + PrintDebug("VMCS_GUEST_STATE\n"); print_vmcs_field(VMCS_GUEST_RIP); print_vmcs_field(VMCS_GUEST_RSP); + print_vmcs_field(VMCS_GUEST_RFLAGS); print_vmcs_field(VMCS_GUEST_CR0); print_vmcs_field(VMCS_GUEST_CR3); print_vmcs_field(VMCS_GUEST_CR4); print_vmcs_field(VMCS_GUEST_DR7); - PrintDebug("\n=== CS Segment===\n"); + + PrintDebug("\n"); + + PrintDebug(" ==> CS\n"); print_vmcs_field(VMCS_GUEST_CS_SELECTOR); print_vmcs_field(VMCS_GUEST_CS_BASE); print_vmcs_field(VMCS_GUEST_CS_LIMIT); print_vmcs_field(VMCS_GUEST_CS_ACCESS); - PrintDebug("\n=== SS Segment ===\n"); + PrintDebug(" ==> SS\n"); print_vmcs_field(VMCS_GUEST_SS_SELECTOR); print_vmcs_field(VMCS_GUEST_SS_BASE); print_vmcs_field(VMCS_GUEST_SS_LIMIT); print_vmcs_field(VMCS_GUEST_SS_ACCESS); - PrintDebug("\n=== DS Segment ===\n"); + PrintDebug(" ==> DS\n"); print_vmcs_field(VMCS_GUEST_DS_SELECTOR); print_vmcs_field(VMCS_GUEST_DS_BASE); print_vmcs_field(VMCS_GUEST_DS_LIMIT); print_vmcs_field(VMCS_GUEST_DS_ACCESS); - PrintDebug("\n=== ES Segment ===\n"); + PrintDebug(" ==> ES\n"); print_vmcs_field(VMCS_GUEST_ES_SELECTOR); print_vmcs_field(VMCS_GUEST_ES_BASE); print_vmcs_field(VMCS_GUEST_ES_LIMIT); print_vmcs_field(VMCS_GUEST_ES_ACCESS); - PrintDebug("\n=== FS Segment ===\n"); + PrintDebug(" ==> FS\n"); print_vmcs_field(VMCS_GUEST_FS_SELECTOR); print_vmcs_field(VMCS_GUEST_FS_BASE); print_vmcs_field(VMCS_GUEST_FS_LIMIT); print_vmcs_field(VMCS_GUEST_FS_ACCESS); - PrintDebug("\n=== GS Segment ===\n"); + PrintDebug(" ==> GS\n"); print_vmcs_field(VMCS_GUEST_GS_SELECTOR); print_vmcs_field(VMCS_GUEST_GS_BASE); print_vmcs_field(VMCS_GUEST_GS_LIMIT); print_vmcs_field(VMCS_GUEST_GS_ACCESS); - PrintDebug("\n=== LDTR Segment ===\n"); + PrintDebug(" ==> LDTR\n"); print_vmcs_field(VMCS_GUEST_LDTR_SELECTOR); print_vmcs_field(VMCS_GUEST_LDTR_BASE); print_vmcs_field(VMCS_GUEST_LDTR_LIMIT); print_vmcs_field(VMCS_GUEST_LDTR_ACCESS); - PrintDebug("\n=== TR Segment ===\n"); + PrintDebug(" ==> TR\n"); print_vmcs_field(VMCS_GUEST_TR_SELECTOR); print_vmcs_field(VMCS_GUEST_TR_BASE); print_vmcs_field(VMCS_GUEST_TR_LIMIT); print_vmcs_field(VMCS_GUEST_TR_ACCESS); - PrintDebug("\n=== GDTR ===\n"); + PrintDebug(" ==> GDTR\n"); print_vmcs_field(VMCS_GUEST_GDTR_BASE); print_vmcs_field(VMCS_GUEST_GDTR_LIMIT); - PrintDebug("\n=== IDTR ===\n"); + PrintDebug(" ==> IDTR\n"); print_vmcs_field(VMCS_GUEST_IDTR_BASE); print_vmcs_field(VMCS_GUEST_IDTR_LIMIT); PrintDebug("\n"); - print_vmcs_field(VMCS_GUEST_RFLAGS); - print_vmcs_field(VMCS_GUEST_ACTIVITY_STATE); - print_vmcs_field(VMCS_GUEST_INT_STATE); - print_vmcs_field(VMCS_GUEST_PENDING_DBG_EXCP); print_vmcs_field(VMCS_GUEST_DBG_CTL); +#ifdef __V3_32BIT__ + print_vmcs_field(VMCS_GUEST_DBG_CTL_HIGH); +#endif print_vmcs_field(VMCS_GUEST_SYSENTER_CS); print_vmcs_field(VMCS_GUEST_SYSENTER_ESP); print_vmcs_field(VMCS_GUEST_SYSENTER_EIP); + print_vmcs_field(VMCS_GUEST_PERF_GLOBAL_CTRL); - print_vmcs_field(VMCS_LINK_PTR); +#ifdef __V3_32BIT__ + print_vmcs_field(VMCS_GUEST_PERF_GLOBAL_CTRL_HIGH); +#endif + + print_vmcs_field(VMCS_GUEST_SMBASE); + + + PrintDebug("GUEST_NON_REGISTER_STATE\n"); + + print_vmcs_field(VMCS_GUEST_ACTIVITY_STATE); + print_vmcs_field(VMCS_GUEST_INT_STATE); + print_vmcs_field(VMCS_GUEST_PENDING_DBG_EXCP); - PrintDebug("\n"); } -/* -void print_debug_vmcs_load_guest() { - const int wordsize = sizeof(addr_t); - uint64_t temp; - struct vmcs_segment_access tmp_seg; - - PrintDebug("\n====== Loading Guest State ======\n"); - PRINT_VMREAD("Guest CR0: %x\n", GUEST_CR0, wordsize); - PRINT_VMREAD("Guest CR3: %x\n", GUEST_CR3, wordsize); - PRINT_VMREAD("Guest CR4: %x\n", GUEST_CR4, wordsize); - PRINT_VMREAD("Guest DR7: %x\n", GUEST_DR7, wordsize); - - READ_VMCS_SEG(&tmp_seg,CS,wordsize); - print_vmcs_segment("CS", &tmp_seg); +static void print_host_state() +{ + PrintDebug("VMCS_HOST_STATE\n"); + + print_vmcs_field(VMCS_HOST_RIP); + print_vmcs_field(VMCS_HOST_RSP); + print_vmcs_field(VMCS_HOST_CR0); + print_vmcs_field(VMCS_HOST_CR3); + print_vmcs_field(VMCS_HOST_CR4); + + PrintDebug("\n"); + print_vmcs_field(VMCS_HOST_CS_SELECTOR); + print_vmcs_field(VMCS_HOST_SS_SELECTOR); + print_vmcs_field(VMCS_HOST_DS_SELECTOR); + print_vmcs_field(VMCS_HOST_ES_SELECTOR); + print_vmcs_field(VMCS_HOST_FS_SELECTOR); + print_vmcs_field(VMCS_HOST_GS_SELECTOR); + print_vmcs_field(VMCS_HOST_TR_SELECTOR); + + PrintDebug("\n"); + print_vmcs_field(VMCS_HOST_FS_BASE); + print_vmcs_field(VMCS_HOST_GS_BASE); + print_vmcs_field(VMCS_HOST_TR_BASE); + print_vmcs_field(VMCS_HOST_GDTR_BASE); + print_vmcs_field(VMCS_HOST_IDTR_BASE); + + PrintDebug("\n"); + print_vmcs_field(VMCS_HOST_SYSENTER_CS); + print_vmcs_field(VMCS_HOST_SYSENTER_ESP); + print_vmcs_field(VMCS_HOST_SYSENTER_EIP); + + print_vmcs_field(VMCS_HOST_PERF_GLOBAL_CTRL); +#ifdef __V3_32BIT__ + print_vmcs_field(VMCS_HOST_PERF_GLOBAL_CTRL_HIGH); +#endif +} + + +static void print_exec_ctrls() { + PrintDebug("VMCS_EXEC_CTRL_FIELDS\n"); + print_vmcs_field(VMCS_PIN_CTRLS); + print_vmcs_field(VMCS_PROC_CTRLS); + print_vmcs_field(VMCS_SEC_PROC_CTRLS); - READ_VMCS_SEG(&tmp_seg,SS,wordsize); - print_vmcs_segment("SS", &tmp_seg); + print_vmcs_field(VMCS_EXCP_BITMAP); + print_vmcs_field(VMCS_PG_FAULT_ERR_MASK); + print_vmcs_field(VMCS_PG_FAULT_ERR_MATCH); + + print_vmcs_field(VMCS_IO_BITMAP_A_ADDR); +#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); +#endif + + print_vmcs_field(VMCS_TSC_OFFSET); +#ifdef __V3_32BIT__ + print_vmcs_field(VMCS_TSC_OFFSET_HIGH); +#endif + + PrintDebug("\n"); + + print_vmcs_field(VMCS_CR0_MASK); + print_vmcs_field(VMCS_CR0_READ_SHDW); + print_vmcs_field(VMCS_CR4_MASK); + print_vmcs_field(VMCS_CR4_READ_SHDW); + + print_vmcs_field(VMCS_CR3_TGT_CNT); + print_vmcs_field(VMCS_CR3_TGT_VAL_0); + print_vmcs_field(VMCS_CR3_TGT_VAL_1); + print_vmcs_field(VMCS_CR3_TGT_VAL_2); + print_vmcs_field(VMCS_CR3_TGT_VAL_3); + + PrintDebug("\n"); + + print_vmcs_field(VMCS_APIC_ACCESS_ADDR); +#ifdef __V3_32BIT__ + print_vmcs_field(VMCS_APIC_ACCESS_ADDR_HIGH); +#endif + + print_vmcs_field(VMCS_VAPIC_ADDR); +#ifdef __V3_32BIT__ + print_vmcs_field(VMCS_VAPIC_ADDR_HIGH); +#endif + + print_vmcs_field(VMCS_TPR_THRESHOLD); + + print_vmcs_field(VMCS_MSR_BITMAP); +#ifdef __V3_32BIT__ + print_vmcs_field(VMCS_MSR_BITMAP_HIGH); +#endif + + print_vmcs_field(VMCS_EXEC_PTR); +#ifdef __V3_32BIT__ + print_vmcs_field(VMCS_EXEC_PTR_HIGH); +#endif +} + + +static void print_exit_ctrls() { + PrintDebug("VMCS_EXIT_CTRLS\n"); - READ_VMCS_SEG(&tmp,DS,wordsize); - print_vmcs_segment("DS", &tmp_seg); + print_vmcs_field(VMCS_EXIT_CTRLS); - READ_VMCS_SEG(&tmp_seg,ES,wordsize); - print_vmcs_segment("ES", &tmp_seg); - READ_VMCS_SEG(&tmp_seg,FS,wordsize); - print_vmcs_segment("FS", &tmp_seg); + print_vmcs_field(VMCS_EXIT_MSR_STORE_CNT); + print_vmcs_field(VMCS_EXIT_MSR_STORE_ADDR); +#ifdef __V3_32BIT__ + print_vmcs_field(VMCS_EXIT_MSR_STORE_ADDR_HIGH); +#endif - READ_VMCS_SEG(&tmp_seg,GS,wordsize); - print_vmcs_segment("GS", &tmp_seg); + print_vmcs_field(VMCS_EXIT_MSR_LOAD_CNT); + print_vmcs_field(VMCS_EXIT_MSR_LOAD_ADDR); +#ifdef __V3_32BIT__ + print_vmcs_field(VMCS_EXIT_MSR_LOAD_ADDR_HIGH); +#endif + +} - READ_VMCS_SEG(&tmp_seg,TR,wordsize); - print_vmcs_segment("TR", &tmp_seg); - READ_VMCS_SEG(&tmp_seg,LDTR,wordsize); - print_vmcs_segment("LDTR", &tmp_seg); +static void print_entry_ctrls() { + PrintDebug("VMCS_ENTRY_CTRLS\n"); - PrintDebug("\n==GDTR==\n"); - PRINT_VMREAD("GDTR Base: %x\n", GUEST_GDTR_BASE, wordsize); - PRINT_VMREAD("GDTR Limit: %x\n", GUEST_GDTR_LIMIT, 32); - PrintDebug("====\n"); - - PrintDebug("\n==LDTR==\n"); - PRINT_VMREAD("LDTR Base: %x\n", GUEST_LDTR_BASE, wordsize); - PRINT_VMREAD("LDTR Limit: %x\n", GUEST_LDTR_LIMIT, 32); - PrintDebug("=====\n"); - - PRINT_VMREAD("Guest RSP: %x\n", GUEST_RSP, wordsize); - PRINT_VMREAD("Guest RIP: %x\n", GUEST_RIP, wordsize); - PRINT_VMREAD("Guest RFLAGS: %x\n", GUEST_RFLAGS, wordsize); - PRINT_VMREAD("Guest Activity state: %x\n", GUEST_ACTIVITY_STATE, 32); - PRINT_VMREAD("Guest Interruptibility state: %x\n", GUEST_INT_STATE, 32); - PRINT_VMREAD("Guest pending debug: %x\n", GUEST_PENDING_DEBUG_EXCS, wordsize); - - PRINT_VMREAD("IA32_DEBUGCTL: %x\n", GUEST_IA32_DEBUGCTL, 64); - PRINT_VMREAD("IA32_SYSENTER_CS: %x\n", GUEST_IA32_SYSENTER_CS, 32); - PRINT_VMREAD("IA32_SYSTENTER_ESP: %x\n", GUEST_IA32_SYSENTER_ESP, wordsize); - PRINT_VMREAD("IA32_SYSTENTER_EIP: %x\n", GUEST_IA32_SYSENTER_EIP, wordsize); - PRINT_VMREAD("IA32_PERF_GLOBAL_CTRL: %x\n", GUEST_IA32_PERF_GLOBAL_CTRL, wordsize); - PRINT_VMREAD("VMCS Link Ptr: %x\n", VMCS_LINK_PTR, 64); - // TODO: Maybe add VMX preemption timer and PDTE (Intel 20-8 Vol. 3b) + print_vmcs_field(VMCS_ENTRY_CTRLS); + + print_vmcs_field(VMCS_ENTRY_MSR_LOAD_CNT); + print_vmcs_field(VMCS_ENTRY_MSR_LOAD_ADDR); +#ifdef __V3_32BIT__ + print_vmcs_field(VMCS_ENTRY_MSR_LOAD_ADDR_HIGH); +#endif + + print_vmcs_field(VMCS_ENTRY_INT_INFO); + print_vmcs_field(VMCS_ENTRY_EXCP_ERR); + print_vmcs_field(VMCS_ENTRY_INSTR_LEN); + + } -void print_debug_load_host() { - const int wordsize = sizeof(addr_t); - uint64_t temp; - vmcs_segment tmp_seg; - - PrintDebug("\n====== Host State ========\n"); - PRINT_VMREAD("Host CR0: %x\n", HOST_CR0, wordsize); - PRINT_VMREAD("Host CR3: %x\n", HOST_CR3, wordsize); - PRINT_VMREAD("Host CR4: %x\n", HOST_CR4, wordsize); - PRINT_VMREAD("Host RSP: %x\n", HOST_RSP, wordsize); - PRINT_VMREAD("Host RIP: %x\n", HOST_RIP, wordsize); - PRINT_VMREAD("IA32_SYSENTER_CS: %x\n", HOST_IA32_SYSENTER_CS, 32); - PRINT_VMREAD("IA32_SYSENTER_ESP: %x\n", HOST_IA32_SYSENTER_ESP, wordsize); - PRINT_VMREAD("IA32_SYSENTER_EIP: %x\n", HOST_IA32_SYSENTER_EIP, wordsize); - - PRINT_VMREAD("Host CS Selector: %x\n", HOST_CS_SELECTOR, 16); - PRINT_VMREAD("Host SS Selector: %x\n", HOST_SS_SELECTOR, 16); - PRINT_VMREAD("Host DS Selector: %x\n", HOST_DS_SELECTOR, 16); - PRINT_VMREAD("Host ES Selector: %x\n", HOST_ES_SELECTOR, 16); - PRINT_VMREAD("Host FS Selector: %x\n", HOST_FS_SELECTOR, 16); - PRINT_VMREAD("Host GS Selector: %x\n", HOST_GS_SELECTOR, 16); - PRINT_VMREAD("Host TR Selector: %x\n", HOST_TR_SELECTOR, 16); - - PRINT_VMREAD("Host FS Base: %x\n", HOST_FS_BASE, wordsize); - PRINT_VMREAD("Host GS Base: %x\n", HOST_GS_BASE, wordsize); - PRINT_VMREAD("Host TR Base: %x\n", HOST_TR_BASE, wordsize); - PRINT_VMREAD("Host GDTR Base: %x\n", HOST_GDTR_BASE, wordsize); - PRINT_VMREAD("Host IDTR Base: %x\n", HOSE_IDTR_BASE, wordsize); + +static void print_exit_info() { + PrintDebug("VMCS_EXIT_INFO\n"); + + print_vmcs_field(VMCS_EXIT_REASON); + print_vmcs_field(VMCS_EXIT_QUAL); + + print_vmcs_field(VMCS_EXIT_INT_INFO); + print_vmcs_field(VMCS_EXIT_INT_ERR); + + print_vmcs_field(VMCS_IDT_VECTOR_INFO); + print_vmcs_field(VMCS_IDT_VECTOR_ERR); + + print_vmcs_field(VMCS_EXIT_INSTR_LEN); + + print_vmcs_field(VMCS_GUEST_LINEAR_ADDR); + print_vmcs_field(VMCS_EXIT_INSTR_INFO); + + print_vmcs_field(VMCS_IO_RCX); + print_vmcs_field(VMCS_IO_RSI); + print_vmcs_field(VMCS_IO_RDI); + print_vmcs_field(VMCS_IO_RIP); + + + print_vmcs_field(VMCS_INSTR_ERR); +} + +void v3_print_vmcs() { + + print_vmcs_field(VMCS_LINK_PTR); +#ifdef __V3_32BIT__ + print_vmcs_field(VMCS_LINK_PTR_HIGH); +#endif + + print_guest_state(); + print_host_state(); + + print_exec_ctrls(); + print_exit_ctrls(); + print_entry_ctrls(); + print_exit_info(); + + + + } -void print_vmcs_segment(char * name, vmcs_segment* seg) -{ - PrintDebug("\n==VMCS %s Segment==\n",name); - PrintDebug("\tSelector: %x\n", seg->selector); - PrintDebug("\tBase Address: %x\n", seg->baseAddr); - PrintDebug("\tLimit: %x\n", seg->limit); - PrintDebug("\tAccess: %x\n", seg->access); -}*/ /* * Returns the field length in bytes @@ -259,6 +744,7 @@ int v3_vmcs_get_field_len(vmcs_field_t field) { /* 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: @@ -279,7 +765,7 @@ int v3_vmcs_get_field_len(vmcs_field_t field) { case VMCS_IDT_VECTOR_INFO: case VMCS_IDT_VECTOR_ERR: case VMCS_EXIT_INSTR_LEN: - case VMCS_VMX_INSTR_INFO: + case VMCS_EXIT_INSTR_INFO: case VMCS_GUEST_ES_LIMIT: case VMCS_GUEST_CS_LIMIT: case VMCS_GUEST_SS_LIMIT: @@ -318,9 +804,11 @@ int v3_vmcs_get_field_len(vmcs_field_t field) { 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: return 4; /* Natural Width Control Fields */ @@ -333,9 +821,11 @@ int v3_vmcs_get_field_len(vmcs_field_t field) { 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: @@ -434,12 +924,16 @@ static const char VMCS_TSC_OFFSET_STR[] = "TSC_OFFSET"; static const char VMCS_TSC_OFFSET_HIGH_STR[] = "TSC_OFFSET_HIGH"; static const char VMCS_VAPIC_ADDR_STR[] = "VAPIC_PAGE_ADDR"; static const char VMCS_VAPIC_ADDR_HIGH_STR[] = "VAPIC_PAGE_ADDR_HIGH"; +static const char VMCS_APIC_ACCESS_ADDR_STR[] = "APIC_ACCESS_ADDR"; +static const char VMCS_APIC_ACCESS_ADDR_HIGH_STR[] = "APIC_ACCESS_ADDR_HIGH"; static const char VMCS_LINK_PTR_STR[] = "VMCS_LINK_PTR"; static const char VMCS_LINK_PTR_HIGH_STR[] = "VMCS_LINK_PTR_HIGH"; static const char VMCS_GUEST_DBG_CTL_STR[] = "GUEST_DEBUG_CTL"; static const char VMCS_GUEST_DBG_CTL_HIGH_STR[] = "GUEST_DEBUG_CTL_HIGH"; static const char VMCS_GUEST_PERF_GLOBAL_CTRL_STR[] = "GUEST_PERF_GLOBAL_CTRL"; static const char VMCS_GUEST_PERF_GLOBAL_CTRL_HIGH_STR[] = "GUEST_PERF_GLOBAL_CTRL_HIGH"; +static const char VMCS_HOST_PERF_GLOBAL_CTRL_STR[] = "HOST_PERF_GLOBAL_CTRL"; +static const char VMCS_HOST_PERF_GLOBAL_CTRL_HIGH_STR[] = "HOST_PERF_GLOBAL_CTRL_HIGH"; static const char VMCS_PIN_CTRLS_STR[] = "PIN_VM_EXEC_CTRLS"; static const char VMCS_PROC_CTRLS_STR[] = "PROC_VM_EXEC_CTRLS"; static const char VMCS_EXCP_BITMAP_STR[] = "EXCEPTION_BITMAP"; @@ -455,6 +949,7 @@ static const char VMCS_ENTRY_INT_INFO_STR[] = "VM_ENTRY_INT_INFO_FIELD"; static const char VMCS_ENTRY_EXCP_ERR_STR[] = "VM_ENTRY_EXCEPTION_ERROR"; static const char VMCS_ENTRY_INSTR_LEN_STR[] = "VM_ENTRY_INSTR_LENGTH"; static const char VMCS_TPR_THRESHOLD_STR[] = "TPR_THRESHOLD"; +static const char VMCS_SEC_PROC_CTRLS_STR[] = "VMCS_SEC_PROC_CTRLS"; static const char VMCS_INSTR_ERR_STR[] = "VM_INSTR_ERROR"; static const char VMCS_EXIT_REASON_STR[] = "EXIT_REASON"; static const char VMCS_EXIT_INT_INFO_STR[] = "VM_EXIT_INT_INFO"; @@ -462,7 +957,7 @@ static const char VMCS_EXIT_INT_ERR_STR[] = "VM_EXIT_INT_ERROR"; static const char VMCS_IDT_VECTOR_INFO_STR[] = "IDT_VECTOR_INFO"; static const char VMCS_IDT_VECTOR_ERR_STR[] = "IDT_VECTOR_ERROR"; static const char VMCS_EXIT_INSTR_LEN_STR[] = "VM_EXIT_INSTR_LENGTH"; -static const char VMCS_VMX_INSTR_INFO_STR[] = "VMX_INSTR_INFO"; +static const char VMCS_EXIT_INSTR_INFO_STR[] = "VMX_INSTR_INFO"; static const char VMCS_GUEST_ES_LIMIT_STR[] = "GUEST_ES_LIMIT"; static const char VMCS_GUEST_CS_LIMIT_STR[] = "GUEST_CS_LIMIT"; static const char VMCS_GUEST_SS_LIMIT_STR[] = "GUEST_SS_LIMIT"; @@ -603,6 +1098,10 @@ const char * v3_vmcs_field_to_str(vmcs_field_t field) { return VMCS_VAPIC_ADDR_STR; case VMCS_VAPIC_ADDR_HIGH: return VMCS_VAPIC_ADDR_HIGH_STR; + case VMCS_APIC_ACCESS_ADDR: + return VMCS_APIC_ACCESS_ADDR_STR; + case VMCS_APIC_ACCESS_ADDR_HIGH: + return VMCS_APIC_ACCESS_ADDR_HIGH_STR; case VMCS_LINK_PTR: return VMCS_LINK_PTR_STR; case VMCS_LINK_PTR_HIGH: @@ -615,6 +1114,10 @@ const char * v3_vmcs_field_to_str(vmcs_field_t field) { return VMCS_GUEST_PERF_GLOBAL_CTRL_STR; case VMCS_GUEST_PERF_GLOBAL_CTRL_HIGH: return VMCS_GUEST_PERF_GLOBAL_CTRL_HIGH_STR; + case VMCS_HOST_PERF_GLOBAL_CTRL: + return VMCS_HOST_PERF_GLOBAL_CTRL_STR; + case VMCS_HOST_PERF_GLOBAL_CTRL_HIGH: + return VMCS_HOST_PERF_GLOBAL_CTRL_HIGH_STR; case VMCS_PIN_CTRLS: return VMCS_PIN_CTRLS_STR; case VMCS_PROC_CTRLS: @@ -645,6 +1148,8 @@ const char * v3_vmcs_field_to_str(vmcs_field_t field) { return VMCS_ENTRY_INSTR_LEN_STR; case VMCS_TPR_THRESHOLD: return VMCS_TPR_THRESHOLD_STR; + case VMCS_SEC_PROC_CTRLS: + return VMCS_SEC_PROC_CTRLS_STR; case VMCS_INSTR_ERR: return VMCS_INSTR_ERR_STR; case VMCS_EXIT_REASON: @@ -659,8 +1164,8 @@ const char * v3_vmcs_field_to_str(vmcs_field_t field) { return VMCS_IDT_VECTOR_ERR_STR; case VMCS_EXIT_INSTR_LEN: return VMCS_EXIT_INSTR_LEN_STR; - case VMCS_VMX_INSTR_INFO: - return VMCS_VMX_INSTR_INFO_STR; + case VMCS_EXIT_INSTR_INFO: + return VMCS_EXIT_INSTR_INFO_STR; case VMCS_GUEST_ES_LIMIT: return VMCS_GUEST_ES_LIMIT_STR; case VMCS_GUEST_CS_LIMIT: