X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmcs.c;h=8fb408072e92c16d53e52a9f1c800a3fc1d875db;hb=88648ddca6003a438826e7d86e28a2ba7b5bfcac;hp=e5de8e3390e0c7d2c918804e3ff21b5833ce929b;hpb=a24a1722328a575cec8dd8578902fd0f68c72c1c;p=palacios.git diff --git a/palacios/src/palacios/vmcs.c b/palacios/src/palacios/vmcs.c index e5de8e3..8fb4080 100644 --- a/palacios/src/palacios/vmcs.c +++ b/palacios/src/palacios/vmcs.c @@ -20,14 +20,496 @@ #include #include #include +#include +#include +#include +#include + + + + + +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; +} + + + + + + + +typedef enum { ES = 0, + CS = 2, + SS = 4, + DS = 6, + FS = 8, + GS = 10, + LDTR = 12, + TR = 14, + GDTR = 16, + IDTR = 18} vmcs_seg_offsets_t; + +typedef enum {BASE = VMCS_GUEST_ES_BASE, + LIMIT = VMCS_GUEST_ES_LIMIT, + ACCESS = VMCS_GUEST_ES_ACCESS, + SELECTOR = VMCS_GUEST_ES_SELECTOR } vmcs_seg_bases_t; + + + +static int v3_read_vmcs_segment(struct v3_segment * seg, vmcs_seg_offsets_t seg_type) { + vmcs_field_t selector = VMCS_GUEST_ES_SELECTOR + seg_type; + vmcs_field_t base = VMCS_GUEST_ES_BASE + seg_type; + vmcs_field_t limit = VMCS_GUEST_ES_LIMIT + seg_type; + vmcs_field_t access = VMCS_GUEST_ES_ACCESS + seg_type; + struct vmcs_segment vmcs_seg; + + memset(&vmcs_seg, 0, sizeof(struct vmcs_segment)); + + check_vmcs_read(limit, &(vmcs_seg.limit)); + check_vmcs_read(base, &(vmcs_seg.base)); + + if ((seg_type != GDTR) && (seg_type != IDTR)) { + check_vmcs_read(selector, &(vmcs_seg.selector)); + check_vmcs_read(access, &(vmcs_seg.access.val)); + } + + v3_vmxseg_to_seg(&vmcs_seg, seg); + + return 0; +} + +static int v3_write_vmcs_segment(struct v3_segment * seg, vmcs_seg_offsets_t seg_type) { + vmcs_field_t selector = VMCS_GUEST_ES_SELECTOR + seg_type; + vmcs_field_t base = VMCS_GUEST_ES_BASE + seg_type; + vmcs_field_t limit = VMCS_GUEST_ES_LIMIT + seg_type; + vmcs_field_t access = VMCS_GUEST_ES_ACCESS + seg_type; + struct vmcs_segment vmcs_seg; + + v3_seg_to_vmxseg(seg, &vmcs_seg); + + check_vmcs_write(limit, vmcs_seg.limit); + check_vmcs_write(base, vmcs_seg.base); + + if ((seg_type != GDTR) && (seg_type != IDTR)) { + check_vmcs_write(access, vmcs_seg.access.val); + check_vmcs_write(selector, vmcs_seg.selector); + } + + return 0; +} + +int v3_read_vmcs_segments(struct v3_segments * segs) { + v3_read_vmcs_segment(&(segs->cs), CS); + v3_read_vmcs_segment(&(segs->ds), DS); + v3_read_vmcs_segment(&(segs->es), ES); + v3_read_vmcs_segment(&(segs->fs), FS); + v3_read_vmcs_segment(&(segs->gs), GS); + v3_read_vmcs_segment(&(segs->ss), SS); + v3_read_vmcs_segment(&(segs->ldtr), LDTR); + v3_read_vmcs_segment(&(segs->gdtr), GDTR); + v3_read_vmcs_segment(&(segs->idtr), IDTR); + v3_read_vmcs_segment(&(segs->tr), TR); + + return 0; +} + +int v3_write_vmcs_segments(struct v3_segments * segs) { + v3_write_vmcs_segment(&(segs->cs), CS); + v3_write_vmcs_segment(&(segs->ds), DS); + v3_write_vmcs_segment(&(segs->es), ES); + v3_write_vmcs_segment(&(segs->fs), FS); + v3_write_vmcs_segment(&(segs->gs), GS); + v3_write_vmcs_segment(&(segs->ss), SS); + v3_write_vmcs_segment(&(segs->ldtr), LDTR); + v3_write_vmcs_segment(&(segs->gdtr), GDTR); + v3_write_vmcs_segment(&(segs->idtr), IDTR); + v3_write_vmcs_segment(&(segs->tr), TR); + + return 0; +} + + +void v3_vmxseg_to_seg(struct vmcs_segment * vmcs_seg, struct v3_segment * seg) { + memset(seg, 0, sizeof(struct v3_segment)); + + seg->selector = vmcs_seg->selector; + seg->limit = vmcs_seg->limit; + seg->base = vmcs_seg->base; + + seg->type = vmcs_seg->access.type; + seg->system = vmcs_seg->access.desc_type; + seg->dpl = vmcs_seg->access.dpl; + seg->present = vmcs_seg->access.present; + seg->avail = vmcs_seg->access.avail; + seg->long_mode = vmcs_seg->access.long_mode; + seg->db = vmcs_seg->access.db; + seg->granularity = vmcs_seg->access.granularity; + seg->unusable = vmcs_seg->access.unusable; + +} + +void v3_seg_to_vmxseg(struct v3_segment * seg, struct vmcs_segment * vmcs_seg) { + memset(vmcs_seg, 0, sizeof(struct vmcs_segment)); + + vmcs_seg->selector = seg->selector; + vmcs_seg->limit = seg->limit; + vmcs_seg->base = seg->base; + + vmcs_seg->access.type = seg->type; + vmcs_seg->access.desc_type = seg->system; + vmcs_seg->access.dpl = seg->dpl; + vmcs_seg->access.present = seg->present; + vmcs_seg->access.avail = seg->avail; + vmcs_seg->access.long_mode = seg->long_mode; + vmcs_seg->access.db = seg->db; + vmcs_seg->access.granularity = seg->granularity; + vmcs_seg->access.unusable = seg->unusable; +} + + + + +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); + vmx_ret |= check_vmcs_write(VMCS_EXCP_BITMAP, arch_data->excp_bmap.value); + + if (info->shdw_pg_mode == NESTED_PAGING) { + vmx_ret |= check_vmcs_write(VMCS_EPT_PTR, info->direct_map_pt); + } + + return vmx_ret; +} + + + + + + +int v3_vmx_save_vmcs(struct guest_info * info) { + struct vmx_data * vmx_info = (struct vmx_data *)(info->vmm_data); + 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_CR4_READ_SHDW, &(vmx_info->guest_cr4)); + check_vmcs_read(VMCS_GUEST_DR7, &(info->dbg_regs.dr7)); + + check_vmcs_read(VMCS_GUEST_RFLAGS, &(info->ctrl_regs.rflags)); + +#ifdef __V3_64BIT__ + check_vmcs_read(VMCS_GUEST_EFER, &(info->ctrl_regs.efer)); +#endif + + error = v3_read_vmcs_segments(&(info->segments)); + + return error; +} + + +int v3_vmx_restore_vmcs(struct guest_info * info) { + struct vmx_data * vmx_info = (struct vmx_data *)(info->vmm_data); + int error = 0; + + check_vmcs_write(VMCS_GUEST_RIP, info->rip); + check_vmcs_write(VMCS_GUEST_RSP, info->vm_regs.rsp); + + check_vmcs_write(VMCS_GUEST_CR0, info->ctrl_regs.cr0); + check_vmcs_write(VMCS_CR0_READ_SHDW, info->shdw_pg_state.guest_cr0); + check_vmcs_write(VMCS_GUEST_CR3, info->ctrl_regs.cr3); + check_vmcs_write(VMCS_GUEST_CR4, info->ctrl_regs.cr4); + check_vmcs_write(VMCS_CR4_READ_SHDW, vmx_info->guest_cr4); + check_vmcs_write(VMCS_GUEST_DR7, info->dbg_regs.dr7); + + check_vmcs_write(VMCS_GUEST_RFLAGS, info->ctrl_regs.rflags); + +#ifdef __V3_64BIT__ + check_vmcs_write(VMCS_GUEST_EFER, info->ctrl_regs.efer); + check_vmcs_write(VMCS_ENTRY_CTRLS, vmx_info->entry_ctrls.value); +#endif + + + + + error = v3_write_vmcs_segments(&(info->segments)); + + return error; + +} + + + +int v3_update_vmcs_host_state(struct guest_info * info) { + int vmx_ret = 0; + addr_t tmp; + struct v3_msr tmp_msr; + addr_t gdtr_base; + struct { + uint16_t selector; + addr_t base; + } __attribute__((packed)) tmp_seg; + +#ifdef __V3_64BIT__ + __asm__ __volatile__ ( "movq %%cr0, %0; " + : "=q"(tmp) + : + ); +#else + __asm__ __volatile__ ( "movl %%cr0, %0; " + : "=q"(tmp) + : + ); +#endif + vmx_ret |= check_vmcs_write(VMCS_HOST_CR0, tmp); + + +#ifdef __V3_64BIT__ + __asm__ __volatile__ ( "movq %%cr3, %0; " + : "=q"(tmp) + : + ); +#else + __asm__ __volatile__ ( "movl %%cr3, %0; " + : "=q"(tmp) + : + ); +#endif + vmx_ret |= check_vmcs_write(VMCS_HOST_CR3, tmp); + + +#ifdef __V3_64BIT__ + __asm__ __volatile__ ( "movq %%cr4, %0; " + : "=q"(tmp) + : + ); +#else + __asm__ __volatile__ ( "movl %%cr4, %0; " + : "=q"(tmp) + : + ); +#endif + vmx_ret |= check_vmcs_write(VMCS_HOST_CR4, tmp); + + + __asm__ __volatile__( + "sgdt (%0);" + : + : "q"(&tmp_seg) + : "memory" + ); + gdtr_base = tmp_seg.base; + vmx_ret |= check_vmcs_write(VMCS_HOST_GDTR_BASE, tmp_seg.base); + + __asm__ __volatile__( + "sidt (%0);" + : + : "q"(&tmp_seg) + : "memory" + ); + vmx_ret |= check_vmcs_write(VMCS_HOST_IDTR_BASE, tmp_seg.base); + + __asm__ __volatile__( + "str (%0);" + : + : "q"(&tmp_seg) + : "memory" + ); + vmx_ret |= check_vmcs_write(VMCS_HOST_TR_SELECTOR, tmp_seg.selector); + + /* The GDTR *index* is bits 3-15 of the selector. */ + { + struct tss_descriptor * desc = NULL; + desc = (struct tss_descriptor *)(gdtr_base + (8 * (tmp_seg.selector >> 3))); + + tmp_seg.base = ((desc->base1) | + (desc->base2 << 16) | + (desc->base3 << 24) | +#ifdef __V3_64BIT__ + ((uint64_t)desc->base4 << 32) +#else + (0) +#endif + ); + + vmx_ret |= check_vmcs_write(VMCS_HOST_TR_BASE, tmp_seg.base); + } + + +#ifdef __V3_64BIT__ + __asm__ __volatile__ ( "movq %%cs, %0; " + : "=q"(tmp) + : + ); +#else + __asm__ __volatile__ ( "movl %%cs, %0; " + : "=q"(tmp) + : + ); +#endif + vmx_ret |= check_vmcs_write(VMCS_HOST_CS_SELECTOR, tmp); + +#ifdef __V3_64BIT__ + __asm__ __volatile__ ( "movq %%ss, %0; " + : "=q"(tmp) + : + ); +#else + __asm__ __volatile__ ( "movl %%ss, %0; " + : "=q"(tmp) + : + ); +#endif + vmx_ret |= check_vmcs_write(VMCS_HOST_SS_SELECTOR, tmp); + +#ifdef __V3_64BIT__ + __asm__ __volatile__ ( "movq %%ds, %0; " + : "=q"(tmp) + : + ); +#else + __asm__ __volatile__ ( "movl %%ds, %0; " + : "=q"(tmp) + : + ); +#endif + vmx_ret |= check_vmcs_write(VMCS_HOST_DS_SELECTOR, tmp); + +#ifdef __V3_64BIT__ + __asm__ __volatile__ ( "movq %%es, %0; " + : "=q"(tmp) + : + ); +#else + __asm__ __volatile__ ( "movl %%es, %0; " + : "=q"(tmp) + : + ); +#endif + vmx_ret |= check_vmcs_write(VMCS_HOST_ES_SELECTOR, tmp); + +#ifdef __V3_64BIT__ + __asm__ __volatile__ ( "movq %%fs, %0; " + : "=q"(tmp) + : + ); +#else + __asm__ __volatile__ ( "movl %%fs, %0; " + : "=q"(tmp) + : + ); +#endif + vmx_ret |= check_vmcs_write(VMCS_HOST_FS_SELECTOR, tmp); + +#ifdef __V3_64BIT__ + __asm__ __volatile__ ( "movq %%gs, %0; " + : "=q"(tmp) + : + ); +#else + __asm__ __volatile__ ( "movl %%gs, %0; " + : "=q"(tmp) + : + ); +#endif + vmx_ret |= check_vmcs_write(VMCS_HOST_GS_SELECTOR, tmp); + + +#define SYSENTER_CS_MSR 0x00000174 +#define SYSENTER_ESP_MSR 0x00000175 +#define SYSENTER_EIP_MSR 0x00000176 +#define FS_BASE_MSR 0xc0000100 +#define GS_BASE_MSR 0xc0000101 +#define EFER_MSR 0xc0000080 + + + // 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); + + + // 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); + + + // EFER + v3_get_msr(EFER_MSR, &(tmp_msr.hi), &(tmp_msr.lo)); + vmx_ret |= check_vmcs_write(VMCS_HOST_EFER, tmp_msr.value); + + // PERF GLOBAL CONTROL + + // PAT + + + // save STAR, LSTAR, FMASK, KERNEL_GS_BASE MSRs in MSR load/store area + { + struct vmx_data * vmx_state = (struct vmx_data *)info->vmm_data; + struct vmcs_msr_save_area * msr_entries = vmx_state->msr_area; + + + v3_get_msr(IA32_STAR_MSR, &(msr_entries->host_star.hi), &(msr_entries->host_star.lo)); + v3_get_msr(IA32_LSTAR_MSR, &(msr_entries->host_lstar.hi), &(msr_entries->host_lstar.lo)); + v3_get_msr(IA32_FMASK_MSR, &(msr_entries->host_fmask.hi), &(msr_entries->host_fmask.lo)); + v3_get_msr(IA32_KERN_GS_BASE_MSR, &(msr_entries->host_kern_gs.hi), &(msr_entries->host_kern_gs.lo)); + } + + + + + + return vmx_ret; +} + -// static const char * v3_vmcs_field_to_str(vmcs_field_t field); -//extern char * exception_names; -// -// Ignores "HIGH" addresses - 32 bit only for now -// static inline void print_vmcs_field(vmcs_field_t vmcs_index) { @@ -49,20 +531,12 @@ static inline void print_vmcs_field(vmcs_field_t vmcs_index) { } +static void print_vmcs_segments() { + struct v3_segments segs; -static void print_guest_state() -{ - 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); - + v3_read_vmcs_segments(&segs); + v3_print_segments(&segs); - PrintDebug("\n"); PrintDebug(" ==> CS\n"); print_vmcs_field(VMCS_GUEST_CS_SELECTOR); @@ -120,6 +594,34 @@ static void print_guest_state() print_vmcs_field(VMCS_GUEST_IDTR_BASE); print_vmcs_field(VMCS_GUEST_IDTR_LIMIT); + +} + + + + +static void print_guest_state() +{ + 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); + + // if save IA32_EFER + print_vmcs_field(VMCS_GUEST_EFER); +#ifdef __V3_32BIT__ + print_vmcs_field(VMCS_GUEST_EFER_HIGH); +#endif + + + PrintDebug("\n"); + + print_vmcs_segments(); + PrintDebug("\n"); print_vmcs_field(VMCS_GUEST_DBG_CTL); @@ -130,6 +632,14 @@ static void print_guest_state() print_vmcs_field(VMCS_GUEST_SYSENTER_ESP); print_vmcs_field(VMCS_GUEST_SYSENTER_EIP); + + // if save IA32_PAT + print_vmcs_field(VMCS_GUEST_PAT); +#ifdef __V3_32BIT__ + print_vmcs_field(VMCS_GUEST_PAT_HIGH); +#endif + + //if load IA32_PERF_GLOBAL_CTRL print_vmcs_field(VMCS_GUEST_PERF_GLOBAL_CTRL); #ifdef __V3_32BIT__ print_vmcs_field(VMCS_GUEST_PERF_GLOBAL_CTRL_HIGH); @@ -138,12 +648,17 @@ static void print_guest_state() 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); + // if VMX preempt timer + print_vmcs_field(VMCS_PREEMPT_TIMER); + } static void print_host_state() @@ -156,6 +671,15 @@ static void print_host_state() print_vmcs_field(VMCS_HOST_CR3); print_vmcs_field(VMCS_HOST_CR4); + + + // if load IA32_EFER + print_vmcs_field(VMCS_HOST_EFER); +#ifdef __V3_32BIT__ + print_vmcs_field(VMCS_HOST_EFER_HIGH); +#endif + + PrintDebug("\n"); print_vmcs_field(VMCS_HOST_CS_SELECTOR); print_vmcs_field(VMCS_HOST_SS_SELECTOR); @@ -177,6 +701,14 @@ static void print_host_state() print_vmcs_field(VMCS_HOST_SYSENTER_ESP); print_vmcs_field(VMCS_HOST_SYSENTER_EIP); + + // if load IA32_PAT + print_vmcs_field(VMCS_HOST_PAT); +#ifdef __V3_32BIT__ + print_vmcs_field(VMCS_HOST_PAT_HIGH); +#endif + + // if load IA32_PERF_GLOBAL_CTRL print_vmcs_field(VMCS_HOST_PERF_GLOBAL_CTRL); #ifdef __V3_32BIT__ print_vmcs_field(VMCS_HOST_PERF_GLOBAL_CTRL_HIGH); @@ -188,6 +720,8 @@ static void print_exec_ctrls() { PrintDebug("VMCS_EXEC_CTRL_FIELDS\n"); print_vmcs_field(VMCS_PIN_CTRLS); print_vmcs_field(VMCS_PROC_CTRLS); + + // if activate secondary controls print_vmcs_field(VMCS_SEC_PROC_CTRLS); print_vmcs_field(VMCS_EXCP_BITMAP); @@ -198,6 +732,7 @@ static void print_exec_ctrls() { #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); @@ -221,20 +756,28 @@ static void print_exec_ctrls() { print_vmcs_field(VMCS_CR3_TGT_VAL_2); print_vmcs_field(VMCS_CR3_TGT_VAL_3); + // Check max number of CR3 targets... may continue... + + PrintDebug("\n"); + // if virtualize apic accesses print_vmcs_field(VMCS_APIC_ACCESS_ADDR); #ifdef __V3_32BIT__ print_vmcs_field(VMCS_APIC_ACCESS_ADDR_HIGH); #endif + // if use tpr shadow print_vmcs_field(VMCS_VAPIC_ADDR); #ifdef __V3_32BIT__ print_vmcs_field(VMCS_VAPIC_ADDR_HIGH); #endif + // if use tpr shadow print_vmcs_field(VMCS_TPR_THRESHOLD); + + // if use MSR bitmaps print_vmcs_field(VMCS_MSR_BITMAP); #ifdef __V3_32BIT__ print_vmcs_field(VMCS_MSR_BITMAP_HIGH); @@ -244,6 +787,50 @@ static void print_exec_ctrls() { #ifdef __V3_32BIT__ print_vmcs_field(VMCS_EXEC_PTR_HIGH); #endif + + +} + +static void print_ept_state() { + V3_Print("VMCS EPT INFO\n"); + + // if enable vpid + print_vmcs_field(VMCS_VPID); + + print_vmcs_field(VMCS_EPT_PTR); +#ifdef __V3_32BIT__ + print_vmcs_field(VMCS_EPT_PTR_HIGH); +#endif + + print_vmcs_field(VMCS_GUEST_PHYS_ADDR); +#ifdef __V3_32BIT__ + print_vmcs_field(VMCS_GUEST_PHYS_ADDR_HIGH); +#endif + + + + print_vmcs_field(VMCS_GUEST_PDPTE0); +#ifdef __V3_32BIT__ + print_vmcs_field(VMCS_GUEST_PDPTE0_HIGH); +#endif + + print_vmcs_field(VMCS_GUEST_PDPTE1); +#ifdef __V3_32BIT__ + print_vmcs_field(VMCS_GUEST_PDPTE1_HIGH); +#endif + + print_vmcs_field(VMCS_GUEST_PDPTE2); +#ifdef __V3_32BIT__ + print_vmcs_field(VMCS_GUEST_PDPTE2_HIGH); +#endif + + print_vmcs_field(VMCS_GUEST_PDPTE3); +#ifdef __V3_32BIT__ + print_vmcs_field(VMCS_GUEST_PDPTE3_HIGH); +#endif + + + } @@ -265,6 +852,11 @@ static void print_exit_ctrls() { print_vmcs_field(VMCS_EXIT_MSR_LOAD_ADDR_HIGH); #endif + + // if pause loop exiting + print_vmcs_field(VMCS_PLE_GAP); + print_vmcs_field(VMCS_PLE_WINDOW); + } @@ -302,7 +894,7 @@ static void print_exit_info() { print_vmcs_field(VMCS_EXIT_INSTR_LEN); print_vmcs_field(VMCS_GUEST_LINEAR_ADDR); - print_vmcs_field(VMCS_VMX_INSTR_INFO); + print_vmcs_field(VMCS_EXIT_INSTR_INFO); print_vmcs_field(VMCS_IO_RCX); print_vmcs_field(VMCS_IO_RSI); @@ -323,175 +915,39 @@ void v3_print_vmcs() { print_guest_state(); print_host_state(); + print_ept_state(); + print_exec_ctrls(); print_exit_ctrls(); print_entry_ctrls(); print_exit_info(); - - - } /* * 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_VMX_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: + switch (enc->width) { + case 0: + return 2; + case 1: { + if (enc->access_type == 1) { + return 4; + } else { + return sizeof(addr_t); + } + } + 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 3: return sizeof(addr_t); - default: - PrintError("Invalid VMCS field\n"); + PrintError("Invalid VMCS field: 0x%x\n", field); return -1; } } @@ -506,7 +962,7 @@ int v3_vmcs_get_field_len(vmcs_field_t field) { - +static const char VMCS_VPID_STR[] = "VPID"; static const char VMCS_GUEST_ES_SELECTOR_STR[] = "GUEST_ES_SELECTOR"; static const char VMCS_GUEST_CS_SELECTOR_STR[] = "GUEST_CS_SELECTOR"; static const char VMCS_GUEST_SS_SELECTOR_STR[] = "GUEST_SS_SELECTOR"; @@ -542,12 +998,32 @@ 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_EPT_PTR_STR[] = "VMCS_EPT_PTR"; +static const char VMCS_EPT_PTR_HIGH_STR[] = "VMCS_EPT_PTR_HIGH"; +static const char VMCS_GUEST_PHYS_ADDR_STR[] = "VMCS_GUEST_PHYS_ADDR"; +static const char VMCS_GUEST_PHYS_ADDR_HIGH_STR[] = "VMCS_GUEST_PHYS_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_PAT_STR[] = "GUEST_PAT"; +static const char VMCS_GUEST_PAT_HIGH_STR[] = "GUEST_PAT_HIGH"; +static const char VMCS_GUEST_EFER_STR[] = "GUEST_EFER"; +static const char VMCS_GUEST_EFER_HIGH_STR[] = "GUEST_EFER_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_GUEST_PDPTE0_STR[] = "GUEST_PDPTE0"; +static const char VMCS_GUEST_PDPTE0_HIGH_STR[] = "GUEST_PDPTE0_HIGH"; +static const char VMCS_GUEST_PDPTE1_STR[] = "GUEST_PDPTE1"; +static const char VMCS_GUEST_PDPTE1_HIGH_STR[] = "GUEST_PDPTE1_HIGH"; +static const char VMCS_GUEST_PDPTE2_STR[] = "GUEST_PDPTE2"; +static const char VMCS_GUEST_PDPTE2_HIGH_STR[] = "GUEST_PDPTE2_HIGH"; +static const char VMCS_GUEST_PDPTE3_STR[] = "GUEST_PDPTE3"; +static const char VMCS_GUEST_PDPTE3_HIGH_STR[] = "GUEST_PDPTE3_HIGH"; +static const char VMCS_HOST_PAT_STR[] = "HOST_PAT"; +static const char VMCS_HOST_PAT_HIGH_STR[] = "HOST_PAT_HIGH"; +static const char VMCS_HOST_EFER_STR[] = "VMCS_HOST_EFER"; +static const char VMCS_HOST_EFER_HIGH_STR[] = "VMCS_HOST_EFER_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"; @@ -566,6 +1042,8 @@ 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_PLE_GAP_STR[] = "PLE_GAP"; +static const char VMCS_PLE_WINDOW_STR[] = "PLE_WINDOW"; 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"; @@ -573,7 +1051,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"; @@ -596,6 +1074,7 @@ static const char VMCS_GUEST_INT_STATE_STR[] = "GUEST_INT_STATE"; static const char VMCS_GUEST_ACTIVITY_STATE_STR[] = "GUEST_ACTIVITY_STATE"; static const char VMCS_GUEST_SMBASE_STR[] = "GUEST_SMBASE"; static const char VMCS_GUEST_SYSENTER_CS_STR[] = "GUEST_SYSENTER_CS"; +static const char VMCS_PREEMPT_TIMER_STR[] = "PREEMPT_TIMER"; static const char VMCS_HOST_SYSENTER_CS_STR[] = "HOST_SYSENTER_CS"; static const char VMCS_CR0_MASK_STR[] = "CR0_GUEST_HOST_MASK"; static const char VMCS_CR4_MASK_STR[] = "CR4_GUEST_HOST_MASK"; @@ -648,6 +1127,8 @@ static const char VMCS_HOST_RIP_STR[] = "HOST_RIP"; const char * v3_vmcs_field_to_str(vmcs_field_t field) { switch (field) { + case VMCS_VPID: + return VMCS_VPID_STR; case VMCS_GUEST_ES_SELECTOR: return VMCS_GUEST_ES_SELECTOR_STR; case VMCS_GUEST_CS_SELECTOR: @@ -718,6 +1199,14 @@ const char * v3_vmcs_field_to_str(vmcs_field_t field) { return VMCS_APIC_ACCESS_ADDR_STR; case VMCS_APIC_ACCESS_ADDR_HIGH: return VMCS_APIC_ACCESS_ADDR_HIGH_STR; + case VMCS_EPT_PTR: + return VMCS_EPT_PTR_STR; + case VMCS_EPT_PTR_HIGH: + return VMCS_EPT_PTR_HIGH_STR; + case VMCS_GUEST_PHYS_ADDR: + return VMCS_GUEST_PHYS_ADDR_STR; + case VMCS_GUEST_PHYS_ADDR_HIGH: + return VMCS_GUEST_PHYS_ADDR_HIGH_STR; case VMCS_LINK_PTR: return VMCS_LINK_PTR_STR; case VMCS_LINK_PTR_HIGH: @@ -726,10 +1215,42 @@ const char * v3_vmcs_field_to_str(vmcs_field_t field) { return VMCS_GUEST_DBG_CTL_STR; case VMCS_GUEST_DBG_CTL_HIGH: return VMCS_GUEST_DBG_CTL_HIGH_STR; - case VMCS_GUEST_PERF_GLOBAL_CTRL: + case VMCS_GUEST_PAT: + return VMCS_GUEST_PAT_STR; + case VMCS_GUEST_PAT_HIGH: + return VMCS_GUEST_PAT_HIGH_STR; + case VMCS_GUEST_EFER: + return VMCS_GUEST_EFER_STR; + case VMCS_GUEST_EFER_HIGH: + return VMCS_GUEST_EFER_HIGH_STR; + case VMCS_GUEST_PERF_GLOBAL_CTRL: return VMCS_GUEST_PERF_GLOBAL_CTRL_STR; case VMCS_GUEST_PERF_GLOBAL_CTRL_HIGH: return VMCS_GUEST_PERF_GLOBAL_CTRL_HIGH_STR; + case VMCS_GUEST_PDPTE0: + return VMCS_GUEST_PDPTE0_STR; + case VMCS_GUEST_PDPTE0_HIGH: + return VMCS_GUEST_PDPTE0_HIGH_STR; + case VMCS_GUEST_PDPTE1: + return VMCS_GUEST_PDPTE1_STR; + case VMCS_GUEST_PDPTE1_HIGH: + return VMCS_GUEST_PDPTE1_HIGH_STR; + case VMCS_GUEST_PDPTE2: + return VMCS_GUEST_PDPTE2_STR; + case VMCS_GUEST_PDPTE2_HIGH: + return VMCS_GUEST_PDPTE2_HIGH_STR; + case VMCS_GUEST_PDPTE3: + return VMCS_GUEST_PDPTE3_STR; + case VMCS_GUEST_PDPTE3_HIGH: + return VMCS_GUEST_PDPTE3_HIGH_STR; + case VMCS_HOST_PAT: + return VMCS_HOST_PAT_STR; + case VMCS_HOST_PAT_HIGH: + return VMCS_HOST_PAT_HIGH_STR; + case VMCS_HOST_EFER: + return VMCS_HOST_EFER_STR; + case VMCS_HOST_EFER_HIGH: + return VMCS_HOST_EFER_HIGH_STR; case VMCS_HOST_PERF_GLOBAL_CTRL: return VMCS_HOST_PERF_GLOBAL_CTRL_STR; case VMCS_HOST_PERF_GLOBAL_CTRL_HIGH: @@ -766,6 +1287,10 @@ const char * v3_vmcs_field_to_str(vmcs_field_t field) { return VMCS_TPR_THRESHOLD_STR; case VMCS_SEC_PROC_CTRLS: return VMCS_SEC_PROC_CTRLS_STR; + case VMCS_PLE_GAP: + return VMCS_PLE_GAP_STR; + case VMCS_PLE_WINDOW: + return VMCS_PLE_WINDOW_STR; case VMCS_INSTR_ERR: return VMCS_INSTR_ERR_STR; case VMCS_EXIT_REASON: @@ -780,8 +1305,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: @@ -826,7 +1351,9 @@ const char * v3_vmcs_field_to_str(vmcs_field_t field) { return VMCS_GUEST_SMBASE_STR; case VMCS_GUEST_SYSENTER_CS: return VMCS_GUEST_SYSENTER_CS_STR; - case VMCS_HOST_SYSENTER_CS: + case VMCS_PREEMPT_TIMER: + return VMCS_PREEMPT_TIMER_STR; + case VMCS_HOST_SYSENTER_CS: return VMCS_HOST_SYSENTER_CS_STR; case VMCS_CR0_MASK: return VMCS_CR0_MASK_STR;