X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fsvm.c;h=05fd183b5e55ffb8ff185be054fad77b6661e7d1;hp=b54ab19dc52f683f34a56ab2ec11f87764912434;hb=60ad6a41c6d0ee08ed689e8505eb0c3df0c2a289;hpb=d26b8881ecd0481b7fb5e24006fe2d84540ed3c1 diff --git a/palacios/src/palacios/svm.c b/palacios/src/palacios/svm.c index b54ab19..05fd183 100644 --- a/palacios/src/palacios/svm.c +++ b/palacios/src/palacios/svm.c @@ -39,6 +39,7 @@ #include #include +#include #ifdef V3_CONFIG_CHECKPOINT @@ -52,6 +53,13 @@ #include +#ifdef V3_CONFIG_MEM_TRACK +#include +#endif + +#ifdef V3_CONFIG_TM_FUNC +#include +#endif #ifndef V3_CONFIG_DEBUG_SVM #undef PrintDebug @@ -59,6 +67,7 @@ #endif + uint32_t v3_last_exit; // This is a global pointer to the host's VMCB @@ -74,7 +83,7 @@ extern int v3_svm_launch(vmcb_t * vmcb, struct v3_gprs * vm_regs, vmcb_t * host_ static vmcb_t * Allocate_VMCB() { vmcb_t * vmcb_page = NULL; - addr_t vmcb_pa = (addr_t)V3_AllocPages(1); + addr_t vmcb_pa = (addr_t)V3_AllocPages(1); // need not be shadow safe, not exposed to guest if ((void *)vmcb_pa == NULL) { PrintError(VM_NONE, VCORE_NONE, "Error allocating VMCB\n"); @@ -154,6 +163,10 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * core) { ctrl_area->exceptions.nmi = 1; */ + +#ifdef V3_CONFIG_TM_FUNC + v3_tm_set_excp_intercepts(ctrl_area); +#endif ctrl_area->instrs.NMI = 1; @@ -281,11 +294,13 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * core) { PrintDebug(core->vm_info, core, "Created\n"); core->ctrl_regs.cr0 |= 0x80000000; - core->ctrl_regs.cr3 = core->direct_map_pt; + + v3_activate_passthrough_pt(core); ctrl_area->cr_reads.cr0 = 1; ctrl_area->cr_writes.cr0 = 1; - //ctrl_area->cr_reads.cr4 = 1; + //intercept cr4 read so shadow pager can use PAE independently of guest + ctrl_area->cr_reads.cr4 = 1; ctrl_area->cr_writes.cr4 = 1; ctrl_area->cr_reads.cr3 = 1; ctrl_area->cr_writes.cr3 = 1; @@ -527,7 +542,11 @@ static int update_irq_entry_state(struct guest_info * info) { } else { switch (v3_intr_pending(info)) { case V3_EXTERNAL_IRQ: { - uint32_t irq = v3_get_intr(info); + int irq = v3_get_intr(info); + + if (irq<0) { + break; + } guest_ctrl->guest_ctrl.V_IRQ = 1; guest_ctrl->guest_ctrl.V_INTR_VECTOR = irq; @@ -618,12 +637,17 @@ int v3_svm_enter(struct guest_info * info) { // Conditionally yield the CPU if the timeslice has expired v3_schedule(info); +#ifdef V3_CONFIG_MEM_TRACK + v3_mem_track_entry(info); +#endif + // 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(); @@ -662,6 +686,8 @@ int v3_svm_enter(struct guest_info * info) { guest_state->rip = info->rip; guest_state->rsp = info->vm_regs.rsp; + V3_FP_ENTRY_RESTORE(info); + #ifdef V3_CONFIG_SYMCALL if (info->sym_core_state.symcall_state.sym_call_active == 0) { update_irq_entry_state(info); @@ -670,6 +696,10 @@ int v3_svm_enter(struct guest_info * info) { update_irq_entry_state(info); #endif +#ifdef V3_CONFIG_TM_FUNC + v3_tm_check_intr_state(info, guest_ctrl, guest_state); +#endif + /* ** */ @@ -694,9 +724,15 @@ int v3_svm_enter(struct guest_info * info) { uint64_t entry_tsc = 0; uint64_t exit_tsc = 0; +#ifdef V3_CONFIG_PWRSTAT_TELEMETRY + v3_pwrstat_telemetry_enter(info); +#endif + #ifdef V3_CONFIG_PMU_TELEMETRY v3_pmu_telemetry_enter(info); #endif + + rdtscll(entry_tsc); v3_svm_launch((vmcb_t *)V3_PAddr(info->vmm_data), &(info->vm_regs), (vmcb_t *)host_vmcbs[V3_Get_CPU()]); @@ -706,6 +742,11 @@ int v3_svm_enter(struct guest_info * info) { #ifdef V3_CONFIG_PMU_TELEMETRY v3_pmu_telemetry_exit(info); #endif + +#ifdef V3_CONFIG_PWRSTAT_TELEMETRY + v3_pwrstat_telemetry_exit(info); +#endif + guest_cycles = exit_tsc - entry_tsc; } @@ -718,6 +759,8 @@ int v3_svm_enter(struct guest_info * info) { info->num_exits++; + V3_FP_EXIT_SAVE(info); + // Save Guest state from VMCB info->rip = guest_state->rip; info->vm_regs.rsp = guest_state->rsp; @@ -765,6 +808,7 @@ int v3_svm_enter(struct guest_info * info) { // reenable global interrupts after vm exit v3_stgi(); + // Conditionally yield the CPU if the timeslice has expired v3_schedule(info); @@ -774,6 +818,7 @@ int v3_svm_enter(struct guest_info * info) { v3_advance_time(info, NULL); v3_update_timers(info); + { int ret = v3_handle_svm_exit(info, exit_code, exit_info1, exit_info2); @@ -789,6 +834,10 @@ int v3_svm_enter(struct guest_info * info) { v3_handle_timeouts(info, guest_cycles); } +#ifdef V3_CONFIG_MEM_TRACK + v3_mem_track_exit(info); +#endif + return 0; } @@ -800,51 +849,75 @@ int v3_start_svm_guest(struct guest_info * info) { PrintDebug(info->vm_info, info, "Starting SVM core %u (on logical core %u)\n", info->vcpu_id, info->pcpu_id); - if (info->vcpu_id == 0) { - info->core_run_state = CORE_RUNNING; - } else { - PrintDebug(info->vm_info, info, "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,-1); - //PrintDebug(info->vm_info, info, "SVM core %u: still waiting for INIT\n", info->vcpu_id); - } +#ifdef V3_CONFIG_HVM + if (v3_setup_hvm_hrt_core_for_boot(info)) { + PrintError(info->vm_info, info, "Failed to setup HRT core...\n"); + return -1; + } +#endif + - PrintDebug(info->vm_info, info, "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(info->vm_info, info, "SVM core %u(on %u): I am starting at CS=0x%x (base=0x%p, limit=0x%x), RIP=0x%p\n", - info->vcpu_id, info->pcpu_id, - info->segments.cs.selector, (void *)(info->segments.cs.base), - info->segments.cs.limit, (void *)(info->rip)); + while (1) { + if (info->core_run_state == CORE_STOPPED) { + if (info->vcpu_id == 0) { + info->core_run_state = CORE_RUNNING; + } else { + PrintDebug(info->vm_info, info, "SVM core %u (on %u): Waiting for core initialization\n", info->vcpu_id, info->pcpu_id); - PrintDebug(info->vm_info, info, "SVM core %u: Launching SVM VM (vmcb=%p) (on cpu %u)\n", - info->vcpu_id, (void *)info->vmm_data, info->pcpu_id); - //PrintDebugVMCB((vmcb_t*)(info->vmm_data)); - - v3_start_time(info); + V3_NO_WORK(info); -#ifdef V3_CONFIG_PMU_TELEMETRY - v3_pmu_telemetry_start(info); -#endif + 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_STILL_NO_WORK(info); - while (1) { + //PrintDebug(info->vm_info, info, "SVM core %u: still waiting for INIT\n", info->vcpu_id); + } + V3_HAVE_WORK_AGAIN(info); + + PrintDebug(info->vm_info, info, "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(info->vm_info, info, "SVM core %u(on %u): I am starting at CS=0x%x (base=0x%p, limit=0x%x), RIP=0x%p\n", + info->vcpu_id, info->pcpu_id, + info->segments.cs.selector, (void *)(info->segments.cs.base), + info->segments.cs.limit, (void *)(info->rip)); + + + + PrintDebug(info->vm_info, info, "SVM core %u: Launching SVM VM (vmcb=%p) (on cpu %u)\n", + info->vcpu_id, (void *)info->vmm_data, info->pcpu_id); + //PrintDebugVMCB((vmcb_t*)(info->vmm_data)); + + v3_start_time(info); + } + if (info->vm_info->run_state == VM_STOPPED) { info->core_run_state = CORE_STOPPED; break; } + +#ifdef V3_CONFIG_PMU_TELEMETRY + v3_pmu_telemetry_start(info); +#endif + +#ifdef V3_CONFIG_PWRSTAT_TELEMETRY + v3_pwrstat_telemetry_start(info); +#endif if (v3_svm_enter(info) == -1) { vmcb_ctrl_t * guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data)); @@ -879,12 +952,12 @@ int v3_start_svm_guest(struct guest_info * info) { v3_dump_mem((uint8_t *)host_addr, 15); v3_print_stack(info); - + break; } - + v3_wait_at_barrier(info); - + if (info->vm_info->run_state == VM_STOPPED) { info->core_run_state = CORE_STOPPED; @@ -905,6 +978,10 @@ int v3_start_svm_guest(struct guest_info * info) { #ifdef V3_CONFIG_PMU_TELEMETRY v3_pmu_telemetry_end(info); #endif + +#ifdef V3_CONFIG_PWRSTAT_TELEMETRY + v3_pwrstat_telemetry_end(info); +#endif // Need to take down the other cores on error... return 0; @@ -1015,7 +1092,7 @@ void v3_init_svm_cpu(int cpu_id) { V3_Print(VM_NONE, VCORE_NONE, "SVM Enabled\n"); // Setup the host state save area - host_vmcbs[cpu_id] = (addr_t)V3_AllocPages(4); + host_vmcbs[cpu_id] = (addr_t)V3_AllocPages(4); // need not be shadow-safe, not exposed to guest if (!host_vmcbs[cpu_id]) { PrintError(VM_NONE, VCORE_NONE, "Failed to allocate VMCB\n"); @@ -1260,7 +1337,7 @@ void Init_VMCB_pe(vmcb_t *vmcb, struct guest_info vm_info) { ctrl_area->instrs.IOIO_PROT = 1; - ctrl_area->IOPM_BASE_PA = (uint_t)V3_AllocPages(3); + ctrl_area->IOPM_BASE_PA = (uint_t)V3_AllocPages(3); // need not be shadow-safe, not exposed to guest if (!ctrl_area->IOPM_BASE_PA) { PrintError(core->vm_info, core, "Cannot allocate IO bitmap\n");