diff options
author | Tom <tomut@yahoo.com> | 2021-02-26 10:59:37 -0700 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-02-26 21:15:38 +0100 |
commit | af2220448834fb0bff5132bf68104719819862ce (patch) | |
tree | e664f8405cf2f0f7c018e70688919e227d2fe049 /Kernel | |
parent | 85ea60b7f1121a95ffc2429d367ec211692cef16 (diff) | |
download | serenity-af2220448834fb0bff5132bf68104719819862ce.zip |
Kernel: Fix HPET timer structure layout
Only the first 3 timers have a reserved field, the 29 other timers
do not have a reserved field.
Fixes #5530
Diffstat (limited to 'Kernel')
-rw-r--r-- | Kernel/Time/HPET.cpp | 48 | ||||
-rw-r--r-- | Kernel/Time/HPET.h | 2 |
2 files changed, 33 insertions, 17 deletions
diff --git a/Kernel/Time/HPET.cpp b/Kernel/Time/HPET.cpp index 7e2da58347..f36d407c62 100644 --- a/Kernel/Time/HPET.cpp +++ b/Kernel/Time/HPET.cpp @@ -74,6 +74,10 @@ struct [[gnu::packed]] TimerStructure { volatile u32 interrupt_routing; HPETRegister comparator_value; volatile u64 fsb_interrupt_route; +}; + +struct [[gnu::packed]] TimerStructureWithReserved { + TimerStructure timer; u64 reserved; }; @@ -92,13 +96,24 @@ struct [[gnu::packed]] HPETRegistersBlock { u8 reserved2[0xF0 - 0x28]; HPETRegister main_counter_value; u64 reserved3; - TimerStructure timers[3]; - u8 reserved4[0x400 - 0x160]; + TimerStructureWithReserved timers[3]; + TimerStructure timers2[29]; + + ALWAYS_INLINE TimerStructure& get_timer_by_index(unsigned index) + { + VERIFY(index < 32); + if (index < 3) + return timers[index].timer; + return timers2[index - 3]; + } }; +static_assert(sizeof(TimerStructure) == 0x18); +static_assert(sizeof(TimerStructureWithReserved) == 0x20); static_assert(__builtin_offsetof(HPETRegistersBlock, main_counter_value) == 0xf0); static_assert(__builtin_offsetof(HPETRegistersBlock, timers[0]) == 0x100); static_assert(__builtin_offsetof(HPETRegistersBlock, timers[1]) == 0x120); +static_assert(sizeof(HPETRegistersBlock) == 0x418); static u64 read_register_safe64(const HPETRegister& reg) { @@ -166,7 +181,7 @@ UNMAP_AFTER_INIT bool HPET::check_for_exisiting_periodic_timers() size_t timers_count = ((registers->capabilities.attributes >> 8) & 0x1f) + 1; for (size_t index = 0; index < timers_count; index++) { - if (registers->timers[index].capabilities & (u32)HPETFlags::TimerConfiguration::PeriodicInterruptCapable) + if (registers->get_timer_by_index(index).capabilities & (u32)HPETFlags::TimerConfiguration::PeriodicInterruptCapable) return true; } return false; @@ -197,7 +212,7 @@ void HPET::update_periodic_comparator_value() regs.main_counter_value.low = 0; regs.main_counter_value.high = 0; for (auto& comparator : m_comparators) { - auto& timer = regs.timers[comparator.comparator_number()]; + auto& timer = regs.get_timer_by_index(comparator.comparator_number()); if (!comparator.is_enabled()) continue; if (comparator.is_periodic()) { @@ -236,7 +251,7 @@ void HPET::update_non_periodic_comparator_value(const HPETComparator& comparator VERIFY(!comparator.is_periodic()); VERIFY(comparator.comparator_number() <= m_comparators.size()); auto& regs = registers(); - auto& timer = regs.timers[comparator.comparator_number()]; + auto& timer = regs.get_timer_by_index(comparator.comparator_number()); u64 value = frequency() / comparator.ticks_per_second(); // NOTE: If the main counter passes this new value before we finish writing it, we will never receive an interrupt! u64 new_counter_value = read_register_safe64(regs.main_counter_value) + value; @@ -284,7 +299,7 @@ void HPET::enable_periodic_interrupt(const HPETComparator& comparator) #endif disable(comparator); VERIFY(comparator.comparator_number() <= m_comparators.size()); - auto& timer = registers().timers[comparator.comparator_number()]; + auto& timer = registers().get_timer_by_index(comparator.comparator_number()); auto capabilities = timer.capabilities; VERIFY(capabilities & (u32)HPETFlags::TimerConfiguration::PeriodicInterruptCapable); timer.capabilities = capabilities | (u32)HPETFlags::TimerConfiguration::GeneratePeriodicInterrupt; @@ -298,7 +313,7 @@ void HPET::disable_periodic_interrupt(const HPETComparator& comparator) #endif disable(comparator); VERIFY(comparator.comparator_number() <= m_comparators.size()); - auto& timer = registers().timers[comparator.comparator_number()]; + auto& timer = registers().get_timer_by_index(comparator.comparator_number()); auto capabilities = timer.capabilities; VERIFY(capabilities & (u32)HPETFlags::TimerConfiguration::PeriodicInterruptCapable); timer.capabilities = capabilities & ~(u32)HPETFlags::TimerConfiguration::GeneratePeriodicInterrupt; @@ -312,7 +327,7 @@ void HPET::disable(const HPETComparator& comparator) klog() << "HPET: Disable comparator " << comparator.comparator_number() << "."; #endif VERIFY(comparator.comparator_number() <= m_comparators.size()); - auto& timer = registers().timers[comparator.comparator_number()]; + auto& timer = registers().get_timer_by_index(comparator.comparator_number()); timer.capabilities = timer.capabilities & ~(u32)HPETFlags::TimerConfiguration::InterruptEnable; } void HPET::enable(const HPETComparator& comparator) @@ -321,7 +336,7 @@ void HPET::enable(const HPETComparator& comparator) klog() << "HPET: Enable comparator " << comparator.comparator_number() << "."; #endif VERIFY(comparator.comparator_number() <= m_comparators.size()); - auto& timer = registers().timers[comparator.comparator_number()]; + auto& timer = registers().get_timer_by_index(comparator.comparator_number()); timer.capabilities = timer.capabilities | (u32)HPETFlags::TimerConfiguration::InterruptEnable; } @@ -329,7 +344,7 @@ Vector<unsigned> HPET::capable_interrupt_numbers(const HPETComparator& comparato { VERIFY(comparator.comparator_number() <= m_comparators.size()); Vector<unsigned> capable_interrupts; - auto& comparator_registers = registers().timers[comparator.comparator_number()]; + auto& comparator_registers = registers().get_timer_by_index(comparator.comparator_number()); u32 interrupt_bitfield = comparator_registers.interrupt_routing; for (size_t index = 0; index < 32; index++) { if (interrupt_bitfield & 1) @@ -343,7 +358,7 @@ Vector<unsigned> HPET::capable_interrupt_numbers(u8 comparator_number) { VERIFY(comparator_number <= m_comparators.size()); Vector<unsigned> capable_interrupts; - auto& comparator_registers = registers().timers[comparator_number]; + auto& comparator_registers = registers().get_timer_by_index(comparator_number); u32 interrupt_bitfield = comparator_registers.interrupt_routing; for (size_t index = 0; index < 32; index++) { if (interrupt_bitfield & 1) @@ -356,14 +371,14 @@ Vector<unsigned> HPET::capable_interrupt_numbers(u8 comparator_number) void HPET::set_comparator_irq_vector(u8 comparator_number, u8 irq_vector) { VERIFY(comparator_number <= m_comparators.size()); - auto& comparator_registers = registers().timers[comparator_number]; + auto& comparator_registers = registers().get_timer_by_index(comparator_number); comparator_registers.capabilities = comparator_registers.capabilities | (irq_vector << 9); } -bool HPET::is_periodic_capable(u8 comparator_number) const +bool HPET::is_periodic_capable(u8 comparator_number) { VERIFY(comparator_number <= m_comparators.size()); - auto& comparator_registers = registers().timers[comparator_number]; + auto& comparator_registers = registers().get_timer_by_index(comparator_number); return comparator_registers.capabilities & (u32)HPETFlags::TimerConfiguration::PeriodicInterruptCapable; } @@ -415,8 +430,9 @@ UNMAP_AFTER_INIT HPET::HPET(PhysicalAddress acpi_hpet) klog() << "HPET: Timers count - " << timers_count; klog() << "HPET: Main counter size: " << ((regs.capabilities.attributes & (u32)HPETFlags::Attributes::Counter64BitCapable) ? "64 bit" : "32 bit"); for (size_t i = 0; i < timers_count; i++) { - bool capable_64_bit = regs.timers[i].capabilities & (u32)HPETFlags::TimerConfiguration::Timer64BitsCapable; - klog() << "HPET: Timer[" << i << "] comparator size: " << (capable_64_bit ? "64 bit" : "32 bit") << " mode: " << ((!capable_64_bit || (regs.timers[i].capabilities & (u32)HPETFlags::TimerConfiguration::Force32BitMode)) ? "32 bit" : "64 bit"); + auto& timer = regs.get_timer_by_index(i); + bool capable_64_bit = timer.capabilities & (u32)HPETFlags::TimerConfiguration::Timer64BitsCapable; + klog() << "HPET: Timer[" << i << "] comparator size: " << (capable_64_bit ? "64 bit" : "32 bit") << " mode: " << ((!capable_64_bit || (timer.capabilities & (u32)HPETFlags::TimerConfiguration::Force32BitMode)) ? "32 bit" : "64 bit"); } VERIFY(timers_count >= 2); diff --git a/Kernel/Time/HPET.h b/Kernel/Time/HPET.h index 696617bbbe..7cdc15fb74 100644 --- a/Kernel/Time/HPET.h +++ b/Kernel/Time/HPET.h @@ -72,7 +72,7 @@ private: void global_disable(); void global_enable(); - bool is_periodic_capable(u8 comparator_number) const; + bool is_periodic_capable(u8 comparator_number); void set_comparators_to_optimal_interrupt_state(size_t timers_count); u64 calculate_ticks_in_nanoseconds() const; |