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.


Explictly tags in saves for PIT, APIC, IOAPIC, SVM, and CORE
[palacios.git] / palacios / src / palacios / svm.c
index 3db11ce..99d12d3 100644 (file)
@@ -243,8 +243,20 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * core) {
     PrintDebug("Exiting on interrupts\n");
     ctrl_area->guest_ctrl.V_INTR_MASKING = 1;
     ctrl_area->instrs.INTR = 1;
+    // The above also assures the TPR changes (CR8) are only virtual
 
 
+    // However, we need to see TPR writes since they will
+    // affect the virtual apic
+    // we reflect out cr8 to ctrl_regs->apic_tpr
+    ctrl_area->cr_reads.cr8 = 1;
+    ctrl_area->cr_writes.cr8 = 1;
+    // We will do all TPR comparisons in the virtual apic
+    // We also do not want the V_TPR to be able to mask the PIC
+    ctrl_area->guest_ctrl.V_IGN_TPR = 1;
+
+    
+
     v3_hook_msr(core->vm_info, EFER_MSR, 
                &v3_handle_efer_read,
                &v3_svm_handle_efer_write, 
@@ -279,7 +291,6 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * core) {
        ctrl_area->cr_writes.cr3 = 1;
 
 
-
        ctrl_area->instrs.INVLPG = 1;
 
        ctrl_area->exceptions.pf = 1;
@@ -287,7 +298,6 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * core) {
        guest_state->g_pat = 0x7040600070406ULL;
 
 
-
     } else if (core->shdw_pg_mode == NESTED_PAGING) {
        // Flush the TLB on entries/exits
        ctrl_area->TLB_CONTROL = 1;
@@ -372,31 +382,62 @@ int v3_deinit_svm_vmcb(struct guest_info * core) {
 #ifdef V3_CONFIG_CHECKPOINT
 int v3_svm_save_core(struct guest_info * core, void * ctx){
 
-    if (v3_chkpt_save_8(ctx, "cpl", &(core->cpl)) == -1) { 
-       PrintError("Could not save SVM cpl\n");
-       return -1;
-    }
+  vmcb_saved_state_t * guest_area = GET_VMCB_SAVE_STATE_AREA(core->vmm_data); 
+
+  // Special case saves of data we need immediate access to
+  // in some cases
+  V3_CHKPT_SAVE(ctx, "CPL", core->cpl, failout);
+  V3_CHKPT_SAVE(ctx,"STAR", guest_area->star, failout); 
+  V3_CHKPT_SAVE(ctx,"CSTAR", guest_area->cstar, failout); 
+  V3_CHKPT_SAVE(ctx,"LSTAR", guest_area->lstar, failout); 
+  V3_CHKPT_SAVE(ctx,"SFMASK", guest_area->sfmask, failout); 
+  V3_CHKPT_SAVE(ctx,"KERNELGSBASE", guest_area->KernelGsBase, failout); 
+  V3_CHKPT_SAVE(ctx,"SYSENTER_CS", guest_area->sysenter_cs, failout); 
+  V3_CHKPT_SAVE(ctx,"SYSENTER_ESP", guest_area->sysenter_esp, failout); 
+  V3_CHKPT_SAVE(ctx,"SYSENTER_EIP", guest_area->sysenter_eip, failout); 
+  
+// and then we save the whole enchilada
+  if (v3_chkpt_save(ctx, "VMCB_DATA", PAGE_SIZE, core->vmm_data)) { 
+    PrintError("Could not save SVM vmcb\n");
+    goto failout;
+  }
+  
+  return 0;
 
-    if (v3_chkpt_save(ctx, "vmcb_data", PAGE_SIZE, core->vmm_data) == -1) { 
-       PrintError("Could not save SVM vmcb\n");
-       return -1;
-    }
+ failout:
+  PrintError("Failed to save SVM state for core\n");
+  return -1;
 
-    return 0;
 }
 
 int v3_svm_load_core(struct guest_info * core, void * ctx){
     
-    if (v3_chkpt_load_8(ctx, "cpl", &(core->cpl)) == -1) { 
-       PrintError("Could not load SVM cpl\n");
-       return -1;
-    }
 
-    if (v3_chkpt_load(ctx, "vmcb_data", PAGE_SIZE, core->vmm_data) == -1) {
-       return -1;
-    }
+  vmcb_saved_state_t * guest_area = GET_VMCB_SAVE_STATE_AREA(core->vmm_data); 
+
+  // Reload what we special cased, which we will overwrite in a minute
+  V3_CHKPT_LOAD(ctx, "CPL", core->cpl, failout);
+  V3_CHKPT_LOAD(ctx,"STAR", guest_area->star, failout); 
+  V3_CHKPT_LOAD(ctx,"CSTAR", guest_area->cstar, failout); 
+  V3_CHKPT_LOAD(ctx,"LSTAR", guest_area->lstar, failout); 
+  V3_CHKPT_LOAD(ctx,"SFMASK", guest_area->sfmask, failout); 
+  V3_CHKPT_LOAD(ctx,"KERNELGSBASE", guest_area->KernelGsBase, failout); 
+  V3_CHKPT_LOAD(ctx,"SYSENTER_CS", guest_area->sysenter_cs, failout); 
+  V3_CHKPT_LOAD(ctx,"SYSENTER_ESP", guest_area->sysenter_esp, failout); 
+  V3_CHKPT_LOAD(ctx,"SYSENTER_EIP", guest_area->sysenter_eip, failout); 
+  
+  // and then we load the whole enchilada
+  if (v3_chkpt_load(ctx, "VMCB_DATA", PAGE_SIZE, core->vmm_data)) { 
+    PrintError("Could not load SVM vmcb\n");
+    goto failout;
+  }
+  
+  return 0;
+
+ failout:
+  PrintError("Failed to save SVM state for core\n");
+  return -1;
 
-    return 0;
 }
 #endif
 
@@ -477,8 +518,11 @@ static int update_irq_entry_state(struct guest_info * info) {
 #endif
        guest_ctrl->guest_ctrl.V_IRQ = 1;
        guest_ctrl->guest_ctrl.V_INTR_VECTOR = info->intr_core_state.irq_vector;
+
+       // We ignore the virtual TPR on this injection
+       // TPR/PPR tests have already been done in the APIC.
        guest_ctrl->guest_ctrl.V_IGN_TPR = 1;
-       guest_ctrl->guest_ctrl.V_INTR_PRIO = 0xf;
+       guest_ctrl->guest_ctrl.V_INTR_PRIO = info->intr_core_state.irq_vector >> 4 ;  // 0xf;
 
     } else {
        switch (v3_intr_pending(info)) {
@@ -487,8 +531,11 @@ static int update_irq_entry_state(struct guest_info * info) {
 
                guest_ctrl->guest_ctrl.V_IRQ = 1;
                guest_ctrl->guest_ctrl.V_INTR_VECTOR = irq;
+
+               // We ignore the virtual TPR on this injection
+               // TPR/PPR tests have already been done in the APIC.
                guest_ctrl->guest_ctrl.V_IGN_TPR = 1;
-               guest_ctrl->guest_ctrl.V_INTR_PRIO = 0xf;
+               guest_ctrl->guest_ctrl.V_INTR_PRIO = info->intr_core_state.irq_vector >> 4 ;  // 0xf;
 
 #ifdef V3_CONFIG_DEBUG_INTERRUPTS
                PrintDebug("Injecting Interrupt %d (EIP=%p)\n", 
@@ -537,7 +584,14 @@ int
 v3_svm_config_tsc_virtualization(struct guest_info * info) {
     vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
 
-    if (!(info->time_state.flags & VM_TIME_TRAP_RDTSC)) {
+
+    if (info->time_state.flags & VM_TIME_TRAP_RDTSC) {
+       ctrl_area->instrs.RDTSC = 1;
+       ctrl_area->svm_instrs.RDTSCP = 1;
+    } else {
+       ctrl_area->instrs.RDTSC = 0;
+       ctrl_area->svm_instrs.RDTSCP = 0;
+
        if (info->time_state.flags & VM_TIME_TSC_PASSTHROUGH) {
                ctrl_area->TSC_OFFSET = 0;
        } else {
@@ -580,7 +634,17 @@ int v3_svm_enter(struct guest_info * info) {
     guest_state->cr4 = info->ctrl_regs.cr4;
     guest_state->dr6 = info->dbg_regs.dr6;
     guest_state->dr7 = info->dbg_regs.dr7;
-    guest_ctrl->guest_ctrl.V_TPR = info->ctrl_regs.cr8 & 0xff;
+
+    // CR8 is now updated by read/writes and it contains the APIC TPR
+    // the V_TPR should be just the class part of that.
+    // This update is here just for completeness.  We currently
+    // are ignoring V_TPR on all injections and doing the priority logivc
+    // in the APIC.
+    // guest_ctrl->guest_ctrl.V_TPR = ((info->ctrl_regs.apic_tpr) >> 4) & 0xf;
+
+    //guest_ctrl->guest_ctrl.V_TPR = info->ctrl_regs.cr8 & 0xff;
+    // 
+    
     guest_state->rflags = info->ctrl_regs.rflags;
     guest_state->efer = info->ctrl_regs.efer;
     
@@ -661,7 +725,11 @@ int v3_svm_enter(struct guest_info * info) {
     info->ctrl_regs.cr4 = guest_state->cr4;
     info->dbg_regs.dr6 = guest_state->dr6;
     info->dbg_regs.dr7 = guest_state->dr7;
-    info->ctrl_regs.cr8 = guest_ctrl->guest_ctrl.V_TPR;
+    //
+    // We do not track this anymore
+    // V_TPR is ignored and we do the logic in the APIC
+    //info->ctrl_regs.cr8 = guest_ctrl->guest_ctrl.V_TPR;
+    //
     info->ctrl_regs.rflags = guest_state->rflags;
     info->ctrl_regs.efer = guest_state->efer;