X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fsvm.c;h=84e720004c37de779df71f071724fe3f67e2f97e;hb=2d3172e90b9f059548bf5dfcf4f85ed71672aac7;hp=1bf16ccfa45dd469533c1a48dfc4df212f407d49;hpb=c58da27ff29c9cd0511c7c3f64eff2644fa85961;p=palacios.git diff --git a/palacios/src/palacios/svm.c b/palacios/src/palacios/svm.c index 1bf16cc..84e7200 100644 --- a/palacios/src/palacios/svm.c +++ b/palacios/src/palacios/svm.c @@ -37,6 +37,9 @@ #include #include +#ifdef V3_CONFIG_CHECKPOINT +#include +#endif #include @@ -126,10 +129,9 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * core) { ctrl_area->instrs.HLT = 1; -#ifdef V3_CONFIG_TIME_VIRTUALIZE_TSC - ctrl_area->instrs.RDTSC = 1; - ctrl_area->svm_instrs.RDTSCP = 1; -#endif + /* Set at VMM launch as needed */ + ctrl_area->instrs.RDTSC = 0; + ctrl_area->svm_instrs.RDTSCP = 0; // guest_state->cr0 = 0x00000001; // PE @@ -308,6 +310,28 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * core) { &v3_handle_vm_cr_read, &v3_handle_vm_cr_write, core); + + + { +#define INT_PENDING_AMD_MSR 0xc0010055 + + v3_hook_msr(core->vm_info, IA32_STAR_MSR, NULL, NULL, NULL); + v3_hook_msr(core->vm_info, IA32_LSTAR_MSR, NULL, NULL, NULL); + v3_hook_msr(core->vm_info, IA32_FMASK_MSR, NULL, NULL, NULL); + v3_hook_msr(core->vm_info, IA32_KERN_GS_BASE_MSR, NULL, NULL, NULL); + v3_hook_msr(core->vm_info, IA32_CSTAR_MSR, NULL, NULL, NULL); + + v3_hook_msr(core->vm_info, SYSENTER_CS_MSR, NULL, NULL, NULL); + v3_hook_msr(core->vm_info, SYSENTER_ESP_MSR, NULL, NULL, NULL); + v3_hook_msr(core->vm_info, SYSENTER_EIP_MSR, NULL, NULL, NULL); + + + v3_hook_msr(core->vm_info, FS_BASE_MSR, NULL, NULL, NULL); + v3_hook_msr(core->vm_info, GS_BASE_MSR, NULL, NULL, NULL); + + // Passthrough read operations are ok. + v3_hook_msr(core->vm_info, INT_PENDING_AMD_MSR, NULL, v3_msr_unhandled_write, NULL); + } } @@ -339,6 +363,27 @@ int v3_deinit_svm_vmcb(struct guest_info * core) { } +#ifdef V3_CONFIG_CHECKPOINT +int v3_svm_save_core(struct guest_info * core, void * ctx){ + + v3_chkpt_save_8(ctx, "cpl", &(core->cpl)); + v3_chkpt_save(ctx, "vmcb_data", PAGE_SIZE, core->vmm_data); + + return 0; +} + +int v3_svm_load_core(struct guest_info * core, void * ctx){ + + v3_chkpt_load_8(ctx, "cpl", &(core->cpl)); + + if (v3_chkpt_load(ctx, "vmcb_data", PAGE_SIZE, core->vmm_data) == -1) { + return -1; + } + + return 0; +} +#endif + static int update_irq_exit_state(struct guest_info * info) { vmcb_ctrl_t * guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data)); @@ -472,6 +517,20 @@ static int update_irq_entry_state(struct guest_info * info) { return 0; } +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) { + ctrl_area->instrs.RDTSC = 1; + ctrl_area->svm_instrs.RDTSCP = 1; + } else { + ctrl_area->instrs.RDTSC = 0; + ctrl_area->svm_instrs.RDTSCP = 0; + ctrl_area->TSC_OFFSET = v3_tsc_host_offset(&info->time_state); + } + return 0; +} /* * CAUTION and DANGER!!! @@ -485,21 +544,20 @@ 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)); addr_t exit_code = 0, exit_info1 = 0, exit_info2 = 0; + uint64_t guest_cycles = 0; // Conditionally yield the CPU if the timeslice has expired v3_yield_cond(info); - // Perform any additional yielding needed for time adjustment - v3_adjust_time(info); + // Update timer devices after being in the VM before doing + // IRQ updates, so that any interrupts they raise get seen + // immediately. + v3_advance_time(info, NULL); + v3_update_timers(info); // disable global interrupts for vm state transition v3_clgi(); - // Update timer devices after being in the VM, with interupts - // disabled, but before doing IRQ updates, so that any interrupts they - //raise get seen immediately. - v3_update_timers(info); - // Synchronize the guest state to the VMCB guest_state->cr0 = info->ctrl_regs.cr0; guest_state->cr2 = info->ctrl_regs.cr2; @@ -544,20 +602,28 @@ int v3_svm_enter(struct guest_info * info) { } #endif - v3_time_enter_vm(info); - guest_ctrl->TSC_OFFSET = v3_tsc_host_offset(&info->time_state); - + v3_svm_config_tsc_virtualization(info); //V3_Print("Calling v3_svm_launch\n"); + { + uint64_t entry_tsc = 0; + uint64_t exit_tsc = 0; + + rdtscll(entry_tsc); + + v3_svm_launch((vmcb_t *)V3_PAddr(info->vmm_data), &(info->vm_regs), (vmcb_t *)host_vmcbs[V3_Get_CPU()]); + + rdtscll(exit_tsc); + + guest_cycles = exit_tsc - entry_tsc; + } - v3_svm_launch((vmcb_t *)V3_PAddr(info->vmm_data), &(info->vm_regs), (vmcb_t *)host_vmcbs[V3_Get_CPU()]); //V3_Print("SVM Returned: Exit Code: %x, guest_rip=%lx\n", (uint32_t)(guest_ctrl->exit_code), (unsigned long)guest_state->rip); v3_last_exit = (uint32_t)(guest_ctrl->exit_code); - // Immediate exit from VM time bookkeeping - v3_time_exit_vm(info); + v3_advance_time(info, &guest_cycles); info->num_exits++; @@ -602,6 +668,11 @@ int v3_svm_enter(struct guest_info * info) { // Conditionally yield the CPU if the timeslice has expired v3_yield_cond(info); + // This update timers is for time-dependent handlers + // if we're slaved to host time + v3_advance_time(info, NULL); + v3_update_timers(info); + { int ret = v3_handle_svm_exit(info, exit_code, exit_info1, exit_info2); @@ -612,6 +683,11 @@ int v3_svm_enter(struct guest_info * info) { } } + if (info->timeouts.timeout_active) { + /* Check to see if any timeouts have expired */ + v3_handle_timeouts(info, guest_cycles); + } + return 0; } @@ -625,16 +701,24 @@ int v3_start_svm_guest(struct guest_info * info) { if (info->vcpu_id == 0) { info->core_run_state = CORE_RUNNING; - info->vm_info->run_state = VM_RUNNING; } else { PrintDebug("SVM core %u (on %u): Waiting for core initialization\n", info->vcpu_id, info->pcpu_id); while (info->core_run_state == CORE_STOPPED) { + + if (info->vm_info->run_state == VM_STOPPED) { + // The VM was stopped before this core was initialized. + return 0; + } + v3_yield(info); //PrintDebug("SVM core %u: still waiting for INIT\n", info->vcpu_id); } PrintDebug("SVM core %u(on %u) initialized\n", info->vcpu_id, info->pcpu_id); + + // We'll be paranoid about race conditions here + v3_wait_at_barrier(info); } PrintDebug("SVM core %u(on %u): I am starting at CS=0x%x (base=0x%p, limit=0x%x), RIP=0x%p\n",