1742a265aSHari Bathini /* SPDX-License-Identifier: GPL-2.0-or-later */ 2742a265aSHari Bathini /* 3742a265aSHari Bathini * Firmware-Assisted Dump support on POWER platform (OPAL). 4742a265aSHari Bathini * 5742a265aSHari Bathini * Copyright 2019, Hari Bathini, IBM Corporation. 6742a265aSHari Bathini */ 7742a265aSHari Bathini 8742a265aSHari Bathini #ifndef _POWERNV_OPAL_FADUMP_H 9742a265aSHari Bathini #define _POWERNV_OPAL_FADUMP_H 10742a265aSHari Bathini 116f713d18SHari Bathini #include <asm/reg.h> 126f713d18SHari Bathini 13742a265aSHari Bathini /* 147b1b3b48SHari Bathini * With kernel & initrd loaded at 512MB (with 256MB size), enforce a minimum 157b1b3b48SHari Bathini * boot memory size of 768MB to ensure f/w loading kernel and initrd doesn't 167b1b3b48SHari Bathini * mess with crash'ed kernel's memory during MPIPL. 177b1b3b48SHari Bathini */ 187b1b3b48SHari Bathini #define OPAL_FADUMP_MIN_BOOT_MEM (0x30000000UL) 197b1b3b48SHari Bathini 207b1b3b48SHari Bathini /* 21742a265aSHari Bathini * OPAL FADump metadata structure format version 22742a265aSHari Bathini * 23742a265aSHari Bathini * OPAL FADump kernel metadata structure stores kernel metadata needed to 24742a265aSHari Bathini * register-for/process crash dump. Format version is used to keep a tab on 25742a265aSHari Bathini * the changes in the structure format. The changes, if any, to the format 26742a265aSHari Bathini * are expected to be minimal and backward compatible. 27742a265aSHari Bathini */ 28742a265aSHari Bathini #define OPAL_FADUMP_VERSION 0x1 29742a265aSHari Bathini 30742a265aSHari Bathini /* 31742a265aSHari Bathini * OPAL FADump kernel metadata 32742a265aSHari Bathini * 33742a265aSHari Bathini * The address of this structure will be registered with f/w for retrieving 34742a265aSHari Bathini * and processing during crash dump. 35742a265aSHari Bathini */ 36742a265aSHari Bathini struct opal_fadump_mem_struct { 37742a265aSHari Bathini u8 version; 38742a265aSHari Bathini u8 reserved[3]; 39742a265aSHari Bathini u16 region_cnt; /* number of regions */ 40742a265aSHari Bathini u16 registered_regions; /* Regions registered for MPIPL */ 41742a265aSHari Bathini u64 fadumphdr_addr; 427dee93a9SHari Bathini struct opal_mpipl_region rgn[FADUMP_MAX_MEM_REGS]; 43742a265aSHari Bathini } __packed; 44742a265aSHari Bathini 455000a17aSHari Bathini /* 465000a17aSHari Bathini * CPU state data 475000a17aSHari Bathini * 485000a17aSHari Bathini * CPU state data information is provided by f/w. The format for this data 495000a17aSHari Bathini * is defined in the HDAT spec. Version is used to keep a tab on the changes 505000a17aSHari Bathini * in this CPU state data format. Changes to this format are unlikely, but 515000a17aSHari Bathini * if there are any changes, please refer to latest HDAT specification. 525000a17aSHari Bathini */ 535000a17aSHari Bathini #define HDAT_FADUMP_CPU_DATA_VER 1 545000a17aSHari Bathini 555000a17aSHari Bathini #define HDAT_FADUMP_CORE_INACTIVE (0x0F) 565000a17aSHari Bathini 575000a17aSHari Bathini /* HDAT thread header for register entries */ 585000a17aSHari Bathini struct hdat_fadump_thread_hdr { 595000a17aSHari Bathini __be32 pir; 605000a17aSHari Bathini /* 0x00 - 0x0F - The corresponding stop state of the core */ 615000a17aSHari Bathini u8 core_state; 625000a17aSHari Bathini u8 reserved[3]; 635000a17aSHari Bathini 645000a17aSHari Bathini __be32 offset; /* Offset to Register Entries array */ 655000a17aSHari Bathini __be32 ecnt; /* Number of entries */ 665000a17aSHari Bathini __be32 esize; /* Alloc size of each array entry in bytes */ 675000a17aSHari Bathini __be32 eactsz; /* Actual size of each array entry in bytes */ 685000a17aSHari Bathini } __packed; 695000a17aSHari Bathini 705000a17aSHari Bathini /* Register types populated by f/w */ 715000a17aSHari Bathini #define HDAT_FADUMP_REG_TYPE_GPR 0x01 725000a17aSHari Bathini #define HDAT_FADUMP_REG_TYPE_SPR 0x02 735000a17aSHari Bathini 745000a17aSHari Bathini /* ID numbers used by f/w while populating certain registers */ 755000a17aSHari Bathini #define HDAT_FADUMP_REG_ID_NIP 0x7D0 765000a17aSHari Bathini #define HDAT_FADUMP_REG_ID_MSR 0x7D1 775000a17aSHari Bathini #define HDAT_FADUMP_REG_ID_CCR 0x7D2 785000a17aSHari Bathini 795000a17aSHari Bathini /* HDAT register entry. */ 805000a17aSHari Bathini struct hdat_fadump_reg_entry { 815000a17aSHari Bathini __be32 reg_type; 825000a17aSHari Bathini __be32 reg_num; 835000a17aSHari Bathini __be64 reg_val; 845000a17aSHari Bathini } __packed; 855000a17aSHari Bathini 866f713d18SHari Bathini static inline void opal_fadump_set_regval_regnum(struct pt_regs *regs, 876f713d18SHari Bathini u32 reg_type, u32 reg_num, 886f713d18SHari Bathini u64 reg_val) 896f713d18SHari Bathini { 906f713d18SHari Bathini if (reg_type == HDAT_FADUMP_REG_TYPE_GPR) { 916f713d18SHari Bathini if (reg_num < 32) 926f713d18SHari Bathini regs->gpr[reg_num] = reg_val; 936f713d18SHari Bathini return; 946f713d18SHari Bathini } 956f713d18SHari Bathini 966f713d18SHari Bathini switch (reg_num) { 976f713d18SHari Bathini case SPRN_CTR: 986f713d18SHari Bathini regs->ctr = reg_val; 996f713d18SHari Bathini break; 1006f713d18SHari Bathini case SPRN_LR: 1016f713d18SHari Bathini regs->link = reg_val; 1026f713d18SHari Bathini break; 1036f713d18SHari Bathini case SPRN_XER: 1046f713d18SHari Bathini regs->xer = reg_val; 1056f713d18SHari Bathini break; 1066f713d18SHari Bathini case SPRN_DAR: 1076f713d18SHari Bathini regs->dar = reg_val; 1086f713d18SHari Bathini break; 1096f713d18SHari Bathini case SPRN_DSISR: 1106f713d18SHari Bathini regs->dsisr = reg_val; 1116f713d18SHari Bathini break; 1126f713d18SHari Bathini case HDAT_FADUMP_REG_ID_NIP: 1136f713d18SHari Bathini regs->nip = reg_val; 1146f713d18SHari Bathini break; 1156f713d18SHari Bathini case HDAT_FADUMP_REG_ID_MSR: 1166f713d18SHari Bathini regs->msr = reg_val; 1176f713d18SHari Bathini break; 1186f713d18SHari Bathini case HDAT_FADUMP_REG_ID_CCR: 1196f713d18SHari Bathini regs->ccr = reg_val; 1206f713d18SHari Bathini break; 1216f713d18SHari Bathini } 1226f713d18SHari Bathini } 1236f713d18SHari Bathini 1246f713d18SHari Bathini static inline void opal_fadump_read_regs(char *bufp, unsigned int regs_cnt, 1256f713d18SHari Bathini unsigned int reg_entry_size, 1266f713d18SHari Bathini bool cpu_endian, 1276f713d18SHari Bathini struct pt_regs *regs) 1286f713d18SHari Bathini { 1296f713d18SHari Bathini struct hdat_fadump_reg_entry *reg_entry; 1306f713d18SHari Bathini u64 val; 1316f713d18SHari Bathini int i; 1326f713d18SHari Bathini 1336f713d18SHari Bathini memset(regs, 0, sizeof(struct pt_regs)); 1346f713d18SHari Bathini 1356f713d18SHari Bathini for (i = 0; i < regs_cnt; i++, bufp += reg_entry_size) { 1366f713d18SHari Bathini reg_entry = (struct hdat_fadump_reg_entry *)bufp; 1376f713d18SHari Bathini val = (cpu_endian ? be64_to_cpu(reg_entry->reg_val) : 1386f713d18SHari Bathini reg_entry->reg_val); 1396f713d18SHari Bathini opal_fadump_set_regval_regnum(regs, 1406f713d18SHari Bathini be32_to_cpu(reg_entry->reg_type), 1416f713d18SHari Bathini be32_to_cpu(reg_entry->reg_num), 1426f713d18SHari Bathini val); 1436f713d18SHari Bathini } 1446f713d18SHari Bathini } 1456f713d18SHari Bathini 146742a265aSHari Bathini #endif /* _POWERNV_OPAL_FADUMP_H */ 147