diff --git a/Kernel/Arch/x86/ISRStubs.h b/Kernel/Arch/x86/ISRStubs.h index 9f9d4ea39a..1108d8556a 100644 --- a/Kernel/Arch/x86/ISRStubs.h +++ b/Kernel/Arch/x86/ISRStubs.h @@ -11,6 +11,54 @@ #include VALIDATE_IS_X86() +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(32) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(33) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(34) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(35) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(36) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(37) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(38) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(39) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(40) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(41) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(42) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(43) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(44) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(45) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(46) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(47) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(48) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(49) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(50) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(51) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(52) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(53) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(54) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(55) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(56) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(57) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(58) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(59) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(60) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(61) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(62) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(63) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(64) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(65) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(66) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(67) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(68) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(69) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(70) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(71) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(72) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(73) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(74) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(75) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(76) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(77) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(78) +GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(79) GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(80) GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(81) GENERATE_GENERIC_INTERRUPT_HANDLER_ASM_ENTRY(82) diff --git a/Kernel/Arch/x86/Interrupts.h b/Kernel/Arch/x86/Interrupts.h index 6fafca5365..ef3fe2c85a 100644 --- a/Kernel/Arch/x86/Interrupts.h +++ b/Kernel/Arch/x86/Interrupts.h @@ -44,6 +44,7 @@ void register_interrupt_handler(u8 number, void (*handler)()); void register_user_callable_interrupt_handler(u8 number, void (*handler)()); GenericInterruptHandler& get_interrupt_handler(u8 interrupt_number); void register_generic_interrupt_handler(u8 number, GenericInterruptHandler&); +void register_disabled_interrupt_handler(u8 number, GenericInterruptHandler& handler); void unregister_generic_interrupt_handler(u8 number, GenericInterruptHandler&); void idt_init(); diff --git a/Kernel/Arch/x86/common/Interrupts.cpp b/Kernel/Arch/x86/common/Interrupts.cpp index d2af2608f3..7a0cf0e404 100644 --- a/Kernel/Arch/x86/common/Interrupts.cpp +++ b/Kernel/Arch/x86/common/Interrupts.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -42,6 +43,7 @@ READONLY_AFTER_INIT static DescriptorTablePointer s_idtr; READONLY_AFTER_INIT static IDTEntry s_idt[256]; static GenericInterruptHandler* s_interrupt_handler[GENERIC_INTERRUPT_HANDLERS_COUNT]; +static GenericInterruptHandler* s_disabled_interrupt_handler[2]; static EntropySource s_entropy_source_interrupts { EntropySource::Static::Interrupts }; @@ -496,10 +498,24 @@ void handle_interrupt(TrapFrame* trap) { clac(); auto& regs = *trap->regs; - VERIFY(regs.isr_number >= IRQ_VECTOR_BASE && regs.isr_number <= (IRQ_VECTOR_BASE + GENERIC_INTERRUPT_HANDLERS_COUNT)); - u8 irq = (u8)(regs.isr_number - 0x50); - s_entropy_source_interrupts.add_random_event(irq); - auto* handler = s_interrupt_handler[irq]; + + GenericInterruptHandler* handler = nullptr; + // Note: we declare interrupt service routine offset 0x20 to 0x2f as + // reserved for when the PIC is disabled, so we can still route spurious + // IRQs to a different interrupt handlers at different location. + if (regs.isr_number >= pic_disabled_vector_base && regs.isr_number <= pic_disabled_vector_end) { + u8 irq = (u8)(regs.isr_number - pic_disabled_vector_base); + if (irq == 7) { + handler = s_disabled_interrupt_handler[0]; + } else if (irq == 15) { + handler = s_disabled_interrupt_handler[1]; + } + } else { + VERIFY(regs.isr_number >= IRQ_VECTOR_BASE && regs.isr_number <= (IRQ_VECTOR_BASE + GENERIC_INTERRUPT_HANDLERS_COUNT)); + u8 irq = (u8)(regs.isr_number - IRQ_VECTOR_BASE); + s_entropy_source_interrupts.add_random_event(irq); + handler = s_interrupt_handler[irq]; + } VERIFY(handler); handler->increment_invoking_counter(); handler->handle_interrupt(regs); @@ -529,6 +545,18 @@ static void revert_to_unused_handler(u8 interrupt_number) handler->register_interrupt_handler(); } +void register_disabled_interrupt_handler(u8 number, GenericInterruptHandler& handler) +{ + if (number == 15) { + s_disabled_interrupt_handler[0] = &handler; + return; + } else if (number == 7) { + s_disabled_interrupt_handler[1] = &handler; + return; + } + VERIFY_NOT_REACHED(); +} + void register_generic_interrupt_handler(u8 interrupt_number, GenericInterruptHandler& handler) { VERIFY(interrupt_number < GENERIC_INTERRUPT_HANDLERS_COUNT); @@ -637,10 +665,58 @@ UNMAP_AFTER_INIT void idt_init() register_interrupt_handler(0x0f, _exception15); register_interrupt_handler(0x10, _exception16); - for (u8 i = 0x11; i < 0x50; i++) + for (u8 i = 0x11; i < 0x20; i++) register_interrupt_handler(i, unimp_trap); dbgln("Initializing unhandled interrupt handlers"); + register_interrupt_handler(0x20, interrupt_32_asm_entry); + register_interrupt_handler(0x21, interrupt_33_asm_entry); + register_interrupt_handler(0x22, interrupt_34_asm_entry); + register_interrupt_handler(0x23, interrupt_35_asm_entry); + register_interrupt_handler(0x24, interrupt_36_asm_entry); + register_interrupt_handler(0x25, interrupt_37_asm_entry); + register_interrupt_handler(0x26, interrupt_38_asm_entry); + register_interrupt_handler(0x27, interrupt_39_asm_entry); + register_interrupt_handler(0x28, interrupt_40_asm_entry); + register_interrupt_handler(0x29, interrupt_41_asm_entry); + register_interrupt_handler(0x2a, interrupt_42_asm_entry); + register_interrupt_handler(0x2b, interrupt_43_asm_entry); + register_interrupt_handler(0x2c, interrupt_44_asm_entry); + register_interrupt_handler(0x2d, interrupt_45_asm_entry); + register_interrupt_handler(0x2e, interrupt_46_asm_entry); + register_interrupt_handler(0x2f, interrupt_47_asm_entry); + register_interrupt_handler(0x30, interrupt_48_asm_entry); + register_interrupt_handler(0x31, interrupt_49_asm_entry); + register_interrupt_handler(0x32, interrupt_50_asm_entry); + register_interrupt_handler(0x33, interrupt_51_asm_entry); + register_interrupt_handler(0x34, interrupt_52_asm_entry); + register_interrupt_handler(0x35, interrupt_53_asm_entry); + register_interrupt_handler(0x36, interrupt_54_asm_entry); + register_interrupt_handler(0x37, interrupt_55_asm_entry); + register_interrupt_handler(0x38, interrupt_56_asm_entry); + register_interrupt_handler(0x39, interrupt_57_asm_entry); + register_interrupt_handler(0x3a, interrupt_58_asm_entry); + register_interrupt_handler(0x3b, interrupt_59_asm_entry); + register_interrupt_handler(0x3c, interrupt_60_asm_entry); + register_interrupt_handler(0x3d, interrupt_61_asm_entry); + register_interrupt_handler(0x3e, interrupt_62_asm_entry); + register_interrupt_handler(0x3f, interrupt_63_asm_entry); + register_interrupt_handler(0x40, interrupt_64_asm_entry); + register_interrupt_handler(0x41, interrupt_65_asm_entry); + register_interrupt_handler(0x42, interrupt_66_asm_entry); + register_interrupt_handler(0x43, interrupt_67_asm_entry); + register_interrupt_handler(0x44, interrupt_68_asm_entry); + register_interrupt_handler(0x45, interrupt_69_asm_entry); + register_interrupt_handler(0x46, interrupt_70_asm_entry); + register_interrupt_handler(0x47, interrupt_71_asm_entry); + register_interrupt_handler(0x48, interrupt_72_asm_entry); + register_interrupt_handler(0x49, interrupt_73_asm_entry); + register_interrupt_handler(0x4a, interrupt_74_asm_entry); + register_interrupt_handler(0x4b, interrupt_75_asm_entry); + register_interrupt_handler(0x4c, interrupt_76_asm_entry); + register_interrupt_handler(0x4d, interrupt_77_asm_entry); + register_interrupt_handler(0x4e, interrupt_78_asm_entry); + register_interrupt_handler(0x4f, interrupt_79_asm_entry); register_interrupt_handler(0x50, interrupt_80_asm_entry); register_interrupt_handler(0x51, interrupt_81_asm_entry); register_interrupt_handler(0x52, interrupt_82_asm_entry); diff --git a/Kernel/Interrupts/InterruptManagement.cpp b/Kernel/Interrupts/InterruptManagement.cpp index 56cf188706..3d2b3aecee 100644 --- a/Kernel/Interrupts/InterruptManagement.cpp +++ b/Kernel/Interrupts/InterruptManagement.cpp @@ -98,6 +98,15 @@ u8 InterruptManagement::get_irq_vector(u8 mapped_interrupt_vector) return mapped_interrupt_vector; } +RefPtr InterruptManagement::get_responsible_irq_controller(IRQControllerType controller_type, u8 interrupt_vector) +{ + for (auto& irq_controller : m_interrupt_controllers) { + if (irq_controller->gsi_base() <= interrupt_vector && irq_controller->type() == controller_type) + return irq_controller; + } + VERIFY_NOT_REACHED(); +} + RefPtr InterruptManagement::get_responsible_irq_controller(u8 interrupt_vector) { if (m_interrupt_controllers.size() == 1 && m_interrupt_controllers[0]->type() == IRQControllerType::i8259) { @@ -173,6 +182,8 @@ UNMAP_AFTER_INIT void InterruptManagement::switch_to_ioapic_mode() if (irq_controller->type() == IRQControllerType::i8259) { irq_controller->hard_disable(); dbgln("Interrupts: Detected {} - Disabled", irq_controller->model()); + SpuriousInterruptHandler::initialize_for_disabled_master_pic(); + SpuriousInterruptHandler::initialize_for_disabled_slave_pic(); } else { dbgln("Interrupts: Detected {}", irq_controller->model()); } diff --git a/Kernel/Interrupts/InterruptManagement.h b/Kernel/Interrupts/InterruptManagement.h index c567e33bb2..b17bbabd8d 100644 --- a/Kernel/Interrupts/InterruptManagement.h +++ b/Kernel/Interrupts/InterruptManagement.h @@ -54,6 +54,7 @@ public: bool smp_enabled() const { return m_smp_enabled; } RefPtr get_responsible_irq_controller(u8 interrupt_vector); + RefPtr get_responsible_irq_controller(IRQControllerType controller_type, u8 interrupt_vector); const Vector& isa_overrides() const { return m_isa_interrupt_overrides; } diff --git a/Kernel/Interrupts/PIC.h b/Kernel/Interrupts/PIC.h index 03ca59bf21..933d7aa28d 100644 --- a/Kernel/Interrupts/PIC.h +++ b/Kernel/Interrupts/PIC.h @@ -12,6 +12,7 @@ namespace Kernel { static constexpr size_t pic_disabled_vector_base = 0x20; +static constexpr size_t pic_disabled_vector_end = 0x2f; class PIC final : public IRQController { public: diff --git a/Kernel/Interrupts/SpuriousInterruptHandler.cpp b/Kernel/Interrupts/SpuriousInterruptHandler.cpp index be46acda39..b43f9fa574 100644 --- a/Kernel/Interrupts/SpuriousInterruptHandler.cpp +++ b/Kernel/Interrupts/SpuriousInterruptHandler.cpp @@ -4,7 +4,9 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include +#include #include #include @@ -16,6 +18,20 @@ UNMAP_AFTER_INIT void SpuriousInterruptHandler::initialize(u8 interrupt_number) handler->register_interrupt_handler(); } +void SpuriousInterruptHandler::initialize_for_disabled_master_pic() +{ + auto* handler = new SpuriousInterruptHandler(7); + register_disabled_interrupt_handler(7, *handler); + handler->enable_interrupt_vector_for_disabled_pic(); +} + +void SpuriousInterruptHandler::initialize_for_disabled_slave_pic() +{ + auto* handler = new SpuriousInterruptHandler(15); + register_disabled_interrupt_handler(15, *handler); + handler->enable_interrupt_vector_for_disabled_pic(); +} + void SpuriousInterruptHandler::register_handler(GenericInterruptHandler& handler) { VERIFY(!m_real_handler); @@ -70,6 +86,12 @@ bool SpuriousInterruptHandler::handle_interrupt(const RegisterState& state) return true; } +void SpuriousInterruptHandler::enable_interrupt_vector_for_disabled_pic() +{ + m_enabled = true; + m_responsible_irq_controller = InterruptManagement::the().get_responsible_irq_controller(IRQControllerType::i8259, interrupt_number()); +} + void SpuriousInterruptHandler::enable_interrupt_vector() { if (m_enabled) diff --git a/Kernel/Interrupts/SpuriousInterruptHandler.h b/Kernel/Interrupts/SpuriousInterruptHandler.h index e215228714..9a7aafa55e 100644 --- a/Kernel/Interrupts/SpuriousInterruptHandler.h +++ b/Kernel/Interrupts/SpuriousInterruptHandler.h @@ -16,6 +16,8 @@ namespace Kernel { class SpuriousInterruptHandler final : public GenericInterruptHandler { public: static void initialize(u8 interrupt_number); + static void initialize_for_disabled_master_pic(); + static void initialize_for_disabled_slave_pic(); virtual ~SpuriousInterruptHandler(); virtual bool handle_interrupt(const RegisterState& regs) override; @@ -32,6 +34,8 @@ public: virtual StringView purpose() const override; virtual StringView controller() const override; + void enable_interrupt_vector_for_disabled_pic(); + private: void enable_interrupt_vector(); void disable_interrupt_vector();