vmap: Add a helper for global TLB shootdowns
authorBarret Rhoden <brho@cs.berkeley.edu>
Sun, 27 Nov 2016 15:09:47 +0000 (10:09 -0500)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 29 Nov 2016 16:27:40 +0000 (11:27 -0500)
The global TLB flush is an x86 thing, though other architectures might
have one too.  On x86, PTE_G means that the TLB entry won't be flushed
on a normal cr3 reload.  We use these for kernel mappings.  You have to
go through a couple extra hoops to flush those entries.

For us to dynamically change kernel virtual mappings, we'll need to
occasionally flush global TLB entries.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/include/pmap.h
kern/src/pmap.c

index 7ed29ad..73cc995 100644 (file)
@@ -91,6 +91,7 @@ void  page_decref(page_t *pp);
 
 void   tlb_invalidate(pgdir_t pgdir, void *ga);
 void tlb_flush_global(void);
 
 void   tlb_invalidate(pgdir_t pgdir, void *ga);
 void tlb_flush_global(void);
+void tlb_shootdown_global(void);
 bool regions_collide_unsafe(uintptr_t start1, uintptr_t end1,
                             uintptr_t start2, uintptr_t end2);
 
 bool regions_collide_unsafe(uintptr_t start1, uintptr_t end1,
                             uintptr_t start2, uintptr_t end2);
 
index 3e92489..fa0fb0b 100644 (file)
@@ -22,6 +22,7 @@
 #include <mm.h>
 #include <multiboot.h>
 #include <arena.h>
 #include <mm.h>
 #include <multiboot.h>
 #include <arena.h>
+#include <init.h>
 
 physaddr_t max_pmem = 0;       /* Total amount of physical memory (bytes) */
 physaddr_t max_paddr = 0;      /* Maximum addressable physical address */
 
 physaddr_t max_pmem = 0;       /* Total amount of physical memory (bytes) */
 physaddr_t max_paddr = 0;      /* Maximum addressable physical address */
@@ -326,6 +327,27 @@ void tlb_invalidate(pgdir_t pgdir, void *va)
        invlpg(va);
 }
 
        invlpg(va);
 }
 
+static void __tlb_global(uint32_t srcid, long a0, long a1, long a2)
+{
+       tlb_flush_global();
+}
+
+/* Does a global TLB flush on all cores. */
+void tlb_shootdown_global(void)
+{
+       tlb_flush_global();
+       if (booting)
+               return;
+       /* TODO: consider a helper for broadcast messages, though note that we're
+        * doing our flush immediately, which our caller expects from us before it
+        * returns. */
+       for (int i = 0; i < num_cores; i++) {
+               if (i == core_id())
+                       continue;
+               send_kernel_message(i, __tlb_global, 0, 0, 0, KMSG_IMMEDIATE);
+       }
+}
+
 /* Helper, returns true if any part of (start1, end1) is within (start2, end2).
  * Equality of endpoints (like end1 == start2) is okay.
  * Assumes no wrap-around. */
 /* Helper, returns true if any part of (start1, end1) is within (start2, end2).
  * Equality of endpoints (like end1 == start2) is okay.
  * Assumes no wrap-around. */