aboutsummaryrefslogtreecommitdiff
path: root/hw/fsp/fsp-attn.c
blob: 877390240384dd9f95ab615e32e82448a50d8682 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// 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 <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();
}