[PATCH] powerpc/mm: Merge various PTE bits and accessors definitions
Benjamin Herrenschmidt
benh at kernel.crashing.org
Mon Mar 2 17:27:15 EST 2009
On Mon, 2009-03-02 at 17:22 +1100, Benjamin Herrenschmidt wrote:
> Now that they are almost identical, we can merge some of the definitions
> related to the PTE format into common files.
Hrm... some of the last 2 patches got mangled with each other ...
applying both works fine but don't try to build with only one of them.
I'll try to fix that up tomorrow.
Ben.
> This creates a new pte-common.h which is included by both 32 and 64-bit
> right after the CPU specific pte-*.h file, and which defines some
> bits to "default" values if they haven't been defined already, and
> then provides a generic definition of most of the bit combinations
> based on these and exposed to the rest of the kernel.
>
> I also moved to the common pgtable.h most of the "small" accessors to the
> PTE bits and modification helpers (pte_mk*). The actual accessors remain
> in their separate files.
>
> Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
> ---
>
> arch/powerpc/include/asm/pgtable-ppc32.h | 124 ---------------------
> arch/powerpc/include/asm/pgtable-ppc64.h | 130 ----------------------
> arch/powerpc/include/asm/pgtable.h | 53 ++++++++-
> arch/powerpc/include/asm/pte-common.h | 177 +++++++++++++++++++++++++++++++
> 4 files changed, 229 insertions(+), 255 deletions(-)
>
> --- linux-work.orig/arch/powerpc/include/asm/pgtable-ppc32.h 2009-03-02 16:11:50.000000000 +1100
> +++ linux-work/arch/powerpc/include/asm/pgtable-ppc32.h 2009-03-02 16:12:50.000000000 +1100
> @@ -97,94 +97,11 @@ extern int icache_44x_need_flush;
> #include <asm/pte-hash32.h>
> #endif
>
> -/* If _PAGE_SPECIAL is defined, then we advertise our support for it */
> -#ifdef _PAGE_SPECIAL
> -#define __HAVE_ARCH_PTE_SPECIAL
> -#endif
> -
> -/*
> - * We define 2 sets of base prot bits, one for basic pages (ie,
> - * cacheable kernel and user pages) and one for non cacheable
> - * pages. We always set _PAGE_COHERENT when SMP is enabled or
> - * the processor might need it for DMA coherency.
> - */
> -#if defined(CONFIG_SMP) || defined(CONFIG_PPC_STD_MMU)
> -#define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_COHERENT)
> -#else
> -#define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED)
> -#endif
> -#define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED)
> -
> -/* Permission masks used for kernel mappings */
> -#define PAGE_KERNEL __pgprot(_PAGE_BASE | _PAGE_KERNEL_RW)
> -#define PAGE_KERNEL_NC __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | \
> - _PAGE_NO_CACHE)
> -#define PAGE_KERNEL_NCG __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | \
> - _PAGE_NO_CACHE | _PAGE_GUARDED)
> -#define PAGE_KERNEL_X __pgprot(_PAGE_BASE | _PAGE_KERNEL_RW | _PAGE_EXEC)
> -#define PAGE_KERNEL_RO __pgprot(_PAGE_BASE | _PAGE_KERNEL_RO)
> -#define PAGE_KERNEL_ROX __pgprot(_PAGE_BASE | _PAGE_KERNEL_RO | _PAGE_EXEC)
> -
> -#if defined(CONFIG_KGDB) || defined(CONFIG_XMON) || defined(CONFIG_BDI_SWITCH) ||\
> - defined(CONFIG_KPROBES)
> -/* We want the debuggers to be able to set breakpoints anywhere, so
> - * don't write protect the kernel text */
> -#define PAGE_KERNEL_TEXT PAGE_KERNEL_X
> -#else
> -#define PAGE_KERNEL_TEXT PAGE_KERNEL_ROX
> -#endif
> -
> -#define PAGE_NONE __pgprot(_PAGE_BASE)
> -#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER)
> -#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
> -#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW)
> -#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC)
> -#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER)
> -#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
> -
> -/*
> - * The PowerPC can only do execute protection on a segment (256MB) basis,
> - * not on a page basis. So we consider execute permission the same as read.
> - * Also, write permissions imply read permissions.
> - * This is the closest we can get..
> - */
> -#define __P000 PAGE_NONE
> -#define __P001 PAGE_READONLY_X
> -#define __P010 PAGE_COPY
> -#define __P011 PAGE_COPY_X
> -#define __P100 PAGE_READONLY
> -#define __P101 PAGE_READONLY_X
> -#define __P110 PAGE_COPY
> -#define __P111 PAGE_COPY_X
> -
> -#define __S000 PAGE_NONE
> -#define __S001 PAGE_READONLY_X
> -#define __S010 PAGE_SHARED
> -#define __S011 PAGE_SHARED_X
> -#define __S100 PAGE_READONLY
> -#define __S101 PAGE_READONLY_X
> -#define __S110 PAGE_SHARED
> -#define __S111 PAGE_SHARED_X
> +/* And here we include common definitions */
> +#include <asm/pte-common.h>
>
> #ifndef __ASSEMBLY__
> -/* Make sure we get a link error if PMD_PAGE_SIZE is ever called on a
> - * kernel without large page PMD support */
> -extern unsigned long bad_call_to_PMD_PAGE_SIZE(void);
>
> -/*
> - * Conversions between PTE values and page frame numbers.
> - */
> -
> -#define pte_pfn(x) (pte_val(x) >> PTE_RPN_SHIFT)
> -#define pte_page(x) pfn_to_page(pte_pfn(x))
> -
> -#define pfn_pte(pfn, prot) __pte(((pte_basic_t)(pfn) << PTE_RPN_SHIFT) |\
> - pgprot_val(prot))
> -#define mk_pte(page, prot) pfn_pte(page_to_pfn(page), prot)
> -#endif /* __ASSEMBLY__ */
> -
> -#define pte_none(pte) ((pte_val(pte) & ~_PTE_NONE_MASK) == 0)
> -#define pte_present(pte) (pte_val(pte) & _PAGE_PRESENT)
> #define pte_clear(mm, addr, ptep) \
> do { pte_update(ptep, ~_PAGE_HASHPTE, 0); } while (0)
>
> @@ -193,43 +110,6 @@ extern unsigned long bad_call_to_PMD_PAG
> #define pmd_present(pmd) (pmd_val(pmd) & _PMD_PRESENT_MASK)
> #define pmd_clear(pmdp) do { pmd_val(*(pmdp)) = 0; } while (0)
>
> -#ifndef __ASSEMBLY__
> -/*
> - * The following only work if pte_present() is true.
> - * Undefined behaviour if not..
> - */
> -static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
> -static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
> -static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
> -static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
> -static inline int pte_special(pte_t pte) { return pte_val(pte) & _PAGE_SPECIAL; }
> -
> -static inline pte_t pte_wrprotect(pte_t pte) {
> - pte_val(pte) &= ~(_PAGE_RW | _PAGE_HWWRITE); return pte; }
> -static inline pte_t pte_mkclean(pte_t pte) {
> - pte_val(pte) &= ~(_PAGE_DIRTY | _PAGE_HWWRITE); return pte; }
> -static inline pte_t pte_mkold(pte_t pte) {
> - pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
> -
> -static inline pte_t pte_mkwrite(pte_t pte) {
> - pte_val(pte) |= _PAGE_RW; return pte; }
> -static inline pte_t pte_mkdirty(pte_t pte) {
> - pte_val(pte) |= _PAGE_DIRTY; return pte; }
> -static inline pte_t pte_mkyoung(pte_t pte) {
> - pte_val(pte) |= _PAGE_ACCESSED; return pte; }
> -static inline pte_t pte_mkspecial(pte_t pte) {
> - pte_val(pte) |= _PAGE_SPECIAL; return pte; }
> -static inline pgprot_t pte_pgprot(pte_t pte)
> -{
> - return __pgprot(pte_val(pte) & PAGE_PROT_BITS);
> -}
> -
> -static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
> -{
> - pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot);
> - return pte;
> -}
> -
> /*
> * When flushing the tlb entry for a page, we also need to flush the hash
> * table entry. flush_hash_pages is assembler (for speed) in hashtable.S.
> Index: linux-work/arch/powerpc/include/asm/pgtable-ppc64.h
> ===================================================================
> --- linux-work.orig/arch/powerpc/include/asm/pgtable-ppc64.h 2009-03-02 16:11:50.000000000 +1100
> +++ linux-work/arch/powerpc/include/asm/pgtable-ppc64.h 2009-03-02 16:12:50.000000000 +1100
> @@ -80,80 +80,8 @@
> * Include the PTE bits definitions
> */
> #include <asm/pte-hash64.h>
> +#include <asm/pte-common.h>
>
> -/* Some other useful definitions */
> -#define PTE_RPN_MAX (1UL << (64 - PTE_RPN_SHIFT))
> -#define PTE_RPN_MASK (~((1UL<<PTE_RPN_SHIFT)-1))
> -
> -/* _PAGE_CHG_MASK masks of bits that are to be preserved accross
> - * pgprot changes
> - */
> -#define _PAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_HPTEFLAGS | _PAGE_DIRTY | \
> - _PAGE_ACCESSED | _PAGE_SPECIAL)
> -
> -#define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_PSIZE)
> -#define _PAGE_BASE (_PAGE_BASE_NC | _PAGE_COHERENT)
> -
> -
> -/* Permission masks used to generate the __P and __S table,
> - *
> - * Note:__pgprot is defined in arch/powerpc/include/asm/page.h
> - */
> -#define PAGE_NONE __pgprot(_PAGE_BASE)
> -#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW)
> -#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC)
> -#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER)
> -#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
> -#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER)
> -#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
> -
> -/* Permission masks used for kernel mappings */
> -#define PAGE_KERNEL __pgprot(_PAGE_BASE | _PAGE_KERNEL_RW)
> -#define PAGE_KERNEL_NC __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | \
> - _PAGE_NO_CACHE)
> -#define PAGE_KERNEL_NCG __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | \
> - _PAGE_NO_CACHE | _PAGE_GUARDED)
> -#define PAGE_KERNEL_X __pgprot(_PAGE_BASE | _PAGE_KERNEL_RW | _PAGE_EXEC)
> -#define PAGE_KERNEL_RO __pgprot(_PAGE_BASE | _PAGE_KERNEL_RO)
> -#define PAGE_KERNEL_ROX __pgprot(_PAGE_BASE | _PAGE_KERNEL_RO | _PAGE_EXEC)
> -
> -/* Protection bits for use by pte_pgprot() */
> -#define PAGE_PROT_BITS (_PAGE_GUARDED | _PAGE_COHERENT | \
> - _PAGE_NO_CACHE | _PAGE_WRITETHRU | \
> - _PAGE_4K_PFN | _PAGE_USER | _PAGE_RW | \
> - _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_EXEC)
> -
> -
> -/* We always have _PAGE_SPECIAL on 64 bit */
> -#define __HAVE_ARCH_PTE_SPECIAL
> -
> -
> -/*
> - * POWER4 and newer have per page execute protection, older chips can only
> - * do this on a segment (256MB) basis.
> - *
> - * Also, write permissions imply read permissions.
> - * This is the closest we can get..
> - *
> - * Note due to the way vm flags are laid out, the bits are XWR
> - */
> -#define __P000 PAGE_NONE
> -#define __P001 PAGE_READONLY
> -#define __P010 PAGE_COPY
> -#define __P011 PAGE_COPY
> -#define __P100 PAGE_READONLY_X
> -#define __P101 PAGE_READONLY_X
> -#define __P110 PAGE_COPY_X
> -#define __P111 PAGE_COPY_X
> -
> -#define __S000 PAGE_NONE
> -#define __S001 PAGE_READONLY
> -#define __S010 PAGE_SHARED
> -#define __S011 PAGE_SHARED
> -#define __S100 PAGE_READONLY_X
> -#define __S101 PAGE_READONLY_X
> -#define __S110 PAGE_SHARED_X
> -#define __S111 PAGE_SHARED_X
>
> #ifdef CONFIG_PPC_MM_SLICES
> #define HAVE_ARCH_UNMAPPED_AREA
> @@ -194,34 +122,8 @@
> #endif /* __real_pte */
>
>
> -/*
> - * Conversion functions: convert a page and protection to a page entry,
> - * and a page entry and page directory to the page they refer to.
> - *
> - * mk_pte takes a (struct page *) as input
> - */
> -#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot))
> -
> -static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot)
> -{
> - pte_t pte;
> -
> -
> - pte_val(pte) = (pfn << PTE_RPN_SHIFT) | pgprot_val(pgprot);
> - return pte;
> -}
> -
> -#define pte_modify(_pte, newprot) \
> - (__pte((pte_val(_pte) & _PAGE_CHG_MASK) | pgprot_val(newprot)))
> -
> -#define pte_none(pte) ((pte_val(pte) & ~_PAGE_HPTEFLAGS) == 0)
> -#define pte_present(pte) (pte_val(pte) & _PAGE_PRESENT)
> -
> /* pte_clear moved to later in this file */
>
> -#define pte_pfn(x) ((unsigned long)((pte_val(x)>>PTE_RPN_SHIFT)))
> -#define pte_page(x) pfn_to_page(pte_pfn(x))
> -
> #define PMD_BAD_BITS (PTE_TABLE_SIZE-1)
> #define PUD_BAD_BITS (PMD_TABLE_SIZE-1)
>
> @@ -269,36 +171,6 @@ static inline pte_t pfn_pte(unsigned lon
> /* This now only contains the vmalloc pages */
> #define pgd_offset_k(address) pgd_offset(&init_mm, address)
>
> -/*
> - * The following only work if pte_present() is true.
> - * Undefined behaviour if not..
> - */
> -static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW;}
> -static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY;}
> -static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED;}
> -static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE;}
> -static inline int pte_special(pte_t pte) { return pte_val(pte) & _PAGE_SPECIAL; }
> -
> -static inline pte_t pte_wrprotect(pte_t pte) {
> - pte_val(pte) &= ~(_PAGE_RW); return pte; }
> -static inline pte_t pte_mkclean(pte_t pte) {
> - pte_val(pte) &= ~(_PAGE_DIRTY); return pte; }
> -static inline pte_t pte_mkold(pte_t pte) {
> - pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
> -static inline pte_t pte_mkwrite(pte_t pte) {
> - pte_val(pte) |= _PAGE_RW; return pte; }
> -static inline pte_t pte_mkdirty(pte_t pte) {
> - pte_val(pte) |= _PAGE_DIRTY; return pte; }
> -static inline pte_t pte_mkyoung(pte_t pte) {
> - pte_val(pte) |= _PAGE_ACCESSED; return pte; }
> -static inline pte_t pte_mkhuge(pte_t pte) {
> - return pte; }
> -static inline pte_t pte_mkspecial(pte_t pte) {
> - pte_val(pte) |= _PAGE_SPECIAL; return pte; }
> -static inline pgprot_t pte_pgprot(pte_t pte)
> -{
> - return __pgprot(pte_val(pte) & PAGE_PROT_BITS);
> -}
>
> /* Atomic PTE updates */
> static inline unsigned long pte_update(struct mm_struct *mm,
> Index: linux-work/arch/powerpc/include/asm/pgtable.h
> ===================================================================
> --- linux-work.orig/arch/powerpc/include/asm/pgtable.h 2009-03-02 16:11:50.000000000 +1100
> +++ linux-work/arch/powerpc/include/asm/pgtable.h 2009-03-02 16:17:52.000000000 +1100
> @@ -25,12 +25,57 @@ static inline void assert_pte_locked(str
> # include <asm/pgtable-ppc32.h>
> #endif
>
> -/* Special mapping for AGP */
> -#define PAGE_AGP (PAGE_KERNEL_NC)
> -#define HAVE_PAGE_AGP
> -
> #ifndef __ASSEMBLY__
>
> +/* Generic accessors to PTE bits */
> +static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
> +static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
> +static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
> +static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
> +static inline int pte_special(pte_t pte) { return pte_val(pte) & _PAGE_SPECIAL; }
> +static inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; }
> +static inline int pte_none(pte_t pte) { return (pte_val(pte) & ~_PTE_NONE_MASK) == 0; }
> +static inline pgprot_t pte_pgprot(pte_t pte) { return __pgprot(pte_val(pte) & PAGE_PROT_BITS); }
> +
> +/* Conversion functions: convert a page and protection to a page entry,
> + * and a page entry and page directory to the page they refer to.
> + *
> + * Even if PTEs can be unsigned long long, a PFN is always an unsigned
> + * long for now.
> + */
> +static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot) {
> + return __pte((pfn << PTE_RPN_SHIFT) | pgprot_val(pgprot)); }
> +static inline unsigned long pte_pfn(pte_t pte) {
> + return pte_val(pte) >> PTE_RPN_SHIFT; }
> +
> +/* Keep these as a macros to avoid include dependency mess */
> +#define pte_page(x) pfn_to_page(pte_pfn(x))
> +#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot))
> +
> +/* Generic modifiers for PTE bits */
> +static inline pte_t pte_wrprotect(pte_t pte) {
> + pte_val(pte) &= ~(_PAGE_RW | _PAGE_HWWRITE); return pte; }
> +static inline pte_t pte_mkclean(pte_t pte) {
> + pte_val(pte) &= ~(_PAGE_DIRTY | _PAGE_HWWRITE); return pte; }
> +static inline pte_t pte_mkold(pte_t pte) {
> + pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
> +static inline pte_t pte_mkwrite(pte_t pte) {
> + pte_val(pte) |= _PAGE_RW; return pte; }
> +static inline pte_t pte_mkdirty(pte_t pte) {
> + pte_val(pte) |= _PAGE_DIRTY; return pte; }
> +static inline pte_t pte_mkyoung(pte_t pte) {
> + pte_val(pte) |= _PAGE_ACCESSED; return pte; }
> +static inline pte_t pte_mkspecial(pte_t pte) {
> + pte_val(pte) |= _PAGE_SPECIAL; return pte; }
> +static inline pte_t pte_mkhuge(pte_t pte) {
> + return pte; }
> +static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
> +{
> + pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot);
> + return pte;
> +}
> +
> +
> /* Insert a PTE, top-level function is out of line. It uses an inline
> * low level function in the respective pgtable-* files
> */
> Index: linux-work/arch/powerpc/include/asm/pte-common.h
> ===================================================================
> --- /dev/null 1970-01-01 00:00:00.000000000 +0000
> +++ linux-work/arch/powerpc/include/asm/pte-common.h 2009-03-02 16:20:02.000000000 +1100
> @@ -0,0 +1,177 @@
> +/* Included from asm/pgtable-*.h only ! */
> +
> +/*
> + * Some bits are only used on some cpu families... Make sure that all
> + * the undefined gets a sensible default
> + */
> +#ifndef _PAGE_HASHPTE
> +#define _PAGE_HASHPTE 0
> +#endif
> +#ifndef _PAGE_SHARED
> +#define _PAGE_SHARED 0
> +#endif
> +#ifndef _PAGE_HWWRITE
> +#define _PAGE_HWWRITE 0
> +#endif
> +#ifndef _PAGE_HWEXEC
> +#define _PAGE_HWEXEC 0
> +#endif
> +#ifndef _PAGE_EXEC
> +#define _PAGE_EXEC 0
> +#endif
> +#ifndef _PAGE_ENDIAN
> +#define _PAGE_ENDIAN 0
> +#endif
> +#ifndef _PAGE_COHERENT
> +#define _PAGE_COHERENT 0
> +#endif
> +#ifndef _PAGE_WRITETHRU
> +#define _PAGE_WRITETHRU 0
> +#endif
> +#ifndef _PAGE_SPECIAL
> +#define _PAGE_SPECIAL 0
> +#endif
> +#ifndef _PAGE_4K_PFN
> +#define _PAGE_4K_PFN 0
> +#endif
> +#ifndef _PAGE_PSIZE
> +#define _PAGE_PSIZE 0
> +#endif
> +#ifndef _PMD_PRESENT_MASK
> +#define _PMD_PRESENT_MASK _PMD_PRESENT
> +#endif
> +#ifndef _PMD_SIZE
> +#define _PMD_SIZE 0
> +#define PMD_PAGE_SIZE(pmd) bad_call_to_PMD_PAGE_SIZE()
> +#endif
> +#ifndef _PAGE_KERNEL_RO
> +#define _PAGE_KERNEL_RO 0
> +#endif
> +#ifndef _PAGE_KERNEL_RW
> +#define _PAGE_KERNEL_RW (_PAGE_DIRTY | _PAGE_RW | _PAGE_HWWRITE)
> +#endif
> +#ifndef _PAGE_HPTEFLAGS
> +#define _PAGE_HPTEFLAGS _PAGE_HASHPTE
> +#endif
> +#ifndef _PTE_NONE_MASK
> +#define _PTE_NONE_MASK _PAGE_HPTEFLAGS
> +#endif
> +
> +/* Make sure we get a link error if PMD_PAGE_SIZE is ever called on a
> + * kernel without large page PMD support
> + */
> +#ifndef __ASSEMBLY__
> +extern unsigned long bad_call_to_PMD_PAGE_SIZE(void);
> +#endif /* __ASSEMBLY__ */
> +
> +/* Location of the PFN in the PTE. Most 32-bit platforms use the same
> + * as _PAGE_SHIFT here (ie, naturally aligned).
> + * Platform who don't just pre-define the value so we don't override it here
> + */
> +#ifndef PTE_RPN_SHIFT
> +#define PTE_RPN_SHIFT (PAGE_SHIFT)
> +#endif
> +
> +/* The mask convered by the RPN must be a ULL on 32-bit platforms with
> + * 64-bit PTEs
> + */
> +#if defined(CONFIG_PPC32) && defined(CONFIG_PTE_64BIT)
> +#define PTE_RPN_MAX (1ULL << (64 - PTE_RPN_SHIFT))
> +#define PTE_RPN_MASK (~((1ULL<<PTE_RPN_SHIFT)-1))
> +#else
> +#define PTE_RPN_MAX (1UL << (32 - PTE_RPN_SHIFT))
> +#define PTE_RPN_MASK (~((1UL<<PTE_RPN_SHIFT)-1))
> +#endif
> +
> +/* _PAGE_CHG_MASK masks of bits that are to be preserved accross
> + * pgprot changes
> + */
> +#define _PAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_HPTEFLAGS | _PAGE_DIRTY | \
> + _PAGE_ACCESSED | _PAGE_SPECIAL)
> +
> +/* Mask of bits returned by pte_pgprot() */
> +#define PAGE_PROT_BITS (_PAGE_GUARDED | _PAGE_COHERENT | _PAGE_NO_CACHE | \
> + _PAGE_WRITETHRU | _PAGE_ENDIAN | _PAGE_4K_PFN | \
> + _PAGE_USER | _PAGE_ACCESSED | \
> + _PAGE_RW | _PAGE_HWWRITE | _PAGE_DIRTY | \
> + _PAGE_EXEC | _PAGE_HWEXEC)
> +
> +/*
> + * We define 2 sets of base prot bits, one for basic pages (ie,
> + * cacheable kernel and user pages) and one for non cacheable
> + * pages. We always set _PAGE_COHERENT when SMP is enabled or
> + * the processor might need it for DMA coherency.
> + */
> +#define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_PSIZE)
> +#if defined(CONFIG_SMP) || defined(CONFIG_PPC_STD_MMU)
> +#define _PAGE_BASE (_PAGE_BASE_NC | _PAGE_COHERENT)
> +#else
> +#define _PAGE_BASE (_PAGE_BASE_NC)
> +#endif
> +
> +/* Permission masks used to generate the __P and __S table,
> + *
> + * Note:__pgprot is defined in arch/powerpc/include/asm/page.h
> + *
> + * Write permissions imply read permissions for now (we could make write-only
> + * pages on BookE but we don't bother for now). Execute permission control is
> + * possible on platforms that define _PAGE_EXEC
> + *
> + * Note due to the way vm flags are laid out, the bits are XWR
> + */
> +#define PAGE_NONE __pgprot(_PAGE_BASE)
> +#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW)
> +#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC)
> +#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER)
> +#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
> +#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER)
> +#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
> +
> +#define __P000 PAGE_NONE
> +#define __P001 PAGE_READONLY
> +#define __P010 PAGE_COPY
> +#define __P011 PAGE_COPY
> +#define __P100 PAGE_READONLY_X
> +#define __P101 PAGE_READONLY_X
> +#define __P110 PAGE_COPY_X
> +#define __P111 PAGE_COPY_X
> +
> +#define __S000 PAGE_NONE
> +#define __S001 PAGE_READONLY
> +#define __S010 PAGE_SHARED
> +#define __S011 PAGE_SHARED
> +#define __S100 PAGE_READONLY_X
> +#define __S101 PAGE_READONLY_X
> +#define __S110 PAGE_SHARED_X
> +#define __S111 PAGE_SHARED_X
> +
> +/* Permission masks used for kernel mappings */
> +#define PAGE_KERNEL __pgprot(_PAGE_BASE | _PAGE_KERNEL_RW)
> +#define PAGE_KERNEL_NC __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | \
> + _PAGE_NO_CACHE)
> +#define PAGE_KERNEL_NCG __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | \
> + _PAGE_NO_CACHE | _PAGE_GUARDED)
> +#define PAGE_KERNEL_X __pgprot(_PAGE_BASE | _PAGE_KERNEL_RW | _PAGE_EXEC)
> +#define PAGE_KERNEL_RO __pgprot(_PAGE_BASE | _PAGE_KERNEL_RO)
> +#define PAGE_KERNEL_ROX __pgprot(_PAGE_BASE | _PAGE_KERNEL_RO | _PAGE_EXEC)
> +
> +/* Protection used for kernel text. We want the debuggers to be able to
> + * set breakpoints anywhere, so don't write protect the kernel text
> + * on platforms where such control is possible.
> + */
> +#if defined(CONFIG_KGDB) || defined(CONFIG_XMON) || defined(CONFIG_BDI_SWITCH) ||\
> + defined(CONFIG_KPROBES)
> +#define PAGE_KERNEL_TEXT PAGE_KERNEL_X
> +#else
> +#define PAGE_KERNEL_TEXT PAGE_KERNEL_ROX
> +#endif
> +
> +/* Advertise special mapping type for AGP */
> +#define PAGE_AGP (PAGE_KERNEL_NC)
> +#define HAVE_PAGE_AGP
> +
> +/* Advertise support for _PAGE_SPECIAL */
> +#ifdef _PAGE_SPECIAL
> +#define __HAVE_ARCH_PTE_SPECIAL
> +#endif
> +
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev at ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
More information about the Linuxppc-dev
mailing list