From: Jack Lange Date: Thu, 13 Oct 2011 15:39:46 +0000 (-0400) Subject: revert timer modifications to fix guest deadlocks X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=9e26adea080d2f014aeb391b1b52ce94f9acec45;p=palacios-OLD.git revert timer modifications to fix guest deadlocks --- diff --git a/palacios/src/devices/apic.c b/palacios/src/devices/apic.c index d83f0bd..6b21f81 100644 --- a/palacios/src/devices/apic.c +++ b/palacios/src/devices/apic.c @@ -220,7 +220,7 @@ struct apic_state { uint32_t tmr_cur_cnt; uint32_t tmr_init_cnt; - uint32_t missed_ints; + struct local_vec_tbl_reg ext_intr_vec_tbl[4]; @@ -295,7 +295,6 @@ static void init_apic_state(struct apic_state * apic, uint32_t id) { apic->rem_rd_data = 0x00000000; apic->tmr_init_cnt = 0x00000000; apic->tmr_cur_cnt = 0x00000000; - apic->missed_ints = 0; apic->lapic_id.val = id; @@ -1563,33 +1562,10 @@ static int apic_begin_irq(struct guest_info * core, void * private_data, int irq } -/* Timer Functions */ - -static void apic_inject_timer_intr(struct guest_info *core, - void * priv_data) { - struct apic_dev_state * apic_dev = (struct apic_dev_state *)(priv_data); - struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]); - // raise irq - PrintDebug("apic %u: core %u: Raising APIC Timer interrupt (periodic=%d) (icnt=%d) (div=%d)\n", - apic->lapic_id.val, core->vcpu_id, - apic->tmr_vec_tbl.tmr_mode, apic->tmr_init_cnt, shift_num); - - if (apic_intr_pending(core, priv_data)) { - PrintDebug("apic %u: core %u: Overriding pending IRQ %d\n", - apic->lapic_id.val, core->vcpu_id, - apic_get_intr_number(core, priv_data)); - } - - if (activate_internal_irq(apic, APIC_TMR_INT) == -1) { - PrintError("apic %u: core %u: Could not raise Timer interrupt\n", - apic->lapic_id.val, core->vcpu_id); - } - return; -} - +/* Timer Functions */ static void apic_update_time(struct guest_info * core, uint64_t cpu_cycles, uint64_t cpu_freq, @@ -1655,18 +1631,40 @@ static void apic_update_time(struct guest_info * core, if (tmr_ticks < apic->tmr_cur_cnt) { apic->tmr_cur_cnt -= tmr_ticks; - if (apic->missed_ints) { - apic_inject_timer_intr(core, priv_data); - apic->missed_ints--; - } } else { tmr_ticks -= apic->tmr_cur_cnt; apic->tmr_cur_cnt = 0; - apic_inject_timer_intr(core, priv_data); + // raise irq + PrintDebug("apic %u: core %u: Raising APIC Timer interrupt (periodic=%d) (icnt=%d) (div=%d)\n", + apic->lapic_id.val, core->vcpu_id, + apic->tmr_vec_tbl.tmr_mode, apic->tmr_init_cnt, shift_num); + + if (apic_intr_pending(core, priv_data)) { + PrintDebug("apic %u: core %u: Overriding pending IRQ %d\n", + apic->lapic_id.val, core->vcpu_id, + apic_get_intr_number(core, priv_data)); + } + if (activate_internal_irq(apic, APIC_TMR_INT) == -1) { + PrintError("apic %u: core %u: Could not raise Timer interrupt\n", + apic->lapic_id.val, core->vcpu_id); + } + if (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_PERIODIC) { - apic->missed_ints += tmr_ticks / apic->tmr_init_cnt; + 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; } @@ -1675,6 +1673,7 @@ static void apic_update_time(struct guest_info * core, return; } + static struct intr_ctrl_ops intr_ops = { .intr_pending = apic_intr_pending, .get_intr_number = apic_get_intr_number, diff --git a/palacios/src/palacios/svm.c b/palacios/src/palacios/svm.c index 6064855..cd741c9 100644 --- a/palacios/src/palacios/svm.c +++ b/palacios/src/palacios/svm.c @@ -569,7 +569,7 @@ int v3_svm_enter(struct guest_info * info) { #endif v3_time_enter_vm(info); - // guest_ctrl->TSC_OFFSET = v3_tsc_host_offset(&info->time_state); + guest_ctrl->TSC_OFFSET = v3_tsc_host_offset(&info->time_state); //V3_Print("Calling v3_svm_launch\n"); diff --git a/palacios/src/palacios/vmm_time.c b/palacios/src/palacios/vmm_time.c index fa8f5cd..781bae7 100644 --- a/palacios/src/palacios/vmm_time.c +++ b/palacios/src/palacios/vmm_time.c @@ -172,21 +172,21 @@ static int skew_guest_time(struct guest_info * info) { guest_time = v3_get_guest_time(time_state); if (guest_time < target_guest_time) { - sint64_t max_skew, desired_skew, skew; + uint64_t max_skew, desired_skew, skew; if (time_state->enter_time) { /* Limit forward skew to 10% of the amount the guest has * run since we last could skew time */ - max_skew = ((sint64_t)guest_time - (sint64_t)time_state->enter_time) / 10; + max_skew = (guest_time - time_state->enter_time) / 10; } else { max_skew = 0; } - desired_skew = (sint64_t)target_guest_time - (sint64_t)guest_time; + desired_skew = target_guest_time - guest_time; skew = desired_skew > max_skew ? max_skew : desired_skew; - PrintDebug("Guest %lld cycles behind where it should be.\n", + PrintDebug("Guest %llu cycles behind where it should be.\n", desired_skew); - PrintDebug("Limit on forward skew is %lld. Skewing forward %lld.\n", + PrintDebug("Limit on forward skew is %llu. Skewing forward %llu.\n", max_skew, skew); v3_offset_time(info, skew); @@ -228,10 +228,10 @@ v3_time_enter_vm( struct guest_info * info ) struct vm_time * time_state = &(info->time_state); uint64_t guest_time, host_time; - host_time = v3_get_host_time(time_state); guest_time = v3_get_guest_time(time_state); + host_time = v3_get_host_time(time_state); time_state->enter_time = host_time; - time_state->guest_host_offset = (sint64_t)guest_time - (sint64_t)host_time; + time_state->guest_host_offset = guest_time - host_time; return 0; } diff --git a/palacios/src/palacios/vmx.c b/palacios/src/palacios/vmx.c index bdfc8c0..505d61c 100644 --- a/palacios/src/palacios/vmx.c +++ b/palacios/src/palacios/vmx.c @@ -750,7 +750,7 @@ static void print_exit_log(struct guest_info * info) { */ int v3_vmx_enter(struct guest_info * info) { int ret = 0; - //uint32_t tsc_offset_low, tsc_offset_high; + uint32_t tsc_offset_low, tsc_offset_high; struct vmx_exit_info exit_info; struct vmx_data * vmx_info = (struct vmx_data *)(info->vmm_data); @@ -795,10 +795,11 @@ int v3_vmx_enter(struct guest_info * info) { // Perform last-minute time bookkeeping prior to entering the VM v3_time_enter_vm(info); - // tsc_offset_high = (uint32_t)((v3_tsc_host_offset(&info->time_state) >> 32) & 0xffffffff); - // tsc_offset_low = (uint32_t)(v3_tsc_host_offset(&info->time_state) & 0xffffffff); - // check_vmcs_write(VMCS_TSC_OFFSET_HIGH, tsc_offset_high); - // check_vmcs_write(VMCS_TSC_OFFSET, tsc_offset_low); + tsc_offset_high = (uint32_t)((v3_tsc_host_offset(&info->time_state) >> 32) & 0xffffffff); + tsc_offset_low = (uint32_t)(v3_tsc_host_offset(&info->time_state) & 0xffffffff); + check_vmcs_write(VMCS_TSC_OFFSET_HIGH, tsc_offset_high); + check_vmcs_write(VMCS_TSC_OFFSET, tsc_offset_low); + if (v3_update_vmcs_host_state(info)) { v3_enable_ints();