aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStafford Horne <shorne@gmail.com>2017-06-23 18:09:59 -0400
committerStafford Horne <shorne@gmail.com>2017-11-03 01:01:14 -0400
commitc056718464512da06d7f65a27d5e4f1707b24c80 (patch)
tree3b3b3076d876428ae8b81826f7171f22e84009a5
parentb441aab7aa0e15955c432736b08a218a6a4c77f0 (diff)
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>
-rw-r--r--arch/openrisc/kernel/head.S51
-rw-r--r--arch/openrisc/kernel/smp.c5
2 files changed, 54 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:
712 712
713#ifdef CONFIG_SMP 713#ifdef CONFIG_SMP
714secondary_wait: 714secondary_wait:
715 /* Doze the cpu until we are asked to run */
716 /* If we dont have power management skip doze */
717 l.mfspr r25,r0,SPR_UPR
718 l.andi r25,r25,SPR_UPR_PMP
719 l.sfeq r25,r0
720 l.bf secondary_check_release
721 l.nop
722
723 /* Setup special secondary exception handler */
724 LOAD_SYMBOL_2_GPR(r3, _secondary_evbar)
725 tophys(r25,r3)
726 l.mtspr r0,r25,SPR_EVBAR
727
728 /* Enable Interrupts */
729 l.mfspr r25,r0,SPR_SR
730 l.ori r25,r25,SPR_SR_IEE
731 l.mtspr r0,r25,SPR_SR
732
733 /* Unmask interrupts interrupts */
734 l.mfspr r25,r0,SPR_PICMR
735 l.ori r25,r25,0xffff
736 l.mtspr r0,r25,SPR_PICMR
737
738 /* Doze */
739 l.mfspr r25,r0,SPR_PMR
740 LOAD_SYMBOL_2_GPR(r3, SPR_PMR_DME)
741 l.or r25,r25,r3
742 l.mtspr r0,r25,SPR_PMR
743
744 /* Wakeup - Restore exception handler */
745 l.mtspr r0,r0,SPR_EVBAR
746
747secondary_check_release:
748 /*
749 * Check if we actually got the release signal, if not go-back to
750 * sleep.
751 */
715 l.mfspr r25,r0,SPR_COREID 752 l.mfspr r25,r0,SPR_COREID
716 l.movhi r3,hi(secondary_release) 753 LOAD_SYMBOL_2_GPR(r3, secondary_release)
717 l.ori r3,r3,lo(secondary_release)
718 tophys(r4, r3) 754 tophys(r4, r3)
719 l.lwz r3,0(r4) 755 l.lwz r3,0(r4)
720 l.sfeq r25,r3 756 l.sfeq r25,r3
@@ -1663,6 +1699,17 @@ ENTRY(_early_uart_init)
1663 l.jr r9 1699 l.jr r9
1664 l.nop 1700 l.nop
1665 1701
1702 .align 0x1000
1703 .global _secondary_evbar
1704_secondary_evbar:
1705
1706 .space 0x800
1707 /* Just disable interrupts and Return */
1708 l.ori r3,r0,SPR_SR_SM
1709 l.mtspr r0,r3,SPR_ESR_BASE
1710 l.rfe
1711
1712
1666 .section .rodata 1713 .section .rodata
1667_string_unhandled_exception: 1714_string_unhandled_exception:
1668 .string "\n\rRunarunaround: Unhandled exception 0x\0" 1715 .string "\n\rRunarunaround: Unhandled exception 0x\0"
diff --git a/arch/openrisc/kernel/smp.c b/arch/openrisc/kernel/smp.c
index 154c94a0cfbc..685b4934fa39 100644
--- a/arch/openrisc/kernel/smp.c
+++ b/arch/openrisc/kernel/smp.c
@@ -26,6 +26,7 @@ unsigned long secondary_release = -1;
26struct thread_info *secondary_thread_info; 26struct thread_info *secondary_thread_info;
27 27
28enum ipi_msg_type { 28enum ipi_msg_type {
29 IPI_WAKEUP,
29 IPI_RESCHEDULE, 30 IPI_RESCHEDULE,
30 IPI_CALL_FUNC, 31 IPI_CALL_FUNC,
31 IPI_CALL_FUNC_SINGLE, 32 IPI_CALL_FUNC_SINGLE,
@@ -42,6 +43,7 @@ static void boot_secondary(unsigned int cpu, struct task_struct *idle)
42 spin_lock(&boot_lock); 43 spin_lock(&boot_lock);
43 44
44 secondary_release = cpu; 45 secondary_release = cpu;
46 smp_cross_call(cpumask_of(cpu), IPI_WAKEUP);
45 47
46 /* 48 /*
47 * now the secondary core is starting up let it run its 49 * now the secondary core is starting up let it run its
@@ -140,6 +142,9 @@ void handle_IPI(unsigned int ipi_msg)
140 unsigned int cpu = smp_processor_id(); 142 unsigned int cpu = smp_processor_id();
141 143
142 switch (ipi_msg) { 144 switch (ipi_msg) {
145 case IPI_WAKEUP:
146 break;
147
143 case IPI_RESCHEDULE: 148 case IPI_RESCHEDULE:
144 scheduler_ipi(); 149 scheduler_ipi();
145 break; 150 break;