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.


real->protected mode switch should work now
Jack Lange [Wed, 2 Apr 2008 00:28:34 +0000 (00:28 +0000)]
palacios/include/geekos/svm_ctrl_regs.h
palacios/include/geekos/vmm_ctrl_regs.h [new file with mode: 0644]
palacios/include/geekos/vmm_shadow_paging.h
palacios/src/geekos/main.c
palacios/src/geekos/svm.c
palacios/src/geekos/svm_ctrl_regs.c
palacios/src/geekos/svm_handler.c

index d8b3e37..44f6b7a 100644 (file)
@@ -19,7 +19,7 @@ static const uchar_t mov_from_cr_byte = 0x20;
 
 
 
-int handle_cr0_write(struct guest_info * info, ullong_t * new_cr0);
+int handle_cr0_write(struct guest_info * info);
 
 
 
diff --git a/palacios/include/geekos/vmm_ctrl_regs.h b/palacios/include/geekos/vmm_ctrl_regs.h
new file mode 100644 (file)
index 0000000..f0d63fe
--- /dev/null
@@ -0,0 +1,118 @@
+#ifndef __VMM_CTRL_REGS_H
+#define __VMM_CTRL_REGS_H
+
+
+struct cr0_real {
+  uint_t pe    : 1;
+  uint_t mp    : 1;
+  uint_t em    : 1;
+  uint_t ts    : 1;
+};
+
+
+struct cr0_32 {
+  uint_t pe    : 1;
+  uint_t mp    : 1;
+  uint_t em    : 1;
+  uint_t ts    : 1;
+  uint_t et    : 1;
+  uint_t ne    : 1;
+  uint_t rsvd1 : 10;
+  uint_t wp    : 1;
+  uint_t rsvd2 : 1;
+  uint_t am    : 1;
+  uint_t rsvd3 : 10;
+  uint_t nw    : 1;
+  uint_t cd    : 1;
+  uint_t pg    : 1;
+};
+
+
+struct cr0_64 {
+  uint_t pe    : 1;
+  uint_t mp    : 1;
+  uint_t em    : 1;
+  uint_t ts    : 1;
+  uint_t et    : 1;
+  uint_t ne    : 1;
+  uint_t rsvd1 : 10;
+  uint_t wp    : 1;
+  uint_t rsvd2 : 1;
+  uint_t am    : 1;
+  uint_t rsvd3 : 10;
+  uint_t nw    : 1;
+  uint_t cd    : 1;
+  uint_t pg    : 1;
+
+  uint_t  rsvd4;  // MBZ
+};
+
+
+struct cr2_32 {
+  uint_t pf_vaddr;
+};
+
+struct cr2_64 {
+  ullong_t pf_vaddr;
+};
+
+
+struct cr3_32 {
+  uint_t rsvd1             : 3;
+  uint_t pwt               : 1;
+  uint_t pcd               : 1;
+  uint_t rsvd2             : 7;
+  uint_t pdt_base_addr    : 20;
+};
+
+
+struct cr3_32_PAE {
+  uint_t rsvd1             : 3;
+  uint_t pwt               : 1;
+  uint_t pcd               : 1;
+  uint_t pdpt_base_addr    : 27;
+};
+
+
+struct cr3_64 {
+  uint_t rsvd1             : 3;
+  uint_t pwt               : 1;
+  uint_t pcd               : 1;
+  uint_t rsvd2             : 7;
+  ullong_t pml4t_base_addr : 40;
+  uint_t rsvd3             : 12; 
+};
+
+
+struct cr4_32 {
+  uint_t vme               : 1;
+  uint_t pvi               : 1;
+  uint_t tsd               : 1;
+  uint_t de                : 1;
+  uint_t pse               : 1;
+  uint_t pae               : 1;
+  uint_t mce               : 1;
+  uint_t pge               : 1;
+  uint_t pce               : 1;
+  uint_t osf_xsr           : 1;
+  uint_t osx               : 1;
+  uint_t rsvd1             : 21;
+};
+
+struct cr4_64 {
+  uint_t vme               : 1;
+  uint_t pvi               : 1;
+  uint_t tsd               : 1;
+  uint_t de                : 1;
+  uint_t pse               : 1;
+  uint_t pae               : 1;
+  uint_t mce               : 1;
+  uint_t pge               : 1;
+  uint_t pce               : 1;
+  uint_t osf_xsr           : 1;
+  uint_t osx               : 1;
+  uint_t rsvd1             : 21;
+  uint_t rsvd2             : 32;
+};
+
+#endif
index e84f72f..1817800 100644 (file)
@@ -16,7 +16,7 @@ struct shadow_page_state {
   paging_mode_t           guest_mode;
   reg_ex_t                guest_cr3;         // points to guest's current page table
 
-  // Should thi sbe here
+  // Should this be here??
   reg_ex_t                guest_cr0;
 
   // these two reflect the top-level page directory 
index 4f21335..85019d5 100644 (file)
@@ -3,7 +3,7 @@
  * Copyright (c) 2001,2003,2004 David H. Hovemeyer <daveho@cs.umd.edu>
  * Copyright (c) 2003, Jeffrey K. Hollingsworth <hollings@cs.umd.edu>
  * Copyright (c) 2004, Iulian Neamtiu <neamtiu@cs.umd.edu>
- * $Revision: 1.26 $
+ * $Revision: 1.27 $
  * 
  * This is free software.  You are permitted to use,
  * redistribute, and modify it as specified in the file "COPYING".
@@ -258,9 +258,9 @@ void Main(struct Boot_Info* bootInfo)
 
 
   
-#if 0
+#if 1
   SerialPrint("Dumping VM kernel Code (first 128 bytes @ 0x%x)\n", 0x100000);
-  SerialMemDump((unsigned char *)0xfe000, 4096);
+  SerialMemDump((unsigned char *)0x100000, 256);
   /*
     SerialPrint("Dumping kernel Code (first 512 bytes @ 0x%x)\n",KERNEL_START);
     SerialMemDump((unsigned char *)VM_KERNEL_START, 512);
@@ -347,7 +347,9 @@ void Main(struct Boot_Info* bootInfo)
       vm_info.cs.base=0xf000;
       vm_info.cs.limit=0xffff;
       */
-      vm_info.rip = 0xfff0;
+      //vm_info.rip = 0xfff0;
+
+      vm_info.rip = 0;
       vm_info.vm_regs.rsp = 0x0;
     }
 
index ad870ff..8108ddb 100644 (file)
@@ -116,7 +116,7 @@ int init_svm_guest(struct guest_info *info) {
   PrintDebug("Initializing VMCB (addr=%x)\n", info->vmm_data);
   Init_VMCB((vmcb_t*)(info->vmm_data), *info);
   
-  info->rip = 0;
+  //  info->rip = 0;
 
   info->vm_regs.rdi = 0;
   info->vm_regs.rsi = 0;
@@ -140,7 +140,9 @@ int start_svm_guest(struct guest_info *info) {
   //PrintDebugVMCB((vmcb_t*)(info->vmm_data));
 
   while (1) {
+
     PrintDebug("SVM Launch Args (vmcb=%x), (info=%x), (vm_regs=%x)\n", info->vmm_data,  &(info->vm_regs));
+    PrintDebug("Launching to RIP: %x\n", info->rip);
     safe_svm_launch((vmcb_t*)(info->vmm_data), &(info->vm_regs));
     //launch_svm((vmcb_t*)(info->vmm_data));
     PrintDebug("SVM Returned\n");
index a0c5e1a..3929222 100644 (file)
@@ -4,8 +4,10 @@
 #include <geekos/vmcb.h>
 #include <geekos/vmm_emulate.h>
 #include <geekos/vm_guest_mem.h>
+#include <geekos/vmm_ctrl_regs.h>
 
-int handle_cr0_write(struct guest_info * info, ullong_t * new_cr0) {
+
+int handle_cr0_write(struct guest_info * info) {
   //vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t *)(info->vmm_data));
   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
   char instr[15];
@@ -14,8 +16,16 @@ int handle_cr0_write(struct guest_info * info, ullong_t * new_cr0) {
 
 
   if (info->cpu_mode == REAL) {
-    read_guest_pa_memory(info, (addr_t)guest_state->rip, 15, instr);
     int index = 0;
+    int ret;
+
+    // The real rip address is actually a combination of the rip + CS base 
+    ret = read_guest_pa_memory(info, (addr_t)guest_state->rip, 15, instr);
+    if (ret != 0) {
+      // 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])) {
       PrintDebug("instr(%d): 0x%x\n", index, instr[index]);
@@ -30,34 +40,61 @@ int handle_cr0_write(struct guest_info * info, ullong_t * new_cr0) {
  
       addr_t first_operand;
       addr_t second_operand;
+      struct cr0_real *old_cr0;
+      struct cr0_real *new_cr0;
      
       // LMSW
       // decode mod/RM
       index += 2;
  
+      old_cr0 = (struct cr0_real*)&(guest_state->cr0);
 
       if (decode_operands16(&(info->vm_regs), instr + index, &first_operand, &second_operand, REG16) != 0) {
        // error... don't know what to do
        return -1;
       }
-
-      PrintDebug("FirstOperand addr: %x, RAX addr: %x\n", first_operand, &(info->vm_regs.rax));
       
+      index += 3;
+
+      new_cr0 = (struct cr0_real *)first_operand;
 
+      if ((new_cr0->pe == 1) && (old_cr0->pe == 0)) {
+       info->cpu_mode = PROTECTED;
+      }
       
 
+      if (info->page_mode == SHADOW_PAGING) {
+       struct cr0_real * virt_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0);
+
+       /* struct cr0_real is only 4 bits wide, 
+        * so we can overwrite the old_cr0 without worrying about the shadow fields
+        */
+       *old_cr0 = *new_cr0;
+       *virt_cr0 = *new_cr0;
+      } else {
+       // for now we just pass through....
+       *old_cr0 = *new_cr0;
+      }
+
+      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] == clts_byte)) {
       // CLTS
     } else {
-      // unsupported instruction, GPF the guest
+      // unsupported instruction, UD the guest
       return -1;
     }
 
 
+  } else if (info->cpu_mode == PROTECTED) {
+    PrintDebug("Protected Mode write to CR0\n");
+    while(1);
+  } else {
+    PrintDebug("Unknown Mode write to CR0\n");
+    while(1);
   }
-
-
   return 0;
 }
 
index 6624da6..6cd7afe 100644 (file)
@@ -21,7 +21,7 @@ int handle_svm_exit(struct guest_info * info) {
   info->vm_regs.rsp = guest_state->rsp;
 
 
-  PrintDebug("SVM Returned: (Exit Code=%x) (VMCB=%x)\n", &(guest_ctrl->exit_code), info->vmm_data); 
+  PrintDebug("SVM Returned:(VMCB=%x)\n", info->vmm_data); 
   PrintDebug("RIP: %x\n", guest_state->rip);
   
 
@@ -30,21 +30,22 @@ int handle_svm_exit(struct guest_info * info) {
   
   // PrintDebugVMCB((vmcb_t*)(info->vmm_data));
   PrintDebug("SVM Returned: Exit Code: %x\n",exit_code); 
+
   PrintDebug("io_info1 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info1));
   PrintDebug("io_info1 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info1)) + 4));
 
   PrintDebug("io_info2 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info2));
   PrintDebug("io_info2 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info2)) + 4));
+  
   if (exit_code == VMEXIT_IOIO) {
     handle_svm_io(info);
 
   } else if (exit_code == VMEXIT_CR0_WRITE) {
     PrintDebug("CR0 Write\n");
-    ullong_t new_cr0 = 0;
-
-    handle_cr0_write(info, &new_cr0);
 
-    guest_state->cr0 = new_cr0;
+    if (handle_cr0_write(info) == -1) {
+      return -1;
+    }
 
   } else if (( (exit_code == VMEXIT_CR3_READ)  ||
               (exit_code == VMEXIT_CR3_WRITE) ||