Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Mark Rutland and committed by
Catalin Marinas
a1c76574 a3bba370

+16 -8
+12 -6
arch/arm64/mm/dump.c
··· 249 249 250 250 for (i = 0; i < PTRS_PER_PMD; i++, pmd++) { 251 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 253 note_page(st, addr, 3, pmd_val(*pmd)); 254 - else 254 + } else { 255 + BUG_ON(pmd_bad(*pmd)); 255 256 walk_pte(st, pmd, addr); 257 + } 256 258 } 257 259 } 258 260 ··· 266 264 267 265 for (i = 0; i < PTRS_PER_PUD; i++, pud++) { 268 266 addr = start + i * PUD_SIZE; 269 - if (pud_none(*pud) || pud_sect(*pud) || pud_bad(*pud)) 267 + if (pud_none(*pud) || pud_sect(*pud)) { 270 268 note_page(st, addr, 2, pud_val(*pud)); 271 - else 269 + } else { 270 + BUG_ON(pud_bad(*pud)); 272 271 walk_pmd(st, pud, addr); 272 + } 273 273 } 274 274 } 275 275 ··· 283 279 284 280 for (i = 0; i < PTRS_PER_PGD; i++, pgd++) { 285 281 addr = start + i * PGDIR_SIZE; 286 - if (pgd_none(*pgd) || pgd_bad(*pgd)) 282 + if (pgd_none(*pgd)) { 287 283 note_page(st, addr, 1, pgd_val(*pgd)); 288 - else 284 + } else { 285 + BUG_ON(pgd_bad(*pgd)); 289 286 walk_pud(st, pgd, addr); 287 + } 290 288 } 291 289 } 292 290
+4 -2
arch/arm64/mm/mmu.c
··· 90 90 { 91 91 pte_t *pte; 92 92 93 - if (pmd_none(*pmd) || pmd_bad(*pmd)) { 93 + if (pmd_none(*pmd) || pmd_sect(*pmd)) { 94 94 pte = alloc(PTRS_PER_PTE * sizeof(pte_t)); 95 95 if (pmd_sect(*pmd)) 96 96 split_pmd(pmd, pte); 97 97 __pmd_populate(pmd, __pa(pte), PMD_TYPE_TABLE); 98 98 flush_tlb_all(); 99 99 } 100 + BUG_ON(pmd_bad(*pmd)); 100 101 101 102 pte = pte_offset_kernel(pmd, addr); 102 103 do { ··· 129 128 /* 130 129 * Check for initial section mappings in the pgd/pud and remove them. 131 130 */ 132 - if (pud_none(*pud) || pud_bad(*pud)) { 131 + if (pud_none(*pud) || pud_sect(*pud)) { 133 132 pmd = alloc(PTRS_PER_PMD * sizeof(pmd_t)); 134 133 if (pud_sect(*pud)) { 135 134 /* ··· 141 140 pud_populate(mm, pud, pmd); 142 141 flush_tlb_all(); 143 142 } 143 + BUG_ON(pud_bad(*pud)); 144 144 145 145 pmd = pmd_offset(pud, addr); 146 146 do {