aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64/mm
diff options
context:
space:
mode:
authorMark Rutland <mark.rutland@arm.com>2015-01-27 11:36:30 -0500
committerCatalin Marinas <catalin.marinas@arm.com>2015-01-28 09:27:43 -0500
commita1c76574f345342d23836b520ce44674d23bc267 (patch)
tree6735a4264e717c4aff50c519c6efe633104745b6 /arch/arm64/mm
parenta3bba370c227b6cbc480aa8959bb32cf966d79a6 (diff)
arm64: mm: use *_sect to check for section maps
The {pgd,pud,pmd}_bad family of macros have slightly fuzzy cross-architecture semantics, and seem to imply a populated entry that is not a next-level table, rather than a particular type of entry (e.g. a section map). In arm64 code, for those cases where we care about whether an entry is a section mapping, we can instead use the {pud,pmd}_sect macros to explicitly check for this case. This helps to document precisely what we care about, making the code easier to read, and allows for future relaxation of the *_bad macros to check for other "bad" entries. To that end this patch updates the table dumping and initial table setup to check for section mappings with {pud,pmd}_sect, and adds/restores BUG_ON(*_bad((*p)) checks after we've handled the *_sect and *_none cases so as to catch remaining "bad" cases. In the fault handling code, show_pte is left with *_bad checks as it only cares about whether it can walk the next level table, and this path is used for both kernel and userspace fault handling. The former case will be followed by a die() where we'll report the address that triggered the fault, which can be useful context for debugging. Signed-off-by: Mark Rutland <mark.rutland@arm.com> Acked-by: Steve Capper <steve.capper@linaro.org> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> Cc: Kees Cook <keescook@chromium.org> Cc: Laura Abbott <lauraa@codeaurora.org> Cc: Will Deacon <will.deacon@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Diffstat (limited to 'arch/arm64/mm')
-rw-r--r--arch/arm64/mm/dump.c18
-rw-r--r--arch/arm64/mm/mmu.c6
2 files changed, 16 insertions, 8 deletions
diff --git a/arch/arm64/mm/dump.c b/arch/arm64/mm/dump.c
index bbc5a29ecaaf..612965375473 100644
--- a/arch/arm64/mm/dump.c
+++ b/arch/arm64/mm/dump.c
@@ -249,10 +249,12 @@ static void walk_pmd(struct pg_state *st, pud_t *pud, unsigned long start)
249 249
250 for (i = 0; i < PTRS_PER_PMD; i++, pmd++) { 250 for (i = 0; i < PTRS_PER_PMD; i++, pmd++) {
251 addr = start + i * PMD_SIZE; 251 addr = start + i * PMD_SIZE;
252 if (pmd_none(*pmd) || pmd_sect(*pmd) || pmd_bad(*pmd)) 252 if (pmd_none(*pmd) || pmd_sect(*pmd)) {
253 note_page(st, addr, 3, pmd_val(*pmd)); 253 note_page(st, addr, 3, pmd_val(*pmd));
254 else 254 } else {
255 BUG_ON(pmd_bad(*pmd));
255 walk_pte(st, pmd, addr); 256 walk_pte(st, pmd, addr);
257 }
256 } 258 }
257} 259}
258 260
@@ -264,10 +266,12 @@ static void walk_pud(struct pg_state *st, pgd_t *pgd, unsigned long start)
264 266
265 for (i = 0; i < PTRS_PER_PUD; i++, pud++) { 267 for (i = 0; i < PTRS_PER_PUD; i++, pud++) {
266 addr = start + i * PUD_SIZE; 268 addr = start + i * PUD_SIZE;
267 if (pud_none(*pud) || pud_sect(*pud) || pud_bad(*pud)) 269 if (pud_none(*pud) || pud_sect(*pud)) {
268 note_page(st, addr, 2, pud_val(*pud)); 270 note_page(st, addr, 2, pud_val(*pud));
269 else 271 } else {
272 BUG_ON(pud_bad(*pud));
270 walk_pmd(st, pud, addr); 273 walk_pmd(st, pud, addr);
274 }
271 } 275 }
272} 276}
273 277
@@ -279,10 +283,12 @@ static void walk_pgd(struct pg_state *st, struct mm_struct *mm, unsigned long st
279 283
280 for (i = 0; i < PTRS_PER_PGD; i++, pgd++) { 284 for (i = 0; i < PTRS_PER_PGD; i++, pgd++) {
281 addr = start + i * PGDIR_SIZE; 285 addr = start + i * PGDIR_SIZE;
282 if (pgd_none(*pgd) || pgd_bad(*pgd)) 286 if (pgd_none(*pgd)) {
283 note_page(st, addr, 1, pgd_val(*pgd)); 287 note_page(st, addr, 1, pgd_val(*pgd));
284 else 288 } else {
289 BUG_ON(pgd_bad(*pgd));
285 walk_pud(st, pgd, addr); 290 walk_pud(st, pgd, addr);
291 }
286 } 292 }
287} 293}
288 294
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index a421f535d351..2eeac10aa0cf 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -90,13 +90,14 @@ static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
90{ 90{
91 pte_t *pte; 91 pte_t *pte;
92 92
93 if (pmd_none(*pmd) || pmd_bad(*pmd)) { 93 if (pmd_none(*pmd) || pmd_sect(*pmd)) {
94 pte = alloc(PTRS_PER_PTE * sizeof(pte_t)); 94 pte = alloc(PTRS_PER_PTE * sizeof(pte_t));
95 if (pmd_sect(*pmd)) 95 if (pmd_sect(*pmd))
96 split_pmd(pmd, pte); 96 split_pmd(pmd, pte);
97 __pmd_populate(pmd, __pa(pte), PMD_TYPE_TABLE); 97 __pmd_populate(pmd, __pa(pte), PMD_TYPE_TABLE);
98 flush_tlb_all(); 98 flush_tlb_all();
99 } 99 }
100 BUG_ON(pmd_bad(*pmd));
100 101
101 pte = pte_offset_kernel(pmd, addr); 102 pte = pte_offset_kernel(pmd, addr);
102 do { 103 do {
@@ -128,7 +129,7 @@ static void alloc_init_pmd(struct mm_struct *mm, pud_t *pud,
128 /* 129 /*
129 * Check for initial section mappings in the pgd/pud and remove them. 130 * Check for initial section mappings in the pgd/pud and remove them.
130 */ 131 */
131 if (pud_none(*pud) || pud_bad(*pud)) { 132 if (pud_none(*pud) || pud_sect(*pud)) {
132 pmd = alloc(PTRS_PER_PMD * sizeof(pmd_t)); 133 pmd = alloc(PTRS_PER_PMD * sizeof(pmd_t));
133 if (pud_sect(*pud)) { 134 if (pud_sect(*pud)) {
134 /* 135 /*
@@ -140,6 +141,7 @@ static void alloc_init_pmd(struct mm_struct *mm, pud_t *pud,
140 pud_populate(mm, pud, pmd); 141 pud_populate(mm, pud, pmd);
141 flush_tlb_all(); 142 flush_tlb_all();
142 } 143 }
144 BUG_ON(pud_bad(*pud));
143 145
144 pmd = pmd_offset(pud, addr); 146 pmd = pmd_offset(pud, addr);
145 do { 147 do {