diff options
author | Stafford Horne <shorne@gmail.com> | 2017-06-24 07:09:59 +0900 |
---|---|---|
committer | Stafford Horne <shorne@gmail.com> | 2017-11-03 14:01:14 +0900 |
commit | c056718464512da06d7f65a27d5e4f1707b24c80 (patch) | |
tree | 3b3b3076d876428ae8b81826f7171f22e84009a5 /arch/openrisc/kernel/head.S | |
parent | b441aab7aa0e15955c432736b08a218a6a4c77f0 (diff) | |
download | linux-c056718464512da06d7f65a27d5e4f1707b24c80.tar.bz2 |
openrisc: sleep instead of spin on secondary wait
Currently we do a spin on secondary cpus when waiting to boot. This
theoretically causes issues with power consumption and does cause issues
with qemu cycle burning (it starves cpu 0 from actually being able to
boot.)
This change puts each secondary cpu to sleep if they have a power
management unit, then signals them to wake via IPI when its time to boot.
If the cpus have no power management unit they will loop as before.
Note: The wakeup IPI requires a special interrupt handler as on secondary
cpu's the interrupt infrastructure is not yet established. This
interrupt handler is set and reset by updating SPR_EVBAR.
Signed-off-by: Stafford Horne <shorne@gmail.com>
Diffstat (limited to 'arch/openrisc/kernel/head.S')
-rw-r--r-- | arch/openrisc/kernel/head.S | 51 |
1 files changed, 49 insertions, 2 deletions
diff --git a/arch/openrisc/kernel/head.S b/arch/openrisc/kernel/head.S index a9972dc103f8..fb02b2a1d6f2 100644 --- a/arch/openrisc/kernel/head.S +++ b/arch/openrisc/kernel/head.S @@ -712,9 +712,45 @@ _flush_tlb: #ifdef CONFIG_SMP secondary_wait: + /* Doze the cpu until we are asked to run */ + /* If we dont have power management skip doze */ + l.mfspr r25,r0,SPR_UPR + l.andi r25,r25,SPR_UPR_PMP + l.sfeq r25,r0 + l.bf secondary_check_release + l.nop + + /* Setup special secondary exception handler */ + LOAD_SYMBOL_2_GPR(r3, _secondary_evbar) + tophys(r25,r3) + l.mtspr r0,r25,SPR_EVBAR + + /* Enable Interrupts */ + l.mfspr r25,r0,SPR_SR + l.ori r25,r25,SPR_SR_IEE + l.mtspr r0,r25,SPR_SR + + /* Unmask interrupts interrupts */ + l.mfspr r25,r0,SPR_PICMR + l.ori r25,r25,0xffff + l.mtspr r0,r25,SPR_PICMR + + /* Doze */ + l.mfspr r25,r0,SPR_PMR + LOAD_SYMBOL_2_GPR(r3, SPR_PMR_DME) + l.or r25,r25,r3 + l.mtspr r0,r25,SPR_PMR + + /* Wakeup - Restore exception handler */ + l.mtspr r0,r0,SPR_EVBAR + +secondary_check_release: + /* + * Check if we actually got the release signal, if not go-back to + * sleep. + */ l.mfspr r25,r0,SPR_COREID - l.movhi r3,hi(secondary_release) - l.ori r3,r3,lo(secondary_release) + LOAD_SYMBOL_2_GPR(r3, secondary_release) tophys(r4, r3) l.lwz r3,0(r4) l.sfeq r25,r3 @@ -1663,6 +1699,17 @@ ENTRY(_early_uart_init) l.jr r9 l.nop + .align 0x1000 + .global _secondary_evbar +_secondary_evbar: + + .space 0x800 + /* Just disable interrupts and Return */ + l.ori r3,r0,SPR_SR_SM + l.mtspr r0,r3,SPR_ESR_BASE + l.rfe + + .section .rodata _string_unhandled_exception: .string "\n\rRunarunaround: Unhandled exception 0x\0" |