summaryrefslogtreecommitdiffstats
path: root/sys/powerpc/booke/platform_bare.c
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2012-11-03 22:02:12 +0000
committermarcel <marcel@FreeBSD.org>2012-11-03 22:02:12 +0000
commit35b3593ff24bff29174560ecf0052522ba298d96 (patch)
tree05f3b3c36172a5e5f25a6d4e3c6e41fc8b4baa4a /sys/powerpc/booke/platform_bare.c
parent85823a3b2e747b0343cd12c3f6750c0f809cff56 (diff)
downloadFreeBSD-src-35b3593ff24bff29174560ecf0052522ba298d96.zip
FreeBSD-src-35b3593ff24bff29174560ecf0052522ba298d96.tar.gz
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().
Diffstat (limited to 'sys/powerpc/booke/platform_bare.c')
-rw-r--r--sys/powerpc/booke/platform_bare.c40
1 files changed, 31 insertions, 9 deletions
diff --git a/sys/powerpc/booke/platform_bare.c b/sys/powerpc/booke/platform_bare.c
index ebc5e11..c5739f7 100644
--- a/sys/powerpc/booke/platform_bare.c
+++ b/sys/powerpc/booke/platform_bare.c
@@ -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, struct pcpu *pc)
}
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, struct pcpu *pc)
* 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 */
OpenPOWER on IntegriCloud