diff --git a/kernel/include/kernel/Processor.h b/kernel/include/kernel/Processor.h index b898f116..64f79482 100644 --- a/kernel/include/kernel/Processor.h +++ b/kernel/include/kernel/Processor.h @@ -132,7 +132,7 @@ namespace Kernel static void handle_ipi(); static void handle_smp_messages(); - static void send_smp_message(ProcessorID, const SMPMessage&, bool send_ipi = true); + static bool send_smp_message(ProcessorID, const SMPMessage&, bool send_ipi = true); static void broadcast_smp_message(const SMPMessage&); static void load_segments(); diff --git a/kernel/kernel/Processor.cpp b/kernel/kernel/Processor.cpp index e08fd9e4..3bb9c7ea 100644 --- a/kernel/kernel/Processor.cpp +++ b/kernel/kernel/Processor.cpp @@ -488,7 +488,7 @@ namespace Kernel set_interrupt_state(state); } - void Processor::send_smp_message(ProcessorID processor_id, const SMPMessage& message, bool send_ipi) + bool Processor::send_smp_message(ProcessorID processor_id, const SMPMessage& message, bool send_ipi) { auto state = get_interrupt_state(); set_interrupt_state(InterruptState::Disabled); @@ -499,6 +499,8 @@ namespace Kernel { processor.lock_tlb_lock(); + const bool is_first_entry = (processor.m_tlb_entry_count == 0); + const auto& tlb_msg = message.flush_tlb; processor.m_tlb_global |= (tlb_msg.page_table == nullptr); @@ -515,7 +517,7 @@ namespace Kernel processor.unlock_tlb_lock(); set_interrupt_state(state); - return; + return is_first_entry; } // find a slot for message @@ -557,15 +559,19 @@ namespace Kernel storage->next = processor.m_smp_pending; } + const bool needs_ipi = (storage->next == nullptr); + if (send_ipi) { if (processor_id == current_id()) handle_smp_messages(); - else + else if (needs_ipi) InterruptController::get().send_ipi(processor_id); } set_interrupt_state(state); + + return needs_ipi; } void Processor::broadcast_smp_message(const SMPMessage& message) @@ -576,15 +582,18 @@ namespace Kernel const auto state = get_interrupt_state(); set_interrupt_state(InterruptState::Disabled); + bool needs_ipi = false; + const auto current_id = Processor::current_id(); for (size_t i = 0; i < Processor::count(); i++) { const auto processor_id = s_processor_ids[i]; if (processor_id != current_id) - send_smp_message(processor_id, message, false); + needs_ipi |= send_smp_message(processor_id, message, false); } - InterruptController::get().broadcast_ipi(); + if (needs_ipi) + InterruptController::get().broadcast_ipi(); set_interrupt_state(state); }