From 71087002cf807e25056dba4e4028a9f204dc9ffd Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Thu, 19 Mar 2009 19:34:09 +0000 Subject: powerpc/mm: Merge various PTE bits and accessors definitions 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 --- arch/powerpc/include/asm/pgtable-ppc32.h | 204 +------------------------------ arch/powerpc/include/asm/pgtable-ppc64.h | 132 +------------------- arch/powerpc/include/asm/pgtable.h | 54 +++++++- arch/powerpc/include/asm/pte-common.h | 180 +++++++++++++++++++++++++++ 4 files changed, 233 insertions(+), 337 deletions(-) create mode 100644 arch/powerpc/include/asm/pte-common.h (limited to 'arch') diff --git a/arch/powerpc/include/asm/pgtable-ppc32.h b/arch/powerpc/include/asm/pgtable-ppc32.h index 7ce331e51f9..ba45c997830 100644 --- a/arch/powerpc/include/asm/pgtable-ppc32.h +++ b/arch/powerpc/include/asm/pgtable-ppc32.h @@ -97,174 +97,11 @@ extern int icache_44x_need_flush; #include #endif -/* If _PAGE_SPECIAL is defined, then we advertise our support for it */ -#ifdef _PAGE_SPECIAL -#define __HAVE_ARCH_PTE_SPECIAL -#endif - -/* - * Some bits are only used on some cpu families... Make sure that all - * the undefined gets defined as 0 - */ -#ifndef _PAGE_HASHPTE -#define _PAGE_HASHPTE 0 -#endif -#ifndef _PTE_NONE_MASK -#define _PTE_NONE_MASK 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 _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 - -#define _PAGE_HPTEFLAGS _PAGE_HASHPTE - -/* Location of the PFN in the PTE. Most 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 - -#ifdef CONFIG_PTE_64BIT -#define PTE_RPN_MAX (1ULL << (64 - PTE_RPN_SHIFT)) -#define PTE_RPN_MASK (~((1ULL< #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) @@ -273,43 +110,6 @@ extern unsigned long bad_call_to_PMD_PAGE_SIZE(void); #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. diff --git a/arch/powerpc/include/asm/pgtable-ppc64.h b/arch/powerpc/include/asm/pgtable-ppc64.h index 5a575f2905f..768e0f08f00 100644 --- a/arch/powerpc/include/asm/pgtable-ppc64.h +++ b/arch/powerpc/include/asm/pgtable-ppc64.h @@ -80,82 +80,8 @@ * Include the PTE bits definitions */ #include +#include -/* Some other useful definitions */ -#define PTE_RPN_MAX (1UL << (64 - PTE_RPN_SHIFT)) -#define PTE_RPN_MASK (~((1UL<>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) @@ -271,36 +171,6 @@ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot) /* 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, diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h index 81574f94ea3..eb17da78112 100644 --- a/arch/powerpc/include/asm/pgtable.h +++ b/arch/powerpc/include/asm/pgtable.h @@ -25,12 +25,58 @@ static inline void assert_pte_locked(struct mm_struct *mm, unsigned long addr) # include #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(((pte_basic_t)(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 */ diff --git a/arch/powerpc/include/asm/pte-common.h b/arch/powerpc/include/asm/pte-common.h new file mode 100644 index 00000000000..d9740e88680 --- /dev/null +++ b/arch/powerpc/include/asm/pte-common.h @@ -0,0 +1,180 @@ +/* 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<