forked from Minki/linux
x86: unify paravirt pagetable accessors
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. [ mingo@elte.hu: fixes ] Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
8405b122ad
commit
4891645e76
@ -1039,6 +1039,27 @@ static inline void set_pmd(pmd_t *pmdp, pmd_t pmdval)
|
||||
{
|
||||
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 */
|
||||
|
@ -15,29 +15,31 @@ static inline void native_set_pte(pte_t *ptep , pte_t pte)
|
||||
{
|
||||
*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
|
||||
|
@ -39,11 +39,6 @@ static inline void native_set_pte(pte_t *ptep, pte_t pte)
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* Since this is only called on user PTEs, and the page fault handler
|
||||
@ -94,16 +89,6 @@ static inline void native_pmd_clear(pmd_t *pmd)
|
||||
*(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
|
||||
* the TLB via cr3 if the top-level pgd is changed...
|
||||
|
@ -178,6 +178,39 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
|
||||
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 pgd_clear(pgd) native_pgd_clear(pgd)
|
||||
#endif
|
||||
|
||||
#ifndef set_pud
|
||||
# define set_pud(pudp, pud) native_set_pud(pudp, pud)
|
||||
#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 /* __ASSEMBLY__ */
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
@ -188,6 +221,22 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/* 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
|
||||
/*
|
||||
* Rules for using pte_update - it must be called after any PTE update which
|
||||
@ -206,16 +255,6 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
|
||||
#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
|
||||
* the dirty bit by hand in the kernel, since the hardware
|
||||
@ -287,10 +326,6 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
|
||||
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 /* __ASSEMBLY__ */
|
||||
|
||||
|
@ -63,51 +63,59 @@ extern void clear_kernel_mapping(unsigned long addr, unsigned long size);
|
||||
#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)
|
||||
{
|
||||
*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;
|
||||
}
|
||||
|
||||
static inline void pud_clear (pud_t *pud)
|
||||
{
|
||||
set_pud(pud, __pud(0));
|
||||
}
|
||||
|
||||
static inline void set_pgd(pgd_t *dst, pgd_t val)
|
||||
{
|
||||
*dst = val;
|
||||
}
|
||||
|
||||
static inline void pgd_clear (pgd_t * pgd)
|
||||
{
|
||||
set_pgd(pgd, __pgd(0));
|
||||
}
|
||||
|
||||
#define native_ptep_get_and_clear(xp) __pte(xchg(&(xp)->pte, 0))
|
||||
|
||||
struct mm_struct;
|
||||
|
||||
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_pte_clear(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep)
|
||||
{
|
||||
pte_t pte;
|
||||
if (full) {
|
||||
pte = *ptep;
|
||||
*ptep = __pte(0);
|
||||
} else {
|
||||
pte = native_ptep_get_and_clear(ptep);
|
||||
}
|
||||
return pte;
|
||||
*ptep = native_make_pte(0);
|
||||
}
|
||||
|
||||
static inline void native_set_pte(pte_t *ptep, pte_t pte)
|
||||
{
|
||||
*ptep = pte;
|
||||
}
|
||||
|
||||
static inline pte_t native_ptep_get_and_clear(pte_t *xp)
|
||||
{
|
||||
#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
|
||||
}
|
||||
|
||||
static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd)
|
||||
{
|
||||
*pmdp = pmd;
|
||||
}
|
||||
|
||||
static inline void native_pmd_clear(pmd_t *pmd)
|
||||
{
|
||||
native_set_pmd(pmd, native_make_pmd(0));
|
||||
}
|
||||
|
||||
static inline void native_set_pud(pud_t *pudp, pud_t pud)
|
||||
{
|
||||
*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_t 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_t 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)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user