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 [Thu, 22 May 2008 03:38:15 +0000 (03:38 +0000)]
palacios/include/palacios/svm.h
palacios/include/palacios/vmm_time.h
palacios/src/devices/8254.c
palacios/src/geekos/vm.c
palacios/src/geekos/vmm_stubs.c
palacios/src/palacios/svm.c
palacios/src/palacios/vmm_time.c

index 9c0912b..3ede354 100644 (file)
@@ -5,6 +5,8 @@
 #include <palacios/vmm.h>
 #include <palacios/vmcb.h>
 
+#ifdef __V3VEE__
+
 #define CPUID_FEATURE_IDS 0x80000001
 #define CPUID_FEATURE_IDS_ecx_svm_avail 0x00000004
 
 #define SVM_HANDLER_ERROR     0x1
 #define SVM_HANDLER_HALT      0x2
 
-
+#endif
 
 
 void Init_SVM(struct vmm_ctrl_ops * vmm_ops);
 int is_svm_capable();
 
 
-vmcb_t * Allocate_VMCB();
-void Init_VMCB(vmcb_t * vmcb, struct guest_info vm_info);
-void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info);
-void Init_VMCB_pe(vmcb_t * vmcb, struct guest_info vm_info);
-
-int init_svm_guest(struct guest_info *info);
-int start_svm_guest(struct guest_info * info);
-
-
-inline addr_t get_rip_linear(struct guest_info * info, addr_t rip, addr_t cs_base);
-
 
 
 #endif
index 2411187..9af1840 100644 (file)
@@ -17,7 +17,7 @@ struct vm_time {
   ullong_t cached_host_tsc;
 
   // The number of cycles pending for notification to the timers
-  ullong_t pending_cycles;
+  //ullong_t pending_cycles;
 
   // Installed Timers 
   uint_t num_timers;
@@ -32,7 +32,7 @@ struct vm_timer_ops {
 
 struct vm_timer {
   void * private_data;
-  struct vm_timer_ops ops;
+  struct vm_timer_ops * ops;
 
   struct list_head timer_link;
 };
@@ -47,6 +47,6 @@ int v3_add_timer(struct guest_info * info, struct vm_timer_ops * ops, void * pri
 int v3_remove_timer(struct guest_info * info, struct vm_timer * timer);
 
 
-void v3_update_timers(struct guest_info * info);
+void v3_update_time(struct guest_info * info, ullong_t cycles);
 
 #endif
index b11fb7e..2f589e5 100644 (file)
@@ -29,56 +29,203 @@ struct channel {
 
   channel_op_mode_t op_mode;
 
+
+
   // Time til interrupt trigger 
-  ullong_t ns;
 
-  uint_t ctr;
-  uint_t prg_ctr;
+  ushort_t counter;
+  ushort_t reload_value;
+
+  uint_t output_pin : 1;
+  uint_t gate_input_pin : 1;
 };
 
 
 struct pit {
 
+  ullong_t pit_counter;
+  ullong_t pit_reload;
+
+
   struct channel ch_0;
   struct channel ch_1;
   struct channel ch_2;
 };
 
-struct pit_cmd {
-  uint_t channel     : 2;
-  uint_t access_mode : 2;
-  uint_t op_mode     : 3;
+
+struct pit_cmd_word {
   uint_t bcd_mode    : 1;
+  uint_t op_mode     : 3;
+  uint_t access_mode : 2;
+  uint_t channel     : 2;
+};
+
+struct pit_rdb_cmd_word {
+  uint_t rsvd         : 1; // SBZ
+  uint_t ch_0         : 1;
+  uint_t ch_1         : 1;
+  uint_t ch_2         : 1;
+  uint_t latch_status : 1;
+  uint_t latch_count  : 1;
+  uint_t readback_cmd : 2; // Must Be 0x3
 };
 
+struct pit_rdb_status_word {
+  uint_t bcd_mode     : 1;
+  uint_t op_mode      : 3;
+  uint_t access_mode  : 2;
+  uint_t null_count   : 1;
+  uint_t pin_state    : 1; 
+};
 
 
 
 
 
 static void pit_update_time(ullong_t cpu_cycles, ullong_t cpu_freq, void * private_data) {
-
+  PrintDebug("Adding %d cycles\n", cpu_cycles);
+  
   return;
 }
 
 
+static int handle_channel_write(struct channel * ch, char val) {
+  //  switch (ch->access_mode) {
+
+
+  //}
+
+
+  return -1;
+}
+
+
+static int handle_channel_read(struct channel * ch, char * val) {
+  return -1;
+}
+
+
+
+
+
+static int handle_channel_cmd(struct channel * ch, struct pit_cmd_word cmd) {
+  ch->op_mode = cmd.op_mode;
+  ch->access_mode = cmd.access_mode;
+
+  switch (cmd.access_mode) {
+  case LATCH_COUNT:
+    return -1;
+    break;
+  case HIBYTE_ONLY:
+    ch->access_state = WAITING_HIBYTE;
+    break;
+  case LOBYTE_ONLY: 
+  case LOBYTE_HIBYTE:
+    ch->access_state = WAITING_LOBYTE;
+    break;
+  }
+
+
+  switch (cmd.op_mode) {
+  case IRQ_ON_TERM_CNT:
+    ch->output_pin = 0;
+    break;
+  case ONE_SHOT: 
+    ch->output_pin = 1;
+    break;
+  case RATE_GEN: 
+    ch->output_pin = 1;
+    break;
+  default:
+    return -1;
+  }
+
+  return 0;
+    
+}
+
+
+
 
 static int pit_read_channel(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
+  struct pit * state = (struct pit *)dev->private_data;
+  char * val = (char *)dst;
+
+  if (length != 1) {
+    PrintDebug("8254 PIT: Invalid Read Write length \n");
+    return -1;
+  }
+
   PrintDebug("8254 PIT: Read of PIT Channel %d\n", port - CHANNEL0_PORT);
+
+  switch (port) {
+  case CHANNEL0_PORT: 
+    if (handle_channel_read(&(state->ch_0), val) == -1) {
+      return -1;
+    }
+    break;
+  case CHANNEL1_PORT:
+    if (handle_channel_read(&(state->ch_1), val) == -1) {
+      return -1;
+    }
+    break;
+  case CHANNEL2_PORT:
+    if (handle_channel_read(&(state->ch_2), val) == -1) {
+      return -1;
+    }
+    break;
+  default:
+    PrintDebug("8254 PIT: Read from invalid port (%d)\n", port);
+    return -1;
+  }
+
   return length;
 }
 
 
 
 static int pit_write_channel(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
+  struct pit * state = (struct pit *)dev->private_data;
+  char val = *(char *)src;
+
+  if (length != 1) {
+    PrintDebug("8254 PIT: Invalid Write Length\n");
+    return -1;
+  }
+
   PrintDebug("8254 PIT: Write to PIT Channel %d\n", port - CHANNEL0_PORT);
+
+
+  switch (port) {
+  case CHANNEL0_PORT:
+    if (handle_channel_write(&(state->ch_0), val) == -1) {
+      return -1;
+    } 
+    break;
+  case CHANNEL1_PORT:
+    if (handle_channel_write(&(state->ch_1), val) == -1) {
+      return -1;
+    }
+    break;
+  case CHANNEL2_PORT:
+    if (handle_channel_write(&(state->ch_2), val) == -1) {
+      return -1;
+    }
+    break;
+  default:
+    PrintDebug("8254 PIT: Write to invalid port (%d)\n", port);
+    return -1;
+  }
+
   return length;
 }
 
 
+
+
 static int pit_write_command(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
   struct pit * state = (struct pit *)dev->private_data;
-  struct pit_cmd * cmd = (struct pit_cmd *)src;
+  struct pit_cmd_word * cmd = (struct pit_cmd_word *)src;
 
   PrintDebug("8254 PIT: Write to PIT Command port\n");
 
@@ -89,11 +236,23 @@ static int pit_write_command(ushort_t port, void * src, uint_t length, struct vm
 
   switch (cmd->channel) {
   case 0:
-    state->ch_0.op_mode = cmd->op_mode;
+    if (handle_channel_cmd(&(state->ch_0), *cmd) == -1) {
+      return -1;
+    }
     break;
   case 1:
+    if (handle_channel_cmd(&(state->ch_1), *cmd) == -1) {
+      return -1;
+    }
     break;
   case 2:
+    if (handle_channel_cmd(&(state->ch_2), *cmd) == -1) {
+      return -1;
+    }
+    break;
+  case 3:
+    // Read Back command
+    return -1;
     break;
   default:
     break;
@@ -120,6 +279,9 @@ static int pit_init(struct vm_device * dev) {
 
   v3_add_timer(dev->vm, &timer_ops, dev);
 
+  // Get cpu frequency and calculate the global pit oscilattor counter/cycle
+
+
   return 0;
 }
 
index 86c9ebf..160be77 100644 (file)
@@ -318,7 +318,7 @@ int RunVMM(struct Boot_Info * bootInfo) {
        //struct vm_device * timer = create_timer();
        struct vm_device * pic = create_pic();
        //struct vm_device * keyboard = create_keyboard();
-       struct vm_device * pit= create_pit();
+       struct vm_device * pit = create_pit();
 
        attach_device(&(vm_info), nvram);
        //attach_device(&(vm_info), timer);
index c83e6d5..15ae589 100644 (file)
@@ -133,70 +133,3 @@ unsigned int get_cpu_khz() {
   return cpu_khz_freq;
 }
 
-
-
-
-#if 0
-
-
-/* ------ Calibrate the TSC ------- 
- * Return processor ticks per second / CALIBRATE_FRAC.
- *
- * Ported From Xen
- */
-#define PIT_MODE 0x43
-#define PIT_CH2 0x42
-#define CLOCK_TICK_RATE 1193180 /* system crystal frequency (Hz) */
-#define CALIBRATE_FRAC  20      /* calibrate over 50ms */
-#define CALIBRATE_LATCH ((CLOCK_TICK_RATE+(CALIBRATE_FRAC/2))/CALIBRATE_FRAC)
-
-
-unsigned long long get_cpu_khz() {
-    ullong_t start, end;
-    unsigned long count;
-    unsigned long long tmp;
-    unsigned long print_tmp; 
-
-    /* Set the Gate high, disable speaker */
-    VM_Out_Byte((VM_In_Byte(0x61) & ~0x02) | 0x01, 0x61);
-
-    /*
-     * Now let's take care of CTC channel 2
-     *
-     * Set the Gate high, program CTC channel 2 for mode 0, (interrupt on
-     * terminal count mode), binary count, load 5 * LATCH count, (LSB and MSB)
-     * to begin countdown.
-     */
-    VM_Out_Byte(0xb0, PIT_MODE);           /* binary, mode 0, LSB/MSB, Ch 2 */
-    VM_Out_Byte(CALIBRATE_LATCH & 0xff, PIT_CH2); /* LSB of count */
-    VM_Out_Byte(CALIBRATE_LATCH >> 8, PIT_CH2);   /* MSB of count */
-
-    rdtscll(start);
-    for ( count = 0; (VM_In_Byte(0x61) & 0x20) == 0; count++ )
-        continue;
-    rdtscll(end);
-
-    /* Error if the CTC doesn't behave itself. */
-    if ( count == 0 ) {
-     PrintBoth("CPU Frequency Calibration Error\n");
-      return 0;
-    }
-
-    tmp = ((end - start) * (ullong_t)CALIBRATE_FRAC);
-
-    do_div(tmp, 1000);
-
-    tmp &= 0xffffffff;
-    print_tmp = (unsigned long)tmp;
-
-   PrintBoth("Detected %lu.%lu MHz CPU\n", print_tmp / 1000, print_tmp % 1000);
-    return tmp;
-}
-
-#undef PIT_CH2
-#undef PIT_MODE
-#undef CLOCK_TICK_RATE
-#undef CALIBRATE_FRAC  
-#undef CALIBRATE_LATCH 
-
-#endif
index e62f5a7..cbed250 100644 (file)
@@ -29,76 +29,182 @@ extern uint_t Get_CR3();
 
 extern void DisableInts();
 
-/* Checks machine SVM capability */
-/* Implemented from: AMD Arch Manual 3, sect 15.4 */ 
-int is_svm_capable() {
-  uint_t ret =  cpuid_ecx(CPUID_FEATURE_IDS);
-  uint_t vm_cr_low = 0, vm_cr_high = 0;
 
 
-  if ((ret & CPUID_FEATURE_IDS_ecx_svm_avail) == 0) {
-    PrintDebug("SVM Not Available\n");
-    return 0;
-  } 
 
-  Get_MSR(SVM_VM_CR_MSR, &vm_cr_high, &vm_cr_low);
 
-  if ((ret & CPUID_SVM_REV_AND_FEATURE_IDS_edx_np) == 1) {
-    PrintDebug("Nested Paging not supported\n");
-  }
 
-  if ((vm_cr_low & SVM_VM_CR_MSR_svmdis) == 0) {
-    return 1;
-  }
 
-  ret = cpuid_edx(CPUID_SVM_REV_AND_FEATURE_IDS);
+static vmcb_t * Allocate_VMCB() {
+  vmcb_t * vmcb_page = (vmcb_t*)os_hooks->allocate_pages(1);
 
-  if ((ret & CPUID_SVM_REV_AND_FEATURE_IDS_edx_svml) == 0) {
-    PrintDebug("SVM BIOS Disabled, not unlockable\n");
-  } else {
-    PrintDebug("SVM is locked with a key\n");
-  }
 
-  return 0;
+  memset(vmcb_page, 0, 4096);
+
+  return vmcb_page;
 }
 
 
 
-void Init_SVM(struct vmm_ctrl_ops * vmm_ops) {
-  reg_ex_t msr;
-  void * host_state;
 
 
-  // Enable SVM on the CPU
-  Get_MSR(EFER_MSR, &(msr.e_reg.high), &(msr.e_reg.low));
-  msr.e_reg.low |= EFER_MSR_svm_enable;
-  Set_MSR(EFER_MSR, 0, msr.e_reg.low);
-  
-  PrintDebug("SVM Enabled\n");
+static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) {
+  vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
+  vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
+  uint_t i;
 
 
-  // Setup the host state save area
-  host_state = os_hooks->allocate_pages(4);
+  guest_state->rsp = vm_info.vm_regs.rsp;
+  // guest_state->rip = vm_info.rip;
+  guest_state->rip = 0xfff0;
+
+  guest_state->cpl = 0;
+
+  //ctrl_area->instrs.instrs.CR0 = 1;
+  ctrl_area->cr_reads.cr0 = 1;
+  ctrl_area->cr_writes.cr0 = 1;
+
+  guest_state->efer |= EFER_MSR_svm_enable;
+  guest_state->rflags = 0x00000002; // The reserved bit is always 1
+  ctrl_area->svm_instrs.VMRUN = 1;
+  ctrl_area->instrs.HLT = 1;
+  // guest_state->cr0 = 0x00000001;    // PE 
+  ctrl_area->guest_ASID = 1;
+
+  ctrl_area->exceptions.de = 1;
+  ctrl_area->exceptions.df = 1;
+  ctrl_area->exceptions.pf = 1;
+  ctrl_area->exceptions.ts = 1;
+  ctrl_area->exceptions.ss = 1;
+  ctrl_area->exceptions.ac = 1;
+  ctrl_area->exceptions.mc = 1;
+  ctrl_area->exceptions.gp = 1;
+  ctrl_area->exceptions.ud = 1;
+  ctrl_area->exceptions.np = 1;
+  ctrl_area->exceptions.of = 1;
+  ctrl_area->exceptions.nmi = 1;
+
+  vm_info.vm_regs.rdx = 0x00000f00;
+
+  guest_state->cr0 = 0x60000010;
+
+  guest_state->cs.selector = 0xf000;
+  guest_state->cs.limit=0xffff;
+  guest_state->cs.base = 0x0000000f0000LL;
+  guest_state->cs.attrib.raw = 0xf3;
+
   
-  msr.e_reg.high = 0;
-  msr.e_reg.low = (uint_t)host_state;
+  struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
+  for ( i = 0; segregs[i] != NULL; i++) {
+    struct vmcb_selector * seg = segregs[i];
+    
+    seg->selector = 0x0000;
+    //    seg->base = seg->selector << 4;
+    seg->base = 0x00000000;
+    seg->attrib.raw = 0xf3;
+    seg->limit = ~0u;
+  }
+  
+  guest_state->gdtr.limit = 0x0000ffff;
+  guest_state->gdtr.base = 0x0000000000000000LL;
+  guest_state->idtr.limit = 0x0000ffff;
+  guest_state->idtr.base = 0x0000000000000000LL;
+
+  guest_state->ldtr.selector = 0x0000;
+  guest_state->ldtr.limit = 0x0000ffff;
+  guest_state->ldtr.base = 0x0000000000000000LL;
+  guest_state->tr.selector = 0x0000;
+  guest_state->tr.limit = 0x0000ffff;
+  guest_state->tr.base = 0x0000000000000000LL;
 
 
-  PrintDebug("Host State being saved at %x\n", (uint_t)host_state);
-  Set_MSR(SVM_VM_HSAVE_PA_MSR, msr.e_reg.high, msr.e_reg.low);
+  guest_state->dr6 = 0x00000000ffff0ff0LL;
+  guest_state->dr7 = 0x0000000000000400LL;
 
+  if (vm_info.io_map.num_ports > 0) {
+    vmm_io_hook_t * iter;
+    addr_t io_port_bitmap;
+    
+    io_port_bitmap = (addr_t)os_hooks->allocate_pages(3);
+    memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3);
+    
+    ctrl_area->IOPM_BASE_PA = io_port_bitmap;
 
+    //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap);
+
+    FOREACH_IO_HOOK(vm_info.io_map, iter) {
+      ushort_t port = iter->port;
+      uchar_t * bitmap = (uchar_t *)io_port_bitmap;
+
+      bitmap += (port / 8);
+      PrintDebug("Setting Bit for port 0x%x\n", port);
+      *bitmap |= 1 << (port % 8);
+    }
+
+
+    //PrintDebugMemDump((uchar_t*)io_port_bitmap, PAGE_SIZE *2);
+
+    ctrl_area->instrs.IOIO_PROT = 1;
+  }
+
+
+
+  PrintDebug("Exiting on interrupts\n");
+  ctrl_area->guest_ctrl.V_INTR_MASKING = 1;
+  ctrl_area->instrs.INTR = 1;
+
+
+  if (vm_info.page_mode == SHADOW_PAGING) {
+    PrintDebug("Creating initial shadow page table\n");
+    vm_info.shdw_pg_state.shadow_cr3 |= ((addr_t)create_passthrough_pde32_pts(&vm_info) & ~0xfff);
+    PrintDebug("Created\n");
+
+    guest_state->cr3 = vm_info.shdw_pg_state.shadow_cr3;
+
+    //PrintDebugPageTables((pde32_t*)(vm_info.shdw_pg_state.shadow_cr3.e_reg.low));
+
+    ctrl_area->cr_reads.cr3 = 1;
+    ctrl_area->cr_writes.cr3 = 1;
+
+
+    ctrl_area->instrs.INVLPG = 1;
+    ctrl_area->instrs.INVLPGA = 1;
+
+    guest_state->g_pat = 0x7040600070406ULL;
+
+    guest_state->cr0 |= 0x80000000;
+  } else if (vm_info.page_mode == NESTED_PAGING) {
+    // Flush the TLB on entries/exits
+    //ctrl_area->TLB_CONTROL = 1;
+
+    // Enable Nested Paging
+    //ctrl_area->NP_ENABLE = 1;
+
+    //PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE));
+
+        // Set the Nested Page Table pointer
+    //    ctrl_area->N_CR3 = ((addr_t)vm_info.page_tables);
+    // ctrl_area->N_CR3 = (addr_t)(vm_info.page_tables);
+
+    //   ctrl_area->N_CR3 = Get_CR3();
+    // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
+
+    //    guest_state->g_pat = 0x7040600070406ULL;
+  }
 
-  // Setup the SVM specific vmm operations
-  vmm_ops->init_guest = &init_svm_guest;
-  vmm_ops->start_guest = &start_svm_guest;
 
 
-  return;
 }
 
 
-int init_svm_guest(struct guest_info *info) {
+
+
+
+
+
+
+
+static int init_svm_guest(struct guest_info *info) {
  
   PrintDebug("Allocating VMCB\n");
   info->vmm_data = (void*)Allocate_VMCB();
@@ -131,7 +237,7 @@ int init_svm_guest(struct guest_info *info) {
 
 
 // can we start a kernel thread here...
-int start_svm_guest(struct guest_info *info) {
+static int start_svm_guest(struct guest_info *info) {
   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
   vmcb_ctrl_t * guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
 
@@ -141,18 +247,19 @@ int start_svm_guest(struct guest_info *info) {
   while (1) {
     ullong_t tmp_tsc;
 
+
     CLGI();
 
     rdtscll(info->time_state.cached_host_tsc);
     guest_ctrl->TSC_OFFSET = info->time_state.guest_tsc - info->time_state.cached_host_tsc;
-    //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");
+
     rdtscll(tmp_tsc);
-    info->time_state.guest_tsc += tmp_tsc - info->time_state.cached_host_tsc;
-    
+
+    //PrintDebug("SVM Returned\n");
+
+    v3_update_time(info, tmp_tsc - info->time_state.cached_host_tsc);
 
     STGI();
 
@@ -188,150 +295,135 @@ int start_svm_guest(struct guest_info *info) {
 
 
 
-vmcb_t * Allocate_VMCB() {
-  vmcb_t * vmcb_page = (vmcb_t*)os_hooks->allocate_pages(1);
-
 
-  memset(vmcb_page, 0, 4096);
+/* Checks machine SVM capability */
+/* Implemented from: AMD Arch Manual 3, sect 15.4 */ 
+int is_svm_capable() {
+  uint_t ret =  cpuid_ecx(CPUID_FEATURE_IDS);
+  uint_t vm_cr_low = 0, vm_cr_high = 0;
 
-  return vmcb_page;
-}
 
+  if ((ret & CPUID_FEATURE_IDS_ecx_svm_avail) == 0) {
+    PrintDebug("SVM Not Available\n");
+    return 0;
+  } 
 
+  Get_MSR(SVM_VM_CR_MSR, &vm_cr_high, &vm_cr_low);
 
-void Init_VMCB(vmcb_t * vmcb, struct guest_info vm_info) {
-  vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
-  vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
-  uint_t i;
+  if ((ret & CPUID_SVM_REV_AND_FEATURE_IDS_edx_np) == 1) {
+    PrintDebug("Nested Paging not supported\n");
+  }
 
+  if ((vm_cr_low & SVM_VM_CR_MSR_svmdis) == 0) {
+    return 1;
+  }
 
-  guest_state->rsp = vm_info.vm_regs.rsp;
-  guest_state->rip = vm_info.rip;
+  ret = cpuid_edx(CPUID_SVM_REV_AND_FEATURE_IDS);
 
+  if ((ret & CPUID_SVM_REV_AND_FEATURE_IDS_edx_svml) == 0) {
+    PrintDebug("SVM BIOS Disabled, not unlockable\n");
+  } else {
+    PrintDebug("SVM is locked with a key\n");
+  }
 
-  //ctrl_area->instrs.instrs.CR0 = 1;
-  ctrl_area->cr_reads.cr0 = 1;
-  ctrl_area->cr_writes.cr0 = 1;
+  return 0;
+}
 
-  guest_state->efer |= EFER_MSR_svm_enable;
-  guest_state->rflags = 0x00000002; // The reserved bit is always 1
-  ctrl_area->svm_instrs.VMRUN = 1;
-  // guest_state->cr0 = 0x00000001;    // PE 
-  ctrl_area->guest_ASID = 1;
 
 
-  ctrl_area->exceptions.de = 1;
-  ctrl_area->exceptions.df = 1;
-  ctrl_area->exceptions.pf = 1;
-  ctrl_area->exceptions.ts = 1;
-  ctrl_area->exceptions.ss = 1;
-  ctrl_area->exceptions.ac = 1;
-  ctrl_area->exceptions.mc = 1;
-  ctrl_area->exceptions.gp = 1;
-  ctrl_area->exceptions.ud = 1;
-  ctrl_area->exceptions.np = 1;
-  ctrl_area->exceptions.of = 1;
-  ctrl_area->exceptions.nmi = 1;
+void Init_SVM(struct vmm_ctrl_ops * vmm_ops) {
+  reg_ex_t msr;
+  void * host_state;
 
-  guest_state->cs.selector = 0x0000;
-  guest_state->cs.limit=~0u;
-  guest_state->cs.base = guest_state->cs.selector<<4;
-  guest_state->cs.attrib.raw = 0xf3;
 
+  // Enable SVM on the CPU
+  Get_MSR(EFER_MSR, &(msr.e_reg.high), &(msr.e_reg.low));
+  msr.e_reg.low |= EFER_MSR_svm_enable;
+  Set_MSR(EFER_MSR, 0, msr.e_reg.low);
   
-  struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
-  for ( i = 0; segregs[i] != NULL; i++) {
-    struct vmcb_selector * seg = segregs[i];
-    
-    seg->selector = 0x0000;
-    seg->base = seg->selector << 4;
-    seg->attrib.raw = 0xf3;
-    seg->limit = ~0u;
-  }
+  PrintDebug("SVM Enabled\n");
+
+
+  // Setup the host state save area
+  host_state = os_hooks->allocate_pages(4);
   
-  if (vm_info.io_map.num_ports > 0) {
-    vmm_io_hook_t * iter;
-    addr_t io_port_bitmap;
-    
-    io_port_bitmap = (addr_t)os_hooks->allocate_pages(3);
-    memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3);
-    
-    ctrl_area->IOPM_BASE_PA = io_port_bitmap;
+  msr.e_reg.high = 0;
+  msr.e_reg.low = (uint_t)host_state;
 
-    //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap);
 
-    FOREACH_IO_HOOK(vm_info.io_map, iter) {
-      ushort_t port = iter->port;
-      uchar_t * bitmap = (uchar_t *)io_port_bitmap;
+  PrintDebug("Host State being saved at %x\n", (uint_t)host_state);
+  Set_MSR(SVM_VM_HSAVE_PA_MSR, msr.e_reg.high, msr.e_reg.low);
 
-      bitmap += (port / 8);
-      PrintDebug("Setting Bit in block %x\n", bitmap);
-      *bitmap |= 1 << (port % 8);
-    }
 
 
-    //PrintDebugMemDump((uchar_t*)io_port_bitmap, PAGE_SIZE *2);
+  // Setup the SVM specific vmm operations
+  vmm_ops->init_guest = &init_svm_guest;
+  vmm_ops->start_guest = &start_svm_guest;
 
-    ctrl_area->instrs.IOIO_PROT = 1;
-  }
 
-  ctrl_area->instrs.INTR = 1;
+  return;
+}
+
 
 
 
-  if (vm_info.page_mode == SHADOW_PAGING) {
-    PrintDebug("Creating initial shadow page table\n");
-    vm_info.shdw_pg_state.shadow_cr3 |= ((addr_t)create_passthrough_pde32_pts(&vm_info) & ~0xfff);
-    PrintDebug("Created\n");
 
-    guest_state->cr3 = vm_info.shdw_pg_state.shadow_cr3;
 
-    ctrl_area->cr_reads.cr3 = 1;
-    ctrl_area->cr_writes.cr3 = 1;
 
 
-    ctrl_area->instrs.INVLPG = 1;
-    ctrl_area->instrs.INVLPGA = 1;
 
-    guest_state->g_pat = 0x7040600070406ULL;
 
-    guest_state->cr0 |= 0x80000000;
-  } else if (vm_info.page_mode == NESTED_PAGING) {
-    // Flush the TLB on entries/exits
-    //ctrl_area->TLB_CONTROL = 1;
 
-    // Enable Nested Paging
-    //ctrl_area->NP_ENABLE = 1;
 
-    //PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE));
 
-        // Set the Nested Page Table pointer
-    //    ctrl_area->N_CR3 = ((addr_t)vm_info.page_tables);
-    // ctrl_area->N_CR3 = (addr_t)(vm_info.page_tables);
 
-    //   ctrl_area->N_CR3 = Get_CR3();
-    // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
 
-    //    guest_state->g_pat = 0x7040600070406ULL;
-  }
 
 
 
-}
 
 
 
-void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*static void Init_VMCB(vmcb_t * vmcb, struct guest_info vm_info) {
   vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
   vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
   uint_t i;
 
 
   guest_state->rsp = vm_info.vm_regs.rsp;
-  // guest_state->rip = vm_info.rip;
-  guest_state->rip = 0xfff0;
+  guest_state->rip = vm_info.rip;
 
-  guest_state->cpl = 0;
 
   //ctrl_area->instrs.instrs.CR0 = 1;
   ctrl_area->cr_reads.cr0 = 1;
@@ -340,10 +432,10 @@ void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) {
   guest_state->efer |= EFER_MSR_svm_enable;
   guest_state->rflags = 0x00000002; // The reserved bit is always 1
   ctrl_area->svm_instrs.VMRUN = 1;
-  ctrl_area->instrs.HLT = 1;
   // guest_state->cr0 = 0x00000001;    // PE 
   ctrl_area->guest_ASID = 1;
 
+
   ctrl_area->exceptions.de = 1;
   ctrl_area->exceptions.df = 1;
   ctrl_area->exceptions.pf = 1;
@@ -357,13 +449,9 @@ void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) {
   ctrl_area->exceptions.of = 1;
   ctrl_area->exceptions.nmi = 1;
 
-  vm_info.vm_regs.rdx = 0x00000f00;
-
-  guest_state->cr0 = 0x60000010;
-
-  guest_state->cs.selector = 0xf000;
-  guest_state->cs.limit=0xffff;
-  guest_state->cs.base = 0x0000000f0000LL;
+  guest_state->cs.selector = 0x0000;
+  guest_state->cs.limit=~0u;
+  guest_state->cs.base = guest_state->cs.selector<<4;
   guest_state->cs.attrib.raw = 0xf3;
 
   
@@ -372,28 +460,11 @@ void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) {
     struct vmcb_selector * seg = segregs[i];
     
     seg->selector = 0x0000;
-    //    seg->base = seg->selector << 4;
-    seg->base = 0x00000000;
+    seg->base = seg->selector << 4;
     seg->attrib.raw = 0xf3;
     seg->limit = ~0u;
   }
   
-  guest_state->gdtr.limit = 0x0000ffff;
-  guest_state->gdtr.base = 0x0000000000000000LL;
-  guest_state->idtr.limit = 0x0000ffff;
-  guest_state->idtr.base = 0x0000000000000000LL;
-
-  guest_state->ldtr.selector = 0x0000;
-  guest_state->ldtr.limit = 0x0000ffff;
-  guest_state->ldtr.base = 0x0000000000000000LL;
-  guest_state->tr.selector = 0x0000;
-  guest_state->tr.limit = 0x0000ffff;
-  guest_state->tr.base = 0x0000000000000000LL;
-
-
-  guest_state->dr6 = 0x00000000ffff0ff0LL;
-  guest_state->dr7 = 0x0000000000000400LL;
-
   if (vm_info.io_map.num_ports > 0) {
     vmm_io_hook_t * iter;
     addr_t io_port_bitmap;
@@ -410,7 +481,7 @@ void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) {
       uchar_t * bitmap = (uchar_t *)io_port_bitmap;
 
       bitmap += (port / 8);
-      PrintDebug("Setting Bit for port 0x%x\n", port);
+      PrintDebug("Setting Bit in block %x\n", bitmap);
       *bitmap |= 1 << (port % 8);
     }
 
@@ -420,13 +491,10 @@ void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) {
     ctrl_area->instrs.IOIO_PROT = 1;
   }
 
-
-
-  PrintDebug("Exiting on interrupts\n");
-  ctrl_area->guest_ctrl.V_INTR_MASKING = 1;
   ctrl_area->instrs.INTR = 1;
 
 
+
   if (vm_info.page_mode == SHADOW_PAGING) {
     PrintDebug("Creating initial shadow page table\n");
     vm_info.shdw_pg_state.shadow_cr3 |= ((addr_t)create_passthrough_pde32_pts(&vm_info) & ~0xfff);
@@ -434,8 +502,6 @@ void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) {
 
     guest_state->cr3 = vm_info.shdw_pg_state.shadow_cr3;
 
-    //PrintDebugPageTables((pde32_t*)(vm_info.shdw_pg_state.shadow_cr3.e_reg.low));
-
     ctrl_area->cr_reads.cr3 = 1;
     ctrl_area->cr_writes.cr3 = 1;
 
@@ -468,6 +534,12 @@ void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) {
 
 
 }
+*/
+
+
+
+
+
 
 
 #if 0
@@ -637,157 +709,3 @@ void Init_VMCB_pe(vmcb_t *vmcb, struct guest_info vm_info) {
 #endif
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-/*
-
-
-void Init_VMCB_Real(vmcb_t * vmcb, struct guest_info vm_info) {
-  vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
-  vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb);
-  uint_t i;
-
-
-  guest_state->rsp = vm_info.vm_regs.rsp;
-  guest_state->rip = vm_info.rip;
-
-
-  guest_state->efer |= EFER_MSR_svm_enable;
-  guest_state->rflags = 0x00000002; // The reserved bit is always 1
-  ctrl_area->svm_instrs.instrs.VMRUN = 1;
-  ctrl_area->guest_ASID = 1;
-  guest_state->cr0 = 0x60000010;
-
-
-  ctrl_area->exceptions.de = 1;
-  ctrl_area->exceptions.df = 1;
-  ctrl_area->exceptions.pf = 1;
-  ctrl_area->exceptions.ts = 1;
-  ctrl_area->exceptions.ss = 1;
-  ctrl_area->exceptions.ac = 1;
-  ctrl_area->exceptions.mc = 1;
-  ctrl_area->exceptions.gp = 1;
-  ctrl_area->exceptions.ud = 1;
-  ctrl_area->exceptions.np = 1;
-  ctrl_area->exceptions.of = 1;
-  ctrl_area->exceptions.nmi = 1;
-
-  guest_state->cs.selector = 0xf000;
-  guest_state->cs.limit=0xffff;
-  guest_state->cs.base =  0xffff0000;
-  guest_state->cs.attrib.raw = 0x9a;
-
-  
-  struct vmcb_selector *segregs [] = {&(guest_state->ss), &(guest_state->ds), &(guest_state->es), &(guest_state->fs), &(guest_state->gs), NULL};
-  for ( i = 0; segregs[i] != NULL; i++) {
-    struct vmcb_selector * seg = segregs[i];
-    
-    seg->selector = 0x0000;
-    seg->base = 0xffff0000;
-    seg->attrib.raw = 0x9b;
-    seg->limit = 0xffff;
-  }
-  
-  // Set GPRs 
-  //
-  //  EDX == 0xfxx
-  //  EAX, EBX, ECX, ESI, EDI, EBP, ESP == 0x0
-  //
-
-  guest_state->gdtr.base = 0;
-  guest_state->gdtr.limit = 0xffff;
-  guest_state->gdtr.attrib.raw = 0x0;
-
-  guest_state->idtr.base = 0;
-  guest_state->idtr.limit = 0xffff;
-  guest_state->idtr.attrib.raw = 0x0;
-
-  guest_state->ldtr.base = 0;
-  guest_state->ldtr.limit = 0xffff;
-  guest_state->ldtr.attrib.raw = 0x82;
-
-  guest_state->tr.base = 0;
-  guest_state->tr.limit = 0xffff;
-  guest_state->tr.attrib.raw = 0x83;
-
-
-
-
-  if (vm_info.io_map.num_ports > 0) {
-    vmm_io_hook_t * iter;
-    addr_t io_port_bitmap;
-    
-    io_port_bitmap = (addr_t)os_hooks->allocate_pages(3);
-    memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3);
-    
-    ctrl_area->IOPM_BASE_PA = io_port_bitmap;
-
-    //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap);
-
-    FOREACH_IO_HOOK(vm_info.io_map, iter) {
-      ushort_t port = iter->port;
-      uchar_t * bitmap = (uchar_t *)io_port_bitmap;
-
-      bitmap += (port / 8);
-      PrintDebug("Setting Bit in block %x\n", bitmap);
-      *bitmap |= 1 << (port % 8);
-    }
-
-    ctrl_area->instrs.instrs.IOIO_PROT = 1;
-  }
-
-  ctrl_area->instrs.instrs.INTR = 1;
-
-  // also determine if CPU supports nested paging
-
-  if (vm_info.page_mode == SHADOW_PAGING) {
-    PrintDebug("Creating initial shadow page table\n");
-    vm_info.shdw_pg_state.shadow_cr3.e_reg.low |= ((addr_t)create_passthrough_pde32_pts(&vm_info) & ~0xfff);
-    PrintDebug("Created\n");
-
-    guest_state->cr3 = vm_info.shdw_pg_state.shadow_cr3.r_reg;
-
-    ctrl_area->cr_reads.crs.cr3 = 1;
-    ctrl_area->cr_writes.crs.cr3 = 1;
-    ctrl_area->cr_reads.crs.cr0 = 1;
-    ctrl_area->cr_writes.crs.cr0 = 1;
-
-    ctrl_area->instrs.instrs.INVLPG = 1;
-    ctrl_area->instrs.instrs.INVLPGA = 1;
-
-       
-    guest_state->g_pat = 0x7040600070406ULL;
-
-    vm_info.shdw_pg_state.guest_cr0.e_reg.low = guest_state->cr0;
-    guest_state->cr0 |= 0x80000000;
-  } else if (vm_info.page_mode == NESTED_PAGING) {
-    // Flush the TLB on entries/exits
-    //ctrl_area->TLB_CONTROL = 1;
-
-    // Enable Nested Paging
-    //ctrl_area->NP_ENABLE = 1;
-
-    //PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE));
-
-        // Set the Nested Page Table pointer
-    //    ctrl_area->N_CR3 = ((addr_t)vm_info.page_tables);
-    // ctrl_area->N_CR3 = (addr_t)(vm_info.page_tables);
-
-    //   ctrl_area->N_CR3 = Get_CR3();
-    // guest_state->cr3 |= (Get_CR3() & 0xfffff000);
-
-    //    guest_state->g_pat = 0x7040600070406ULL;
-  }
-
-}
-*/
index 027236d..a7cd626 100644 (file)
@@ -12,7 +12,7 @@ void v3_init_time(struct vm_time * time_state) {
  
   time_state->guest_tsc = 0;
   time_state->cached_host_tsc = 0;
-  time_state->pending_cycles = 0;
+  // time_state->pending_cycles = 0;
   
   INIT_LIST_HEAD(&(time_state->timers));
   time_state->num_timers = 0;
@@ -20,30 +20,40 @@ void v3_init_time(struct vm_time * time_state) {
 
 
 int v3_add_timer(struct guest_info * info, struct vm_timer_ops * ops, void * private_data) {
-  //  V3_Malloc
+  struct vm_timer * timer = NULL;
+  timer = (struct vm_timer *)V3_Malloc(sizeof(struct vm_timer));
+  V3_ASSERT(timer != NULL);
+
+  timer->ops = ops;
+  timer->private_data = private_data;
 
-  /*
   list_add(&(timer->timer_link), &(info->time_state.timers));
   info->time_state.num_timers++;
-  */
+
   return 0;
 }
 
-int remove_timer(struct guest_info * info, struct vm_timer * timer) {
+
+int v3_remove_timer(struct guest_info * info, struct vm_timer * timer) {
   list_del(&(timer->timer_link));
   info->time_state.num_timers--;
 
+  V3_Free(timer);
   return 0;
 }
 
 
-void update_timers(struct guest_info * info) {
+
+void v3_update_time(struct guest_info * info, ullong_t cycles) {
   struct vm_timer * tmp_timer;
   
+  info->time_state.guest_tsc += cycles;
+
   list_for_each_entry(tmp_timer, &(info->time_state.timers), timer_link) {
-    tmp_timer->ops.update_time(info->time_state.pending_cycles, info->time_state.cpu_freq, tmp_timer->private_data);
+    tmp_timer->ops->update_time(cycles, info->time_state.cpu_freq, tmp_timer->private_data);
   }
+  
 
 
-  info->time_state.pending_cycles = 0;
+  //info->time_state.pending_cycles = 0;
 }