- 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
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)
/* 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"));
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 */
#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