/* Add external interrupts, NMI exiting, and virtual NMI */
vmx_state->pin_ctrls.nmi_exit = 1;
+ vmx_state->pin_ctrls.virt_nmi = 1;
vmx_state->pin_ctrls.ext_int_exit = 1;
+
/* We enable the preemption timer by default to measure accurate guest time */
if (avail_pin_ctrls.active_preempt_timer) {
V3_Print("VMX Preemption Timer is available\n");
vmx_state->exit_ctrls.save_preempt_timer = 1;
}
+ // we want it to use this when halting
vmx_state->pri_proc_ctrls.hlt_exit = 1;
+ // cpuid tells it that it does not have these instructions
+ vmx_state->pri_proc_ctrls.monitor_exit = 1;
+ vmx_state->pri_proc_ctrls.mwait_exit = 1;
+ // we don't need to handle a pause, although this is where
+ // we could pull out of a spin lock acquire or schedule to find its partner
vmx_state->pri_proc_ctrls.pause_exit = 0;
+
vmx_state->pri_proc_ctrls.tsc_offset = 1;
#ifdef V3_CONFIG_TIME_VIRTUALIZE_TSC
vmx_state->pri_proc_ctrls.rdtsc_exit = 1;
// Setup Guests initial PAT field
vmx_ret |= check_vmcs_write(VMCS_GUEST_PAT, 0x0007040600070406LL);
+ // Capture CR8 mods so that we can keep the apic_tpr correct
+ vmx_state->pri_proc_ctrls.cr8_ld_exit = 1;
+ vmx_state->pri_proc_ctrls.cr8_str_exit = 1;
+
+
/* Setup paging */
if (core->shdw_pg_mode == SHADOW_PAGING) {
PrintDebug("Creating initial shadow page table\n");
#endif
+
if (v3_update_vmcs_ctrl_fields(core)) {
#endif
}
+
+ // Lastly we check for an NMI exit, and reinject if so
+ {
+ struct vmx_basic_exit_info * basic_info = (struct vmx_basic_exit_info *)&(exit_info.exit_reason);
+
+ if (basic_info->reason == VMX_EXIT_INFO_EXCEPTION_OR_NMI) {
+ if ((uint8_t)exit_info.int_info == 2) {
+ asm("int $2");
+ }
+ }
+ }
+
// reenable global interrupts after vm exit
v3_enable_ints();