# Makefile for GeekOS kernel, userspace, and tools
 # Copyright (c) 2004,2005 David H. Hovemeyer <daveho@cs.umd.edu>
-# $Revision: 1.31 $
+# $Revision: 1.32 $
 
 # This is free software.  You are permitted to use,
 # redistribute, and modify it as specified in the file "COPYING".
 
 
 VMM_C_SRCS :=   vm_guest.c \
-               svm.c svm_handler.c vmm.c vmm_util.c svm_ctrl_regs.c \
+               svm.c svm_handler.c vmm.c vmm_util.c vmm_ctrl_regs.c \
                vmcb.c vmm_mem.c vmm_paging.c vmm_io.c vmm_debug.c svm_io.c \
                vmm_intr.c vmm_irq.c\
                vmm_shadow_paging.c vm_guest_mem.c  \
 
   /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
   ../include/geekos/paging.h ../include/geekos/bootinfo.h \
   ../include/geekos/malloc.h ../include/palacios/vmm.h \
-  ../include/palacios/vmm_string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/palacios/vmm_mem.h ../include/palacios/vmm_types.h \
-  ../include/palacios/vm_guest.h ../include/palacios/vmm_io.h \
+  ../include/palacios/vm_guest.h ../include/palacios/vmm_mem.h \
+  ../include/palacios/vmm_types.h ../include/palacios/vmm_io.h \
   ../include/palacios/vmm_util.h ../include/palacios/vmm_shadow_paging.h \
   ../include/palacios/vmm_paging.h ../include/palacios/vmm_intr.h \
   ../include/palacios/vmm_dev_mgr.h ../include/palacios/vmm_list.h \
+  ../include/palacios/vmm_string.h \
+  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
   ../include/palacios/vmm_irq.h ../include/geekos/debug.h \
   ../include/geekos/serial.h ../include/geekos/irq.h \
   ../include/geekos/int.h ../include/geekos/string.h \
   ../include/palacios/vmm_util.h ../include/palacios/vmm_types.h \
   ../include/geekos/ktypes.h \
   /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/palacios/vmm.h ../include/palacios/vmm_string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/palacios/vmm_mem.h ../include/palacios/vm_guest.h \
-  ../include/palacios/vmm_io.h ../include/palacios/vmm_shadow_paging.h \
+  ../include/palacios/vmm.h ../include/palacios/vm_guest.h \
+  ../include/palacios/vmm_mem.h ../include/palacios/vmm_io.h \
+  ../include/palacios/vmm_shadow_paging.h \
   ../include/palacios/vmm_paging.h ../include/palacios/vmm_intr.h \
   ../include/palacios/vmm_dev_mgr.h ../include/palacios/vmm_list.h \
+  ../include/palacios/vmm_string.h \
+  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
   ../include/palacios/vmm_irq.h ../include/palacios/vmcb.h \
   ../include/palacios/svm_handler.h ../include/palacios/vmm_debug.h \
-  ../include/palacios/vm_guest_mem.h
-palacios/svm_handler.o: ../src/palacios/svm_handler.c \
-  ../include/palacios/svm_handler.h ../include/palacios/svm.h \
-  ../include/palacios/vmm_util.h ../include/palacios/vmm_types.h \
-  ../include/geekos/ktypes.h \
+  ../include/palacios/vm_guest_mem.h ../include/palacios/vmm_emulate.h
+palacios/vmm.o: ../src/palacios/vmm.c ../include/palacios/vmm.h \
+  ../include/palacios/vm_guest.h ../include/palacios/vmm_mem.h \
+  ../include/palacios/vmm_types.h ../include/geekos/ktypes.h \
   /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/palacios/vmm.h ../include/palacios/vmm_string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/palacios/vmm_mem.h ../include/palacios/vm_guest.h \
-  ../include/palacios/vmm_io.h ../include/palacios/vmm_shadow_paging.h \
+  ../include/palacios/vmm_io.h ../include/palacios/vmm_util.h \
+  ../include/palacios/vmm_shadow_paging.h \
   ../include/palacios/vmm_paging.h ../include/palacios/vmm_intr.h \
   ../include/palacios/vmm_dev_mgr.h ../include/palacios/vmm_list.h \
-  ../include/palacios/vmm_irq.h ../include/palacios/vmcb.h \
-  ../include/palacios/vm_guest_mem.h ../include/palacios/vmm_emulate.h \
-  ../include/palacios/svm_ctrl_regs.h ../include/palacios/svm_io.h
-palacios/vmm.o: ../src/palacios/vmm.c ../include/palacios/vmm.h \
   ../include/palacios/vmm_string.h \
   /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/palacios/vmm_mem.h ../include/palacios/vmm_types.h \
-  ../include/geekos/ktypes.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/palacios/vm_guest.h ../include/palacios/vmm_io.h \
-  ../include/palacios/vmm_util.h ../include/palacios/vmm_shadow_paging.h \
-  ../include/palacios/vmm_paging.h ../include/palacios/vmm_intr.h \
-  ../include/palacios/vmm_dev_mgr.h ../include/palacios/vmm_list.h \
   ../include/palacios/vmm_irq.h ../include/palacios/svm.h \
   ../include/palacios/vmcb.h ../include/palacios/vmx.h \
   ../include/palacios/vmcs.h ../include/palacios/vmcs_gen.h
 palacios/vmm_util.o: ../src/palacios/vmm_util.c ../include/palacios/vmm_util.h \
   ../include/palacios/vmm_types.h ../include/geekos/ktypes.h \
   /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/palacios/vmm.h ../include/palacios/vmm_string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/palacios/vmm_mem.h ../include/palacios/vm_guest.h \
-  ../include/palacios/vmm_io.h ../include/palacios/vmm_shadow_paging.h \
+  ../include/palacios/vmm.h ../include/palacios/vm_guest.h \
+  ../include/palacios/vmm_mem.h ../include/palacios/vmm_io.h \
+  ../include/palacios/vmm_shadow_paging.h \
   ../include/palacios/vmm_paging.h ../include/palacios/vmm_intr.h \
   ../include/palacios/vmm_dev_mgr.h ../include/palacios/vmm_list.h \
+  ../include/palacios/vmm_string.h \
+  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
   ../include/palacios/vmm_irq.h
-palacios/svm_ctrl_regs.o: ../src/palacios/svm_ctrl_regs.c \
-  ../include/palacios/svm_ctrl_regs.h ../include/palacios/vm_guest.h \
+palacios/vmm_ctrl_regs.o: ../src/palacios/vmm_ctrl_regs.c \
   ../include/palacios/vmm_mem.h ../include/palacios/vmm_types.h \
   ../include/geekos/ktypes.h \
   /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
+  ../include/palacios/vmm.h ../include/palacios/vm_guest.h \
   ../include/palacios/vmm_io.h ../include/palacios/vmm_util.h \
   ../include/palacios/vmm_shadow_paging.h \
   ../include/palacios/vmm_paging.h ../include/palacios/vmm_intr.h \
   ../include/palacios/vmm_dev_mgr.h ../include/palacios/vmm_list.h \
   ../include/palacios/vmm_string.h \
   /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/palacios/vmm_irq.h ../include/palacios/vmm.h \
-  ../include/palacios/vmcb.h ../include/palacios/vmm_emulate.h \
-  ../include/palacios/vm_guest_mem.h ../include/palacios/vmm_ctrl_regs.h
+  ../include/palacios/vmm_irq.h ../include/palacios/vmcb.h \
+  ../include/palacios/vmm_emulate.h ../include/palacios/vm_guest_mem.h \
+  ../include/palacios/vmm_ctrl_regs.h
 palacios/vmcb.o: ../src/palacios/vmcb.c ../include/palacios/vmcb.h \
   ../include/palacios/vmm_types.h ../include/geekos/ktypes.h \
   /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/palacios/vmm.h ../include/palacios/vmm_string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/palacios/vmm_mem.h ../include/palacios/vm_guest.h \
+  ../include/palacios/vm_guest.h ../include/palacios/vmm_mem.h \
   ../include/palacios/vmm_io.h ../include/palacios/vmm_util.h \
   ../include/palacios/vmm_shadow_paging.h \
   ../include/palacios/vmm_paging.h ../include/palacios/vmm_intr.h \
   ../include/palacios/vmm_dev_mgr.h ../include/palacios/vmm_list.h \
-  ../include/palacios/vmm_irq.h
+  ../include/palacios/vmm_string.h \
+  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
+  ../include/palacios/vmm_irq.h ../include/palacios/vmm.h
 palacios/vmm_mem.o: ../src/palacios/vmm_mem.c ../include/palacios/vmm_mem.h \
   ../include/palacios/vmm_types.h ../include/geekos/ktypes.h \
   /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/palacios/vmm.h ../include/palacios/vmm_string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/palacios/vm_guest.h ../include/palacios/vmm_io.h \
-  ../include/palacios/vmm_util.h ../include/palacios/vmm_shadow_paging.h \
+  ../include/palacios/vmm.h ../include/palacios/vm_guest.h \
+  ../include/palacios/vmm_io.h ../include/palacios/vmm_util.h \
+  ../include/palacios/vmm_shadow_paging.h \
   ../include/palacios/vmm_paging.h ../include/palacios/vmm_intr.h \
   ../include/palacios/vmm_dev_mgr.h ../include/palacios/vmm_list.h \
+  ../include/palacios/vmm_string.h \
+  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
   ../include/palacios/vmm_irq.h
 palacios/vmm_paging.o: ../src/palacios/vmm_paging.c \
   ../include/palacios/vmm_paging.h ../include/palacios/vmm_types.h \
   ../include/geekos/ktypes.h \
   /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
   ../include/palacios/vmm_mem.h ../include/palacios/vmm_util.h \
-  ../include/palacios/vmm.h ../include/palacios/vmm_string.h \
+  ../include/palacios/vmm.h ../include/palacios/vm_guest.h \
+  ../include/palacios/vmm_io.h ../include/palacios/vmm_shadow_paging.h \
+  ../include/palacios/vmm_intr.h ../include/palacios/vmm_dev_mgr.h \
+  ../include/palacios/vmm_list.h ../include/palacios/vmm_string.h \
   /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/palacios/vm_guest.h ../include/palacios/vmm_io.h \
-  ../include/palacios/vmm_shadow_paging.h ../include/palacios/vmm_intr.h \
-  ../include/palacios/vmm_dev_mgr.h ../include/palacios/vmm_list.h \
   ../include/palacios/vmm_irq.h ../include/palacios/vm_guest_mem.h
 palacios/vmm_io.o: ../src/palacios/vmm_io.c ../include/palacios/vmm_io.h \
   ../include/palacios/vmm_types.h ../include/geekos/ktypes.h \
   /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
   ../include/palacios/vmm_util.h ../include/palacios/vmm_string.h \
   /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/palacios/vmm.h ../include/palacios/vmm_mem.h \
-  ../include/palacios/vm_guest.h ../include/palacios/vmm_shadow_paging.h \
+  ../include/palacios/vmm.h ../include/palacios/vm_guest.h \
+  ../include/palacios/vmm_mem.h ../include/palacios/vmm_shadow_paging.h \
   ../include/palacios/vmm_paging.h ../include/palacios/vmm_intr.h \
   ../include/palacios/vmm_dev_mgr.h ../include/palacios/vmm_list.h \
   ../include/palacios/vmm_irq.h
 palacios/vmm_debug.o: ../src/palacios/vmm_debug.c ../include/palacios/vmm_debug.h \
-  ../include/palacios/vmm.h ../include/palacios/vmm_string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
+  ../include/palacios/vmm.h ../include/palacios/vm_guest.h \
   ../include/palacios/vmm_mem.h ../include/palacios/vmm_types.h \
   ../include/geekos/ktypes.h \
   /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/palacios/vm_guest.h ../include/palacios/vmm_io.h \
-  ../include/palacios/vmm_util.h ../include/palacios/vmm_shadow_paging.h \
+  ../include/palacios/vmm_io.h ../include/palacios/vmm_util.h \
+  ../include/palacios/vmm_shadow_paging.h \
   ../include/palacios/vmm_paging.h ../include/palacios/vmm_intr.h \
   ../include/palacios/vmm_dev_mgr.h ../include/palacios/vmm_list.h \
+  ../include/palacios/vmm_string.h \
+  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
   ../include/palacios/vmm_irq.h
 palacios/svm_io.o: ../src/palacios/svm_io.c ../include/palacios/svm_io.h \
   ../include/palacios/vm_guest.h ../include/palacios/vmm_mem.h \
 palacios/vmm_intr.o: ../src/palacios/vmm_intr.c ../include/palacios/vmm_intr.h \
   ../include/palacios/vmm_types.h ../include/geekos/ktypes.h \
   /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/palacios/vmm.h ../include/palacios/vmm_string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/palacios/vmm_mem.h ../include/palacios/vm_guest.h \
-  ../include/palacios/vmm_io.h ../include/palacios/vmm_util.h \
-  ../include/palacios/vmm_shadow_paging.h \
+  ../include/palacios/vmm.h ../include/palacios/vm_guest.h \
+  ../include/palacios/vmm_mem.h ../include/palacios/vmm_io.h \
+  ../include/palacios/vmm_util.h ../include/palacios/vmm_shadow_paging.h \
   ../include/palacios/vmm_paging.h ../include/palacios/vmm_dev_mgr.h \
-  ../include/palacios/vmm_list.h ../include/palacios/vmm_irq.h
+  ../include/palacios/vmm_list.h ../include/palacios/vmm_string.h \
+  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
+  ../include/palacios/vmm_irq.h
 palacios/vmm_irq.o: ../src/palacios/vmm_irq.c
 palacios/vmm_shadow_paging.o: ../src/palacios/vmm_shadow_paging.c \
   ../include/palacios/vmm_shadow_paging.h ../include/palacios/vmm_util.h \
   ../include/palacios/vmm_types.h ../include/geekos/ktypes.h \
   /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
   ../include/palacios/vmm_paging.h ../include/palacios/vmm_mem.h \
-  ../include/palacios/vmm.h ../include/palacios/vmm_string.h \
+  ../include/palacios/vmm.h ../include/palacios/vm_guest.h \
+  ../include/palacios/vmm_io.h ../include/palacios/vmm_intr.h \
+  ../include/palacios/vmm_dev_mgr.h ../include/palacios/vmm_list.h \
+  ../include/palacios/vmm_string.h \
   /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/palacios/vm_guest.h ../include/palacios/vmm_io.h \
-  ../include/palacios/vmm_intr.h ../include/palacios/vmm_dev_mgr.h \
-  ../include/palacios/vmm_list.h ../include/palacios/vmm_irq.h \
-  ../include/palacios/vm_guest_mem.h
+  ../include/palacios/vmm_irq.h ../include/palacios/vm_guest_mem.h
 palacios/vm_guest_mem.o: ../src/palacios/vm_guest_mem.c \
   ../include/palacios/vm_guest_mem.h ../include/palacios/vm_guest.h \
   ../include/palacios/vmm_mem.h ../include/palacios/vmm_types.h \
   ../include/palacios/vmm_list.h ../include/palacios/vmm_string.h \
   /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
   ../include/palacios/vmm_dev_mgr.h ../include/palacios/vmm.h \
-  ../include/palacios/vmm_mem.h ../include/palacios/vm_guest.h \
+  ../include/palacios/vm_guest.h ../include/palacios/vmm_mem.h \
   ../include/palacios/vmm_io.h ../include/palacios/vmm_util.h \
   ../include/palacios/vmm_shadow_paging.h \
   ../include/palacios/vmm_paging.h ../include/palacios/vmm_intr.h \
   ../include/palacios/vmm_list.h ../include/palacios/vmm_string.h \
   /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
   ../include/palacios/vmm_dev_mgr.h ../include/palacios/vmm.h \
-  ../include/palacios/vmm_mem.h ../include/palacios/vm_guest.h \
+  ../include/palacios/vm_guest.h ../include/palacios/vmm_mem.h \
   ../include/palacios/vmm_io.h ../include/palacios/vmm_util.h \
   ../include/palacios/vmm_shadow_paging.h \
   ../include/palacios/vmm_paging.h ../include/palacios/vmm_intr.h \
   ../include/palacios/vmm_list.h ../include/palacios/vmm_string.h \
   /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
   ../include/palacios/vmm_dev_mgr.h ../include/palacios/vmm.h \
-  ../include/palacios/vmm_mem.h ../include/palacios/vm_guest.h \
+  ../include/palacios/vm_guest.h ../include/palacios/vmm_mem.h \
   ../include/palacios/vmm_io.h ../include/palacios/vmm_util.h \
   ../include/palacios/vmm_shadow_paging.h \
   ../include/palacios/vmm_paging.h ../include/palacios/vmm_intr.h \
   ../include/palacios/vmm_list.h ../include/palacios/vmm_string.h \
   /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
   ../include/palacios/vmm_dev_mgr.h ../include/palacios/vmm_intr.h \
-  ../include/palacios/vmm.h ../include/palacios/vmm_mem.h \
-  ../include/palacios/vm_guest.h ../include/palacios/vmm_io.h \
+  ../include/palacios/vmm.h ../include/palacios/vm_guest.h \
+  ../include/palacios/vmm_mem.h ../include/palacios/vmm_io.h \
   ../include/palacios/vmm_util.h ../include/palacios/vmm_shadow_paging.h \
   ../include/palacios/vmm_paging.h ../include/palacios/vmm_irq.h
 devices/8259a.o: ../src/devices/8259a.c ../include/devices/8259a.h \
   ../include/palacios/vmm_list.h ../include/palacios/vmm_string.h \
   /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
   ../include/palacios/vmm_dev_mgr.h ../include/palacios/vmm_intr.h \
-  ../include/palacios/vmm.h ../include/palacios/vmm_mem.h \
-  ../include/palacios/vm_guest.h ../include/palacios/vmm_io.h \
+  ../include/palacios/vmm.h ../include/palacios/vm_guest.h \
+  ../include/palacios/vmm_mem.h ../include/palacios/vmm_io.h \
   ../include/palacios/vmm_util.h ../include/palacios/vmm_shadow_paging.h \
   ../include/palacios/vmm_paging.h ../include/palacios/vmm_irq.h
 
 #include <palacios/vmm_irq.h>
 
 
-typedef ullong_t gpr_t;
-
-/*
-  struct guest_gprs {
-  addr_t rax;
-  addr_t rbx;
-  addr_t rcx;
-  addr_t rdx;
-  addr_t rsi;
-  addr_t rdi;
-  addr_t rbp;
-  };
-*/
-
-struct guest_gprs {
-  gpr_t rdi;
-  gpr_t rsi;
-  gpr_t rbp;
-  gpr_t rsp;
-  gpr_t rbx;
-  gpr_t rdx;
-  gpr_t rcx;
-  gpr_t rax;
+typedef ullong_t v3_reg_t;
+
+
+
+struct v3_gprs {
+  v3_reg_t rdi;
+  v3_reg_t rsi;
+  v3_reg_t rbp;
+  v3_reg_t rsp;
+  v3_reg_t rbx;
+  v3_reg_t rdx;
+  v3_reg_t rcx;
+  v3_reg_t rax;
+};
+
+
+struct v3_ctrl_regs {
+  v3_reg_t cr0;
+  v3_reg_t cr2;
+  v3_reg_t cr3;
+  v3_reg_t cr4;
+  v3_reg_t cr8;
+  v3_reg_t rflags;
 };
 
 
+struct v3_segment {
+  ushort_t selector;
+  uint_t limit;
+  ullong_t base;
+  uint_t type           : 4;
+  uint_t system         : 1;
+  uint_t dpl            : 2;
+  uint_t present        : 1;
+  uint_t avail          : 1;
+  uint_t long_mode      : 1;
+  uint_t db             : 1;
+  uint_t granularity    : 1;
+};
+
+
+struct v3_segments {
+  struct v3_segment cs;
+  struct v3_segment ds;
+  struct v3_segment es;
+  struct v3_segment fs;
+  struct v3_segment gs;
+  struct v3_segment ss;
+  struct v3_segment ldtr;
+  struct v3_segment gdtr;
+  struct v3_segment idtr;
+  struct v3_segment tr;
+};
+
 struct shadow_page_state;
 struct shadow_map;
 
   vm_cpu_mode_t cpu_mode;
 
 
-  struct guest_gprs vm_regs;
+  struct v3_gprs vm_regs;
+  struct v3_ctrl_regs ctrl_regs;
+  struct v3_segments segments;
 
   struct vm_ctrl_ops vm_ops;
 
 
 #define __VMCB_H
 
 #include <palacios/vmm_types.h>
-
+#include <palacios/vm_guest.h>
 
 #define VMCB_CTRL_AREA_OFFSET                   0x0
 #define VMCB_STATE_SAVE_AREA_OFFSET             0x400
 void PrintDebugVMCB(vmcb_t * vmcb);
 
 
+void set_vmcb_segments(vmcb_t * vmcb, struct v3_segments * segs);
+void get_vmcb_segments(vmcb_t * vmcb, struct v3_segments * segs);
+
 #endif
 
 #define __VMM_CTRL_REGS_H
 
 
+#include <palacios/vm_guest.h>
+
 struct cr0_real {
   uint_t pe    : 1;
   uint_t mp    : 1;
 };
 
 
+
+
+
+// First opcode byte
+static const uchar_t cr_access_byte = 0x0f;
+
+// Second opcode byte
+static const uchar_t lmsw_byte = 0x01;
+static const uchar_t lmsw_reg_byte = 0x6;
+static const uchar_t smsw_byte = 0x01;
+static const uchar_t smsw_reg_byte = 0x4;
+static const uchar_t clts_byte = 0x06;
+static const uchar_t mov_to_cr_byte = 0x22;
+static const uchar_t mov_from_cr_byte = 0x20;
+
+
+
+int handle_cr0_write(struct guest_info * info);
+int handle_cr0_read(struct guest_info * info);
+
+int handle_cr3_write(struct guest_info * info);
+int handle_cr3_read(struct guest_info * info);
+
+
 #endif
 
 
 
 
-static inline addr_t get_addr_linear(struct guest_info * info, addr_t addr, addr_t seg_base) {
+static inline addr_t get_addr_linear(struct guest_info * info, addr_t addr, struct v3_segment * seg) {
   switch (info->cpu_mode) {
   case REAL:
-    return addr + (seg_base << 4);
+    return addr + (seg->selector << 4);
     break;
   case PROTECTED:
   case PROTECTED_PG:
-    return addr + seg_base;
+    return addr + seg->base;
     break;
   default:
     return 0;
 typedef enum {INVALID_REG_SIZE, REG64, REG32, REG16, REG8} reg_size_t;
 typedef enum {INVALID_OPERAND, REG_OPERAND, MEM_OPERAND} operand_type_t;
 
-struct guest_gprs;
+struct v3_gprs;
 
-static inline addr_t decode_register(struct guest_gprs * gprs, char reg_code, reg_size_t reg_size) {
+static inline addr_t decode_register(struct v3_gprs * gprs, char reg_code, reg_size_t reg_size) {
   addr_t reg_addr;
 
   switch (reg_code) {
 
 
 
-static inline operand_type_t decode_operands16(struct guest_gprs * gprs, // input/output
+static inline operand_type_t decode_operands16(struct v3_gprs * gprs, // input/output
                                               char * modrm_instr,       // input
                                               int * offset,             // output
                                               addr_t * first_operand,   // output
 
 
 
-static inline operand_type_t decode_operands32(struct guest_gprs * gprs, // input/output
+static inline operand_type_t decode_operands32(struct v3_gprs * gprs, // input/output
                                               char * modrm_instr,       // input
                                               int * offset,             // output
                                               addr_t * first_operand,   // output
 
 extern void Get_MSR(uint_t MSR, uint_t * high_byte, uint_t * low_byte); 
 extern void Set_MSR(uint_t MSR, uint_t high_byte, uint_t low_byte);
 extern uint_t launch_svm(vmcb_t * vmcb_addr);
-extern void safe_svm_launch(vmcb_t * vmcb_addr, struct guest_gprs * gprs);
+extern void safe_svm_launch(vmcb_t * vmcb_addr, struct v3_gprs * gprs);
 
 extern void STGI();
 extern void CLGI();
 
       PrintDebug("RIP: %x\n", guest_state->rip);
 
-      if (info->cpu_mode == REAL) {
-       linear_addr = get_addr_linear(info, guest_state->rip, guest_state->cs.selector);
-      } else {
-       linear_addr = get_addr_linear(info, guest_state->rip, guest_state->cs.base);
-      }
+
+      linear_addr = get_addr_linear(info, guest_state->rip, &(info->segments.cs));
+
 
       PrintDebug("RIP Linear: %x\n", linear_addr);
 
 
 #include <palacios/vmm.h>
 #include <palacios/vm_guest_mem.h>
 #include <palacios/vmm_emulate.h>
-#include <palacios/svm_ctrl_regs.h>
+#include <palacios/vmm_ctrl_regs.h>
 #include <palacios/svm_io.h>
 #include <palacios/vmm_intr.h>
 
+
 extern struct vmm_os_hooks * os_hooks;
 
 
   info->vm_regs.rsp = guest_state->rsp;  
 
 
+  info->ctrl_regs.cr0 = guest_state->cr0;
+  info->ctrl_regs.cr2 = guest_state->cr2;
+  info->ctrl_regs.cr3 = guest_state->cr3;
+  info->ctrl_regs.cr4 = guest_state->cr4;
+  info->ctrl_regs.cr8 = guest_ctrl->guest_ctrl.V_TPR;
+  info->ctrl_regs.rflags = guest_state->rflags;
+
+  get_vmcb_segments((vmcb_t*)(info->vmm_data), &(info->segments));
+
+
   exit_code = guest_ctrl->exit_code;
  
   PrintDebug("SVM Returned: Exit Code: %x\n",exit_code); 
     char buf[15];
     addr_t host_addr;
 
-    if (info->cpu_mode == REAL) {
-      rip_addr = get_addr_linear(info, guest_state->rip, guest_state->cs.selector);
-    } else {
-      rip_addr = get_addr_linear(info, guest_state->rip, guest_state->cs.base);
-    }
+
+    rip_addr = get_addr_linear(info, guest_state->rip, &(info->segments.cs));
+
 
 
     PrintDebug("SVM Returned:(VMCB=%x)\n", info->vmm_data); 
   }
 
 
+  guest_state->cr0 = info->ctrl_regs.cr0;
+  guest_state->cr2 = info->ctrl_regs.cr2;
+  guest_state->cr3 = info->ctrl_regs.cr3;
+  guest_state->cr4 = info->ctrl_regs.cr4;
+  guest_ctrl->guest_ctrl.V_TPR = info->ctrl_regs.cr8 & 0xff;
+  guest_state->rflags = info->ctrl_regs.rflags;
+
 
   guest_state->rax = info->vm_regs.rax;
   guest_state->rip = info->rip;
   guest_state->rsp = info->vm_regs.rsp;
 
+
+  set_vmcb_segments((vmcb_t*)(info->vmm_data), &(info->segments));
+
   if (exit_code == VMEXIT_INTR) {
     PrintDebug("INTR ret IP = %x\n", guest_state->rip);
   }
 
   
   vmm_io_hook_t * hook = get_io_hook(&(info->io_map), io_info->port);
   uint_t read_size = 0;
-  addr_t base_addr = guest_state->es.base ;
+
   addr_t dst_addr = 0;
   uint_t rep_num = 1;
   ullong_t mask = 0;
 
   while (rep_num > 0) {
     addr_t host_addr;
-    dst_addr = get_addr_linear(info, info->vm_regs.rdi & mask, base_addr);
+    dst_addr = get_addr_linear(info, info->vm_regs.rdi & mask, &(info->segments.es));
     
     if (guest_va_to_host_va(info, dst_addr, &host_addr) == -1) {
       // either page fault or gpf...
   
   vmm_io_hook_t * hook = get_io_hook(&(info->io_map), io_info->port);
   uint_t write_size = 0;
-  addr_t base_addr = guest_state->ds.base;
+
   addr_t dst_addr = 0;
   uint_t rep_num = 1;
   ullong_t mask = 0;
 
   while (rep_num > 0) {
     addr_t host_addr;
-    dst_addr = get_addr_linear(info, (info->vm_regs.rsi & mask), base_addr);
+    dst_addr = get_addr_linear(info, (info->vm_regs.rsi & mask), &(info->segments.ds));
     
     if (guest_va_to_host_va(info, dst_addr, &host_addr) == -1) {
       // either page fault or gpf...
 
 #include <palacios/vmm_util.h>
 
 
+
+void set_vmcb_segment(struct vmcb_selector * vmcb_seg, struct v3_segment * seg) {
+  vmcb_seg->selector = seg->selector;
+  vmcb_seg->limit = seg->limit;
+  vmcb_seg->base = seg->base;
+  vmcb_seg->attrib.fields.type = seg->type;
+  vmcb_seg->attrib.fields.S = seg->system;
+  vmcb_seg->attrib.fields.dpl = seg->dpl;
+  vmcb_seg->attrib.fields.P = seg->present;
+  vmcb_seg->attrib.fields.avl = seg->avail;
+  vmcb_seg->attrib.fields.L = seg->long_mode;
+  vmcb_seg->attrib.fields.db = seg->db;
+  vmcb_seg->attrib.fields.G = seg->granularity;
+}
+
+
+void get_vmcb_segment(struct vmcb_selector * vmcb_seg, struct v3_segment * seg) {
+  seg->selector = vmcb_seg->selector;
+  seg->limit = vmcb_seg->limit;
+  seg->base = vmcb_seg->base;
+  seg->type = vmcb_seg->attrib.fields.type;
+  seg->system = vmcb_seg->attrib.fields.S;
+  seg->dpl = vmcb_seg->attrib.fields.dpl;
+  seg->present = vmcb_seg->attrib.fields.P;
+  seg->avail = vmcb_seg->attrib.fields.avl;
+  seg->long_mode = vmcb_seg->attrib.fields.L;
+  seg->db = vmcb_seg->attrib.fields.db;
+  seg->granularity = vmcb_seg->attrib.fields.G;
+}
+
+
+void set_vmcb_segments(vmcb_t * vmcb, struct v3_segments * segs) {
+  vmcb_saved_state_t * guest_area = GET_VMCB_SAVE_STATE_AREA(vmcb);
+
+  set_vmcb_segment(&(guest_area->cs), &(segs->cs));
+  set_vmcb_segment(&(guest_area->ds), &(segs->ds));
+  set_vmcb_segment(&(guest_area->es), &(segs->es));
+  set_vmcb_segment(&(guest_area->fs), &(segs->fs));
+  set_vmcb_segment(&(guest_area->gs), &(segs->gs));
+  set_vmcb_segment(&(guest_area->ss), &(segs->ss));
+  set_vmcb_segment(&(guest_area->ldtr), &(segs->ldtr));
+  set_vmcb_segment(&(guest_area->gdtr), &(segs->gdtr));
+  set_vmcb_segment(&(guest_area->idtr), &(segs->idtr));
+  set_vmcb_segment(&(guest_area->tr), &(segs->tr));
+}
+
+
+void get_vmcb_segments(vmcb_t * vmcb, struct v3_segments * segs) {
+  vmcb_saved_state_t * guest_area = GET_VMCB_SAVE_STATE_AREA(vmcb);
+
+  get_vmcb_segment(&(guest_area->cs), &(segs->cs));
+  get_vmcb_segment(&(guest_area->ds), &(segs->ds));
+  get_vmcb_segment(&(guest_area->es), &(segs->es));
+  get_vmcb_segment(&(guest_area->fs), &(segs->fs));
+  get_vmcb_segment(&(guest_area->gs), &(segs->gs));
+  get_vmcb_segment(&(guest_area->ss), &(segs->ss));
+  get_vmcb_segment(&(guest_area->ldtr), &(segs->ldtr));
+  get_vmcb_segment(&(guest_area->gdtr), &(segs->gdtr));
+  get_vmcb_segment(&(guest_area->idtr), &(segs->idtr));
+  get_vmcb_segment(&(guest_area->tr), &(segs->tr));
+}
+
+
 void PrintDebugVMCB(vmcb_t * vmcb) {
   reg_ex_t tmp_reg;
 
 
--- /dev/null
+#include <palacios/vmm_mem.h>
+#include <palacios/vmm.h>
+#include <palacios/vmcb.h>
+#include <palacios/vmm_emulate.h>
+#include <palacios/vm_guest_mem.h>
+#include <palacios/vmm_ctrl_regs.h>
+
+
+/* Segmentation is a problem here...
+ *
+ * When we get a memory operand, presumably we use the default segment (which is?) 
+ * unless an alternate segment was specfied in the prefix...
+ */
+
+
+int handle_cr0_write(struct guest_info * info) {
+  char instr[15];
+  
+  
+  if (info->cpu_mode == REAL) {
+    int index = 0;
+    int ret;
+
+    // The real rip address is actually a combination of the rip + CS base 
+    ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
+    if (ret != 15) {
+      // I think we should inject a GPF into the guest
+      PrintDebug("Could not read instruction (ret=%d)\n", ret);
+      return -1;
+    }
+
+    while (is_prefix_byte(instr[index])) {
+      index++; 
+    }
+
+    if ((instr[index] == cr_access_byte) && 
+       (instr[index + 1] == lmsw_byte) && 
+       (MODRM_REG(instr[index + 2]) == lmsw_reg_byte)) {
+ 
+      addr_t first_operand;
+      addr_t second_operand;
+      struct cr0_real *real_cr0;
+      struct cr0_real *new_cr0;
+      operand_type_t addr_type;
+      char new_cr0_val = 0;
+      // LMSW
+      // decode mod/RM
+      index += 2;
+ 
+      real_cr0 = (struct cr0_real*)&(info->ctrl_regs.cr0);
+
+      addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
+
+
+      if (addr_type == REG_OPERAND) {
+       new_cr0 = (struct cr0_real *)first_operand;
+      } else if (addr_type == MEM_OPERAND) {
+       addr_t host_addr;
+
+       if (guest_pa_to_host_va(info, first_operand + (info->segments.ds.base << 4), &host_addr) == -1) {
+         // gpf the guest
+         return -1;
+       }
+
+       new_cr0 = (struct cr0_real *)host_addr;
+      } else {
+       // error... don't know what to do
+       return -1;
+      }
+                
+      if ((new_cr0->pe == 1) && (real_cr0->pe == 0)) {
+       info->cpu_mode = PROTECTED;
+      } else if ((new_cr0->pe == 0) && (real_cr0->pe == 1)) {
+       info->cpu_mode = REAL;
+      }
+      
+      new_cr0_val = *(char*)(new_cr0) & 0x0f;
+
+
+      if (info->page_mode == SHADOW_PAGING) {
+       struct cr0_real * shadow_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0);
+
+       PrintDebug("Old CR0=%x, Old Shadow CR0=%x\n", *real_cr0, *shadow_cr0);  
+       /* struct cr0_real is only 4 bits wide, 
+        * so we can overwrite the real_cr0 without worrying about the shadow fields
+        */
+       *(char*)real_cr0 &= 0xf0;
+       *(char*)real_cr0 |= new_cr0_val;
+       
+       *(char*)shadow_cr0 &= 0xf0;
+       *(char*)shadow_cr0 |= new_cr0_val;
+
+       PrintDebug("New CR0=%x, New Shadow CR0=%x\n", *real_cr0, *shadow_cr0);  
+      } else {
+       PrintDebug("Old CR0=%x\n", *real_cr0);  
+       // for now we just pass through....
+       *(char*)real_cr0 &= 0xf0;
+       *(char*)real_cr0 |= new_cr0_val;
+
+       PrintDebug("New CR0=%x\n", *real_cr0);  
+      }
+
+
+      info->rip += index;
+
+    } else if ((instr[index] == cr_access_byte) && 
+              (instr[index + 1] == clts_byte)) {
+      // CLTS
+
+
+    } else if ((instr[index] == cr_access_byte) && 
+              (instr[index + 1] = mov_to_cr_byte)) {
+      addr_t first_operand;
+      addr_t second_operand;
+      struct cr0_32 *real_cr0;
+      struct cr0_32 *new_cr0;
+      operand_type_t addr_type;
+     
+      
+      index += 2;
+ 
+      real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
+
+      addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
+
+      if (addr_type != REG_OPERAND) {
+       /* Mov to CR0 Can only be a 32 bit register */
+       // FIX ME
+       return -1;
+      }
+
+      new_cr0 = (struct cr0_32 *)first_operand;
+
+      if (new_cr0->pe == 1) {
+       PrintDebug("Entering Protected Mode\n");
+       info->cpu_mode = PROTECTED;
+      }
+
+      if (new_cr0->pg == 1) {
+       // GPF the guest??
+       return -1;
+      }
+
+      if (info->page_mode == SHADOW_PAGING) {
+       struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
+       
+       PrintDebug("Old CR0=%x, Old Shadow CR0=%x\n", *real_cr0, *shadow_cr0);  
+       *real_cr0 = *new_cr0;
+       real_cr0->pg = 1;
+
+       *shadow_cr0 = *new_cr0;
+
+       PrintDebug("New CR0=%x, New Shadow CR0=%x\n", *real_cr0, *shadow_cr0);  
+      } else {
+       PrintDebug("Old CR0=%x\n", *real_cr0);  
+       *real_cr0 = *new_cr0;
+       PrintDebug("New CR0=%x\n", *real_cr0);  
+      }
+
+      info->rip += index;
+
+    } else {
+      PrintDebug("Unsupported Instruction\n");
+      // unsupported instruction, UD the guest
+      return -1;
+    }
+
+
+  } else if (info->cpu_mode == PROTECTED) {
+    int index = 0;
+    int ret;
+
+    PrintDebug("Protected Mode write to CR0\n");
+
+    // The real rip address is actually a combination of the rip + CS base 
+    ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
+    if (ret != 15) {
+      // I think we should inject a GPF into the guest
+      PrintDebug("Could not read instruction (ret=%d)\n", ret);
+      return -1;
+    }
+
+    while (is_prefix_byte(instr[index])) {
+      index++; 
+    }
+
+    if ((instr[index] == cr_access_byte) && 
+       (instr[index + 1] == mov_to_cr_byte)) {
+    
+      addr_t first_operand;
+      addr_t second_operand;
+      struct cr0_32 *real_cr0;
+      struct cr0_32 *new_cr0;
+      operand_type_t addr_type;
+
+      index += 2;
+ 
+      real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
+
+      addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
+
+      if (addr_type != REG_OPERAND) {
+       return -1;
+      }
+
+      new_cr0 = (struct cr0_32 *)first_operand;
+
+
+      if (info->page_mode == SHADOW_PAGING) {
+       struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
+
+       if (new_cr0->pg == 1){
+         struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
+
+         info->cpu_mode = PROTECTED_PG;
+         
+         *shadow_cr0 = *new_cr0;
+         *real_cr0 = *new_cr0;
+
+         //
+         // Activate Shadow Paging
+         //
+         PrintDebug("Turning on paging in the guest\n");
+
+         info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
+         
+
+       } else if (new_cr0->pe == 0) {
+         info->cpu_mode = REAL;
+
+         *shadow_cr0 = *new_cr0;
+         *real_cr0 = *new_cr0;
+         real_cr0->pg = 1;
+       }
+
+
+      } else {
+       *real_cr0 = *new_cr0;
+      }
+
+      info->rip += index;
+    }
+    
+  } else { 
+    PrintDebug("Unknown Mode write to CR0\n");
+    return -1;
+  }
+  return 0;
+}
+
+
+int handle_cr0_read(struct guest_info * info) {
+  char instr[15];
+
+  if (info->cpu_mode == REAL) {
+    int index = 0;
+    int ret;
+
+    // The real rip address is actually a combination of the rip + CS base 
+    ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
+    if (ret != 15) {
+      // I think we should inject a GPF into the guest
+      PrintDebug("Could not read Real Mode instruction (ret=%d)\n", ret);
+      return -1;
+    }
+
+
+    while (is_prefix_byte(instr[index])) {
+      index++; 
+    }
+
+    if ((instr[index] == cr_access_byte) && 
+       (instr[index + 1] == smsw_byte) && 
+       (MODRM_REG(instr[index + 2]) == smsw_reg_byte)) {
+
+      addr_t first_operand;
+      addr_t second_operand;
+      struct cr0_real *cr0;
+      operand_type_t addr_type;
+      char cr0_val = 0;
+
+      index += 2;
+      
+      cr0 = (struct cr0_real*)&(info->ctrl_regs.cr0);
+      
+      
+      addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16);
+      
+      if (addr_type == MEM_OPERAND) {
+       addr_t host_addr;
+       
+       if (guest_pa_to_host_va(info, first_operand + (info->segments.ds.base << 4), &host_addr) == -1) {
+         // gpf the guest
+         return -1;
+       }
+       
+       first_operand = host_addr;
+      } else {
+       // error... don't know what to do
+       return -1;
+      }
+
+      cr0_val = *(char*)cr0 & 0x0f;
+
+      *(char *)first_operand &= 0xf0;
+      *(char *)first_operand |= cr0_val;
+
+      PrintDebug("index = %d, rip = %x\n", index, (ulong_t)(info->rip));
+      info->rip += index;
+      PrintDebug("new_rip = %x\n", (ulong_t)(info->rip));
+    } else if ((instr[index] == cr_access_byte) &&
+              (instr[index+1] == mov_from_cr_byte)) {
+      /* Mov from CR0
+       * This can only take a 32 bit register argument in anything less than 64 bit mode.
+       */
+      addr_t first_operand;
+      addr_t second_operand;
+      operand_type_t addr_type;
+
+      struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
+
+      index += 2;
+
+      addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
+     
+      struct cr0_32 * virt_cr0 = (struct cr0_32 *)first_operand;
+  
+      if (addr_type != REG_OPERAND) {
+       // invalid opcode to guest
+       PrintDebug("Invalid operand type in mov from CR0\n");
+       return -1;
+      }
+
+      if (info->page_mode == SHADOW_PAGING) {
+       *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
+      } else {
+       *virt_cr0 = *real_cr0;
+      }
+
+      info->rip += index;
+
+    } else {
+      PrintDebug("Unknown read instr from CR0\n");
+      return -1;
+    }
+
+  } else if (info->cpu_mode == PROTECTED) {
+    int index = 0;
+    int ret;
+
+    // The real rip address is actually a combination of the rip + CS base 
+    ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
+    if (ret != 15) {
+      // I think we should inject a GPF into the guest
+      PrintDebug("Could not read Proteced mode instruction (ret=%d)\n", ret);
+      return -1;
+    }
+
+    while (is_prefix_byte(instr[index])) {
+      index++; 
+    }
+
+
+    if ((instr[index] == cr_access_byte) &&
+       (instr[index+1] == mov_from_cr_byte)) {
+      addr_t first_operand;
+      addr_t second_operand;
+      operand_type_t addr_type;
+      struct cr0_32 * virt_cr0;
+      struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
+
+      index += 2;
+
+      addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
+
+      if (addr_type != REG_OPERAND) {
+       PrintDebug("Invalid operand type in mov from CR0\n");
+       return -1;
+      }
+      
+      virt_cr0 = (struct cr0_32 *)first_operand;
+
+      if (info->page_mode == SHADOW_PAGING) {
+       *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
+      } else {
+       *virt_cr0 = *real_cr0;
+      }
+      
+      info->rip += index;
+
+    } else { 
+      PrintDebug("Unknown read instruction from CR0\n");
+      return -1;
+    }
+
+  } else {
+    PrintDebug("Unknown mode read from CR0\n");
+    return -1;
+  }
+
+
+  return 0;
+}
+
+
+
+
+int handle_cr3_write(struct guest_info * info) {
+  if ((info->cpu_mode == PROTECTED) || (info->cpu_mode == PROTECTED_PG)) {
+    int index = 0;
+    int ret;
+    char instr[15];
+
+    ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
+    if (ret != 15) {
+      PrintDebug("Could not read instruction (ret=%d)\n", ret);
+      return -1;
+    }
+    
+    while (is_prefix_byte(instr[index])) {
+      index++;
+    }
+
+    if ((instr[index] == cr_access_byte) && 
+       (instr[index + 1] == mov_to_cr_byte)) {
+
+      addr_t first_operand;
+      addr_t second_operand;
+      struct cr3_32 * new_cr3;
+      //      struct cr3_32 * real_cr3;
+      operand_type_t addr_type;
+
+      index += 2;
+
+      addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
+
+      if (addr_type != REG_OPERAND) {
+       /* Mov to CR3 can only be a 32 bit register */
+       return -1;
+      }
+
+      new_cr3 = (struct cr3_32 *)first_operand;
+
+      if (info->page_mode == SHADOW_PAGING) {
+       addr_t shadow_pt;
+       struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
+       struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
+
+
+       *guest_cr3 = *new_cr3;
+
+       // Something like this
+       shadow_pt =  create_new_shadow_pt32(info);
+       //shadow_pt = setup_shadow_pt32(info, CR3_TO_PDE32(*(addr_t *)new_cr3));
+
+       /* Copy Various flags */
+       *shadow_cr3 = *new_cr3;
+       
+       shadow_cr3->pdt_base_addr = PD32_BASE_ADDR(shadow_pt);
+
+       if (info->cpu_mode == PROTECTED_PG) {
+         // If we aren't in paged mode then we have to preserve the identity mapped CR3
+         info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
+       }
+      }
+
+      info->rip += index;
+
+    } else {
+      PrintDebug("Unknown Instruction\n");
+      return -1;
+    }
+  } else {
+    PrintDebug("Invalid operating Mode\n");
+    return -1;
+  }
+
+  return 0;
+}
+
+
+
+
+int handle_cr3_read(struct guest_info * info) {
+  if ((info->cpu_mode == PROTECTED) || (info->cpu_mode == PROTECTED_PG)) {
+    int index = 0;
+    int ret;
+    char instr[15];
+
+    ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
+    if (ret != 15) {
+      PrintDebug("Could not read instruction (ret=%d)\n", ret);
+      return -1;
+    }
+    
+    while (is_prefix_byte(instr[index])) {
+      index++;
+    }
+
+    if ((instr[index] == cr_access_byte) && 
+       (instr[index + 1] == mov_from_cr_byte)) {
+      addr_t first_operand;
+      addr_t second_operand;
+      struct cr3_32 * virt_cr3;
+      struct cr3_32 * real_cr3 = (struct cr3_32 *)&(info->ctrl_regs.cr3);
+      operand_type_t addr_type;
+
+      index += 2;
+
+      addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
+
+      if (addr_type != REG_OPERAND) {
+       /* Mov to CR3 can only be a 32 bit register */
+       return -1;
+      }
+
+      virt_cr3 = (struct cr3_32 *)first_operand;
+
+      if (info->page_mode == SHADOW_PAGING) {
+       *virt_cr3 = *(struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
+      } else {
+       *virt_cr3 = *real_cr3;
+      }
+      
+      info->rip += index;
+    } else {
+      PrintDebug("Unknown Instruction\n");
+      return -1;
+    }
+  } else {
+    PrintDebug("Invalid operating Mode\n");
+    return -1;
+  }
+
+  return 0;
+}
 
     return -1;
   }
 
-
   shadow_pte_access = can_access_pte32(shadow_pte, fault_addr, error_code);
 
   if (shadow_pte_access == PT_ENTRY_NOT_PRESENT) {
 
     shadow_pte_entry->present = guest_pte_entry->present;
     shadow_pte_entry->user_page = guest_pte_entry->user_page;
-    
+
     //set according to VMM policy
     shadow_pte_entry->write_through = 0;
     shadow_pte_entry->cache_disable = 0;
     //
     // Page Table Entry marked non-user
     //
-    
+
     PrintDebug("Shadow Paging User access error\n");
     return -1;
   } else if (shadow_pte_access == PT_ACCESS_OK) {
     return -1;
   }
 
-
   return 0;
 }