From: Tomas Hruby Date: Thu, 21 Oct 2010 17:07:01 +0000 (+0000) Subject: single shot timer interrupts fix X-Git-Tag: v3.2.0~771 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/migration-4to9?a=commitdiff_plain;h=a1eefc013e0f7c2c6b8e8934aece8eefe608abec;p=minix.git single shot timer interrupts fix - accidentaly this wasn't part of the SMP merge and the implementation remained uncomplete with the timer keeping ticking periodically - APIC timer is set for a signel shot and restarted everytime it expires. This way we can keep the AP's trully idle - the timer is restarted a little later before leaving to userspace - LAPIC_TIMER_ICR is written before LAPIC_LVTTR so the newest value is used --- diff --git a/kernel/arch/i386/apic.c b/kernel/arch/i386/apic.c index b5246f425..1655f1672 100644 --- a/kernel/arch/i386/apic.c +++ b/kernel/arch/i386/apic.c @@ -508,14 +508,14 @@ PUBLIC void lapic_set_timer_one_shot(const u32_t usec) ticks_per_us = (lapic_bus_freq[cpu] / 1000000) * config_apic_timer_x; + lapic_write(LAPIC_TIMER_ICR, usec * ticks_per_us); + lvtt = APIC_TDCR_1; lapic_write(LAPIC_TIMER_DCR, lvtt); /* configure timer as one-shot */ lvtt = APIC_TIMER_INT_VECTOR; lapic_write(LAPIC_LVTTR, lvtt); - - lapic_write(LAPIC_TIMER_ICR, usec * ticks_per_us); } PUBLIC void lapic_set_timer_periodic(const unsigned freq) diff --git a/kernel/arch/i386/arch_clock.c b/kernel/arch/i386/arch_clock.c index 83157401d..cc6ec35ec 100644 --- a/kernel/arch/i386/arch_clock.c +++ b/kernel/arch/i386/arch_clock.c @@ -124,8 +124,8 @@ PUBLIC int init_local_timer(unsigned freq) /* if we know the address, lapic is enabled and we should use it */ if (lapic_addr) { unsigned cpu = cpuid; - lapic_set_timer_periodic(freq); tsc_per_ms[cpu] = div64u(cpu_get_freq(cpu), 1000); + lapic_set_timer_one_shot(1000000/system_hz); } else { BOOT_VERBOSE(printf("Initiating legacy i8253 timer\n")); diff --git a/kernel/proc.c b/kernel/proc.c index 3e416ae4d..438b43c39 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -370,8 +370,6 @@ check_misc_flags: p = arch_finish_switch_to_user(); assert(!is_zero64(p->p_cpu_time_left)); - restart_local_timer(); - context_stop(proc_addr(KERNEL)); /* If the process isn't the owner of FPU, enable the FPU exception */ @@ -389,6 +387,9 @@ check_misc_flags: #ifdef CONFIG_SMP refresh_tlb(); #endif + + restart_local_timer(); + /* * restore_user_context() carries out the actual mode switch from kernel * to userspace. This function does not return