Skip to content

Commit 755563b

Browse files
paulusmackmpe
authored andcommitted
powerpc/powernv: Fixes for hypervisor doorbell handling
Since we can now use hypervisor doorbells for host IPIs, this makes sure we clear the host IPI flag when taking a doorbell interrupt, and clears any pending doorbell IPI in pnv_smp_cpu_kill_self() (as we already do for IPIs sent via the XICS interrupt controller). Otherwise if there did happen to be a leftover pending doorbell interrupt for an offline CPU thread for any reason, it would prevent that thread from going into a power-saving mode; it would instead keep waking up because of the interrupt. Signed-off-by: Paul Mackerras <[email protected]> Signed-off-by: Michael Ellerman <[email protected]>
1 parent 06e5801 commit 755563b

File tree

4 files changed

+20
-2
lines changed

4 files changed

+20
-2
lines changed

arch/powerpc/include/asm/ppc-opcode.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@
153153
#define PPC_INST_MFSPR_PVR_MASK 0xfc1fffff
154154
#define PPC_INST_MFTMR 0x7c0002dc
155155
#define PPC_INST_MSGSND 0x7c00019c
156+
#define PPC_INST_MSGCLR 0x7c0001dc
156157
#define PPC_INST_MSGSNDP 0x7c00011c
157158
#define PPC_INST_MTTMR 0x7c0003dc
158159
#define PPC_INST_NOP 0x60000000
@@ -309,6 +310,8 @@
309310
___PPC_RB(b) | __PPC_EH(eh))
310311
#define PPC_MSGSND(b) stringify_in_c(.long PPC_INST_MSGSND | \
311312
___PPC_RB(b))
313+
#define PPC_MSGCLR(b) stringify_in_c(.long PPC_INST_MSGCLR | \
314+
___PPC_RB(b))
312315
#define PPC_MSGSNDP(b) stringify_in_c(.long PPC_INST_MSGSNDP | \
313316
___PPC_RB(b))
314317
#define PPC_POPCNTB(a, s) stringify_in_c(.long PPC_INST_POPCNTB | \

arch/powerpc/include/asm/reg.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,13 +608,16 @@
608608
#define SRR1_ISI_N_OR_G 0x10000000 /* ISI: Access is no-exec or G */
609609
#define SRR1_ISI_PROT 0x08000000 /* ISI: Other protection fault */
610610
#define SRR1_WAKEMASK 0x00380000 /* reason for wakeup */
611+
#define SRR1_WAKEMASK_P8 0x003c0000 /* reason for wakeup on POWER8 */
611612
#define SRR1_WAKESYSERR 0x00300000 /* System error */
612613
#define SRR1_WAKEEE 0x00200000 /* External interrupt */
613614
#define SRR1_WAKEMT 0x00280000 /* mtctrl */
614615
#define SRR1_WAKEHMI 0x00280000 /* Hypervisor maintenance */
615616
#define SRR1_WAKEDEC 0x00180000 /* Decrementer interrupt */
617+
#define SRR1_WAKEDBELL 0x00140000 /* Privileged doorbell on P8 */
616618
#define SRR1_WAKETHERM 0x00100000 /* Thermal management interrupt */
617619
#define SRR1_WAKERESET 0x00100000 /* System reset */
620+
#define SRR1_WAKEHDBELL 0x000c0000 /* Hypervisor doorbell on P8 */
618621
#define SRR1_WAKESTATE 0x00030000 /* Powersave exit mask [46:47] */
619622
#define SRR1_WS_DEEPEST 0x00030000 /* Some resources not maintained,
620623
* may not be recoverable */

arch/powerpc/kernel/dbell.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include <asm/dbell.h>
1919
#include <asm/irq_regs.h>
20+
#include <asm/kvm_ppc.h>
2021

2122
#ifdef CONFIG_SMP
2223
void doorbell_setup_this_cpu(void)
@@ -41,6 +42,7 @@ void doorbell_exception(struct pt_regs *regs)
4142

4243
may_hard_irq_enable();
4344

45+
kvmppc_set_host_ipi(smp_processor_id(), 0);
4446
__this_cpu_inc(irq_stat.doorbell_irqs);
4547

4648
smp_ipi_demux();

arch/powerpc/platforms/powernv/smp.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
#include <asm/runlatch.h>
3434
#include <asm/code-patching.h>
3535
#include <asm/dbell.h>
36+
#include <asm/kvm_ppc.h>
37+
#include <asm/ppc-opcode.h>
3638

3739
#include "powernv.h"
3840

@@ -149,7 +151,7 @@ static int pnv_smp_cpu_disable(void)
149151
static void pnv_smp_cpu_kill_self(void)
150152
{
151153
unsigned int cpu;
152-
unsigned long srr1;
154+
unsigned long srr1, wmask;
153155
u32 idle_states;
154156

155157
/* Standard hot unplug procedure */
@@ -161,6 +163,10 @@ static void pnv_smp_cpu_kill_self(void)
161163
generic_set_cpu_dead(cpu);
162164
smp_wmb();
163165

166+
wmask = SRR1_WAKEMASK;
167+
if (cpu_has_feature(CPU_FTR_ARCH_207S))
168+
wmask = SRR1_WAKEMASK_P8;
169+
164170
idle_states = pnv_get_supported_cpuidle_states();
165171
/* We don't want to take decrementer interrupts while we are offline,
166172
* so clear LPCR:PECE1. We keep PECE2 enabled.
@@ -191,10 +197,14 @@ static void pnv_smp_cpu_kill_self(void)
191197
* having finished executing in a KVM guest, then srr1
192198
* contains 0.
193199
*/
194-
if ((srr1 & SRR1_WAKEMASK) == SRR1_WAKEEE) {
200+
if ((srr1 & wmask) == SRR1_WAKEEE) {
195201
icp_native_flush_interrupt();
196202
local_paca->irq_happened &= PACA_IRQ_HARD_DIS;
197203
smp_mb();
204+
} else if ((srr1 & wmask) == SRR1_WAKEHDBELL) {
205+
unsigned long msg = PPC_DBELL_TYPE(PPC_DBELL_SERVER);
206+
asm volatile(PPC_MSGCLR(%0) : : "r" (msg));
207+
kvmppc_set_host_ipi(cpu, 0);
198208
}
199209

200210
if (cpu_core_split_required())

0 commit comments

Comments
 (0)