0001
0002
0003
0004
0005
0006
0007
0008
0009 #define pr_fmt(fmt) "opal core: " fmt
0010
0011 #include <linux/memblock.h>
0012 #include <linux/uaccess.h>
0013 #include <linux/proc_fs.h>
0014 #include <linux/elf.h>
0015 #include <linux/elfcore.h>
0016 #include <linux/kobject.h>
0017 #include <linux/sysfs.h>
0018 #include <linux/slab.h>
0019 #include <linux/crash_core.h>
0020 #include <linux/of.h>
0021
0022 #include <asm/page.h>
0023 #include <asm/opal.h>
0024 #include <asm/fadump-internal.h>
0025
0026 #include "opal-fadump.h"
0027
0028 #define MAX_PT_LOAD_CNT 8
0029
0030
0031 #define AUXV_CNT 1
0032 #define AUXV_DESC_SZ (((2 * AUXV_CNT) + 1) * sizeof(Elf64_Off))
0033
0034 struct opalcore_config {
0035 u32 num_cpus;
0036
0037 u32 crashing_cpu;
0038
0039
0040 u64 cpu_state_destination_vaddr;
0041 u64 cpu_state_data_size;
0042 u64 cpu_state_entry_size;
0043
0044
0045 u64 ptload_addr[MAX_PT_LOAD_CNT];
0046 u64 ptload_size[MAX_PT_LOAD_CNT];
0047 u64 ptload_cnt;
0048
0049
0050 Elf64_Phdr *ptload_phdr;
0051
0052
0053 size_t opalcore_size;
0054
0055
0056 size_t opalcorebuf_sz;
0057 char *opalcorebuf;
0058
0059
0060 char auxv_buf[AUXV_DESC_SZ];
0061 };
0062
0063 struct opalcore {
0064 struct list_head list;
0065 u64 paddr;
0066 size_t size;
0067 loff_t offset;
0068 };
0069
0070 static LIST_HEAD(opalcore_list);
0071 static struct opalcore_config *oc_conf;
0072 static const struct opal_mpipl_fadump *opalc_metadata;
0073 static const struct opal_mpipl_fadump *opalc_cpu_metadata;
0074 static struct kobject *mpipl_kobj;
0075
0076
0077
0078
0079
0080 bool kernel_initiated;
0081
0082 static struct opalcore * __init get_new_element(void)
0083 {
0084 return kzalloc(sizeof(struct opalcore), GFP_KERNEL);
0085 }
0086
0087 static inline int is_opalcore_usable(void)
0088 {
0089 return (oc_conf && oc_conf->opalcorebuf != NULL) ? 1 : 0;
0090 }
0091
0092 static Elf64_Word *__init append_elf64_note(Elf64_Word *buf, char *name,
0093 u32 type, void *data,
0094 size_t data_len)
0095 {
0096 Elf64_Nhdr *note = (Elf64_Nhdr *)buf;
0097 Elf64_Word namesz = strlen(name) + 1;
0098
0099 note->n_namesz = cpu_to_be32(namesz);
0100 note->n_descsz = cpu_to_be32(data_len);
0101 note->n_type = cpu_to_be32(type);
0102 buf += DIV_ROUND_UP(sizeof(*note), sizeof(Elf64_Word));
0103 memcpy(buf, name, namesz);
0104 buf += DIV_ROUND_UP(namesz, sizeof(Elf64_Word));
0105 memcpy(buf, data, data_len);
0106 buf += DIV_ROUND_UP(data_len, sizeof(Elf64_Word));
0107
0108 return buf;
0109 }
0110
0111 static void __init fill_prstatus(struct elf_prstatus *prstatus, int pir,
0112 struct pt_regs *regs)
0113 {
0114 memset(prstatus, 0, sizeof(struct elf_prstatus));
0115 elf_core_copy_regs(&(prstatus->pr_reg), regs);
0116
0117
0118
0119
0120
0121
0122 prstatus->common.pr_pid = cpu_to_be32(100 + pir);
0123 prstatus->common.pr_ppid = cpu_to_be32(1);
0124
0125
0126
0127
0128
0129 if (pir == oc_conf->crashing_cpu) {
0130 short sig;
0131
0132 sig = kernel_initiated ? SIGUSR1 : SIGTERM;
0133 prstatus->common.pr_cursig = cpu_to_be16(sig);
0134 }
0135 }
0136
0137 static Elf64_Word *__init auxv_to_elf64_notes(Elf64_Word *buf,
0138 u64 opal_boot_entry)
0139 {
0140 Elf64_Off *bufp = (Elf64_Off *)oc_conf->auxv_buf;
0141 int idx = 0;
0142
0143 memset(bufp, 0, AUXV_DESC_SZ);
0144
0145
0146 bufp[idx++] = cpu_to_be64(AT_ENTRY);
0147 bufp[idx++] = cpu_to_be64(opal_boot_entry);
0148
0149
0150 bufp[idx++] = cpu_to_be64(AT_NULL);
0151
0152 buf = append_elf64_note(buf, CRASH_CORE_NOTE_NAME, NT_AUXV,
0153 oc_conf->auxv_buf, AUXV_DESC_SZ);
0154 return buf;
0155 }
0156
0157
0158
0159
0160
0161 static ssize_t read_opalcore(struct file *file, struct kobject *kobj,
0162 struct bin_attribute *bin_attr, char *to,
0163 loff_t pos, size_t count)
0164 {
0165 struct opalcore *m;
0166 ssize_t tsz, avail;
0167 loff_t tpos = pos;
0168
0169 if (pos >= oc_conf->opalcore_size)
0170 return 0;
0171
0172
0173 avail = oc_conf->opalcore_size - pos;
0174 if (count > avail)
0175 count = avail;
0176
0177 if (count == 0)
0178 return 0;
0179
0180
0181 if (tpos < oc_conf->opalcorebuf_sz) {
0182 tsz = min_t(size_t, oc_conf->opalcorebuf_sz - tpos, count);
0183 memcpy(to, oc_conf->opalcorebuf + tpos, tsz);
0184 to += tsz;
0185 tpos += tsz;
0186 count -= tsz;
0187 }
0188
0189 list_for_each_entry(m, &opalcore_list, list) {
0190
0191 if (count == 0)
0192 break;
0193
0194 if (tpos < m->offset + m->size) {
0195 void *addr;
0196
0197 tsz = min_t(size_t, m->offset + m->size - tpos, count);
0198 addr = (void *)(m->paddr + tpos - m->offset);
0199 memcpy(to, __va(addr), tsz);
0200 to += tsz;
0201 tpos += tsz;
0202 count -= tsz;
0203 }
0204 }
0205
0206 return (tpos - pos);
0207 }
0208
0209 static struct bin_attribute opal_core_attr = {
0210 .attr = {.name = "core", .mode = 0400},
0211 .read = read_opalcore
0212 };
0213
0214
0215
0216
0217
0218
0219
0220
0221 static Elf64_Word * __init opalcore_append_cpu_notes(Elf64_Word *buf)
0222 {
0223 u32 thread_pir, size_per_thread, regs_offset, regs_cnt, reg_esize;
0224 struct hdat_fadump_thread_hdr *thdr;
0225 struct elf_prstatus prstatus;
0226 Elf64_Word *first_cpu_note;
0227 struct pt_regs regs;
0228 char *bufp;
0229 int i;
0230
0231 size_per_thread = oc_conf->cpu_state_entry_size;
0232 bufp = __va(oc_conf->cpu_state_destination_vaddr);
0233
0234
0235
0236
0237
0238
0239 thdr = (struct hdat_fadump_thread_hdr *)bufp;
0240 regs_offset = (offsetof(struct hdat_fadump_thread_hdr, offset) +
0241 be32_to_cpu(thdr->offset));
0242 reg_esize = be32_to_cpu(thdr->esize);
0243 regs_cnt = be32_to_cpu(thdr->ecnt);
0244
0245 pr_debug("--------CPU State Data------------\n");
0246 pr_debug("NumCpus : %u\n", oc_conf->num_cpus);
0247 pr_debug("\tOffset: %u, Entry size: %u, Cnt: %u\n",
0248 regs_offset, reg_esize, regs_cnt);
0249
0250
0251
0252
0253
0254 first_cpu_note = buf;
0255 buf = append_elf64_note(buf, CRASH_CORE_NOTE_NAME, NT_PRSTATUS,
0256 &prstatus, sizeof(prstatus));
0257
0258 for (i = 0; i < oc_conf->num_cpus; i++, bufp += size_per_thread) {
0259 thdr = (struct hdat_fadump_thread_hdr *)bufp;
0260 thread_pir = be32_to_cpu(thdr->pir);
0261
0262 pr_debug("[%04d] PIR: 0x%x, core state: 0x%02x\n",
0263 i, thread_pir, thdr->core_state);
0264
0265
0266
0267
0268
0269
0270
0271 if (thdr->core_state == HDAT_FADUMP_CORE_INACTIVE)
0272 continue;
0273
0274 opal_fadump_read_regs((bufp + regs_offset), regs_cnt,
0275 reg_esize, false, ®s);
0276
0277 pr_debug("PIR 0x%x - R1 : 0x%llx, NIP : 0x%llx\n", thread_pir,
0278 be64_to_cpu(regs.gpr[1]), be64_to_cpu(regs.nip));
0279 fill_prstatus(&prstatus, thread_pir, ®s);
0280
0281 if (thread_pir != oc_conf->crashing_cpu) {
0282 buf = append_elf64_note(buf, CRASH_CORE_NOTE_NAME,
0283 NT_PRSTATUS, &prstatus,
0284 sizeof(prstatus));
0285 } else {
0286
0287
0288
0289
0290 append_elf64_note(first_cpu_note, CRASH_CORE_NOTE_NAME,
0291 NT_PRSTATUS, &prstatus,
0292 sizeof(prstatus));
0293 }
0294 }
0295
0296 return buf;
0297 }
0298
0299 static int __init create_opalcore(void)
0300 {
0301 u64 opal_boot_entry, opal_base_addr, paddr;
0302 u32 hdr_size, cpu_notes_size, count;
0303 struct device_node *dn;
0304 struct opalcore *new;
0305 loff_t opalcore_off;
0306 struct page *page;
0307 Elf64_Phdr *phdr;
0308 Elf64_Ehdr *elf;
0309 int i, ret;
0310 char *bufp;
0311
0312
0313 hdr_size = (sizeof(Elf64_Ehdr) +
0314 ((oc_conf->ptload_cnt + 1) * sizeof(Elf64_Phdr)));
0315 cpu_notes_size = ((oc_conf->num_cpus * (CRASH_CORE_NOTE_HEAD_BYTES +
0316 CRASH_CORE_NOTE_NAME_BYTES +
0317 CRASH_CORE_NOTE_DESC_BYTES)) +
0318 (CRASH_CORE_NOTE_HEAD_BYTES +
0319 CRASH_CORE_NOTE_NAME_BYTES + AUXV_DESC_SZ));
0320
0321
0322 oc_conf->opalcorebuf_sz = PAGE_ALIGN(hdr_size + cpu_notes_size);
0323 oc_conf->opalcorebuf = alloc_pages_exact(oc_conf->opalcorebuf_sz,
0324 GFP_KERNEL | __GFP_ZERO);
0325 if (!oc_conf->opalcorebuf) {
0326 pr_err("Not enough memory to setup OPAL core (size: %lu)\n",
0327 oc_conf->opalcorebuf_sz);
0328 oc_conf->opalcorebuf_sz = 0;
0329 return -ENOMEM;
0330 }
0331 count = oc_conf->opalcorebuf_sz / PAGE_SIZE;
0332 page = virt_to_page(oc_conf->opalcorebuf);
0333 for (i = 0; i < count; i++)
0334 mark_page_reserved(page + i);
0335
0336 pr_debug("opalcorebuf = 0x%llx\n", (u64)oc_conf->opalcorebuf);
0337
0338
0339 dn = of_find_node_by_name(NULL, "ibm,opal");
0340 if (dn) {
0341 ret = of_property_read_u64(dn, "opal-base-address",
0342 &opal_base_addr);
0343 pr_debug("opal-base-address: %llx\n", opal_base_addr);
0344 ret |= of_property_read_u64(dn, "opal-boot-address",
0345 &opal_boot_entry);
0346 pr_debug("opal-boot-address: %llx\n", opal_boot_entry);
0347 }
0348 if (!dn || ret)
0349 pr_warn("WARNING: Failed to read OPAL base & entry values\n");
0350
0351
0352 count = 0;
0353
0354 bufp = oc_conf->opalcorebuf;
0355 elf = (Elf64_Ehdr *)bufp;
0356 bufp += sizeof(Elf64_Ehdr);
0357 memcpy(elf->e_ident, ELFMAG, SELFMAG);
0358 elf->e_ident[EI_CLASS] = ELF_CLASS;
0359 elf->e_ident[EI_DATA] = ELFDATA2MSB;
0360 elf->e_ident[EI_VERSION] = EV_CURRENT;
0361 elf->e_ident[EI_OSABI] = ELF_OSABI;
0362 memset(elf->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD);
0363 elf->e_type = cpu_to_be16(ET_CORE);
0364 elf->e_machine = cpu_to_be16(ELF_ARCH);
0365 elf->e_version = cpu_to_be32(EV_CURRENT);
0366 elf->e_entry = 0;
0367 elf->e_phoff = cpu_to_be64(sizeof(Elf64_Ehdr));
0368 elf->e_shoff = 0;
0369 elf->e_flags = 0;
0370
0371 elf->e_ehsize = cpu_to_be16(sizeof(Elf64_Ehdr));
0372 elf->e_phentsize = cpu_to_be16(sizeof(Elf64_Phdr));
0373 elf->e_phnum = 0;
0374 elf->e_shentsize = 0;
0375 elf->e_shnum = 0;
0376 elf->e_shstrndx = 0;
0377
0378 phdr = (Elf64_Phdr *)bufp;
0379 bufp += sizeof(Elf64_Phdr);
0380 phdr->p_type = cpu_to_be32(PT_NOTE);
0381 phdr->p_flags = 0;
0382 phdr->p_align = 0;
0383 phdr->p_paddr = phdr->p_vaddr = 0;
0384 phdr->p_offset = cpu_to_be64(hdr_size);
0385 phdr->p_filesz = phdr->p_memsz = cpu_to_be64(cpu_notes_size);
0386 count++;
0387
0388 opalcore_off = oc_conf->opalcorebuf_sz;
0389 oc_conf->ptload_phdr = (Elf64_Phdr *)bufp;
0390 paddr = 0;
0391 for (i = 0; i < oc_conf->ptload_cnt; i++) {
0392 phdr = (Elf64_Phdr *)bufp;
0393 bufp += sizeof(Elf64_Phdr);
0394 phdr->p_type = cpu_to_be32(PT_LOAD);
0395 phdr->p_flags = cpu_to_be32(PF_R|PF_W|PF_X);
0396 phdr->p_align = 0;
0397
0398 new = get_new_element();
0399 if (!new)
0400 return -ENOMEM;
0401 new->paddr = oc_conf->ptload_addr[i];
0402 new->size = oc_conf->ptload_size[i];
0403 new->offset = opalcore_off;
0404 list_add_tail(&new->list, &opalcore_list);
0405
0406 phdr->p_paddr = cpu_to_be64(paddr);
0407 phdr->p_vaddr = cpu_to_be64(opal_base_addr + paddr);
0408 phdr->p_filesz = phdr->p_memsz =
0409 cpu_to_be64(oc_conf->ptload_size[i]);
0410 phdr->p_offset = cpu_to_be64(opalcore_off);
0411
0412 count++;
0413 opalcore_off += oc_conf->ptload_size[i];
0414 paddr += oc_conf->ptload_size[i];
0415 }
0416
0417 elf->e_phnum = cpu_to_be16(count);
0418
0419 bufp = (char *)opalcore_append_cpu_notes((Elf64_Word *)bufp);
0420 bufp = (char *)auxv_to_elf64_notes((Elf64_Word *)bufp, opal_boot_entry);
0421
0422 oc_conf->opalcore_size = opalcore_off;
0423 return 0;
0424 }
0425
0426 static void opalcore_cleanup(void)
0427 {
0428 if (oc_conf == NULL)
0429 return;
0430
0431
0432 sysfs_remove_bin_file(mpipl_kobj, &opal_core_attr);
0433 oc_conf->ptload_phdr = NULL;
0434 oc_conf->ptload_cnt = 0;
0435
0436
0437 if (oc_conf->opalcorebuf) {
0438 void *end = (void *)((u64)oc_conf->opalcorebuf +
0439 oc_conf->opalcorebuf_sz);
0440
0441 free_reserved_area(oc_conf->opalcorebuf, end, -1, NULL);
0442 oc_conf->opalcorebuf = NULL;
0443 oc_conf->opalcorebuf_sz = 0;
0444 }
0445
0446 kfree(oc_conf);
0447 oc_conf = NULL;
0448 }
0449 __exitcall(opalcore_cleanup);
0450
0451 static void __init opalcore_config_init(void)
0452 {
0453 u32 idx, cpu_data_version;
0454 struct device_node *np;
0455 const __be32 *prop;
0456 u64 addr = 0;
0457 int i, ret;
0458
0459 np = of_find_node_by_path("/ibm,opal/dump");
0460 if (np == NULL)
0461 return;
0462
0463 if (!of_device_is_compatible(np, "ibm,opal-dump")) {
0464 pr_warn("Support missing for this f/w version!\n");
0465 return;
0466 }
0467
0468
0469 prop = of_get_property(np, "mpipl-boot", NULL);
0470 if (!prop) {
0471 of_node_put(np);
0472 return;
0473 }
0474
0475
0476 ret = opal_mpipl_query_tag(OPAL_MPIPL_TAG_OPAL, &addr);
0477 if ((ret != OPAL_SUCCESS) || !addr) {
0478 pr_err("Failed to get OPAL metadata (%d)\n", ret);
0479 goto error_out;
0480 }
0481
0482 addr = be64_to_cpu(addr);
0483 pr_debug("OPAL metadata addr: %llx\n", addr);
0484 opalc_metadata = __va(addr);
0485
0486
0487 ret = opal_mpipl_query_tag(OPAL_MPIPL_TAG_CPU, &addr);
0488 if ((ret != OPAL_SUCCESS) || !addr) {
0489 pr_err("Failed to get OPAL CPU metadata (%d)\n", ret);
0490 goto error_out;
0491 }
0492
0493 addr = be64_to_cpu(addr);
0494 pr_debug("CPU metadata addr: %llx\n", addr);
0495 opalc_cpu_metadata = __va(addr);
0496
0497
0498 oc_conf = kzalloc(sizeof(struct opalcore_config), GFP_KERNEL);
0499 if (oc_conf == NULL)
0500 goto error_out;
0501
0502
0503 if (opalc_metadata->version != OPAL_MPIPL_VERSION) {
0504 pr_warn("Supported OPAL metadata version: %u, found: %u!\n",
0505 OPAL_MPIPL_VERSION, opalc_metadata->version);
0506 pr_warn("WARNING: F/W using newer OPAL metadata format!!\n");
0507 }
0508
0509 oc_conf->ptload_cnt = 0;
0510 idx = be32_to_cpu(opalc_metadata->region_cnt);
0511 if (idx > MAX_PT_LOAD_CNT) {
0512 pr_warn("WARNING: OPAL regions count (%d) adjusted to limit (%d)",
0513 idx, MAX_PT_LOAD_CNT);
0514 idx = MAX_PT_LOAD_CNT;
0515 }
0516 for (i = 0; i < idx; i++) {
0517 oc_conf->ptload_addr[oc_conf->ptload_cnt] =
0518 be64_to_cpu(opalc_metadata->region[i].dest);
0519 oc_conf->ptload_size[oc_conf->ptload_cnt++] =
0520 be64_to_cpu(opalc_metadata->region[i].size);
0521 }
0522 oc_conf->ptload_cnt = i;
0523 oc_conf->crashing_cpu = be32_to_cpu(opalc_metadata->crashing_pir);
0524
0525 if (!oc_conf->ptload_cnt) {
0526 pr_err("OPAL memory regions not found\n");
0527 goto error_out;
0528 }
0529
0530
0531 cpu_data_version = be32_to_cpu(opalc_cpu_metadata->cpu_data_version);
0532 if (cpu_data_version != HDAT_FADUMP_CPU_DATA_VER) {
0533 pr_warn("Supported CPU data version: %u, found: %u!\n",
0534 HDAT_FADUMP_CPU_DATA_VER, cpu_data_version);
0535 pr_warn("WARNING: F/W using newer CPU state data format!!\n");
0536 }
0537
0538 addr = be64_to_cpu(opalc_cpu_metadata->region[0].dest);
0539 if (!addr) {
0540 pr_err("CPU state data not found!\n");
0541 goto error_out;
0542 }
0543 oc_conf->cpu_state_destination_vaddr = (u64)__va(addr);
0544
0545 oc_conf->cpu_state_data_size =
0546 be64_to_cpu(opalc_cpu_metadata->region[0].size);
0547 oc_conf->cpu_state_entry_size =
0548 be32_to_cpu(opalc_cpu_metadata->cpu_data_size);
0549
0550 if ((oc_conf->cpu_state_entry_size == 0) ||
0551 (oc_conf->cpu_state_entry_size > oc_conf->cpu_state_data_size)) {
0552 pr_err("CPU state data is invalid.\n");
0553 goto error_out;
0554 }
0555 oc_conf->num_cpus = (oc_conf->cpu_state_data_size /
0556 oc_conf->cpu_state_entry_size);
0557
0558 of_node_put(np);
0559 return;
0560
0561 error_out:
0562 pr_err("Could not export /sys/firmware/opal/core\n");
0563 opalcore_cleanup();
0564 of_node_put(np);
0565 }
0566
0567 static ssize_t release_core_store(struct kobject *kobj,
0568 struct kobj_attribute *attr,
0569 const char *buf, size_t count)
0570 {
0571 int input = -1;
0572
0573 if (kstrtoint(buf, 0, &input))
0574 return -EINVAL;
0575
0576 if (input == 1) {
0577 if (oc_conf == NULL) {
0578 pr_err("'/sys/firmware/opal/core' file not accessible!\n");
0579 return -EPERM;
0580 }
0581
0582
0583
0584
0585
0586 opalcore_cleanup();
0587 } else
0588 return -EINVAL;
0589
0590 return count;
0591 }
0592
0593 static struct kobj_attribute opalcore_rel_attr = __ATTR_WO(release_core);
0594
0595 static struct attribute *mpipl_attr[] = {
0596 &opalcore_rel_attr.attr,
0597 NULL,
0598 };
0599
0600 static struct bin_attribute *mpipl_bin_attr[] = {
0601 &opal_core_attr,
0602 NULL,
0603
0604 };
0605
0606 static const struct attribute_group mpipl_group = {
0607 .attrs = mpipl_attr,
0608 .bin_attrs = mpipl_bin_attr,
0609 };
0610
0611 static int __init opalcore_init(void)
0612 {
0613 int rc = -1;
0614
0615 opalcore_config_init();
0616
0617 if (oc_conf == NULL)
0618 return rc;
0619
0620 create_opalcore();
0621
0622
0623
0624
0625
0626 if (!(is_opalcore_usable())) {
0627 pr_err("Failed to export /sys/firmware/opal/mpipl/core\n");
0628 opalcore_cleanup();
0629 return rc;
0630 }
0631
0632
0633 opal_core_attr.size = oc_conf->opalcore_size;
0634
0635 mpipl_kobj = kobject_create_and_add("mpipl", opal_kobj);
0636 if (!mpipl_kobj) {
0637 pr_err("unable to create mpipl kobject\n");
0638 return -ENOMEM;
0639 }
0640
0641
0642 rc = sysfs_create_group(mpipl_kobj, &mpipl_group);
0643 if (rc) {
0644 pr_err("mpipl sysfs group creation failed (%d)", rc);
0645 opalcore_cleanup();
0646 return rc;
0647 }
0648
0649
0650
0651
0652 rc = compat_only_sysfs_link_entry_to_kobj(opal_kobj, mpipl_kobj,
0653 "core", NULL);
0654 if (rc) {
0655 pr_err("unable to create core symlink (%d)\n", rc);
0656 return rc;
0657 }
0658
0659 return 0;
0660 }
0661 fs_initcall(opalcore_init);