From: Hari Bathini <[email protected]> Firmware provides architected register state data at the time of crash. This data contains PIR value. Need to store the logical CPUs PIR values to match the data provided by f/w with the corresponding logical CPU.
Signed-off-by: Hari Bathini <[email protected]> Signed-off-by: Vasant Hegde <[email protected]> --- arch/powerpc/kernel/fadump.c | 40 +--- arch/powerpc/kernel/fadump_internal.c | 129 ++++++++++++++ arch/powerpc/kernel/fadump_internal.h | 32 +++ arch/powerpc/platforms/powernv/opal-fadump.c | 216 +++++++++++++++++++++-- arch/powerpc/platforms/powernv/opal-fadump.h | 9 + arch/powerpc/platforms/pseries/pseries_fadump.c | 1 6 files changed, 384 insertions(+), 43 deletions(-) diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c index 190f7ed..d9cf809 100644 --- a/arch/powerpc/kernel/fadump.c +++ b/arch/powerpc/kernel/fadump.c @@ -276,10 +276,10 @@ static unsigned long get_fadump_area_size(void) size += fw_dump.hpte_region_size; size += fw_dump.boot_memory_size; size += sizeof(struct fadump_crash_info_header); - size += sizeof(struct elfhdr); /* ELF core header.*/ - size += sizeof(struct elf_phdr); /* place holder for cpu notes */ - /* Program headers for crash memory regions. */ - size += sizeof(struct elf_phdr) * (memblock_num_regions(memory) + 2); + /* To store the start address of backup area */ + size += sizeof(unsigned long *); + size += get_fadump_elfcore_hdr_size(); + size += fw_dump.backup_area_size; size = PAGE_ALIGN(size); return size; @@ -892,26 +892,6 @@ static int fadump_create_elfcore_headers(char *bufp) return 0; } -static unsigned long init_fadump_header(unsigned long addr) -{ - struct fadump_crash_info_header *fdh; - - if (!addr) - return 0; - - fw_dump.fadumphdr_addr = addr; - fdh = __va(addr); - addr += sizeof(struct fadump_crash_info_header); - - memset(fdh, 0, sizeof(struct fadump_crash_info_header)); - fdh->magic_number = FADUMP_CRASH_INFO_MAGIC; - fdh->elfcorehdr_addr = addr; - /* We will set the crashing cpu id in crash_fadump() during crash. */ - fdh->crashing_cpu = CPU_UNKNOWN; - - return addr; -} - static int register_fadump(void) { unsigned long addr; @@ -929,15 +909,15 @@ static int register_fadump(void) if (ret) return ret; - addr = fw_dump.meta_area_start; - /* Initialize fadump crash info header. */ - addr = init_fadump_header(addr); + addr = fw_dump.ops->init_fadump_header(&fw_dump); vaddr = __va(addr); pr_debug("Creating ELF core headers at %#016lx\n", addr); fadump_create_elfcore_headers(vaddr); + fadump_populate_backup_area(&fw_dump); + /* register the future kernel dump with firmware. */ pr_debug("Registering for firmware-assisted kernel dump...\n"); return fw_dump.ops->register_fadump(&fw_dump); @@ -1242,8 +1222,12 @@ int __init setup_fadump(void) fadump_invalidate_release_mem(); } /* Initialize the kernel dump memory structure for FAD registration. */ - else if (fw_dump.reserve_dump_area_size) + else if (fw_dump.reserve_dump_area_size) { fw_dump.ops->init_fadump_mem_struct(&fw_dump); + fw_dump.ops->init_fadump_header(&fw_dump); + init_fadump_backup_area(&fw_dump); + fadump_populate_backup_area(&fw_dump); + } fadump_init_files(); diff --git a/arch/powerpc/kernel/fadump_internal.c b/arch/powerpc/kernel/fadump_internal.c index b46c7da..ea6f8ba 100644 --- a/arch/powerpc/kernel/fadump_internal.c +++ b/arch/powerpc/kernel/fadump_internal.c @@ -20,6 +20,34 @@ #include "fadump_internal.h" +/* + * Initializes the legacy fadump header format. + * Platform specific code can reuse/overwrite this format. + * OPAL platform overrides this data to add backup area support. + * + * TODO: Extend backup area support to pseries to make it robust? + */ +unsigned long generic_init_fadump_header(struct fw_dump *fadump_conf) +{ + unsigned long addr = fadump_conf->meta_area_start; + struct fadump_crash_info_header *fdh; + + if (!addr) + return 0; + + fadump_conf->fadumphdr_addr = addr; + fdh = __va(addr); + addr += sizeof(struct fadump_crash_info_header); + + memset(fdh, 0, sizeof(struct fadump_crash_info_header)); + fdh->magic_number = FADUMP_CRASH_INFO_MAGIC; + fdh->elfcorehdr_addr = addr; + /* We will set the crashing cpu id in crash_fadump() during crash. */ + fdh->crashing_cpu = CPU_UNKNOWN; + + return addr; +} + void *fadump_cpu_notes_buf_alloc(unsigned long size) { void *vaddr; @@ -106,6 +134,43 @@ void fadump_set_regval(struct pt_regs *regs, u64 reg_id, u64 reg_val) regs->dsisr = (unsigned long)reg_val; } +void fadump_set_regval_regnum(struct pt_regs *regs, u64 reg_id, + u64 reg_val, int reg_cnt) +{ + if (reg_cnt >= 63) { + if (reg_id < 32) { + regs->gpr[reg_id] = reg_val; + return; + } + } + switch (reg_id) { + case 2000: + regs->nip = reg_val; + break; + case 2001: + regs->msr = reg_val; + break; + case 9: + regs->ctr = reg_val; + break; + case 8: + regs->link = reg_val; + break; + case 1: + regs->xer = reg_val; + break; + case 2002: + regs->ccr = reg_val; + break; + case 19: + regs->dar = reg_val; + break; + case 18: + regs->dsisr = reg_val; + break; + } +} + u32 *fadump_regs_to_elf_notes(u32 *buf, struct pt_regs *regs) { struct elf_prstatus prstatus; @@ -121,6 +186,19 @@ u32 *fadump_regs_to_elf_notes(u32 *buf, struct pt_regs *regs) return buf; } +unsigned long get_fadump_elfcore_hdr_size(void) +{ + unsigned long size = 0; + + size = sizeof(struct elfhdr); /* ELF core header.*/ + size += sizeof(struct elf_phdr); /* place holder for cpu notes */ + size += sizeof(struct elf_phdr); /* vmcoreinfo notes program header */ + /* Program headers for crash memory regions. */ + size += sizeof(struct elf_phdr) * (memblock_num_regions(memory) + 1); + + return size; +} + void fadump_update_elfcore_header(struct fw_dump *fadump_conf, char *bufp) { struct elfhdr *elf; @@ -203,3 +281,54 @@ int is_reserved_memory_area_contiguous(struct fw_dump *fadump_conf) return is_memory_area_contiguous(d_start, d_end); } + +void init_fadump_backup_area(struct fw_dump *fadump_conf) +{ + unsigned long addr = fadump_conf->backup_area_start; + struct fadump_backup_area *backup_info; + + if (!addr) + return; + + backup_info = __va(addr); + memset(backup_info, 0xFF, fadump_conf->backup_area_size); + backup_info->version = BACKUP_AREA_VERSION_V1; + backup_info->size = fadump_conf->backup_area_size; + backup_info->nr_threads = 0; +} + +static inline void read_pir(void *val) +{ + *(unsigned long *)val = mfspr(SPRN_PIR); +} + +unsigned long fadump_populate_backup_area(struct fw_dump *fadump_conf) +{ + unsigned long pir, addr; + struct fadump_backup_area *backup_info; + unsigned int i; + + if (!fadump_conf->backup_area_start) + return 0; + + addr = fadump_conf->backup_area_start; + backup_info = __va(addr); + addr += fadump_conf->backup_area_size; + + backup_info->present_mask = *cpu_present_mask; + for_each_present_cpu(i) { + /* + * Skip if PIR is already read to avoid complex scenarios + * where the CPUs are offline'd after initial read. + */ + if (backup_info->thread_pir[i] != 0xFFFFFFFFU) + continue; + + smp_call_function_single(i, read_pir, &pir, 1); + pr_debug("Logical CPU: %d, PIR: 0x%lx\n", i, pir); + backup_info->thread_pir[i] = pir; + backup_info->nr_threads++; + } + + return addr; +} diff --git a/arch/powerpc/kernel/fadump_internal.h b/arch/powerpc/kernel/fadump_internal.h index 61c6335..a117f60 100644 --- a/arch/powerpc/kernel/fadump_internal.h +++ b/arch/powerpc/kernel/fadump_internal.h @@ -71,6 +71,9 @@ static inline u64 str_to_u64(const char *str) #define FADUMP_CRASH_INFO_MAGIC STR_TO_HEX("FADMPINF") +/* Backup area support in this version */ +#define FADUMP_CRASH_INFO_MAGIC_V2 STR_TO_HEX("FADINFV2") + /* Register entry. */ struct fadump_reg_entry { __be64 reg_id; @@ -89,6 +92,21 @@ struct fadump_crash_info_header { /* Platform specific callback functions */ struct fadump_ops; +#define BACKUP_AREA_VERSION_V1 1 + +/* Backup area populated with data for processing in capture kernel */ +struct fadump_backup_area { + u32 size; + u32 version:4; + u32 nr_threads:28; + u32 thread_pir[NR_CPUS]; + struct cpumask present_mask; + /* + * New backup data entries can be added here by bumping up + * the version field. + */ +}; + /* Firmware-Assited Dump platforms */ enum fadump_platform_type { FADUMP_PLATFORM_UNKNOWN = 0, @@ -106,6 +124,9 @@ struct fadump_memory_range { /* Firmware-assisted dump configuration details. */ struct fw_dump { + unsigned long cpu_state_destination_addr; + unsigned long cpu_state_data_version; + unsigned long cpu_state_entry_size; unsigned long cpu_state_data_size; unsigned long hpte_region_size; unsigned long boot_memory_size; @@ -113,6 +134,8 @@ struct fw_dump { unsigned long reserve_dump_area_size; unsigned long meta_area_start; unsigned long preserv_area_start; + unsigned long backup_area_start; + unsigned long backup_area_size; /* cmd line option during boot */ unsigned long reserve_bootvar; @@ -148,6 +171,7 @@ struct fw_dump { struct fadump_ops { ulong (*init_fadump_mem_struct)(struct fw_dump *fadump_config); + ulong (*init_fadump_header)(struct fw_dump *fadump_config); int (*register_fadump)(struct fw_dump *fadump_config); int (*unregister_fadump)(struct fw_dump *fadump_config); int (*invalidate_fadump)(struct fw_dump *fadump_config); @@ -157,15 +181,23 @@ struct fadump_ops { void (*crash_fadump)(const char *msg); }; +/* Generic version of fadump operations */ +unsigned long generic_init_fadump_header(struct fw_dump *fadump_conf); + /* Helper functions */ void *fadump_cpu_notes_buf_alloc(unsigned long size); void fadump_cpu_notes_buf_free(unsigned long vaddr, unsigned long size); void fadump_set_meta_area_start(struct fw_dump *fadump_conf); void fadump_set_regval(struct pt_regs *regs, u64 reg_id, u64 reg_val); +void fadump_set_regval_regnum(struct pt_regs *regs, u64 reg_id, + u64 reg_val, int reg_cnt); u32 *fadump_regs_to_elf_notes(u32 *buf, struct pt_regs *regs); +unsigned long get_fadump_elfcore_hdr_size(void); void fadump_update_elfcore_header(struct fw_dump *fadump_config, char *bufp); int is_boot_memory_area_contiguous(struct fw_dump *fadump_conf); int is_reserved_memory_area_contiguous(struct fw_dump *fadump_conf); +void init_fadump_backup_area(struct fw_dump *fadump_conf); +unsigned long fadump_populate_backup_area(struct fw_dump *fadump_conf); #ifdef CONFIG_PPC_PSERIES extern int pseries_dt_scan_fadump(struct fw_dump *fadump_config, ulong node); diff --git a/arch/powerpc/platforms/powernv/opal-fadump.c b/arch/powerpc/platforms/powernv/opal-fadump.c index 0679d98..9e677de 100644 --- a/arch/powerpc/platforms/powernv/opal-fadump.c +++ b/arch/powerpc/platforms/powernv/opal-fadump.c @@ -32,6 +32,39 @@ static struct opal_fadump_mem_struct fdm; static const struct opal_fadump_mem_struct *fdm_active; unsigned long fdm_actual_size; +/* + * Backup area is not available in older format. In the newer fadump + * header format (v2), backup info is stored at the end of elfcorehdrs + * and pointer to this address is stored at the tail end of FADump + * crash info header. + */ +static void opal_set_backup_area_start(struct fw_dump *fadump_conf) +{ + unsigned long addr = fadump_conf->meta_area_start; + + /* + * The start of meta area holds fadump_crash_info_header followed + * by a pointer to backup area start address, elfcore headers & + * backup info. + */ + addr += sizeof(struct fadump_crash_info_header); + + if (fadump_conf->dump_active) { + /* Pointer to backup area start address */ + unsigned long *ptr = __va(addr); + + addr = *ptr; + } else { + addr += sizeof(unsigned long *); + addr += get_fadump_elfcore_hdr_size(); + } + + fadump_conf->backup_area_start = addr; + + pr_debug("Backup area start address: 0x%lx\n", + fadump_conf->backup_area_start); +} + static void opal_set_preserv_area_start(struct fw_dump *fadump_conf) { fadump_conf->preserv_area_start = fadump_conf->rmr_destination_addr; @@ -94,6 +127,12 @@ static void update_fadump_config(struct fw_dump *fadump_conf, last_end = base + size; j++; + } else if (fdm->section[i].src_type == + OPAL_FADUMP_CPU_STATE_DATA) { + fadump_conf->cpu_state_destination_addr = + be64_to_cpu(fdm->section[i].dest_addr); + fadump_conf->cpu_state_data_size = + be64_to_cpu(fdm->section[i].dest_size); } } fadump_conf->rmr_regions_cnt = j; @@ -103,6 +142,7 @@ static void update_fadump_config(struct fw_dump *fadump_conf, fadump_set_meta_area_start(fadump_conf); opal_set_preserv_area_start(fadump_conf); + opal_set_backup_area_start(fadump_conf); } static ulong opal_init_fadump_mem_struct(struct fw_dump *fadump_conf) @@ -134,6 +174,41 @@ static ulong opal_init_fadump_mem_struct(struct fw_dump *fadump_conf) return addr; } +/* + * Newer fadump header version (v2) is used for process'ing OPAL FADump. + * In this version, PIR to Logical CPU map is backed up by crashing kernel + * for the capture kernel to make sense of the register state data provided + * by F/W. The start address of the area where this info is backed up is + * stored at the tail end of fadump crash info header. + */ +static ulong opal_init_fadump_header(struct fw_dump *fadump_conf) +{ + unsigned long addr = fadump_conf->meta_area_start; + struct fadump_crash_info_header *fdh; + unsigned long *backup_area_ptr; + + if (!addr) + return 0; + + fdh = __va(addr); + addr = generic_init_fadump_header(fadump_conf); + fdh->magic_number = FADUMP_CRASH_INFO_MAGIC_V2; + + /* + * This function returns the start address of elfcore headers. + * Earlier, elfcore headers sit right below crash info header but + * with V2, pointer to backup area start address (8 bytes) sits + * in-between. So, update the return value and elfcorehdr_addr + * in fadump crash info structure accordingly. + */ + backup_area_ptr = __va(addr); + addr += sizeof(unsigned long *); + fdh->elfcorehdr_addr = addr; + *backup_area_ptr = fadump_conf->backup_area_start; + + return addr; +} + static int opal_register_fadump(struct fw_dump *fadump_conf) { int rc, err = -EIO; @@ -199,6 +274,39 @@ static int opal_invalidate_fadump(struct fw_dump *fadump_conf) return 0; } +static inline int fadump_get_logical_cpu(struct fadump_backup_area *ba, u32 pir) +{ + int i = 0, cpu = CPU_UNKNOWN; + + for_each_cpu(i, &(ba->present_mask)) { + if (ba->thread_pir[i] == pir) { + cpu = i; + break; + } + } + + return cpu; +} + +static struct fadump_reg_entry* +fadump_read_registers(unsigned int regs_per_thread, + struct fadump_reg_entry *reg_entry, + struct pt_regs *regs) +{ + int i; + int reg_cnt = 0; + + memset(regs, 0, sizeof(struct pt_regs)); + + for (i = 0; i < regs_per_thread; i++) { + fadump_set_regval_regnum(regs, be64_to_cpu(reg_entry->reg_id), + be64_to_cpu(reg_entry->reg_value), + reg_cnt++); + reg_entry++; + } + return reg_entry; +} + /* * Read CPU state dump data and convert it into ELF notes. * @@ -206,10 +314,27 @@ static int opal_invalidate_fadump(struct fw_dump *fadump_conf) * a GPR/SPR flag in the first 8 bytes and the register value in the next * 8 bytes. For more details refer to F/W documentation. */ -static int __init fadump_build_cpu_notes(struct fw_dump *fadump_conf) +static int __init fadump_build_cpu_notes(struct fw_dump *fadump_conf, + struct fadump_backup_area *backup_info) { - u32 num_cpus = 1, *note_buf; + struct opal_thread_hdr *thdr; + struct fadump_reg_entry *reg_entry; struct fadump_crash_info_header *fdh = NULL; + unsigned long addr; + u32 num_cpus, *note_buf; + u32 thread_pir; + char *bufp; + struct pt_regs regs; + int i, rc = 0, cpu = 0; + unsigned int size_of_each_thread, regs_per_thread; + + size_of_each_thread = fadump_conf->cpu_state_entry_size; + num_cpus = (fadump_conf->cpu_state_data_size / size_of_each_thread); + regs_per_thread = ((size_of_each_thread - CPU_REG_ENTRY_OFFSET) / + sizeof(struct fadump_reg_entry)); + + addr = fadump_conf->cpu_state_destination_addr; + bufp = __va(addr); /* Allocate buffer to hold cpu crash notes. */ fadump_conf->cpu_notes_buf_size = num_cpus * sizeof(note_buf_t); @@ -229,22 +354,58 @@ static int __init fadump_build_cpu_notes(struct fw_dump *fadump_conf) if (fadump_conf->fadumphdr_addr) fdh = __va(fadump_conf->fadumphdr_addr); - if (fdh && (fdh->crashing_cpu != CPU_UNKNOWN)) { - note_buf = fadump_regs_to_elf_notes(note_buf, &(fdh->regs)); - final_note(note_buf); + if (backup_info->nr_threads != num_cpus) { + pr_warn("Calculated numcpus (%d) not same as populated value (%d)!\n", + num_cpus, backup_info->nr_threads); + } + pr_debug("--------CPU State Data------------\n"); + pr_debug("NumCpus : %u\n", num_cpus); + + for (i = 0; i < num_cpus; i++, bufp += size_of_each_thread) { + thdr = (struct opal_thread_hdr *)bufp; + thread_pir = be32_to_cpu(thdr->pir); + cpu = fadump_get_logical_cpu(backup_info, thread_pir); + if (cpu == CPU_UNKNOWN) { + pr_warn("Unable to get the logical CPU of PIR %d\n", + thread_pir); + continue; + } + + reg_entry = (struct fadump_reg_entry *)(bufp + + CPU_REG_ENTRY_OFFSET); + + if (fdh) { + if (!cpumask_test_cpu(cpu, &fdh->online_mask)) + continue; + + if (fdh->crashing_cpu == cpu) { + regs = fdh->regs; + note_buf = fadump_regs_to_elf_notes(note_buf, + ®s); + continue; + } + } + + fadump_read_registers(regs_per_thread, reg_entry, ®s); + note_buf = fadump_regs_to_elf_notes(note_buf, ®s); + } + final_note(note_buf); + if (fdh) { pr_debug("Updating elfcore header (%llx) with cpu notes\n", fdh->elfcorehdr_addr); fadump_update_elfcore_header(fadump_conf, __va(fdh->elfcorehdr_addr)); } - return 0; + return rc; } static int __init opal_process_fadump(struct fw_dump *fadump_conf) { struct fadump_crash_info_header *fdh; + struct fadump_backup_area *backup_info = NULL; + unsigned long addr; int rc = 0; if (!fdm_active || !fadump_conf->fadumphdr_addr) @@ -252,19 +413,19 @@ static int __init opal_process_fadump(struct fw_dump *fadump_conf) /* Validate the fadump crash info header */ fdh = __va(fadump_conf->fadumphdr_addr); - if (fdh->magic_number != FADUMP_CRASH_INFO_MAGIC) { + if (fdh->magic_number != FADUMP_CRASH_INFO_MAGIC_V2) { pr_err("Crash info header is not valid.\n"); return -EINVAL; } - /* - * TODO: To build cpu notes, find a way to map PIR to logical id. - * Also, we may need different method for pseries and powernv. - * The currently booted kernel could have a different PIR to - * logical id mapping. So, try saving info of previous kernel's - * paca to get the right PIR to logical id mapping. - */ - rc = fadump_build_cpu_notes(fadump_conf); + addr = fadump_conf->backup_area_start; + backup_info = __va(addr); + if (!addr || (backup_info->version != BACKUP_AREA_VERSION_V1)) { + pr_err("Backup data missing or unsupported!\n"); + return -EINVAL; + } + + rc = fadump_build_cpu_notes(fadump_conf, backup_info); if (rc) return rc; @@ -327,6 +488,7 @@ static void opal_crash_fadump(const char *msg) static struct fadump_ops opal_fadump_ops = { .init_fadump_mem_struct = opal_init_fadump_mem_struct, + .init_fadump_header = opal_init_fadump_header, .register_fadump = opal_register_fadump, .unregister_fadump = opal_unregister_fadump, .invalidate_fadump = opal_invalidate_fadump, @@ -338,6 +500,7 @@ static struct fadump_ops opal_fadump_ops = { int __init opal_dt_scan_fadump(struct fw_dump *fadump_conf, ulong node) { unsigned long dn; + const __be32 *prop; /* * Check if Firmware Assisted dump is supported. if yes, check @@ -349,6 +512,19 @@ int __init opal_dt_scan_fadump(struct fw_dump *fadump_conf, ulong node) return 1; } + fadump_conf->backup_area_size = sizeof(struct fadump_backup_area); + + prop = of_get_flat_dt_prop(dn, "cpu-data-version", NULL); + if (prop) + fadump_conf->cpu_state_data_version = of_read_number(prop, 1); + + if (fadump_conf->cpu_state_data_version != CPU_STATE_DATA_VERSION) { + pr_err("CPU state data format version mismatch!\n"); + pr_err("Kernel: %u, OPAL: %lu\n", CPU_STATE_DATA_VERSION, + fadump_conf->cpu_state_data_version); + return 1; + } + /* * Firmware currently supports only 32-bit value for size, * align it to 1MB size. @@ -363,6 +539,16 @@ int __init opal_dt_scan_fadump(struct fw_dump *fadump_conf, ulong node) pr_info("Firmware-assisted dump is active.\n"); fadump_conf->dump_active = 1; update_fadump_config(fadump_conf, (void *)__pa(fdm_active)); + + /* + * Doesn't need to populate these fields while registering dump + * as destination address and size are provided by F/W. + */ + prop = of_get_flat_dt_prop(dn, "cpu-data-size", NULL); + if (prop) { + fadump_conf->cpu_state_entry_size = + of_read_number(prop, 1); + } } fadump_conf->ops = &opal_fadump_ops; diff --git a/arch/powerpc/platforms/powernv/opal-fadump.h b/arch/powerpc/platforms/powernv/opal-fadump.h index a5eeb2c..392e4ce 100644 --- a/arch/powerpc/platforms/powernv/opal-fadump.h +++ b/arch/powerpc/platforms/powernv/opal-fadump.h @@ -13,6 +13,9 @@ #ifndef __PPC64_OPAL_FA_DUMP_H__ #define __PPC64_OPAL_FA_DUMP_H__ +#define CPU_STATE_DATA_VERSION 1 +#define CPU_REG_ENTRY_OFFSET 16 + #define OPAL_FADUMP_CPU_STATE_DATA 0x0000 /* OPAL : 0x01 – 0x39 */ #define OPAL_FADUMP_OPAL_REGION 0x0001 @@ -37,4 +40,10 @@ enum opal_fadump_section_types { #define OPAL_MAX_SECTIONS (OPAL_SECTIONS + \ MAX_REAL_MEM_REGIONS - 1) +struct opal_thread_hdr { + __be32 pir; + u8 core_state; + u8 reserved[11]; +} __packed; + #endif /* __PPC64_OPAL_FA_DUMP_H__ */ diff --git a/arch/powerpc/platforms/pseries/pseries_fadump.c b/arch/powerpc/platforms/pseries/pseries_fadump.c index f380f3f..f1d7b66 100644 --- a/arch/powerpc/platforms/pseries/pseries_fadump.c +++ b/arch/powerpc/platforms/pseries/pseries_fadump.c @@ -460,6 +460,7 @@ static void pseries_crash_fadump(const char *msg) static struct fadump_ops pseries_fadump_ops = { .init_fadump_mem_struct = pseries_init_fadump_mem_struct, + .init_fadump_header = generic_init_fadump_header, .register_fadump = pseries_register_fadump, .unregister_fadump = pseries_unregister_fadump, .invalidate_fadump = pseries_invalidate_fadump,
