From 7770285aedb0446b15d4e2805e4dec251c08dd5b Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Thu, 25 Apr 2024 13:40:57 +0200 Subject: [PATCH] hw: remove duplicated definition of x86 local APIC Ref genodelabs/genode#5310 --- .../src/bootstrap/spec/x86_64/platform.cc | 71 ++++++------------- repos/base-hw/src/core/spec/x86_64/pic.cc | 2 +- repos/base-hw/src/core/spec/x86_64/pic.h | 36 +--------- .../base-hw/src/include/hw/spec/x86_64/apic.h | 64 +++++++++++++++++ 4 files changed, 90 insertions(+), 83 deletions(-) create mode 100644 repos/base-hw/src/include/hw/spec/x86_64/apic.h diff --git a/repos/base-hw/src/bootstrap/spec/x86_64/platform.cc b/repos/base-hw/src/bootstrap/spec/x86_64/platform.cc index 1668f9b0a8..185a079266 100644 --- a/repos/base-hw/src/bootstrap/spec/x86_64/platform.cc +++ b/repos/base-hw/src/bootstrap/spec/x86_64/platform.cc @@ -20,6 +20,7 @@ #include #include +#include using namespace Genode; @@ -274,57 +275,28 @@ Bootstrap::Platform::Board::Board() } -struct Lapic : Mmio +static inline +void ipi_to_all(Hw::Local_apic &lapic, unsigned const boot_frame, + Hw::Local_apic::Icr_low::Delivery_mode::Mode const mode) { - struct Svr : Register<0x0f0, 32> - { - struct APIC_enable : Bitfield<8, 1> { }; - }; + using Icr_low = Hw::Local_apic::Icr_low; - struct Icr_low : Register<0x300, 32> - { - struct Vector : Bitfield< 0, 8> { }; - struct Delivery_mode : Bitfield< 8, 3> - { - enum Mode { INIT = 5, SIPI = 6 }; - }; - struct Delivery_status : Bitfield<12, 1> { }; - struct Level_assert : Bitfield<14, 1> { }; - struct Dest_shorthand : Bitfield<18, 2> - { - enum { ALL_OTHERS = 3 }; - }; - }; - - struct Icr_high : Register<0x310, 32> - { - struct Destination : Bitfield<24, 8> { }; - }; - - Lapic(addr_t const addr) : Mmio({(char *)addr, Mmio::SIZE}) { } -}; - - -static inline void ipi_to_all(Lapic &lapic, unsigned const boot_frame, - Lapic::Icr_low::Delivery_mode::Mode const mode) -{ /* wait until ready */ - while (lapic.read()) + while (lapic.read()) asm volatile ("pause":::"memory"); unsigned const apic_cpu_id = 0; /* unused for IPI to all */ - Lapic::Icr_low::access_t icr_low = 0; - - Lapic::Icr_low::Vector::set(icr_low, boot_frame); - Lapic::Icr_low::Delivery_mode::set(icr_low, mode); - Lapic::Icr_low::Level_assert::set(icr_low); - Lapic::Icr_low::Level_assert::set(icr_low); - Lapic::Icr_low::Dest_shorthand::set(icr_low, Lapic::Icr_low::Dest_shorthand::ALL_OTHERS); + Icr_low::access_t icr_low = 0; + Icr_low::Vector::set(icr_low, boot_frame); + Icr_low::Delivery_mode::set(icr_low, mode); + Icr_low::Level_assert::set(icr_low); + Icr_low::Level_assert::set(icr_low); + Icr_low::Dest_shorthand::set(icr_low, Icr_low::Dest_shorthand::ALL_OTHERS); /* program */ - lapic.write(apic_cpu_id); - lapic.write(icr_low); + lapic.write(apic_cpu_id); + lapic.write(icr_low); } @@ -356,11 +328,11 @@ unsigned Bootstrap::Platform::enable_mmu() Cpu::IA32_apic_base::Lapic::set(lapic_msr); Cpu::IA32_apic_base::write(lapic_msr); - Lapic lapic(board.core_mmio.virt_addr(Hw::Cpu_memory_map::lapic_phys_base())); + Hw::Local_apic lapic(board.core_mmio.virt_addr(Hw::Cpu_memory_map::lapic_phys_base())); /* enable local APIC if required */ - if (!lapic.read()) - lapic.write(true); + if (!lapic.read()) + lapic.write(true); /* reset assembly counter (crt0.s) by last booted CPU, required for resume */ if (__cpus_booted >= board.cpus) @@ -377,12 +349,15 @@ unsigned Bootstrap::Platform::enable_mmu() /* BSP - we're primary CPU - wake now all other CPUs */ /* see Intel Multiprocessor documentation - we need to do INIT-SIPI-SIPI */ - ipi_to_all(lapic, 0 /* unused */, Lapic::Icr_low::Delivery_mode::INIT); + ipi_to_all(lapic, 0 /* unused */, + Hw::Local_apic::Icr_low::Delivery_mode::INIT); /* wait 10 ms - debates ongoing whether this is still required */ - ipi_to_all(lapic, AP_BOOT_CODE_PAGE >> 12, Lapic::Icr_low::Delivery_mode::SIPI); + ipi_to_all(lapic, AP_BOOT_CODE_PAGE >> 12, + Hw::Local_apic::Icr_low::Delivery_mode::SIPI); /* wait 200 us - debates ongoing whether this is still required */ /* debates ongoing whether the second SIPI is still required */ - ipi_to_all(lapic, AP_BOOT_CODE_PAGE >> 12, Lapic::Icr_low::Delivery_mode::SIPI); + ipi_to_all(lapic, AP_BOOT_CODE_PAGE >> 12, + Hw::Local_apic::Icr_low::Delivery_mode::SIPI); return (unsigned)cpu_id; } diff --git a/repos/base-hw/src/core/spec/x86_64/pic.cc b/repos/base-hw/src/core/spec/x86_64/pic.cc index 99cdef7574..645f81953c 100644 --- a/repos/base-hw/src/core/spec/x86_64/pic.cc +++ b/repos/base-hw/src/core/spec/x86_64/pic.cc @@ -39,7 +39,7 @@ enum { Local_interrupt_controller:: Local_interrupt_controller(Global_interrupt_controller &global_irq_ctrl) : - Mmio { {(char *)Platform::mmio_to_virt(Hw::Cpu_memory_map::lapic_phys_base()), Mmio::SIZE} }, + Local_apic({Platform::mmio_to_virt(Hw::Cpu_memory_map::lapic_phys_base())}), _global_irq_ctrl { global_irq_ctrl } { init(); diff --git a/repos/base-hw/src/core/spec/x86_64/pic.h b/repos/base-hw/src/core/spec/x86_64/pic.h index dc31eb99f9..9079ee25bd 100644 --- a/repos/base-hw/src/core/spec/x86_64/pic.h +++ b/repos/base-hw/src/core/spec/x86_64/pic.h @@ -17,6 +17,7 @@ /* Genode includes */ #include +#include #include namespace Board { @@ -148,43 +149,10 @@ class Board::Global_interrupt_controller : public Genode::Mmio +class Board::Local_interrupt_controller : private Hw::Local_apic { private: - /* - * Registers - */ - - struct Id : Register<0x020, 32> { }; - struct EOI : Register<0x0b0, 32, true> { }; - struct Svr : Register<0x0f0, 32> - { - struct APIC_enable : Bitfield<8, 1> { }; - }; - - /* - * ISR register, see Intel SDM Vol. 3A, section 10.8.4. - * - * Each of the 8 32-bit ISR values is followed by 12 bytes of padding. - */ - struct Isr : Register_array<0x100, 32, 8 * 4, 32> { }; - - /* - * Interrupt control register - */ - struct Icr_low : Register<0x300, 32, true> - { - struct Vector : Bitfield< 0, 8> { }; - struct Delivery_status : Bitfield<12, 1> { }; - struct Level_assert : Bitfield<14, 1> { }; - }; - - struct Icr_high : Register<0x310, 32, true> - { - struct Destination : Bitfield<24, 8> { }; - }; - Global_interrupt_controller &_global_irq_ctrl; /** diff --git a/repos/base-hw/src/include/hw/spec/x86_64/apic.h b/repos/base-hw/src/include/hw/spec/x86_64/apic.h new file mode 100644 index 0000000000..db1586047a --- /dev/null +++ b/repos/base-hw/src/include/hw/spec/x86_64/apic.h @@ -0,0 +1,64 @@ +/* + * \brief APIC definitions + * \author Stefan Kalkowski + * \date 2024-04-25 + */ + +/* + * Copyright (C) 2024 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__INCLUDE__HW__SPEC__X86_64__APIC_H_ +#define _SRC__INCLUDE__HW__SPEC__X86_64__APIC_H_ + +namespace Hw { class Local_apic; } + +#include + +struct Hw::Local_apic : Genode::Mmio +{ + struct Id : Register<0x020, 32> { }; + struct EOI : Register<0x0b0, 32, true> { }; + struct Svr : Register<0x0f0, 32> + { + struct APIC_enable : Bitfield<8, 1> { }; + }; + + /* + * ISR register, see Intel SDM Vol. 3A, section 10.8.4. + * + * Each of the 8 32-bit ISR values is followed by 12 bytes of padding. + */ + struct Isr : Register_array<0x100, 32, 8 * 4, 32> { }; + + /* + * Interrupt control register + */ + struct Icr_low : Register<0x300, 32, true> + { + struct Vector : Bitfield< 0, 8> { }; + struct Delivery_mode : Bitfield< 8, 3> + { + enum Mode { INIT = 5, SIPI = 6 }; + }; + + struct Delivery_status : Bitfield<12, 1> { }; + struct Level_assert : Bitfield<14, 1> { }; + struct Dest_shorthand : Bitfield<18, 2> + { + enum { ALL_OTHERS = 3 }; + }; + }; + + struct Icr_high : Register<0x310, 32, true> + { + struct Destination : Bitfield<24, 8> { }; + }; + + Local_apic(addr_t const addr) : Mmio({(char*)addr, Mmio::SIZE}) {} +}; + +#endif /* _SRC__INCLUDE__HW__SPEC__X86_64__APIC_H_ */