Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


s patch fixes some issues I've had when compiling Palacios 32-bit.
[palacios.git] / palacios / src / palacios / vmcs.c
index 5ab9a0c..a77de77 100644 (file)
 #include <palacios/vmcs.h>
 #include <palacios/vmx_lowlevel.h>
 #include <palacios/vmm.h>
+#include <palacios/vmx.h>
+#include <palacios/vm_guest_mem.h>
+#include <palacios/vmm_ctrl_regs.h>
+#include <palacios/vmm_lowlevel.h>
+
+
+
+
+
+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);
+
+    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));
+    if (((struct vmx_data *)info->vmm_data)->ia32e_avail) {
+        check_vmcs_read(VMCS_GUEST_EFER, &(info->ctrl_regs.efer));
+    }
+
+    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);
+
+    if (((struct vmx_data *)info->vmm_data)->ia32e_avail) {
+        check_vmcs_write(VMCS_GUEST_EFER, info->ctrl_regs.efer);
+    }
+
+    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 vmx_data * arch_data = (struct vmx_data *)(info->vmm_data);
+    struct v3_msr tmp_msr;
+
+#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);
+
+
+
+    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);    
+
+
+
+#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);
+
+    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;
+}
+
 
 
-static const char * 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) {
     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", 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", 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", 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);
     }
 }
 
 
-static inline void print_vmcs_segments() {
-    // see vm_guest.c
+static void print_vmcs_segments() {
+    struct v3_segments segs; 
+
+    v3_read_vmcs_segments(&segs);
+    v3_print_segments(&segs);
+
+
+    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("   ==> 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("   ==> 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("   ==> 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("   ==> 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("   ==> 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("   ==> 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("   ==> 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("   ==> GDTR\n");
+    print_vmcs_field(VMCS_GUEST_GDTR_BASE);
+    print_vmcs_field(VMCS_GUEST_GDTR_LIMIT);
+
+    PrintDebug("   ==> IDTR\n");
+    print_vmcs_field(VMCS_GUEST_IDTR_BASE);
+    print_vmcs_field(VMCS_GUEST_IDTR_LIMIT);
+
+
 }
 
 
 
 
-/*
-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_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);
+
+
+    PrintDebug("\n");
+
+    print_vmcs_segments();
+
+    PrintDebug("\n");
+
+    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);
+#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);
+
+}
+       
+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");
+
+    print_vmcs_field(VMCS_EXIT_CTRLS);
 
-    READ_VMCS_SEG(&tmp,DS,wordsize);
-    print_vmcs_segment("DS", &tmp_seg);
 
-    READ_VMCS_SEG(&tmp_seg,ES,wordsize);
-    print_vmcs_segment("ES", &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,FS,wordsize);
-    print_vmcs_segment("FS", &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,GS,wordsize);
-    print_vmcs_segment("GS", &tmp_seg);
+}
 
-    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);
+
+
+}
+
+
+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 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);
+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
@@ -183,6 +779,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:
@@ -203,7 +800,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:
@@ -242,9 +839,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 */
@@ -257,9 +856,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:
@@ -358,12 +959,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";
@@ -379,6 +984,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";
@@ -386,7 +992,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";
@@ -459,7 +1065,7 @@ static const char VMCS_HOST_RIP_STR[] = "HOST_RIP";
 
 
 
-static const char * vmcs_field_to_str(vmcs_field_t field) {   
+const char * v3_vmcs_field_to_str(vmcs_field_t field) {   
     switch (field) {
         case VMCS_GUEST_ES_SELECTOR:
             return VMCS_GUEST_ES_SELECTOR_STR;
@@ -527,6 +1133,10 @@ static const char * 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:
@@ -539,6 +1149,10 @@ static const char * 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:
@@ -569,6 +1183,8 @@ static const char * 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:
@@ -583,8 +1199,8 @@ static const char * 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: