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

powerpc/32s: Allocate one 256k IBAT instead of two consecutives 128k IBATs

Today we have the following IBATs allocated:

---[ Instruction Block Address Translation ]---
0: 0xc0000000-0xc03fffff 0x00000000 4M Kernel x m
1: 0xc0400000-0xc05fffff 0x00400000 2M Kernel x m
2: 0xc0600000-0xc06fffff 0x00600000 1M Kernel x m
3: 0xc0700000-0xc077ffff 0x00700000 512K Kernel x m
4: 0xc0780000-0xc079ffff 0x00780000 128K Kernel x m
5: 0xc07a0000-0xc07bffff 0x007a0000 128K Kernel x m
6: -
7: -

The two 128K should be a single 256K instead.

When _etext is not aligned to 128Kbytes, the system will allocate
all necessary BATs to the lower 128Kbytes boundary, then allocate
an additional 128Kbytes BAT for the remaining block.

Instead, align the top to 128Kbytes so that the function directly
allocates a 256Kbytes last block:

---[ Instruction Block Address Translation ]---
0: 0xc0000000-0xc03fffff 0x00000000 4M Kernel x m
1: 0xc0400000-0xc05fffff 0x00400000 2M Kernel x m
2: 0xc0600000-0xc06fffff 0x00600000 1M Kernel x m
3: 0xc0700000-0xc077ffff 0x00700000 512K Kernel x m
4: 0xc0780000-0xc07bffff 0x00780000 256K Kernel x m
5: -
6: -
7: -

Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/ab58b296832b0ec650e2203200e060adbcb2677d.1637930421.git.christophe.leroy@csgroup.eu

authored by

Christophe Leroy and committed by
Michael Ellerman
37eb7ca9 dede19be

+2 -3
+2 -3
arch/powerpc/mm/book3s32/mmu.c
··· 196 196 int nb = mmu_has_feature(MMU_FTR_USE_HIGH_BATS) ? 8 : 4; 197 197 int i; 198 198 unsigned long base = (unsigned long)_stext - PAGE_OFFSET; 199 - unsigned long top = (unsigned long)_etext - PAGE_OFFSET; 199 + unsigned long top = ALIGN((unsigned long)_etext - PAGE_OFFSET, SZ_128K); 200 200 unsigned long border = (unsigned long)__init_begin - PAGE_OFFSET; 201 201 unsigned long size; 202 202 203 - for (i = 0; i < nb - 1 && base < top && top - base > (128 << 10);) { 203 + for (i = 0; i < nb - 1 && base < top;) { 204 204 size = block_size(base, top); 205 205 setibat(i++, PAGE_OFFSET + base, base, size, PAGE_KERNEL_TEXT); 206 206 base += size; 207 207 } 208 208 if (base < top) { 209 209 size = block_size(base, top); 210 - size = max(size, 128UL << 10); 211 210 if ((top - base) > size) { 212 211 size <<= 1; 213 212 if (strict_kernel_rwx_enabled() && base + size > border)