X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmx.c;h=f0823b4cfe5c6d099fd8950fe8351985aefc4487;hp=d6471a1dac5f16b2debcff2dcee1b0f9f461aa19;hb=60ad6a41c6d0ee08ed689e8505eb0c3df0c2a289;hpb=acaadd79c597c8d5180fbfbec79c01fef3dff003 diff --git a/palacios/src/palacios/vmx.c b/palacios/src/palacios/vmx.c index d6471a1..f0823b4 100644 --- a/palacios/src/palacios/vmx.c +++ b/palacios/src/palacios/vmx.c @@ -44,6 +44,10 @@ #include #include +#ifdef V3_CONFIG_MEM_TRACK +#include +#endif + #ifndef V3_CONFIG_DEBUG_VMX #undef PrintDebug #define PrintDebug(fmt, args...) @@ -97,7 +101,7 @@ static addr_t allocate_vmcs() { PrintDebug(VM_NONE, VCORE_NONE, "Allocating page\n"); - temp = V3_AllocPages(1); + temp = V3_AllocPages(1); // need not be shadow-safe, not exposed to guest if (!temp) { PrintError(VM_NONE, VCORE_NONE, "Cannot allocate VMCS\n"); return -1; @@ -270,16 +274,19 @@ static int init_vmcs_bios(struct guest_info * core, struct vmx_data * vmx_state) // Cause VM_EXIT whenever CR4.VMXE or CR4.PAE bits are written - vmx_ret |= check_vmcs_write(VMCS_CR4_MASK, CR4_VMXE | CR4_PAE); + vmx_ret |= check_vmcs_write(VMCS_CR4_MASK, CR4_VMXE | CR4_PAE ); - core->ctrl_regs.cr3 = core->direct_map_pt; + v3_activate_passthrough_pt(core); // vmx_state->pinbased_ctrls |= NMI_EXIT; /* Add CR exits */ vmx_state->pri_proc_ctrls.cr3_ld_exit = 1; vmx_state->pri_proc_ctrls.cr3_str_exit = 1; - + + // Note that we intercept cr4.pae writes + // and we have cr4 read-shadowed to the shadow pager's cr4 + vmx_state->pri_proc_ctrls.invlpg_exit = 1; /* Add page fault exits */ @@ -326,7 +333,7 @@ static int init_vmcs_bios(struct guest_info * core, struct vmx_data * vmx_state) - if (v3_init_ept(core, &hw_info) == -1) { + if (v3_init_nested_paging_core(core, &hw_info) == -1) { PrintError(core->vm_info, core, "Error initializing EPT\n"); return -1; } @@ -424,7 +431,7 @@ static int init_vmcs_bios(struct guest_info * core, struct vmx_data * vmx_state) ((struct cr0_32 *)&(core->shdw_pg_state.guest_cr0))->ne = 1; ((struct cr0_32 *)&(core->shdw_pg_state.guest_cr0))->cd = 0; - if (v3_init_ept(core, &hw_info) == -1) { + if (v3_init_nested_paging_core(core, &hw_info) == -1) { PrintError(core->vm_info, core, "Error initializing EPT\n"); return -1; } @@ -456,7 +463,7 @@ static int init_vmcs_bios(struct guest_info * core, struct vmx_data * vmx_state) return -1; } - vmx_state->msr_area_paddr = (addr_t)V3_AllocPages(1); + vmx_state->msr_area_paddr = (addr_t)V3_AllocPages(1); // need not be shadow-safe, not exposed to guest if (vmx_state->msr_area_paddr == (addr_t)NULL) { PrintError(core->vm_info, core, "could not allocate msr load/store area\n"); @@ -687,7 +694,7 @@ int v3_vmx_load_core(struct guest_info * core, void * ctx){ struct cr0_32 * shadow_cr0; addr_t vmcs_page_paddr; //HPA - vmcs_page_paddr = (addr_t) V3_AllocPages(1); + vmcs_page_paddr = (addr_t) V3_AllocPages(1); // need not be shadow-safe, not exposed to guest if (!vmcs_page_paddr) { PrintError(core->vm_info, core, "Could not allocate space for a vmcs in VMX\n"); @@ -820,7 +827,14 @@ static int update_irq_entry_state(struct guest_info * info) { switch (v3_intr_pending(info)) { case V3_EXTERNAL_IRQ: { - info->intr_core_state.irq_vector = v3_get_intr(info); + + int irq = v3_get_intr(info); + + if (irq<0) { + break; + } + + info->intr_core_state.irq_vector = irq; ent_int.vector = info->intr_core_state.irq_vector; ent_int.type = 0; ent_int.error_code = 0; @@ -966,7 +980,11 @@ int v3_vmx_enter(struct guest_info * info) { uint64_t guest_cycles = 0; // Conditionally yield the CPU if the timeslice has expired - v3_yield_cond(info,-1); + v3_schedule(info); + +#ifdef V3_CONFIG_MEM_TRACK + v3_mem_track_entry(info); +#endif // Update timer devices late after being in the VM so that as much // of the time in the VM is accounted for as possible. Also do it before @@ -1021,12 +1039,21 @@ int v3_vmx_enter(struct guest_info * info) { check_vmcs_write(VMCS_PREEMPT_TIMER, preempt_window); } - + + V3_FP_ENTRY_RESTORE(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 + if (vmx_info->state == VMX_UNLAUNCHED) { vmx_info->state = VMX_LAUNCHED; rdtscll(entry_tsc); @@ -1041,6 +1068,14 @@ int v3_vmx_enter(struct guest_info * info) { } guest_cycles = exit_tsc - entry_tsc; + +#ifdef V3_CONFIG_PMU_TELEMETRY + v3_pmu_telemetry_exit(info); +#endif + +#ifdef V3_CONFIG_PWRSTAT_TELEMETRY + v3_pwrstat_telemetry_exit(info); +#endif } // PrintDebug(info->vm_info, info, "VMX Exit: ret=%d\n", ret); @@ -1058,6 +1093,8 @@ int v3_vmx_enter(struct guest_info * info) { info->num_exits++; + V3_FP_EXIT_SAVE(info); + /* If we have the preemption time, then use it to get more accurate guest time */ if (vmx_info->pin_ctrls.active_preempt_timer) { uint32_t cycles_left = 0; @@ -1135,7 +1172,7 @@ int v3_vmx_enter(struct guest_info * info) { v3_enable_ints(); // Conditionally yield the CPU if the timeslice has expired - v3_yield_cond(info,-1); + v3_schedule(info); v3_advance_time(info, NULL); v3_update_timers(info); @@ -1149,6 +1186,10 @@ int v3_vmx_enter(struct guest_info * info) { v3_handle_timeouts(info, guest_cycles); } +#ifdef V3_CONFIG_MEM_TRACK + v3_mem_track_exit(info); +#endif + return 0; } @@ -1157,48 +1198,71 @@ int v3_start_vmx_guest(struct guest_info * info) { PrintDebug(info->vm_info, info, "Starting VMX core %u\n", info->vcpu_id); - if (info->vcpu_id == 0) { - info->core_run_state = CORE_RUNNING; - } else { - - PrintDebug(info->vm_info, info, "VMX core %u: Waiting for core initialization\n", info->vcpu_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, "VMX core %u: still waiting for INIT\n",info->vcpu_id); - } - - PrintDebug(info->vm_info, info, "VMX core %u initialized\n", info->vcpu_id); - - // We'll be paranoid about race conditions here - v3_wait_at_barrier(info); +#if V3_CONFIG_HVM + if (v3_setup_hvm_vm_for_boot(vm)) { + PrintError(vm, VCORE_NONE, "HVM setup for boot failed\n"); + return -1; } - - - PrintDebug(info->vm_info, info, "VMX core %u: I am starting at CS=0x%x (base=0x%p, limit=0x%x), RIP=0x%p\n", - info->vcpu_id, info->segments.cs.selector, (void *)(info->segments.cs.base), - info->segments.cs.limit, (void *)(info->rip)); - - - PrintDebug(info->vm_info, info, "VMX core %u: Launching VMX VM on logical core %u\n", info->vcpu_id, info->pcpu_id); - - v3_start_time(info); - +#endif + while (1) { - - if (info->vm_info->run_state == VM_STOPPED) { - info->core_run_state = CORE_STOPPED; - break; + if (info->core_run_state == CORE_STOPPED) { + if (info->vcpu_id == 0) { + info->core_run_state = CORE_RUNNING; + } else { + + PrintDebug(info->vm_info, info, "VMX core %u: Waiting for core initialization\n", info->vcpu_id); + + V3_NO_WORK(info); + + 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); + //PrintDebug(info->vm_info, info, "VMX core %u: still waiting for INIT\n",info->vcpu_id); + } + + V3_HAVE_WORK_AGAIN(info); + + PrintDebug(info->vm_info, info, "VMX core %u initialized\n", info->vcpu_id); + + // We'll be paranoid about race conditions here + v3_wait_at_barrier(info); + } + + + PrintDebug(info->vm_info, info, "VMX core %u: I am starting at CS=0x%x (base=0x%p, limit=0x%x), RIP=0x%p\n", + info->vcpu_id, info->segments.cs.selector, (void *)(info->segments.cs.base), + info->segments.cs.limit, (void *)(info->rip)); + + + PrintDebug(info->vm_info, info, "VMX core %u: Launching VMX VM on logical core %u\n", info->vcpu_id, info->pcpu_id); + + 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_vmx_enter(info) == -1) { - + addr_t host_addr; addr_t linear_addr = 0; @@ -1246,6 +1310,14 @@ int v3_start_vmx_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 + return 0; }