ppc32: Fix initialisation of the POWER4 / G5 MMU Hash table

especially related to the use of the btext early debug text
engine
parent 0c22001d
...@@ -291,6 +291,8 @@ void __init MMU_init(void) ...@@ -291,6 +291,8 @@ void __init MMU_init(void)
ppc_md.progress("MMU:exit", 0x211); ppc_md.progress("MMU:exit", 0x211);
#ifdef CONFIG_BOOTX_TEXT #ifdef CONFIG_BOOTX_TEXT
/* By default, we are no longer mapped */
boot_text_mapped = 0;
/* Must be done last, or ppc_md.progress will die. */ /* Must be done last, or ppc_md.progress will die. */
map_boot_text(); map_boot_text();
#endif #endif
......
...@@ -260,6 +260,74 @@ prom_next_node(phandle *nodep) ...@@ -260,6 +260,74 @@ prom_next_node(phandle *nodep)
} }
} }
#ifdef CONFIG_POWER4
/*
* Set up a hash table with a set of entries in it to map the
* first 64MB of RAM. This is used on 64-bit machines since
* some of them don't have BATs.
*/
static inline void make_pte(unsigned long htab, unsigned int hsize,
unsigned int va, unsigned int pa, int mode)
{
unsigned int *pteg;
unsigned int hash, i, vsid;
vsid = ((va >> 28) * 0x111) << 12;
hash = ((va ^ vsid) >> 5) & 0x7fff80;
pteg = (unsigned int *)(htab + (hash & (hsize - 1)));
for (i = 0; i < 8; ++i, pteg += 4) {
if ((pteg[1] & 1) == 0) {
pteg[1] = vsid | ((va >> 16) & 0xf80) | 1;
pteg[3] = pa | mode;
break;
}
}
}
extern unsigned long _SDR1;
extern PTE *Hash;
extern unsigned long Hash_size;
static void __init
prom_alloc_htab(void)
{
unsigned int hsize;
unsigned long htab;
unsigned int addr;
/*
* Because of OF bugs we can't use the "claim" client
* interface to allocate memory for the hash table.
* This code is only used on 64-bit PPCs, and the only
* 64-bit PPCs at the moment are RS/6000s, and their
* OF is based at 0xc00000 (the 12M point), so we just
* arbitrarily use the 0x800000 - 0xc00000 region for the
* hash table.
* -- paulus.
*/
hsize = 4 << 20; /* POWER4 has no BATs */
htab = (8 << 20);
call_prom("claim", 3, 1, htab, hsize, 0);
Hash = (void *)(htab + KERNELBASE);
Hash_size = hsize;
_SDR1 = htab + __ilog2(hsize) - 18;
/*
* Put in PTEs for the first 64MB of RAM
*/
memset((void *)htab, 0, hsize);
for (addr = 0; addr < 0x4000000; addr += 0x1000)
make_pte(htab, hsize, addr + KERNELBASE, addr,
_PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX);
#if 0 /* DEBUG stuff mapping the SCC */
make_pte(htab, hsize, 0x80013000, 0x80013000,
_PAGE_ACCESSED | _PAGE_NO_CACHE | _PAGE_GUARDED | PP_RWXX);
#endif
}
#endif /* CONFIG_POWER4 */
/* /*
* If we have a display that we don't know how to drive, * If we have a display that we don't know how to drive,
* we will want to try to execute OF's open method for it * we will want to try to execute OF's open method for it
...@@ -434,13 +502,30 @@ setup_disp_fake_bi(ihandle dp) ...@@ -434,13 +502,30 @@ setup_disp_fake_bi(ihandle dp)
address += 0x1000; address += 0x1000;
#ifdef CONFIG_POWER4 #ifdef CONFIG_POWER4
extern int boot_text_mapped; #if CONFIG_TASK_SIZE > 0x80000000
btext_setup_display(width, height, depth, pitch, address); #error CONFIG_TASK_SIZE cannot be above 0x80000000 with BOOTX_TEXT on G5
boot_text_mapped = 0; #endif
#else {
extern boot_infos_t disp_bi;
unsigned long va, pa, i, offset;
va = 0x90000000;
pa = address & 0xfffff000ul;
offset = address & 0x00000fff;
for (i=0; i<0x4000; i++) {
make_pte((unsigned long)Hash - KERNELBASE, Hash_size, va, pa,
_PAGE_ACCESSED | _PAGE_NO_CACHE |
_PAGE_GUARDED | PP_RWXX);
va += 0x1000;
pa += 0x1000;
}
btext_setup_display(width, height, depth, pitch, 0x90000000 | offset);
disp_bi.dispDeviceBase = (u8 *)address;
}
#else /* CONFIG_POWER4 */
btext_setup_display(width, height, depth, pitch, address); btext_setup_display(width, height, depth, pitch, address);
btext_prepare_BAT(); btext_prepare_BAT();
#endif #endif /* CONFIG_POWER4 */
#endif /* CONFIG_BOOTX_TEXT */ #endif /* CONFIG_BOOTX_TEXT */
} }
...@@ -648,72 +733,6 @@ prom_hold_cpus(unsigned long mem) ...@@ -648,72 +733,6 @@ prom_hold_cpus(unsigned long mem)
} }
} }
#ifdef CONFIG_POWER4
/*
* Set up a hash table with a set of entries in it to map the
* first 64MB of RAM. This is used on 64-bit machines since
* some of them don't have BATs.
* We assume the PTE will fit in the primary PTEG.
*/
static inline void make_pte(unsigned long htab, unsigned int hsize,
unsigned int va, unsigned int pa, int mode)
{
unsigned int *pteg;
unsigned int hash, i, vsid;
vsid = ((va >> 28) * 0x111) << 12;
hash = ((va ^ vsid) >> 5) & 0x7fff80;
pteg = (unsigned int *)(htab + (hash & (hsize - 1)));
for (i = 0; i < 8; ++i, pteg += 4) {
if ((pteg[1] & 1) == 0) {
pteg[1] = vsid | ((va >> 16) & 0xf80) | 1;
pteg[3] = pa | mode;
break;
}
}
}
extern unsigned long _SDR1;
extern PTE *Hash;
extern unsigned long Hash_size;
static void __init
prom_alloc_htab(void)
{
unsigned int hsize;
unsigned long htab;
unsigned int addr;
/*
* Because of OF bugs we can't use the "claim" client
* interface to allocate memory for the hash table.
* This code is only used on 64-bit PPCs, and the only
* 64-bit PPCs at the moment are RS/6000s, and their
* OF is based at 0xc00000 (the 12M point), so we just
* arbitrarily use the 0x800000 - 0xc00000 region for the
* hash table.
* -- paulus.
*/
hsize = 4 << 20; /* POWER4 has no BATs */
htab = (8 << 20);
call_prom("claim", 3, 1, htab, hsize, 0);
Hash = (void *)(htab + KERNELBASE);
Hash_size = hsize;
_SDR1 = htab + __ilog2(hsize) - 18;
/*
* Put in PTEs for the first 64MB of RAM
*/
cacheable_memzero((void *)htab, hsize);
for (addr = 0; addr < 0x4000000; addr += 0x1000)
make_pte(htab, hsize, addr + KERNELBASE, addr,
_PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX);
make_pte(htab, hsize, 0x80013000, 0x80013000,
_PAGE_ACCESSED | _PAGE_NO_CACHE | _PAGE_GUARDED | PP_RWXX);
}
#endif /* CONFIG_POWER4 */
static void __init static void __init
prom_instantiate_rtas(void) prom_instantiate_rtas(void)
{ {
...@@ -836,9 +855,10 @@ prom_init(int r3, int r4, prom_entry pp) ...@@ -836,9 +855,10 @@ prom_init(int r3, int r4, prom_entry pp)
* loaded by an OF bootloader which did set a BAT for us. * loaded by an OF bootloader which did set a BAT for us.
* This breaks OF translate so we force phys to be 0. * This breaks OF translate so we force phys to be 0.
*/ */
if (offset == 0) if (offset == 0) {
prom_print("(already at 0xc0000000) phys=0\n");
phys = 0; phys = 0;
else if ((int) call_prom("getprop", 4, 1, prom_chosen, "mmu", } else if ((int) call_prom("getprop", 4, 1, prom_chosen, "mmu",
&prom_mmu, sizeof(prom_mmu)) <= 0) { &prom_mmu, sizeof(prom_mmu)) <= 0) {
prom_print(" no MMU found\n"); prom_print(" no MMU found\n");
} else if ((int)call_prom_ret("call-method", 4, 4, result, "translate", } else if ((int)call_prom_ret("call-method", 4, 4, result, "translate",
......
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