#include <palacios/vmm_barrier.h>
#include <palacios/vmm_debug.h>
+#include <palacios/vmm_perftune.h>
#ifdef V3_CONFIG_CHECKPOINT
#include <palacios/vmm_sprintf.h>
+#ifdef V3_CONFIG_TM_FUNC
+#include <extensions/trans_mem.h>
+#endif
#ifndef V3_CONFIG_DEBUG_SVM
#undef PrintDebug
#endif
+
uint32_t v3_last_exit;
// This is a global pointer to the host's VMCB
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");
ctrl_area->exceptions.nmi = 1;
*/
+
+#ifdef V3_CONFIG_TM_FUNC
+ v3_tm_set_excp_intercepts(ctrl_area);
+#endif
ctrl_area->instrs.NMI = 1;
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;
} 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;
uint64_t guest_cycles = 0;
// Conditionally yield the CPU if the timeslice has expired
- v3_yield_cond(info,-1);
+ v3_schedule(info);
// Update timer devices after being in the VM before doing
// IRQ updates, so that any interrupts they raise get seen
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);
update_irq_entry_state(info);
#endif
+#ifdef V3_CONFIG_TM_FUNC
+ v3_tm_check_intr_state(info, guest_ctrl, guest_state);
+#endif
+
/* ** */
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()]);
rdtscll(exit_tsc);
+#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;
}
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;
v3_stgi();
// Conditionally yield the CPU if the timeslice has expired
- v3_yield_cond(info,-1);
+ v3_schedule(info);
// This update timers is for time-dependent handlers
// if we're slaved to host time
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);
- }
-
- 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);
- }
+ while (1) {
- 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));
+ 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);
+ V3_NO_WORK(info);
- 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);
+ 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));
addr_t host_addr;
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;
}
+#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;
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");
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");