[PATCH 09 of 10] x86: unify paravirt pagetable accessors

Jeremy Fitzhardinge
2008-01-08T22:18:14Z

Put all the defines for mapping pagetable operations to their native
versions (for the non-paravirt case) into one place. Make the
corresponding changes to paravirt.h.

The tricky part here is that when a pagetable entry can't be updated
atomically (ie, 32-bit PAE), we need special handlers for pte_clear,
set_pte_atomic and set_pte_present. However, the other two modes
don't need special handling for these, and can use a common
set_pte(_at) path.

Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com>

---
include/asm-x86/paravirt.h | 21 ++++++++++
include/asm-x86/pgtable-2level.h | 30 ++++++++-------
include/asm-x86/pgtable-3level.h | 15 -------
include/asm-x86/pgtable.h | 60 +++++++++++++++++++++++-------
include/asm-x86/pgtable_64.h | 76 ++++++++++++++++++++------------------
5 files changed, 124 insertions(+), 78 deletions(-)

diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h
--- a/include/asm-x86/paravirt.h
+++ b/include/asm-x86/paravirt.h
@@ -1039,6 +1039,27 @@ static inline void set_pmd(pmd_t *pmdp,
{
PVOP_VCALL2(pv_mmu_ops.set_pmd, pmdp, pmdval.pud.pgd.pgd);
}
+
+static inline void pmd_clear(pmd_t *pmdp)
+{
+ set_pmd(pmdp, __pmd(0));
+}
+
+static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+ set_pte_at(mm, addr, ptep, __pte(0));
+}
+
+static inline void set_pte_atomic(pte_t *ptep, pte_t pte)
+{
+ set_pte(ptep, pte);
+}
+
+static inline void set_pte_present(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pte)
+{
+ set_pte(ptep, pte);
+}
#endif /* CONFIG_X86_PAE */

/* Lazy mode for batching updates / context switch */
diff --git a/include/asm-x86/pgtable-2level.h b/include/asm-x86/pgtable-2level.h
--- a/include/asm-x86/pgtable-2level.h
+++ b/include/asm-x86/pgtable-2level.h
@@ -15,29 +15,31 @@ static inline void native_set_pte(pte_t
{
*ptep = pte;
}
-static inline void native_set_pte_at(struct mm_struct *mm, unsigned long addr,
- pte_t *ptep , pte_t pte)
-{
- native_set_pte(ptep, pte);
-}
+
static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd)
{
*pmdp = pmd;
}
-#ifndef CONFIG_PARAVIRT
-#define set_pte(pteptr, pteval) native_set_pte(pteptr, pteval)
-#define set_pte_at(mm,addr,ptep,pteval) native_set_pte_at(mm, addr, ptep, pteval)
-#define set_pmd(pmdptr, pmdval) native_set_pmd(pmdptr, pmdval)
-#endif

-#define set_pte_atomic(pteptr, pteval) set_pte(pteptr,pteval)
-#define set_pte_present(mm,addr,ptep,pteval) set_pte_at(mm,addr,ptep,pteval)
+static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte)
+{
+ native_set_pte(ptep, pte);
+}

-#define pmd_clear(xp) do { set_pmd(xp, __pmd(0)); } while (0)
+static inline void native_set_pte_present(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pte)
+{
+ native_set_pte(ptep, pte);
+}
+
+static inline void native_pmd_clear(pmd_t *pmdp)
+{
+ native_set_pmd(pmdp, __pmd(0));
+}

static inline void native_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *xp)
{
- *xp = __pte(0);
+ *xp = native_make_pte(0);
}

#ifdef CONFIG_SMP
diff --git a/include/asm-x86/pgtable-3level.h b/include/asm-x86/pgtable-3level.h
--- a/include/asm-x86/pgtable-3level.h
+++ b/include/asm-x86/pgtable-3level.h
@@ -38,11 +38,6 @@ static inline void native_set_pte(pte_t
ptep->pte_high = pte.pte_high;
smp_wmb();
ptep->pte_low = pte.pte_low;
-}
-static inline void native_set_pte_at(struct mm_struct *mm, unsigned long addr,
- pte_t *ptep , pte_t pte)
-{
- native_set_pte(ptep, pte);
}

/*
@@ -93,16 +88,6 @@ static inline void native_pmd_clear(pmd_
smp_wmb();
*(tmp + 1) = 0;
}
-
-#ifndef CONFIG_PARAVIRT
-#define set_pte(ptep, pte) native_set_pte(ptep, pte)
-#define set_pte_at(mm, addr, ptep, pte) native_set_pte_at(mm, addr, ptep, pte)
-#define set_pte_present(mm, addr, ptep, pte) native_set_pte_present(mm, addr, ptep, pte)
-#define set_pte_atomic(ptep, pte) native_set_pte_atomic(ptep, pte)
-#define set_pmd(pmdp, pmd) native_set_pmd(pmdp, pmd)
-#define set_pud(pudp, pud) native_set_pud(pudp, pud)
-#define pmd_clear(pmd) native_pmd_clear(pmd)
-#endif

/*
* Pentium-II erratum A13: in PAE mode we explicitly have to flush
diff --git a/include/asm-x86/pgtable.h b/include/asm-x86/pgtable.h
--- a/include/asm-x86/pgtable.h
+++ b/include/asm-x86/pgtable.h
@@ -175,6 +175,36 @@ static inline pte_t pte_modify(pte_t pte
return __pte(val);
}

+#ifdef CONFIG_PARAVIRT
+#include <asm/paravirt.h>
+#else /* !CONFIG_PARAVIRT */
+#define set_pte(ptep, pte) native_set_pte(ptep, pte)
+#define set_pte_at(mm, addr, ptep, pte) native_set_pte_at(mm, addr, ptep, pte)
+
+#define set_pte_present(mm, addr, ptep, pte) \
+ native_set_pte_present(mm, addr, ptep, pte)
+#define set_pte_atomic(ptep, pte) \
+ native_set_pte_atomic(ptep, pte)
+
+#define set_pmd(pmdp, pmd) native_set_pmd(pmdp, pmd)
+
+#ifndef __PAGETABLE_PUD_FOLDED
+#define set_pgd(pgdp, pgd) native_set_pgd(pgdp, pgd)
+#define set_pud(pudp, pud) native_set_pud(pudp, pud)
+#define pgd_clear(pgd) native_pgd_clear(pgd)
+#endif
+
+#ifndef __PAGETABLE_PMD_FOLDED
+#define pud_clear(pud) native_pud_clear(pud)
+#endif
+
+#define pte_clear(mm, addr, ptep) native_pte_clear(mm, addr, ptep)
+#define pmd_clear(pmd) native_pmd_clear(pmd)
+
+#define pte_update(mm, addr, ptep) do { } while (0)
+#define pte_update_defer(mm, addr, ptep) do { } while (0)
+#endif /* CONFIG_PARAVIRT */
+
#endif /* __ASSEMBLER__ */

#ifdef CONFIG_X86_32
@@ -184,6 +214,22 @@ static inline pte_t pte_modify(pte_t pte
#endif

#ifndef __ASSEMBLER__
+
+/* local pte updates need not use xchg for locking */
+static inline pte_t native_local_ptep_get_and_clear(pte_t *ptep)
+{
+ pte_t res = *ptep;
+
+ /* Pure native function needs no input for mm, addr */
+ native_pte_clear(NULL, 0, ptep);
+ return res;
+}
+
+static inline void native_set_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep , pte_t pte)
+{
+ native_set_pte(ptep, pte);
+}

#ifndef CONFIG_PARAVIRT
/*
@@ -202,16 +248,6 @@ static inline pte_t pte_modify(pte_t pte
#define pte_update(mm, addr, ptep) do { } while (0)
#define pte_update_defer(mm, addr, ptep) do { } while (0)
#endif
-
-/* local pte updates need not use xchg for locking */
-static inline pte_t native_local_ptep_get_and_clear(pte_t *ptep)
-{
- pte_t res = *ptep;
-
- /* Pure native function needs no input for mm, addr */
- native_pte_clear(NULL, 0, ptep);
- return res;
-}

/*
* We only update the dirty/accessed state if we set
@@ -284,10 +320,6 @@ static inline void ptep_set_wrprotect(st
pte_update(mm, addr, ptep);
}

-#ifndef CONFIG_PARAVIRT
-#define pte_clear(mm, addr, ptep) native_pte_clear(mm, addr, ptep)
-#endif /* !CONFIG_PARAVIRT */
-
#include <asm-generic/pgtable.h>
#endif /* __ASSEMBLER__ */

diff --git a/include/asm-x86/pgtable_64.h b/include/asm-x86/pgtable_64.h
--- a/include/asm-x86/pgtable_64.h
+++ b/include/asm-x86/pgtable_64.h
@@ -63,51 +63,59 @@ extern void clear_kernel_mapping(unsigne
#define pgd_none(x) (!pgd_val(x))
#define pud_none(x) (!pud_val(x))

-static inline void set_pte(pte_t *dst, pte_t val)
+struct mm_struct;
+
+static inline void native_pte_clear(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep)
{
- *dst = val;
-}
-#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
-
-static inline void set_pmd(pmd_t *dst, pmd_t val)
-{
- *dst = val;
-}
-
-static inline void set_pud(pud_t *dst, pud_t val)
-{
- *dst = val;
+ *ptep = native_make_pte(0);
}

-static inline void pud_clear (pud_t *pud)
+static inline void native_set_pte(pte_t *ptep, pte_t pte)
{
- set_pud(pud, __pud(0));
+ *ptep = pte;
}

-static inline void set_pgd(pgd_t *dst, pgd_t val)
+static inline pte_t native_ptep_get_and_clear(pte_t *xp)
{
- *dst = val;
-}
-
-static inline void pgd_clear (pgd_t * pgd)
-{
- set_pgd(pgd, __pgd(0));
+#ifdef CONFIG_SMP
+ return native_make_pte(xchg(&xp->pte, 0));
+#else
+ /* native_local_ptep_get_and_clear, but duplicated because of cyclic dependency */
+ pte_t ret = *xp;
+ native_pte_clear(NULL, 0, xp);
+ return ret;
+#endif
}

-#define native_ptep_get_and_clear(xp) __pte(xchg(&(xp)->pte, 0))
+static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd)
+{
+ *pmdp = pmd;
+}

-struct mm_struct;
+static inline void native_pmd_clear(pmd_t *pmd)
+{
+ native_set_pmd(pmd, native_make_pmd(0));
+}

-static inline pte_t native_ptep_get_and_clear_full(struct mm_struct *mm, unsigned long addr, pte_t *ptep, int full)
+static inline void native_set_pud(pud_t *pudp, pud_t pud)
{
- pte_t pte;
- if (full) {
- pte = *ptep;
- *ptep = __pte(0);
- } else {
- pte = native_ptep_get_and_clear(ptep);
- }
- return pte;
+ *pudp = pud;
+}
+
+static inline void native_pud_clear(pud_t *pud)
+{
+ native_set_pud(pud, native_make_pud(0));
+}
+
+static inline void native_set_pgd(pgd_t *pgdp, pgd_t pgd)
+{
+ *pgdp = pgd;
+}
+
+static inline void native_pgd_clear(pgd_t * pgd)
+{
+ native_set_pgd(pgd, native_make_pgd(0));
}

#define pte_same(a, b) ((a).pte == (b).pte)
@@ -151,7 +159,6 @@ static inline unsigned long pmd_bad(pmd_

#define pte_none(x) (!pte_val(x))
#define pte_present(x) (pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE))
-#define native_pte_clear(mm,addr,xp) do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)

#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) /* FIXME: is this right? */
#define pte_page(x) pfn_to_page(pte_pfn(x))
@@ -196,7 +203,6 @@ static inline unsigned long pmd_bad(pmd_
pmd_index(address))
#define pmd_none(x) (!pmd_val(x))
#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
-#define pmd_clear(xp) do { set_pmd(xp, __pmd(0)); } while (0)
#define pfn_pmd(nr,prot) (__pmd(((nr) << PAGE_SHIFT) | pgprot_val(prot)))
#define pmd_pfn(x) ((pmd_val(x) & __PHYSICAL_MASK) >> PAGE_SHIFT)