diff --git a/Kernel/Interrupts/GenericInterruptHandler.cpp b/Kernel/Interrupts/GenericInterruptHandler.cpp index 00074b3619..12f078d811 100644 --- a/Kernel/Interrupts/GenericInterruptHandler.cpp +++ b/Kernel/Interrupts/GenericInterruptHandler.cpp @@ -39,20 +39,20 @@ GenericInterruptHandler& GenericInterruptHandler::from(u8 interrupt_number) GenericInterruptHandler::GenericInterruptHandler(u8 interrupt_number) : m_interrupt_number(interrupt_number) { - register_generic_interrupt_handler(interrupt_number, *this); + register_generic_interrupt_handler(InterruptManagement::acquire_mapped_interrupt_number(m_interrupt_number), *this); } GenericInterruptHandler::~GenericInterruptHandler() { - unregister_generic_interrupt_handler(m_interrupt_number, *this); + unregister_generic_interrupt_handler(InterruptManagement::acquire_mapped_interrupt_number(m_interrupt_number), *this); } void GenericInterruptHandler::change_interrupt_number(u8 number) { ASSERT_INTERRUPTS_ENABLED(); - unregister_generic_interrupt_handler(interrupt_number(), *this); + unregister_generic_interrupt_handler(InterruptManagement::acquire_mapped_interrupt_number(interrupt_number()), *this); m_interrupt_number = number; - register_generic_interrupt_handler(interrupt_number(), *this); + register_generic_interrupt_handler(InterruptManagement::acquire_mapped_interrupt_number(interrupt_number()), *this); } void GenericInterruptHandler::increment_invoking_counter() { diff --git a/Kernel/Interrupts/IOAPIC.cpp b/Kernel/Interrupts/IOAPIC.cpp index dca67b6ead..c1cb1d495b 100644 --- a/Kernel/Interrupts/IOAPIC.cpp +++ b/Kernel/Interrupts/IOAPIC.cpp @@ -42,15 +42,14 @@ enum DeliveryMode { External = 7 }; -IOAPIC::IOAPIC(ioapic_mmio_regs& regs, u32 gsi_base, Vector>& isa_overrides, Vector>& pci_overrides) +IOAPIC::IOAPIC(ioapic_mmio_regs& regs, u32 gsi_base) : m_physical_access_registers(regs) , m_gsi_base(gsi_base) , m_id((read_register(0x0) >> 24) & 0xFF) , m_version(read_register(0x1) & 0xFF) , m_redirection_entries((read_register(0x1) >> 16) + 1) - , m_isa_interrupt_overrides(isa_overrides) - , m_pci_interrupt_overrides(pci_overrides) { + InterruptDisabler disabler; klog() << "IOAPIC ID: 0x" << String::format("%x", m_id); klog() << "IOAPIC Version: 0x" << String::format("%x", m_version) << ", Redirection Entries count - " << m_redirection_entries; klog() << "IOAPIC Arbitration ID 0x" << String::format("%x", read_register(0x2)); @@ -63,11 +62,8 @@ void IOAPIC::initialize() void IOAPIC::map_interrupt_redirection(u8 interrupt_vector) { - if (interrupt_vector == 11) { - configure_redirection_entry(11, 11 + IRQ_VECTOR_BASE, DeliveryMode::LowPriority, false, true, true, true, 0); - return; - } - for (auto redirection_override : m_isa_interrupt_overrides) { + InterruptDisabler disabler; + for (auto redirection_override : InterruptManagement::the().isa_overrides()) { ASSERT(!redirection_override.is_null()); if (redirection_override->source() != interrupt_vector) continue; @@ -102,7 +98,7 @@ void IOAPIC::map_interrupt_redirection(u8 interrupt_vector) trigger_level_mode = true; break; } - configure_redirection_entry(redirection_override->gsi(), redirection_override->source() + IRQ_VECTOR_BASE, DeliveryMode::LowPriority, false, active_low, trigger_level_mode, true, 0); + configure_redirection_entry(redirection_override->gsi(), InterruptManagement::acquire_mapped_interrupt_number(redirection_override->source()) + IRQ_VECTOR_BASE, DeliveryMode::Normal, false, active_low, trigger_level_mode, true, 0); return; } isa_identity_map(interrupt_vector); @@ -110,18 +106,20 @@ void IOAPIC::map_interrupt_redirection(u8 interrupt_vector) void IOAPIC::isa_identity_map(int index) { - configure_redirection_entry(index, index + IRQ_VECTOR_BASE, DeliveryMode::Normal, true, false, false, true, 1); + InterruptDisabler disabler; + configure_redirection_entry(index, InterruptManagement::acquire_mapped_interrupt_number(index) + IRQ_VECTOR_BASE, DeliveryMode::Normal, false, false, false, true, 0); } void IOAPIC::map_pci_interrupts() { + InterruptDisabler disabler; configure_redirection_entry(11, 11 + IRQ_VECTOR_BASE, DeliveryMode::Normal, false, false, true, true, 0); } void IOAPIC::map_isa_interrupts() { InterruptDisabler disabler; - for (auto redirection_override : m_isa_interrupt_overrides) { + for (auto redirection_override : InterruptManagement::the().isa_overrides()) { ASSERT(!redirection_override.is_null()); bool active_low; // See ACPI spec Version 6.2, page 205 to learn more about Interrupt Overriding Flags. @@ -154,7 +152,7 @@ void IOAPIC::map_isa_interrupts() trigger_level_mode = true; break; } - configure_redirection_entry(redirection_override->gsi(), redirection_override->source() + IRQ_VECTOR_BASE, 0, false, active_low, trigger_level_mode, true, 0); + configure_redirection_entry(redirection_override->gsi(), InterruptManagement::acquire_mapped_interrupt_number(redirection_override->source()) + IRQ_VECTOR_BASE, 0, false, active_low, trigger_level_mode, true, 0); } } @@ -180,6 +178,7 @@ void IOAPIC::reset_redirection_entry(int index) const void IOAPIC::configure_redirection_entry(int index, u8 interrupt_vector, u8 delivery_mode, bool logical_destination, bool active_low, bool trigger_level_mode, bool masked, u8 destination) const { + InterruptDisabler disabler; ASSERT((u32)index < m_redirection_entries); u32 redirection_entry1 = interrupt_vector | (delivery_mode & 0b111) << 8 | logical_destination << 11 | active_low << 13 | trigger_level_mode << 15 | masked << 16; u32 redirection_entry2 = destination << 24; @@ -236,7 +235,7 @@ int IOAPIC::find_redirection_entry_by_vector(u8 vector) const { InterruptDisabler disabler; for (size_t index = 0; index < m_redirection_entries; index++) { - if (read_redirection_entry_vector(index) == (vector + IRQ_VECTOR_BASE)) + if (read_redirection_entry_vector(index) == (InterruptManagement::acquire_mapped_interrupt_number(vector) + IRQ_VECTOR_BASE)) return index; } return -1; diff --git a/Kernel/Interrupts/IOAPIC.h b/Kernel/Interrupts/IOAPIC.h index 4192421dfa..d7d629ecce 100644 --- a/Kernel/Interrupts/IOAPIC.h +++ b/Kernel/Interrupts/IOAPIC.h @@ -41,7 +41,7 @@ class PCIInterruptOverrideMetadata; class IOAPIC final : public IRQController { public: - IOAPIC(ioapic_mmio_regs& regs, u32 gsi_base, Vector>& overrides, Vector>& pci_overrides); + IOAPIC(ioapic_mmio_regs& regs, u32 gsi_base); virtual void enable(u8 number) override; virtual void disable(u8 number) override; virtual void hard_disable() override; @@ -81,7 +81,5 @@ private: u8 m_id; u8 m_version; u32 m_redirection_entries; - Vector> m_isa_interrupt_overrides; - Vector> m_pci_interrupt_overrides; }; } diff --git a/Kernel/Interrupts/InterruptManagement.cpp b/Kernel/Interrupts/InterruptManagement.cpp index b6217e5638..adf9b0400b 100644 --- a/Kernel/Interrupts/InterruptManagement.cpp +++ b/Kernel/Interrupts/InterruptManagement.cpp @@ -27,11 +27,14 @@ #include #include #include +#include #include #include #include #include +#include #include +#include #define PCAT_COMPAT_FLAG 0x1 @@ -72,6 +75,26 @@ IRQController& InterruptManagement::get_interrupt_controller(int index) return *m_interrupt_controllers[index]; } +Vector> InterruptManagement::isa_overrides() +{ + return m_isa_interrupt_overrides; +} + +u8 InterruptManagement::acquire_mapped_interrupt_number(u8 number) +{ + if (!InterruptManagement::initialized()) { + // This is necessary, because we install UnhandledInterruptHandlers before we actually initialize the Interrupt Management object... + return number; + } + return InterruptManagement::the().get_mapped_vector_number(number); +} + +u8 InterruptManagement::get_mapped_vector_number(u8 original_vector) +{ + // FIXME: For SMP configuration (with IOAPICs) use a better routing scheme to make redirections more efficient. + return original_vector; +} + RefPtr InterruptManagement::get_responsible_irq_controller(u8 interrupt_vector) { if (m_interrupt_controllers.size() == 1 && m_interrupt_controllers[0]->type() == IRQControllerType::i8259) { @@ -110,6 +133,8 @@ InterruptManagement::InterruptManagement() void InterruptManagement::switch_to_pic_mode() { klog() << "Interrupts: Switch to Legacy PIC mode"; + InterruptDisabler disabler; + m_smp_enabled = false; SpuriousInterruptHandler::initialize(7); SpuriousInterruptHandler::initialize(15); for (auto& irq_controller : m_interrupt_controllers) { @@ -126,6 +151,8 @@ void InterruptManagement::switch_to_pic_mode() void InterruptManagement::switch_to_ioapic_mode() { klog() << "Interrupts: Switch to IOAPIC mode"; + InterruptDisabler disabler; + m_smp_enabled = true; if (m_interrupt_controllers.size() == 1) { if (get_interrupt_controller(0).type() == IRQControllerType::i8259) { klog() << "Interrupts: NO IOAPIC detected, Reverting to PIC mode."; @@ -141,6 +168,9 @@ void InterruptManagement::switch_to_ioapic_mode() dbg() << "Interrupts: Detected " << irq_controller->model(); } } + APIC::init(); + APIC::enable_bsp(); + MultiProcessorParser::initialize(); } void InterruptManagement::locate_apic_data() @@ -163,7 +193,7 @@ void InterruptManagement::locate_apic_data() auto* ioapic_entry = (const ACPI::Structures::MADTEntries::IOAPIC*)madt_entry; dbg() << "IOAPIC found @ MADT entry " << entry_index << ", MMIO Registers @ Px" << String::format("%x", ioapic_entry->ioapic_address); m_interrupt_controllers.resize(1 + irq_controller_count); - m_interrupt_controllers[irq_controller_count] = adopt(*new IOAPIC(*(ioapic_mmio_regs*)ioapic_entry->ioapic_address, ioapic_entry->gsi_base, m_isa_interrupt_overrides, m_pci_interrupt_overrides)); + m_interrupt_controllers[irq_controller_count] = adopt(*new IOAPIC(*(ioapic_mmio_regs*)ioapic_entry->ioapic_address, ioapic_entry->gsi_base)); irq_controller_count++; } if (madt_entry->type == (u8)ACPI::Structures::MADTEntryType::InterruptSourceOverride) { diff --git a/Kernel/Interrupts/InterruptManagement.h b/Kernel/Interrupts/InterruptManagement.h index 50c695a18d..9c448c45be 100644 --- a/Kernel/Interrupts/InterruptManagement.h +++ b/Kernel/Interrupts/InterruptManagement.h @@ -47,11 +47,16 @@ public: static InterruptManagement& the(); static void initialize(); static bool initialized(); + static u8 acquire_mapped_interrupt_number(u8); virtual void switch_to_pic_mode(); virtual void switch_to_ioapic_mode(); RefPtr get_responsible_irq_controller(u8 interrupt_vector); + Vector> isa_overrides(); + + u8 get_mapped_vector_number(u8 original_vector); + void enumerate_interrupt_handlers(Function); IRQController& get_interrupt_controller(int index); @@ -60,6 +65,7 @@ private: PhysicalAddress search_for_madt(); void locate_apic_data(); void locate_pci_interrupt_overrides(); + bool m_smp_enabled { false }; FixedArray> m_interrupt_controllers { 1 }; Vector> m_isa_interrupt_overrides; Vector> m_pci_interrupt_overrides;