Kernel: Implement IPI broadcasting

This commit is contained in:
Bananymous 2024-03-09 23:53:38 +02:00
parent 2323a55517
commit 89ca4c8a8b
8 changed files with 36 additions and 5 deletions

View File

@ -10,7 +10,7 @@
#include <kernel/Timer/PIT.h> #include <kernel/Timer/PIT.h>
#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 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 namespace Kernel
{ {

View File

@ -174,6 +174,7 @@ irq 28
irq 29 irq 29
irq 30 irq 30
irq 31 irq 31
irq 32
// arguments in RAX, RBX, RCX, RDX, RSI, RDI // arguments in RAX, RBX, RCX, RDX, RSI, RDI
// System V ABI: RDI, RSI, RDX, RCX, R8, R9 // System V ABI: RDI, RSI, RDX, RCX, R8, R9

View File

@ -19,6 +19,8 @@ namespace Kernel
virtual BAN::Optional<uint8_t> get_free_irq() override; virtual BAN::Optional<uint8_t> get_free_irq() override;
virtual void initialize_multiprocessor() override; virtual void initialize_multiprocessor() override;
virtual void broadcast_ipi() override;
virtual void enable() override;
private: private:
uint32_t read_from_local_apic(ptrdiff_t); uint32_t read_from_local_apic(ptrdiff_t);

View File

@ -7,6 +7,7 @@
#include <stdint.h> #include <stdint.h>
constexpr uint8_t IRQ_VECTOR_BASE = 0x20; constexpr uint8_t IRQ_VECTOR_BASE = 0x20;
constexpr uint8_t IRQ_IPI = 32;
namespace Kernel namespace Kernel
{ {

View File

@ -21,6 +21,8 @@ namespace Kernel
static InterruptController& get(); static InterruptController& get();
virtual void initialize_multiprocessor() = 0; virtual void initialize_multiprocessor() = 0;
virtual void broadcast_ipi() = 0;
virtual void enable() = 0;
virtual BAN::ErrorOr<void> reserve_irq(uint8_t irq) = 0; virtual BAN::ErrorOr<void> reserve_irq(uint8_t irq) = 0;
virtual BAN::Optional<uint8_t> get_free_irq() = 0; virtual BAN::Optional<uint8_t> get_free_irq() = 0;

View File

@ -17,6 +17,8 @@ namespace Kernel
virtual BAN::Optional<uint8_t> get_free_irq() override; virtual BAN::Optional<uint8_t> get_free_irq() override;
virtual void initialize_multiprocessor() override; virtual void initialize_multiprocessor() override;
virtual void broadcast_ipi() override {}
virtual void enable() override {}
static void remap(); static void remap();
static void mask_all(); static void mask_all();

View File

@ -215,9 +215,8 @@ namespace Kernel
io_apic.max_redirs = io_apic.read(IOAPIC_MAX_REDIRS); io_apic.max_redirs = io_apic.read(IOAPIC_MAX_REDIRS);
} }
// Mask all interrupts // Enable local apic
uint32_t sivr = apic->read_from_local_apic(LAPIC_SIV_REG); apic->write_to_local_apic(LAPIC_SIV_REG, apic->read_from_local_apic(LAPIC_SIV_REG) | 0x1FF);
apic->write_to_local_apic(LAPIC_SIV_REG, sivr | 0x1FF);
return apic; return apic;
} }
@ -313,6 +312,28 @@ namespace Kernel
dprintln("{} processors started", *g_ap_running_count); 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) uint32_t APIC::read_from_local_apic(ptrdiff_t offset)
{ {
return MMIO::read32(m_local_apic_vaddr + offset); return MMIO::read32(m_local_apic_vaddr + offset);
@ -370,7 +391,8 @@ namespace Kernel
redir.vector = IRQ_VECTOR_BASE + irq; redir.vector = IRQ_VECTOR_BASE + irq;
redir.mask = 0; 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, redir.lo_dword);
ioapic->write(IOAPIC_REDIRS + gsi * 2 + 1, redir.hi_dword); ioapic->write(IOAPIC_REDIRS + gsi * 2 + 1, redir.hi_dword);

View File

@ -214,6 +214,7 @@ extern "C" void ap_main()
Processor::initialize(); Processor::initialize();
PageTable::kernel().initial_load(); PageTable::kernel().initial_load();
Processor::allocate_idle_thread(); Processor::allocate_idle_thread();
InterruptController::get().enable();
dprintln("ap{} initialized", Processor::current_id()); dprintln("ap{} initialized", Processor::current_id());