summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2013-06-28 20:44:33 +0200
committerRichard Braun <rbraun@sceen.net>2013-06-28 20:44:33 +0200
commit722366c46be7a75dd13429cb7efb1144ac913f76 (patch)
tree975cde395e125aa30e3dd9ae19ab9661112cb31a
parent757bcadf8732ca7c1a0acaac9115dc788c4f6d28 (diff)
x86/cpu: new cpu_tlb_flush_all function
This function completely flushes the TLB, including global pages.
-rw-r--r--arch/x86/machine/cpu.h72
1 files changed, 48 insertions, 24 deletions
diff --git a/arch/x86/machine/cpu.h b/arch/x86/machine/cpu.h
index 9749353c..d655496e 100644
--- a/arch/x86/machine/cpu.h
+++ b/arch/x86/machine/cpu.h
@@ -284,30 +284,6 @@ CPU_DECL_GETSET_CR(cr3)
CPU_DECL_GETSET_CR(cr4)
/*
- * Flush the whole TLB.
- *
- * Implies a compiler barrier.
- */
-static __always_inline void
-cpu_tlb_flush(void)
-{
- cpu_set_cr3(cpu_get_cr3());
-}
-
-/*
- * Flush a single page table entry in the TLB. In some cases, the entire TLB
- * can be flushed by this instruction. The va parameter is a virtual
- * address in the page described by the PTE to flush.
- *
- * Implies a compiler barrier.
- */
-static __always_inline void
-cpu_tlb_flush_va(unsigned long va)
-{
- asm volatile("invlpg (%0)" : : "r" (va) : "memory");
-}
-
-/*
* Return the content of the EFLAGS register.
*
* Implies a compiler barrier.
@@ -532,6 +508,54 @@ cpu_set_msr(uint32_t msr, uint32_t low, uint32_t high)
}
/*
+ * Flush non-global TLB entries.
+ *
+ * Implies a compiler barrier.
+ */
+static __always_inline void
+cpu_tlb_flush(void)
+{
+ cpu_set_cr3(cpu_get_cr3());
+}
+
+/*
+ * Flush all TLB entries, including global ones.
+ *
+ * Implies a compiler barrier.
+ */
+static __always_inline void
+cpu_tlb_flush_all(void)
+{
+ if (!cpu_has_global_pages())
+ cpu_tlb_flush();
+ else {
+ unsigned long cr4;
+
+ cr4 = cpu_get_cr4();
+
+ if (!(cr4 & CPU_CR4_PGE))
+ cpu_tlb_flush();
+ else {
+ cr4 &= ~CPU_CR4_PGE;
+ cpu_set_cr4(cr4);
+ cr4 |= CPU_CR4_PGE;
+ cpu_set_cr4(cr4);
+ }
+ }
+}
+
+/*
+ * Flush a single page table entry in the TLB.
+ *
+ * Implies a compiler barrier.
+ */
+static __always_inline void
+cpu_tlb_flush_va(unsigned long va)
+{
+ asm volatile("invlpg (%0)" : : "r" (va) : "memory");
+}
+
+/*
* XXX For now, directly use the PIT.
*/
static __always_inline void