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
This commit is contained in:
parent
ebbc730fc3
commit
a1eefc013e
@ -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;
|
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;
|
lvtt = APIC_TDCR_1;
|
||||||
lapic_write(LAPIC_TIMER_DCR, lvtt);
|
lapic_write(LAPIC_TIMER_DCR, lvtt);
|
||||||
|
|
||||||
/* configure timer as one-shot */
|
/* configure timer as one-shot */
|
||||||
lvtt = APIC_TIMER_INT_VECTOR;
|
lvtt = APIC_TIMER_INT_VECTOR;
|
||||||
lapic_write(LAPIC_LVTTR, lvtt);
|
lapic_write(LAPIC_LVTTR, lvtt);
|
||||||
|
|
||||||
lapic_write(LAPIC_TIMER_ICR, usec * ticks_per_us);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PUBLIC void lapic_set_timer_periodic(const unsigned freq)
|
PUBLIC void lapic_set_timer_periodic(const unsigned freq)
|
||||||
|
@ -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 we know the address, lapic is enabled and we should use it */
|
||||||
if (lapic_addr) {
|
if (lapic_addr) {
|
||||||
unsigned cpu = cpuid;
|
unsigned cpu = cpuid;
|
||||||
lapic_set_timer_periodic(freq);
|
|
||||||
tsc_per_ms[cpu] = div64u(cpu_get_freq(cpu), 1000);
|
tsc_per_ms[cpu] = div64u(cpu_get_freq(cpu), 1000);
|
||||||
|
lapic_set_timer_one_shot(1000000/system_hz);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
BOOT_VERBOSE(printf("Initiating legacy i8253 timer\n"));
|
BOOT_VERBOSE(printf("Initiating legacy i8253 timer\n"));
|
||||||
|
@ -370,8 +370,6 @@ check_misc_flags:
|
|||||||
p = arch_finish_switch_to_user();
|
p = arch_finish_switch_to_user();
|
||||||
assert(!is_zero64(p->p_cpu_time_left));
|
assert(!is_zero64(p->p_cpu_time_left));
|
||||||
|
|
||||||
restart_local_timer();
|
|
||||||
|
|
||||||
context_stop(proc_addr(KERNEL));
|
context_stop(proc_addr(KERNEL));
|
||||||
|
|
||||||
/* If the process isn't the owner of FPU, enable the FPU exception */
|
/* If the process isn't the owner of FPU, enable the FPU exception */
|
||||||
@ -389,6 +387,9 @@ check_misc_flags:
|
|||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
refresh_tlb();
|
refresh_tlb();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
restart_local_timer();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* restore_user_context() carries out the actual mode switch from kernel
|
* restore_user_context() carries out the actual mode switch from kernel
|
||||||
* to userspace. This function does not return
|
* to userspace. This function does not return
|
||||||
|
Loading…
x
Reference in New Issue
Block a user