From 9404124b117cec0242d65af0a8baabfe9a29e5ed Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 6 Feb 2004 14:12:02 +1100 Subject: [PATCH] ppc32: Fix initialisation of the POWER4 / G5 MMU Hash table especially related to the use of the btext early debug text engine --- arch/ppc/mm/init.c | 2 + arch/ppc/syslib/prom_init.c | 166 ++++++++++++++++++++---------------- 2 files changed, 95 insertions(+), 73 deletions(-) diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c index e65213ea0b6ec..b61a61ceea40a 100644 --- a/arch/ppc/mm/init.c +++ b/arch/ppc/mm/init.c @@ -291,6 +291,8 @@ void __init MMU_init(void) ppc_md.progress("MMU:exit", 0x211); #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. */ map_boot_text(); #endif diff --git a/arch/ppc/syslib/prom_init.c b/arch/ppc/syslib/prom_init.c index b49620cd6346d..e114c595b1490 100644 --- a/arch/ppc/syslib/prom_init.c +++ b/arch/ppc/syslib/prom_init.c @@ -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, * we will want to try to execute OF's open method for it @@ -434,13 +502,30 @@ setup_disp_fake_bi(ihandle dp) address += 0x1000; #ifdef CONFIG_POWER4 - extern int boot_text_mapped; - btext_setup_display(width, height, depth, pitch, address); - boot_text_mapped = 0; -#else +#if CONFIG_TASK_SIZE > 0x80000000 +#error CONFIG_TASK_SIZE cannot be above 0x80000000 with BOOTX_TEXT on G5 +#endif + { + 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_prepare_BAT(); -#endif +#endif /* CONFIG_POWER4 */ #endif /* CONFIG_BOOTX_TEXT */ } @@ -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 prom_instantiate_rtas(void) { @@ -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. * 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; - 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_print(" no MMU found\n"); } else if ((int)call_prom_ret("call-method", 4, 4, result, "translate", -- 2.53.0