hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/arch/powerpc/platforms/powernv/setup.c
....@@ -1,12 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * PowerNV setup code.
34 *
45 * Copyright 2011 IBM Corp.
5
- *
6
- * This program is free software; you can redistribute it and/or
7
- * modify it under the terms of the GNU General Public License
8
- * as published by the Free Software Foundation; either version
9
- * 2 of the License, or (at your option) any later version.
106 */
117
128 #undef DEBUG
....@@ -28,6 +24,7 @@
2824 #include <linux/bug.h>
2925 #include <linux/pci.h>
3026 #include <linux/cpufreq.h>
27
+#include <linux/memblock.h>
3128
3229 #include <asm/machdep.h>
3330 #include <asm/firmware.h>
....@@ -101,7 +98,7 @@
10198 security_ftr_clear(SEC_FTR_BNDS_CHK_SPEC_BAR);
10299 }
103100
104
-static void pnv_setup_rfi_flush(void)
101
+static void pnv_setup_security_mitigations(void)
105102 {
106103 struct device_node *np, *fw_features;
107104 enum l1d_flush_type type;
....@@ -148,14 +145,37 @@
148145 enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) &&
149146 security_ftr_enabled(SEC_FTR_L1D_FLUSH_UACCESS);
150147 setup_uaccess_flush(enable);
148
+
149
+ setup_stf_barrier();
150
+}
151
+
152
+static void __init pnv_check_guarded_cores(void)
153
+{
154
+ struct device_node *dn;
155
+ int bad_count = 0;
156
+
157
+ for_each_node_by_type(dn, "cpu") {
158
+ if (of_property_match_string(dn, "status", "bad") >= 0)
159
+ bad_count++;
160
+ };
161
+
162
+ if (bad_count) {
163
+ printk(" _ _______________\n");
164
+ pr_cont(" | | / \\\n");
165
+ pr_cont(" | | | WARNING! |\n");
166
+ pr_cont(" | | | |\n");
167
+ pr_cont(" | | | It looks like |\n");
168
+ pr_cont(" |_| | you have %*d |\n", 3, bad_count);
169
+ pr_cont(" _ | guarded cores |\n");
170
+ pr_cont(" (_) \\_______________/\n");
171
+ }
151172 }
152173
153174 static void __init pnv_setup_arch(void)
154175 {
155176 set_arch_panic_timeout(10, ARCH_PANIC_TIMEOUT);
156177
157
- pnv_setup_rfi_flush();
158
- setup_stf_barrier();
178
+ pnv_setup_security_mitigations();
159179
160180 /* Initialize SMP */
161181 pnv_smp_init();
....@@ -170,7 +190,11 @@
170190 /* Enable NAP mode */
171191 powersave_nap = 1;
172192
193
+ pnv_check_guarded_cores();
194
+
173195 /* XXX PMCS */
196
+
197
+ pnv_rng_init();
174198 }
175199
176200 static void __init pnv_init(void)
....@@ -187,6 +211,19 @@
187211 else
188212 #endif
189213 add_preferred_console("hvc", 0, NULL);
214
+
215
+ if (!radix_enabled()) {
216
+ size_t size = sizeof(struct slb_entry) * mmu_slb_size;
217
+ int i;
218
+
219
+ /* Allocate per cpu area to save old slb contents during MCE */
220
+ for_each_possible_cpu(i) {
221
+ paca_ptrs[i]->mce_faulty_slbs =
222
+ memblock_alloc_node(size,
223
+ __alignof__(struct slb_entry),
224
+ cpu_to_node(i));
225
+ }
226
+ }
190227 }
191228
192229 static void __init pnv_init_IRQ(void)
....@@ -236,17 +273,47 @@
236273
237274 static void __noreturn pnv_restart(char *cmd)
238275 {
239
- long rc = OPAL_BUSY;
276
+ long rc;
240277
241278 pnv_prepare_going_down();
242279
243
- while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
244
- rc = opal_cec_reboot();
245
- if (rc == OPAL_BUSY_EVENT)
246
- opal_poll_events(NULL);
280
+ do {
281
+ if (!cmd || !strlen(cmd))
282
+ rc = opal_cec_reboot();
283
+ else if (strcmp(cmd, "full") == 0)
284
+ rc = opal_cec_reboot2(OPAL_REBOOT_FULL_IPL, NULL);
285
+ else if (strcmp(cmd, "mpipl") == 0)
286
+ rc = opal_cec_reboot2(OPAL_REBOOT_MPIPL, NULL);
287
+ else if (strcmp(cmd, "error") == 0)
288
+ rc = opal_cec_reboot2(OPAL_REBOOT_PLATFORM_ERROR, NULL);
289
+ else if (strcmp(cmd, "fast") == 0)
290
+ rc = opal_cec_reboot2(OPAL_REBOOT_FAST, NULL);
247291 else
292
+ rc = OPAL_UNSUPPORTED;
293
+
294
+ if (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
295
+ /* Opal is busy wait for some time and retry */
296
+ opal_poll_events(NULL);
248297 mdelay(10);
249
- }
298
+
299
+ } else if (cmd && rc) {
300
+ /* Unknown error while issuing reboot */
301
+ if (rc == OPAL_UNSUPPORTED)
302
+ pr_err("Unsupported '%s' reboot.\n", cmd);
303
+ else
304
+ pr_err("Unable to issue '%s' reboot. Err=%ld\n",
305
+ cmd, rc);
306
+ pr_info("Forcing a cec-reboot\n");
307
+ cmd = NULL;
308
+ rc = OPAL_BUSY;
309
+
310
+ } else if (rc != OPAL_SUCCESS) {
311
+ /* Unknown error while issuing cec-reboot */
312
+ pr_err("Unable to reboot. Err=%ld\n", rc);
313
+ }
314
+
315
+ } while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT);
316
+
250317 for (;;)
251318 opal_poll_events(NULL);
252319 }
....@@ -381,7 +448,15 @@
381448 #ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
382449 static unsigned long pnv_memory_block_size(void)
383450 {
384
- return 256UL * 1024 * 1024;
451
+ /*
452
+ * We map the kernel linear region with 1GB large pages on radix. For
453
+ * memory hot unplug to work our memory block size must be at least
454
+ * this size.
455
+ */
456
+ if (radix_enabled())
457
+ return radix_mem_block_size;
458
+ else
459
+ return 256UL * 1024 * 1024;
385460 }
386461 #endif
387462
....@@ -394,7 +469,10 @@
394469 /* ppc_md.system_reset_exception gets filled in by pnv_smp_init() */
395470 ppc_md.machine_check_exception = opal_machine_check;
396471 ppc_md.mce_check_early_recovery = opal_mce_check_early_recovery;
397
- ppc_md.hmi_exception_early = opal_hmi_exception_early;
472
+ if (opal_check_token(OPAL_HANDLE_HMI2))
473
+ ppc_md.hmi_exception_early = opal_hmi_exception_early2;
474
+ else
475
+ ppc_md.hmi_exception_early = opal_hmi_exception_early;
398476 ppc_md.handle_hmi_exception = opal_handle_hmi_exception;
399477 }
400478
....@@ -454,6 +532,16 @@
454532 return ret_freq;
455533 }
456534
535
+static long pnv_machine_check_early(struct pt_regs *regs)
536
+{
537
+ long handled = 0;
538
+
539
+ if (cur_cpu_spec && cur_cpu_spec->machine_check_early)
540
+ handled = cur_cpu_spec->machine_check_early(regs);
541
+
542
+ return handled;
543
+}
544
+
457545 define_machine(powernv) {
458546 .name = "PowerNV",
459547 .probe = pnv_probe,
....@@ -465,6 +553,7 @@
465553 .machine_shutdown = pnv_shutdown,
466554 .power_save = NULL,
467555 .calibrate_decr = generic_calibrate_decr,
556
+ .machine_check_early = pnv_machine_check_early,
468557 #ifdef CONFIG_KEXEC_CORE
469558 .kexec_cpu_down = pnv_kexec_cpu_down,
470559 #endif