summaryrefslogtreecommitdiff
path: root/Kernel/Arch
diff options
context:
space:
mode:
authorTom <tomut@yahoo.com>2021-01-02 12:27:38 -0700
committerAndreas Kling <kling@serenityos.org>2021-01-02 20:56:35 +0100
commit0d44ee6f2bd5b6a4c8a101880f93e41e6cef9f54 (patch)
tree12a87cd2cf6d2ec8edffa1fc504e50e400fc272f /Kernel/Arch
parentc630669304b62f8cc8e28548ba9dfba29c82ca33 (diff)
downloadserenity-0d44ee6f2bd5b6a4c8a101880f93e41e6cef9f54.zip
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.
Diffstat (limited to 'Kernel/Arch')
-rw-r--r--Kernel/Arch/i386/CPU.cpp18
-rw-r--r--Kernel/Arch/i386/CPU.h5
2 files changed, 18 insertions, 5 deletions
diff --git a/Kernel/Arch/i386/CPU.cpp b/Kernel/Arch/i386/CPU.cpp
index bd227e061a..825f98e7b0 100644
--- a/Kernel/Arch/i386/CPU.cpp
+++ b/Kernel/Arch/i386/CPU.cpp
@@ -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);
diff --git a/Kernel/Arch/i386/CPU.h b/Kernel/Arch/i386/CPU.h
index 41dc2748cb..d42ff1707a 100644
--- a/Kernel/Arch/i386/CPU.h
+++ b/Kernel/Arch/i386/CPU.h
@@ -666,6 +666,7 @@ struct ProcessorMessage {
void (*free)(void*);
} callback_with_data;
struct {
+ const PageDirectory* page_directory;
u8* ptr;
size_t page_count;
} flush_tlb;
@@ -787,7 +788,7 @@ public:
}
static void flush_tlb_local(VirtualAddress vaddr, size_t page_count);
- static void flush_tlb(VirtualAddress vaddr, size_t page_count);
+ static void flush_tlb(const PageDirectory*, VirtualAddress, size_t);
Descriptor& get_gdt_entry(u16 selector);
void flush_gdt();
@@ -991,7 +992,7 @@ public:
}
static void smp_unicast(u32 cpu, void (*callback)(), bool async);
static void smp_unicast(u32 cpu, void (*callback)(void*), void* data, void (*free_data)(void*), bool async);
- static void smp_broadcast_flush_tlb(VirtualAddress vaddr, size_t page_count);
+ static void smp_broadcast_flush_tlb(const PageDirectory*, VirtualAddress, size_t);
template<typename Callback>
static void deferred_call_queue(Callback callback)