Commit fb5ab0d6 authored by Russell King's avatar Russell King

[ARM] Fix slab corruption issues triggered with pud_t integration.

When the page tables are wrapped from 4 levels to 2 levels, the new
MM code requires PMD_SHIFT to match PUD_SHIFT, which must also
match PGDIR_SHIFT.  If PMD_SHIFT is smaller than PUD_SHIFT, we risk
freeing a still-in-use table (== page) which can then get re-used
for the slab cache.

Testing and inspection shows that there isn't any real benefit from
keeping PMD_SHIFT set to 20.

In addition, add some comments concerning the granularity of
alloc_init_section() and fix a missing PMD assignment in the
rebooting code.  Somehow we managed to get away with that, although
it is actually wrong.  Maybe I've just been lucky until now.
Signed-off-by: default avatarRussell King <rmk@arm.linux.org.uk>
parent 5c4ac43f
...@@ -239,7 +239,8 @@ void free_pgd_slow(pgd_t *pgd) ...@@ -239,7 +239,8 @@ void free_pgd_slow(pgd_t *pgd)
/* /*
* Create a SECTION PGD between VIRT and PHYS in domain * Create a SECTION PGD between VIRT and PHYS in domain
* DOMAIN with protection PROT * DOMAIN with protection PROT. This operates on half-
* pgdir entry increments.
*/ */
static inline void static inline void
alloc_init_section(unsigned long virt, unsigned long phys, int prot) alloc_init_section(unsigned long virt, unsigned long phys, int prot)
...@@ -481,6 +482,9 @@ static void __init create_mapping(struct map_desc *md) ...@@ -481,6 +482,9 @@ static void __init create_mapping(struct map_desc *md)
length -= PAGE_SIZE; length -= PAGE_SIZE;
} }
/*
* A section mapping covers half a "pgdir" entry.
*/
while (length >= (PGDIR_SIZE / 2)) { while (length >= (PGDIR_SIZE / 2)) {
alloc_init_section(virt, virt + off, prot_sect); alloc_init_section(virt, virt + off, prot_sect);
...@@ -522,6 +526,7 @@ void setup_mm_for_reboot(char mode) ...@@ -522,6 +526,7 @@ void setup_mm_for_reboot(char mode)
pmdval |= PMD_BIT4; pmdval |= PMD_BIT4;
pmd = pmd_offset(pgd + i, i << PGDIR_SHIFT); pmd = pmd_offset(pgd + i, i << PGDIR_SHIFT);
set_pmd(pmd, __pmd(pmdval)); set_pmd(pmd, __pmd(pmdval));
set_pmd(pmd + 1, __pmd(pmdval + 1 << (PGDIR_SHIFT - 1)));
} }
} }
......
...@@ -82,7 +82,7 @@ ...@@ -82,7 +82,7 @@
* PMD_SHIFT determines the size of the area a second-level page table can map * PMD_SHIFT determines the size of the area a second-level page table can map
* PGDIR_SHIFT determines what a third-level page table entry can map * PGDIR_SHIFT determines what a third-level page table entry can map
*/ */
#define PMD_SHIFT 20 #define PMD_SHIFT 21
#define PGDIR_SHIFT 21 #define PGDIR_SHIFT 21
#define LIBRARY_TEXT_START 0x0c000000 #define LIBRARY_TEXT_START 0x0c000000
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment