apic->tmr_cur_cnt = op_val;
break;
case TMR_DIV_CFG_OFFSET:
+ PrintDebug("apic %u: core %u: setting tmr_div_cfg to 0x%x\n",
+ apic->lapic_id.val, core->vcpu_id, op_val);
apic->tmr_div_cfg.val = op_val;
break;
}
if (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_PERIODIC) {
+ static unsigned int nexits = 0;
+ static unsigned int missed_ints = 0;
+
+ nexits++;
+ missed_ints += tmr_ticks / apic->tmr_init_cnt;
+
+ if ((missed_ints > 0) && (nexits >= 5000)) {
+ V3_Print("apic %u: core %u: missed %u timer interrupts total in last %u exits.\n",
+ apic->lapic_id.val, core->vcpu_id, missed_ints, nexits);
+ missed_ints = 0;
+ nexits = 0;
+ }
+
tmr_ticks = tmr_ticks % apic->tmr_init_cnt;
apic->tmr_cur_cnt = apic->tmr_init_cnt - tmr_ticks;
}
// disable global interrupts for vm state transition
v3_clgi();
- // Update timer devices right before entering the VM. Doing it
- // here makes sure the guest sees any timers that fired while
- // it was in the VMM
+ // Update timer devices after being in the VM, with interupts
+ // disabled, but before doing IRQ updates, so that any interrupts they
+ //raise get seen immediately.
v3_update_timers(info);
// Synchronize the guest state to the VMCB
info->mem_mode = v3_get_vm_mem_mode(info);
/* ** */
-
// save exit info here
exit_code = guest_ctrl->exit_code;
exit_info1 = guest_ctrl->exit_info1;
exit_info2 = guest_ctrl->exit_info2;
-
#ifdef V3_CONFIG_SYMCALL
if (info->sym_core_state.symcall_state.sym_call_active == 0) {
update_irq_exit_state(info);
update_irq_exit_state(info);
#endif
-
// reenable global interrupts after vm exit
v3_stgi();
-
// Conditionally yield the CPU if the timeslice has expired
v3_yield_cond(info);
-
-
if (v3_handle_svm_exit(info, exit_code, exit_info1, exit_info2) != 0) {
PrintError("Error in SVM exit handler\n");
PrintError(" last exit was %d\n", v3_last_exit);
// disable global interrupts for vm state transition
v3_disable_ints();
- // Update timer devices prior to entering VM. Doing it here
- // makes sure the guest sees any timers that fired while it
- // was in the VMM
+ // 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
+ // 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);
if (vmcs_store() != vmx_info->vmcs_ptr_phys) {
exit_log[info->num_exits % 10] = exit_info;
-
#ifdef V3_CONFIG_SYMCALL
if (info->sym_core_state.symcall_state.sym_call_active == 0) {
update_irq_exit_state(info);