hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/arch/powerpc/kernel/rtas.c
....@@ -1,14 +1,10 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 *
34 * Procedures for interfacing to the RTAS on CHRP machines.
45 *
56 * Peter Bergner, IBM March 2001.
67 * Copyright (C) 2001 IBM.
7
- *
8
- * This program is free software; you can redistribute it and/or
9
- * modify it under the terms of the GNU General Public License
10
- * as published by the Free Software Foundation; either version
11
- * 2 of the License, or (at your option) any later version.
128 */
139
1410 #include <stdarg.h>
....@@ -20,6 +16,7 @@
2016 #include <linux/capability.h>
2117 #include <linux/delay.h>
2218 #include <linux/cpu.h>
19
+#include <linux/sched.h>
2320 #include <linux/smp.h>
2421 #include <linux/completion.h>
2522 #include <linux/cpumask.h>
....@@ -44,6 +41,7 @@
4441 #include <asm/time.h>
4542 #include <asm/mmu.h>
4643 #include <asm/topology.h>
44
+#include <asm/paca.h>
4745
4846 /* This is here deliberately so it's only used in this file */
4947 void enter_rtas(unsigned long);
....@@ -54,10 +52,10 @@
5452 EXPORT_SYMBOL(rtas);
5553
5654 DEFINE_SPINLOCK(rtas_data_buf_lock);
57
-EXPORT_SYMBOL(rtas_data_buf_lock);
55
+EXPORT_SYMBOL_GPL(rtas_data_buf_lock);
5856
59
-char rtas_data_buf[RTAS_DATA_BUF_SIZE] __cacheline_aligned;
60
-EXPORT_SYMBOL(rtas_data_buf);
57
+char rtas_data_buf[RTAS_DATA_BUF_SIZE] __aligned(SZ_4K);
58
+EXPORT_SYMBOL_GPL(rtas_data_buf);
6159
6260 unsigned long rtas_rmo_buf;
6361
....@@ -66,7 +64,7 @@
6664 * This is done like this so rtas_flash can be a module.
6765 */
6866 void (*rtas_flash_term_hook)(int);
69
-EXPORT_SYMBOL(rtas_flash_term_hook);
67
+EXPORT_SYMBOL_GPL(rtas_flash_term_hook);
7068
7169 /* RTAS use home made raw locking instead of spin_lock_irqsave
7270 * because those can be called from within really nasty contexts
....@@ -314,7 +312,7 @@
314312
315313 spin_unlock(&progress_lock);
316314 }
317
-EXPORT_SYMBOL(rtas_progress); /* needed by rtas_flash module */
315
+EXPORT_SYMBOL_GPL(rtas_progress); /* needed by rtas_flash module */
318316
319317 int rtas_token(const char *service)
320318 {
....@@ -324,7 +322,7 @@
324322 tokp = of_get_property(rtas.dev, service, NULL);
325323 return tokp ? be32_to_cpu(*tokp) : RTAS_UNKNOWN_SERVICE;
326324 }
327
-EXPORT_SYMBOL(rtas_token);
325
+EXPORT_SYMBOL_GPL(rtas_token);
328326
329327 int rtas_service_present(const char *service)
330328 {
....@@ -401,7 +399,7 @@
401399 buf = kmalloc(RTAS_ERROR_LOG_MAX, GFP_ATOMIC);
402400 }
403401 if (buf)
404
- memcpy(buf, rtas_err_buf, RTAS_ERROR_LOG_MAX);
402
+ memmove(buf, rtas_err_buf, RTAS_ERROR_LOG_MAX);
405403 }
406404
407405 return buf;
....@@ -484,7 +482,7 @@
484482 }
485483 return ret;
486484 }
487
-EXPORT_SYMBOL(rtas_call);
485
+EXPORT_SYMBOL_GPL(rtas_call);
488486
489487 /* For RTAS_BUSY (-2), delay for 1 millisecond. For an extended busy status
490488 * code of 990n, perform the hinted delay of 10^n (last digit) milliseconds.
....@@ -519,7 +517,7 @@
519517
520518 return ms;
521519 }
522
-EXPORT_SYMBOL(rtas_busy_delay);
520
+EXPORT_SYMBOL_GPL(rtas_busy_delay);
523521
524522 static int rtas_error_rc(int rtas_rc)
525523 {
....@@ -565,7 +563,7 @@
565563 return rtas_error_rc(rc);
566564 return rc;
567565 }
568
-EXPORT_SYMBOL(rtas_get_power_level);
566
+EXPORT_SYMBOL_GPL(rtas_get_power_level);
569567
570568 int rtas_set_power_level(int powerdomain, int level, int *setlevel)
571569 {
....@@ -583,7 +581,7 @@
583581 return rtas_error_rc(rc);
584582 return rc;
585583 }
586
-EXPORT_SYMBOL(rtas_set_power_level);
584
+EXPORT_SYMBOL_GPL(rtas_set_power_level);
587585
588586 int rtas_get_sensor(int sensor, int index, int *state)
589587 {
....@@ -601,7 +599,7 @@
601599 return rtas_error_rc(rc);
602600 return rc;
603601 }
604
-EXPORT_SYMBOL(rtas_get_sensor);
602
+EXPORT_SYMBOL_GPL(rtas_get_sensor);
605603
606604 int rtas_get_sensor_fast(int sensor, int index, int *state)
607605 {
....@@ -662,7 +660,7 @@
662660 return rtas_error_rc(rc);
663661 return rc;
664662 }
665
-EXPORT_SYMBOL(rtas_set_indicator);
663
+EXPORT_SYMBOL_GPL(rtas_set_indicator);
666664
667665 /*
668666 * Ignoring RTAS extended delay
....@@ -717,6 +715,7 @@
717715
718716 /* Must be in the RMO region, so we place it here */
719717 static char rtas_os_term_buf[2048];
718
+static s32 ibm_os_term_token = RTAS_UNKNOWN_SERVICE;
720719
721720 void rtas_os_term(char *str)
722721 {
....@@ -728,16 +727,20 @@
728727 * this property may terminate the partition which we want to avoid
729728 * since it interferes with panic_timeout.
730729 */
731
- if (RTAS_UNKNOWN_SERVICE == rtas_token("ibm,os-term") ||
732
- RTAS_UNKNOWN_SERVICE == rtas_token("ibm,extended-os-term"))
730
+ if (ibm_os_term_token == RTAS_UNKNOWN_SERVICE)
733731 return;
734732
735733 snprintf(rtas_os_term_buf, 2048, "OS panic: %s", str);
736734
735
+ /*
736
+ * Keep calling as long as RTAS returns a "try again" status,
737
+ * but don't use rtas_busy_delay(), which potentially
738
+ * schedules.
739
+ */
737740 do {
738
- status = rtas_call(rtas_token("ibm,os-term"), 1, 1, NULL,
741
+ status = rtas_call(ibm_os_term_token, 1, 1, NULL,
739742 __pa(rtas_os_term_buf));
740
- } while (rtas_busy_delay(status));
743
+ } while (rtas_busy_delay_time(status));
741744
742745 if (status != 0)
743746 printk(KERN_EMERG "ibm,os-term call failed %d\n", status);
....@@ -845,97 +848,6 @@
845848 __rtas_suspend_cpu((struct rtas_suspend_me_data *)info, 1);
846849 }
847850
848
-enum rtas_cpu_state {
849
- DOWN,
850
- UP,
851
-};
852
-
853
-#ifndef CONFIG_SMP
854
-static int rtas_cpu_state_change_mask(enum rtas_cpu_state state,
855
- cpumask_var_t cpus)
856
-{
857
- if (!cpumask_empty(cpus)) {
858
- cpumask_clear(cpus);
859
- return -EINVAL;
860
- } else
861
- return 0;
862
-}
863
-#else
864
-/* On return cpumask will be altered to indicate CPUs changed.
865
- * CPUs with states changed will be set in the mask,
866
- * CPUs with status unchanged will be unset in the mask. */
867
-static int rtas_cpu_state_change_mask(enum rtas_cpu_state state,
868
- cpumask_var_t cpus)
869
-{
870
- int cpu;
871
- int cpuret = 0;
872
- int ret = 0;
873
-
874
- if (cpumask_empty(cpus))
875
- return 0;
876
-
877
- for_each_cpu(cpu, cpus) {
878
- struct device *dev = get_cpu_device(cpu);
879
-
880
- switch (state) {
881
- case DOWN:
882
- cpuret = device_offline(dev);
883
- break;
884
- case UP:
885
- cpuret = device_online(dev);
886
- break;
887
- }
888
- if (cpuret < 0) {
889
- pr_debug("%s: cpu_%s for cpu#%d returned %d.\n",
890
- __func__,
891
- ((state == UP) ? "up" : "down"),
892
- cpu, cpuret);
893
- if (!ret)
894
- ret = cpuret;
895
- if (state == UP) {
896
- /* clear bits for unchanged cpus, return */
897
- cpumask_shift_right(cpus, cpus, cpu);
898
- cpumask_shift_left(cpus, cpus, cpu);
899
- break;
900
- } else {
901
- /* clear bit for unchanged cpu, continue */
902
- cpumask_clear_cpu(cpu, cpus);
903
- }
904
- }
905
- }
906
-
907
- return ret;
908
-}
909
-#endif
910
-
911
-int rtas_online_cpus_mask(cpumask_var_t cpus)
912
-{
913
- int ret;
914
-
915
- ret = rtas_cpu_state_change_mask(UP, cpus);
916
-
917
- if (ret) {
918
- cpumask_var_t tmp_mask;
919
-
920
- if (!alloc_cpumask_var(&tmp_mask, GFP_KERNEL))
921
- return ret;
922
-
923
- /* Use tmp_mask to preserve cpus mask from first failure */
924
- cpumask_copy(tmp_mask, cpus);
925
- rtas_offline_cpus_mask(tmp_mask);
926
- free_cpumask_var(tmp_mask);
927
- }
928
-
929
- return ret;
930
-}
931
-EXPORT_SYMBOL(rtas_online_cpus_mask);
932
-
933
-int rtas_offline_cpus_mask(cpumask_var_t cpus)
934
-{
935
- return rtas_cpu_state_change_mask(DOWN, cpus);
936
-}
937
-EXPORT_SYMBOL(rtas_offline_cpus_mask);
938
-
939851 int rtas_ibm_suspend_me(u64 handle)
940852 {
941853 long state;
....@@ -943,8 +855,6 @@
943855 unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
944856 struct rtas_suspend_me_data data;
945857 DECLARE_COMPLETION_ONSTACK(done);
946
- cpumask_var_t offline_mask;
947
- int cpuret;
948858
949859 if (!rtas_service_present("ibm,suspend-me"))
950860 return -ENOSYS;
....@@ -965,9 +875,6 @@
965875 return -EIO;
966876 }
967877
968
- if (!alloc_cpumask_var(&offline_mask, GFP_KERNEL))
969
- return -ENOMEM;
970
-
971878 atomic_set(&data.working, 0);
972879 atomic_set(&data.done, 0);
973880 atomic_set(&data.error, 0);
....@@ -976,43 +883,76 @@
976883
977884 lock_device_hotplug();
978885
979
- /* All present CPUs must be online */
980
- cpumask_andnot(offline_mask, cpu_present_mask, cpu_online_mask);
981
- cpuret = rtas_online_cpus_mask(offline_mask);
982
- if (cpuret) {
983
- pr_err("%s: Could not bring present CPUs online.\n", __func__);
984
- atomic_set(&data.error, cpuret);
985
- goto out;
986
- }
987
-
988886 cpu_hotplug_disable();
989
- stop_topology_update();
990887
991888 /* Call function on all CPUs. One of us will make the
992889 * rtas call
993890 */
994
- if (on_each_cpu(rtas_percpu_suspend_me, &data, 0))
995
- atomic_set(&data.error, -EINVAL);
891
+ on_each_cpu(rtas_percpu_suspend_me, &data, 0);
996892
997893 wait_for_completion(&done);
998894
999895 if (atomic_read(&data.error) != 0)
1000896 printk(KERN_ERR "Error doing global join\n");
1001897
1002
- start_topology_update();
898
+
1003899 cpu_hotplug_enable();
1004900
1005
- /* Take down CPUs not online prior to suspend */
1006
- cpuret = rtas_offline_cpus_mask(offline_mask);
1007
- if (cpuret)
1008
- pr_warn("%s: Could not restore CPUs to offline state.\n",
1009
- __func__);
1010
-
1011
-out:
1012901 unlock_device_hotplug();
1013
- free_cpumask_var(offline_mask);
902
+
1014903 return atomic_read(&data.error);
1015904 }
905
+
906
+/**
907
+ * rtas_call_reentrant() - Used for reentrant rtas calls
908
+ * @token: Token for desired reentrant RTAS call
909
+ * @nargs: Number of Input Parameters
910
+ * @nret: Number of Output Parameters
911
+ * @outputs: Array of outputs
912
+ * @...: Inputs for desired RTAS call
913
+ *
914
+ * According to LoPAR documentation, only "ibm,int-on", "ibm,int-off",
915
+ * "ibm,get-xive" and "ibm,set-xive" are currently reentrant.
916
+ * Reentrant calls need their own rtas_args buffer, so not using rtas.args, but
917
+ * PACA one instead.
918
+ *
919
+ * Return: -1 on error,
920
+ * First output value of RTAS call if (nret > 0),
921
+ * 0 otherwise,
922
+ */
923
+int rtas_call_reentrant(int token, int nargs, int nret, int *outputs, ...)
924
+{
925
+ va_list list;
926
+ struct rtas_args *args;
927
+ unsigned long flags;
928
+ int i, ret = 0;
929
+
930
+ if (!rtas.entry || token == RTAS_UNKNOWN_SERVICE)
931
+ return -1;
932
+
933
+ local_irq_save(flags);
934
+ preempt_disable();
935
+
936
+ /* We use the per-cpu (PACA) rtas args buffer */
937
+ args = local_paca->rtas_args_reentrant;
938
+
939
+ va_start(list, outputs);
940
+ va_rtas_call_unlocked(args, token, nargs, nret, list);
941
+ va_end(list);
942
+
943
+ if (nret > 1 && outputs)
944
+ for (i = 0; i < nret - 1; ++i)
945
+ outputs[i] = be32_to_cpu(args->rets[i + 1]);
946
+
947
+ if (nret > 0)
948
+ ret = be32_to_cpu(args->rets[0]);
949
+
950
+ local_irq_restore(flags);
951
+ preempt_enable();
952
+
953
+ return ret;
954
+}
955
+
1016956 #else /* CONFIG_PPC_PSERIES */
1017957 int rtas_ibm_suspend_me(u64 handle)
1018958 {
....@@ -1105,7 +1045,7 @@
11051045 { "get-time-of-day", -1, -1, -1, -1, -1 },
11061046 { "ibm,get-vpd", -1, 0, -1, 1, 2 },
11071047 { "ibm,lpar-perftools", -1, 2, 3, -1, -1 },
1108
- { "ibm,platform-dump", -1, 4, 5, -1, -1 },
1048
+ { "ibm,platform-dump", -1, 4, 5, -1, -1 }, /* Special cased */
11091049 { "ibm,read-slot-reset-state", -1, -1, -1, -1, -1 },
11101050 { "ibm,scan-log-dump", -1, 0, 1, -1, -1 },
11111051 { "ibm,set-dynamic-indicator", -1, 2, -1, -1, -1 },
....@@ -1152,6 +1092,15 @@
11521092 size = 1;
11531093
11541094 end = base + size - 1;
1095
+
1096
+ /*
1097
+ * Special case for ibm,platform-dump - NULL buffer
1098
+ * address is used to indicate end of dump processing
1099
+ */
1100
+ if (!strcmp(f->name, "ibm,platform-dump") &&
1101
+ base == 0)
1102
+ return false;
1103
+
11551104 if (!in_rmo_buf(base, end))
11561105 goto err;
11571106 }
....@@ -1323,6 +1272,13 @@
13231272 no_entry = of_property_read_u32(rtas.dev, "linux,rtas-entry", &entry);
13241273 rtas.entry = no_entry ? rtas.base : entry;
13251274
1275
+ /*
1276
+ * Discover these now to avoid device tree lookups in the
1277
+ * panic path.
1278
+ */
1279
+ if (of_property_read_bool(rtas.dev, "ibm,extended-os-term"))
1280
+ ibm_os_term_token = rtas_token("ibm,os-term");
1281
+
13261282 /* If RTAS was found, allocate the RMO buffer for it and look for
13271283 * the stop-self token if any
13281284 */
....@@ -1332,7 +1288,11 @@
13321288 ibm_suspend_me_token = rtas_token("ibm,suspend-me");
13331289 }
13341290 #endif
1335
- rtas_rmo_buf = memblock_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, rtas_region);
1291
+ rtas_rmo_buf = memblock_phys_alloc_range(RTAS_RMOBUF_MAX, PAGE_SIZE,
1292
+ 0, rtas_region);
1293
+ if (!rtas_rmo_buf)
1294
+ panic("ERROR: RTAS: Failed to allocate %lx bytes below %pa\n",
1295
+ PAGE_SIZE, &rtas_region);
13361296
13371297 #ifdef CONFIG_RTAS_ERROR_LOGGING
13381298 rtas_last_error_token = rtas_token("rtas-last-error");
....@@ -1357,6 +1317,12 @@
13571317 entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL);
13581318 sizep = of_get_flat_dt_prop(node, "rtas-size", NULL);
13591319
1320
+#ifdef CONFIG_PPC64
1321
+ /* need this feature to decide the crashkernel offset */
1322
+ if (of_get_flat_dt_prop(node, "ibm,hypertas-functions", NULL))
1323
+ powerpc_firmware_features |= FW_FEATURE_LPAR;
1324
+#endif
1325
+
13601326 if (basep && entryp && sizep) {
13611327 rtas.base = *basep;
13621328 rtas.entry = *entryp;