diff options
author | marcel <marcel@FreeBSD.org> | 2008-09-16 17:22:16 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2008-09-16 17:22:16 +0000 |
commit | c30442519135193341da3ed7a651eb15bcea26b8 (patch) | |
tree | 33a29b8ea047141e6fbf030a73562a25ccf21b1f /sys/powerpc | |
parent | 79892756cd617d3c35e4bb2a2d5d346cbec9efe4 (diff) | |
download | FreeBSD-src-c30442519135193341da3ed7a651eb15bcea26b8.zip FreeBSD-src-c30442519135193341da3ed7a651eb15bcea26b8.tar.gz |
Rewrite cpudep_ap_bootstrap(). We now enable L3, L2, L1D and L1I
caches if not yet enabed. This is required for coherency and
atomic operations to work, not to mention performance. We use the
L2 and L3 cache settings of the BSP to configure the APs caches.
Can't be bad.
Program NAP and not DOZE. DOZE is present only on earlier CPUs
and the bit is reserved on the MPC7441 & MPC7451. NAP will do
bus snooping to keep caches coherent.
Program the PIR with the cpuid. This may not be necessary...
Diffstat (limited to 'sys/powerpc')
-rw-r--r-- | sys/powerpc/aim/mp_cpudep.c | 124 |
1 files changed, 110 insertions, 14 deletions
diff --git a/sys/powerpc/aim/mp_cpudep.c b/sys/powerpc/aim/mp_cpudep.c index 585186a..cfdb53d 100644 --- a/sys/powerpc/aim/mp_cpudep.c +++ b/sys/powerpc/aim/mp_cpudep.c @@ -50,6 +50,8 @@ __FBSDID("$FreeBSD$"); #include <machine/ofw_machdep.h> extern void *rstcode; +extern register_t l2cr_config; +extern register_t l3cr_config; void *ap_pcpu; @@ -138,29 +140,123 @@ powerpc_smp_get_bsp(struct cpuref *cpuref) return (powerpc_smp_fill_cpuref(cpuref, bsp)); } +static register_t +l2_enable(void) +{ + register_t ccr; + + ccr = mfspr(SPR_L2CR); + if (ccr & L2CR_L2E) + return (ccr); + + /* Configure L2 cache. */ + ccr = l2cr_config & ~L2CR_L2E; + mtspr(SPR_L2CR, ccr | L2CR_L2I); + do { + ccr = mfspr(SPR_L2CR); + } while (ccr & L2CR_L2I); + powerpc_sync(); + mtspr(SPR_L2CR, l2cr_config); + powerpc_sync(); + + return (l2cr_config); +} + +static register_t +l3_enable(void) +{ + register_t ccr; + + ccr = mfspr(SPR_L3CR); + if (ccr & L3CR_L3E) + return (ccr); + + /* Configure L3 cache. */ + ccr = l3cr_config & ~(L3CR_L3E | L3CR_L3I | L3CR_L3PE | L3CR_L3CLKEN); + mtspr(SPR_L3CR, ccr); + ccr |= 0x4000000; /* Magic, but documented. */ + mtspr(SPR_L3CR, ccr); + ccr |= L3CR_L3CLKEN; + mtspr(SPR_L3CR, ccr); + mtspr(SPR_L3CR, ccr | L3CR_L3I); + while (mfspr(SPR_L3CR) & L3CR_L3I) + ; + mtspr(SPR_L3CR, ccr & ~L3CR_L3CLKEN); + powerpc_sync(); + DELAY(100); + mtspr(SPR_L3CR, ccr); + powerpc_sync(); + DELAY(100); + ccr |= L3CR_L3E; + mtspr(SPR_L3CR, ccr); + powerpc_sync(); + + return(ccr); +} + +static register_t +l1d_enable(void) +{ + register_t hid; + + hid = mfspr(SPR_HID0); + if (hid & HID0_DCE) + return (hid); + + /* Enable L1 D-cache */ + hid |= HID0_DCE; + powerpc_sync(); + mtspr(SPR_HID0, hid | HID0_DCFI); + powerpc_sync(); + + return (hid); +} + +static register_t +l1i_enable(void) +{ + register_t hid; + + hid = mfspr(SPR_HID0); + if (hid & HID0_ICE) + return (hid); + + /* Enable L1 I-cache */ + hid |= HID0_ICE; + isync(); + mtspr(SPR_HID0, hid | HID0_ICFI); + isync(); + + return (hid); +} + uint32_t cpudep_ap_bootstrap(void) { - uint32_t hid, msr, sp; + uint32_t hid, msr, reg, sp; + + // reg = mfspr(SPR_MSSCR0); + // mtspr(SPR_MSSCR0, reg | 0x3); __asm __volatile("mtsprg 0, %0" :: "r"(ap_pcpu)); - __asm __volatile("sync"); + powerpc_sync(); - hid = mfspr(SPR_HID0); - hid &= ~(HID0_ICE | HID0_DCE); - hid &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); - mtspr(SPR_HID0, hid); - isync(); + __asm __volatile("mtspr 1023,%0" :: "r"(PCPU_GET(cpuid))); + __asm __volatile("mfspr %0,1023" : "=r"(pcpup->pc_pir)); - hid |= HID0_ICFI | HID0_DCFI; - hid |= HID0_ICE | HID0_DCE; - mtspr(SPR_HID0, hid); + msr = PSL_FP | PSL_IR | PSL_DR | PSL_ME | PSL_RI; + powerpc_sync(); isync(); - - msr = PSL_IR | PSL_DR | PSL_ME | PSL_RI; mtmsr(msr); isync(); + reg = l3_enable(); + reg = l2_enable(); + reg = l1d_enable(); + reg = l1i_enable(); + + hid = mfspr(SPR_HID0); + hid &= ~(HID0_DOZE | HID0_SLEEP); hid |= HID0_NAP | HID0_DPM; mtspr(SPR_HID0, hid); isync(); @@ -189,10 +285,10 @@ powerpc_smp_start_cpu(struct pcpu *pc) rstvec = (uint8_t *)(0x80000000 + reset); *rstvec = 4; - __asm __volatile("sync"); + powerpc_sync(); DELAY(1); *rstvec = 0; - __asm __volatile("sync"); + powerpc_sync(); timeout = 1000; while (!pc->pc_awake && timeout--) |