* [PATCH] powerpc/mm: Merge various PTE bits and accessors definitions
@ 2009-03-02 6:22 Benjamin Herrenschmidt
2009-03-02 6:27 ` Benjamin Herrenschmidt
2009-03-02 7:38 ` Michael Ellerman
0 siblings, 2 replies; 4+ messages in thread
From: Benjamin Herrenschmidt @ 2009-03-02 6:22 UTC (permalink / raw)
To: linuxppc-dev
Now that they are almost identical, we can merge some of the definitions
related to the PTE format into common files.
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@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
+
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] powerpc/mm: Merge various PTE bits and accessors definitions
2009-03-02 6:22 [PATCH] powerpc/mm: Merge various PTE bits and accessors definitions Benjamin Herrenschmidt
@ 2009-03-02 6:27 ` Benjamin Herrenschmidt
2009-03-02 7:38 ` Michael Ellerman
1 sibling, 0 replies; 4+ messages in thread
From: Benjamin Herrenschmidt @ 2009-03-02 6:27 UTC (permalink / raw)
To: linuxppc-dev
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@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@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] powerpc/mm: Merge various PTE bits and accessors definitions
2009-03-02 6:22 [PATCH] powerpc/mm: Merge various PTE bits and accessors definitions Benjamin Herrenschmidt
2009-03-02 6:27 ` Benjamin Herrenschmidt
@ 2009-03-02 7:38 ` Michael Ellerman
2009-03-02 7:57 ` Benjamin Herrenschmidt
1 sibling, 1 reply; 4+ messages in thread
From: Michael Ellerman @ 2009-03-02 7:38 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 932 bytes --]
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.
<snip>
> +/* 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
What about FTRACE? ∞TRACE etc.
cheers
--
Michael Ellerman
OzLabs, IBM Australia Development Lab
wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)
We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] powerpc/mm: Merge various PTE bits and accessors definitions
2009-03-02 7:38 ` Michael Ellerman
@ 2009-03-02 7:57 ` Benjamin Herrenschmidt
0 siblings, 0 replies; 4+ messages in thread
From: Benjamin Herrenschmidt @ 2009-03-02 7:57 UTC (permalink / raw)
To: michael; +Cc: linuxppc-dev
On Mon, 2009-03-02 at 18:38 +1100, Michael Ellerman wrote:
> 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.
>
> <snip>
>
> > +/* 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
>
> What about FTRACE? ∞TRACE etc.
Well, I'm just moving those bits around from pgtable-ppc32.h (ie, only
ppc32 uses PAGE_KERNEL_TEXT for now anyway).
Note also that as it is, with ppc32 hash, we don't honor the read-only
restriction on the BAT mapping anyway.
So yes, there's room for fixing things but that isn't what this patch
does.
Cheers,
Ben.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2009-03-02 7:58 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-03-02 6:22 [PATCH] powerpc/mm: Merge various PTE bits and accessors definitions Benjamin Herrenschmidt
2009-03-02 6:27 ` Benjamin Herrenschmidt
2009-03-02 7:38 ` Michael Ellerman
2009-03-02 7:57 ` Benjamin Herrenschmidt
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).