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.


Additional VMX support. Bootstrapping code added.
[palacios.git] / palacios / src / palacios / vmx.c
index 0395b6e..d152e0b 100644 (file)
@@ -23,6 +23,7 @@
 #include <palacios/vmx.h>
 #include <palacios/vmcs.h>
 #include <palacios/vmm.h>
+#include <palacios/vmx_lowlevel.h>
 
 
 // 
@@ -35,6 +36,7 @@
 
 #include <palacios/vmm_util.h>
 #include <palacios/vmm_string.h>
+#include <palacios/vmm_ctrl_regs.h>
 
 
 
@@ -50,7 +52,6 @@ extern int Launch_VM(ullong_t vmcsPtr, uint_t eip);
 #define ROMBIOS_DEBUG_PORT    0x403
 
 
-static struct VM theVM;
 
 static uint_t GetLinearIP(struct VM * vm) {
   if (vm->state == VM_VMXASSIST_V8086_BIOS || vm->state == VM_VMXASSIST_V8086) { 
@@ -66,22 +67,19 @@ static uint_t GetLinearIP(struct VM * vm) {
 #define MAX_CODE 512
 #define INSTR_OFFSET_START 17
 #define NOP_SEQ_LEN        10
-#define INSTR_OFFSET_END   (INSTR_OFFSET_START+NOP_SEQ_LEN-1)
+#define INSTR_OFFSET_END   (INSTR_OFFSET_START + NOP_SEQ_LEN - 1)
 #define TEMPLATE_CODE_LEN  35
 
-uint_t oldesp=0;
-uint_t myregs=0;
+uint_t oldesp = 0;
+uint_t myregs = 0;
 
 
 
+static struct vmcs_data* vmxon_ptr;
 
 
 
-extern uint_t VMCS_CLEAR();
-extern uint_t VMCS_LOAD();
-extern uint_t VMCS_STORE();
 extern uint_t VMCS_LAUNCH();
-extern uint_t VMCS_RESUME();
 extern uint_t Init_VMCS_HostState();
 extern uint_t Init_VMCS_GuestState();
 
@@ -123,60 +121,61 @@ void DecodeCurrentInstruction(struct VM *vm, struct Instruction *inst)
 }
 
 
-static void V8086ModeSegmentRegisterFixup(struct VM *vm)
+static void setup_v8086_mode_for_boot(struct guest_info* vm_info)
 {
-  vm->vmcs.guestStateArea.cs.baseAddr = vm->vmcs.guestStateArea.cs.selector << 4;
-  vm->vmcs.guestStateArea.es.baseAddr = vm->vmcs.guestStateArea.es.selector << 4;
-  vm->vmcs.guestStateArea.ss.baseAddr = vm->vmcs.guestStateArea.ss.selector << 4;
-  vm->vmcs.guestStateArea.ds.baseAddr = vm->vmcs.guestStateArea.ds.selector << 4;
-  vm->vmcs.guestStateArea.fs.baseAddr = vm->vmcs.guestStateArea.fs.selector << 4;
-  vm->vmcs.guestStateArea.gs.baseAddr = vm->vmcs.guestStateArea.gs.selector << 4;
-}
-
-static void SetupV8086ModeForBoot(struct VM *vm)
-{
-  vm->state = VM_VMXASSIST_V8086_BIOS;
-
-  // Put guest into V8086 mode on return
-  vm->vmcs.guestStateArea.rflags |= EFLAGS_VM | EFLAGS_IOPL_HI | EFLAGS_IOPL_LO ;
-  
-  // We will start at f000:fff0 on return
-  //
-  // We want this to look as much as possible as a processor
-  // reset
-  vm->vmcs.guestStateArea.rip = 0xfff0;  // note, 16 bit rip
-  vm->vmcs.guestStateArea.cs.selector = 0xf000;
-  vm->vmcs.guestStateArea.cs.limit = 0xffff;
-  vm->vmcs.guestStateArea.cs.access.as_dword = 0xf3;
-
-  vm->vmcs.guestStateArea.ss.selector = 0x0000;
-  vm->vmcs.guestStateArea.ss.limit = 0xffff;
-  vm->vmcs.guestStateArea.ss.access.as_dword = 0xf3;
-
-  vm->vmcs.guestStateArea.ds.selector = 0x0000;
-  vm->vmcs.guestStateArea.ds.limit = 0xffff;
-  vm->vmcs.guestStateArea.ds.access.as_dword = 0xf3;
-
-  vm->vmcs.guestStateArea.es.selector = 0x0000;
-  vm->vmcs.guestStateArea.es.limit = 0xffff;
-  vm->vmcs.guestStateArea.es.access.as_dword = 0xf3;
-
-  vm->vmcs.guestStateArea.fs.selector = 0x0000;
-  vm->vmcs.guestStateArea.fs.limit = 0xffff;
-  vm->vmcs.guestStateArea.fs.access.as_dword = 0xf3;
-
-  vm->vmcs.guestStateArea.gs.selector = 0x0000;
-  vm->vmcs.guestStateArea.gs.limit = 0xffff;
-  vm->vmcs.guestStateArea.gs.access.as_dword = 0xf3;
-  
-  V8086ModeSegmentRegisterFixup(vm);
-
-  PrintTrace_VMCSData(&(vm->vmcs));
 
+    ((struct vmx_data*)vm_info->vmm_data)->state = VMXASSIST_V8086_BIOS;
+    ((struct rflags)info->ctrl_regs.rflags).vm = 1;
+    ((struct rflags)info->ctrl_regs.rflags).iopl = 3;
+
+
+    vm_info->rip = 0xfff0;
+
+    vm_info->segments.cs.selector = 0xf000;
+    vm_info->segments.cs.base = 0xf000<<4;
+    vm_info->segments.cs.limit = 0xffff;
+    vm_info->segments.cs.type = 3;
+    vm_info->segments.cs.system = 1;
+    vm_info->segments.cs.dpl = 3;
+    vm_info->segments.cs.present = 1;
+    vm_info->segments.cs.granularity = 0;
+
+    vm_info->segments.ss.selector = 0x0000;
+    vm_info->segments.ss.base = 0x0000<<4;
+    vm_info->segments.ss.limit = 0xffff;
+    vm_info->segments.ss.type = 3;
+    vm_info->segments.ss.system = 1;
+    vm_info->segments.ss.dpl = 3;
+    vm_info->segments.ss.present = 1;
+    vm_info->segments.ss.granularity = 0;
+
+    vm_info->segments.es.selector = 0x0000;
+    vm_info->segments.es.base = 0x0000<<4;
+    vm_info->segments.es.limit = 0xffff;
+    vm_info->segments.es.type = 3;
+    vm_info->segments.es.system = 1;
+    vm_info->segments.es.dpl = 3;
+    vm_info->segments.es.present = 1;
+    vm_info->segments.es.granularity = 0;
+
+    vm_info->segments.fs.selector = 0x0000;
+    vm_info->segments.fs.base = 0x0000<<4;
+    vm_info->segments.fs.limit = 0xffff;
+    vm_info->segments.fs.type = 3;
+    vm_info->segments.fs.system = 1;
+    vm_info->segments.fs.dpl = 3;
+    vm_info->segments.fs.present = 1;
+    vm_info->segments.fs.granularity = 0;
+
+    vm_info->segments.gs.selector = 0x0000;
+    vm_info->segments.gs.base = 0x0000<<4;
+    vm_info->segments.gs.limit = 0xffff;
+    vm_info->segments.gs.type = 3;
+    vm_info->segments.gs.system = 1;
+    vm_info->segments.gs.dpl = 3;
+    vm_info->segments.gs.present = 1;
+    vm_info->segments.gs.granularity = 0;
 }
-  
-
-
 
 static void ConfigureExits(struct VM *vm)
 {
@@ -229,7 +228,7 @@ int MyLaunch(struct VM *vm)
 
   PrintTrace("Guest ESP: 0x%x (%u)\n", guest_esp, guest_esp);
 
-  exit_eip=(uint_t)RunVMM;
+  exit_eip = (uint_t)RunVMM;
 
   PrintTrace("Clear\n");
   VMCS_CLEAR(vmcs);
@@ -275,13 +274,14 @@ int MyLaunch(struct VM *vm)
   /* Guest state */
   PrintTrace("Setting up guest state\n");
   PrintTrace("GUEST_RIP: %x (%u)\n", entry_eip, entry_eip);
-  VMCS_WRITE(GUEST_RIP,&entry_eip);
+  VMCS_WRITE(GUEST_RIP, &entry_eip);
 
   SetCRBitsCorrectly(IA32_VMX_CR0_FIXED0_MSR, IA32_VMX_CR0_FIXED1_MSR, GUEST_CR0);
   SetCRBitsCorrectly(IA32_VMX_CR4_FIXED0_MSR, IA32_VMX_CR4_FIXED1_MSR, GUEST_CR4);
   ret = Init_VMCS_GuestState();
 
   PrintTrace("InitGuestState returned\n");
+
   if (ret != VMX_SUCCESS) {
     if (ret == VMX_FAIL_VALID) {
       PrintTrace("Init Guest state: VMCS FAILED WITH ERROR\n");
@@ -291,11 +291,11 @@ int MyLaunch(struct VM *vm)
     return ret;
   }
   PrintTrace("GUEST_RSP: %x (%u)\n", guest_esp, (uint_t)guest_esp);
-  VMCS_WRITE(GUEST_RSP,&guest_esp);
+  VMCS_WRITE(GUEST_RSP, &guest_esp);
 
   //  tmpReg = 0x4100;
   tmpReg = 0xffffffff;
-  if (VMCS_WRITE(EXCEPTION_BITMAP,&tmpReg ) != VMX_SUCCESS) {
+  if (VMCS_WRITE(EXCEPTION_BITMAP, &tmpReg) != VMX_SUCCESS) {
     PrintInfo("Bitmap error\n");
   }
 
@@ -384,22 +384,24 @@ static addr_t sanitize_bits2(uint32_t msr_num0, uint32_t msr_num1, addr_t val) {
 
 
 
-static vmcs_t * allocate_vmcs() {
+static vmcs_data* allocate_vmcs() {
     reg_ex_t msr;
-    vmcs_t * vmcs_page = (vmcs_t *)V3_VAddr(V3_AllocPages(1));
+    vmcs_data* vmcs_page = (vmcs_data*)V3_VAddr(V3_AllocPages(1));
 
-    memset(vmcb_page, 0, 4096);
+    memset(vmcs_page, 0, 4096);
 
     v3_get_msr(VMX_BASIC_MSR, &(msr.e_reg.high), &(msr.e_reg.low));
     
-    *(uint32_t *)vmcs_page = ((struct vmx_basic_msr *)msr.val)->revision;
+    vmcs_page->revision = ((struct vmx_basic_msr)msr).revision;
 
     return vmcs_page;
 }
 
 
 
-static void init_vmcs_bios(vmcs_t * vmcs, struct guest_info * vm_info) {
+static void init_vmcs_bios(struct guest_info * vm_info) 
+{
+
 
 }
 
@@ -408,11 +410,17 @@ static void init_vmcs_bios(vmcs_t * vmcs, struct guest_info * vm_info) {
 static int init_vmx_guest(struct guest_info * info, struct v3_vm_config * config_ptr) {
     v3_pre_config_guest(info, config_ptr);
 
+    struct vmx_data* data;
+
+    PrintDebug("Allocating vmx_data\n");
+    data = (struct vmx_data*)V3_Malloc(sizeof(struct vmx_data));
     PrintDebug("Allocating VMCS\n");
-    info->vmm_data = (void *)allocate_vmcs();
+    data->vmcs = allocate_vmcs();
 
-    PrintDebug("Initializing VMCS (addr=%p)\n", (void *)info->vmm_data);
-    init_vmcs_bios((vmcs_t *)(info->vmm_data), info);
+    info->vmm_data = (void*)data;
+
+    PrintDebug("Initializing VMCS (addr=%p)\n", info->vmm_data);
+    init_vmcs_bios((struct vmx_data*)(info->vmm_data), info);
 
     v3_post_config_guest(info, config_ptr);
 
@@ -422,7 +430,23 @@ static int init_vmx_guest(struct guest_info * info, struct v3_vm_config * config
 
 
 
-static int start_svm_guest(struct guest_info *info) {
+static int start_vmx_guest(struct guest_info *info) {
+    struct vmx_data* vmx_data = (struct vmx_data*)info->vmm_data;
+    int vmx_ret;
+
+    // Have to do a whole lot of flag setting here
+    vmx_ret = vmcs_clear(vmx_data->vmcs);
+    if(vmx_ret != VMX_SUCCESS) {
+        PrintDebug("VMCS Clear failed\n");
+        return -1;
+    }
+    vmx_ret = vmcs_load(vmx_data->vmcs);
+    if(vmx_ret != VMX_SUCCESS) {
+        PrintDebug("Executing VMPTRLD\n");
+        return -1;
+    }
+
+    // Setup guest state
     return -1;
 }
 
@@ -449,12 +473,11 @@ int v3_is_vmx_capable() {
        }
 
     } else {
-       PrintDebug("VMX not supported on this cpu\n");
-       return 0;
+        PrintDebug("VMX not supported on this cpu\n");
+        return 0;
     }
 
     return 1;
-
 }
 
 static int has_vmx_nested_paging() {
@@ -476,7 +499,7 @@ static int setup_base_host_state() {
     
 
 
-    vmwrite(HOST_IDTR_BASE, 
+    //   vmwrite(HOST_IDTR_BASE, 
 
 
 }
@@ -486,15 +509,7 @@ static int setup_base_host_state() {
 void v3_init_vmx(struct v3_ctrl_ops * vm_ops) {
     v3_msr_t basic_msr;
 
-    // Setup the host state save area
-    void * host_state = V3_AllocPages(1);
-
-    v3_get_msr(VMX_BASIC_MSR, &(basic_msr.hi), &(basic_msr.lo));
-    
-    *(uint32_t *)host_state = ((struct vmx_basic_msr *)basic_msr.value)->revision;
     
-    PrintDebug("VMX revision: 0x%p\n", host_state);
-
     __asm__ __volatile__ (
                          "movl %%cr4, %%ebx; "
                          "orl  %%ebx, 0x00002000; "
@@ -510,18 +525,22 @@ void v3_init_vmx(struct v3_ctrl_ops * vm_ops) {
                          "movl %%ebx, %%cr0"
                          );
 
+    // Setup VMXON Region
+    vmxon_ptr = allocate_vmcs();
+    PrintDebug("VMX revision: 0x%p\n", (void*)vmxon_ptr);
 
-    if (v3_enable_vmx(host_state) == 0) {
-       PrintDebug("VMX Enabled\n");
+    if (v3_enable_vmx(vmxon_ptr) == 0) {
+        PrintDebug("VMX Enabled\n");
     } else {
-       PrintDebug("VMX initialization failure\n");
+        PrintError("VMX initialization failure\n");
+        return;
     }
        
 
     if (has_vmx_nested_paging() == 1) {
-       v3_cpu_type = V3_VMX_EPT_CPU;
+        v3_cpu_type = V3_VMX_EPT_CPU;
     } else {
-       v3_cpu_type = V3_VMX_CPU;
+        v3_cpu_type = V3_VMX_CPU;
     }
 
     // Setup the VMX specific vmm operations