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.


Time configuration parameters added. More time control code prototyped,
[palacios.git] / palacios / src / palacios / svm.c
index 50d2b85..dc2b660 100644 (file)
@@ -113,7 +113,7 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * core) {
     
 
     ctrl_area->instrs.NMI = 1;
-    ctrl_area->instrs.SMI = 1;
+    ctrl_area->instrs.SMI = 0; // allow SMIs to run in guest
     ctrl_area->instrs.INIT = 1;
     ctrl_area->instrs.PAUSE = 1;
     ctrl_area->instrs.shutdown_evts = 1;
@@ -189,15 +189,11 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * core) {
     core->dbg_regs.dr7 = 0x0000000000000400LL;
 
 
-    /** THESE NEED TO BE MOVED TO GLOBAL LOCATION **/
-    v3_init_svm_io_map(core->vm_info);
     ctrl_area->IOPM_BASE_PA = (addr_t)V3_PAddr(core->vm_info->io_map.arch_data);
     ctrl_area->instrs.IOIO_PROT = 1;
-
-    v3_init_svm_msr_map(core->vm_info);
+           
     ctrl_area->MSRPM_BASE_PA = (addr_t)V3_PAddr(core->vm_info->msr_map.arch_data);
-    ctrl_area->instrs.MSR_PROT = 1;
-    /** *** **/
+    ctrl_area->instrs.MSR_PROT = 1;   
 
 
     PrintDebug("Exiting on interrupts\n");
@@ -290,6 +286,9 @@ int v3_init_svm_vmcb(struct guest_info * info, v3_vm_class_t vm_class) {
 static int update_irq_exit_state(struct guest_info * info) {
     vmcb_ctrl_t * guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
 
+    // Fix for QEMU bug using EVENTINJ as an internal cache
+    guest_ctrl->EVENTINJ.valid = 0;
+
     if ((info->intr_core_state.irq_pending == 1) && (guest_ctrl->guest_ctrl.V_IRQ == 0)) {
        
 #ifdef CONFIG_DEBUG_INTERRUPTS
@@ -310,7 +309,7 @@ static int update_irq_exit_state(struct guest_info * info) {
        // Interrupt was taken fully vectored
        info->intr_core_state.irq_started = 0;
 
-    } else {
+    } else if ((info->intr_core_state.irq_started == 1) && (guest_ctrl->exit_int_info.valid == 1)) {
 #ifdef CONFIG_DEBUG_INTERRUPTS
        PrintDebug("EXIT INT INFO is set (vec=%d)\n", guest_ctrl->exit_int_info.vector);
 #endif
@@ -323,6 +322,12 @@ static int update_irq_exit_state(struct guest_info * info) {
 static int update_irq_entry_state(struct guest_info * info) {
     vmcb_ctrl_t * guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
 
+
+    if (info->intr_core_state.irq_pending == 0) {
+       guest_ctrl->guest_ctrl.V_IRQ = 0;
+       guest_ctrl->guest_ctrl.V_INTR_VECTOR = 0;
+    }
+    
     if (v3_excp_pending(info)) {
        uint_t excp = v3_get_excp_number(info);
        
@@ -411,7 +416,6 @@ static int update_irq_entry_state(struct guest_info * info) {
 int v3_svm_enter(struct guest_info * info) {
     vmcb_ctrl_t * guest_ctrl = 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)); 
-    ullong_t tmp_tsc;
     addr_t exit_code = 0, exit_info1 = 0, exit_info2 = 0;
 
     // Conditionally yield the CPU if the timeslice has expired
@@ -439,8 +443,8 @@ int v3_svm_enter(struct guest_info * info) {
     guest_state->rip = info->rip;
     guest_state->rsp = info->vm_regs.rsp;
 
-#ifdef CONFIG_SYMBIOTIC
-    if (info->vm_info->sym_state.symcalls[info->cpu_id].sym_call_active == 0) {
+#ifdef CONFIG_SYMCALL
+    if (info->sym_core_state.symcall_state.sym_call_active == 0) {
        update_irq_entry_state(info);
     }
 #else 
@@ -456,8 +460,8 @@ int v3_svm_enter(struct guest_info * info) {
       (void *)(addr_t)info->rip);
     */
 
-#ifdef CONFIG_SYMBIOTIC
-    if (info->vm_info->sym_state.symcalls[info->cpu_id].sym_call_active == 1) {
+#ifdef CONFIG_SYMCALL
+    if (info->sym_core_state.symcall_state.sym_call_active == 1) {
        if (guest_ctrl->guest_ctrl.V_IRQ == 1) {
            V3_Print("!!! Injecting Interrupt during Sym call !!!\n");
        }
@@ -465,25 +469,30 @@ int v3_svm_enter(struct guest_info * info) {
 #endif
 
 
-    rdtscll(info->time_state.cached_host_tsc);
-    guest_ctrl->TSC_OFFSET = info->time_state.guest_tsc - info->time_state.cached_host_tsc;
-       
+    v3_update_timers(info);
+    v3_resume_time(info);
+
+#ifdef CONFIG_TIME_TSC_OFFSET
+    guest_ctrl->TSC_OFFSET = info->time_state.host_offset;
+#endif
+
+    //V3_Print("Calling v3_svm_launch\n");
+
     v3_svm_launch((vmcb_t *)V3_PAddr(info->vmm_data), &(info->vm_regs), (vmcb_t *)host_vmcbs[info->cpu_id]);
-    
 
-    v3_last_exit = (uint32_t)(guest_ctrl->exit_code);
+    v3_pause_time(info);
+#ifdef CONFIG_TIME_MASK_OVERHEAD
+    v3_offset_time(info, -SVM_ENTRY_OVERHEAD);
+#endif
 
-    //  v3_print_cond("SVM Returned: Exit Code: %x\n", (uint32_t)(guest_ctrl->exit_code));
+    //V3_Print("SVM Returned: Exit Code: %x, guest_rip=%lx\n", (uint32_t)(guest_ctrl->exit_code), (unsigned long)guest_state->rip);
 
-    rdtscll(tmp_tsc);
+    v3_last_exit = (uint32_t)(guest_ctrl->exit_code);
 
     //PrintDebug("SVM Returned\n");
     
     info->num_exits++;
 
-    v3_update_time(info, tmp_tsc - info->time_state.cached_host_tsc);
-
-
     // Save Guest state from VMCB
     info->rip = guest_state->rip;
     info->vm_regs.rsp = guest_state->rsp;
@@ -513,8 +522,8 @@ int v3_svm_enter(struct guest_info * info) {
     exit_info2 = guest_ctrl->exit_info2;
 
 
-#ifdef CONFIG_SYMBIOTIC
-    if (info->vm_info->sym_state.symcalls[info->cpu_id].sym_call_active == 0) {
+#ifdef CONFIG_SYMCALL
+    if (info->sym_core_state.symcall_state.sym_call_active == 0) {
        update_irq_exit_state(info);
     }
 #else
@@ -530,6 +539,7 @@ int v3_svm_enter(struct guest_info * info) {
     v3_yield_cond(info);
 
 
+
     if (v3_handle_svm_exit(info, exit_code, exit_info1, exit_info2) != 0) {
        PrintError("Error in SVM exit handler\n");
        return -1;
@@ -545,13 +555,40 @@ int v3_start_svm_guest(struct guest_info *info) {
     //  vmcb_ctrl_t * guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
 
 
+    PrintDebug("Starting SVM core %u\n",info->cpu_id);
+    if (info->cpu_mode==INIT) { 
+       PrintDebug("SVM core %u: I am an AP in INIT mode, waiting for that to change\n",info->cpu_id);
+       while (info->cpu_mode==INIT) {
+           v3_yield(info);
+           //PrintDebug("SVM core %u: still waiting for INIT\n",info->cpu_id);
+       }
+       PrintDebug("SVM core %u: I am out of INIT\n",info->cpu_id);
+       if (info->cpu_mode==SIPI) { 
+           PrintDebug("SVM core %u: I am waiting on a SIPI to set my starting address\n",info->cpu_id);
+           while (info->cpu_mode==SIPI) {
+               v3_yield(info);
+               //PrintDebug("SVM core %u: still waiting for SIPI\n",info->cpu_id);
+           }
+       }
+       PrintDebug("SVM core %u: I have my SIPI\n", info->cpu_id);
+    }
+
+    if (info->cpu_mode!=REAL) { 
+       PrintError("SVM core %u: I am not in REAL mode at launch!  Huh?!\n", info->cpu_id);
+       return -1;
+    }
+
+    PrintDebug("SVM core %u: I am starting at CS=0x%x (base=0x%p, limit=0x%x),  RIP=0x%p\n", 
+              info->cpu_id, info->segments.cs.selector, (void*)(info->segments.cs.base), 
+              info->segments.cs.limit,(void*)(info->rip));
+
 
-    PrintDebug("Launching SVM VM (vmcb=%p)\n", (void *)info->vmm_data);
+
+    PrintDebug("SVM core %u: Launching SVM VM (vmcb=%p)\n", info->cpu_id, (void *)info->vmm_data);
     //PrintDebugVMCB((vmcb_t*)(info->vmm_data));
     
     info->vm_info->run_state = VM_RUNNING;
-    rdtscll(info->yield_start_cycle);
-
+    v3_start_time(info);
 
     while (1) {
        if (v3_svm_enter(info) == -1) {
@@ -561,29 +598,29 @@ int v3_start_svm_guest(struct guest_info *info) {
            
            info->vm_info->run_state = VM_ERROR;
            
-           V3_Print("SVM ERROR!!\n"); 
+           V3_Print("SVM core %u: SVM ERROR!!\n", info->cpu_id); 
            
            v3_print_guest_state(info);
            
-           V3_Print("SVM Exit Code: %p\n", (void *)(addr_t)guest_ctrl->exit_code); 
+           V3_Print("SVM core %u: SVM Exit Code: %p\n", info->cpu_id, (void *)(addr_t)guest_ctrl->exit_code); 
            
-           V3_Print("exit_info1 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info1));
-           V3_Print("exit_info1 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info1)) + 4));
+           V3_Print("SVM core %u: exit_info1 low = 0x%.8x\n", info->cpu_id, *(uint_t*)&(guest_ctrl->exit_info1));
+           V3_Print("SVM core %u: exit_info1 high = 0x%.8x\n", info->cpu_id, *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info1)) + 4));
            
-           V3_Print("exit_info2 low = 0x%.8x\n", *(uint_t*)&(guest_ctrl->exit_info2));
-           V3_Print("exit_info2 high = 0x%.8x\n", *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info2)) + 4));
+           V3_Print("SVM core %u: exit_info2 low = 0x%.8x\n", info->cpu_id, *(uint_t*)&(guest_ctrl->exit_info2));
+           V3_Print("SVM core %u: exit_info2 high = 0x%.8x\n", info->cpu_id, *(uint_t *)(((uchar_t *)&(guest_ctrl->exit_info2)) + 4));
            
            linear_addr = get_addr_linear(info, info->rip, &(info->segments.cs));
            
            if (info->mem_mode == PHYSICAL_MEM) {
-               guest_pa_to_host_va(info, linear_addr, &host_addr);
+               v3_gpa_to_hva(info, linear_addr, &host_addr);
            } else if (info->mem_mode == VIRTUAL_MEM) {
-               guest_va_to_host_va(info, linear_addr, &host_addr);
+               v3_gva_to_hva(info, linear_addr, &host_addr);
            }
            
-           V3_Print("Host Address of rip = 0x%p\n", (void *)host_addr);
+           V3_Print("SVM core %u: Host Address of rip = 0x%p\n", info->cpu_id, (void *)host_addr);
            
-           V3_Print("Instr (15 bytes) at %p:\n", (void *)host_addr);
+           V3_Print("SVM core %u: Instr (15 bytes) at %p:\n", info->cpu_id, (void *)host_addr);
            v3_dump_mem((uint8_t *)host_addr, 15);
            
            v3_print_stack(info);
@@ -598,6 +635,9 @@ int v3_start_svm_guest(struct guest_info *info) {
 */
        
     }
+
+    // Need to take down the other cores on error... 
+
     return 0;
 }