blob: 6e358e0d401750cde8c11e3116bf3e0b8d343346 [file] [log] [blame]
// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
/*
* FSP ATTentioN support
*
* FSP can grab a bunch of things on host firmware dying,
* let's set that up.
*
* Copyright 2013-2019 IBM Corp.
*/
#include <fsp.h>
#include <skiboot.h>
#include <fsp-elog.h>
#include <fsp-attn.h>
#include <hdata/spira.h>
#include <stack.h>
#include <processor.h>
#include <opal-dump.h>
#define TI_CMD_VALID 0x1 /* Command valid */
#define TI_CMD 0xA1 /* Terminate Immediate command */
#define TI_DATA_LEN 0x0400 /* Data length */
/* Controls dump actions
* - Non-destructive hardware dump (bit 0)
* - memory dump (bit 1)
* - Destructive hardware dump (bit 2)
*/
#define TI_DMP_CTL 0x6
/* Dump type
* 0 - Abbreviated hardware dump
* 1 - Complete hardware dump
* 2 - No hardware dump
*/
#define TI_DUMP_TYPE 0x1
#define TI_FORMAT 0x02 /* SRC format */
#define TI_SRC_FLAGS 0x0 /* SRC flags */
#define TI_ASCII_WORDS 0x0 /* Number of ASCII words */
/* HEX words: Number of hex words of data added, up to 8 total
* this value is one more.
*/
#define TI_HEX_WORDS 0x02
/* SRC length : 8 byte header, 8 hex words of data and
* 32 byte ASCII SRC
*/
#define TI_SRC_LEN 0x48
static struct ti_attn *ti_attn;
/* Initialises SP attention area with default values */
static void init_sp_attn_area(void)
{
/* Already done */
if (ti_attn)
return;
/* We are just enabling attention area 1 */
ti_attn = (struct ti_attn *)&cpu_ctl_sp_attn_area1;
/* Attention component checks Attn area 2 first, if its NULL
* it will check for Attn area 1.
*/
memset(&cpu_ctl_sp_attn_area1, 0, sizeof(struct sp_attn_area));
memset(&cpu_ctl_sp_attn_area2, 0, sizeof(struct sp_attn_area));
ti_attn->cmd_valid = TI_CMD_VALID;
ti_attn->attn_cmd = TI_CMD;
ti_attn->data_len = CPU_TO_BE16(TI_DATA_LEN);
/* Dump control byte not used as of now */
ti_attn->dump_ctrl =TI_DMP_CTL;
ti_attn->dump_type = CPU_TO_BE16(TI_DUMP_TYPE);
/* SRC format */
ti_attn->src_fmt = TI_FORMAT;
/* SRC flags */
ti_attn->src_flags = TI_SRC_FLAGS;
/* #ASCII words */
ti_attn->ascii_cnt = TI_ASCII_WORDS;
/* #HEX words */
ti_attn->hex_cnt = TI_HEX_WORDS;
ti_attn->src_len = CPU_TO_BE16(TI_SRC_LEN);
snprintf(ti_attn->src, SRC_LEN, "%X", generate_src_from_comp(OPAL_RC_ATTN));
}
/* Updates src in sp attention area
*/
static void update_sp_attn_area(const char *msg)
{
#define STACK_BUF_ENTRIES 20
struct bt_entry bt_buf[STACK_BUF_ENTRIES];
struct bt_metadata metadata;
unsigned int len;
if (!fsp_present())
return;
/* This can be called early */
if (!ti_attn)
init_sp_attn_area();
ti_attn->src_word[0] =
cpu_to_be32((uint32_t)((uint64_t)__builtin_return_address(0) & 0xffffffff));
snprintf(ti_attn->msg.version, VERSION_LEN, "%s", version);
backtrace_create(bt_buf, STACK_BUF_ENTRIES, &metadata);
metadata.token = OPAL_LAST + 1;
len = BT_FRAME_LEN;
backtrace_print(bt_buf, &metadata, ti_attn->msg.bt_buf, &len, false);
snprintf(ti_attn->msg.file_info, FILE_INFO_LEN, "%s", msg);
ti_attn->msg_len = cpu_to_be32(VERSION_LEN + BT_FRAME_LEN +
strlen(ti_attn->msg.file_info));
}
void __attribute__((noreturn)) ibm_fsp_terminate(const char *msg)
{
/* Update SP attention area */
update_sp_attn_area(msg);
/* Update op panel op_display */
op_display(OP_FATAL, OP_MOD_CORE, 0x6666);
/* Save crashing CPU details */
opal_mpipl_save_crashing_pir();
/* XXX FIXME: We should fsp_poll for a while to ensure any pending
* console writes have made it out, but until we have decent PSI
* link handling we must not do it forever. Polling can prevent the
* FSP from bringing the PSI link up and it can get stuck in a
* reboot loop.
*/
trigger_attn();
for (;;) ;
}
/* Intialises SP attention area */
void fsp_attn_init(void)
{
if (!fsp_present())
return;
init_sp_attn_area();
}