]>
Commit | Line | Data |
---|---|---|
0cb42a7c GKH |
1 | From 19f8a5b5be2898573a5e1dc1db93e8d40117606a Mon Sep 17 00:00:00 2001 |
2 | From: Paul Mackerras <paulus@ozlabs.org> | |
3 | Date: Tue, 12 Feb 2019 11:58:29 +1100 | |
4 | Subject: powerpc/powernv: Don't reprogram SLW image on every KVM guest entry/exit | |
5 | ||
6 | From: Paul Mackerras <paulus@ozlabs.org> | |
7 | ||
8 | commit 19f8a5b5be2898573a5e1dc1db93e8d40117606a upstream. | |
9 | ||
10 | Commit 24be85a23d1f ("powerpc/powernv: Clear PECE1 in LPCR via stop-api | |
11 | only on Hotplug", 2017-07-21) added two calls to opal_slw_set_reg() | |
12 | inside pnv_cpu_offline(), with the aim of changing the LPCR value in | |
13 | the SLW image to disable wakeups from the decrementer while a CPU is | |
14 | offline. However, pnv_cpu_offline() gets called each time a secondary | |
15 | CPU thread is woken up to participate in running a KVM guest, that is, | |
16 | not just when a CPU is offlined. | |
17 | ||
18 | Since opal_slw_set_reg() is a very slow operation (with observed | |
19 | execution times around 20 milliseconds), this means that an offline | |
20 | secondary CPU can often be busy doing the opal_slw_set_reg() call | |
21 | when the primary CPU wants to grab all the secondary threads so that | |
22 | it can run a KVM guest. This leads to messages like "KVM: couldn't | |
23 | grab CPU n" being printed and guest execution failing. | |
24 | ||
25 | There is no need to reprogram the SLW image on every KVM guest entry | |
26 | and exit. So that we do it only when a CPU is really transitioning | |
27 | between online and offline, this moves the calls to | |
28 | pnv_program_cpu_hotplug_lpcr() into pnv_smp_cpu_kill_self(). | |
29 | ||
30 | Fixes: 24be85a23d1f ("powerpc/powernv: Clear PECE1 in LPCR via stop-api only on Hotplug") | |
31 | Cc: stable@vger.kernel.org # v4.14+ | |
32 | Signed-off-by: Paul Mackerras <paulus@ozlabs.org> | |
33 | Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> | |
34 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
35 | ||
36 | --- | |
37 | arch/powerpc/include/asm/powernv.h | 2 ++ | |
38 | arch/powerpc/platforms/powernv/idle.c | 27 ++------------------------- | |
39 | arch/powerpc/platforms/powernv/smp.c | 25 +++++++++++++++++++++++++ | |
40 | 3 files changed, 29 insertions(+), 25 deletions(-) | |
41 | ||
42 | --- a/arch/powerpc/include/asm/powernv.h | |
43 | +++ b/arch/powerpc/include/asm/powernv.h | |
44 | @@ -23,6 +23,8 @@ extern int pnv_npu2_handle_fault(struct | |
45 | unsigned long *flags, unsigned long *status, | |
46 | int count); | |
47 | ||
48 | +void pnv_program_cpu_hotplug_lpcr(unsigned int cpu, u64 lpcr_val); | |
49 | + | |
50 | void pnv_tm_init(void); | |
51 | #else | |
52 | static inline void powernv_set_nmmu_ptcr(unsigned long ptcr) { } | |
53 | --- a/arch/powerpc/platforms/powernv/idle.c | |
54 | +++ b/arch/powerpc/platforms/powernv/idle.c | |
55 | @@ -458,7 +458,8 @@ EXPORT_SYMBOL_GPL(pnv_power9_force_smt4_ | |
56 | #endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */ | |
57 | ||
58 | #ifdef CONFIG_HOTPLUG_CPU | |
59 | -static void pnv_program_cpu_hotplug_lpcr(unsigned int cpu, u64 lpcr_val) | |
60 | + | |
61 | +void pnv_program_cpu_hotplug_lpcr(unsigned int cpu, u64 lpcr_val) | |
62 | { | |
63 | u64 pir = get_hard_smp_processor_id(cpu); | |
64 | ||
65 | @@ -481,20 +482,6 @@ unsigned long pnv_cpu_offline(unsigned i | |
66 | { | |
67 | unsigned long srr1; | |
68 | u32 idle_states = pnv_get_supported_cpuidle_states(); | |
69 | - u64 lpcr_val; | |
70 | - | |
71 | - /* | |
72 | - * We don't want to take decrementer interrupts while we are | |
73 | - * offline, so clear LPCR:PECE1. We keep PECE2 (and | |
74 | - * LPCR_PECE_HVEE on P9) enabled as to let IPIs in. | |
75 | - * | |
76 | - * If the CPU gets woken up by a special wakeup, ensure that | |
77 | - * the SLW engine sets LPCR with decrementer bit cleared, else | |
78 | - * the CPU will come back to the kernel due to a spurious | |
79 | - * wakeup. | |
80 | - */ | |
81 | - lpcr_val = mfspr(SPRN_LPCR) & ~(u64)LPCR_PECE1; | |
82 | - pnv_program_cpu_hotplug_lpcr(cpu, lpcr_val); | |
83 | ||
84 | __ppc64_runlatch_off(); | |
85 | ||
86 | @@ -526,16 +513,6 @@ unsigned long pnv_cpu_offline(unsigned i | |
87 | ||
88 | __ppc64_runlatch_on(); | |
89 | ||
90 | - /* | |
91 | - * Re-enable decrementer interrupts in LPCR. | |
92 | - * | |
93 | - * Further, we want stop states to be woken up by decrementer | |
94 | - * for non-hotplug cases. So program the LPCR via stop api as | |
95 | - * well. | |
96 | - */ | |
97 | - lpcr_val = mfspr(SPRN_LPCR) | (u64)LPCR_PECE1; | |
98 | - pnv_program_cpu_hotplug_lpcr(cpu, lpcr_val); | |
99 | - | |
100 | return srr1; | |
101 | } | |
102 | #endif | |
103 | --- a/arch/powerpc/platforms/powernv/smp.c | |
104 | +++ b/arch/powerpc/platforms/powernv/smp.c | |
105 | @@ -39,6 +39,7 @@ | |
106 | #include <asm/cpuidle.h> | |
107 | #include <asm/kexec.h> | |
108 | #include <asm/reg.h> | |
109 | +#include <asm/powernv.h> | |
110 | ||
111 | #include "powernv.h" | |
112 | ||
113 | @@ -153,6 +154,7 @@ static void pnv_smp_cpu_kill_self(void) | |
114 | { | |
115 | unsigned int cpu; | |
116 | unsigned long srr1, wmask; | |
117 | + u64 lpcr_val; | |
118 | ||
119 | /* Standard hot unplug procedure */ | |
120 | /* | |
121 | @@ -174,6 +176,19 @@ static void pnv_smp_cpu_kill_self(void) | |
122 | if (cpu_has_feature(CPU_FTR_ARCH_207S)) | |
123 | wmask = SRR1_WAKEMASK_P8; | |
124 | ||
125 | + /* | |
126 | + * We don't want to take decrementer interrupts while we are | |
127 | + * offline, so clear LPCR:PECE1. We keep PECE2 (and | |
128 | + * LPCR_PECE_HVEE on P9) enabled so as to let IPIs in. | |
129 | + * | |
130 | + * If the CPU gets woken up by a special wakeup, ensure that | |
131 | + * the SLW engine sets LPCR with decrementer bit cleared, else | |
132 | + * the CPU will come back to the kernel due to a spurious | |
133 | + * wakeup. | |
134 | + */ | |
135 | + lpcr_val = mfspr(SPRN_LPCR) & ~(u64)LPCR_PECE1; | |
136 | + pnv_program_cpu_hotplug_lpcr(cpu, lpcr_val); | |
137 | + | |
138 | while (!generic_check_cpu_restart(cpu)) { | |
139 | /* | |
140 | * Clear IPI flag, since we don't handle IPIs while | |
141 | @@ -246,6 +261,16 @@ static void pnv_smp_cpu_kill_self(void) | |
142 | ||
143 | } | |
144 | ||
145 | + /* | |
146 | + * Re-enable decrementer interrupts in LPCR. | |
147 | + * | |
148 | + * Further, we want stop states to be woken up by decrementer | |
149 | + * for non-hotplug cases. So program the LPCR via stop api as | |
150 | + * well. | |
151 | + */ | |
152 | + lpcr_val = mfspr(SPRN_LPCR) | (u64)LPCR_PECE1; | |
153 | + pnv_program_cpu_hotplug_lpcr(cpu, lpcr_val); | |
154 | + | |
155 | DBG("CPU%d coming online...\n", cpu); | |
156 | } | |
157 |