diff --git a/repos/base-hw/src/core/spec/x86_64/timer.cc b/repos/base-hw/src/core/spec/x86_64/timer.cc index b75b25b5c..fe008d633 100644 --- a/repos/base-hw/src/core/spec/x86_64/timer.cc +++ b/repos/base-hw/src/core/spec/x86_64/timer.cc @@ -56,18 +56,25 @@ uint32_t Timer_driver::pit_calc_timer_freq(void) Timer_driver::Timer_driver(unsigned) : Mmio(Platform::mmio_to_virt(Hw::Cpu_memory_map::MMIO_LAPIC_BASE)) { - write( - Divide_configuration::Divide_value::MAX); - /* Enable LAPIC timer in one-shot mode */ write(Board::TIMER_VECTOR_KERNEL); write(0); write(0); write(0); - /* Calculate timer frequency */ - ticks_per_ms = pit_calc_timer_freq(); - assert(ticks_per_ms >= TIMER_MIN_TICKS_PER_MS); + /* calibrate LAPIC frequency to fullfill our requirements */ + for (Divide_configuration::access_t div = Divide_configuration::Divide_value::MAX; + div && ticks_per_ms < TIMER_MIN_TICKS_PER_MS; div--) + { + if (!div){ + error("Failed to calibrate timer frequency"); + throw Calibration_failed(); + } + write(div); + + /* Calculate timer frequency */ + ticks_per_ms = pit_calc_timer_freq(); + } } diff --git a/repos/base-hw/src/core/spec/x86_64/timer_driver.h b/repos/base-hw/src/core/spec/x86_64/timer_driver.h index ac95fd0de..6b9dbca77 100644 --- a/repos/base-hw/src/core/spec/x86_64/timer_driver.h +++ b/repos/base-hw/src/core/spec/x86_64/timer_driver.h @@ -63,6 +63,8 @@ struct Kernel::Timer_driver : Genode::Mmio }; }; + struct Calibration_failed : Genode::Exception { }; + Genode::uint32_t ticks_per_ms = 0; /* Measure LAPIC timer frequency using PIT channel 2 */