Kernel: Implement API for sending IPIs for only one processor
Also move the spin wait to check for pending IPI sends to the start of ipi sending function. There is no need to wait for IPI send succeeding right after it. It is enough to make sure there are not multiple IPIs being sent at the same time.
This commit is contained in:
parent
819c130366
commit
f49689caac
|
@ -19,6 +19,7 @@ namespace Kernel
|
|||
virtual BAN::Optional<uint8_t> get_free_irq() override;
|
||||
|
||||
virtual void initialize_multiprocessor() override;
|
||||
virtual void send_ipi(ProcessorID target) override;
|
||||
virtual void broadcast_ipi() override;
|
||||
virtual void enable() override;
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ namespace Kernel
|
|||
static InterruptController& get();
|
||||
|
||||
virtual void initialize_multiprocessor() = 0;
|
||||
virtual void send_ipi(ProcessorID target) = 0;
|
||||
virtual void broadcast_ipi() = 0;
|
||||
virtual void enable() = 0;
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ namespace Kernel
|
|||
virtual BAN::Optional<uint8_t> get_free_irq() override;
|
||||
|
||||
virtual void initialize_multiprocessor() override;
|
||||
virtual void send_ipi(ProcessorID) override {}
|
||||
virtual void broadcast_ipi() override {}
|
||||
virtual void enable() override {}
|
||||
|
||||
|
|
|
@ -319,8 +319,29 @@ namespace Kernel
|
|||
dprintln("{} processors started", *g_ap_running_count);
|
||||
}
|
||||
|
||||
|
||||
void APIC::send_ipi(ProcessorID target)
|
||||
{
|
||||
ASSERT(Kernel::Processor::get_interrupt_state() == InterruptState::Disabled);
|
||||
while ((read_from_local_apic(LAPIC_ICR_LO_REG) & ICR_LO_delivery_status_send_pending) == ICR_LO_delivery_status_send_pending)
|
||||
__builtin_ia32_pause();
|
||||
write_to_local_apic(LAPIC_ICR_HI_REG, (read_from_local_apic(LAPIC_ICR_HI_REG) & 0x00FFFFFF) | (target << 24));
|
||||
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_none
|
||||
| (IRQ_VECTOR_BASE + IRQ_IPI)
|
||||
);
|
||||
}
|
||||
|
||||
void APIC::broadcast_ipi()
|
||||
{
|
||||
ASSERT(Kernel::Processor::get_interrupt_state() == InterruptState::Disabled);
|
||||
while ((read_from_local_apic(LAPIC_ICR_LO_REG) & ICR_LO_delivery_status_send_pending) == ICR_LO_delivery_status_send_pending)
|
||||
__builtin_ia32_pause();
|
||||
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)
|
||||
|
@ -331,8 +352,6 @@ namespace Kernel
|
|||
| 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()
|
||||
|
|
Loading…
Reference in New Issue