root/arch/powerpc/platforms/powernv/opal-core.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_new_element
  2. is_opalcore_usable
  3. append_elf64_note
  4. fill_prstatus
  5. auxv_to_elf64_notes
  6. read_opalcore
  7. opalcore_append_cpu_notes
  8. create_opalcore
  9. opalcore_cleanup
  10. opalcore_config_init
  11. fadump_release_opalcore_store
  12. opalcore_init

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Interface for exporting the OPAL ELF core.
   4  * Heavily inspired from fs/proc/vmcore.c
   5  *
   6  * Copyright 2019, Hari Bathini, IBM Corporation.
   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 /* NT_AUXV note related info */
  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         /* PIR value of crashing CPU */
  37         u32                     crashing_cpu;
  38 
  39         /* CPU state data info from F/W */
  40         u64                     cpu_state_destination_vaddr;
  41         u64                     cpu_state_data_size;
  42         u64                     cpu_state_entry_size;
  43 
  44         /* OPAL memory to be exported as PT_LOAD segments */
  45         u64                     ptload_addr[MAX_PT_LOAD_CNT];
  46         u64                     ptload_size[MAX_PT_LOAD_CNT];
  47         u64                     ptload_cnt;
  48 
  49         /* Pointer to the first PT_LOAD in the ELF core file */
  50         Elf64_Phdr              *ptload_phdr;
  51 
  52         /* Total size of opalcore file. */
  53         size_t                  opalcore_size;
  54 
  55         /* Buffer for all the ELF core headers and the PT_NOTE */
  56         size_t                  opalcorebuf_sz;
  57         char                    *opalcorebuf;
  58 
  59         /* NT_AUXV buffer */
  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  * Set crashing CPU's signal to SIGUSR1. if the kernel is triggered
  77  * by kernel, SIGTERM otherwise.
  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          * Overload PID with PIR value.
 118          * As a PIR value could also be '0', add an offset of '100'
 119          * to every PIR to avoid misinterpretations in GDB.
 120          */
 121         prstatus->pr_pid  = cpu_to_be32(100 + pir);
 122         prstatus->pr_ppid = cpu_to_be32(1);
 123 
 124         /*
 125          * Indicate SIGUSR1 for crash initiated from kernel.
 126          * SIGTERM otherwise.
 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         /* Entry point of OPAL */
 145         bufp[idx++] = cpu_to_be64(AT_ENTRY);
 146         bufp[idx++] = cpu_to_be64(opal_boot_entry);
 147 
 148         /* end of vector */
 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  * Read from the ELF header and then the crash dump.
 158  * Returns number of bytes read on success, -errno on failure.
 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         /* Adjust count if it goes beyond opalcore size */
 172         avail = oc_conf->opalcore_size - pos;
 173         if (count > avail)
 174                 count = avail;
 175 
 176         if (count == 0)
 177                 return 0;
 178 
 179         /* Read ELF core header and/or PT_NOTE segment */
 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                 /* nothing more to read here */
 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  * Read CPU state dump data and convert it into ELF notes.
 215  *
 216  * Each register entry is of 16 bytes, A numerical identifier along with
 217  * a GPR/SPR flag in the first 8 bytes and the register value in the next
 218  * 8 bytes. For more details refer to F/W documentation.
 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          * Offset for register entries, entry size and registers count is
 235          * duplicated in every thread header in keeping with HDAT format.
 236          * Use these values from the first thread header.
 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          * Skip past the first CPU note. Fill this note with the
 251          * crashing CPU's prstatus.
 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                  * Register state data of MAX cores is provided by firmware,
 266                  * but some of this cores may not be active. So, while
 267                  * processing register state data, check core state and
 268                  * skip threads that belong to inactive cores.
 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, &regs);
 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, &regs);
 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                          * Add crashing CPU as the first NT_PRSTATUS note for
 287                          * GDB to process the core file appropriately.
 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         /* Get size of header & CPU notes for OPAL core */
 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         /* Allocate buffer to setup OPAL core */
 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         /* Read OPAL related device-tree entries */
 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         /* Use count to keep track of the program headers */
 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         /* Remove OPAL core sysfs file */
 431         sysfs_remove_bin_file(opal_kobj, &opal_core_attr);
 432         oc_conf->ptload_phdr = NULL;
 433         oc_conf->ptload_cnt = 0;
 434 
 435         /* free the buffer used for setting up OPAL core */
 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         /* Check if dump has been initiated on last reboot */
 468         prop = of_get_property(np, "mpipl-boot", NULL);
 469         if (!prop) {
 470                 of_node_put(np);
 471                 return;
 472         }
 473 
 474         /* Get OPAL metadata */
 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         /* Get OPAL CPU metadata */
 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         /* Allocate memory for config buffer */
 497         oc_conf = kzalloc(sizeof(struct opalcore_config), GFP_KERNEL);
 498         if (oc_conf == NULL)
 499                 goto error_out;
 500 
 501         /* Parse OPAL metadata */
 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         /* Parse OPAL CPU metadata */
 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                  * Take away '/sys/firmware/opal/core' and release all memory
 583                  * used for exporting this file.
 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          * If oc_conf->opalcorebuf= is set in the 2nd kernel,
 609          * then capture the dump.
 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         /* Set OPAL core file size */
 618         opal_core_attr.size = oc_conf->opalcore_size;
 619 
 620         /* Export OPAL core sysfs file */
 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);

/* [<][>][^][v][top][bottom][index][help] */