1
2
3
4
5
6
7
8
9
10
11
12#define pr_fmt(fmt) "opal: " fmt
13
14#include <linux/printk.h>
15#include <linux/types.h>
16#include <linux/of.h>
17#include <linux/of_fdt.h>
18#include <linux/of_platform.h>
19#include <linux/interrupt.h>
20#include <linux/notifier.h>
21#include <linux/slab.h>
22#include <linux/sched.h>
23#include <linux/kobject.h>
24#include <linux/delay.h>
25#include <linux/memblock.h>
26#include <linux/kthread.h>
27#include <linux/freezer.h>
28
29#include <asm/machdep.h>
30#include <asm/opal.h>
31#include <asm/firmware.h>
32#include <asm/mce.h>
33
34#include "powernv.h"
35
36
37struct kobject *opal_kobj;
38
39struct opal {
40 u64 base;
41 u64 entry;
42 u64 size;
43} opal;
44
45struct mcheck_recoverable_range {
46 u64 start_addr;
47 u64 end_addr;
48 u64 recover_addr;
49};
50
51static struct mcheck_recoverable_range *mc_recoverable_range;
52static int mc_recoverable_range_len;
53
54struct device_node *opal_node;
55static DEFINE_SPINLOCK(opal_write_lock);
56static struct atomic_notifier_head opal_msg_notifier_head[OPAL_MSG_TYPE_MAX];
57static uint32_t opal_heartbeat;
58static struct task_struct *kopald_tsk;
59
60void opal_configure_cores(void)
61{
62
63
64
65
66
67
68#ifdef __BIG_ENDIAN__
69 opal_reinit_cpus(OPAL_REINIT_CPUS_HILE_BE);
70#else
71 opal_reinit_cpus(OPAL_REINIT_CPUS_HILE_LE);
72#endif
73
74
75 if (cur_cpu_spec->cpu_restore)
76 cur_cpu_spec->cpu_restore();
77}
78
79int __init early_init_dt_scan_opal(unsigned long node,
80 const char *uname, int depth, void *data)
81{
82 const void *basep, *entryp, *sizep;
83 int basesz, entrysz, runtimesz;
84
85 if (depth != 1 || strcmp(uname, "ibm,opal") != 0)
86 return 0;
87
88 basep = of_get_flat_dt_prop(node, "opal-base-address", &basesz);
89 entryp = of_get_flat_dt_prop(node, "opal-entry-address", &entrysz);
90 sizep = of_get_flat_dt_prop(node, "opal-runtime-size", &runtimesz);
91
92 if (!basep || !entryp || !sizep)
93 return 1;
94
95 opal.base = of_read_number(basep, basesz/4);
96 opal.entry = of_read_number(entryp, entrysz/4);
97 opal.size = of_read_number(sizep, runtimesz/4);
98
99 pr_debug("OPAL Base = 0x%llx (basep=%p basesz=%d)\n",
100 opal.base, basep, basesz);
101 pr_debug("OPAL Entry = 0x%llx (entryp=%p basesz=%d)\n",
102 opal.entry, entryp, entrysz);
103 pr_debug("OPAL Entry = 0x%llx (sizep=%p runtimesz=%d)\n",
104 opal.size, sizep, runtimesz);
105
106 if (of_flat_dt_is_compatible(node, "ibm,opal-v3")) {
107 powerpc_firmware_features |= FW_FEATURE_OPAL;
108 pr_info("OPAL detected !\n");
109 } else {
110 panic("OPAL != V3 detected, no longer supported.\n");
111 }
112
113 return 1;
114}
115
116int __init early_init_dt_scan_recoverable_ranges(unsigned long node,
117 const char *uname, int depth, void *data)
118{
119 int i, psize, size;
120 const __be32 *prop;
121
122 if (depth != 1 || strcmp(uname, "ibm,opal") != 0)
123 return 0;
124
125 prop = of_get_flat_dt_prop(node, "mcheck-recoverable-ranges", &psize);
126
127 if (!prop)
128 return 1;
129
130 pr_debug("Found machine check recoverable ranges.\n");
131
132
133
134
135
136
137
138
139 mc_recoverable_range_len = psize / (sizeof(*prop) * 5);
140
141
142 if (!mc_recoverable_range_len)
143 return 1;
144
145
146 size = mc_recoverable_range_len *
147 sizeof(struct mcheck_recoverable_range);
148
149
150
151
152
153
154 mc_recoverable_range =__va(memblock_alloc_base(size, __alignof__(u64),
155 ppc64_rma_size));
156 memset(mc_recoverable_range, 0, size);
157
158 for (i = 0; i < mc_recoverable_range_len; i++) {
159 mc_recoverable_range[i].start_addr =
160 of_read_number(prop + (i * 5) + 0, 2);
161 mc_recoverable_range[i].end_addr =
162 mc_recoverable_range[i].start_addr +
163 of_read_number(prop + (i * 5) + 2, 1);
164 mc_recoverable_range[i].recover_addr =
165 of_read_number(prop + (i * 5) + 3, 2);
166
167 pr_debug("Machine check recoverable range: %llx..%llx: %llx\n",
168 mc_recoverable_range[i].start_addr,
169 mc_recoverable_range[i].end_addr,
170 mc_recoverable_range[i].recover_addr);
171 }
172 return 1;
173}
174
175static int __init opal_register_exception_handlers(void)
176{
177#ifdef __BIG_ENDIAN__
178 u64 glue;
179
180 if (!(powerpc_firmware_features & FW_FEATURE_OPAL))
181 return -ENODEV;
182
183
184
185
186 glue = 0x7000;
187
188
189
190
191
192
193
194
195
196
197
198
199
200 if (!opal_check_token(OPAL_HANDLE_HMI)) {
201 pr_info("Old firmware detected, OPAL handles HMIs.\n");
202 opal_register_exception_handler(
203 OPAL_HYPERVISOR_MAINTENANCE_HANDLER,
204 0, glue);
205 glue += 128;
206 }
207
208 opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue);
209#endif
210
211 return 0;
212}
213machine_early_initcall(powernv, opal_register_exception_handlers);
214
215
216
217
218
219int opal_message_notifier_register(enum opal_msg_type msg_type,
220 struct notifier_block *nb)
221{
222 if (!nb || msg_type >= OPAL_MSG_TYPE_MAX) {
223 pr_warning("%s: Invalid arguments, msg_type:%d\n",
224 __func__, msg_type);
225 return -EINVAL;
226 }
227
228 return atomic_notifier_chain_register(
229 &opal_msg_notifier_head[msg_type], nb);
230}
231EXPORT_SYMBOL_GPL(opal_message_notifier_register);
232
233int opal_message_notifier_unregister(enum opal_msg_type msg_type,
234 struct notifier_block *nb)
235{
236 return atomic_notifier_chain_unregister(
237 &opal_msg_notifier_head[msg_type], nb);
238}
239EXPORT_SYMBOL_GPL(opal_message_notifier_unregister);
240
241static void opal_message_do_notify(uint32_t msg_type, void *msg)
242{
243
244 atomic_notifier_call_chain(&opal_msg_notifier_head[msg_type],
245 msg_type, msg);
246}
247
248static void opal_handle_message(void)
249{
250 s64 ret;
251
252
253
254
255 static struct opal_msg msg;
256 u32 type;
257
258 ret = opal_get_msg(__pa(&msg), sizeof(msg));
259
260 if (ret == OPAL_RESOURCE)
261 return;
262
263
264 if (ret) {
265 pr_warning("%s: Failed to retrieve opal message, err=%lld\n",
266 __func__, ret);
267 return;
268 }
269
270 type = be32_to_cpu(msg.msg_type);
271
272
273 if (type >= OPAL_MSG_TYPE_MAX) {
274 pr_warn_once("%s: Unknown message type: %u\n", __func__, type);
275 return;
276 }
277 opal_message_do_notify(type, (void *)&msg);
278}
279
280static irqreturn_t opal_message_notify(int irq, void *data)
281{
282 opal_handle_message();
283 return IRQ_HANDLED;
284}
285
286static int __init opal_message_init(void)
287{
288 int ret, i, irq;
289
290 for (i = 0; i < OPAL_MSG_TYPE_MAX; i++)
291 ATOMIC_INIT_NOTIFIER_HEAD(&opal_msg_notifier_head[i]);
292
293 irq = opal_event_request(ilog2(OPAL_EVENT_MSG_PENDING));
294 if (!irq) {
295 pr_err("%s: Can't register OPAL event irq (%d)\n",
296 __func__, irq);
297 return irq;
298 }
299
300 ret = request_irq(irq, opal_message_notify,
301 IRQ_TYPE_LEVEL_HIGH, "opal-msg", NULL);
302 if (ret) {
303 pr_err("%s: Can't request OPAL event irq (%d)\n",
304 __func__, ret);
305 return ret;
306 }
307
308 return 0;
309}
310
311int opal_get_chars(uint32_t vtermno, char *buf, int count)
312{
313 s64 rc;
314 __be64 evt, len;
315
316 if (!opal.entry)
317 return -ENODEV;
318 opal_poll_events(&evt);
319 if ((be64_to_cpu(evt) & OPAL_EVENT_CONSOLE_INPUT) == 0)
320 return 0;
321 len = cpu_to_be64(count);
322 rc = opal_console_read(vtermno, &len, buf);
323 if (rc == OPAL_SUCCESS)
324 return be64_to_cpu(len);
325 return 0;
326}
327
328int opal_put_chars(uint32_t vtermno, const char *data, int total_len)
329{
330 int written = 0;
331 __be64 olen;
332 s64 len, rc;
333 unsigned long flags;
334 __be64 evt;
335
336 if (!opal.entry)
337 return -ENODEV;
338
339
340
341
342
343
344
345
346
347 spin_lock_irqsave(&opal_write_lock, flags);
348 rc = opal_console_write_buffer_space(vtermno, &olen);
349 len = be64_to_cpu(olen);
350 if (rc || len < total_len) {
351 spin_unlock_irqrestore(&opal_write_lock, flags);
352
353 if (rc)
354 return total_len;
355 opal_poll_events(NULL);
356 return -EAGAIN;
357 }
358
359
360
361
362 rc = OPAL_BUSY;
363 while(total_len > 0 && (rc == OPAL_BUSY ||
364 rc == OPAL_BUSY_EVENT || rc == OPAL_SUCCESS)) {
365 olen = cpu_to_be64(total_len);
366 rc = opal_console_write(vtermno, &olen, data);
367 len = be64_to_cpu(olen);
368
369
370 if (rc != OPAL_SUCCESS && rc != OPAL_BUSY &&
371 rc != OPAL_BUSY_EVENT) {
372 written = total_len;
373 break;
374 }
375 if (rc == OPAL_SUCCESS) {
376 total_len -= len;
377 data += len;
378 written += len;
379 }
380
381
382
383
384
385 do
386 opal_poll_events(&evt);
387 while(rc == OPAL_SUCCESS &&
388 (be64_to_cpu(evt) & OPAL_EVENT_CONSOLE_OUTPUT));
389 }
390 spin_unlock_irqrestore(&opal_write_lock, flags);
391 return written;
392}
393
394static int opal_recover_mce(struct pt_regs *regs,
395 struct machine_check_event *evt)
396{
397 int recovered = 0;
398 uint64_t ea = get_mce_fault_addr(evt);
399
400 if (!(regs->msr & MSR_RI)) {
401
402 pr_err("Machine check interrupt unrecoverable: MSR(RI=0)\n");
403 recovered = 0;
404 } else if (evt->disposition == MCE_DISPOSITION_RECOVERED) {
405
406 recovered = 1;
407 } else if (ea && !is_kernel_addr(ea)) {
408
409
410
411
412
413
414
415
416 if (user_mode(regs) && !is_global_init(current)) {
417 _exception(SIGBUS, regs, BUS_MCEERR_AR, regs->nip);
418 recovered = 1;
419 } else
420 recovered = 0;
421 } else if (user_mode(regs) && !is_global_init(current) &&
422 evt->severity == MCE_SEV_ERROR_SYNC) {
423
424
425
426
427 _exception(SIGBUS, regs, BUS_MCEERR_AR, regs->nip);
428 recovered = 1;
429 }
430 return recovered;
431}
432
433int opal_machine_check(struct pt_regs *regs)
434{
435 struct machine_check_event evt;
436 int ret;
437
438 if (!get_mce_event(&evt, MCE_EVENT_RELEASE))
439 return 0;
440
441
442 if (evt.version != MCE_V1) {
443 pr_err("Machine Check Exception, Unknown event version %d !\n",
444 evt.version);
445 return 0;
446 }
447 machine_check_print_event_info(&evt);
448
449 if (opal_recover_mce(regs, &evt))
450 return 1;
451
452
453
454
455
456
457
458
459
460
461
462
463
464 ret = opal_cec_reboot2(OPAL_REBOOT_PLATFORM_ERROR,
465 "Unrecoverable Machine Check exception");
466 if (ret == OPAL_UNSUPPORTED) {
467 pr_emerg("Reboot type %d not supported\n",
468 OPAL_REBOOT_PLATFORM_ERROR);
469 }
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487 panic("PowerNV Unrecovered Machine Check");
488 return 0;
489}
490
491
492int opal_hmi_exception_early(struct pt_regs *regs)
493{
494 s64 rc;
495
496
497
498
499
500
501 rc = opal_handle_hmi();
502 if (rc == OPAL_SUCCESS) {
503 local_paca->hmi_event_available = 1;
504 return 1;
505 }
506 return 0;
507}
508
509
510int opal_handle_hmi_exception(struct pt_regs *regs)
511{
512 s64 rc;
513 __be64 evt = 0;
514
515
516
517
518
519
520 if (!local_paca->hmi_event_available)
521 return 0;
522
523 local_paca->hmi_event_available = 0;
524 rc = opal_poll_events(&evt);
525 if (rc == OPAL_SUCCESS && evt)
526 opal_handle_events(be64_to_cpu(evt));
527
528 return 1;
529}
530
531static uint64_t find_recovery_address(uint64_t nip)
532{
533 int i;
534
535 for (i = 0; i < mc_recoverable_range_len; i++)
536 if ((nip >= mc_recoverable_range[i].start_addr) &&
537 (nip < mc_recoverable_range[i].end_addr))
538 return mc_recoverable_range[i].recover_addr;
539 return 0;
540}
541
542bool opal_mce_check_early_recovery(struct pt_regs *regs)
543{
544 uint64_t recover_addr = 0;
545
546 if (!opal.base || !opal.size)
547 goto out;
548
549 if ((regs->nip >= opal.base) &&
550 (regs->nip < (opal.base + opal.size)))
551 recover_addr = find_recovery_address(regs->nip);
552
553
554
555
556 if (recover_addr)
557 regs->nip = recover_addr;
558
559out:
560 return !!recover_addr;
561}
562
563static int opal_sysfs_init(void)
564{
565 opal_kobj = kobject_create_and_add("opal", firmware_kobj);
566 if (!opal_kobj) {
567 pr_warn("kobject_create_and_add opal failed\n");
568 return -ENOMEM;
569 }
570
571 return 0;
572}
573
574static ssize_t symbol_map_read(struct file *fp, struct kobject *kobj,
575 struct bin_attribute *bin_attr,
576 char *buf, loff_t off, size_t count)
577{
578 return memory_read_from_buffer(buf, count, &off, bin_attr->private,
579 bin_attr->size);
580}
581
582static BIN_ATTR_RO(symbol_map, 0);
583
584static void opal_export_symmap(void)
585{
586 const __be64 *syms;
587 unsigned int size;
588 struct device_node *fw;
589 int rc;
590
591 fw = of_find_node_by_path("/ibm,opal/firmware");
592 if (!fw)
593 return;
594 syms = of_get_property(fw, "symbol-map", &size);
595 if (!syms || size != 2 * sizeof(__be64))
596 return;
597
598
599 bin_attr_symbol_map.private = __va(be64_to_cpu(syms[0]));
600 bin_attr_symbol_map.size = be64_to_cpu(syms[1]);
601
602 rc = sysfs_create_bin_file(opal_kobj, &bin_attr_symbol_map);
603 if (rc)
604 pr_warn("Error %d creating OPAL symbols file\n", rc);
605}
606
607static void __init opal_dump_region_init(void)
608{
609 void *addr;
610 uint64_t size;
611 int rc;
612
613 if (!opal_check_token(OPAL_REGISTER_DUMP_REGION))
614 return;
615
616
617 addr = log_buf_addr_get();
618 if (addr == NULL)
619 return;
620
621 size = log_buf_len_get();
622 if (size == 0)
623 return;
624
625 rc = opal_register_dump_region(OPAL_DUMP_REGION_LOG_BUF,
626 __pa(addr), size);
627
628
629
630 if (rc && rc != OPAL_UNSUPPORTED)
631 pr_warn("DUMP: Failed to register kernel log buffer. "
632 "rc = %d\n", rc);
633}
634
635static void opal_pdev_init(struct device_node *opal_node,
636 const char *compatible)
637{
638 struct device_node *np;
639
640 for_each_child_of_node(opal_node, np)
641 if (of_device_is_compatible(np, compatible))
642 of_platform_device_create(np, NULL, NULL);
643}
644
645static void opal_i2c_create_devs(void)
646{
647 struct device_node *np;
648
649 for_each_compatible_node(np, NULL, "ibm,opal-i2c")
650 of_platform_device_create(np, NULL, NULL);
651}
652
653static int kopald(void *unused)
654{
655 unsigned long timeout = msecs_to_jiffies(opal_heartbeat) + 1;
656 __be64 events;
657
658 set_freezable();
659 do {
660 try_to_freeze();
661 opal_poll_events(&events);
662 opal_handle_events(be64_to_cpu(events));
663 schedule_timeout_interruptible(timeout);
664 } while (!kthread_should_stop());
665
666 return 0;
667}
668
669void opal_wake_poller(void)
670{
671 if (kopald_tsk)
672 wake_up_process(kopald_tsk);
673}
674
675static void opal_init_heartbeat(void)
676{
677
678 if (of_property_read_u32(opal_node, "ibm,heartbeat-ms",
679 &opal_heartbeat) != 0)
680 opal_heartbeat = 0;
681
682 if (opal_heartbeat)
683 kopald_tsk = kthread_run(kopald, NULL, "kopald");
684}
685
686static int __init opal_init(void)
687{
688 struct device_node *np, *consoles, *leds;
689 int rc;
690
691 opal_node = of_find_node_by_path("/ibm,opal");
692 if (!opal_node) {
693 pr_warn("Device node not found\n");
694 return -ENODEV;
695 }
696
697
698 consoles = of_find_node_by_path("/ibm,opal/consoles");
699 if (consoles) {
700 for_each_child_of_node(consoles, np) {
701 if (strcmp(np->name, "serial"))
702 continue;
703 of_platform_device_create(np, NULL, NULL);
704 }
705 of_node_put(consoles);
706 }
707
708
709 opal_message_init();
710
711
712 opal_async_comp_init();
713
714
715 opal_sensor_init();
716
717
718 opal_hmi_handler_init();
719
720
721 opal_i2c_create_devs();
722
723
724 opal_init_heartbeat();
725
726
727 leds = of_find_node_by_path("/ibm,opal/leds");
728 if (leds) {
729 of_platform_device_create(leds, "opal_leds", NULL);
730 of_node_put(leds);
731 }
732
733
734 opal_msglog_init();
735
736
737 rc = opal_sysfs_init();
738 if (rc == 0) {
739
740 opal_export_symmap();
741
742 opal_dump_region_init();
743
744 rc = opal_elog_init();
745
746 opal_flash_update_init();
747
748 opal_platform_dump_init();
749
750 opal_sys_param_init();
751
752 opal_msglog_sysfs_init();
753 }
754
755
756 opal_pdev_init(opal_node, "ibm,opal-ipmi");
757 opal_pdev_init(opal_node, "ibm,opal-flash");
758 opal_pdev_init(opal_node, "ibm,opal-prd");
759
760
761 opal_pdev_init(opal_node, "ibm,opal-oppanel");
762
763
764 opal_kmsg_init();
765
766 return 0;
767}
768machine_subsys_initcall(powernv, opal_init);
769
770void opal_shutdown(void)
771{
772 long rc = OPAL_BUSY;
773
774 opal_event_shutdown();
775
776
777
778
779
780
781 while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
782 rc = opal_sync_host_reboot();
783 if (rc == OPAL_BUSY)
784 opal_poll_events(NULL);
785 else
786 mdelay(10);
787 }
788
789
790 if (opal_check_token(OPAL_UNREGISTER_DUMP_REGION))
791 opal_unregister_dump_region(OPAL_DUMP_REGION_LOG_BUF);
792}
793
794
795EXPORT_SYMBOL_GPL(opal_invalid_call);
796EXPORT_SYMBOL_GPL(opal_xscom_read);
797EXPORT_SYMBOL_GPL(opal_xscom_write);
798EXPORT_SYMBOL_GPL(opal_ipmi_send);
799EXPORT_SYMBOL_GPL(opal_ipmi_recv);
800EXPORT_SYMBOL_GPL(opal_flash_read);
801EXPORT_SYMBOL_GPL(opal_flash_write);
802EXPORT_SYMBOL_GPL(opal_flash_erase);
803EXPORT_SYMBOL_GPL(opal_prd_msg);
804
805
806struct opal_sg_list *opal_vmalloc_to_sg_list(void *vmalloc_addr,
807 unsigned long vmalloc_size)
808{
809 struct opal_sg_list *sg, *first = NULL;
810 unsigned long i = 0;
811
812 sg = kzalloc(PAGE_SIZE, GFP_KERNEL);
813 if (!sg)
814 goto nomem;
815
816 first = sg;
817
818 while (vmalloc_size > 0) {
819 uint64_t data = vmalloc_to_pfn(vmalloc_addr) << PAGE_SHIFT;
820 uint64_t length = min(vmalloc_size, PAGE_SIZE);
821
822 sg->entry[i].data = cpu_to_be64(data);
823 sg->entry[i].length = cpu_to_be64(length);
824 i++;
825
826 if (i >= SG_ENTRIES_PER_NODE) {
827 struct opal_sg_list *next;
828
829 next = kzalloc(PAGE_SIZE, GFP_KERNEL);
830 if (!next)
831 goto nomem;
832
833 sg->length = cpu_to_be64(
834 i * sizeof(struct opal_sg_entry) + 16);
835 i = 0;
836 sg->next = cpu_to_be64(__pa(next));
837 sg = next;
838 }
839
840 vmalloc_addr += length;
841 vmalloc_size -= length;
842 }
843
844 sg->length = cpu_to_be64(i * sizeof(struct opal_sg_entry) + 16);
845
846 return first;
847
848nomem:
849 pr_err("%s : Failed to allocate memory\n", __func__);
850 opal_free_sg_list(first);
851 return NULL;
852}
853
854void opal_free_sg_list(struct opal_sg_list *sg)
855{
856 while (sg) {
857 uint64_t next = be64_to_cpu(sg->next);
858
859 kfree(sg);
860
861 if (next)
862 sg = __va(next);
863 else
864 sg = NULL;
865 }
866}
867
868int opal_error_code(int rc)
869{
870 switch (rc) {
871 case OPAL_SUCCESS: return 0;
872
873 case OPAL_PARAMETER: return -EINVAL;
874 case OPAL_ASYNC_COMPLETION: return -EINPROGRESS;
875 case OPAL_BUSY_EVENT: return -EBUSY;
876 case OPAL_NO_MEM: return -ENOMEM;
877 case OPAL_PERMISSION: return -EPERM;
878
879 case OPAL_UNSUPPORTED: return -EIO;
880 case OPAL_HARDWARE: return -EIO;
881 case OPAL_INTERNAL_ERROR: return -EIO;
882 default:
883 pr_err("%s: unexpected OPAL error %d\n", __func__, rc);
884 return -EIO;
885 }
886}
887
888EXPORT_SYMBOL_GPL(opal_poll_events);
889EXPORT_SYMBOL_GPL(opal_rtc_read);
890EXPORT_SYMBOL_GPL(opal_rtc_write);
891EXPORT_SYMBOL_GPL(opal_tpo_read);
892EXPORT_SYMBOL_GPL(opal_tpo_write);
893EXPORT_SYMBOL_GPL(opal_i2c_request);
894
895EXPORT_SYMBOL_GPL(opal_leds_get_ind);
896EXPORT_SYMBOL_GPL(opal_leds_set_ind);
897
898EXPORT_SYMBOL_GPL(opal_write_oppanel_async);
899