diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-12-08 13:02:04 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-12-08 13:02:04 -0500 |
commit | 6ae25a5b9d7ba86d6ac19c403dfa57dae6caa73d (patch) | |
tree | 41d04269f268d6162e5f1866496dd42fbc79d2a4 /arch/arm/include | |
parent | 3ee0fc5ca129cbae81c073756febcb1c552af446 (diff) | |
parent | 497b7e943d0dc5743454de56dcdb67352bbf96b2 (diff) |
Merge branch 'for-rmk' of git://git.kernel.org/pub/scm/linux/kernel/git/cmarinas/linux into devel-stable
Conflicts:
arch/arm/mm/ioremap.c
Diffstat (limited to 'arch/arm/include')
-rw-r--r-- | arch/arm/include/asm/assembler.h | 11 | ||||
-rw-r--r-- | arch/arm/include/asm/page.h | 4 | ||||
-rw-r--r-- | arch/arm/include/asm/pgalloc.h | 26 | ||||
-rw-r--r-- | arch/arm/include/asm/pgtable-2level.h | 41 | ||||
-rw-r--r-- | arch/arm/include/asm/pgtable-3level-hwdef.h | 77 | ||||
-rw-r--r-- | arch/arm/include/asm/pgtable-3level-types.h | 70 | ||||
-rw-r--r-- | arch/arm/include/asm/pgtable-3level.h | 155 | ||||
-rw-r--r-- | arch/arm/include/asm/pgtable-hwdef.h | 4 | ||||
-rw-r--r-- | arch/arm/include/asm/pgtable.h | 43 | ||||
-rw-r--r-- | arch/arm/include/asm/proc-fns.h | 21 | ||||
-rw-r--r-- | arch/arm/include/asm/system.h | 8 | ||||
-rw-r--r-- | arch/arm/include/asm/tlb.h | 12 |
12 files changed, 433 insertions, 39 deletions
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index 29035e86a59d..b6e65dedfd71 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h | |||
@@ -187,6 +187,17 @@ | |||
187 | #endif | 187 | #endif |
188 | 188 | ||
189 | /* | 189 | /* |
190 | * Instruction barrier | ||
191 | */ | ||
192 | .macro instr_sync | ||
193 | #if __LINUX_ARM_ARCH__ >= 7 | ||
194 | isb | ||
195 | #elif __LINUX_ARM_ARCH__ == 6 | ||
196 | mcr p15, 0, r0, c7, c5, 4 | ||
197 | #endif | ||
198 | .endm | ||
199 | |||
200 | /* | ||
190 | * SMP data memory barrier | 201 | * SMP data memory barrier |
191 | */ | 202 | */ |
192 | .macro smp_dmb mode | 203 | .macro smp_dmb mode |
diff --git a/arch/arm/include/asm/page.h b/arch/arm/include/asm/page.h index ca94653f1ecb..97b440c25c58 100644 --- a/arch/arm/include/asm/page.h +++ b/arch/arm/include/asm/page.h | |||
@@ -151,7 +151,11 @@ extern void __cpu_copy_user_highpage(struct page *to, struct page *from, | |||
151 | #define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) | 151 | #define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) |
152 | extern void copy_page(void *to, const void *from); | 152 | extern void copy_page(void *to, const void *from); |
153 | 153 | ||
154 | #ifdef CONFIG_ARM_LPAE | ||
155 | #include <asm/pgtable-3level-types.h> | ||
156 | #else | ||
154 | #include <asm/pgtable-2level-types.h> | 157 | #include <asm/pgtable-2level-types.h> |
158 | #endif | ||
155 | 159 | ||
156 | #endif /* CONFIG_MMU */ | 160 | #endif /* CONFIG_MMU */ |
157 | 161 | ||
diff --git a/arch/arm/include/asm/pgalloc.h b/arch/arm/include/asm/pgalloc.h index 3e08fd3fbb6b..943504f53f57 100644 --- a/arch/arm/include/asm/pgalloc.h +++ b/arch/arm/include/asm/pgalloc.h | |||
@@ -25,12 +25,34 @@ | |||
25 | #define _PAGE_USER_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_USER)) | 25 | #define _PAGE_USER_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_USER)) |
26 | #define _PAGE_KERNEL_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_KERNEL)) | 26 | #define _PAGE_KERNEL_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_KERNEL)) |
27 | 27 | ||
28 | #ifdef CONFIG_ARM_LPAE | ||
29 | |||
30 | static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) | ||
31 | { | ||
32 | return (pmd_t *)get_zeroed_page(GFP_KERNEL | __GFP_REPEAT); | ||
33 | } | ||
34 | |||
35 | static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) | ||
36 | { | ||
37 | BUG_ON((unsigned long)pmd & (PAGE_SIZE-1)); | ||
38 | free_page((unsigned long)pmd); | ||
39 | } | ||
40 | |||
41 | static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) | ||
42 | { | ||
43 | set_pud(pud, __pud(__pa(pmd) | PMD_TYPE_TABLE)); | ||
44 | } | ||
45 | |||
46 | #else /* !CONFIG_ARM_LPAE */ | ||
47 | |||
28 | /* | 48 | /* |
29 | * Since we have only two-level page tables, these are trivial | 49 | * Since we have only two-level page tables, these are trivial |
30 | */ | 50 | */ |
31 | #define pmd_alloc_one(mm,addr) ({ BUG(); ((pmd_t *)2); }) | 51 | #define pmd_alloc_one(mm,addr) ({ BUG(); ((pmd_t *)2); }) |
32 | #define pmd_free(mm, pmd) do { } while (0) | 52 | #define pmd_free(mm, pmd) do { } while (0) |
33 | #define pgd_populate(mm,pmd,pte) BUG() | 53 | #define pud_populate(mm,pmd,pte) BUG() |
54 | |||
55 | #endif /* CONFIG_ARM_LPAE */ | ||
34 | 56 | ||
35 | extern pgd_t *pgd_alloc(struct mm_struct *mm); | 57 | extern pgd_t *pgd_alloc(struct mm_struct *mm); |
36 | extern void pgd_free(struct mm_struct *mm, pgd_t *pgd); | 58 | extern void pgd_free(struct mm_struct *mm, pgd_t *pgd); |
@@ -109,7 +131,9 @@ static inline void __pmd_populate(pmd_t *pmdp, phys_addr_t pte, | |||
109 | { | 131 | { |
110 | pmdval_t pmdval = (pte + PTE_HWTABLE_OFF) | prot; | 132 | pmdval_t pmdval = (pte + PTE_HWTABLE_OFF) | prot; |
111 | pmdp[0] = __pmd(pmdval); | 133 | pmdp[0] = __pmd(pmdval); |
134 | #ifndef CONFIG_ARM_LPAE | ||
112 | pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t)); | 135 | pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t)); |
136 | #endif | ||
113 | flush_pmd_entry(pmdp); | 137 | flush_pmd_entry(pmdp); |
114 | } | 138 | } |
115 | 139 | ||
diff --git a/arch/arm/include/asm/pgtable-2level.h b/arch/arm/include/asm/pgtable-2level.h index 470457e1cfc5..2317a71c8f8e 100644 --- a/arch/arm/include/asm/pgtable-2level.h +++ b/arch/arm/include/asm/pgtable-2level.h | |||
@@ -140,4 +140,45 @@ | |||
140 | #define L_PTE_MT_DEV_CACHED (_AT(pteval_t, 0x0b) << 2) /* 1011 */ | 140 | #define L_PTE_MT_DEV_CACHED (_AT(pteval_t, 0x0b) << 2) /* 1011 */ |
141 | #define L_PTE_MT_MASK (_AT(pteval_t, 0x0f) << 2) | 141 | #define L_PTE_MT_MASK (_AT(pteval_t, 0x0f) << 2) |
142 | 142 | ||
143 | #ifndef __ASSEMBLY__ | ||
144 | |||
145 | /* | ||
146 | * The "pud_xxx()" functions here are trivial when the pmd is folded into | ||
147 | * the pud: the pud entry is never bad, always exists, and can't be set or | ||
148 | * cleared. | ||
149 | */ | ||
150 | #define pud_none(pud) (0) | ||
151 | #define pud_bad(pud) (0) | ||
152 | #define pud_present(pud) (1) | ||
153 | #define pud_clear(pudp) do { } while (0) | ||
154 | #define set_pud(pud,pudp) do { } while (0) | ||
155 | |||
156 | static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr) | ||
157 | { | ||
158 | return (pmd_t *)pud; | ||
159 | } | ||
160 | |||
161 | #define pmd_bad(pmd) (pmd_val(pmd) & 2) | ||
162 | |||
163 | #define copy_pmd(pmdpd,pmdps) \ | ||
164 | do { \ | ||
165 | pmdpd[0] = pmdps[0]; \ | ||
166 | pmdpd[1] = pmdps[1]; \ | ||
167 | flush_pmd_entry(pmdpd); \ | ||
168 | } while (0) | ||
169 | |||
170 | #define pmd_clear(pmdp) \ | ||
171 | do { \ | ||
172 | pmdp[0] = __pmd(0); \ | ||
173 | pmdp[1] = __pmd(0); \ | ||
174 | clean_pmd_entry(pmdp); \ | ||
175 | } while (0) | ||
176 | |||
177 | /* we don't need complex calculations here as the pmd is folded into the pgd */ | ||
178 | #define pmd_addr_end(addr,end) (end) | ||
179 | |||
180 | #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext) | ||
181 | |||
182 | #endif /* __ASSEMBLY__ */ | ||
183 | |||
143 | #endif /* _ASM_PGTABLE_2LEVEL_H */ | 184 | #endif /* _ASM_PGTABLE_2LEVEL_H */ |
diff --git a/arch/arm/include/asm/pgtable-3level-hwdef.h b/arch/arm/include/asm/pgtable-3level-hwdef.h new file mode 100644 index 000000000000..d7952824c5c4 --- /dev/null +++ b/arch/arm/include/asm/pgtable-3level-hwdef.h | |||
@@ -0,0 +1,77 @@ | |||
1 | /* | ||
2 | * arch/arm/include/asm/pgtable-3level-hwdef.h | ||
3 | * | ||
4 | * Copyright (C) 2011 ARM Ltd. | ||
5 | * Author: Catalin Marinas <catalin.marinas@arm.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | #ifndef _ASM_PGTABLE_3LEVEL_HWDEF_H | ||
21 | #define _ASM_PGTABLE_3LEVEL_HWDEF_H | ||
22 | |||
23 | /* | ||
24 | * Hardware page table definitions. | ||
25 | * | ||
26 | * + Level 1/2 descriptor | ||
27 | * - common | ||
28 | */ | ||
29 | #define PMD_TYPE_MASK (_AT(pmdval_t, 3) << 0) | ||
30 | #define PMD_TYPE_FAULT (_AT(pmdval_t, 0) << 0) | ||
31 | #define PMD_TYPE_TABLE (_AT(pmdval_t, 3) << 0) | ||
32 | #define PMD_TYPE_SECT (_AT(pmdval_t, 1) << 0) | ||
33 | #define PMD_BIT4 (_AT(pmdval_t, 0)) | ||
34 | #define PMD_DOMAIN(x) (_AT(pmdval_t, 0)) | ||
35 | |||
36 | /* | ||
37 | * - section | ||
38 | */ | ||
39 | #define PMD_SECT_BUFFERABLE (_AT(pmdval_t, 1) << 2) | ||
40 | #define PMD_SECT_CACHEABLE (_AT(pmdval_t, 1) << 3) | ||
41 | #define PMD_SECT_S (_AT(pmdval_t, 3) << 8) | ||
42 | #define PMD_SECT_AF (_AT(pmdval_t, 1) << 10) | ||
43 | #define PMD_SECT_nG (_AT(pmdval_t, 1) << 11) | ||
44 | #define PMD_SECT_XN (_AT(pmdval_t, 1) << 54) | ||
45 | #define PMD_SECT_AP_WRITE (_AT(pmdval_t, 0)) | ||
46 | #define PMD_SECT_AP_READ (_AT(pmdval_t, 0)) | ||
47 | #define PMD_SECT_TEX(x) (_AT(pmdval_t, 0)) | ||
48 | |||
49 | /* | ||
50 | * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers). | ||
51 | */ | ||
52 | #define PMD_SECT_UNCACHED (_AT(pmdval_t, 0) << 2) /* strongly ordered */ | ||
53 | #define PMD_SECT_BUFFERED (_AT(pmdval_t, 1) << 2) /* normal non-cacheable */ | ||
54 | #define PMD_SECT_WT (_AT(pmdval_t, 2) << 2) /* normal inner write-through */ | ||
55 | #define PMD_SECT_WB (_AT(pmdval_t, 3) << 2) /* normal inner write-back */ | ||
56 | #define PMD_SECT_WBWA (_AT(pmdval_t, 7) << 2) /* normal inner write-alloc */ | ||
57 | |||
58 | /* | ||
59 | * + Level 3 descriptor (PTE) | ||
60 | */ | ||
61 | #define PTE_TYPE_MASK (_AT(pteval_t, 3) << 0) | ||
62 | #define PTE_TYPE_FAULT (_AT(pteval_t, 0) << 0) | ||
63 | #define PTE_TYPE_PAGE (_AT(pteval_t, 3) << 0) | ||
64 | #define PTE_BUFFERABLE (_AT(pteval_t, 1) << 2) /* AttrIndx[0] */ | ||
65 | #define PTE_CACHEABLE (_AT(pteval_t, 1) << 3) /* AttrIndx[1] */ | ||
66 | #define PTE_EXT_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */ | ||
67 | #define PTE_EXT_AF (_AT(pteval_t, 1) << 10) /* Access Flag */ | ||
68 | #define PTE_EXT_NG (_AT(pteval_t, 1) << 11) /* nG */ | ||
69 | #define PTE_EXT_XN (_AT(pteval_t, 1) << 54) /* XN */ | ||
70 | |||
71 | /* | ||
72 | * 40-bit physical address supported. | ||
73 | */ | ||
74 | #define PHYS_MASK_SHIFT (40) | ||
75 | #define PHYS_MASK ((1ULL << PHYS_MASK_SHIFT) - 1) | ||
76 | |||
77 | #endif | ||
diff --git a/arch/arm/include/asm/pgtable-3level-types.h b/arch/arm/include/asm/pgtable-3level-types.h new file mode 100644 index 000000000000..921aa30259c4 --- /dev/null +++ b/arch/arm/include/asm/pgtable-3level-types.h | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | * arch/arm/include/asm/pgtable-3level-types.h | ||
3 | * | ||
4 | * Copyright (C) 2011 ARM Ltd. | ||
5 | * Author: Catalin Marinas <catalin.marinas@arm.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | #ifndef _ASM_PGTABLE_3LEVEL_TYPES_H | ||
21 | #define _ASM_PGTABLE_3LEVEL_TYPES_H | ||
22 | |||
23 | #include <asm/types.h> | ||
24 | |||
25 | typedef u64 pteval_t; | ||
26 | typedef u64 pmdval_t; | ||
27 | typedef u64 pgdval_t; | ||
28 | |||
29 | #undef STRICT_MM_TYPECHECKS | ||
30 | |||
31 | #ifdef STRICT_MM_TYPECHECKS | ||
32 | |||
33 | /* | ||
34 | * These are used to make use of C type-checking.. | ||
35 | */ | ||
36 | typedef struct { pteval_t pte; } pte_t; | ||
37 | typedef struct { pmdval_t pmd; } pmd_t; | ||
38 | typedef struct { pgdval_t pgd; } pgd_t; | ||
39 | typedef struct { pteval_t pgprot; } pgprot_t; | ||
40 | |||
41 | #define pte_val(x) ((x).pte) | ||
42 | #define pmd_val(x) ((x).pmd) | ||
43 | #define pgd_val(x) ((x).pgd) | ||
44 | #define pgprot_val(x) ((x).pgprot) | ||
45 | |||
46 | #define __pte(x) ((pte_t) { (x) } ) | ||
47 | #define __pmd(x) ((pmd_t) { (x) } ) | ||
48 | #define __pgd(x) ((pgd_t) { (x) } ) | ||
49 | #define __pgprot(x) ((pgprot_t) { (x) } ) | ||
50 | |||
51 | #else /* !STRICT_MM_TYPECHECKS */ | ||
52 | |||
53 | typedef pteval_t pte_t; | ||
54 | typedef pmdval_t pmd_t; | ||
55 | typedef pgdval_t pgd_t; | ||
56 | typedef pteval_t pgprot_t; | ||
57 | |||
58 | #define pte_val(x) (x) | ||
59 | #define pmd_val(x) (x) | ||
60 | #define pgd_val(x) (x) | ||
61 | #define pgprot_val(x) (x) | ||
62 | |||
63 | #define __pte(x) (x) | ||
64 | #define __pmd(x) (x) | ||
65 | #define __pgd(x) (x) | ||
66 | #define __pgprot(x) (x) | ||
67 | |||
68 | #endif /* STRICT_MM_TYPECHECKS */ | ||
69 | |||
70 | #endif /* _ASM_PGTABLE_3LEVEL_TYPES_H */ | ||
diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h new file mode 100644 index 000000000000..759af70f9a0a --- /dev/null +++ b/arch/arm/include/asm/pgtable-3level.h | |||
@@ -0,0 +1,155 @@ | |||
1 | /* | ||
2 | * arch/arm/include/asm/pgtable-3level.h | ||
3 | * | ||
4 | * Copyright (C) 2011 ARM Ltd. | ||
5 | * Author: Catalin Marinas <catalin.marinas@arm.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | #ifndef _ASM_PGTABLE_3LEVEL_H | ||
21 | #define _ASM_PGTABLE_3LEVEL_H | ||
22 | |||
23 | /* | ||
24 | * With LPAE, there are 3 levels of page tables. Each level has 512 entries of | ||
25 | * 8 bytes each, occupying a 4K page. The first level table covers a range of | ||
26 | * 512GB, each entry representing 1GB. Since we are limited to 4GB input | ||
27 | * address range, only 4 entries in the PGD are used. | ||
28 | * | ||
29 | * There are enough spare bits in a page table entry for the kernel specific | ||
30 | * state. | ||
31 | */ | ||
32 | #define PTRS_PER_PTE 512 | ||
33 | #define PTRS_PER_PMD 512 | ||
34 | #define PTRS_PER_PGD 4 | ||
35 | |||
36 | #define PTE_HWTABLE_PTRS (PTRS_PER_PTE) | ||
37 | #define PTE_HWTABLE_OFF (0) | ||
38 | #define PTE_HWTABLE_SIZE (PTRS_PER_PTE * sizeof(u64)) | ||
39 | |||
40 | /* | ||
41 | * PGDIR_SHIFT determines the size a top-level page table entry can map. | ||
42 | */ | ||
43 | #define PGDIR_SHIFT 30 | ||
44 | |||
45 | /* | ||
46 | * PMD_SHIFT determines the size a middle-level page table entry can map. | ||
47 | */ | ||
48 | #define PMD_SHIFT 21 | ||
49 | |||
50 | #define PMD_SIZE (1UL << PMD_SHIFT) | ||
51 | #define PMD_MASK (~(PMD_SIZE-1)) | ||
52 | #define PGDIR_SIZE (1UL << PGDIR_SHIFT) | ||
53 | #define PGDIR_MASK (~(PGDIR_SIZE-1)) | ||
54 | |||
55 | /* | ||
56 | * section address mask and size definitions. | ||
57 | */ | ||
58 | #define SECTION_SHIFT 21 | ||
59 | #define SECTION_SIZE (1UL << SECTION_SHIFT) | ||
60 | #define SECTION_MASK (~(SECTION_SIZE-1)) | ||
61 | |||
62 | #define USER_PTRS_PER_PGD (PAGE_OFFSET / PGDIR_SIZE) | ||
63 | |||
64 | /* | ||
65 | * "Linux" PTE definitions for LPAE. | ||
66 | * | ||
67 | * These bits overlap with the hardware bits but the naming is preserved for | ||
68 | * consistency with the classic page table format. | ||
69 | */ | ||
70 | #define L_PTE_PRESENT (_AT(pteval_t, 3) << 0) /* Valid */ | ||
71 | #define L_PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !PRESENT */ | ||
72 | #define L_PTE_BUFFERABLE (_AT(pteval_t, 1) << 2) /* AttrIndx[0] */ | ||
73 | #define L_PTE_CACHEABLE (_AT(pteval_t, 1) << 3) /* AttrIndx[1] */ | ||
74 | #define L_PTE_USER (_AT(pteval_t, 1) << 6) /* AP[1] */ | ||
75 | #define L_PTE_RDONLY (_AT(pteval_t, 1) << 7) /* AP[2] */ | ||
76 | #define L_PTE_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */ | ||
77 | #define L_PTE_YOUNG (_AT(pteval_t, 1) << 10) /* AF */ | ||
78 | #define L_PTE_XN (_AT(pteval_t, 1) << 54) /* XN */ | ||
79 | #define L_PTE_DIRTY (_AT(pteval_t, 1) << 55) /* unused */ | ||
80 | #define L_PTE_SPECIAL (_AT(pteval_t, 1) << 56) /* unused */ | ||
81 | |||
82 | /* | ||
83 | * To be used in assembly code with the upper page attributes. | ||
84 | */ | ||
85 | #define L_PTE_XN_HIGH (1 << (54 - 32)) | ||
86 | #define L_PTE_DIRTY_HIGH (1 << (55 - 32)) | ||
87 | |||
88 | /* | ||
89 | * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers). | ||
90 | */ | ||
91 | #define L_PTE_MT_UNCACHED (_AT(pteval_t, 0) << 2) /* strongly ordered */ | ||
92 | #define L_PTE_MT_BUFFERABLE (_AT(pteval_t, 1) << 2) /* normal non-cacheable */ | ||
93 | #define L_PTE_MT_WRITETHROUGH (_AT(pteval_t, 2) << 2) /* normal inner write-through */ | ||
94 | #define L_PTE_MT_WRITEBACK (_AT(pteval_t, 3) << 2) /* normal inner write-back */ | ||
95 | #define L_PTE_MT_WRITEALLOC (_AT(pteval_t, 7) << 2) /* normal inner write-alloc */ | ||
96 | #define L_PTE_MT_DEV_SHARED (_AT(pteval_t, 4) << 2) /* device */ | ||
97 | #define L_PTE_MT_DEV_NONSHARED (_AT(pteval_t, 4) << 2) /* device */ | ||
98 | #define L_PTE_MT_DEV_WC (_AT(pteval_t, 1) << 2) /* normal non-cacheable */ | ||
99 | #define L_PTE_MT_DEV_CACHED (_AT(pteval_t, 3) << 2) /* normal inner write-back */ | ||
100 | #define L_PTE_MT_MASK (_AT(pteval_t, 7) << 2) | ||
101 | |||
102 | /* | ||
103 | * Software PGD flags. | ||
104 | */ | ||
105 | #define L_PGD_SWAPPER (_AT(pgdval_t, 1) << 55) /* swapper_pg_dir entry */ | ||
106 | |||
107 | #ifndef __ASSEMBLY__ | ||
108 | |||
109 | #define pud_none(pud) (!pud_val(pud)) | ||
110 | #define pud_bad(pud) (!(pud_val(pud) & 2)) | ||
111 | #define pud_present(pud) (pud_val(pud)) | ||
112 | |||
113 | #define pud_clear(pudp) \ | ||
114 | do { \ | ||
115 | *pudp = __pud(0); \ | ||
116 | clean_pmd_entry(pudp); \ | ||
117 | } while (0) | ||
118 | |||
119 | #define set_pud(pudp, pud) \ | ||
120 | do { \ | ||
121 | *pudp = pud; \ | ||
122 | flush_pmd_entry(pudp); \ | ||
123 | } while (0) | ||
124 | |||
125 | static inline pmd_t *pud_page_vaddr(pud_t pud) | ||
126 | { | ||
127 | return __va(pud_val(pud) & PHYS_MASK & (s32)PAGE_MASK); | ||
128 | } | ||
129 | |||
130 | /* Find an entry in the second-level page table.. */ | ||
131 | #define pmd_index(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) | ||
132 | static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr) | ||
133 | { | ||
134 | return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(addr); | ||
135 | } | ||
136 | |||
137 | #define pmd_bad(pmd) (!(pmd_val(pmd) & 2)) | ||
138 | |||
139 | #define copy_pmd(pmdpd,pmdps) \ | ||
140 | do { \ | ||
141 | *pmdpd = *pmdps; \ | ||
142 | flush_pmd_entry(pmdpd); \ | ||
143 | } while (0) | ||
144 | |||
145 | #define pmd_clear(pmdp) \ | ||
146 | do { \ | ||
147 | *pmdp = __pmd(0); \ | ||
148 | clean_pmd_entry(pmdp); \ | ||
149 | } while (0) | ||
150 | |||
151 | #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,__pte(pte_val(pte)|(ext))) | ||
152 | |||
153 | #endif /* __ASSEMBLY__ */ | ||
154 | |||
155 | #endif /* _ASM_PGTABLE_3LEVEL_H */ | ||
diff --git a/arch/arm/include/asm/pgtable-hwdef.h b/arch/arm/include/asm/pgtable-hwdef.h index 183111164ce9..8426229ba292 100644 --- a/arch/arm/include/asm/pgtable-hwdef.h +++ b/arch/arm/include/asm/pgtable-hwdef.h | |||
@@ -10,6 +10,10 @@ | |||
10 | #ifndef _ASMARM_PGTABLE_HWDEF_H | 10 | #ifndef _ASMARM_PGTABLE_HWDEF_H |
11 | #define _ASMARM_PGTABLE_HWDEF_H | 11 | #define _ASMARM_PGTABLE_HWDEF_H |
12 | 12 | ||
13 | #ifdef CONFIG_ARM_LPAE | ||
14 | #include <asm/pgtable-3level-hwdef.h> | ||
15 | #else | ||
13 | #include <asm/pgtable-2level-hwdef.h> | 16 | #include <asm/pgtable-2level-hwdef.h> |
17 | #endif | ||
14 | 18 | ||
15 | #endif | 19 | #endif |
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index a784859cc7a9..3f2f0eb76211 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h | |||
@@ -11,19 +11,24 @@ | |||
11 | #define _ASMARM_PGTABLE_H | 11 | #define _ASMARM_PGTABLE_H |
12 | 12 | ||
13 | #include <linux/const.h> | 13 | #include <linux/const.h> |
14 | #include <asm-generic/4level-fixup.h> | ||
15 | #include <asm/proc-fns.h> | 14 | #include <asm/proc-fns.h> |
16 | 15 | ||
17 | #ifndef CONFIG_MMU | 16 | #ifndef CONFIG_MMU |
18 | 17 | ||
18 | #include <asm-generic/4level-fixup.h> | ||
19 | #include "pgtable-nommu.h" | 19 | #include "pgtable-nommu.h" |
20 | 20 | ||
21 | #else | 21 | #else |
22 | 22 | ||
23 | #include <asm-generic/pgtable-nopud.h> | ||
23 | #include <asm/memory.h> | 24 | #include <asm/memory.h> |
24 | #include <asm/pgtable-hwdef.h> | 25 | #include <asm/pgtable-hwdef.h> |
25 | 26 | ||
27 | #ifdef CONFIG_ARM_LPAE | ||
28 | #include <asm/pgtable-3level.h> | ||
29 | #else | ||
26 | #include <asm/pgtable-2level.h> | 30 | #include <asm/pgtable-2level.h> |
31 | #endif | ||
27 | 32 | ||
28 | /* | 33 | /* |
29 | * Just any arbitrary offset to the start of the vmalloc VM area: the | 34 | * Just any arbitrary offset to the start of the vmalloc VM area: the |
@@ -164,39 +169,8 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; | |||
164 | /* to find an entry in a kernel page-table-directory */ | 169 | /* to find an entry in a kernel page-table-directory */ |
165 | #define pgd_offset_k(addr) pgd_offset(&init_mm, addr) | 170 | #define pgd_offset_k(addr) pgd_offset(&init_mm, addr) |
166 | 171 | ||
167 | /* | ||
168 | * The "pgd_xxx()" functions here are trivial for a folded two-level | ||
169 | * setup: the pgd is never bad, and a pmd always exists (as it's folded | ||
170 | * into the pgd entry) | ||
171 | */ | ||
172 | #define pgd_none(pgd) (0) | ||
173 | #define pgd_bad(pgd) (0) | ||
174 | #define pgd_present(pgd) (1) | ||
175 | #define pgd_clear(pgdp) do { } while (0) | ||
176 | #define set_pgd(pgd,pgdp) do { } while (0) | ||
177 | #define set_pud(pud,pudp) do { } while (0) | ||
178 | |||
179 | |||
180 | /* Find an entry in the second-level page table.. */ | ||
181 | #define pmd_offset(dir, addr) ((pmd_t *)(dir)) | ||
182 | |||
183 | #define pmd_none(pmd) (!pmd_val(pmd)) | 172 | #define pmd_none(pmd) (!pmd_val(pmd)) |
184 | #define pmd_present(pmd) (pmd_val(pmd)) | 173 | #define pmd_present(pmd) (pmd_val(pmd)) |
185 | #define pmd_bad(pmd) (pmd_val(pmd) & 2) | ||
186 | |||
187 | #define copy_pmd(pmdpd,pmdps) \ | ||
188 | do { \ | ||
189 | pmdpd[0] = pmdps[0]; \ | ||
190 | pmdpd[1] = pmdps[1]; \ | ||
191 | flush_pmd_entry(pmdpd); \ | ||
192 | } while (0) | ||
193 | |||
194 | #define pmd_clear(pmdp) \ | ||
195 | do { \ | ||
196 | pmdp[0] = __pmd(0); \ | ||
197 | pmdp[1] = __pmd(0); \ | ||
198 | clean_pmd_entry(pmdp); \ | ||
199 | } while (0) | ||
200 | 174 | ||
201 | static inline pte_t *pmd_page_vaddr(pmd_t pmd) | 175 | static inline pte_t *pmd_page_vaddr(pmd_t pmd) |
202 | { | 176 | { |
@@ -205,10 +179,6 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd) | |||
205 | 179 | ||
206 | #define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK)) | 180 | #define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK)) |
207 | 181 | ||
208 | /* we don't need complex calculations here as the pmd is folded into the pgd */ | ||
209 | #define pmd_addr_end(addr,end) (end) | ||
210 | |||
211 | |||
212 | #ifndef CONFIG_HIGHPTE | 182 | #ifndef CONFIG_HIGHPTE |
213 | #define __pte_map(pmd) pmd_page_vaddr(*(pmd)) | 183 | #define __pte_map(pmd) pmd_page_vaddr(*(pmd)) |
214 | #define __pte_unmap(pte) do { } while (0) | 184 | #define __pte_unmap(pte) do { } while (0) |
@@ -230,7 +200,6 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd) | |||
230 | #define pte_page(pte) pfn_to_page(pte_pfn(pte)) | 200 | #define pte_page(pte) pfn_to_page(pte_pfn(pte)) |
231 | #define mk_pte(page,prot) pfn_pte(page_to_pfn(page), prot) | 201 | #define mk_pte(page,prot) pfn_pte(page_to_pfn(page), prot) |
232 | 202 | ||
233 | #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext) | ||
234 | #define pte_clear(mm,addr,ptep) set_pte_ext(ptep, __pte(0), 0) | 203 | #define pte_clear(mm,addr,ptep) set_pte_ext(ptep, __pte(0), 0) |
235 | 204 | ||
236 | #if __LINUX_ARM_ARCH__ < 6 | 205 | #if __LINUX_ARM_ARCH__ < 6 |
diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h index 9e92cb205e65..f3628fb3d2b3 100644 --- a/arch/arm/include/asm/proc-fns.h +++ b/arch/arm/include/asm/proc-fns.h | |||
@@ -65,7 +65,11 @@ extern struct processor { | |||
65 | * Set a possibly extended PTE. Non-extended PTEs should | 65 | * Set a possibly extended PTE. Non-extended PTEs should |
66 | * ignore 'ext'. | 66 | * ignore 'ext'. |
67 | */ | 67 | */ |
68 | #ifdef CONFIG_ARM_LPAE | ||
69 | void (*set_pte_ext)(pte_t *ptep, pte_t pte); | ||
70 | #else | ||
68 | void (*set_pte_ext)(pte_t *ptep, pte_t pte, unsigned int ext); | 71 | void (*set_pte_ext)(pte_t *ptep, pte_t pte, unsigned int ext); |
72 | #endif | ||
69 | 73 | ||
70 | /* Suspend/resume */ | 74 | /* Suspend/resume */ |
71 | unsigned int suspend_size; | 75 | unsigned int suspend_size; |
@@ -79,7 +83,11 @@ extern void cpu_proc_fin(void); | |||
79 | extern int cpu_do_idle(void); | 83 | extern int cpu_do_idle(void); |
80 | extern void cpu_dcache_clean_area(void *, int); | 84 | extern void cpu_dcache_clean_area(void *, int); |
81 | extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm); | 85 | extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm); |
86 | #ifdef CONFIG_ARM_LPAE | ||
87 | extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte); | ||
88 | #else | ||
82 | extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext); | 89 | extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext); |
90 | #endif | ||
83 | extern void cpu_reset(unsigned long addr) __attribute__((noreturn)); | 91 | extern void cpu_reset(unsigned long addr) __attribute__((noreturn)); |
84 | 92 | ||
85 | /* These three are private to arch/arm/kernel/suspend.c */ | 93 | /* These three are private to arch/arm/kernel/suspend.c */ |
@@ -107,6 +115,18 @@ extern void cpu_resume(void); | |||
107 | 115 | ||
108 | #define cpu_switch_mm(pgd,mm) cpu_do_switch_mm(virt_to_phys(pgd),mm) | 116 | #define cpu_switch_mm(pgd,mm) cpu_do_switch_mm(virt_to_phys(pgd),mm) |
109 | 117 | ||
118 | #ifdef CONFIG_ARM_LPAE | ||
119 | #define cpu_get_pgd() \ | ||
120 | ({ \ | ||
121 | unsigned long pg, pg2; \ | ||
122 | __asm__("mrrc p15, 0, %0, %1, c2" \ | ||
123 | : "=r" (pg), "=r" (pg2) \ | ||
124 | : \ | ||
125 | : "cc"); \ | ||
126 | pg &= ~(PTRS_PER_PGD*sizeof(pgd_t)-1); \ | ||
127 | (pgd_t *)phys_to_virt(pg); \ | ||
128 | }) | ||
129 | #else | ||
110 | #define cpu_get_pgd() \ | 130 | #define cpu_get_pgd() \ |
111 | ({ \ | 131 | ({ \ |
112 | unsigned long pg; \ | 132 | unsigned long pg; \ |
@@ -115,6 +135,7 @@ extern void cpu_resume(void); | |||
115 | pg &= ~0x3fff; \ | 135 | pg &= ~0x3fff; \ |
116 | (pgd_t *)phys_to_virt(pg); \ | 136 | (pgd_t *)phys_to_virt(pg); \ |
117 | }) | 137 | }) |
138 | #endif | ||
118 | 139 | ||
119 | #endif | 140 | #endif |
120 | 141 | ||
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index fe7de7571bac..53785828744c 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h | |||
@@ -80,6 +80,14 @@ struct siginfo; | |||
80 | void arm_notify_die(const char *str, struct pt_regs *regs, struct siginfo *info, | 80 | void arm_notify_die(const char *str, struct pt_regs *regs, struct siginfo *info, |
81 | unsigned long err, unsigned long trap); | 81 | unsigned long err, unsigned long trap); |
82 | 82 | ||
83 | #ifdef CONFIG_ARM_LPAE | ||
84 | #define FAULT_CODE_ALIGNMENT 33 | ||
85 | #define FAULT_CODE_DEBUG 34 | ||
86 | #else | ||
87 | #define FAULT_CODE_ALIGNMENT 1 | ||
88 | #define FAULT_CODE_DEBUG 2 | ||
89 | #endif | ||
90 | |||
83 | void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int, | 91 | void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int, |
84 | struct pt_regs *), | 92 | struct pt_regs *), |
85 | int sig, int code, const char *name); | 93 | int sig, int code, const char *name); |
diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h index 265f908c4a6e..5d3ed7e38561 100644 --- a/arch/arm/include/asm/tlb.h +++ b/arch/arm/include/asm/tlb.h | |||
@@ -202,8 +202,18 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, | |||
202 | tlb_remove_page(tlb, pte); | 202 | tlb_remove_page(tlb, pte); |
203 | } | 203 | } |
204 | 204 | ||
205 | static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp, | ||
206 | unsigned long addr) | ||
207 | { | ||
208 | #ifdef CONFIG_ARM_LPAE | ||
209 | tlb_add_flush(tlb, addr); | ||
210 | tlb_remove_page(tlb, virt_to_page(pmdp)); | ||
211 | #endif | ||
212 | } | ||
213 | |||
205 | #define pte_free_tlb(tlb, ptep, addr) __pte_free_tlb(tlb, ptep, addr) | 214 | #define pte_free_tlb(tlb, ptep, addr) __pte_free_tlb(tlb, ptep, addr) |
206 | #define pmd_free_tlb(tlb, pmdp, addr) pmd_free((tlb)->mm, pmdp) | 215 | #define pmd_free_tlb(tlb, pmdp, addr) __pmd_free_tlb(tlb, pmdp, addr) |
216 | #define pud_free_tlb(tlb, pudp, addr) pud_free((tlb)->mm, pudp) | ||
207 | 217 | ||
208 | #define tlb_migrate_finish(mm) do { } while (0) | 218 | #define tlb_migrate_finish(mm) do { } while (0) |
209 | 219 | ||