|
@@ -558,6 +558,112 @@ static inline int pmd_trans_unstable(pmd_t *pmd)
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_NUMA_BALANCING
|
|
|
+#ifdef CONFIG_ARCH_USES_NUMA_PROT_NONE
|
|
|
+/*
|
|
|
+ * _PAGE_NUMA works identical to _PAGE_PROTNONE (it's actually the
|
|
|
+ * same bit too). It's set only when _PAGE_PRESET is not set and it's
|
|
|
+ * never set if _PAGE_PRESENT is set.
|
|
|
+ *
|
|
|
+ * pte/pmd_present() returns true if pte/pmd_numa returns true. Page
|
|
|
+ * fault triggers on those regions if pte/pmd_numa returns true
|
|
|
+ * (because _PAGE_PRESENT is not set).
|
|
|
+ */
|
|
|
+#ifndef pte_numa
|
|
|
+static inline int pte_numa(pte_t pte)
|
|
|
+{
|
|
|
+ return (pte_flags(pte) &
|
|
|
+ (_PAGE_NUMA|_PAGE_PRESENT)) == _PAGE_NUMA;
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifndef pmd_numa
|
|
|
+static inline int pmd_numa(pmd_t pmd)
|
|
|
+{
|
|
|
+ return (pmd_flags(pmd) &
|
|
|
+ (_PAGE_NUMA|_PAGE_PRESENT)) == _PAGE_NUMA;
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+/*
|
|
|
+ * pte/pmd_mknuma sets the _PAGE_ACCESSED bitflag automatically
|
|
|
+ * because they're called by the NUMA hinting minor page fault. If we
|
|
|
+ * wouldn't set the _PAGE_ACCESSED bitflag here, the TLB miss handler
|
|
|
+ * would be forced to set it later while filling the TLB after we
|
|
|
+ * return to userland. That would trigger a second write to memory
|
|
|
+ * that we optimize away by setting _PAGE_ACCESSED here.
|
|
|
+ */
|
|
|
+#ifndef pte_mknonnuma
|
|
|
+static inline pte_t pte_mknonnuma(pte_t pte)
|
|
|
+{
|
|
|
+ pte = pte_clear_flags(pte, _PAGE_NUMA);
|
|
|
+ return pte_set_flags(pte, _PAGE_PRESENT|_PAGE_ACCESSED);
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifndef pmd_mknonnuma
|
|
|
+static inline pmd_t pmd_mknonnuma(pmd_t pmd)
|
|
|
+{
|
|
|
+ pmd = pmd_clear_flags(pmd, _PAGE_NUMA);
|
|
|
+ return pmd_set_flags(pmd, _PAGE_PRESENT|_PAGE_ACCESSED);
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifndef pte_mknuma
|
|
|
+static inline pte_t pte_mknuma(pte_t pte)
|
|
|
+{
|
|
|
+ pte = pte_set_flags(pte, _PAGE_NUMA);
|
|
|
+ return pte_clear_flags(pte, _PAGE_PRESENT);
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifndef pmd_mknuma
|
|
|
+static inline pmd_t pmd_mknuma(pmd_t pmd)
|
|
|
+{
|
|
|
+ pmd = pmd_set_flags(pmd, _PAGE_NUMA);
|
|
|
+ return pmd_clear_flags(pmd, _PAGE_PRESENT);
|
|
|
+}
|
|
|
+#endif
|
|
|
+#else
|
|
|
+extern int pte_numa(pte_t pte);
|
|
|
+extern int pmd_numa(pmd_t pmd);
|
|
|
+extern pte_t pte_mknonnuma(pte_t pte);
|
|
|
+extern pmd_t pmd_mknonnuma(pmd_t pmd);
|
|
|
+extern pte_t pte_mknuma(pte_t pte);
|
|
|
+extern pmd_t pmd_mknuma(pmd_t pmd);
|
|
|
+#endif /* CONFIG_ARCH_USES_NUMA_PROT_NONE */
|
|
|
+#else
|
|
|
+static inline int pmd_numa(pmd_t pmd)
|
|
|
+{
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static inline int pte_numa(pte_t pte)
|
|
|
+{
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static inline pte_t pte_mknonnuma(pte_t pte)
|
|
|
+{
|
|
|
+ return pte;
|
|
|
+}
|
|
|
+
|
|
|
+static inline pmd_t pmd_mknonnuma(pmd_t pmd)
|
|
|
+{
|
|
|
+ return pmd;
|
|
|
+}
|
|
|
+
|
|
|
+static inline pte_t pte_mknuma(pte_t pte)
|
|
|
+{
|
|
|
+ return pte;
|
|
|
+}
|
|
|
+
|
|
|
+static inline pmd_t pmd_mknuma(pmd_t pmd)
|
|
|
+{
|
|
|
+ return pmd;
|
|
|
+}
|
|
|
+#endif /* CONFIG_NUMA_BALANCING */
|
|
|
+
|
|
|
#endif /* CONFIG_MMU */
|
|
|
|
|
|
#endif /* !__ASSEMBLY__ */
|