Kernel: Implement IPI broadcasting
This commit is contained in:
parent
2323a55517
commit
89ca4c8a8b
|
@ -10,7 +10,7 @@
|
|||
#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 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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -19,6 +19,8 @@ namespace Kernel
|
|||
virtual BAN::Optional<uint8_t> 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);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <stdint.h>
|
||||
|
||||
constexpr uint8_t IRQ_VECTOR_BASE = 0x20;
|
||||
constexpr uint8_t IRQ_IPI = 32;
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
|
|
@ -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<void> reserve_irq(uint8_t irq) = 0;
|
||||
virtual BAN::Optional<uint8_t> get_free_irq() = 0;
|
||||
|
|
|
@ -17,6 +17,8 @@ namespace Kernel
|
|||
virtual BAN::Optional<uint8_t> 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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
Loading…
Reference in New Issue