#include <palacios/vmx_assist.h>
#include <palacios/vmx_hw_info.h>
+#ifdef V3_CONFIG_MEM_TRACK
+#include <palacios/vmm_mem_track.h>
+#endif
+
#ifndef V3_CONFIG_DEBUG_VMX
#undef PrintDebug
#define PrintDebug(fmt, args...)
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;
// 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 */
- 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;
}
((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;
}
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");
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");
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;
// 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 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
// updating IRQ entry state so that any interrupts the timers raise get
check_vmcs_write(VMCS_PREEMPT_TIMER, preempt_window);
}
-
+
+ V3_FP_ENTRY_RESTORE(info);
{
uint64_t entry_tsc = 0;
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;
v3_handle_timeouts(info, guest_cycles);
}
+#ifdef V3_CONFIG_MEM_TRACK
+ v3_mem_track_exit(info);
+#endif
+
return 0;
}
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) {
+#ifdef V3_CONFIG_MULTIBOOT
+ if (v3_setup_multiboot_core_for_boot(info)) {
+ PrintError(info->vm_info, info, "Failed to setup Multiboot core...\n");
+ return -1;
+ }
+#endif
+#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
+
+ 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, "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) {
- // The VM was stopped before this core was initialized.
- return 0;
+ info->core_run_state = CORE_STOPPED;
+ break;
}
-
- 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);
- }
-
-
- 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);
-
#ifdef V3_CONFIG_PMU_TELEMETRY
- v3_pmu_telemetry_start(info);
+ v3_pmu_telemetry_start(info);
#endif
-
+
#ifdef V3_CONFIG_PWRSTAT_TELEMETRY
- v3_pwrstat_telemetry_start(info);
+ v3_pwrstat_telemetry_start(info);
#endif
-
- while (1) {
-
- if (info->vm_info->run_state == VM_STOPPED) {
- info->core_run_state = CORE_STOPPED;
- break;
- }
-
+
+
if (v3_vmx_enter(info) == -1) {
-
+
addr_t host_addr;
addr_t linear_addr = 0;