1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 19:47:44 +00:00

Kernel: Ignore TLB flush requests for user addresses of other processes

If a TLB flush request is broadcast to other processors and the addresses
to flush are user mode addresses, we can ignore such a request on the
target processor if the page directory currently in use doesn't match
the addresses to be flushed. We still need to broadcast to all processors
in that case because the other processors may switch to that same page
directory at any time.
This commit is contained in:
Tom 2021-01-02 12:27:38 -07:00 committed by Andreas Kling
parent c630669304
commit 0d44ee6f2b
5 changed files with 25 additions and 12 deletions

View file

@ -1790,10 +1790,10 @@ void Processor::flush_tlb_local(VirtualAddress vaddr, size_t page_count)
}
}
void Processor::flush_tlb(VirtualAddress vaddr, size_t page_count)
void Processor::flush_tlb(const PageDirectory* page_directory, VirtualAddress vaddr, size_t page_count)
{
if (s_smp_enabled)
smp_broadcast_flush_tlb(vaddr, page_count);
smp_broadcast_flush_tlb(page_directory, vaddr, page_count);
else
flush_tlb_local(vaddr, page_count);
}
@ -1911,6 +1911,17 @@ bool Processor::smp_process_pending_messages()
msg->callback_with_data.handler(msg->callback_with_data.data);
break;
case ProcessorMessage::FlushTlb:
if (is_user_address(VirtualAddress(msg->flush_tlb.ptr))) {
// We assume that we don't cross into kernel land!
ASSERT(is_user_range(VirtualAddress(msg->flush_tlb.ptr), msg->flush_tlb.page_count * PAGE_SIZE));
if (read_cr3() != msg->flush_tlb.page_directory->cr3()) {
//This processor isn't using this page directory right now, we can ignore this request
#ifdef SMP_DEBUG
dbg() << "SMP[" << id() << "]: No need to flush " << msg->flush_tlb.page_count << " pages at " << VirtualAddress(msg->flush_tlb.ptr);
#endif
break;
}
}
flush_tlb_local(VirtualAddress(msg->flush_tlb.ptr), msg->flush_tlb.page_count);
break;
}
@ -2068,11 +2079,12 @@ void Processor::smp_unicast(u32 cpu, void (*callback)(), bool async)
smp_unicast_message(cpu, msg, async);
}
void Processor::smp_broadcast_flush_tlb(VirtualAddress vaddr, size_t page_count)
void Processor::smp_broadcast_flush_tlb(const PageDirectory* page_directory, VirtualAddress vaddr, size_t page_count)
{
auto& msg = smp_get_from_pool();
msg.async = false;
msg.type = ProcessorMessage::FlushTlb;
msg.flush_tlb.page_directory = page_directory;
msg.flush_tlb.ptr = vaddr.as_ptr();
msg.flush_tlb.page_count = page_count;
smp_broadcast_message(msg);