forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/arch/powerpc/platforms/powernv/opal.c
....@@ -1,12 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * PowerNV OPAL high level interfaces
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 #define pr_fmt(fmt) "opal: " fmt
....@@ -26,7 +22,6 @@
2622 #include <linux/memblock.h>
2723 #include <linux/kthread.h>
2824 #include <linux/freezer.h>
29
-#include <linux/printk.h>
3025 #include <linux/kmsg_dump.h>
3126 #include <linux/console.h>
3227 #include <linux/sched/debug.h>
....@@ -39,6 +34,16 @@
3934 #include <asm/bug.h>
4035
4136 #include "powernv.h"
37
+
38
+#define OPAL_MSG_QUEUE_MAX 16
39
+
40
+struct opal_msg_node {
41
+ struct list_head list;
42
+ struct opal_msg msg;
43
+};
44
+
45
+static DEFINE_SPINLOCK(msg_list_lock);
46
+static LIST_HEAD(msg_list);
4247
4348 /* /sys/firmware/opal */
4449 struct kobject *opal_kobj;
....@@ -55,6 +60,8 @@
5560 u64 recover_addr;
5661 };
5762
63
+static int msg_list_size;
64
+
5865 static struct mcheck_recoverable_range *mc_recoverable_range;
5966 static int mc_recoverable_range_len;
6067
....@@ -63,6 +70,8 @@
6370 static struct atomic_notifier_head opal_msg_notifier_head[OPAL_MSG_TYPE_MAX];
6471 static uint32_t opal_heartbeat;
6572 static struct task_struct *kopald_tsk;
73
+static struct opal_msg *opal_msg;
74
+static u32 opal_msg_size __ro_after_init;
6675
6776 void opal_configure_cores(void)
6877 {
....@@ -171,8 +180,10 @@
171180 /*
172181 * Allocate a buffer to hold the MC recoverable ranges.
173182 */
174
- mc_recoverable_range =__va(memblock_alloc(size, __alignof__(u64)));
175
- memset(mc_recoverable_range, 0, size);
183
+ mc_recoverable_range = memblock_alloc(size, __alignof__(u64));
184
+ if (!mc_recoverable_range)
185
+ panic("%s: Failed to allocate %u bytes align=0x%lx\n",
186
+ __func__, size, __alignof__(u64));
176187
177188 for (i = 0; i < mc_recoverable_range_len; i++) {
178189 mc_recoverable_range[i].start_addr =
....@@ -205,16 +216,18 @@
205216 glue = 0x7000;
206217
207218 /*
208
- * Check if we are running on newer firmware that exports
209
- * OPAL_HANDLE_HMI token. If yes, then don't ask OPAL to patch
210
- * the HMI interrupt and we catch it directly in Linux.
219
+ * Only ancient OPAL firmware requires this.
220
+ * Specifically, firmware from FW810.00 (released June 2014)
221
+ * through FW810.20 (Released October 2014).
211222 *
212
- * For older firmware (i.e currently released POWER8 System Firmware
213
- * as of today <= SV810_087), we fallback to old behavior and let OPAL
214
- * patch the HMI vector and handle it inside OPAL firmware.
223
+ * Check if we are running on newer (post Oct 2014) firmware that
224
+ * exports the OPAL_HANDLE_HMI token. If yes, then don't ask OPAL to
225
+ * patch the HMI interrupt and we catch it directly in Linux.
215226 *
216
- * For newer firmware (in development/yet to be released) we will
217
- * start catching/handling HMI directly in Linux.
227
+ * For older firmware (i.e < FW810.20), we fallback to old behavior and
228
+ * let OPAL patch the HMI vector and handle it inside OPAL firmware.
229
+ *
230
+ * For newer firmware we catch/handle the HMI directly in Linux.
218231 */
219232 if (!opal_check_token(OPAL_HANDLE_HMI)) {
220233 pr_info("Old firmware detected, OPAL handles HMIs.\n");
....@@ -224,12 +237,54 @@
224237 glue += 128;
225238 }
226239
240
+ /*
241
+ * Only applicable to ancient firmware, all modern
242
+ * (post March 2015/skiboot 5.0) firmware will just return
243
+ * OPAL_UNSUPPORTED.
244
+ */
227245 opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue);
228246 #endif
229247
230248 return 0;
231249 }
232250 machine_early_initcall(powernv, opal_register_exception_handlers);
251
+
252
+static void queue_replay_msg(void *msg)
253
+{
254
+ struct opal_msg_node *msg_node;
255
+
256
+ if (msg_list_size < OPAL_MSG_QUEUE_MAX) {
257
+ msg_node = kzalloc(sizeof(*msg_node), GFP_ATOMIC);
258
+ if (msg_node) {
259
+ INIT_LIST_HEAD(&msg_node->list);
260
+ memcpy(&msg_node->msg, msg, sizeof(struct opal_msg));
261
+ list_add_tail(&msg_node->list, &msg_list);
262
+ msg_list_size++;
263
+ } else
264
+ pr_warn_once("message queue no memory\n");
265
+
266
+ if (msg_list_size >= OPAL_MSG_QUEUE_MAX)
267
+ pr_warn_once("message queue full\n");
268
+ }
269
+}
270
+
271
+static void dequeue_replay_msg(enum opal_msg_type msg_type)
272
+{
273
+ struct opal_msg_node *msg_node, *tmp;
274
+
275
+ list_for_each_entry_safe(msg_node, tmp, &msg_list, list) {
276
+ if (be32_to_cpu(msg_node->msg.msg_type) != msg_type)
277
+ continue;
278
+
279
+ atomic_notifier_call_chain(&opal_msg_notifier_head[msg_type],
280
+ msg_type,
281
+ &msg_node->msg);
282
+
283
+ list_del(&msg_node->list);
284
+ kfree(msg_node);
285
+ msg_list_size--;
286
+ }
287
+}
233288
234289 /*
235290 * Opal message notifier based on message type. Allow subscribers to get
....@@ -238,14 +293,30 @@
238293 int opal_message_notifier_register(enum opal_msg_type msg_type,
239294 struct notifier_block *nb)
240295 {
296
+ int ret;
297
+ unsigned long flags;
298
+
241299 if (!nb || msg_type >= OPAL_MSG_TYPE_MAX) {
242300 pr_warn("%s: Invalid arguments, msg_type:%d\n",
243301 __func__, msg_type);
244302 return -EINVAL;
245303 }
246304
247
- return atomic_notifier_chain_register(
248
- &opal_msg_notifier_head[msg_type], nb);
305
+ spin_lock_irqsave(&msg_list_lock, flags);
306
+ ret = atomic_notifier_chain_register(
307
+ &opal_msg_notifier_head[msg_type], nb);
308
+
309
+ /*
310
+ * If the registration succeeded, replay any queued messages that came
311
+ * in prior to the notifier chain registration. msg_list_lock held here
312
+ * to ensure they're delivered prior to any subsequent messages.
313
+ */
314
+ if (ret == 0)
315
+ dequeue_replay_msg(msg_type);
316
+
317
+ spin_unlock_irqrestore(&msg_list_lock, flags);
318
+
319
+ return ret;
249320 }
250321 EXPORT_SYMBOL_GPL(opal_message_notifier_register);
251322
....@@ -259,6 +330,23 @@
259330
260331 static void opal_message_do_notify(uint32_t msg_type, void *msg)
261332 {
333
+ unsigned long flags;
334
+ bool queued = false;
335
+
336
+ spin_lock_irqsave(&msg_list_lock, flags);
337
+ if (opal_msg_notifier_head[msg_type].head == NULL) {
338
+ /*
339
+ * Queue up the msg since no notifiers have registered
340
+ * yet for this msg_type.
341
+ */
342
+ queue_replay_msg(msg);
343
+ queued = true;
344
+ }
345
+ spin_unlock_irqrestore(&msg_list_lock, flags);
346
+
347
+ if (queued)
348
+ return;
349
+
262350 /* notify subscribers */
263351 atomic_notifier_call_chain(&opal_msg_notifier_head[msg_type],
264352 msg_type, msg);
....@@ -267,14 +355,9 @@
267355 static void opal_handle_message(void)
268356 {
269357 s64 ret;
270
- /*
271
- * TODO: pre-allocate a message buffer depending on opal-msg-size
272
- * value in /proc/device-tree.
273
- */
274
- static struct opal_msg msg;
275358 u32 type;
276359
277
- ret = opal_get_msg(__pa(&msg), sizeof(msg));
360
+ ret = opal_get_msg(__pa(opal_msg), opal_msg_size);
278361 /* No opal message pending. */
279362 if (ret == OPAL_RESOURCE)
280363 return;
....@@ -286,14 +369,14 @@
286369 return;
287370 }
288371
289
- type = be32_to_cpu(msg.msg_type);
372
+ type = be32_to_cpu(opal_msg->msg_type);
290373
291374 /* Sanity check */
292375 if (type >= OPAL_MSG_TYPE_MAX) {
293376 pr_warn_once("%s: Unknown message type: %u\n", __func__, type);
294377 return;
295378 }
296
- opal_message_do_notify(type, (void *)&msg);
379
+ opal_message_do_notify(type, (void *)opal_msg);
297380 }
298381
299382 static irqreturn_t opal_message_notify(int irq, void *data)
....@@ -302,9 +385,23 @@
302385 return IRQ_HANDLED;
303386 }
304387
305
-static int __init opal_message_init(void)
388
+static int __init opal_message_init(struct device_node *opal_node)
306389 {
307390 int ret, i, irq;
391
+
392
+ ret = of_property_read_u32(opal_node, "opal-msg-size", &opal_msg_size);
393
+ if (ret) {
394
+ pr_notice("Failed to read opal-msg-size property\n");
395
+ opal_msg_size = sizeof(struct opal_msg);
396
+ }
397
+
398
+ opal_msg = kmalloc(opal_msg_size, GFP_KERNEL);
399
+ if (!opal_msg) {
400
+ opal_msg_size = sizeof(struct opal_msg);
401
+ /* Try to allocate fixed message size */
402
+ opal_msg = kmalloc(opal_msg_size, GFP_KERNEL);
403
+ BUG_ON(opal_msg == NULL);
404
+ }
308405
309406 for (i = 0; i < OPAL_MSG_TYPE_MAX; i++)
310407 ATOMIC_INIT_NOTIFIER_HEAD(&opal_msg_notifier_head[i]);
....@@ -504,7 +601,7 @@
504601 recovered = 0;
505602 }
506603
507
- if (!recovered && evt->severity == MCE_SEV_ERROR_SYNC) {
604
+ if (!recovered && evt->sync_error) {
508605 /*
509606 * Try to kill processes if we get a synchronous machine check
510607 * (e.g., one caused by execution of this instruction). This
....@@ -535,7 +632,7 @@
535632 return recovered;
536633 }
537634
538
-void pnv_platform_error_reboot(struct pt_regs *regs, const char *msg)
635
+void __noreturn pnv_platform_error_reboot(struct pt_regs *regs, const char *msg)
539636 {
540637 panic_flush_kmsg_start();
541638
....@@ -587,7 +684,7 @@
587684 evt.version);
588685 return 0;
589686 }
590
- machine_check_print_event_info(&evt, user_mode(regs));
687
+ machine_check_print_event_info(&evt, user_mode(regs), false);
591688
592689 if (opal_recover_mce(regs, &evt))
593690 return 1;
....@@ -613,7 +710,28 @@
613710 return 0;
614711 }
615712
616
-/* HMI exception handler called in virtual mode during check_irq_replay. */
713
+int opal_hmi_exception_early2(struct pt_regs *regs)
714
+{
715
+ s64 rc;
716
+ __be64 out_flags;
717
+
718
+ /*
719
+ * call opal hmi handler.
720
+ * Check 64-bit flag mask to find out if an event was generated,
721
+ * and whether TB is still valid or not etc.
722
+ */
723
+ rc = opal_handle_hmi2(&out_flags);
724
+ if (rc != OPAL_SUCCESS)
725
+ return 0;
726
+
727
+ if (be64_to_cpu(out_flags) & OPAL_HMI_FLAGS_NEW_EVENT)
728
+ local_paca->hmi_event_available = 1;
729
+ if (be64_to_cpu(out_flags) & OPAL_HMI_FLAGS_TOD_TB_FAIL)
730
+ tb_invalid = true;
731
+ return 1;
732
+}
733
+
734
+/* HMI exception handler called in virtual mode when irqs are next enabled. */
617735 int opal_handle_hmi_exception(struct pt_regs *regs)
618736 {
619737 /*
....@@ -672,48 +790,85 @@
672790 return 0;
673791 }
674792
675
-static ssize_t symbol_map_read(struct file *fp, struct kobject *kobj,
676
- struct bin_attribute *bin_attr,
677
- char *buf, loff_t off, size_t count)
678
-{
679
- return memory_read_from_buffer(buf, count, &off, bin_attr->private,
680
- bin_attr->size);
681
-}
682
-
683
-static struct bin_attribute symbol_map_attr = {
684
- .attr = {.name = "symbol_map", .mode = 0400},
685
- .read = symbol_map_read
686
-};
687
-
688
-static void opal_export_symmap(void)
689
-{
690
- const __be64 *syms;
691
- unsigned int size;
692
- struct device_node *fw;
693
- int rc;
694
-
695
- fw = of_find_node_by_path("/ibm,opal/firmware");
696
- if (!fw)
697
- return;
698
- syms = of_get_property(fw, "symbol-map", &size);
699
- if (!syms || size != 2 * sizeof(__be64))
700
- return;
701
-
702
- /* Setup attributes */
703
- symbol_map_attr.private = __va(be64_to_cpu(syms[0]));
704
- symbol_map_attr.size = be64_to_cpu(syms[1]);
705
-
706
- rc = sysfs_create_bin_file(opal_kobj, &symbol_map_attr);
707
- if (rc)
708
- pr_warn("Error %d creating OPAL symbols file\n", rc);
709
-}
710
-
711793 static ssize_t export_attr_read(struct file *fp, struct kobject *kobj,
712794 struct bin_attribute *bin_attr, char *buf,
713795 loff_t off, size_t count)
714796 {
715797 return memory_read_from_buffer(buf, count, &off, bin_attr->private,
716798 bin_attr->size);
799
+}
800
+
801
+static int opal_add_one_export(struct kobject *parent, const char *export_name,
802
+ struct device_node *np, const char *prop_name)
803
+{
804
+ struct bin_attribute *attr = NULL;
805
+ const char *name = NULL;
806
+ u64 vals[2];
807
+ int rc;
808
+
809
+ rc = of_property_read_u64_array(np, prop_name, &vals[0], 2);
810
+ if (rc)
811
+ goto out;
812
+
813
+ attr = kzalloc(sizeof(*attr), GFP_KERNEL);
814
+ if (!attr) {
815
+ rc = -ENOMEM;
816
+ goto out;
817
+ }
818
+ name = kstrdup(export_name, GFP_KERNEL);
819
+ if (!name) {
820
+ rc = -ENOMEM;
821
+ goto out;
822
+ }
823
+
824
+ sysfs_bin_attr_init(attr);
825
+ attr->attr.name = name;
826
+ attr->attr.mode = 0400;
827
+ attr->read = export_attr_read;
828
+ attr->private = __va(vals[0]);
829
+ attr->size = vals[1];
830
+
831
+ rc = sysfs_create_bin_file(parent, attr);
832
+out:
833
+ if (rc) {
834
+ kfree(name);
835
+ kfree(attr);
836
+ }
837
+
838
+ return rc;
839
+}
840
+
841
+static void opal_add_exported_attrs(struct device_node *np,
842
+ struct kobject *kobj)
843
+{
844
+ struct device_node *child;
845
+ struct property *prop;
846
+
847
+ for_each_property_of_node(np, prop) {
848
+ int rc;
849
+
850
+ if (!strcmp(prop->name, "name") ||
851
+ !strcmp(prop->name, "phandle"))
852
+ continue;
853
+
854
+ rc = opal_add_one_export(kobj, prop->name, np, prop->name);
855
+ if (rc) {
856
+ pr_warn("Unable to add export %pOF/%s, rc = %d!\n",
857
+ np, prop->name, rc);
858
+ }
859
+ }
860
+
861
+ for_each_child_of_node(np, child) {
862
+ struct kobject *child_kobj;
863
+
864
+ child_kobj = kobject_create_and_add(child->name, kobj);
865
+ if (!child_kobj) {
866
+ pr_err("Unable to create export dir for %pOF\n", child);
867
+ continue;
868
+ }
869
+
870
+ opal_add_exported_attrs(child, child_kobj);
871
+ }
717872 }
718873
719874 /*
....@@ -725,11 +880,8 @@
725880 */
726881 static void opal_export_attrs(void)
727882 {
728
- struct bin_attribute *attr;
729883 struct device_node *np;
730
- struct property *prop;
731884 struct kobject *kobj;
732
- u64 vals[2];
733885 int rc;
734886
735887 np = of_find_node_by_path("/ibm,opal/firmware/exports");
....@@ -740,44 +892,20 @@
740892 kobj = kobject_create_and_add("exports", opal_kobj);
741893 if (!kobj) {
742894 pr_warn("kobject_create_and_add() of exports failed\n");
895
+ of_node_put(np);
743896 return;
744897 }
745898
746
- for_each_property_of_node(np, prop) {
747
- if (!strcmp(prop->name, "name") || !strcmp(prop->name, "phandle"))
748
- continue;
899
+ opal_add_exported_attrs(np, kobj);
749900
750
- if (of_property_read_u64_array(np, prop->name, &vals[0], 2))
751
- continue;
752
-
753
- attr = kzalloc(sizeof(*attr), GFP_KERNEL);
754
-
755
- if (attr == NULL) {
756
- pr_warn("Failed kmalloc for bin_attribute!");
757
- continue;
758
- }
759
-
760
- sysfs_bin_attr_init(attr);
761
- attr->attr.name = kstrdup(prop->name, GFP_KERNEL);
762
- attr->attr.mode = 0400;
763
- attr->read = export_attr_read;
764
- attr->private = __va(vals[0]);
765
- attr->size = vals[1];
766
-
767
- if (attr->attr.name == NULL) {
768
- pr_warn("Failed kstrdup for bin_attribute attr.name");
769
- kfree(attr);
770
- continue;
771
- }
772
-
773
- rc = sysfs_create_bin_file(kobj, attr);
774
- if (rc) {
775
- pr_warn("Error %d creating OPAL sysfs exports/%s file\n",
776
- rc, prop->name);
777
- kfree(attr->attr.name);
778
- kfree(attr);
779
- }
780
- }
901
+ /*
902
+ * NB: symbol_map existed before the generic export interface so it
903
+ * lives under the top level opal_kobj.
904
+ */
905
+ rc = opal_add_one_export(opal_kobj, "symbol_map",
906
+ np->parent, "symbol-map");
907
+ if (rc)
908
+ pr_warn("Error %d creating OPAL symbols file\n", rc);
781909
782910 of_node_put(np);
783911 }
....@@ -880,7 +1008,7 @@
8801008 consoles = of_find_node_by_path("/ibm,opal/consoles");
8811009 if (consoles) {
8821010 for_each_child_of_node(consoles, np) {
883
- if (strcmp(np->name, "serial"))
1011
+ if (!of_node_name_eq(np, "serial"))
8841012 continue;
8851013 of_platform_device_create(np, NULL, NULL);
8861014 }
....@@ -888,7 +1016,7 @@
8881016 }
8891017
8901018 /* Initialise OPAL messaging system */
891
- opal_message_init();
1019
+ opal_message_init(opal_node);
8921020
8931021 /* Initialise OPAL asynchronous completion interface */
8941022 opal_async_comp_init();
....@@ -924,8 +1052,6 @@
9241052 /* Create "opal" kobject under /sys/firmware */
9251053 rc = opal_sysfs_init();
9261054 if (rc == 0) {
927
- /* Export symbol map to userspace */
928
- opal_export_symmap();
9291055 /* Setup dump region interface */
9301056 opal_dump_region_init();
9311057 /* Setup error log interface */
....@@ -938,10 +1064,9 @@
9381064 opal_sys_param_init();
9391065 /* Setup message log sysfs interface. */
9401066 opal_msglog_sysfs_init();
1067
+ /* Add all export properties*/
1068
+ opal_export_attrs();
9411069 }
942
-
943
- /* Export all properties */
944
- opal_export_attrs();
9451070
9461071 /* Initialize platform devices: IPMI backend, PRD & flash interface */
9471072 opal_pdev_init("ibm,opal-ipmi");
....@@ -963,6 +1088,12 @@
9631088 /* Initialise OPAL sensor groups */
9641089 opal_sensor_groups_init();
9651090
1091
+ /* Initialise OPAL Power control interface */
1092
+ opal_power_control_init();
1093
+
1094
+ /* Initialize OPAL secure variables */
1095
+ opal_pdev_init("ibm,secvar-backend");
1096
+
9661097 return 0;
9671098 }
9681099 machine_subsys_initcall(powernv, opal_init);