forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-06 08f87f769b595151be1afeff53e144f543faa614
kernel/arch/powerpc/platforms/pseries/smp.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * SMP support for pSeries machines.
34 *
....@@ -5,11 +6,6 @@
56 * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com
67 *
78 * Plus various changes from other IBM teams...
8
- *
9
- * This program is free software; you can redistribute it and/or
10
- * modify it under the terms of the GNU General Public License
11
- * as published by the Free Software Foundation; either version
12
- * 2 of the License, or (at your option) any later version.
139 */
1410
1511
....@@ -24,12 +20,12 @@
2420 #include <linux/err.h>
2521 #include <linux/device.h>
2622 #include <linux/cpu.h>
23
+#include <linux/pgtable.h>
2724
2825 #include <asm/ptrace.h>
2926 #include <linux/atomic.h>
3027 #include <asm/irq.h>
3128 #include <asm/page.h>
32
-#include <asm/pgtable.h>
3329 #include <asm/io.h>
3430 #include <asm/prom.h>
3531 #include <asm/smp.h>
....@@ -45,10 +41,10 @@
4541 #include <asm/dbell.h>
4642 #include <asm/plpar_wrappers.h>
4743 #include <asm/code-patching.h>
44
+#include <asm/svm.h>
45
+#include <asm/kvm_guest.h>
4846
4947 #include "pseries.h"
50
-#include "offline_states.h"
51
-
5248
5349 /*
5450 * The Primary thread of each non-boot processor was started from the OF client
....@@ -109,12 +105,6 @@
109105 return 1;
110106 }
111107
112
- /* Fixup atomic count: it exited inside IRQ handler. */
113
- task_thread_info(paca_ptrs[lcpu]->__current)->preempt_count = 0;
114
-#ifdef CONFIG_HOTPLUG_CPU
115
- if (get_cpu_current_state(lcpu) == CPU_STATE_INACTIVE)
116
- goto out;
117
-#endif
118108 /*
119109 * If the RTAS start-cpu token does not exist then presume the
120110 * cpu is already spinning.
....@@ -129,9 +119,6 @@
129119 return 0;
130120 }
131121
132
-#ifdef CONFIG_HOTPLUG_CPU
133
-out:
134
-#endif
135122 return 1;
136123 }
137124
....@@ -146,10 +133,6 @@
146133 vpa_init(cpu);
147134
148135 cpumask_clear_cpu(cpu, of_spin_mask);
149
-#ifdef CONFIG_HOTPLUG_CPU
150
- set_cpu_current_state(cpu, CPU_STATE_ONLINE);
151
- set_default_offline_state(cpu);
152
-#endif
153136 }
154137
155138 static int smp_pSeries_kick_cpu(int nr)
....@@ -166,20 +149,6 @@
166149 * the processor will continue on to secondary_start
167150 */
168151 paca_ptrs[nr]->cpu_start = 1;
169
-#ifdef CONFIG_HOTPLUG_CPU
170
- set_preferred_offline_state(nr, CPU_STATE_ONLINE);
171
-
172
- if (get_cpu_current_state(nr) == CPU_STATE_INACTIVE) {
173
- long rc;
174
- unsigned long hcpuid;
175
-
176
- hcpuid = get_hard_smp_processor_id(nr);
177
- rc = plpar_hcall_norets(H_PROD, hcpuid);
178
- if (rc != H_SUCCESS)
179
- printk(KERN_ERR "Error: Prod to wake up processor %d "
180
- "Ret= %ld\n", nr, rc);
181
- }
182
-#endif
183152
184153 return 0;
185154 }
....@@ -191,13 +160,16 @@
191160 return 0;
192161 }
193162
194
-static void smp_pseries_cause_ipi(int cpu)
163
+/* Cause IPI as setup by the interrupt controller (xics or xive) */
164
+static void (*ic_cause_ipi)(int cpu) __ro_after_init;
165
+
166
+/* Use msgsndp doorbells target is a sibling, else use interrupt controller */
167
+static void dbell_or_ic_cause_ipi(int cpu)
195168 {
196
- /* POWER9 should not use this handler */
197169 if (doorbell_try_core_ipi(cpu))
198170 return;
199171
200
- icp_ops->cause_ipi(cpu);
172
+ ic_cause_ipi(cpu);
201173 }
202174
203175 static int pseries_cause_nmi_ipi(int cpu)
....@@ -221,26 +193,51 @@
221193 return 0;
222194 }
223195
224
-static __init void pSeries_smp_probe_xics(void)
225
-{
226
- xics_smp_probe();
227
-
228
- if (cpu_has_feature(CPU_FTR_DBELL))
229
- smp_ops->cause_ipi = smp_pseries_cause_ipi;
230
- else
231
- smp_ops->cause_ipi = icp_ops->cause_ipi;
232
-}
233
-
234196 static __init void pSeries_smp_probe(void)
235197 {
236198 if (xive_enabled())
237
- /*
238
- * Don't use P9 doorbells when XIVE is enabled. IPIs
239
- * using MMIOs should be faster
240
- */
241199 xive_smp_probe();
242200 else
243
- pSeries_smp_probe_xics();
201
+ xics_smp_probe();
202
+
203
+ /* No doorbell facility, must use the interrupt controller for IPIs */
204
+ if (!cpu_has_feature(CPU_FTR_DBELL))
205
+ return;
206
+
207
+ /* Doorbells can only be used for IPIs between SMT siblings */
208
+ if (!cpu_has_feature(CPU_FTR_SMT))
209
+ return;
210
+
211
+ check_kvm_guest();
212
+
213
+ if (is_kvm_guest()) {
214
+ /*
215
+ * KVM emulates doorbells by disabling FSCR[MSGP] so msgsndp
216
+ * faults to the hypervisor which then reads the instruction
217
+ * from guest memory, which tends to be slower than using XIVE.
218
+ */
219
+ if (xive_enabled())
220
+ return;
221
+
222
+ /*
223
+ * XICS hcalls aren't as fast, so we can use msgsndp (which
224
+ * also helps exercise KVM emulation), however KVM can't
225
+ * emulate secure guests because it can't read the instruction
226
+ * out of their memory.
227
+ */
228
+ if (is_secure_guest())
229
+ return;
230
+ }
231
+
232
+ /*
233
+ * Under PowerVM, FSCR[MSGP] is enabled as guest vCPU siblings are
234
+ * gang scheduled on the same physical core, so doorbells are always
235
+ * faster than the interrupt controller, and they can be used by
236
+ * secure guests.
237
+ */
238
+
239
+ ic_cause_ipi = smp_ops->cause_ipi;
240
+ smp_ops->cause_ipi = dbell_or_ic_cause_ipi;
244241 }
245242
246243 static struct smp_ops_t pseries_smp_ops = {