forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
146 lines
3.8 KiB
146 lines
3.8 KiB
/* SPDX-License-Identifier: GPL-2.0-or-later */ |
|
/* |
|
* Firmware-Assisted Dump support on POWER platform (OPAL). |
|
* |
|
* Copyright 2019, Hari Bathini, IBM Corporation. |
|
*/ |
|
|
|
#ifndef _POWERNV_OPAL_FADUMP_H |
|
#define _POWERNV_OPAL_FADUMP_H |
|
|
|
#include <asm/reg.h> |
|
|
|
/* |
|
* With kernel & initrd loaded at 512MB (with 256MB size), enforce a minimum |
|
* boot memory size of 768MB to ensure f/w loading kernel and initrd doesn't |
|
* mess with crash'ed kernel's memory during MPIPL. |
|
*/ |
|
#define OPAL_FADUMP_MIN_BOOT_MEM (0x30000000UL) |
|
|
|
/* |
|
* OPAL FADump metadata structure format version |
|
* |
|
* OPAL FADump kernel metadata structure stores kernel metadata needed to |
|
* register-for/process crash dump. Format version is used to keep a tab on |
|
* the changes in the structure format. The changes, if any, to the format |
|
* are expected to be minimal and backward compatible. |
|
*/ |
|
#define OPAL_FADUMP_VERSION 0x1 |
|
|
|
/* |
|
* OPAL FADump kernel metadata |
|
* |
|
* The address of this structure will be registered with f/w for retrieving |
|
* and processing during crash dump. |
|
*/ |
|
struct opal_fadump_mem_struct { |
|
u8 version; |
|
u8 reserved[3]; |
|
u16 region_cnt; /* number of regions */ |
|
u16 registered_regions; /* Regions registered for MPIPL */ |
|
u64 fadumphdr_addr; |
|
struct opal_mpipl_region rgn[FADUMP_MAX_MEM_REGS]; |
|
} __packed; |
|
|
|
/* |
|
* CPU state data |
|
* |
|
* CPU state data information is provided by f/w. The format for this data |
|
* is defined in the HDAT spec. Version is used to keep a tab on the changes |
|
* in this CPU state data format. Changes to this format are unlikely, but |
|
* if there are any changes, please refer to latest HDAT specification. |
|
*/ |
|
#define HDAT_FADUMP_CPU_DATA_VER 1 |
|
|
|
#define HDAT_FADUMP_CORE_INACTIVE (0x0F) |
|
|
|
/* HDAT thread header for register entries */ |
|
struct hdat_fadump_thread_hdr { |
|
__be32 pir; |
|
/* 0x00 - 0x0F - The corresponding stop state of the core */ |
|
u8 core_state; |
|
u8 reserved[3]; |
|
|
|
__be32 offset; /* Offset to Register Entries array */ |
|
__be32 ecnt; /* Number of entries */ |
|
__be32 esize; /* Alloc size of each array entry in bytes */ |
|
__be32 eactsz; /* Actual size of each array entry in bytes */ |
|
} __packed; |
|
|
|
/* Register types populated by f/w */ |
|
#define HDAT_FADUMP_REG_TYPE_GPR 0x01 |
|
#define HDAT_FADUMP_REG_TYPE_SPR 0x02 |
|
|
|
/* ID numbers used by f/w while populating certain registers */ |
|
#define HDAT_FADUMP_REG_ID_NIP 0x7D0 |
|
#define HDAT_FADUMP_REG_ID_MSR 0x7D1 |
|
#define HDAT_FADUMP_REG_ID_CCR 0x7D2 |
|
|
|
/* HDAT register entry. */ |
|
struct hdat_fadump_reg_entry { |
|
__be32 reg_type; |
|
__be32 reg_num; |
|
__be64 reg_val; |
|
} __packed; |
|
|
|
static inline void opal_fadump_set_regval_regnum(struct pt_regs *regs, |
|
u32 reg_type, u32 reg_num, |
|
u64 reg_val) |
|
{ |
|
if (reg_type == HDAT_FADUMP_REG_TYPE_GPR) { |
|
if (reg_num < 32) |
|
regs->gpr[reg_num] = reg_val; |
|
return; |
|
} |
|
|
|
switch (reg_num) { |
|
case SPRN_CTR: |
|
regs->ctr = reg_val; |
|
break; |
|
case SPRN_LR: |
|
regs->link = reg_val; |
|
break; |
|
case SPRN_XER: |
|
regs->xer = reg_val; |
|
break; |
|
case SPRN_DAR: |
|
regs->dar = reg_val; |
|
break; |
|
case SPRN_DSISR: |
|
regs->dsisr = reg_val; |
|
break; |
|
case HDAT_FADUMP_REG_ID_NIP: |
|
regs->nip = reg_val; |
|
break; |
|
case HDAT_FADUMP_REG_ID_MSR: |
|
regs->msr = reg_val; |
|
break; |
|
case HDAT_FADUMP_REG_ID_CCR: |
|
regs->ccr = reg_val; |
|
break; |
|
} |
|
} |
|
|
|
static inline void opal_fadump_read_regs(char *bufp, unsigned int regs_cnt, |
|
unsigned int reg_entry_size, |
|
bool cpu_endian, |
|
struct pt_regs *regs) |
|
{ |
|
struct hdat_fadump_reg_entry *reg_entry; |
|
u64 val; |
|
int i; |
|
|
|
memset(regs, 0, sizeof(struct pt_regs)); |
|
|
|
for (i = 0; i < regs_cnt; i++, bufp += reg_entry_size) { |
|
reg_entry = (struct hdat_fadump_reg_entry *)bufp; |
|
val = (cpu_endian ? be64_to_cpu(reg_entry->reg_val) : |
|
reg_entry->reg_val); |
|
opal_fadump_set_regval_regnum(regs, |
|
be32_to_cpu(reg_entry->reg_type), |
|
be32_to_cpu(reg_entry->reg_num), |
|
val); |
|
} |
|
} |
|
|
|
#endif /* _POWERNV_OPAL_FADUMP_H */
|
|
|