aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/include
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/include')
-rw-r--r--arch/arm/include/asm/assembler.h11
-rw-r--r--arch/arm/include/asm/page.h4
-rw-r--r--arch/arm/include/asm/pgalloc.h26
-rw-r--r--arch/arm/include/asm/pgtable-2level.h41
-rw-r--r--arch/arm/include/asm/pgtable-3level-hwdef.h77
-rw-r--r--arch/arm/include/asm/pgtable-3level-types.h70
-rw-r--r--arch/arm/include/asm/pgtable-3level.h155
-rw-r--r--arch/arm/include/asm/pgtable-hwdef.h4
-rw-r--r--arch/arm/include/asm/pgtable.h43
-rw-r--r--arch/arm/include/asm/proc-fns.h21
-rw-r--r--arch/arm/include/asm/system.h8
-rw-r--r--arch/arm/include/asm/tlb.h12
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)
152extern void copy_page(void *to, const void *from); 152extern 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
30static 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
35static 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
41static 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
35extern pgd_t *pgd_alloc(struct mm_struct *mm); 57extern pgd_t *pgd_alloc(struct mm_struct *mm);
36extern void pgd_free(struct mm_struct *mm, pgd_t *pgd); 58extern 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
156static 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
25typedef u64 pteval_t;
26typedef u64 pmdval_t;
27typedef 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 */
36typedef struct { pteval_t pte; } pte_t;
37typedef struct { pmdval_t pmd; } pmd_t;
38typedef struct { pgdval_t pgd; } pgd_t;
39typedef 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
53typedef pteval_t pte_t;
54typedef pmdval_t pmd_t;
55typedef pgdval_t pgd_t;
56typedef 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
125static 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))
132static 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
201static inline pte_t *pmd_page_vaddr(pmd_t pmd) 175static 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);
79extern int cpu_do_idle(void); 83extern int cpu_do_idle(void);
80extern void cpu_dcache_clean_area(void *, int); 84extern void cpu_dcache_clean_area(void *, int);
81extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm); 85extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm);
86#ifdef CONFIG_ARM_LPAE
87extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte);
88#else
82extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext); 89extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext);
90#endif
83extern void cpu_reset(unsigned long addr) __attribute__((noreturn)); 91extern 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;
80void arm_notify_die(const char *str, struct pt_regs *regs, struct siginfo *info, 80void 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
83void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int, 91void 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
205static 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