This source file includes following definitions.
- get_new_element
- is_opalcore_usable
- append_elf64_note
- fill_prstatus
- auxv_to_elf64_notes
- read_opalcore
- opalcore_append_cpu_notes
- create_opalcore
- opalcore_cleanup
- opalcore_config_init
- fadump_release_opalcore_store
- opalcore_init
1
2
3
4
5
6
7
8
9 #define pr_fmt(fmt) "opal core: " fmt
10
11 #include <linux/memblock.h>
12 #include <linux/uaccess.h>
13 #include <linux/proc_fs.h>
14 #include <linux/elf.h>
15 #include <linux/elfcore.h>
16 #include <linux/kobject.h>
17 #include <linux/sysfs.h>
18 #include <linux/slab.h>
19 #include <linux/crash_core.h>
20 #include <linux/of.h>
21
22 #include <asm/page.h>
23 #include <asm/opal.h>
24 #include <asm/fadump-internal.h>
25
26 #include "opal-fadump.h"
27
28 #define MAX_PT_LOAD_CNT 8
29
30
31 #define AUXV_CNT 1
32 #define AUXV_DESC_SZ (((2 * AUXV_CNT) + 1) * sizeof(Elf64_Off))
33
34 struct opalcore_config {
35 u32 num_cpus;
36
37 u32 crashing_cpu;
38
39
40 u64 cpu_state_destination_vaddr;
41 u64 cpu_state_data_size;
42 u64 cpu_state_entry_size;
43
44
45 u64 ptload_addr[MAX_PT_LOAD_CNT];
46 u64 ptload_size[MAX_PT_LOAD_CNT];
47 u64 ptload_cnt;
48
49
50 Elf64_Phdr *ptload_phdr;
51
52
53 size_t opalcore_size;
54
55
56 size_t opalcorebuf_sz;
57 char *opalcorebuf;
58
59
60 char auxv_buf[AUXV_DESC_SZ];
61 };
62
63 struct opalcore {
64 struct list_head list;
65 u64 paddr;
66 size_t size;
67 loff_t offset;
68 };
69
70 static LIST_HEAD(opalcore_list);
71 static struct opalcore_config *oc_conf;
72 static const struct opal_mpipl_fadump *opalc_metadata;
73 static const struct opal_mpipl_fadump *opalc_cpu_metadata;
74
75
76
77
78
79 bool kernel_initiated;
80
81 static struct opalcore * __init get_new_element(void)
82 {
83 return kzalloc(sizeof(struct opalcore), GFP_KERNEL);
84 }
85
86 static inline int is_opalcore_usable(void)
87 {
88 return (oc_conf && oc_conf->opalcorebuf != NULL) ? 1 : 0;
89 }
90
91 static Elf64_Word *append_elf64_note(Elf64_Word *buf, char *name,
92 u32 type, void *data,
93 size_t data_len)
94 {
95 Elf64_Nhdr *note = (Elf64_Nhdr *)buf;
96 Elf64_Word namesz = strlen(name) + 1;
97
98 note->n_namesz = cpu_to_be32(namesz);
99 note->n_descsz = cpu_to_be32(data_len);
100 note->n_type = cpu_to_be32(type);
101 buf += DIV_ROUND_UP(sizeof(*note), sizeof(Elf64_Word));
102 memcpy(buf, name, namesz);
103 buf += DIV_ROUND_UP(namesz, sizeof(Elf64_Word));
104 memcpy(buf, data, data_len);
105 buf += DIV_ROUND_UP(data_len, sizeof(Elf64_Word));
106
107 return buf;
108 }
109
110 static void fill_prstatus(struct elf_prstatus *prstatus, int pir,
111 struct pt_regs *regs)
112 {
113 memset(prstatus, 0, sizeof(struct elf_prstatus));
114 elf_core_copy_kernel_regs(&(prstatus->pr_reg), regs);
115
116
117
118
119
120
121 prstatus->pr_pid = cpu_to_be32(100 + pir);
122 prstatus->pr_ppid = cpu_to_be32(1);
123
124
125
126
127
128 if (pir == oc_conf->crashing_cpu) {
129 short sig;
130
131 sig = kernel_initiated ? SIGUSR1 : SIGTERM;
132 prstatus->pr_cursig = cpu_to_be16(sig);
133 }
134 }
135
136 static Elf64_Word *auxv_to_elf64_notes(Elf64_Word *buf,
137 u64 opal_boot_entry)
138 {
139 Elf64_Off *bufp = (Elf64_Off *)oc_conf->auxv_buf;
140 int idx = 0;
141
142 memset(bufp, 0, AUXV_DESC_SZ);
143
144
145 bufp[idx++] = cpu_to_be64(AT_ENTRY);
146 bufp[idx++] = cpu_to_be64(opal_boot_entry);
147
148
149 bufp[idx++] = cpu_to_be64(AT_NULL);
150
151 buf = append_elf64_note(buf, CRASH_CORE_NOTE_NAME, NT_AUXV,
152 oc_conf->auxv_buf, AUXV_DESC_SZ);
153 return buf;
154 }
155
156
157
158
159
160 static ssize_t read_opalcore(struct file *file, struct kobject *kobj,
161 struct bin_attribute *bin_attr, char *to,
162 loff_t pos, size_t count)
163 {
164 struct opalcore *m;
165 ssize_t tsz, avail;
166 loff_t tpos = pos;
167
168 if (pos >= oc_conf->opalcore_size)
169 return 0;
170
171
172 avail = oc_conf->opalcore_size - pos;
173 if (count > avail)
174 count = avail;
175
176 if (count == 0)
177 return 0;
178
179
180 if (tpos < oc_conf->opalcorebuf_sz) {
181 tsz = min_t(size_t, oc_conf->opalcorebuf_sz - tpos, count);
182 memcpy(to, oc_conf->opalcorebuf + tpos, tsz);
183 to += tsz;
184 tpos += tsz;
185 count -= tsz;
186 }
187
188 list_for_each_entry(m, &opalcore_list, list) {
189
190 if (count == 0)
191 break;
192
193 if (tpos < m->offset + m->size) {
194 void *addr;
195
196 tsz = min_t(size_t, m->offset + m->size - tpos, count);
197 addr = (void *)(m->paddr + tpos - m->offset);
198 memcpy(to, __va(addr), tsz);
199 to += tsz;
200 tpos += tsz;
201 count -= tsz;
202 }
203 }
204
205 return (tpos - pos);
206 }
207
208 static struct bin_attribute opal_core_attr = {
209 .attr = {.name = "core", .mode = 0400},
210 .read = read_opalcore
211 };
212
213
214
215
216
217
218
219
220 static Elf64_Word * __init opalcore_append_cpu_notes(Elf64_Word *buf)
221 {
222 u32 thread_pir, size_per_thread, regs_offset, regs_cnt, reg_esize;
223 struct hdat_fadump_thread_hdr *thdr;
224 struct elf_prstatus prstatus;
225 Elf64_Word *first_cpu_note;
226 struct pt_regs regs;
227 char *bufp;
228 int i;
229
230 size_per_thread = oc_conf->cpu_state_entry_size;
231 bufp = __va(oc_conf->cpu_state_destination_vaddr);
232
233
234
235
236
237
238 thdr = (struct hdat_fadump_thread_hdr *)bufp;
239 regs_offset = (offsetof(struct hdat_fadump_thread_hdr, offset) +
240 be32_to_cpu(thdr->offset));
241 reg_esize = be32_to_cpu(thdr->esize);
242 regs_cnt = be32_to_cpu(thdr->ecnt);
243
244 pr_debug("--------CPU State Data------------\n");
245 pr_debug("NumCpus : %u\n", oc_conf->num_cpus);
246 pr_debug("\tOffset: %u, Entry size: %u, Cnt: %u\n",
247 regs_offset, reg_esize, regs_cnt);
248
249
250
251
252
253 first_cpu_note = buf;
254 buf = append_elf64_note(buf, CRASH_CORE_NOTE_NAME, NT_PRSTATUS,
255 &prstatus, sizeof(prstatus));
256
257 for (i = 0; i < oc_conf->num_cpus; i++, bufp += size_per_thread) {
258 thdr = (struct hdat_fadump_thread_hdr *)bufp;
259 thread_pir = be32_to_cpu(thdr->pir);
260
261 pr_debug("[%04d] PIR: 0x%x, core state: 0x%02x\n",
262 i, thread_pir, thdr->core_state);
263
264
265
266
267
268
269
270 if (thdr->core_state == HDAT_FADUMP_CORE_INACTIVE)
271 continue;
272
273 opal_fadump_read_regs((bufp + regs_offset), regs_cnt,
274 reg_esize, false, ®s);
275
276 pr_debug("PIR 0x%x - R1 : 0x%llx, NIP : 0x%llx\n", thread_pir,
277 be64_to_cpu(regs.gpr[1]), be64_to_cpu(regs.nip));
278 fill_prstatus(&prstatus, thread_pir, ®s);
279
280 if (thread_pir != oc_conf->crashing_cpu) {
281 buf = append_elf64_note(buf, CRASH_CORE_NOTE_NAME,
282 NT_PRSTATUS, &prstatus,
283 sizeof(prstatus));
284 } else {
285
286
287
288
289 append_elf64_note(first_cpu_note, CRASH_CORE_NOTE_NAME,
290 NT_PRSTATUS, &prstatus,
291 sizeof(prstatus));
292 }
293 }
294
295 return buf;
296 }
297
298 static int __init create_opalcore(void)
299 {
300 u64 opal_boot_entry, opal_base_addr, paddr;
301 u32 hdr_size, cpu_notes_size, count;
302 struct device_node *dn;
303 struct opalcore *new;
304 loff_t opalcore_off;
305 struct page *page;
306 Elf64_Phdr *phdr;
307 Elf64_Ehdr *elf;
308 int i, ret;
309 char *bufp;
310
311
312 hdr_size = (sizeof(Elf64_Ehdr) +
313 ((oc_conf->ptload_cnt + 1) * sizeof(Elf64_Phdr)));
314 cpu_notes_size = ((oc_conf->num_cpus * (CRASH_CORE_NOTE_HEAD_BYTES +
315 CRASH_CORE_NOTE_NAME_BYTES +
316 CRASH_CORE_NOTE_DESC_BYTES)) +
317 (CRASH_CORE_NOTE_HEAD_BYTES +
318 CRASH_CORE_NOTE_NAME_BYTES + AUXV_DESC_SZ));
319
320
321 oc_conf->opalcorebuf_sz = PAGE_ALIGN(hdr_size + cpu_notes_size);
322 oc_conf->opalcorebuf = alloc_pages_exact(oc_conf->opalcorebuf_sz,
323 GFP_KERNEL | __GFP_ZERO);
324 if (!oc_conf->opalcorebuf) {
325 pr_err("Not enough memory to setup OPAL core (size: %lu)\n",
326 oc_conf->opalcorebuf_sz);
327 oc_conf->opalcorebuf_sz = 0;
328 return -ENOMEM;
329 }
330 count = oc_conf->opalcorebuf_sz / PAGE_SIZE;
331 page = virt_to_page(oc_conf->opalcorebuf);
332 for (i = 0; i < count; i++)
333 mark_page_reserved(page + i);
334
335 pr_debug("opalcorebuf = 0x%llx\n", (u64)oc_conf->opalcorebuf);
336
337
338 dn = of_find_node_by_name(NULL, "ibm,opal");
339 if (dn) {
340 ret = of_property_read_u64(dn, "opal-base-address",
341 &opal_base_addr);
342 pr_debug("opal-base-address: %llx\n", opal_base_addr);
343 ret |= of_property_read_u64(dn, "opal-boot-address",
344 &opal_boot_entry);
345 pr_debug("opal-boot-address: %llx\n", opal_boot_entry);
346 }
347 if (!dn || ret)
348 pr_warn("WARNING: Failed to read OPAL base & entry values\n");
349
350
351 count = 0;
352
353 bufp = oc_conf->opalcorebuf;
354 elf = (Elf64_Ehdr *)bufp;
355 bufp += sizeof(Elf64_Ehdr);
356 memcpy(elf->e_ident, ELFMAG, SELFMAG);
357 elf->e_ident[EI_CLASS] = ELF_CLASS;
358 elf->e_ident[EI_DATA] = ELFDATA2MSB;
359 elf->e_ident[EI_VERSION] = EV_CURRENT;
360 elf->e_ident[EI_OSABI] = ELF_OSABI;
361 memset(elf->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD);
362 elf->e_type = cpu_to_be16(ET_CORE);
363 elf->e_machine = cpu_to_be16(ELF_ARCH);
364 elf->e_version = cpu_to_be32(EV_CURRENT);
365 elf->e_entry = 0;
366 elf->e_phoff = cpu_to_be64(sizeof(Elf64_Ehdr));
367 elf->e_shoff = 0;
368 elf->e_flags = 0;
369
370 elf->e_ehsize = cpu_to_be16(sizeof(Elf64_Ehdr));
371 elf->e_phentsize = cpu_to_be16(sizeof(Elf64_Phdr));
372 elf->e_phnum = 0;
373 elf->e_shentsize = 0;
374 elf->e_shnum = 0;
375 elf->e_shstrndx = 0;
376
377 phdr = (Elf64_Phdr *)bufp;
378 bufp += sizeof(Elf64_Phdr);
379 phdr->p_type = cpu_to_be32(PT_NOTE);
380 phdr->p_flags = 0;
381 phdr->p_align = 0;
382 phdr->p_paddr = phdr->p_vaddr = 0;
383 phdr->p_offset = cpu_to_be64(hdr_size);
384 phdr->p_filesz = phdr->p_memsz = cpu_to_be64(cpu_notes_size);
385 count++;
386
387 opalcore_off = oc_conf->opalcorebuf_sz;
388 oc_conf->ptload_phdr = (Elf64_Phdr *)bufp;
389 paddr = 0;
390 for (i = 0; i < oc_conf->ptload_cnt; i++) {
391 phdr = (Elf64_Phdr *)bufp;
392 bufp += sizeof(Elf64_Phdr);
393 phdr->p_type = cpu_to_be32(PT_LOAD);
394 phdr->p_flags = cpu_to_be32(PF_R|PF_W|PF_X);
395 phdr->p_align = 0;
396
397 new = get_new_element();
398 if (!new)
399 return -ENOMEM;
400 new->paddr = oc_conf->ptload_addr[i];
401 new->size = oc_conf->ptload_size[i];
402 new->offset = opalcore_off;
403 list_add_tail(&new->list, &opalcore_list);
404
405 phdr->p_paddr = cpu_to_be64(paddr);
406 phdr->p_vaddr = cpu_to_be64(opal_base_addr + paddr);
407 phdr->p_filesz = phdr->p_memsz =
408 cpu_to_be64(oc_conf->ptload_size[i]);
409 phdr->p_offset = cpu_to_be64(opalcore_off);
410
411 count++;
412 opalcore_off += oc_conf->ptload_size[i];
413 paddr += oc_conf->ptload_size[i];
414 }
415
416 elf->e_phnum = cpu_to_be16(count);
417
418 bufp = (char *)opalcore_append_cpu_notes((Elf64_Word *)bufp);
419 bufp = (char *)auxv_to_elf64_notes((Elf64_Word *)bufp, opal_boot_entry);
420
421 oc_conf->opalcore_size = opalcore_off;
422 return 0;
423 }
424
425 static void opalcore_cleanup(void)
426 {
427 if (oc_conf == NULL)
428 return;
429
430
431 sysfs_remove_bin_file(opal_kobj, &opal_core_attr);
432 oc_conf->ptload_phdr = NULL;
433 oc_conf->ptload_cnt = 0;
434
435
436 if (oc_conf->opalcorebuf) {
437 void *end = (void *)((u64)oc_conf->opalcorebuf +
438 oc_conf->opalcorebuf_sz);
439
440 free_reserved_area(oc_conf->opalcorebuf, end, -1, NULL);
441 oc_conf->opalcorebuf = NULL;
442 oc_conf->opalcorebuf_sz = 0;
443 }
444
445 kfree(oc_conf);
446 oc_conf = NULL;
447 }
448 __exitcall(opalcore_cleanup);
449
450 static void __init opalcore_config_init(void)
451 {
452 u32 idx, cpu_data_version;
453 struct device_node *np;
454 const __be32 *prop;
455 u64 addr = 0;
456 int i, ret;
457
458 np = of_find_node_by_path("/ibm,opal/dump");
459 if (np == NULL)
460 return;
461
462 if (!of_device_is_compatible(np, "ibm,opal-dump")) {
463 pr_warn("Support missing for this f/w version!\n");
464 return;
465 }
466
467
468 prop = of_get_property(np, "mpipl-boot", NULL);
469 if (!prop) {
470 of_node_put(np);
471 return;
472 }
473
474
475 ret = opal_mpipl_query_tag(OPAL_MPIPL_TAG_OPAL, &addr);
476 if ((ret != OPAL_SUCCESS) || !addr) {
477 pr_err("Failed to get OPAL metadata (%d)\n", ret);
478 goto error_out;
479 }
480
481 addr = be64_to_cpu(addr);
482 pr_debug("OPAL metadata addr: %llx\n", addr);
483 opalc_metadata = __va(addr);
484
485
486 ret = opal_mpipl_query_tag(OPAL_MPIPL_TAG_CPU, &addr);
487 if ((ret != OPAL_SUCCESS) || !addr) {
488 pr_err("Failed to get OPAL CPU metadata (%d)\n", ret);
489 goto error_out;
490 }
491
492 addr = be64_to_cpu(addr);
493 pr_debug("CPU metadata addr: %llx\n", addr);
494 opalc_cpu_metadata = __va(addr);
495
496
497 oc_conf = kzalloc(sizeof(struct opalcore_config), GFP_KERNEL);
498 if (oc_conf == NULL)
499 goto error_out;
500
501
502 if (opalc_metadata->version != OPAL_MPIPL_VERSION) {
503 pr_warn("Supported OPAL metadata version: %u, found: %u!\n",
504 OPAL_MPIPL_VERSION, opalc_metadata->version);
505 pr_warn("WARNING: F/W using newer OPAL metadata format!!\n");
506 }
507
508 oc_conf->ptload_cnt = 0;
509 idx = be32_to_cpu(opalc_metadata->region_cnt);
510 if (idx > MAX_PT_LOAD_CNT) {
511 pr_warn("WARNING: OPAL regions count (%d) adjusted to limit (%d)",
512 MAX_PT_LOAD_CNT, idx);
513 idx = MAX_PT_LOAD_CNT;
514 }
515 for (i = 0; i < idx; i++) {
516 oc_conf->ptload_addr[oc_conf->ptload_cnt] =
517 be64_to_cpu(opalc_metadata->region[i].dest);
518 oc_conf->ptload_size[oc_conf->ptload_cnt++] =
519 be64_to_cpu(opalc_metadata->region[i].size);
520 }
521 oc_conf->ptload_cnt = i;
522 oc_conf->crashing_cpu = be32_to_cpu(opalc_metadata->crashing_pir);
523
524 if (!oc_conf->ptload_cnt) {
525 pr_err("OPAL memory regions not found\n");
526 goto error_out;
527 }
528
529
530 cpu_data_version = be32_to_cpu(opalc_cpu_metadata->cpu_data_version);
531 if (cpu_data_version != HDAT_FADUMP_CPU_DATA_VER) {
532 pr_warn("Supported CPU data version: %u, found: %u!\n",
533 HDAT_FADUMP_CPU_DATA_VER, cpu_data_version);
534 pr_warn("WARNING: F/W using newer CPU state data format!!\n");
535 }
536
537 addr = be64_to_cpu(opalc_cpu_metadata->region[0].dest);
538 if (!addr) {
539 pr_err("CPU state data not found!\n");
540 goto error_out;
541 }
542 oc_conf->cpu_state_destination_vaddr = (u64)__va(addr);
543
544 oc_conf->cpu_state_data_size =
545 be64_to_cpu(opalc_cpu_metadata->region[0].size);
546 oc_conf->cpu_state_entry_size =
547 be32_to_cpu(opalc_cpu_metadata->cpu_data_size);
548
549 if ((oc_conf->cpu_state_entry_size == 0) ||
550 (oc_conf->cpu_state_entry_size > oc_conf->cpu_state_data_size)) {
551 pr_err("CPU state data is invalid.\n");
552 goto error_out;
553 }
554 oc_conf->num_cpus = (oc_conf->cpu_state_data_size /
555 oc_conf->cpu_state_entry_size);
556
557 of_node_put(np);
558 return;
559
560 error_out:
561 pr_err("Could not export /sys/firmware/opal/core\n");
562 opalcore_cleanup();
563 of_node_put(np);
564 }
565
566 static ssize_t fadump_release_opalcore_store(struct kobject *kobj,
567 struct kobj_attribute *attr,
568 const char *buf, size_t count)
569 {
570 int input = -1;
571
572 if (kstrtoint(buf, 0, &input))
573 return -EINVAL;
574
575 if (input == 1) {
576 if (oc_conf == NULL) {
577 pr_err("'/sys/firmware/opal/core' file not accessible!\n");
578 return -EPERM;
579 }
580
581
582
583
584
585 opalcore_cleanup();
586 } else
587 return -EINVAL;
588
589 return count;
590 }
591
592 static struct kobj_attribute opalcore_rel_attr = __ATTR(fadump_release_opalcore,
593 0200, NULL,
594 fadump_release_opalcore_store);
595
596 static int __init opalcore_init(void)
597 {
598 int rc = -1;
599
600 opalcore_config_init();
601
602 if (oc_conf == NULL)
603 return rc;
604
605 create_opalcore();
606
607
608
609
610
611 if (!(is_opalcore_usable())) {
612 pr_err("Failed to export /sys/firmware/opal/core\n");
613 opalcore_cleanup();
614 return rc;
615 }
616
617
618 opal_core_attr.size = oc_conf->opalcore_size;
619
620
621 rc = sysfs_create_bin_file(opal_kobj, &opal_core_attr);
622 if (rc != 0) {
623 pr_err("Failed to export /sys/firmware/opal/core\n");
624 opalcore_cleanup();
625 return rc;
626 }
627
628 rc = sysfs_create_file(kernel_kobj, &opalcore_rel_attr.attr);
629 if (rc) {
630 pr_warn("unable to create sysfs file fadump_release_opalcore (%d)\n",
631 rc);
632 }
633
634 return 0;
635 }
636 fs_initcall(opalcore_init);