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.


Merge branch 'devel' of palacios@newskysaw.cs.northwestern.edu:/home/palacios/palacio...
[palacios.git] / palacios / src / palacios / vmcs.c
index e7f9570..f8fe322 100644 (file)
 #include <palacios/vmm_ctrl_regs.h>
 #include <palacios/vmm_lowlevel.h>
 
-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)
-{
+
+static int inline check_vmcs_write(vmcs_field_t field, addr_t val) {
     int ret = 0;
     ret = vmcs_write(field, val);
 
@@ -65,8 +41,7 @@ static int inline check_vmcs_write(vmcs_field_t field, addr_t val)
     return 0;
 }
 
-static int inline check_vmcs_read(vmcs_field_t field, void * val)
-{
+static int inline check_vmcs_read(vmcs_field_t field, void * val) {
     int ret = 0;
     ret = vmcs_read(field, val);
 
@@ -77,123 +52,143 @@ static int inline check_vmcs_read(vmcs_field_t field, void * val)
     return 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
-//
 
-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;
+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;
 
-    memset(&access, 0, sizeof(access));
+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;
 
-    /* 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);
+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;
 
-    /* SS Segment */
-    memset(&access, 0, sizeof(access));
-    translate_v3_seg_to_access(&(info->segments.ss), &access);
+    memset(&vmcs_seg, 0, sizeof(struct vmcs_segment));
 
-    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);
+    check_vmcs_read(limit, &(vmcs_seg.limit));
+    check_vmcs_read(base, &(vmcs_seg.base));
 
-    /* DS Segment */
-    memset(&access, 0, sizeof(access));
-    translate_v3_seg_to_access(&(info->segments.ds), &access);
+    if ((seg_type != GDTR) && (seg_type != IDTR)) {
+       check_vmcs_read(selector, &(vmcs_seg.selector));
+       check_vmcs_read(access, &(vmcs_seg.access.val)); 
+    }
 
-    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);
+    v3_vmxseg_to_seg(&vmcs_seg, seg);
 
+    return 0;
+}
 
-    /* ES Segment */
-    memset(&access, 0, sizeof(access));
-    translate_v3_seg_to_access(&(info->segments.es), &access);
+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;
 
-    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);
+    v3_seg_to_vmxseg(seg, &vmcs_seg);
 
-    /* FS Segment */
-    memset(&access, 0, sizeof(access));
-    translate_v3_seg_to_access(&(info->segments.fs), &access);
+    check_vmcs_write(limit, vmcs_seg.limit);
+    check_vmcs_write(base, vmcs_seg.base);
 
-    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);
+    if ((seg_type != GDTR) && (seg_type != IDTR)) {
+       check_vmcs_write(access, vmcs_seg.access.val); 
+       check_vmcs_write(selector, vmcs_seg.selector);
+    }
 
-    /* GS Segment */
-    memset(&access, 0, sizeof(access));
-    translate_v3_seg_to_access(&(info->segments.gs), &access);
+    return 0;
+}
 
-    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);
+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);
 
-    /* LDTR segment */
-    memset(&access, 0, sizeof(access));
-    translate_v3_seg_to_access(&(info->segments.ldtr), &access);
+    return 0;
+}
 
-    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);
+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);
 
-    /* TR Segment */
-    memset(&access, 0, sizeof(access));
-    translate_v3_seg_to_access(&(info->segments.tr), &access);
+    return 0;
+}
 
-    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 */
+void v3_vmxseg_to_seg(struct vmcs_segment * vmcs_seg, struct v3_segment * seg) {
+    memset(seg, 0, sizeof(struct v3_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);
+    seg->selector = vmcs_seg->selector;
+    seg->limit = vmcs_seg->limit;
+    seg->base = vmcs_seg->base;
 
-    /* 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);
+    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;
 
-    return vmx_ret;
+}
 
+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);
@@ -211,30 +206,116 @@ int v3_update_vmcs_ctrl_fields(struct guest_info * info) {
     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) {
+#ifdef __V3_64BIT__
+        check_vmcs_read(VMCS_GUEST_EFER, &(info->ctrl_regs.efer));
+#else
+       uint32_t hi, lo;
+        check_vmcs_read(VMCS_GUEST_EFER, &hi);
+        check_vmcs_read(VMCS_GUEST_EFER_HIGH, &lo);
+        info->ctrl_regs.efer = ((uint64_t) hi << 32) | lo;
+#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);
+
+    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);
 
 
@@ -256,40 +337,82 @@ int v3_update_vmcs_host_state(struct guest_info * info) {
 
 
 
+#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);
@@ -315,104 +438,9 @@ int v3_update_vmcs_host_state(struct guest_info * info) {
 }
 
 
-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);
@@ -433,21 +461,13 @@ 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);
     print_vmcs_field(VMCS_GUEST_CS_BASE);
@@ -504,6 +524,28 @@ 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);
+
+
+    PrintDebug("\n");
+
+    print_vmcs_segments();
+
     PrintDebug("\n");
 
     print_vmcs_field(VMCS_GUEST_DBG_CTL);
@@ -582,6 +624,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);
@@ -720,162 +763,31 @@ void v3_print_vmcs() {
 
 /*
  * 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_EXIT_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 {
+#ifdef __V3_64BIT__
+               return 8;
+#else
+               return 4;
+#endif
+           }
+       }
+       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;
     }
 }