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.


*** empty log message ***
Jack Lange [Fri, 7 Mar 2008 20:25:40 +0000 (20:25 +0000)]
17 files changed:
palacios/build/Makefile
palacios/include/geekos/svm.h
palacios/include/geekos/vmcb.h
palacios/include/geekos/vmm.h
palacios/include/geekos/vmm_mem.h
palacios/include/geekos/vmm_paging.h
palacios/include/geekos/vmm_util.h
palacios/src/geekos/int.c
palacios/src/geekos/lowlevel.asm
palacios/src/geekos/main.c
palacios/src/geekos/mem.c
palacios/src/geekos/svm.c
palacios/src/geekos/vmcs.c
palacios/src/geekos/vmm_mem.c
palacios/src/geekos/vmm_paging.c
palacios/src/geekos/vmm_util.c
palacios/src/geekos/vmx.c

index a82b6cc..ab3ad93 100644 (file)
@@ -1,6 +1,6 @@
 # Makefile for GeekOS kernel, userspace, and tools
 # Copyright (c) 2004,2005 David H. Hovemeyer <daveho@cs.umd.edu>
-# $Revision: 1.15 $
+# $Revision: 1.16 $
 
 # This is free software.  You are permitted to use,
 # redistribute, and modify it as specified in the file "COPYING".
@@ -300,7 +300,7 @@ vm_kernel: force
 
 
 vmm_mem_test: geekos/vmm_mem.c
-       $(HOST_CC) -m32 -o mem_test -DVMM_MEM_TEST -I../include ../src/geekos/vmm_mem.c ../src/geekos/vmm_paging.c 
+       $(HOST_CC) -m32 -o mem_test -DVMM_MEM_TEST -I../include ../src/geekos/vmm_mem.c 
 
 
 # Clean build directories of generated files
index 84c48dd..6bb2389 100644 (file)
@@ -10,6 +10,7 @@
 
 #define CPUID_SVM_REV_AND_FEATURE_IDS 0x8000000a
 #define CPUID_SVM_REV_AND_FEATURE_IDS_edx_svml 0x00000004
+#define CPUID_SVM_REV_AND_FEATURE_IDS_edx_np  0x00000001
 
 
 #define EFER_MSR                 0xc0000080
index b17c7d9..ebcce6b 100644 (file)
@@ -71,8 +71,8 @@ union Debug_Registers {
 union Exception_Vectors {
   uint_t bitmap                  PACKED;
   struct {
-    uint_t ex0         : 1        PACKED;
-    uint_t ex1         : 1        PACKED;
+    uint_t ex0          : 1        PACKED;
+    uint_t ex1          : 1        PACKED;
     uint_t ex2         : 1        PACKED;
     uint_t ex3         : 1        PACKED;
     uint_t ex4         : 1        PACKED;
@@ -103,7 +103,41 @@ union Exception_Vectors {
     uint_t ex29        : 1        PACKED;
     uint_t ex30        : 1        PACKED;
     uint_t ex31        : 1        PACKED;
-  } exceptions;
+  } ex_numbers;
+  struct {
+    uint_t de          : 1        PACKED; // divide by zero
+    uint_t db          : 1        PACKED; // Debug
+    uint_t nmi         : 1        PACKED; // Non-maskable interrupt
+    uint_t bp          : 1        PACKED; // Breakpoint
+    uint_t of          : 1        PACKED; // Overflow
+    uint_t br          : 1        PACKED; // Bound-Range
+    uint_t ud          : 1        PACKED; // Invalid-Opcode
+    uint_t nm          : 1        PACKED; // Device-not-available
+    uint_t df          : 1        PACKED; // Double Fault
+    uint_t ex9         : 1        PACKED; 
+    uint_t ts          : 1        PACKED; // Invalid TSS
+    uint_t np          : 1        PACKED; // Segment-not-present
+    uint_t ss          : 1        PACKED; // Stack
+    uint_t gp          : 1        PACKED; // General Protection Fault
+    uint_t pf          : 1        PACKED; // Page fault
+    uint_t ex15        : 1        PACKED;
+    uint_t mf          : 1        PACKED; // Floating point exception
+    uint_t ac          : 1        PACKED; // Alignment-check
+    uint_t mc          : 1        PACKED; // Machine Check
+    uint_t xf          : 1        PACKED; // SIMD floating-point
+    uint_t ex20        : 1        PACKED;
+    uint_t ex21        : 1        PACKED;
+    uint_t ex22        : 1        PACKED;
+    uint_t ex23        : 1        PACKED;
+    uint_t ex24        : 1        PACKED;
+    uint_t ex25        : 1        PACKED;
+    uint_t ex26        : 1        PACKED;
+    uint_t ex27        : 1        PACKED;
+    uint_t ex28        : 1        PACKED;
+    uint_t ex29        : 1        PACKED;
+    uint_t sx          : 1        PACKED; // Security Exception
+    uint_t ex31        : 1        PACKED;
+  } ex_names;
 };
 
 
@@ -239,10 +273,12 @@ typedef struct VMCB_Control_Area {
    * But it does say that the EXITINTINFO field is in bits 63-1
    * ALL other occurances mention a 1 bit reserved field
    */
-  uint_t rsvd8              : 1         PACKED;
-  ullong_t N_CR3            : 63        PACKED;
+  //  uint_t rsvd8              : 1         PACKED;
+  //ullong_t N_CR3            : 63        PACKED;
+  ullong_t N_CR3                        PACKED;
   /* ** */
 
+
   uint_t LBR_VIRTUALIZATION_ENABLE : 1  PACKED;
   ullong_t rsvd9            : 63        PACKED;   // Should be 0
 
index 8751e02..93e7211 100644 (file)
@@ -6,6 +6,7 @@
 #include <geekos/string.h>
 
 #include <geekos/vmm_mem.h>
+#include <geekos/vmm_paging.h>
 
 
 /* utility definitions */
@@ -76,6 +77,7 @@ typedef struct guest_info {
   vmm_mem_layout_t mem_layout;
   // device_map
 
+  vmm_pde_t * page_tables;
   void * vmm_data;
 } guest_info_t;
 
index 75e788c..877382c 100644 (file)
@@ -5,11 +5,17 @@
 #include <geekos/ktypes.h>
 
 
+/*
+ * The mem list is TEMPORARY, simply to lock down which pages are assigned to the VM
+ * We will remove it and use the host page allocation mechanism in the future
+ */
+
+
 typedef unsigned long addr_t;
 
 
 typedef struct mem_region {
- addr_t addr;
+  addr_t addr;
   uint_t num_pages;
 
   struct mem_region * next;
@@ -36,8 +42,8 @@ typedef enum region_type {GUEST, UNMAPPED, SHARED} region_type_t;
 
 
 typedef struct layout_region {
-  addr_t addr;
-  uint_t num_pages;
+  addr_t start;
+  addr_t end;
 
   region_type_t type;
 
@@ -51,8 +57,6 @@ typedef struct layout_region {
 typedef struct vmm_mem_layout {
   uint_t num_pages;
   uint_t num_regions;
-  uint_t num_guest_pages;
 
   layout_region_t * head;
 } vmm_mem_layout_t;
@@ -76,15 +80,15 @@ void print_mem_list(vmm_mem_list_t * list);
 void init_mem_layout(vmm_mem_layout_t * layout);
 void free_mem_layout(vmm_mem_layout_t * layout);
 
-layout_region_t * get_layout_cursor(vmm_mem_layout_t * layout, addr_t addr);
 
 int add_mem_range(vmm_mem_layout_t * layout, layout_region_t * region);
-int add_shared_mem_range(vmm_mem_layout_t * layout, addr_t addr, uint_t num_pages, addr_t host_addr);
-int add_unmapped_mem_range(vmm_mem_layout_t * layout, addr_t addr, uint_t num_pages);
-int add_guest_mem_range(vmm_mem_layout_t * layout, addr_t addr, uint_t num_pages);
+int add_shared_mem_range(vmm_mem_layout_t * layout, addr_t start, addr_t end, addr_t host_addr);
+int add_unmapped_mem_range(vmm_mem_layout_t * layout, addr_t start, addr_t end);
+int add_guest_mem_range(vmm_mem_layout_t * layout, addr_t start, addr_t end);
 
 
-addr_t get_mem_layout_addr(vmm_mem_layout_t * list, uint_t index);
+addr_t get_mem_layout_addr(vmm_mem_layout_t * layout, uint_t index);
+layout_region_t * get_mem_layout_region(vmm_mem_layout_t * layout, addr_t addr);
 
 void print_mem_layout(vmm_mem_layout_t * layout);
 
index 5d41452..b97d835 100644 (file)
@@ -2,7 +2,7 @@
 #define __VMM_PAGING_H
 
 #include <geekos/ktypes.h>
-#include <geekos/vmm.h>
+
 
 
 #include <geekos/vmm_mem.h>
@@ -28,6 +28,9 @@
 #define VM_EXEC      0
 
 
+#define GUEST_PAGE   0x0
+#define SHARED_PAGE  0x1
+
 typedef struct pde {
   uint_t present         : 1;
   uint_t flags           : 4;
@@ -37,7 +40,7 @@ typedef struct pde {
   uint_t global_page     : 1;
   uint_t vmm_info        : 3;
   uint_t pt_base_addr    : 20;
-} pde_t;
+} vmm_pde_t;
 
 typedef struct pte {
   uint_t present         : 1;
@@ -48,13 +51,14 @@ typedef struct pte {
   uint_t global_page     : 1;
   uint_t vmm_info        : 3;
   uint_t page_base_addr  : 20;
-} pte_t;
+} vmm_pte_t;
 
 
-pde_t * generate_guest_page_tables(vmm_mem_layout_t * layout, vmm_mem_list_t * list);
+vmm_pde_t * generate_guest_page_tables(vmm_mem_layout_t * layout, vmm_mem_list_t * list);
 
+void free_guest_page_tables(vmm_pde_t * pde);
 
-void PrintDebugPageTables(pde_t * pde);
+void PrintDebugPageTables(vmm_pde_t * pde);
 
 
 
index ae58b10..16931b4 100644 (file)
@@ -1,13 +1,15 @@
 #ifndef __VMM_UTIL_H
 #define __VMM_UTIL_H
 
-#include <geekos/vmm.h>
-#include <geekos/vmm_mem.h>
+#include <geekos/ktypes.h>
+
 
 
 #ifndef PAGE_SIZE
 #define PAGE_SIZE 4096
 #endif
+
+
 typedef union reg_ex {
   ullong_t r_reg;
   struct {
index 70b7b70..1799cfe 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * GeekOS interrupt handling data structures and functions
  * Copyright (c) 2001,2003 David H. Hovemeyer <daveho@cs.umd.edu>
- * $Revision: 1.3 $
+ * $Revision: 1.4 $
  * 
  * This is free software.  You are permitted to use,
  * redistribute, and modify it as specified in the file "COPYING".
@@ -318,11 +318,18 @@ static void Dummy_Interrupt_Handler(struct Interrupt_State* state)
 {
   Begin_IRQ(state);
 
-  Print("Unexpected Interrupt!  Ignoring!\n");
-  SerialPrint("*** Unexpected interrupt! *** Ignoring!\n");
-  Dump_Interrupt_State(state);
-  //  SerialPrint_VMCS_ALL();
-
+  
+  /* A "feature" of some chipsets is that if an interrupt is raised by mistake
+   * then its automatically assigned to IRQ 7(Int 39). 
+   * Makes perfect sense...
+   * See:
+   * http://forums12.itrc.hp.com/service/forums/questionanswer.do?admit=109447627+1204759699215+28353475&threadId=1118488
+   */
+  if (state->intNum != 39) {
+    Print("Unexpected Interrupt!  Ignoring!\n");
+    SerialPrint("*** Unexpected interrupt! *** Ignoring!\n");
+    Dump_Interrupt_State(state);
+  } 
   End_IRQ(state);
 
   //STOP();
index c530a5c..9869d9f 100644 (file)
@@ -2,7 +2,7 @@
 ; Low level interrupt/thread handling code for GeekOS.
 ; Copyright (c) 2001,2003,2004 David H. Hovemeyer <daveho@cs.umd.edu>
 ; Copyright (c) 2003, Jeffrey K. Hollingsworth <hollings@cs.umd.edu>
-; $Revision: 1.3 $
+; $Revision: 1.4 $
 
 ; This is free software.  You are permitted to use,
 ; redistribute, and modify it as specified in the file "COPYING".
@@ -172,7 +172,7 @@ EXPORT Set_MSR
 EXPORT Get_MSR
 
 EXPORT Get_CR2
-
+EXPORT Get_CR3
 
 EXPORT Proc_test
 
@@ -380,6 +380,11 @@ Get_CR2:
 
 
 align 8
+Get_CR3:
+       mov     eax, cr3
+       ret
+
+align 8
 Proc_test:
        push    ebp
        mov     ebp, esp
index 3d3ebba..5f12931 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.16 $
+ * $Revision: 1.17 $
  * 
  * This is free software.  You are permitted to use,
  * redistribute, and modify it as specified in the file "COPYING".
 
 #include <geekos/vmm_stubs.h>
 
-/*
-  static inline unsigned int cpuid_ecx(unsigned int op)
-  {
-  unsigned int eax, ecx;
-  
-  __asm__("cpuid"
-  : "=a" (eax), "=c" (ecx)
-  : "0" (op)
-  : "bx", "dx" );
-  
-  return ecx;
-  }
-*/
 
 
 
@@ -169,20 +156,6 @@ void Buzzer(ulong_t arg) {
 
 
 
-void Hello(ulong_t arg)
-{
-  char *b="hello ";
-  char byte;
-  short port=0xe9;
-  int i;
-  while(1){
-    for (i=0;i<6;i++) { 
-      byte=b[i];
-      __asm__ __volatile__ ("outb %b0, %w1" : : "a"(byte), "Nd"(port) );
-    }
-  }
-}
-
 void Keyboard_Listener(ulong_t arg) {
   ulong_t * doIBuzz = (ulong_t*)arg;
   Keycode key_press;
@@ -209,47 +182,13 @@ extern char BSS_START, BSS_END;
 
 extern char end;
 
-/*
-void VM_Thread(ulong_t arg) 
-{
-  int ret;
-  struct VMDescriptor *vm = (struct VMDescriptor *) arg;
-
-  SerialPrintLevel(100,"VM_Thread: Launching VM with (entry_ip=%x, exit_eip=%x, guest_esp=%x)\n",
-             vm->entry_ip, vm->exit_eip, vm->guest_esp);
-
-  SerialPrintLevel(100,"VM_Thread: You should see nothing further from me\n");
-
-
-  ret = VMLaunch(vm);
-
-
-  SerialPrintLevel(100,"VM_Thread: uh oh...");
-
-  switch (ret) { 
-  case VMX_SUCCESS:
-    SerialPrintLevel(100,"Normal VMExit Occurred\n");
-    break;
-  case VMX_FAIL_INVALID:
-    SerialPrintLevel(100,"Possibile invalid VMCS (%.8x)\n", ret);
-    break;
-  case VMX_FAIL_VALID:
-    SerialPrintLevel(100,"Valid VMCS, errorcode recorded in VMCS\n");
-    break;
-  case VMM_ERROR:
-    SerialPrintLevel(100,"VMM Error\n");
-    break;
-  default:
-    SerialPrintLevel(100,"VMLaunch returned unknown error (%.8x)\n", ret);
-    break;
-  }
-  
-  SerialPrintLevel(100,"VM_Thread: Spinning\n");
-  while (1) {}
-    
-}
-*/
 
+/* This is an ugly hack to get at the VM  memory */
+ulong_t vm_range_start;
+ulong_t vm_range_end;
+ulong_t guest_kernel_start;
+ulong_t guest_kernel_end;
+/* ** */
 
 
 int AllocateAndMapPagesForRange(uint_t start, uint_t length, pte_t template_pte)
@@ -329,6 +268,9 @@ void Main(struct Boot_Info* bootInfo)
     struct vmm_os_hooks os_hooks;
     struct vmm_ctrl_ops vmm_ops;
     guest_info_t vm_info;
+    addr_t rsp;
+    addr_t rip;
+
     memset(&os_hooks, 0, sizeof(struct vmm_os_hooks));
     memset(&vmm_ops, 0, sizeof(struct vmm_ctrl_ops));
     memset(&vm_info, 0, sizeof(guest_info_t));
@@ -348,14 +290,21 @@ void Main(struct Boot_Info* bootInfo)
     init_mem_layout(&(vm_info.mem_layout));
     init_mem_list(&(vm_info.mem_list));
 
-    //  add_mem_list_pages(&(vm_info.mem_list), START_OF_VM, 20);
-    //add_guest_mem_range(&(vm_info.mem_layout), 0, 20);
 
+    add_mem_list_pages(&(vm_info.mem_list), vm_range_start, (vm_range_end - vm_range_start) / PAGE_SIZE);
+    //    add_unmapped_mem_range(&(vm_info.mem_layout), 0, 256);
+    //add_shared_mem_range(&(vm_info.mem_layout), guest_kernel_start, (guest_kernel_end - guest_kernel_start) / PAGE_SIZE, guest_kernel_start);
+    //add_guest_mem_range(&(vm_info.mem_layout), guest_kernel_end, 20);
 
-    vm_info.rip = (ullong_t)(void*)&BuzzVM;
-    vm_info.rsp = (ulong_t)Alloc_Page();
+    add_shared_mem_range(&(vm_info.mem_layout), 0, 0x1000000, 0);
 
-    SerialPrint("Initializing Guest\n");
+    rip = (ulong_t)(void*)&BuzzVM;
+    vm_info.rip = rip;
+    rsp = (ulong_t)Alloc_Page();
+    vm_info.rsp = rsp;
+
+
+    SerialPrint("Initializing Guest (eip=0x%.8x) (esp=0x%.8x)\n", rip, rsp);
     (vmm_ops).init_guest(&vm_info);
     SerialPrint("Starting Guest\n");
     (vmm_ops).start_guest(&vm_info);
@@ -371,37 +320,6 @@ void Main(struct Boot_Info* bootInfo)
 
 
 
-
-
-  // Try to launch a real VM
-
-
-  // We now map pages of physical memory into where we are going
-  // to slap the vmxassist, bios, and vgabios code
-  /*
-  pte_t template_pte;
-
-  template_pte.present=1;
-  template_pte.flags=VM_WRITE|VM_READ|VM_USER|VM_EXEC;
-  template_pte.accessed=0;
-  template_pte.dirty=0;
-  template_pte.pteAttribute=0;
-  template_pte.globalPage=0;
-  template_pte.kernelInfo=0;
-  
-  SerialPrintLevel(1000,"Allocating Pages for VM kernel\n");
-  
-#define SEGLEN (1024*64)
-
-  AllocateAndMapPagesForRange(START_OF_VM+0x100000, VM_KERNEL_LENGTH / 512, template_pte);
-*/
-  // Now we should be copying into actual memory
-
-  //SerialPrintLevel(1000,"Copying VM code from %x to %x (%d bytes)\n", VM_KERNEL_START, START_OF_VM+0x100000,VM_KERNEL_LENGTH);
-  //memcpy((char*)(START_OF_VM+0x100000),(char*)VM_KERNEL_START,VM_KERNEL_LENGTH);
-
-  //SerialPrintLevel(1000, "VM copied\n");
-
   /*
   // jump into vmxassist
   vm.entry_ip=(uint_t)0x00107fd0;
index 5267ee1..7772582 100644 (file)
@@ -2,7 +2,7 @@
  * Physical memory allocation
  * Copyright (c) 2001,2003,2004 David H. Hovemeyer <daveho@cs.umd.edu>
  * Copyright (c) 2003, Jeffrey K. Hollingsworth <hollings@cs.umd.edu>
- * $Revision: 1.4 $
+ * $Revision: 1.5 $
  * 
  * This is free software.  You are permitted to use,
  * redistribute, and modify it as specified in the file "COPYING".
@@ -22,6 +22,7 @@
 #include <geekos/serial.h>
 #include <geekos/debug.h>
 
+
 /* ----------------------------------------------------------------------
  * Global data
  * ---------------------------------------------------------------------- */
@@ -36,6 +37,18 @@ struct Page* g_pageList;
  */
 uint_t g_freePageCount = 0;
 
+
+
+/* 
+ *  the disgusting way to get at the memory assigned to a VM
+ */
+extern ulong_t vm_range_start;
+extern ulong_t vm_range_end;
+extern ulong_t guest_kernel_start;
+extern ulong_t guest_kernel_end;
+
+
+
 /* ----------------------------------------------------------------------
  * Private data and functions
  * ---------------------------------------------------------------------- */
@@ -56,6 +69,9 @@ static struct Page_List s_freeList;
  */
 int unsigned s_numPages;
 
+
+
+
 /*
  * Add a range of pages to the inventory of physical memory.
  */
@@ -172,7 +188,13 @@ void Init_Mem(struct Boot_Info* bootInfo)
     vmmMemEnd = Round_Up_To_Page(pageListEnd + VMM_AVAIL_MEM_SIZE);
 
 
-
+    /* 
+     *  the disgusting way to get at the memory assigned to a VM
+     */
+    vm_range_start = vmmMemEnd;
+    vm_range_end = endOfMem;
+    guest_kernel_start = ISA_HOLE_END;
+    guest_kernel_end = guestEnd;
 
     Add_Page_Range(0, PAGE_SIZE, PAGE_UNUSED);                        // BIOS area
     Add_Page_Range(PAGE_SIZE, PAGE_SIZE * 3, PAGE_ALLOCATED);         // Intial kernel thread obj + stack
index 4ba49b2..75e65f8 100644 (file)
@@ -13,7 +13,7 @@ extern uint_t cpuid_edx(uint_t op);
 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 uint_t Get_CR3();
 
 /* Checks machine SVM capability */
 /* Implemented from: AMD Arch Manual 3, sect 15.4 */ 
@@ -35,6 +35,11 @@ int is_svm_capable() {
 
   ret = cpuid_edx(CPUID_SVM_REV_AND_FEATURE_IDS);
   
+
+  if ((ret & CPUID_SVM_REV_AND_FEATURE_IDS_edx_np) == 0) {
+    PrintDebug("Nested Paging not supported\n");
+  }
+
   if ((ret & CPUID_SVM_REV_AND_FEATURE_IDS_edx_svml) == 0) {
     PrintDebug("SVM BIOS Disabled, not unlockable\n");
   } else {
@@ -81,8 +86,7 @@ void Init_SVM(struct vmm_ctrl_ops * vmm_ops) {
 
 
 int init_svm_guest(struct guest_info *info) {
-  pde_t * pde;
-
   PrintDebug("Allocating VMCB\n");
   info->vmm_data = (void*)Allocate_VMCB();
 
@@ -90,9 +94,10 @@ int init_svm_guest(struct guest_info *info) {
   PrintDebug("Generating Guest nested page tables\n");
   print_mem_list(&(info->mem_list));
   print_mem_layout(&(info->mem_layout));
-  pde = generate_guest_page_tables(&(info->mem_layout), &(info->mem_list));
-  PrintDebugPageTables(pde);
+  info->page_tables = generate_guest_page_tables(&(info->mem_layout), &(info->mem_list));
+  //PrintDebugPageTables(info->page_tables);
 
+  
 
   PrintDebug("Initializing VMCB (addr=%x)\n", info->vmm_data);
   Init_VMCB((vmcb_t*)(info->vmm_data), *info);
@@ -185,16 +190,50 @@ void Init_VMCB(vmcb_t *vmcb, guest_info_t vm_info) {
     seg->base = 0;
   }
 
+  /* ** */
+
 
   guest_state->efer |= EFER_MSR_svm_enable;
-  guest_state->cr0 = 0x00000001;    // PE 
   guest_state->rflags = 0x00000002; // The reserved bit is always 1
   ctrl_area->svm_instrs.instrs.VMRUN = 1;
+  guest_state->cr0 = 0x00000001;    // PE 
   ctrl_area->guest_ASID = 1;
 
 
+  // Setup exits
+
+  
+  ctrl_area->exceptions.ex_names.de = 1;
+  ctrl_area->exceptions.ex_names.df = 1;
+  ctrl_area->exceptions.ex_names.pf = 1;
+  ctrl_area->exceptions.ex_names.ts = 1;
+  ctrl_area->exceptions.ex_names.ss = 1;
+  ctrl_area->exceptions.ex_names.ac = 1;
+  ctrl_area->exceptions.ex_names.mc = 1;
+  ctrl_area->exceptions.ex_names.gp = 1;
+  ctrl_area->exceptions.ex_names.ud = 1;
+  ctrl_area->exceptions.ex_names.np = 1;
+  ctrl_area->exceptions.ex_names.of = 1;
+  
+  // also determine if CPU supports nested paging
+  if (vm_info.page_tables) {
+    // Flush the TLB on entries/exits
+    ctrl_area->TLB_CONTROL = 1;
+
+    // Enable Nested Paging
+    ctrl_area->NP_ENABLE = 1;
+
+        // Set the Nested Page Table pointer
+    ctrl_area->N_CR3 |= ((addr_t)vm_info.page_tables & 0xfffff000);
+    
+    guest_state->cr3 = Get_CR3();
+
+    PrintDebug("Set Nested CR3: lo: 0x%x  hi: 0x%x\n", (uint_t)*(&(ctrl_area->N_CR3)), (uint_t)*(&(ctrl_area->N_CR3) + 4));
+    PrintDebug("Set Guest CR3: lo: 0x%x  hi: 0x%x\n", (uint_t)*(&(guest_state->cr3)), (uint_t)*(&(guest_state->cr3) + 4));
+    // Enable Paging
+    guest_state->cr0 |= 0x80000000;
+  }
 
-  /* ** */
 
 }
 
index fdb962f..68faebd 100644 (file)
@@ -1,5 +1,5 @@
 #include <geekos/vmcs.h>
-#include <geekos/serial.h>
+
 
 
 
index b2721eb..1071b74 100644 (file)
@@ -216,96 +216,71 @@ void free_mem_layout(vmm_mem_layout_t * layout) {
 }
 
 
-/* this function returns a pointer to the location in the layout list that 
- * corresponds to addr.
- * Rules: 
- *     IF addr is in a region, a ptr to that region is returned
- *     IF addr is not in a region, a ptr to the previous region is returned
- *     IF addr is before all regions, returns NULL
- *     IF list is empty, returns NULL
- */
-layout_region_t * get_layout_cursor(vmm_mem_layout_t * layout, addr_t addr) {
-  layout_region_t * prev_region = layout->head;
-
-
-  while (prev_region != NULL) {
-    if ( (addr >= prev_region->addr) && 
-        (addr < (prev_region->addr + (prev_region->num_pages * PAGE_SIZE))) ) {
-      return prev_region;
-    } else if (addr < prev_region->addr) {
-      // If this region is the current head, then this should return NULL
-      return prev_region->prev;
-    } else if (addr >= (prev_region->addr + (prev_region->num_pages * PAGE_SIZE))) {
-      if (prev_region->next) {
-       prev_region = prev_region->next;
-      } else {
-       return prev_region;
-      }
-    }
-  }
-
-  return prev_region;
-}
-
 
 /* This is slightly different semantically from the mem list, in that we don't allow overlaps
  * we could probably allow overlappig regions of the same type... but I'll let someone else deal with that
  */
 int add_mem_range(vmm_mem_layout_t * layout, layout_region_t * region) {
-  layout_region_t * cursor = get_layout_cursor(layout, region->addr);
-
-  if (cursor == NULL) {
-    if (layout->head) {
-      if (layout->head->addr < region->addr + (region->num_pages * PAGE_SIZE) - 1) {
-       // overlaps not allowed
-       return -1;
-      }
-      layout->head->prev = region;
-    }
+  layout_region_t * cursor = layout->head;
 
+  if ((!cursor) || (cursor->start >= region->end)) {
     region->prev = NULL;
-    region->next = layout->head;
-    layout->head = region;
-    
+    region->next = cursor;
+    layout->num_pages += (region->end - region->start) / PAGE_SIZE;
     layout->num_regions++;
-    layout->num_pages += region->num_pages;
-  } else if ((region->addr >= cursor->addr) && 
-            (region->addr <= cursor->addr + (cursor->num_pages * PAGE_SIZE) - 1)) {
-    // overlaps not allowed
-    return -1;
-  } else if (region->addr > cursor->addr + (cursor->num_pages * PAGE_SIZE) - 1) {
-    // add region to layout
-    region->next = cursor->next;
-    region->prev = cursor;
-    
-    if (region->next) {
-      region->next->prev = region;
-    }
-    cursor->next = region;
+    layout->head = region;
 
-    layout->num_regions++;
-    layout->num_pages += region->num_pages;
-  } else {
-    return -1;
+    return 0;
   }
 
+  while (cursor) {
+    // Check if it overlaps with the current cursor
+    if ((cursor->end > region->start) && (cursor->start < region->start)) {
+      // overlaps not allowed
+      return -1;
+    }
+    
+    // add to the end of the list
+    if (!(cursor->next)) {
+      cursor->next = region;
+      region->prev = cursor;
+      layout->num_regions++;
+      layout->num_pages += (region->end - region->start) / PAGE_SIZE;
+      return 0;
+    } else if (cursor->next->start >= region->end) {
+      // add here
+      region->next = cursor->next;
+      region->prev = cursor;
+
+      cursor->next->prev = region;
+      cursor->next = region;
+
+      layout->num_regions++;
+      layout->num_pages += (region->end - region->start) / PAGE_SIZE;
+      
+      return 0;
+    } else if (cursor->next->end < region->start) {
+      cursor = cursor->next;
+    } else {
+      return -1;
+    }
+  }
 
-  return 0;
+  return -1;
 }
 
 
 
 
 
-int add_shared_mem_range(vmm_mem_layout_t * layout, addr_t addr, uint_t num_pages, addr_t host_addr) {
+int add_shared_mem_range(vmm_mem_layout_t * layout, addr_t start, addr_t end, addr_t host_addr) {
   layout_region_t * shared_region = os_hooks->malloc(sizeof(layout_region_t));
   int ret;
 
   shared_region->next = NULL;
   shared_region->prev = NULL;
-  shared_region->addr = addr;
-  shared_region->num_pages = num_pages;
+  shared_region->start = start;
+  shared_region->end = end;
   shared_region->type = SHARED;
   shared_region->host_addr = host_addr;
 
@@ -318,14 +293,14 @@ int add_shared_mem_range(vmm_mem_layout_t * layout, addr_t addr, uint_t num_page
   return ret;
 }
 
-int add_unmapped_mem_range(vmm_mem_layout_t * layout, addr_t addr, uint_t num_pages) {
+int add_unmapped_mem_range(vmm_mem_layout_t * layout, addr_t start, addr_t end) {
   layout_region_t * unmapped_region = os_hooks->malloc(sizeof(layout_region_t));
   int ret;  
 
   unmapped_region->next = NULL;
   unmapped_region->prev = NULL;
-  unmapped_region->addr = addr;
-  unmapped_region->num_pages = num_pages;
+  unmapped_region->start = start;
+  unmapped_region->end = end;
   unmapped_region->type = UNMAPPED;
   unmapped_region->host_addr = 0;
 
@@ -338,22 +313,20 @@ int add_unmapped_mem_range(vmm_mem_layout_t * layout, addr_t addr, uint_t num_pa
   return ret;
 }
 
-int add_guest_mem_range(vmm_mem_layout_t * layout, addr_t addr, uint_t num_pages) {
+int add_guest_mem_range(vmm_mem_layout_t * layout, addr_t start, addr_t end) {
   layout_region_t * guest_region = os_hooks->malloc(sizeof(layout_region_t));
   int ret;
 
   guest_region->next = NULL;
   guest_region->prev = NULL;
-  guest_region->addr = addr;
-  guest_region->num_pages = num_pages;
+  guest_region->start = start;
+  guest_region->end = end;
   guest_region->type = GUEST;
   guest_region->host_addr = 0;
 
   ret = add_mem_range(layout, guest_region);
   
-  if (ret == 0) {
-    layout->num_guest_pages += num_pages;
-  } else {
+  if (ret != 0) {
     VMMFree(guest_region);
   }
 
@@ -379,17 +352,36 @@ addr_t get_mem_layout_addr(vmm_mem_layout_t * layout, uint_t index) {
       return -1;
     }
 
-    if (reg->num_pages <= index) {
-      i -= reg->num_pages;
+    int num_reg_pages = reg->end - reg->start;
+
+    if (num_reg_pages <= index) {
+      i -= num_reg_pages;
       reg = reg->next;
     } else {
-      return reg->addr + (i * PAGE_SIZE);
+      return reg->start + (i * PAGE_SIZE);
     }
   }
 
   return -1;
 }
 
+layout_region_t * get_mem_layout_region(vmm_mem_layout_t * layout, addr_t addr) {
+  layout_region_t * tmp_reg = layout->head;
+
+
+  while (tmp_reg) {
+    if ((tmp_reg->start <= addr) && (tmp_reg->end > addr)) {
+      return tmp_reg;
+    } else if (tmp_reg->start > addr) {
+      return NULL;
+    } else {
+      tmp_reg = tmp_reg->next;
+    }
+  }
+
+  return NULL;
+}
+
 
 
 
@@ -416,7 +408,7 @@ void print_mem_layout(vmm_mem_layout_t * layout) {
   PrintDebug("Memory Layout (regions: %d) (pages: %d)\n", layout->num_regions, layout->num_pages);
 
   while (cur) {
-    PrintDebug("%d: 0x%x - 0x%x\n", i, cur->addr, cur->addr + (cur->num_pages * PAGE_SIZE) - 1);
+    PrintDebug("%d: 0x%x - 0x%x\n", i, cur->start, cur->end -1);
     cur = cur->next;
     i++;
   }
@@ -433,7 +425,6 @@ void print_mem_layout(vmm_mem_layout_t * layout) {
 
 
 
-
 #ifdef VMM_MEM_TEST
 
 
@@ -441,7 +432,7 @@ void print_mem_layout(vmm_mem_layout_t * layout) {
 #include <stdio.h>
 #include <stdarg.h>
 
-#include <geekos/vmm_paging.h>
+
 
 
 
@@ -513,39 +504,44 @@ int mem_list_add_test_1(  vmm_mem_list_t * list) {
 
 int mem_layout_add_test_1(vmm_mem_layout_t *layout) {
 
-  uint_t offset = 0;
+  
+  uint_t start = 0;
+  uint_t end = 0;
 
   PrintDebug("\n\nTesting Memory Layout\n");
 
   init_mem_layout(layout);
 
-  offset = PAGE_SIZE * 6;
-  PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 10));
-  add_guest_mem_range(layout, offset, 10);
+  start = 0x6000;
+  end = 0x10000;;
+  PrintDebug("Adding 0x%x - 0x%x\n", start, end);
+  add_guest_mem_range(layout, start, end);
   print_mem_layout(layout);
 
 
-  offset = PAGE_SIZE * 20;
-  PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 1));
-  add_guest_mem_range(layout, offset, 1);
+  start = 0x1000;
+  end = 0x3000;
+  PrintDebug("Adding 0x%x - 0x%x\n", start, end);
+  add_guest_mem_range(layout, start, end);
   print_mem_layout(layout);
 
-
-  offset = PAGE_SIZE * 16;
-  PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + PAGE_SIZE * 4);
-  add_guest_mem_range(layout, offset, 4);
+  start = 0x2000;
+  end = 0x6000;
+  PrintDebug("Adding 0x%x - 0x%x\n", start, end);
+  add_guest_mem_range(layout, start, end);
   print_mem_layout(layout);
 
-
-  offset = PAGE_SIZE * 10;
-  PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 30));
-  add_guest_mem_range(layout, offset, 30);
+  start = 0x4000;
+  end = 0x5000;
+  PrintDebug("Adding 0x%x - 0x%x\n", start, end);
+  add_guest_mem_range(layout, start, end);
   print_mem_layout(layout);
 
 
-  offset = 0;
-  PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 1));
-  add_guest_mem_range(layout, offset, 1);
+  start = 0x5000;
+  end = 0x7000;
+  PrintDebug("Adding 0x%x - 0x%x\n", start, end);
+  add_guest_mem_range(layout, start, end);
   print_mem_layout(layout);
 
 
@@ -573,10 +569,6 @@ int main(int argc, char ** argv) {
   printf("mem_list_add_test_1: %d\n", mem_list_add_test_1(&list));
   printf("layout_add_test_1: %d\n", mem_layout_add_test_1(&layout));
 
-
-  pde_t * pde = generate_guest_page_tables(&layout, &list);
-  PrintDebugPageTables(pde);
-
   return 0;
 }
 #endif
index 81719a4..879d68a 100644 (file)
@@ -1,6 +1,6 @@
 #include <geekos/vmm_paging.h>
 
-
+#include <geekos/vmm.h>
 
 
 
@@ -13,7 +13,7 @@ extern struct vmm_os_hooks * os_hooks;
  * pulling pages from the mem_list when necessary
  * If there are any gaps in the layout, we add them as unmapped pages
  */
-pde_t * generate_guest_page_tables(vmm_mem_layout_t * layout, vmm_mem_list_t * list) {
+vmm_pde_t * generate_guest_page_tables(vmm_mem_layout_t * layout, vmm_mem_list_t * list) {
   ullong_t current_page_addr = 0;
   uint_t layout_index = 0;
   uint_t list_index = 0;
@@ -24,7 +24,7 @@ pde_t * generate_guest_page_tables(vmm_mem_layout_t * layout, vmm_mem_list_t * l
 
   
 
-  pde_t * pde = os_hooks->allocate_pages(1);
+  vmm_pde_t * pde = os_hooks->allocate_pages(1);
 
   for (i = 0; i < MAX_PAGE_DIR_ENTRIES; i++) {
     if (num_entries == 0) { 
@@ -37,7 +37,7 @@ pde_t * generate_guest_page_tables(vmm_mem_layout_t * layout, vmm_mem_list_t * l
       pde[i].vmm_info = 0;
       pde[i].pt_base_addr = 0;
     } else {
-      pte_t * pte = os_hooks->allocate_pages(1);
+      vmm_pte_t * pte = os_hooks->allocate_pages(1);
 
       pde[i].present = 1;
       pde[i].flags = VM_READ | VM_WRITE | VM_EXEC | VM_USER;
@@ -67,7 +67,7 @@ pde_t * generate_guest_page_tables(vmm_mem_layout_t * layout, vmm_mem_list_t * l
          current_page_addr += PAGE_SIZE;
        } else if (current_page_addr == layout_addr) {
          // Set up the Table entry to map correctly to the layout region
-         layout_region_t * page_region = get_layout_cursor(layout, layout_addr);
+         layout_region_t * page_region = get_mem_layout_region(layout, layout_addr);
 
          if (page_region->type == UNMAPPED) {
            pte[j].present = 0;
@@ -86,17 +86,25 @@ pde_t * generate_guest_page_tables(vmm_mem_layout_t * layout, vmm_mem_list_t * l
          if (page_region->type == UNMAPPED) {
            pte[j].page_base_addr = 0;
          } else if (page_region->type == SHARED) {
-           pte[j].page_base_addr = page_region->host_addr >> 12;
+           addr_t host_addr = page_region->host_addr + (layout_addr - page_region->start);
+
+           pte[j].page_base_addr = host_addr >> 12;
+           pte[j].vmm_info = SHARED_PAGE;
          } else if (page_region->type == GUEST) {
            addr_t list_addr =  get_mem_list_addr(list, list_index++);
            
            if (list_addr == -1) {
              // error
-             // cleanup....
+             // cleanup...
+             free_guest_page_tables(pde);
              return NULL;
            }
            PrintDebug("Adding guest page (%x)\n", list_addr);
            pte[j].page_base_addr = list_addr >> 12;
+           
+           // Reset this when we move over to dynamic page allocation
+           //      pte[j].vmm_info = GUEST_PAGE;           
+           pte[j].vmm_info = SHARED_PAGE;
          }
 
          num_entries--;
@@ -106,6 +114,7 @@ pde_t * generate_guest_page_tables(vmm_mem_layout_t * layout, vmm_mem_list_t * l
          // error
          PrintDebug("Error creating page table...\n");
          // cleanup
+         free_guest_page_tables(pde);
          return NULL;
        }
       }
@@ -116,9 +125,31 @@ pde_t * generate_guest_page_tables(vmm_mem_layout_t * layout, vmm_mem_list_t * l
 }
 
 
+void free_guest_page_tables(vmm_pde_t * pde) {
+  int i, j;
+
+
+  for (i = 0; (i < MAX_PAGE_DIR_ENTRIES); i++) {
+    if (pde[i].present) {
+      vmm_pte_t * pte = (vmm_pte_t *)(pde[i].pt_base_addr << PAGE_POWER);
+      
+      for (j = 0; (j < MAX_PAGE_TABLE_ENTRIES); j++) {
+       if ((pte[j].present) && (pte[j].vmm_info & GUEST_PAGE)){
+         os_hooks->free_page((void *)(pte[j].page_base_addr  << PAGE_POWER));
+       }
+      }
+      
+      os_hooks->free_page(pte);
+    }
+  }
+
+  os_hooks->free_page(pde);
+}
+
+
 
 
-void PrintPDE(void * virtual_address, pde_t * pde)
+void PrintPDE(void * virtual_address, vmm_pde_t * pde)
 {
   PrintDebug("PDE %p -> %p : present=%x, flags=%x, accessed=%x, reserved=%x, largePages=%x, globalPage=%x, kernelInfo=%x\n",
              virtual_address,
@@ -132,7 +163,7 @@ void PrintPDE(void * virtual_address, pde_t * pde)
              pde->vmm_info);
 }
   
-void PrintPTE(void * virtual_address, pte_t * pte)
+void PrintPTE(void * virtual_address, vmm_pte_t * pte)
 {
   PrintDebug("PTE %p -> %p : present=%x, flags=%x, accessed=%x, dirty=%x, pteAttribute=%x, globalPage=%x, vmm_info=%x\n",
              virtual_address,
@@ -148,7 +179,7 @@ void PrintPTE(void * virtual_address, pte_t * pte)
 
 
 
-void PrintPD(pde_t * pde)
+void PrintPD(vmm_pde_t * pde)
 {
   int i;
 
@@ -158,11 +189,11 @@ void PrintPD(pde_t * pde)
   }
 }
 
-void PrintPT(void * starting_address, pte_t * pte) 
+void PrintPT(void * starting_address, vmm_pte_t * pte) 
 {
   int i;
 
-  //  PrintDebug("Page Table at %p:\n", pte);
+  PrintDebug("Page Table at %p:\n", pte);
   for (i = 0; (i < MAX_PAGE_TABLE_ENTRIES) && pte[i].present; i++) { 
     PrintPTE(starting_address + (PAGE_SIZE * i), &(pte[i]));
   }
@@ -172,7 +203,7 @@ void PrintPT(void * starting_address, pte_t * pte)
 
 
 
-void PrintDebugPageTables(pde_t * pde)
+void PrintDebugPageTables(vmm_pde_t * pde)
 {
   int i;
   
index 4aa4d34..3164e69 100644 (file)
@@ -1,5 +1,6 @@
 #include <geekos/vmm_util.h>
 
+#include <geekos/vmm.h>
 
 extern struct vmm_os_hooks * os_hooks;
 
index 8aa8b2f..2278da9 100644 (file)
@@ -1,8 +1,5 @@
 /* Eventually  we want to get rid of these */
-#include <geekos/mem.h>
-#include <geekos/segment.h>
-#include <geekos/gdt.h>
-#include <geekos/idt.h>
+
 #include <geekos/cpu.h>
 #include <geekos/io_devs.h>
 /* ** */
@@ -30,6 +27,8 @@ extern int Launch_VM(ullong_t vmcsPtr, uint_t eip);
 #define ROMBIOS_DEBUG_PORT    0x403
 
 
+extern struct vmm_os_hooks * os_hooks;
+
 
 static struct VM theVM;
 
@@ -884,7 +883,7 @@ int VMLaunch(struct VMDescriptor *vm)
 
 VmxOnRegion * CreateVmxOnRegion() {
   union VMX_MSR basicMSR;
-  VmxOnRegion * region = (VmxOnRegion *)Alloc_Page();
+  VmxOnRegion * region = (VmxOnRegion *)(os_hooks)->allocate_pages(1);
 
   Get_MSR(IA32_VMX_BASIC_MSR, &basicMSR.regs.high, &basicMSR.regs.low);
   //  memcpy(region, &basicMSR.vmxBasic.revision, sizeof(uint_t));
@@ -898,7 +897,7 @@ VmxOnRegion * CreateVmxOnRegion() {
 
 VMCS * CreateVMCS() {
   union VMX_MSR basicMSR;
-  VMCS * vmcs = (VMCS *)Alloc_Page();
+  VMCS * vmcs = (VMCS *)(os_hooks)->allocate_pages(1);
 
   Get_MSR(IA32_VMX_BASIC_MSR, &basicMSR.regs.high, &basicMSR.regs.low);
   *(ulong_t *)vmcs = basicMSR.vmxBasic.revision;