diff options
Diffstat (limited to 'arch/xtensa/include/asm/pgtable.h')
| -rw-r--r-- | arch/xtensa/include/asm/pgtable.h | 165 | 
1 files changed, 95 insertions, 70 deletions
diff --git a/arch/xtensa/include/asm/pgtable.h b/arch/xtensa/include/asm/pgtable.h index b03c043ce75..4b0ca35a93b 100644 --- a/arch/xtensa/include/asm/pgtable.h +++ b/arch/xtensa/include/asm/pgtable.h @@ -5,7 +5,7 @@   * it under the terms of the GNU General Public License version 2 as   * published by the Free Software Foundation.   * - * Copyright (C) 2001 - 2007 Tensilica Inc. + * Copyright (C) 2001 - 2013 Tensilica Inc.   */  #ifndef _XTENSA_PGTABLE_H @@ -64,41 +64,82 @@   * Virtual memory area. We keep a distance to other memory regions to be   * on the safe side. We also use this area for cache aliasing.   */ -  #define VMALLOC_START		0xC0000000  #define VMALLOC_END		0xC7FEFFFF  #define TLBTEMP_BASE_1		0xC7FF0000  #define TLBTEMP_BASE_2		0xC7FF8000  /* - * Xtensa Linux config PTE layout (when present): - *	31-12:	PPN - *	11-6:	Software - *	5-4:	RING - *	3-0:	CA + * For the Xtensa architecture, the PTE layout is as follows: + * + *		31------12  11  10-9   8-6  5-4  3-2  1-0 + *		+-----------------------------------------+ + *		|           |   Software   |   HARDWARE   | + *		|    PPN    |          ADW | RI |Attribute| + *		+-----------------------------------------+ + *   pte_none	|             MBZ          | 01 | 11 | 00 | + *		+-----------------------------------------+ + *   present	|    PPN    | 0 | 00 | ADW | RI | CA | wx | + *		+- - - - - - - - - - - - - - - - - - - - -+ + *   (PAGE_NONE)|    PPN    | 0 | 00 | ADW | 01 | 11 | 11 | + *		+-----------------------------------------+ + *   swap	|     index     |   type   | 01 | 11 | 00 | + *		+- - - - - - - - - - - - - - - - - - - - -+ + *   file	|        file offset       | 01 | 11 | 10 | + *		+-----------------------------------------+   * - * Similar to the Alpha and MIPS ports, we need to keep track of the ref - * and mod bits in software.  We have a software "you can read - * from this page" bit, and a hardware one which actually lets the - * process read from the page.  On the same token we have a software - * writable bit and the real hardware one which actually lets the - * process write to the page. + * For T1050 hardware and earlier the layout differs for present and (PAGE_NONE) + *		+-----------------------------------------+ + *   present	|    PPN    | 0 | 00 | ADW | RI | CA | w1 | + *		+-----------------------------------------+ + *   (PAGE_NONE)|    PPN    | 0 | 00 | ADW | 01 | 01 | 00 | + *		+-----------------------------------------+   * - * See further below for PTE layout for swapped-out pages. + *  Legend: + *   PPN        Physical Page Number + *   ADW	software: accessed (young) / dirty / writable + *   RI         ring (0=privileged, 1=user, 2 and 3 are unused) + *   CA		cache attribute: 00 bypass, 01 writeback, 10 writethrough + *		(11 is invalid and used to mark pages that are not present) + *   w		page is writable (hw) + *   x		page is executable (hw) + *   index      swap offset / PAGE_SIZE (bit 11-31: 21 bits -> 8 GB) + *		(note that the index is always non-zero) + *   type       swap type (5 bits -> 32 types) + *   file offset 26-bit offset into the file, in increments of PAGE_SIZE + * + *  Notes: + *   - (PROT_NONE) is a special case of 'present' but causes an exception for + *     any access (read, write, and execute). + *   - 'multihit-exception' has the highest priority of all MMU exceptions, + *     so the ring must be set to 'RING_USER' even for 'non-present' pages. + *   - on older hardware, the exectuable flag was not supported and + *     used as a 'valid' flag, so it needs to be always set. + *   - we need to keep track of certain flags in software (dirty and young) + *     to do this, we use write exceptions and have a separate software w-flag. + *   - attribute value 1101 (and 1111 on T1050 and earlier) is reserved   */ +#define _PAGE_ATTRIB_MASK	0xf +  #define _PAGE_HW_EXEC		(1<<0)	/* hardware: page is executable */  #define _PAGE_HW_WRITE		(1<<1)	/* hardware: page is writable */ -#define _PAGE_FILE		(1<<1)	/* non-linear mapping, if !present */ -#define _PAGE_PROTNONE		(3<<0)	/* special case for VM_PROT_NONE */ - -/* None of these cache modes include MP coherency:  */  #define _PAGE_CA_BYPASS		(0<<2)	/* bypass, non-speculative */  #define _PAGE_CA_WB		(1<<2)	/* write-back */  #define _PAGE_CA_WT		(2<<2)	/* write-through */  #define _PAGE_CA_MASK		(3<<2) -#define _PAGE_INVALID		(3<<2) +#define _PAGE_CA_INVALID	(3<<2) + +/* We use invalid attribute values to distinguish special pte entries */ +#if XCHAL_HW_VERSION_MAJOR < 2000 +#define _PAGE_HW_VALID		0x01	/* older HW needed this bit set */ +#define _PAGE_NONE		0x04 +#else +#define _PAGE_HW_VALID		0x00 +#define _PAGE_NONE		0x0f +#endif +#define _PAGE_FILE		(1<<1)	/* file mapped page, only if !present */  #define _PAGE_USER		(1<<4)	/* user access (ring=1) */ @@ -108,19 +149,12 @@  #define _PAGE_DIRTY		(1<<7)	/* software: page dirty */  #define _PAGE_ACCESSED		(1<<8)	/* software: page accessed (read) */ -/* On older HW revisions, we always have to set bit 0 */ -#if XCHAL_HW_VERSION_MAJOR < 2000 -# define _PAGE_VALID		(1<<0) -#else -# define _PAGE_VALID		0 -#endif - -#define _PAGE_CHG_MASK	(PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) -#define _PAGE_PRESENT	(_PAGE_VALID | _PAGE_CA_WB | _PAGE_ACCESSED) -  #ifdef CONFIG_MMU -#define PAGE_NONE	   __pgprot(_PAGE_INVALID | _PAGE_USER | _PAGE_PROTNONE) +#define _PAGE_CHG_MASK	   (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) +#define _PAGE_PRESENT	   (_PAGE_HW_VALID | _PAGE_CA_WB | _PAGE_ACCESSED) + +#define PAGE_NONE	   __pgprot(_PAGE_NONE | _PAGE_USER)  #define PAGE_COPY	   __pgprot(_PAGE_PRESENT | _PAGE_USER)  #define PAGE_COPY_EXEC	   __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_HW_EXEC)  #define PAGE_READONLY	   __pgprot(_PAGE_PRESENT | _PAGE_USER) @@ -132,9 +166,9 @@  #define PAGE_KERNEL_EXEC   __pgprot(_PAGE_PRESENT|_PAGE_HW_WRITE|_PAGE_HW_EXEC)  #if (DCACHE_WAY_SIZE > PAGE_SIZE) -# define _PAGE_DIRECTORY (_PAGE_VALID | _PAGE_ACCESSED) +# define _PAGE_DIRECTORY   (_PAGE_HW_VALID | _PAGE_ACCESSED | _PAGE_CA_BYPASS)  #else -# define _PAGE_DIRECTORY (_PAGE_VALID | _PAGE_ACCESSED | _PAGE_CA_WB) +# define _PAGE_DIRECTORY   (_PAGE_HW_VALID | _PAGE_ACCESSED | _PAGE_CA_WB)  #endif  #else /* no mmu */ @@ -186,12 +220,11 @@ extern unsigned long empty_zero_page[1024];  #ifdef CONFIG_MMU  extern pgd_t swapper_pg_dir[PAGE_SIZE/sizeof(pgd_t)];  extern void paging_init(void); -extern void pgtable_cache_init(void);  #else  # define swapper_pg_dir NULL  static inline void paging_init(void) { } -static inline void pgtable_cache_init(void) { }  #endif +static inline void pgtable_cache_init(void) { }  /*   * The pmd contains the kernel virtual address of the pte page. @@ -202,12 +235,16 @@ static inline void pgtable_cache_init(void) { }  /*   * pte status.   */ -#define pte_none(pte)	 (pte_val(pte) == _PAGE_INVALID) -#define pte_present(pte)						\ -	(((pte_val(pte) & _PAGE_CA_MASK) != _PAGE_INVALID)		\ -	 || ((pte_val(pte) & _PAGE_PROTNONE) == _PAGE_PROTNONE)) +# define pte_none(pte)	 (pte_val(pte) == (_PAGE_CA_INVALID | _PAGE_USER)) +#if XCHAL_HW_VERSION_MAJOR < 2000 +# define pte_present(pte) ((pte_val(pte) & _PAGE_CA_MASK) != _PAGE_CA_INVALID) +#else +# define pte_present(pte)						\ +	(((pte_val(pte) & _PAGE_CA_MASK) != _PAGE_CA_INVALID)		\ +	 || ((pte_val(pte) & _PAGE_ATTRIB_MASK) == _PAGE_NONE)) +#endif  #define pte_clear(mm,addr,ptep)						\ -	do { update_pte(ptep, __pte(_PAGE_INVALID)); } while(0) +	do { update_pte(ptep, __pte(_PAGE_CA_INVALID | _PAGE_USER)); } while (0)  #define pmd_none(pmd)	 (!pmd_val(pmd))  #define pmd_present(pmd) (pmd_val(pmd) & PAGE_MASK) @@ -273,6 +310,10 @@ set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pteval)  	update_pte(ptep, pteval);  } +static inline void set_pte(pte_t *ptep, pte_t pteval) +{ +	update_pte(ptep, pteval); +}  static inline void  set_pmd(pmd_t *pmdp, pmd_t pmdval) @@ -284,7 +325,7 @@ struct vm_area_struct;  static inline int  ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, -    			  pte_t *ptep) +			  pte_t *ptep)  {  	pte_t pte = *ptep;  	if (!pte_young(pte)) @@ -304,8 +345,8 @@ ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)  static inline void  ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)  { -  	pte_t pte = *ptep; -  	update_pte(ptep, pte_wrprotect(pte)); +	pte_t pte = *ptep; +	update_pte(ptep, pte_wrprotect(pte));  }  /* to find an entry in a kernel page-table-directory */ @@ -328,35 +369,23 @@ ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)  /* - * Encode and decode a swap entry. - * - * Format of swap pte: - *  bit	   0	   MBZ - *  bit	   1	   page-file (must be zero) - *  bits   2 -  3  page hw access mode (must be 11: _PAGE_INVALID) - *  bits   4 -  5  ring protection (must be 01: _PAGE_USER) - *  bits   6 - 10  swap type (5 bits -> 32 types) - *  bits  11 - 31  swap offset / PAGE_SIZE (21 bits -> 8GB) -  - * Format of file pte: - *  bit	   0	   MBZ - *  bit	   1	   page-file (must be one: _PAGE_FILE) - *  bits   2 -  3  page hw access mode (must be 11: _PAGE_INVALID) - *  bits   4 -  5  ring protection (must be 01: _PAGE_USER) - *  bits   6 - 31  file offset / PAGE_SIZE + * Encode and decode a swap and file entry.   */ +#define SWP_TYPE_BITS		5 +#define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > SWP_TYPE_BITS)  #define __swp_type(entry)	(((entry).val >> 6) & 0x1f)  #define __swp_offset(entry)	((entry).val >> 11)  #define __swp_entry(type,offs)	\ -	((swp_entry_t) {((type) << 6) | ((offs) << 11) | _PAGE_INVALID}) +	((swp_entry_t){((type) << 6) | ((offs) << 11) | \ +	 _PAGE_CA_INVALID | _PAGE_USER})  #define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })  #define __swp_entry_to_pte(x)	((pte_t) { (x).val }) -#define PTE_FILE_MAX_BITS	28 -#define pte_to_pgoff(pte)	(pte_val(pte) >> 4) +#define PTE_FILE_MAX_BITS	26 +#define pte_to_pgoff(pte)	(pte_val(pte) >> 6)  #define pgoff_to_pte(off)	\ -	((pte_t) { ((off) << 4) | _PAGE_INVALID | _PAGE_FILE }) +	((pte_t) { ((off) << 6) | _PAGE_CA_INVALID | _PAGE_FILE | _PAGE_USER })  #endif /*  !defined (__ASSEMBLY__) */ @@ -393,14 +422,6 @@ ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)  extern  void update_mmu_cache(struct vm_area_struct * vma,  			      unsigned long address, pte_t *ptep); -/* - * remap a physical page `pfn' of size `size' with page protection `prot' - * into virtual address `from' - */ - -#define io_remap_pfn_range(vma,from,pfn,size,prot) \ -                remap_pfn_range(vma, from, pfn, size, prot) -  typedef pte_t *pte_addr_t;  #endif /* !defined (__ASSEMBLY__) */ @@ -410,6 +431,10 @@ typedef pte_t *pte_addr_t;  #define __HAVE_ARCH_PTEP_SET_WRPROTECT  #define __HAVE_ARCH_PTEP_MKDIRTY  #define __HAVE_ARCH_PTE_SAME +/* We provide our own get_unmapped_area to cope with + * SHM area cache aliasing for userland. + */ +#define HAVE_ARCH_UNMAPPED_AREA  #include <asm-generic/pgtable.h>  | 
