Commit e4d6654e authored by Christophe Leroy's avatar Christophe Leroy Committed by Michael Ellerman

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: default avatarChristophe Leroy <christophe.leroy@c-s.fr>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 14e609d6
...@@ -73,39 +73,58 @@ unsigned long p_block_mapped(phys_addr_t pa) ...@@ -73,39 +73,58 @@ unsigned long p_block_mapped(phys_addr_t pa)
return 0; 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 __init mmu_mapin_ram(unsigned long base, unsigned long top)
{ {
unsigned long tot, bl, done; int idx;
unsigned long max_size = (256<<20);
if (__map_without_bats) { if (__map_without_bats) {
printk(KERN_DEBUG "RAM mapped without BATs\n"); 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 if (size < 128 << 10)
smallest alignment of the physical address. */
tot = top;
for (bl = 128<<10; bl < max_size; bl <<= 1) {
if (bl * 2 > tot)
break; break;
setbat(idx, PAGE_OFFSET + base, base, size, PAGE_KERNEL_X);
base += size;
} }
setbat(2, PAGE_OFFSET, 0, bl, PAGE_KERNEL_X); return base;
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;
} }
/* /*
......
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