static struct vmx_exit_info exit_log[10];
+static uint64_t rip_log[10];
+
+
static void print_exit_log(struct guest_info * info) {
int cnt = info->num_exits % 10;
V3_Print("\tint_info = %p\n", (void *)(addr_t)tmp->int_info);
V3_Print("\tint_err = %p\n", (void *)(addr_t)tmp->int_err);
V3_Print("\tinstr_info = %p\n", (void *)(addr_t)tmp->instr_info);
+ V3_Print("\tguest_linear_addr= %p\n", (void *)(addr_t)tmp->guest_linear_addr);
+ V3_Print("\tRIP = %p\n", (void *)rip_log[cnt]);
+
cnt--;
}
+int
+v3_vmx_schedule_timeout(struct guest_info * info)
+{
+ struct vmx_data * vmx_state = (struct vmx_data *)(info->vmm_data);
+ sint64_t cycles;
+ uint32_t timeout;
+
+ /* Check if the hardware supports an active timeout */
+#define VMX_ACTIVE_PREEMPT_TIMER_PIN 0x40
+ if (hw_info.pin_ctrls.req_mask & VMX_ACTIVE_PREEMPT_TIMER_PIN) {
+ /* The hardware doesn't support us modifying this pin control */
+ return 0;
+ }
+
+ /* Check if we have one to schedule and schedule it if we do */
+ cycles = (sint64_t)info->time_state.next_timeout - (sint64_t)v3_get_guest_time(&info->time_state);
+ if (info->time_state.next_timeout == (ullong_t) -1) {
+ timeout = 0;
+ vmx_state->pin_ctrls.active_preempt_timer = 0;
+ } else if (cycles < 0) {
+ /* set the timeout to 0 to force an immediate re-exit since it expired between
+ * when we checked a timeout and now. IF SOMEONE CONTINAULLY SETS A SHORT TIMEOUT,
+ * THIS CAN LOCK US OUT OF THE GUEST! */
+ timeout = 0;
+ vmx_state->pin_ctrls.active_preempt_timer = 1;
+ } else {
+ /* The hardware supports scheduling a timeout, and we have one to
+ * schedule */
+ timeout = (uint32_t)cycles >> hw_info.misc_info.tsc_multiple;
+ vmx_state->pin_ctrls.active_preempt_timer = 1;
+ }
+
+ /* Actually program the timer based on the settings above. */
+ check_vmcs_write(VMCS_PREEMPT_TIMER, timeout);
+ check_vmcs_write(VMCS_PIN_CTRLS, vmx_state->pin_ctrls.value);
+ return 0;
+}
+
/*
* CAUTION and DANGER!!!
*
// Perform any additional yielding needed for time adjustment
v3_adjust_time(info);
+ // Check for timeout - since this calls generic hooks in devices
+ // that may do things like pause the VM, it cannot be with interrupts
+ // disabled.
+ v3_check_timeout(info);
+
// disable global interrupts for vm state transition
v3_disable_ints();
// Update timer devices late after being in the VM so that as much
- // of hte time in the VM is accounted for as possible. Also do it before
+ // 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
// handled on the next VM entry. Must be done with interrupts disabled.
v3_update_timers(info);
vmcs_write(VMCS_GUEST_CR3, guest_cr3);
}
+ // Update vmx active preemption timer to exit at the next timeout if
+ // the hardware supports it.
+ v3_vmx_schedule_timeout(info);
+
// Perform last-minute time bookkeeping prior to entering the VM
v3_time_enter_vm(info);
//PrintDebug("VMX Exit taken, id-qual: %u-%lu\n", exit_info.exit_reason, exit_info.exit_qual);
exit_log[info->num_exits % 10] = exit_info;
+ rip_log[info->num_exits % 10] = get_addr_linear(info, info->rip, &(info->segments.cs));
#ifdef V3_CONFIG_SYMCALL
if (info->sym_core_state.symcall_state.sym_call_active == 0) {
void v3_init_vmx_cpu(int cpu_id) {
addr_t vmx_on_region = 0;
+ extern v3_cpu_arch_t v3_mach_type;
- if (cpu_id == 0) {
+ if (v3_mach_type == V3_INVALID_CPU) {
if (v3_init_vmx_hw(&hw_info) == -1) {
PrintError("Could not initialize VMX hardware features on cpu %d\n", cpu_id);
return;
v3_cpu_types[cpu_id] = V3_VMX_EPT_UG_CPU;
}
}
+
}