diff --git a/kernel/arch/x86_64/IDT.cpp b/kernel/arch/x86_64/IDT.cpp index c11ff2b8..dce1d4e3 100644 --- a/kernel/arch/x86_64/IDT.cpp +++ b/kernel/arch/x86_64/IDT.cpp @@ -10,7 +10,7 @@ #include #define ISR_LIST_X X(0) X(1) X(2) X(3) X(4) X(5) X(6) X(7) X(8) X(9) X(10) X(11) X(12) X(13) X(14) X(15) X(16) X(17) X(18) X(19) X(20) X(21) X(22) X(23) X(24) X(25) X(26) X(27) X(28) X(29) X(30) X(31) -#define IRQ_LIST_X X(0) X(1) X(2) X(3) X(4) X(5) X(6) X(7) X(8) X(9) X(10) X(11) X(12) X(13) X(14) X(15) X(16) X(17) X(18) X(19) X(20) X(21) X(22) X(23) X(24) X(25) X(26) X(27) X(28) X(29) X(30) X(31) +#define IRQ_LIST_X X(0) X(1) X(2) X(3) X(4) X(5) X(6) X(7) X(8) X(9) X(10) X(11) X(12) X(13) X(14) X(15) X(16) X(17) X(18) X(19) X(20) X(21) X(22) X(23) X(24) X(25) X(26) X(27) X(28) X(29) X(30) X(31) X(32) namespace Kernel { diff --git a/kernel/arch/x86_64/interrupts.S b/kernel/arch/x86_64/interrupts.S index 45acaa6a..7a78e818 100644 --- a/kernel/arch/x86_64/interrupts.S +++ b/kernel/arch/x86_64/interrupts.S @@ -174,6 +174,7 @@ irq 28 irq 29 irq 30 irq 31 +irq 32 // arguments in RAX, RBX, RCX, RDX, RSI, RDI // System V ABI: RDI, RSI, RDX, RCX, R8, R9 diff --git a/kernel/include/kernel/APIC.h b/kernel/include/kernel/APIC.h index 2e57e5de..074a5e07 100644 --- a/kernel/include/kernel/APIC.h +++ b/kernel/include/kernel/APIC.h @@ -19,6 +19,8 @@ namespace Kernel virtual BAN::Optional get_free_irq() override; virtual void initialize_multiprocessor() override; + virtual void broadcast_ipi() override; + virtual void enable() override; private: uint32_t read_from_local_apic(ptrdiff_t); diff --git a/kernel/include/kernel/IDT.h b/kernel/include/kernel/IDT.h index 0a79c8a8..b99a66f2 100644 --- a/kernel/include/kernel/IDT.h +++ b/kernel/include/kernel/IDT.h @@ -7,6 +7,7 @@ #include constexpr uint8_t IRQ_VECTOR_BASE = 0x20; +constexpr uint8_t IRQ_IPI = 32; namespace Kernel { diff --git a/kernel/include/kernel/InterruptController.h b/kernel/include/kernel/InterruptController.h index 82b286e9..115d0112 100644 --- a/kernel/include/kernel/InterruptController.h +++ b/kernel/include/kernel/InterruptController.h @@ -21,6 +21,8 @@ namespace Kernel static InterruptController& get(); virtual void initialize_multiprocessor() = 0; + virtual void broadcast_ipi() = 0; + virtual void enable() = 0; virtual BAN::ErrorOr reserve_irq(uint8_t irq) = 0; virtual BAN::Optional get_free_irq() = 0; diff --git a/kernel/include/kernel/PIC.h b/kernel/include/kernel/PIC.h index 51fe0413..117071a4 100644 --- a/kernel/include/kernel/PIC.h +++ b/kernel/include/kernel/PIC.h @@ -17,6 +17,8 @@ namespace Kernel virtual BAN::Optional get_free_irq() override; virtual void initialize_multiprocessor() override; + virtual void broadcast_ipi() override {} + virtual void enable() override {} static void remap(); static void mask_all(); diff --git a/kernel/kernel/APIC.cpp b/kernel/kernel/APIC.cpp index 274449c3..0c46d651 100644 --- a/kernel/kernel/APIC.cpp +++ b/kernel/kernel/APIC.cpp @@ -215,9 +215,8 @@ namespace Kernel io_apic.max_redirs = io_apic.read(IOAPIC_MAX_REDIRS); } - // Mask all interrupts - uint32_t sivr = apic->read_from_local_apic(LAPIC_SIV_REG); - apic->write_to_local_apic(LAPIC_SIV_REG, sivr | 0x1FF); + // Enable local apic + apic->write_to_local_apic(LAPIC_SIV_REG, apic->read_from_local_apic(LAPIC_SIV_REG) | 0x1FF); return apic; } @@ -313,6 +312,28 @@ namespace Kernel dprintln("{} processors started", *g_ap_running_count); } + void APIC::broadcast_ipi() + { + write_to_local_apic(LAPIC_ICR_HI_REG, (read_from_local_apic(LAPIC_ICR_HI_REG) & 0x00FFFFFF) | 0xFF000000); + write_to_local_apic(LAPIC_ICR_LO_REG, + (read_from_local_apic(LAPIC_ICR_LO_REG) & ICR_LO_reserved_mask) + | ICR_LO_delivery_mode_fixed + | ICR_LO_destination_mode_physical + | ICR_LO_level_assert + | ICR_LO_trigger_mode_level + | ICR_LO_destination_shorthand_all_excluding_self + | (IRQ_VECTOR_BASE + IRQ_IPI) + ); + while ((read_from_local_apic(LAPIC_ICR_LO_REG) & ICR_LO_delivery_status_send_pending) == ICR_LO_delivery_status_send_pending) + __builtin_ia32_pause(); + } + + void APIC::enable() + { + write_to_local_apic(LAPIC_SIV_REG, read_from_local_apic(LAPIC_SIV_REG) | 0x1FF); + } + + uint32_t APIC::read_from_local_apic(ptrdiff_t offset) { return MMIO::read32(m_local_apic_vaddr + offset); @@ -370,7 +391,8 @@ namespace Kernel redir.vector = IRQ_VECTOR_BASE + irq; redir.mask = 0; - redir.destination = m_processors.front().apic_id; + // FIXME: distribute IRQs more evenly? + redir.destination = Kernel::Processor::bsb_id(); ioapic->write(IOAPIC_REDIRS + gsi * 2, redir.lo_dword); ioapic->write(IOAPIC_REDIRS + gsi * 2 + 1, redir.hi_dword); diff --git a/kernel/kernel/kernel.cpp b/kernel/kernel/kernel.cpp index 238d1f8d..c9f85c8f 100644 --- a/kernel/kernel/kernel.cpp +++ b/kernel/kernel/kernel.cpp @@ -214,6 +214,7 @@ extern "C" void ap_main() Processor::initialize(); PageTable::kernel().initial_load(); Processor::allocate_idle_thread(); + InterruptController::get().enable(); dprintln("ap{} initialized", Processor::current_id());