Date: Sat, 3 Nov 2012 22:02:13 +0000 (UTC) From: Marcel Moolenaar <marcel@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r242526 - head/sys/powerpc/booke Message-ID: <201211032202.qA3M2Duo053169@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: marcel Date: Sat Nov 3 22:02:12 2012 New Revision: 242526 URL: http://svn.freebsd.org/changeset/base/242526 Log: 1. Have the APs initialize the TLB1 entries from what has been programmed on the BSP during (early) boot. This makes sure that the APs get configured the same as the BSP, irrspective of how FreeBSD was loaded. 2. Make sure to flush the dcache after writing the TLB1 entries to the boot page. The APs aren't part of the coherency domain just yet. 3. Set pmap_bootstrapped after calling pmap_bootstrap(). The FDT code now maps the devices (like OF), and this resulted in a panic. 4. Since we pre-wire the CCSR, make sure not to map chunks of it in pmap_mapdev(). Modified: head/sys/powerpc/booke/locore.S head/sys/powerpc/booke/machdep.c head/sys/powerpc/booke/platform_bare.c head/sys/powerpc/booke/pmap.c Modified: head/sys/powerpc/booke/locore.S ============================================================================== --- head/sys/powerpc/booke/locore.S Sat Nov 3 21:20:55 2012 (r242525) +++ head/sys/powerpc/booke/locore.S Sat Nov 3 22:02:12 2012 (r242526) @@ -126,9 +126,11 @@ __start: bl tlb1_find_current /* the entry found is returned in r29 */ bl tlb1_inval_all_but_current + /* * Create temporary mapping in AS=1 and switch to it */ + addi %r3, %r29, 1 bl tlb1_temp_mapping_as1 mfmsr %r3 @@ -242,19 +244,21 @@ done_mapping: __boot_page: bl 1f - .globl bp_trace -bp_trace: + .globl bp_ntlb1s +bp_ntlb1s: .long 0 - .globl bp_kernload -bp_kernload: - .long 0 + .globl bp_tlb1 +bp_tlb1: + .space 4 * 3 * 16 + + .globl bp_tlb1_end +bp_tlb1_end: /* * Initial configuration */ -1: - mflr %r31 /* r31 hold the address of bp_trace */ +1: mflr %r31 /* r31 hold the address of bp_ntlb1s */ /* Set HIDs */ lis %r3, HID0_E500_DEFAULT_SET@h @@ -283,9 +287,11 @@ bp_kernload: bl tlb1_find_current /* the entry number found is in r29 */ bl tlb1_inval_all_but_current + /* * Create temporary translation in AS=1 and switch to it */ + lwz %r3, 0(%r31) bl tlb1_temp_mapping_as1 mfmsr %r3 @@ -306,44 +312,34 @@ bp_kernload: /* * Setup final mapping in TLB1[1] and switch to it */ - /* Final kernel mapping, map in 16 MB of RAM */ - lis %r3, MAS0_TLBSEL1@h /* Select TLB1 */ - li %r4, 0 /* Entry 0 */ - rlwimi %r3, %r4, 16, 4, 15 + lwz %r6, 0(%r31) + addi %r5, %r31, 4 + li %r4, 0 + +4: lis %r3, MAS0_TLBSEL1@h + rlwimi %r3, %r4, 16, 12, 15 mtspr SPR_MAS0, %r3 isync - - li %r3, (TLB_SIZE_16M << MAS1_TSIZE_SHIFT)@l - oris %r3, %r3, (MAS1_VALID | MAS1_IPROT)@h - mtspr SPR_MAS1, %r3 /* note TS was not filled, so it's TS=0 */ + lwz %r3, 0(%r5) + mtspr SPR_MAS1, %r3 isync - - lis %r3, KERNBASE@h - ori %r3, %r3, KERNBASE@l /* EPN = KERNBASE */ - ori %r3, %r3, MAS2_M@l /* WIMGE = 0b00100 */ + lwz %r3, 4(%r5) mtspr SPR_MAS2, %r3 isync - - /* Retrieve kernel load [physical] address from bp_kernload */ - bl 4f -4: mflr %r3 - rlwinm %r3, %r3, 0, 0, 19 - lis %r4, bp_kernload@h - ori %r4, %r4, bp_kernload@l - lis %r5, __boot_page@h - ori %r5, %r5, __boot_page@l - sub %r4, %r4, %r5 /* offset of bp_kernload within __boot_page */ - lwzx %r3, %r4, %r3 - - /* Set RPN and protection */ - ori %r3, %r3, (MAS3_SX | MAS3_SW | MAS3_SR)@l + lwz %r3, 8(%r5) mtspr SPR_MAS3, %r3 isync tlbwe isync msync + addi %r5, %r5, 12 + addi %r4, %r4, 1 + cmpw %r4, %r6 + blt 4b /* Switch to the final mapping */ + lis %r5, __boot_page@ha + ori %r5, %r5, __boot_page@l bl 5f 5: mflr %r3 rlwinm %r3, %r3, 0, 0xfff /* Offset from boot page start */ @@ -460,11 +456,14 @@ tlb1_inval_entry: blr /* - * r29 current entry number - * r28 returned temp entry - * r3-r5 scratched + * r3 entry of temp translation + * r29 entry of current translation + * r28 returns temp entry passed in r3 + * r4-r5 scratched */ tlb1_temp_mapping_as1: + mr %r28, %r3 + /* Read our current translation */ lis %r3, MAS0_TLBSEL1@h /* Select TLB1 */ rlwimi %r3, %r29, 16, 12, 15 /* Select our current entry */ @@ -472,14 +471,8 @@ tlb1_temp_mapping_as1: isync tlbre - /* - * Prepare and write temp entry - * - * FIXME this is not robust against overflow i.e. when the current - * entry is the last in TLB1 - */ + /* Prepare and write temp entry */ lis %r3, MAS0_TLBSEL1@h /* Select TLB1 */ - addi %r28, %r29, 1 /* Use next entry. */ rlwimi %r3, %r28, 16, 12, 15 /* Select temp entry */ mtspr SPR_MAS0, %r3 isync Modified: head/sys/powerpc/booke/machdep.c ============================================================================== --- head/sys/powerpc/booke/machdep.c Sat Nov 3 21:20:55 2012 (r242525) +++ head/sys/powerpc/booke/machdep.c Sat Nov 3 22:02:12 2012 (r242526) @@ -413,6 +413,7 @@ booke_init(uint32_t arg1, uint32_t arg2) /* Initialise virtual memory. */ pmap_mmu_install(MMU_TYPE_BOOKE, 0); pmap_bootstrap((uintptr_t)kernel_text, end); + pmap_bootstrapped = 1; debugf("MSR = 0x%08x\n", mfmsr()); #if defined(BOOKE_E500) //tlb1_print_entries(); Modified: head/sys/powerpc/booke/platform_bare.c ============================================================================== --- head/sys/powerpc/booke/platform_bare.c Sat Nov 3 21:20:55 2012 (r242525) +++ head/sys/powerpc/booke/platform_bare.c Sat Nov 3 22:02:12 2012 (r242526) @@ -55,9 +55,11 @@ __FBSDID("$FreeBSD$"); #ifdef SMP extern void *ap_pcpu; +extern vm_paddr_t kernload; /* Kernel physical load address */ extern uint8_t __boot_page[]; /* Boot page body */ -extern uint32_t bp_kernload; /* Kernel physical load address */ -extern uint32_t bp_trace; /* AP boot trace field */ +extern uint32_t bp_ntlb1s; +extern uint32_t bp_tlb1[]; +extern uint32_t bp_tlb1_end[]; #endif extern uint32_t *bootinfo; @@ -248,8 +250,9 @@ static int bare_smp_start_cpu(platform_t plat, struct pcpu *pc) { #ifdef SMP + uint32_t *tlb1; uint32_t bptr, eebpcr; - int timeout; + int i, timeout; eebpcr = ccsr_read4(OCP85XX_EEBPCR); if ((eebpcr & (1 << (pc->pc_cpuid + 24))) != 0) { @@ -259,18 +262,37 @@ bare_smp_start_cpu(platform_t plat, stru } ap_pcpu = pc; - __asm __volatile("msync; isync"); + + i = 0; + tlb1 = bp_tlb1; + while (i < bp_ntlb1s && tlb1 < bp_tlb1_end) { + mtspr(SPR_MAS0, MAS0_TLBSEL(1) | MAS0_ESEL(i)); + __asm __volatile("isync; tlbre"); + tlb1[0] = mfspr(SPR_MAS1); + tlb1[1] = mfspr(SPR_MAS2); + tlb1[2] = mfspr(SPR_MAS3); + i++; + tlb1 += 3; + } + if (i < bp_ntlb1s) + bp_ntlb1s = i; /* * Set BPTR to the physical address of the boot page */ - bptr = ((uint32_t)__boot_page - KERNBASE) + bp_kernload; - ccsr_write4(OCP85XX_BPTR, (bptr >> 12) | 0x80000000); + bptr = ((uint32_t)__boot_page - KERNBASE) + kernload; + KASSERT((bptr & 0xfff) == 0, + ("%s: boot page is not aligned (%#x)", __func__, bptr)); + bptr = (bptr >> 12) | 0x80000000u; + ccsr_write4(OCP85XX_BPTR, bptr); + __asm __volatile("isync; msync"); + + /* Flush caches to have our changes hit DRAM. */ + cpu_flush_dcache(__boot_page, 4096); /* * Release AP from hold-off state */ - bp_trace = 0; eebpcr |= (1 << (pc->pc_cpuid + 24)); ccsr_write4(OCP85XX_EEBPCR, eebpcr); __asm __volatile("isync; msync"); @@ -285,10 +307,10 @@ bare_smp_start_cpu(platform_t plat, stru * usable otherwise. */ ccsr_write4(OCP85XX_BPTR, 0); + __asm __volatile("isync; msync"); if (!pc->pc_awake) - printf("SMP: CPU %d didn't wake up (trace code %#x).\n", - pc->pc_awake, bp_trace); + printf("SMP: CPU %d didn't wake up.\n", pc->pc_cpuid); return ((pc->pc_awake) ? 0 : EBUSY); #else /* No SMP support */ Modified: head/sys/powerpc/booke/pmap.c ============================================================================== --- head/sys/powerpc/booke/pmap.c Sat Nov 3 21:20:55 2012 (r242525) +++ head/sys/powerpc/booke/pmap.c Sat Nov 3 22:02:12 2012 (r242526) @@ -111,9 +111,10 @@ extern unsigned char _end[]; extern uint32_t *bootinfo; #ifdef SMP -extern uint32_t bp_kernload; +extern uint32_t bp_ntlb1s; #endif +vm_paddr_t ccsrbar_pa; vm_paddr_t kernload; vm_offset_t kernstart; vm_size_t kernsize; @@ -962,10 +963,6 @@ mmu_booke_bootstrap(mmu_t mmu, vm_offset debugf("mmu_booke_bootstrap: entered\n"); -#ifdef SMP - bp_kernload = kernload; -#endif - /* Initialize invalidation mutex */ mtx_init(&tlbivax_mutex, "tlbivax", NULL, MTX_SPIN); @@ -1279,7 +1276,7 @@ pmap_bootstrap_ap(volatile uint32_t *trc * have the snapshot of its contents in the s/w tlb1[] table, so use * these values directly to (re)program AP's TLB1 hardware. */ - for (i = 0; i < tlb1_idx; i ++) { + for (i = bp_ntlb1s; i < tlb1_idx; i++) { /* Skip invalid entries */ if (!(tlb1[i].mas1 & MAS1_VALID)) continue; @@ -2601,6 +2598,18 @@ mmu_booke_mapdev(mmu_t mmu, vm_paddr_t p uintptr_t va; vm_size_t sz; + /* + * CCSR is premapped. Note that (pa + size - 1) is there to make sure + * we don't wrap around. Devices on the local bus typically extend all + * the way up to and including 0xffffffff. In that case (pa + size) + * would be 0. This creates a false positive (i.e. we think it's + * within the CCSR) and not create a mapping. + */ + if (pa >= ccsrbar_pa && (pa + size - 1) < (ccsrbar_pa + CCSRBAR_SIZE)) { + va = CCSRBAR_VA + (pa - ccsrbar_pa); + return ((void *)va); + } + va = (pa >= 0x80000000) ? pa : (0xe2000000 + pa); res = (void *)va; @@ -3011,6 +3020,8 @@ tlb1_init(vm_offset_t ccsrbar) uint32_t tsz; u_int i; + ccsrbar_pa = ccsrbar; + if (bootinfo != NULL && bootinfo[0] != 1) { tlb1_idx = *((uint16_t *)(bootinfo + 8)); } else @@ -3042,6 +3053,10 @@ tlb1_init(vm_offset_t ccsrbar) /* Map in CCSRBAR. */ tlb1_set_entry(CCSRBAR_VA, ccsrbar, CCSRBAR_SIZE, _TLB_ENTRY_IO); +#ifdef SMP + bp_ntlb1s = tlb1_idx; +#endif + /* Purge the remaining entries */ for (i = tlb1_idx; i < TLB1_ENTRIES; i++) tlb1_write_entry(i);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201211032202.qA3M2Duo053169>