Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003  * Firmware-Assisted Dump support on POWER platform (OPAL).
0004  *
0005  * Copyright 2019, Hari Bathini, IBM Corporation.
0006  */
0007 
0008 #ifndef _POWERNV_OPAL_FADUMP_H
0009 #define _POWERNV_OPAL_FADUMP_H
0010 
0011 #include <asm/reg.h>
0012 
0013 /*
0014  * With kernel & initrd loaded at 512MB (with 256MB size), enforce a minimum
0015  * boot memory size of 768MB to ensure f/w loading kernel and initrd doesn't
0016  * mess with crash'ed kernel's memory during MPIPL.
0017  */
0018 #define OPAL_FADUMP_MIN_BOOT_MEM        (0x30000000UL)
0019 
0020 /*
0021  * OPAL FADump metadata structure format version
0022  *
0023  * OPAL FADump kernel metadata structure stores kernel metadata needed to
0024  * register-for/process crash dump. Format version is used to keep a tab on
0025  * the changes in the structure format. The changes, if any, to the format
0026  * are expected to be minimal and backward compatible.
0027  */
0028 #define OPAL_FADUMP_VERSION         0x1
0029 
0030 /*
0031  * OPAL FADump kernel metadata
0032  *
0033  * The address of this structure will be registered with f/w for retrieving
0034  * in the capture kernel to process the crash dump.
0035  */
0036 struct opal_fadump_mem_struct {
0037     u8  version;
0038     u8  reserved[3];
0039     __be16  region_cnt;     /* number of regions */
0040     __be16  registered_regions; /* Regions registered for MPIPL */
0041     __be64  fadumphdr_addr;
0042     struct opal_mpipl_region    rgn[FADUMP_MAX_MEM_REGS];
0043 } __packed;
0044 
0045 /*
0046  * CPU state data
0047  *
0048  * CPU state data information is provided by f/w. The format for this data
0049  * is defined in the HDAT spec. Version is used to keep a tab on the changes
0050  * in this CPU state data format. Changes to this format are unlikely, but
0051  * if there are any changes, please refer to latest HDAT specification.
0052  */
0053 #define HDAT_FADUMP_CPU_DATA_VER        1
0054 
0055 #define HDAT_FADUMP_CORE_INACTIVE       (0x0F)
0056 
0057 /* HDAT thread header for register entries */
0058 struct hdat_fadump_thread_hdr {
0059     __be32  pir;
0060     /* 0x00 - 0x0F - The corresponding stop state of the core */
0061     u8      core_state;
0062     u8      reserved[3];
0063 
0064     __be32  offset; /* Offset to Register Entries array */
0065     __be32  ecnt;   /* Number of entries */
0066     __be32  esize;  /* Alloc size of each array entry in bytes */
0067     __be32  eactsz; /* Actual size of each array entry in bytes */
0068 } __packed;
0069 
0070 /* Register types populated by f/w */
0071 #define HDAT_FADUMP_REG_TYPE_GPR        0x01
0072 #define HDAT_FADUMP_REG_TYPE_SPR        0x02
0073 
0074 /* ID numbers used by f/w while populating certain registers */
0075 #define HDAT_FADUMP_REG_ID_NIP          0x7D0
0076 #define HDAT_FADUMP_REG_ID_MSR          0x7D1
0077 #define HDAT_FADUMP_REG_ID_CCR          0x7D2
0078 
0079 /* HDAT register entry. */
0080 struct hdat_fadump_reg_entry {
0081     __be32      reg_type;
0082     __be32      reg_num;
0083     __be64      reg_val;
0084 } __packed;
0085 
0086 static inline void opal_fadump_set_regval_regnum(struct pt_regs *regs,
0087                          u32 reg_type, u32 reg_num,
0088                          u64 reg_val)
0089 {
0090     if (reg_type == HDAT_FADUMP_REG_TYPE_GPR) {
0091         if (reg_num < 32)
0092             regs->gpr[reg_num] = reg_val;
0093         return;
0094     }
0095 
0096     switch (reg_num) {
0097     case SPRN_CTR:
0098         regs->ctr = reg_val;
0099         break;
0100     case SPRN_LR:
0101         regs->link = reg_val;
0102         break;
0103     case SPRN_XER:
0104         regs->xer = reg_val;
0105         break;
0106     case SPRN_DAR:
0107         regs->dar = reg_val;
0108         break;
0109     case SPRN_DSISR:
0110         regs->dsisr = reg_val;
0111         break;
0112     case HDAT_FADUMP_REG_ID_NIP:
0113         regs->nip = reg_val;
0114         break;
0115     case HDAT_FADUMP_REG_ID_MSR:
0116         regs->msr = reg_val;
0117         break;
0118     case HDAT_FADUMP_REG_ID_CCR:
0119         regs->ccr = reg_val;
0120         break;
0121     }
0122 }
0123 
0124 static inline void opal_fadump_read_regs(char *bufp, unsigned int regs_cnt,
0125                      unsigned int reg_entry_size,
0126                      bool cpu_endian,
0127                      struct pt_regs *regs)
0128 {
0129     struct hdat_fadump_reg_entry *reg_entry;
0130     u64 val;
0131     int i;
0132 
0133     memset(regs, 0, sizeof(struct pt_regs));
0134 
0135     for (i = 0; i < regs_cnt; i++, bufp += reg_entry_size) {
0136         reg_entry = (struct hdat_fadump_reg_entry *)bufp;
0137         val = (cpu_endian ? be64_to_cpu(reg_entry->reg_val) :
0138                (u64)(reg_entry->reg_val));
0139         opal_fadump_set_regval_regnum(regs,
0140                           be32_to_cpu(reg_entry->reg_type),
0141                           be32_to_cpu(reg_entry->reg_num),
0142                           val);
0143     }
0144 }
0145 
0146 #endif /* _POWERNV_OPAL_FADUMP_H */