forked from mirrors/linux
		
	arm64: MMU definitions
The virtual memory layout is described in Documentation/arm64/memory.txt. This patch adds the MMU definitions for the 4KB and 64KB translation table configurations. The SECTION_SIZE is 2MB with 4KB page and 512MB with 64KB page configuration. PHYS_OFFSET is calculated at run-time and stored in a variable (no run-time code patching at this stage). On the current implementation, both user and kernel address spaces are 512G (39-bit) each with a maximum of 256G for the RAM linear mapping. Linux uses 3 levels of translation tables with the 4K page configuration and 2 levels with the 64K configuration. Extending the memory space beyond 39-bit with the 4K pages or 42-bit with 64K pages requires an additional level of translation tables. The SPARSEMEM configuration is global to all AArch64 platforms and allows for 1GB sections with SPARSEMEM_VMEMMAP enabled by default. Signed-off-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Acked-by: Tony Lindgren <tony@atomide.com> Acked-by: Nicolas Pitre <nico@linaro.org> Acked-by: Olof Johansson <olof@lixom.net> Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com> Acked-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
		
							parent
							
								
									60ffc30d56
								
							
						
					
					
						commit
						4f04d8f005
					
				
					 10 changed files with 912 additions and 0 deletions
				
			
		
							
								
								
									
										73
									
								
								Documentation/arm64/memory.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								Documentation/arm64/memory.txt
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,73 @@ | |||
| 		     Memory Layout on AArch64 Linux | ||||
| 		     ============================== | ||||
| 
 | ||||
| Author: Catalin Marinas <catalin.marinas@arm.com> | ||||
| Date  : 20 February 2012 | ||||
| 
 | ||||
| This document describes the virtual memory layout used by the AArch64 | ||||
| Linux kernel. The architecture allows up to 4 levels of translation | ||||
| tables with a 4KB page size and up to 3 levels with a 64KB page size. | ||||
| 
 | ||||
| AArch64 Linux uses 3 levels of translation tables with the 4KB page | ||||
| configuration, allowing 39-bit (512GB) virtual addresses for both user | ||||
| and kernel. With 64KB pages, only 2 levels of translation tables are | ||||
| used but the memory layout is the same. | ||||
| 
 | ||||
| User addresses have bits 63:39 set to 0 while the kernel addresses have | ||||
| the same bits set to 1. TTBRx selection is given by bit 63 of the | ||||
| virtual address. The swapper_pg_dir contains only kernel (global) | ||||
| mappings while the user pgd contains only user (non-global) mappings. | ||||
| The swapper_pgd_dir address is written to TTBR1 and never written to | ||||
| TTBR0. | ||||
| 
 | ||||
| 
 | ||||
| AArch64 Linux memory layout: | ||||
| 
 | ||||
| Start			End			Size		Use | ||||
| ----------------------------------------------------------------------- | ||||
| 0000000000000000	0000007fffffffff	 512GB		user | ||||
| 
 | ||||
| ffffff8000000000	ffffffbbfffcffff	~240GB		vmalloc | ||||
| 
 | ||||
| ffffffbbfffd0000	ffffffbcfffdffff	  64KB		[guard page] | ||||
| 
 | ||||
| ffffffbbfffe0000	ffffffbcfffeffff	  64KB		PCI I/O space | ||||
| 
 | ||||
| ffffffbbffff0000	ffffffbcffffffff	  64KB		[guard page] | ||||
| 
 | ||||
| ffffffbc00000000	ffffffbdffffffff	   8GB		vmemmap | ||||
| 
 | ||||
| ffffffbe00000000	ffffffbffbffffff	  ~8GB		[guard, future vmmemap] | ||||
| 
 | ||||
| ffffffbffc000000	ffffffbfffffffff	  64MB		modules | ||||
| 
 | ||||
| ffffffc000000000	ffffffffffffffff	 256GB		memory | ||||
| 
 | ||||
| 
 | ||||
| Translation table lookup with 4KB pages: | ||||
| 
 | ||||
| +--------+--------+--------+--------+--------+--------+--------+--------+ | ||||
| |63    56|55    48|47    40|39    32|31    24|23    16|15     8|7      0| | ||||
| +--------+--------+--------+--------+--------+--------+--------+--------+ | ||||
|  |                 |         |         |         |         | | ||||
|  |                 |         |         |         |         v | ||||
|  |                 |         |         |         |   [11:0]  in-page offset | ||||
|  |                 |         |         |         +-> [20:12] L3 index | ||||
|  |                 |         |         +-----------> [29:21] L2 index | ||||
|  |                 |         +---------------------> [38:30] L1 index | ||||
|  |                 +-------------------------------> [47:39] L0 index (not used) | ||||
|  +-------------------------------------------------> [63] TTBR0/1 | ||||
| 
 | ||||
| 
 | ||||
| Translation table lookup with 64KB pages: | ||||
| 
 | ||||
| +--------+--------+--------+--------+--------+--------+--------+--------+ | ||||
| |63    56|55    48|47    40|39    32|31    24|23    16|15     8|7      0| | ||||
| +--------+--------+--------+--------+--------+--------+--------+--------+ | ||||
|  |                 |    |               |              | | ||||
|  |                 |    |               |              v | ||||
|  |                 |    |               |            [15:0]  in-page offset | ||||
|  |                 |    |               +----------> [28:16] L3 index | ||||
|  |                 |    +--------------------------> [41:29] L2 index (only 38:29 used) | ||||
|  |                 +-------------------------------> [47:42] L1 index (not used) | ||||
|  +-------------------------------------------------> [63] TTBR0/1 | ||||
							
								
								
									
										144
									
								
								arch/arm64/include/asm/memory.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								arch/arm64/include/asm/memory.h
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,144 @@ | |||
| /*
 | ||||
|  * Based on arch/arm/include/asm/memory.h | ||||
|  * | ||||
|  * Copyright (C) 2000-2002 Russell King | ||||
|  * Copyright (C) 2012 ARM Ltd. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License version 2 as | ||||
|  * published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  * | ||||
|  * Note: this file should not be included by non-asm/.h files | ||||
|  */ | ||||
| #ifndef __ASM_MEMORY_H | ||||
| #define __ASM_MEMORY_H | ||||
| 
 | ||||
| #include <linux/compiler.h> | ||||
| #include <linux/const.h> | ||||
| #include <linux/types.h> | ||||
| #include <asm/sizes.h> | ||||
| 
 | ||||
| /*
 | ||||
|  * Allow for constants defined here to be used from assembly code | ||||
|  * by prepending the UL suffix only with actual C code compilation. | ||||
|  */ | ||||
| #define UL(x) _AC(x, UL) | ||||
| 
 | ||||
| /*
 | ||||
|  * PAGE_OFFSET - the virtual address of the start of the kernel image. | ||||
|  * VA_BITS - the maximum number of bits for virtual addresses. | ||||
|  * TASK_SIZE - the maximum size of a user space task. | ||||
|  * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area. | ||||
|  * The module space lives between the addresses given by TASK_SIZE | ||||
|  * and PAGE_OFFSET - it must be within 128MB of the kernel text. | ||||
|  */ | ||||
| #define PAGE_OFFSET		UL(0xffffffc000000000) | ||||
| #define MODULES_END		(PAGE_OFFSET) | ||||
| #define MODULES_VADDR		(MODULES_END - SZ_64M) | ||||
| #define VA_BITS			(39) | ||||
| #define TASK_SIZE_64		(UL(1) << VA_BITS) | ||||
| 
 | ||||
| #ifdef CONFIG_COMPAT | ||||
| #define TASK_SIZE_32		UL(0x100000000) | ||||
| #define TASK_SIZE		(test_thread_flag(TIF_32BIT) ? \ | ||||
| 				TASK_SIZE_32 : TASK_SIZE_64) | ||||
| #else | ||||
| #define TASK_SIZE		TASK_SIZE_64 | ||||
| #endif /* CONFIG_COMPAT */ | ||||
| 
 | ||||
| #define TASK_UNMAPPED_BASE	(PAGE_ALIGN(TASK_SIZE / 4)) | ||||
| 
 | ||||
| #if TASK_SIZE_64 > MODULES_VADDR | ||||
| #error Top of 64-bit user space clashes with start of module space | ||||
| #endif | ||||
| 
 | ||||
| /*
 | ||||
|  * Physical vs virtual RAM address space conversion.  These are | ||||
|  * private definitions which should NOT be used outside memory.h | ||||
|  * files.  Use virt_to_phys/phys_to_virt/__pa/__va instead. | ||||
|  */ | ||||
| #define __virt_to_phys(x)	(((phys_addr_t)(x) - PAGE_OFFSET + PHYS_OFFSET)) | ||||
| #define __phys_to_virt(x)	((unsigned long)((x) - PHYS_OFFSET + PAGE_OFFSET)) | ||||
| 
 | ||||
| /*
 | ||||
|  * Convert a physical address to a Page Frame Number and back | ||||
|  */ | ||||
| #define	__phys_to_pfn(paddr)	((unsigned long)((paddr) >> PAGE_SHIFT)) | ||||
| #define	__pfn_to_phys(pfn)	((phys_addr_t)(pfn) << PAGE_SHIFT) | ||||
| 
 | ||||
| /*
 | ||||
|  * Convert a page to/from a physical address | ||||
|  */ | ||||
| #define page_to_phys(page)	(__pfn_to_phys(page_to_pfn(page))) | ||||
| #define phys_to_page(phys)	(pfn_to_page(__phys_to_pfn(phys))) | ||||
| 
 | ||||
| /*
 | ||||
|  * Memory types available. | ||||
|  */ | ||||
| #define MT_DEVICE_nGnRnE	0 | ||||
| #define MT_DEVICE_nGnRE		1 | ||||
| #define MT_DEVICE_GRE		2 | ||||
| #define MT_NORMAL_NC		3 | ||||
| #define MT_NORMAL		4 | ||||
| 
 | ||||
| #ifndef __ASSEMBLY__ | ||||
| 
 | ||||
| extern phys_addr_t		memstart_addr; | ||||
| /* PHYS_OFFSET - the physical address of the start of memory. */ | ||||
| #define PHYS_OFFSET		({ memstart_addr; }) | ||||
| 
 | ||||
| /*
 | ||||
|  * PFNs are used to describe any physical page; this means | ||||
|  * PFN 0 == physical address 0. | ||||
|  * | ||||
|  * This is the PFN of the first RAM page in the kernel | ||||
|  * direct-mapped view.  We assume this is the first page | ||||
|  * of RAM in the mem_map as well. | ||||
|  */ | ||||
| #define PHYS_PFN_OFFSET	(PHYS_OFFSET >> PAGE_SHIFT) | ||||
| 
 | ||||
| /*
 | ||||
|  * Note: Drivers should NOT use these.  They are the wrong | ||||
|  * translation for translating DMA addresses.  Use the driver | ||||
|  * DMA support - see dma-mapping.h. | ||||
|  */ | ||||
| static inline phys_addr_t virt_to_phys(const volatile void *x) | ||||
| { | ||||
| 	return __virt_to_phys((unsigned long)(x)); | ||||
| } | ||||
| 
 | ||||
| static inline void *phys_to_virt(phys_addr_t x) | ||||
| { | ||||
| 	return (void *)(__phys_to_virt(x)); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Drivers should NOT use these either. | ||||
|  */ | ||||
| #define __pa(x)			__virt_to_phys((unsigned long)(x)) | ||||
| #define __va(x)			((void *)__phys_to_virt((phys_addr_t)(x))) | ||||
| #define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT) | ||||
| 
 | ||||
| /*
 | ||||
|  *  virt_to_page(k)	convert a _valid_ virtual address to struct page * | ||||
|  *  virt_addr_valid(k)	indicates whether a virtual address is valid | ||||
|  */ | ||||
| #define ARCH_PFN_OFFSET		PHYS_PFN_OFFSET | ||||
| 
 | ||||
| #define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) | ||||
| #define	virt_addr_valid(kaddr)	(((void *)(kaddr) >= (void *)PAGE_OFFSET) && \ | ||||
| 				 ((void *)(kaddr) < (void *)high_memory)) | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #include <asm-generic/memory_model.h> | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										30
									
								
								arch/arm64/include/asm/mmu.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								arch/arm64/include/asm/mmu.h
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | |||
| /*
 | ||||
|  * Copyright (C) 2012 ARM Ltd. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License version 2 as | ||||
|  * published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| #ifndef __ASM_MMU_H | ||||
| #define __ASM_MMU_H | ||||
| 
 | ||||
| typedef struct { | ||||
| 	unsigned int id; | ||||
| 	raw_spinlock_t id_lock; | ||||
| 	void *vdso; | ||||
| } mm_context_t; | ||||
| 
 | ||||
| #define ASID(mm)	((mm)->context.id & 0xffff) | ||||
| 
 | ||||
| extern void paging_init(void); | ||||
| extern void setup_mm_for_reboot(void); | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										43
									
								
								arch/arm64/include/asm/pgtable-2level-hwdef.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								arch/arm64/include/asm/pgtable-2level-hwdef.h
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,43 @@ | |||
| /*
 | ||||
|  * Copyright (C) 2012 ARM Ltd. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License version 2 as | ||||
|  * published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| #ifndef __ASM_PGTABLE_2LEVEL_HWDEF_H | ||||
| #define __ASM_PGTABLE_2LEVEL_HWDEF_H | ||||
| 
 | ||||
| /*
 | ||||
|  * With LPAE and 64KB pages, there are 2 levels of page tables. Each level has | ||||
|  * 8192 entries of 8 bytes each, occupying a 64KB page. Levels 0 and 1 are not | ||||
|  * used. The 2nd level table (PGD for Linux) can cover a range of 4TB, each | ||||
|  * entry representing 512MB. The user and kernel address spaces are limited to | ||||
|  * 512GB and therefore we only use 1024 entries in the PGD. | ||||
|  */ | ||||
| #define PTRS_PER_PTE		8192 | ||||
| #define PTRS_PER_PGD		1024 | ||||
| 
 | ||||
| /*
 | ||||
|  * PGDIR_SHIFT determines the size a top-level page table entry can map. | ||||
|  */ | ||||
| #define PGDIR_SHIFT		29 | ||||
| #define PGDIR_SIZE		(_AC(1, UL) << PGDIR_SHIFT) | ||||
| #define PGDIR_MASK		(~(PGDIR_SIZE-1)) | ||||
| 
 | ||||
| /*
 | ||||
|  * section address mask and size definitions. | ||||
|  */ | ||||
| #define SECTION_SHIFT		29 | ||||
| #define SECTION_SIZE		(_AC(1, UL) << SECTION_SHIFT) | ||||
| #define SECTION_MASK		(~(SECTION_SIZE-1)) | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										60
									
								
								arch/arm64/include/asm/pgtable-2level-types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								arch/arm64/include/asm/pgtable-2level-types.h
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,60 @@ | |||
| /*
 | ||||
|  * Copyright (C) 2012 ARM Ltd. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License version 2 as | ||||
|  * published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| #ifndef __ASM_PGTABLE_2LEVEL_TYPES_H | ||||
| #define __ASM_PGTABLE_2LEVEL_TYPES_H | ||||
| 
 | ||||
| typedef u64 pteval_t; | ||||
| typedef u64 pgdval_t; | ||||
| typedef pgdval_t pmdval_t; | ||||
| 
 | ||||
| #undef STRICT_MM_TYPECHECKS | ||||
| 
 | ||||
| #ifdef STRICT_MM_TYPECHECKS | ||||
| 
 | ||||
| /*
 | ||||
|  * These are used to make use of C type-checking.. | ||||
|  */ | ||||
| typedef struct { pteval_t pte; } pte_t; | ||||
| typedef struct { pgdval_t pgd; } pgd_t; | ||||
| typedef struct { pteval_t pgprot; } pgprot_t; | ||||
| 
 | ||||
| #define pte_val(x)      ((x).pte) | ||||
| #define pgd_val(x)	((x).pgd) | ||||
| #define pgprot_val(x)   ((x).pgprot) | ||||
| 
 | ||||
| #define __pte(x)        ((pte_t) { (x) } ) | ||||
| #define __pgd(x)	((pgd_t) { (x) } ) | ||||
| #define __pgprot(x)     ((pgprot_t) { (x) } ) | ||||
| 
 | ||||
| #else	/* !STRICT_MM_TYPECHECKS */ | ||||
| 
 | ||||
| typedef pteval_t pte_t; | ||||
| typedef pgdval_t pgd_t; | ||||
| typedef pteval_t pgprot_t; | ||||
| 
 | ||||
| #define pte_val(x)	(x) | ||||
| #define pgd_val(x)	(x) | ||||
| #define pgprot_val(x)	(x) | ||||
| 
 | ||||
| #define __pte(x)	(x) | ||||
| #define __pgd(x)	(x) | ||||
| #define __pgprot(x)	(x) | ||||
| 
 | ||||
| #endif	/* STRICT_MM_TYPECHECKS */ | ||||
| 
 | ||||
| #include <asm-generic/pgtable-nopmd.h> | ||||
| 
 | ||||
| #endif	/* __ASM_PGTABLE_2LEVEL_TYPES_H */ | ||||
							
								
								
									
										50
									
								
								arch/arm64/include/asm/pgtable-3level-hwdef.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								arch/arm64/include/asm/pgtable-3level-hwdef.h
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,50 @@ | |||
| /*
 | ||||
|  * Copyright (C) 2012 ARM Ltd. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License version 2 as | ||||
|  * published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| #ifndef __ASM_PGTABLE_3LEVEL_HWDEF_H | ||||
| #define __ASM_PGTABLE_3LEVEL_HWDEF_H | ||||
| 
 | ||||
| /*
 | ||||
|  * With LPAE and 4KB pages, there are 3 levels of page tables. Each level has | ||||
|  * 512 entries of 8 bytes each, occupying a 4K page. The first level table | ||||
|  * covers a range of 512GB, each entry representing 1GB. The user and kernel | ||||
|  * address spaces are limited to 512GB each. | ||||
|  */ | ||||
| #define PTRS_PER_PTE		512 | ||||
| #define PTRS_PER_PMD		512 | ||||
| #define PTRS_PER_PGD		512 | ||||
| 
 | ||||
| /*
 | ||||
|  * PGDIR_SHIFT determines the size a top-level page table entry can map. | ||||
|  */ | ||||
| #define PGDIR_SHIFT		30 | ||||
| #define PGDIR_SIZE		(_AC(1, UL) << PGDIR_SHIFT) | ||||
| #define PGDIR_MASK		(~(PGDIR_SIZE-1)) | ||||
| 
 | ||||
| /*
 | ||||
|  * PMD_SHIFT determines the size a middle-level page table entry can map. | ||||
|  */ | ||||
| #define PMD_SHIFT		21 | ||||
| #define PMD_SIZE		(_AC(1, UL) << PMD_SHIFT) | ||||
| #define PMD_MASK		(~(PMD_SIZE-1)) | ||||
| 
 | ||||
| /*
 | ||||
|  * section address mask and size definitions. | ||||
|  */ | ||||
| #define SECTION_SHIFT		21 | ||||
| #define SECTION_SIZE		(_AC(1, UL) << SECTION_SHIFT) | ||||
| #define SECTION_MASK		(~(SECTION_SIZE-1)) | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										66
									
								
								arch/arm64/include/asm/pgtable-3level-types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								arch/arm64/include/asm/pgtable-3level-types.h
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,66 @@ | |||
| /*
 | ||||
|  * Copyright (C) 2012 ARM Ltd. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License version 2 as | ||||
|  * published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| #ifndef __ASM_PGTABLE_3LEVEL_TYPES_H | ||||
| #define __ASM_PGTABLE_3LEVEL_TYPES_H | ||||
| 
 | ||||
| typedef u64 pteval_t; | ||||
| typedef u64 pmdval_t; | ||||
| typedef u64 pgdval_t; | ||||
| 
 | ||||
| #undef STRICT_MM_TYPECHECKS | ||||
| 
 | ||||
| #ifdef STRICT_MM_TYPECHECKS | ||||
| 
 | ||||
| /*
 | ||||
|  * These are used to make use of C type-checking.. | ||||
|  */ | ||||
| typedef struct { pteval_t pte; } pte_t; | ||||
| typedef struct { pmdval_t pmd; } pmd_t; | ||||
| typedef struct { pgdval_t pgd; } pgd_t; | ||||
| typedef struct { pteval_t pgprot; } pgprot_t; | ||||
| 
 | ||||
| #define pte_val(x)      ((x).pte) | ||||
| #define pmd_val(x)      ((x).pmd) | ||||
| #define pgd_val(x)	((x).pgd) | ||||
| #define pgprot_val(x)   ((x).pgprot) | ||||
| 
 | ||||
| #define __pte(x)        ((pte_t) { (x) } ) | ||||
| #define __pmd(x)        ((pmd_t) { (x) } ) | ||||
| #define __pgd(x)	((pgd_t) { (x) } ) | ||||
| #define __pgprot(x)     ((pgprot_t) { (x) } ) | ||||
| 
 | ||||
| #else	/* !STRICT_MM_TYPECHECKS */ | ||||
| 
 | ||||
| typedef pteval_t pte_t; | ||||
| typedef pmdval_t pmd_t; | ||||
| typedef pgdval_t pgd_t; | ||||
| typedef pteval_t pgprot_t; | ||||
| 
 | ||||
| #define pte_val(x)	(x) | ||||
| #define pmd_val(x)	(x) | ||||
| #define pgd_val(x)	(x) | ||||
| #define pgprot_val(x)	(x) | ||||
| 
 | ||||
| #define __pte(x)	(x) | ||||
| #define __pmd(x)	(x) | ||||
| #define __pgd(x)	(x) | ||||
| #define __pgprot(x)	(x) | ||||
| 
 | ||||
| #endif	/* STRICT_MM_TYPECHECKS */ | ||||
| 
 | ||||
| #include <asm-generic/pgtable-nopud.h> | ||||
| 
 | ||||
| #endif	/* __ASM_PGTABLE_3LEVEL_TYPES_H */ | ||||
							
								
								
									
										94
									
								
								arch/arm64/include/asm/pgtable-hwdef.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								arch/arm64/include/asm/pgtable-hwdef.h
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,94 @@ | |||
| /*
 | ||||
|  * Copyright (C) 2012 ARM Ltd. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License version 2 as | ||||
|  * published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| #ifndef __ASM_PGTABLE_HWDEF_H | ||||
| #define __ASM_PGTABLE_HWDEF_H | ||||
| 
 | ||||
| #ifdef CONFIG_ARM64_64K_PAGES | ||||
| #include <asm/pgtable-2level-hwdef.h> | ||||
| #else | ||||
| #include <asm/pgtable-3level-hwdef.h> | ||||
| #endif | ||||
| 
 | ||||
| /*
 | ||||
|  * Hardware page table definitions. | ||||
|  * | ||||
|  * Level 2 descriptor (PMD). | ||||
|  */ | ||||
| #define PMD_TYPE_MASK		(_AT(pmdval_t, 3) << 0) | ||||
| #define PMD_TYPE_FAULT		(_AT(pmdval_t, 0) << 0) | ||||
| #define PMD_TYPE_TABLE		(_AT(pmdval_t, 3) << 0) | ||||
| #define PMD_TYPE_SECT		(_AT(pmdval_t, 1) << 0) | ||||
| 
 | ||||
| /*
 | ||||
|  * Section | ||||
|  */ | ||||
| #define PMD_SECT_S		(_AT(pmdval_t, 3) << 8) | ||||
| #define PMD_SECT_AF		(_AT(pmdval_t, 1) << 10) | ||||
| #define PMD_SECT_NG		(_AT(pmdval_t, 1) << 11) | ||||
| #define PMD_SECT_XN		(_AT(pmdval_t, 1) << 54) | ||||
| 
 | ||||
| /*
 | ||||
|  * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers). | ||||
|  */ | ||||
| #define PMD_ATTRINDX(t)		(_AT(pmdval_t, (t)) << 2) | ||||
| #define PMD_ATTRINDX_MASK	(_AT(pmdval_t, 7) << 2) | ||||
| 
 | ||||
| /*
 | ||||
|  * Level 3 descriptor (PTE). | ||||
|  */ | ||||
| #define PTE_TYPE_MASK		(_AT(pteval_t, 3) << 0) | ||||
| #define PTE_TYPE_FAULT		(_AT(pteval_t, 0) << 0) | ||||
| #define PTE_TYPE_PAGE		(_AT(pteval_t, 3) << 0) | ||||
| #define PTE_USER		(_AT(pteval_t, 1) << 6)		/* AP[1] */ | ||||
| #define PTE_RDONLY		(_AT(pteval_t, 1) << 7)		/* AP[2] */ | ||||
| #define PTE_SHARED		(_AT(pteval_t, 3) << 8)		/* SH[1:0], inner shareable */ | ||||
| #define PTE_AF			(_AT(pteval_t, 1) << 10)	/* Access Flag */ | ||||
| #define PTE_NG			(_AT(pteval_t, 1) << 11)	/* nG */ | ||||
| #define PTE_XN			(_AT(pteval_t, 1) << 54)	/* XN */ | ||||
| 
 | ||||
| /*
 | ||||
|  * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers). | ||||
|  */ | ||||
| #define PTE_ATTRINDX(t)		(_AT(pteval_t, (t)) << 2) | ||||
| #define PTE_ATTRINDX_MASK	(_AT(pteval_t, 7) << 2) | ||||
| 
 | ||||
| /*
 | ||||
|  * 40-bit physical address supported. | ||||
|  */ | ||||
| #define PHYS_MASK_SHIFT		(40) | ||||
| #define PHYS_MASK		((UL(1) << PHYS_MASK_SHIFT) - 1) | ||||
| 
 | ||||
| /*
 | ||||
|  * TCR flags. | ||||
|  */ | ||||
| #define TCR_TxSZ(x)		(((UL(64) - (x)) << 16) | ((UL(64) - (x)) << 0)) | ||||
| #define TCR_IRGN_NC		((UL(0) << 8) | (UL(0) << 24)) | ||||
| #define TCR_IRGN_WBWA		((UL(1) << 8) | (UL(1) << 24)) | ||||
| #define TCR_IRGN_WT		((UL(2) << 8) | (UL(2) << 24)) | ||||
| #define TCR_IRGN_WBnWA		((UL(3) << 8) | (UL(3) << 24)) | ||||
| #define TCR_IRGN_MASK		((UL(3) << 8) | (UL(3) << 24)) | ||||
| #define TCR_ORGN_NC		((UL(0) << 10) | (UL(0) << 26)) | ||||
| #define TCR_ORGN_WBWA		((UL(1) << 10) | (UL(1) << 26)) | ||||
| #define TCR_ORGN_WT		((UL(2) << 10) | (UL(2) << 26)) | ||||
| #define TCR_ORGN_WBnWA		((UL(3) << 10) | (UL(3) << 26)) | ||||
| #define TCR_ORGN_MASK		((UL(3) << 10) | (UL(3) << 26)) | ||||
| #define TCR_SHARED		((UL(3) << 12) | (UL(3) << 28)) | ||||
| #define TCR_TG0_64K		(UL(1) << 14) | ||||
| #define TCR_TG1_64K		(UL(1) << 30) | ||||
| #define TCR_IPS_40BIT		(UL(2) << 32) | ||||
| #define TCR_ASID16		(UL(1) << 36) | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										328
									
								
								arch/arm64/include/asm/pgtable.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										328
									
								
								arch/arm64/include/asm/pgtable.h
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,328 @@ | |||
| /*
 | ||||
|  * Copyright (C) 2012 ARM Ltd. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License version 2 as | ||||
|  * published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| #ifndef __ASM_PGTABLE_H | ||||
| #define __ASM_PGTABLE_H | ||||
| 
 | ||||
| #include <asm/proc-fns.h> | ||||
| 
 | ||||
| #include <asm/memory.h> | ||||
| #include <asm/pgtable-hwdef.h> | ||||
| 
 | ||||
| /*
 | ||||
|  * Software defined PTE bits definition. | ||||
|  */ | ||||
| #define PTE_VALID		(_AT(pteval_t, 1) << 0)	/* pte_present() check */ | ||||
| #define PTE_FILE		(_AT(pteval_t, 1) << 2)	/* only when !pte_present() */ | ||||
| #define PTE_DIRTY		(_AT(pteval_t, 1) << 55) | ||||
| #define PTE_SPECIAL		(_AT(pteval_t, 1) << 56) | ||||
| 
 | ||||
| /*
 | ||||
|  * VMALLOC and SPARSEMEM_VMEMMAP ranges. | ||||
|  */ | ||||
| #define VMALLOC_START		UL(0xffffff8000000000) | ||||
| #define VMALLOC_END		(PAGE_OFFSET - UL(0x400000000) - SZ_64K) | ||||
| 
 | ||||
| #define vmemmap			((struct page *)(VMALLOC_END + SZ_64K)) | ||||
| 
 | ||||
| #define FIRST_USER_ADDRESS	0 | ||||
| 
 | ||||
| #ifndef __ASSEMBLY__ | ||||
| extern void __pte_error(const char *file, int line, unsigned long val); | ||||
| extern void __pmd_error(const char *file, int line, unsigned long val); | ||||
| extern void __pgd_error(const char *file, int line, unsigned long val); | ||||
| 
 | ||||
| #define pte_ERROR(pte)		__pte_error(__FILE__, __LINE__, pte_val(pte)) | ||||
| #ifndef CONFIG_ARM64_64K_PAGES | ||||
| #define pmd_ERROR(pmd)		__pmd_error(__FILE__, __LINE__, pmd_val(pmd)) | ||||
| #endif | ||||
| #define pgd_ERROR(pgd)		__pgd_error(__FILE__, __LINE__, pgd_val(pgd)) | ||||
| 
 | ||||
| /*
 | ||||
|  * The pgprot_* and protection_map entries will be fixed up at runtime to | ||||
|  * include the cachable and bufferable bits based on memory policy, as well as | ||||
|  * any architecture dependent bits like global/ASID and SMP shared mapping | ||||
|  * bits. | ||||
|  */ | ||||
| #define _PAGE_DEFAULT		PTE_TYPE_PAGE | PTE_AF | ||||
| 
 | ||||
| extern pgprot_t pgprot_default; | ||||
| 
 | ||||
| #define _MOD_PROT(p, b)	__pgprot(pgprot_val(p) | (b)) | ||||
| 
 | ||||
| #define PAGE_NONE		_MOD_PROT(pgprot_default, PTE_NG | PTE_XN | PTE_RDONLY) | ||||
| #define PAGE_SHARED		_MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_XN) | ||||
| #define PAGE_SHARED_EXEC	_MOD_PROT(pgprot_default, PTE_USER | PTE_NG) | ||||
| #define PAGE_COPY		_MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY) | ||||
| #define PAGE_COPY_EXEC		_MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_RDONLY) | ||||
| #define PAGE_READONLY		_MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY) | ||||
| #define PAGE_READONLY_EXEC	_MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_RDONLY) | ||||
| #define PAGE_KERNEL		_MOD_PROT(pgprot_default, PTE_XN | PTE_DIRTY) | ||||
| #define PAGE_KERNEL_EXEC	_MOD_PROT(pgprot_default, PTE_DIRTY) | ||||
| 
 | ||||
| #define __PAGE_NONE		__pgprot(_PAGE_DEFAULT | PTE_NG | PTE_XN | PTE_RDONLY) | ||||
| #define __PAGE_SHARED		__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_XN) | ||||
| #define __PAGE_SHARED_EXEC	__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG) | ||||
| #define __PAGE_COPY		__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY) | ||||
| #define __PAGE_COPY_EXEC	__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_RDONLY) | ||||
| #define __PAGE_READONLY		__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY) | ||||
| #define __PAGE_READONLY_EXEC	__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_RDONLY) | ||||
| 
 | ||||
| #endif /* __ASSEMBLY__ */ | ||||
| 
 | ||||
| #define __P000  __PAGE_NONE | ||||
| #define __P001  __PAGE_READONLY | ||||
| #define __P010  __PAGE_COPY | ||||
| #define __P011  __PAGE_COPY | ||||
| #define __P100  __PAGE_READONLY_EXEC | ||||
| #define __P101  __PAGE_READONLY_EXEC | ||||
| #define __P110  __PAGE_COPY_EXEC | ||||
| #define __P111  __PAGE_COPY_EXEC | ||||
| 
 | ||||
| #define __S000  __PAGE_NONE | ||||
| #define __S001  __PAGE_READONLY | ||||
| #define __S010  __PAGE_SHARED | ||||
| #define __S011  __PAGE_SHARED | ||||
| #define __S100  __PAGE_READONLY_EXEC | ||||
| #define __S101  __PAGE_READONLY_EXEC | ||||
| #define __S110  __PAGE_SHARED_EXEC | ||||
| #define __S111  __PAGE_SHARED_EXEC | ||||
| 
 | ||||
| #ifndef __ASSEMBLY__ | ||||
| /*
 | ||||
|  * ZERO_PAGE is a global shared page that is always zero: used | ||||
|  * for zero-mapped memory areas etc.. | ||||
|  */ | ||||
| extern struct page *empty_zero_page; | ||||
| #define ZERO_PAGE(vaddr)	(empty_zero_page) | ||||
| 
 | ||||
| #define pte_pfn(pte)		((pte_val(pte) & PHYS_MASK) >> PAGE_SHIFT) | ||||
| 
 | ||||
| #define pfn_pte(pfn,prot)	(__pte(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot))) | ||||
| 
 | ||||
| #define pte_none(pte)		(!pte_val(pte)) | ||||
| #define pte_clear(mm,addr,ptep)	set_pte(ptep, __pte(0)) | ||||
| #define pte_page(pte)		(pfn_to_page(pte_pfn(pte))) | ||||
| #define pte_offset_kernel(dir,addr)	(pmd_page_vaddr(*(dir)) + __pte_index(addr)) | ||||
| 
 | ||||
| #define pte_offset_map(dir,addr)	pte_offset_kernel((dir), (addr)) | ||||
| #define pte_offset_map_nested(dir,addr)	pte_offset_kernel((dir), (addr)) | ||||
| #define pte_unmap(pte)			do { } while (0) | ||||
| #define pte_unmap_nested(pte)		do { } while (0) | ||||
| 
 | ||||
| /*
 | ||||
|  * The following only work if pte_present(). Undefined behaviour otherwise. | ||||
|  */ | ||||
| #define pte_present(pte)	(pte_val(pte) & PTE_VALID) | ||||
| #define pte_dirty(pte)		(pte_val(pte) & PTE_DIRTY) | ||||
| #define pte_young(pte)		(pte_val(pte) & PTE_AF) | ||||
| #define pte_special(pte)	(pte_val(pte) & PTE_SPECIAL) | ||||
| #define pte_write(pte)		(!(pte_val(pte) & PTE_RDONLY)) | ||||
| #define pte_exec(pte)		(!(pte_val(pte) & PTE_XN)) | ||||
| 
 | ||||
| #define pte_present_exec_user(pte) \ | ||||
| 	((pte_val(pte) & (PTE_VALID | PTE_USER | PTE_XN)) == \ | ||||
| 	 (PTE_VALID | PTE_USER)) | ||||
| 
 | ||||
| #define PTE_BIT_FUNC(fn,op) \ | ||||
| static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } | ||||
| 
 | ||||
| PTE_BIT_FUNC(wrprotect, |= PTE_RDONLY); | ||||
| PTE_BIT_FUNC(mkwrite,   &= ~PTE_RDONLY); | ||||
| PTE_BIT_FUNC(mkclean,   &= ~PTE_DIRTY); | ||||
| PTE_BIT_FUNC(mkdirty,   |= PTE_DIRTY); | ||||
| PTE_BIT_FUNC(mkold,     &= ~PTE_AF); | ||||
| PTE_BIT_FUNC(mkyoung,   |= PTE_AF); | ||||
| PTE_BIT_FUNC(mkspecial, |= PTE_SPECIAL); | ||||
| 
 | ||||
| static inline void set_pte(pte_t *ptep, pte_t pte) | ||||
| { | ||||
| 	*ptep = pte; | ||||
| } | ||||
| 
 | ||||
| extern void __sync_icache_dcache(pte_t pteval, unsigned long addr); | ||||
| 
 | ||||
| static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, | ||||
| 			      pte_t *ptep, pte_t pte) | ||||
| { | ||||
| 	if (pte_present_exec_user(pte)) | ||||
| 		__sync_icache_dcache(pte, addr); | ||||
| 	set_pte(ptep, pte); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Huge pte definitions. | ||||
|  */ | ||||
| #define pte_huge(pte)		((pte_val(pte) & PTE_TYPE_MASK) == PTE_TYPE_HUGEPAGE) | ||||
| #define pte_mkhuge(pte)		(__pte((pte_val(pte) & ~PTE_TYPE_MASK) | PTE_TYPE_HUGEPAGE)) | ||||
| 
 | ||||
| #define __pgprot_modify(prot,mask,bits)		\ | ||||
| 	__pgprot((pgprot_val(prot) & ~(mask)) | (bits)) | ||||
| 
 | ||||
| #define __HAVE_ARCH_PTE_SPECIAL | ||||
| 
 | ||||
| /*
 | ||||
|  * Mark the prot value as uncacheable and unbufferable. | ||||
|  */ | ||||
| #define pgprot_noncached(prot) \ | ||||
| 	__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRnE)) | ||||
| #define pgprot_writecombine(prot) \ | ||||
| 	__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_GRE)) | ||||
| #define pgprot_dmacoherent(prot) \ | ||||
| 	__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC)) | ||||
| #define __HAVE_PHYS_MEM_ACCESS_PROT | ||||
| struct file; | ||||
| extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, | ||||
| 				     unsigned long size, pgprot_t vma_prot); | ||||
| 
 | ||||
| #define pmd_none(pmd)		(!pmd_val(pmd)) | ||||
| #define pmd_present(pmd)	(pmd_val(pmd)) | ||||
| 
 | ||||
| #define pmd_bad(pmd)		(!(pmd_val(pmd) & 2)) | ||||
| 
 | ||||
| static inline void set_pmd(pmd_t *pmdp, pmd_t pmd) | ||||
| { | ||||
| 	*pmdp = pmd; | ||||
| 	dsb(); | ||||
| } | ||||
| 
 | ||||
| static inline void pmd_clear(pmd_t *pmdp) | ||||
| { | ||||
| 	set_pmd(pmdp, __pmd(0)); | ||||
| } | ||||
| 
 | ||||
| static inline pte_t *pmd_page_vaddr(pmd_t pmd) | ||||
| { | ||||
| 	return __va(pmd_val(pmd) & PHYS_MASK & (s32)PAGE_MASK); | ||||
| } | ||||
| 
 | ||||
| #define pmd_page(pmd)		pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK)) | ||||
| 
 | ||||
| /*
 | ||||
|  * Conversion functions: convert a page and protection to a page entry, | ||||
|  * and a page entry and page directory to the page they refer to. | ||||
|  */ | ||||
| #define mk_pte(page,prot)	pfn_pte(page_to_pfn(page),prot) | ||||
| 
 | ||||
| #ifndef CONFIG_ARM64_64K_PAGES | ||||
| 
 | ||||
| #define pud_none(pud)		(!pud_val(pud)) | ||||
| #define pud_bad(pud)		(!(pud_val(pud) & 2)) | ||||
| #define pud_present(pud)	(pud_val(pud)) | ||||
| 
 | ||||
| static inline void set_pud(pud_t *pudp, pud_t pud) | ||||
| { | ||||
| 	*pudp = pud; | ||||
| 	dsb(); | ||||
| } | ||||
| 
 | ||||
| static inline void pud_clear(pud_t *pudp) | ||||
| { | ||||
| 	set_pud(pudp, __pud(0)); | ||||
| } | ||||
| 
 | ||||
| static inline pmd_t *pud_page_vaddr(pud_t pud) | ||||
| { | ||||
| 	return __va(pud_val(pud) & PHYS_MASK & (s32)PAGE_MASK); | ||||
| } | ||||
| 
 | ||||
| #endif	/* CONFIG_ARM64_64K_PAGES */ | ||||
| 
 | ||||
| /* to find an entry in a page-table-directory */ | ||||
| #define pgd_index(addr)		(((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)) | ||||
| 
 | ||||
| #define pgd_offset(mm, addr)	((mm)->pgd+pgd_index(addr)) | ||||
| 
 | ||||
| /* to find an entry in a kernel page-table-directory */ | ||||
| #define pgd_offset_k(addr)	pgd_offset(&init_mm, addr) | ||||
| 
 | ||||
| /* Find an entry in the second-level page table.. */ | ||||
| #ifndef CONFIG_ARM64_64K_PAGES | ||||
| #define pmd_index(addr)		(((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) | ||||
| static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr) | ||||
| { | ||||
| 	return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(addr); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| /* Find an entry in the third-level page table.. */ | ||||
| #define __pte_index(addr)	(((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) | ||||
| 
 | ||||
| static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | ||||
| { | ||||
| 	const pteval_t mask = PTE_USER | PTE_XN | PTE_RDONLY; | ||||
| 	pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask); | ||||
| 	return pte; | ||||
| } | ||||
| 
 | ||||
| extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; | ||||
| extern pgd_t idmap_pg_dir[PTRS_PER_PGD]; | ||||
| 
 | ||||
| #define SWAPPER_DIR_SIZE	(3 * PAGE_SIZE) | ||||
| #define IDMAP_DIR_SIZE		(2 * PAGE_SIZE) | ||||
| 
 | ||||
| /*
 | ||||
|  * Encode and decode a swap entry: | ||||
|  *	bits 0-1:	present (must be zero) | ||||
|  *	bit  2:		PTE_FILE | ||||
|  *	bits 3-8:	swap type | ||||
|  *	bits 9-63:	swap offset | ||||
|  */ | ||||
| #define __SWP_TYPE_SHIFT	3 | ||||
| #define __SWP_TYPE_BITS		6 | ||||
| #define __SWP_TYPE_MASK		((1 << __SWP_TYPE_BITS) - 1) | ||||
| #define __SWP_OFFSET_SHIFT	(__SWP_TYPE_BITS + __SWP_TYPE_SHIFT) | ||||
| 
 | ||||
| #define __swp_type(x)		(((x).val >> __SWP_TYPE_SHIFT) & __SWP_TYPE_MASK) | ||||
| #define __swp_offset(x)		((x).val >> __SWP_OFFSET_SHIFT) | ||||
| #define __swp_entry(type,offset) ((swp_entry_t) { ((type) << __SWP_TYPE_SHIFT) | ((offset) << __SWP_OFFSET_SHIFT) }) | ||||
| 
 | ||||
| #define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) }) | ||||
| #define __swp_entry_to_pte(swp)	((pte_t) { (swp).val }) | ||||
| 
 | ||||
| /*
 | ||||
|  * Ensure that there are not more swap files than can be encoded in the kernel | ||||
|  * the PTEs. | ||||
|  */ | ||||
| #define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > __SWP_TYPE_BITS) | ||||
| 
 | ||||
| /*
 | ||||
|  * Encode and decode a file entry: | ||||
|  *	bits 0-1:	present (must be zero) | ||||
|  *	bit  2:		PTE_FILE | ||||
|  *	bits 3-63:	file offset / PAGE_SIZE | ||||
|  */ | ||||
| #define pte_file(pte)		(pte_val(pte) & PTE_FILE) | ||||
| #define pte_to_pgoff(x)		(pte_val(x) >> 3) | ||||
| #define pgoff_to_pte(x)		__pte(((x) << 3) | PTE_FILE) | ||||
| 
 | ||||
| #define PTE_FILE_MAX_BITS	61 | ||||
| 
 | ||||
| extern int kern_addr_valid(unsigned long addr); | ||||
| 
 | ||||
| #include <asm-generic/pgtable.h> | ||||
| 
 | ||||
| /*
 | ||||
|  * 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) | ||||
| 
 | ||||
| #define pgtable_cache_init() do { } while (0) | ||||
| 
 | ||||
| #endif /* !__ASSEMBLY__ */ | ||||
| 
 | ||||
| #endif /* __ASM_PGTABLE_H */ | ||||
							
								
								
									
										24
									
								
								arch/arm64/include/asm/sparsemem.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								arch/arm64/include/asm/sparsemem.h
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | |||
| /*
 | ||||
|  * Copyright (C) 2012 ARM Ltd. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License version 2 as | ||||
|  * published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| #ifndef __ASM_SPARSEMEM_H | ||||
| #define __ASM_SPARSEMEM_H | ||||
| 
 | ||||
| #ifdef CONFIG_SPARSEMEM | ||||
| #define MAX_PHYSMEM_BITS	40 | ||||
| #define SECTION_SIZE_BITS	30 | ||||
| #endif | ||||
| 
 | ||||
| #endif | ||||
		Loading…
	
		Reference in a new issue
	
	 Catalin Marinas
						Catalin Marinas