powerpc/mm/32s: rework mmu_mapin_ram()

This patch reworks mmu_mapin_ram() to be more generic and map as much
blocks as possible. It now supports blocks not starting at address 0.

It scans DBATs array to find free ones instead of forcing the use of
BAT2 and BAT3.

Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
Christophe Leroy 2019-02-21 19:08:39 +00:00 committed by Michael Ellerman
parent 14e609d693
commit e4d6654ebe
1 changed files with 41 additions and 22 deletions

View File

@ -73,39 +73,58 @@ unsigned long p_block_mapped(phys_addr_t pa)
return 0;
}
static int find_free_bat(void)
{
int b;
if (cpu_has_feature(CPU_FTR_601)) {
for (b = 0; b < 4; b++) {
struct ppc_bat *bat = BATS[b];
if (!(bat[0].batl & 0x40))
return b;
}
} else {
int n = mmu_has_feature(MMU_FTR_USE_HIGH_BATS) ? 8 : 4;
for (b = 0; b < n; b++) {
struct ppc_bat *bat = BATS[b];
if (!(bat[1].batu & 3))
return b;
}
}
return -1;
}
static unsigned int block_size(unsigned long base, unsigned long top)
{
unsigned int max_size = (cpu_has_feature(CPU_FTR_601) ? 8 : 256) << 20;
unsigned int base_shift = (fls(base) - 1) & 31;
unsigned int block_shift = (fls(top - base) - 1) & 31;
return min3(max_size, 1U << base_shift, 1U << block_shift);
}
unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
{
unsigned long tot, bl, done;
unsigned long max_size = (256<<20);
int idx;
if (__map_without_bats) {
printk(KERN_DEBUG "RAM mapped without BATs\n");
return 0;
return base;
}
/* Set up BAT2 and if necessary BAT3 to cover RAM. */
while ((idx = find_free_bat()) != -1 && base != top) {
unsigned int size = block_size(base, top);
/* Make sure we don't map a block larger than the
smallest alignment of the physical address. */
tot = top;
for (bl = 128<<10; bl < max_size; bl <<= 1) {
if (bl * 2 > tot)
if (size < 128 << 10)
break;
setbat(idx, PAGE_OFFSET + base, base, size, PAGE_KERNEL_X);
base += size;
}
setbat(2, PAGE_OFFSET, 0, bl, PAGE_KERNEL_X);
done = (unsigned long)bat_addrs[2].limit - PAGE_OFFSET + 1;
if ((done < tot) && !bat_addrs[3].limit) {
/* use BAT3 to cover a bit more */
tot -= done;
for (bl = 128<<10; bl < max_size; bl <<= 1)
if (bl * 2 > tot)
break;
setbat(3, PAGE_OFFSET+done, done, bl, PAGE_KERNEL_X);
done = (unsigned long)bat_addrs[3].limit - PAGE_OFFSET + 1;
}
return done;
return base;
}
/*