blob: d25fa7c66ac48f148c916e2359ea712fc15739d0 [file] [log] [blame]
Omkar Anand Kulkarni1ab5c602023-06-27 16:32:47 +05301/*
Rohit Mathewa0dd3072024-02-03 17:22:54 +00002 * Copyright (c) 2023-2024, Arm Limited and Contributors. All rights reserved.
Omkar Anand Kulkarni1ab5c602023-06-27 16:32:47 +05303 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
8#include <string.h>
9
10#include <bl31/interrupt_mgmt.h>
11#include <lib/el3_runtime/context_mgmt.h>
12#include <lib/extensions/ras.h>
13#include <plat/common/platform.h>
14#include <services/sdei.h>
15#include <services/spm_mm_svc.h>
16
Rohit Mathewa0dd3072024-02-03 17:22:54 +000017#include <nrd_ras.h>
Omkar Anand Kulkarni1ab5c602023-06-27 16:32:47 +053018
19#define CPU_CONTEXT_REG_GPR_ARR_SIZE 32
20#define CPU_CONTEXT_REG_EL1_ARR_SIZE 17
21#define CPU_CONTEXT_REG_EL2_ARR_SIZE 16
22#define CPU_CONTEXT_REG_EL3_ARR_SIZE 10
23
24/*
25 * MM Communicate message header GUID to indicate the payload is intended for
26 * CPU MM driver.
27 */
28struct efi_guid cpu_ecc_event_guid = {
29 0x2c1b3bfc, 0x42cd, 0x4a66,
30 {0xac, 0xd1, 0xa4, 0xd1, 0x63, 0xe9, 0x90, 0xf6}
31 };
32
33/*
34 * CPU error information data structure communicated as part of MM
35 * Communication data payload.
36 */
37typedef struct {
38 uint64_t ErrStatus;
39 uint64_t ErrMisc0;
40 uint64_t ErrAddr;
41 uint64_t SecurityState;
42 uint64_t ErrCtxGpr[CPU_CONTEXT_REG_GPR_ARR_SIZE];
43 uint64_t ErrCtxEl1Reg[CPU_CONTEXT_REG_EL1_ARR_SIZE];
44 uint64_t ErrCtxEl2Reg[CPU_CONTEXT_REG_EL2_ARR_SIZE];
45 uint64_t ErrCtxEl3Reg[CPU_CONTEXT_REG_EL3_ARR_SIZE];
46} cpu_err_info;
47
48/*
49 * Reads the CPU context and error information from the relevant registers and
50 * populates the CPU error information data structure.
51 */
52static void populate_cpu_err_data(cpu_err_info *cpu_info,
53 uint64_t security_state)
54{
55 void *ctx;
56
57 ctx = cm_get_context(security_state);
58
59 cpu_info->ErrStatus = read_erxstatus_el1();
60 cpu_info->ErrMisc0 = read_erxmisc0_el1();
61 cpu_info->ErrAddr = read_erxaddr_el1();
62 cpu_info->SecurityState = security_state;
63
64 /* populate CPU EL1 context information. */
65 cpu_info->ErrCtxEl1Reg[0] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
66 CTX_ELR_EL1);
67 cpu_info->ErrCtxEl1Reg[1] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
68 CTX_ESR_EL1);
69 cpu_info->ErrCtxEl1Reg[2] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
70 CTX_FAR_EL1);
71 cpu_info->ErrCtxEl1Reg[3] = read_isr_el1();
72 cpu_info->ErrCtxEl1Reg[4] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
73 CTX_MAIR_EL1);
74 cpu_info->ErrCtxEl1Reg[5] = read_midr_el1();
75 cpu_info->ErrCtxEl1Reg[6] = read_mpidr_el1();
76 cpu_info->ErrCtxEl1Reg[7] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
77 CTX_SCTLR_EL1);
78 cpu_info->ErrCtxEl1Reg[8] = read_ctx_reg(get_gpregs_ctx(ctx),
79 CTX_GPREG_SP_EL0);
80 cpu_info->ErrCtxEl1Reg[9] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
81 CTX_SP_EL1);
82 cpu_info->ErrCtxEl1Reg[10] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
83 CTX_SPSR_EL1);
84 cpu_info->ErrCtxEl1Reg[11] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
85 CTX_TCR_EL1);
86 cpu_info->ErrCtxEl1Reg[12] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
87 CTX_TPIDR_EL0);
88 cpu_info->ErrCtxEl1Reg[13] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
89 CTX_TPIDR_EL1);
90 cpu_info->ErrCtxEl1Reg[14] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
91 CTX_TPIDRRO_EL0);
92 cpu_info->ErrCtxEl1Reg[15] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
93 CTX_TTBR0_EL1);
94 cpu_info->ErrCtxEl1Reg[16] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
95 CTX_TTBR1_EL1);
96
97#if CTX_INCLUDE_EL2_REGS
98 cpu_info->ErrCtxEl2Reg[0] = read_ctx_reg(get_el2_sysregs_ctx(ctx),
99 CTX_ELR_EL2);
100 cpu_info->ErrCtxEl2Reg[1] = read_ctx_reg(get_el2_sysregs_ctx(ctx),
101 CTX_ESR_EL2);
102 cpu_info->ErrCtxEl2Reg[2] = read_ctx_reg(get_el2_sysregs_ctx(ctx),
103 CTX_FAR_EL2);
104 cpu_info->ErrCtxEl2Reg[3] = read_ctx_reg(get_el2_sysregs_ctx(ctx),
105 CTX_HACR_EL2);
106 cpu_info->ErrCtxEl2Reg[4] = read_ctx_reg(get_el2_sysregs_ctx(ctx),
107 CTX_HCR_EL2);
108 cpu_info->ErrCtxEl2Reg[5] = read_ctx_reg(get_el2_sysregs_ctx(ctx),
109 CTX_HPFAR_EL2);
110 cpu_info->ErrCtxEl2Reg[6] = read_ctx_reg(get_el2_sysregs_ctx(ctx),
111 CTX_MAIR_EL2);
112 cpu_info->ErrCtxEl2Reg[7] = read_ctx_reg(get_el2_sysregs_ctx(ctx),
113 CTX_SCTLR_EL2);
114 cpu_info->ErrCtxEl2Reg[8] = read_ctx_reg(get_el2_sysregs_ctx(ctx),
115 CTX_SP_EL2);
116 cpu_info->ErrCtxEl2Reg[9] = read_ctx_reg(get_el2_sysregs_ctx(ctx),
117 CTX_SPSR_EL2);
118 cpu_info->ErrCtxEl2Reg[10] = read_ctx_reg(get_el2_sysregs_ctx(ctx),
119 CTX_TCR_EL2);
120 cpu_info->ErrCtxEl2Reg[11] = read_ctx_reg(get_el2_sysregs_ctx(ctx),
121 CTX_TPIDR_EL2);
122 cpu_info->ErrCtxEl2Reg[12] = read_ctx_reg(get_el2_sysregs_ctx(ctx),
123 CTX_TTBR0_EL2);
124 cpu_info->ErrCtxEl2Reg[13] = read_ctx_reg(get_el2_sysregs_ctx(ctx),
125 CTX_VTCR_EL2);
126 cpu_info->ErrCtxEl2Reg[14] = read_ctx_reg(get_el2_sysregs_ctx(ctx),
127 CTX_VTTBR_EL2);
128 cpu_info->ErrCtxEl2Reg[15] = read_ctx_reg(get_el2_sysregs_ctx(ctx),
129 CTX_ESR_EL2);
130#endif
131
132 cpu_info->ErrCtxEl3Reg[0] = read_ctx_reg(get_el3state_ctx(ctx),
133 CTX_ELR_EL3);
134 cpu_info->ErrCtxEl3Reg[1] = read_ctx_reg(get_el3state_ctx(ctx),
135 CTX_ESR_EL3);
136 cpu_info->ErrCtxEl3Reg[2] = read_far_el3();
137 cpu_info->ErrCtxEl3Reg[4] = read_mair_el3();
138 cpu_info->ErrCtxEl3Reg[5] = read_sctlr_el3();
139 cpu_info->ErrCtxEl3Reg[6] = 0; /* sp_el3 */
140 cpu_info->ErrCtxEl3Reg[7] = read_tcr_el3();
141 cpu_info->ErrCtxEl3Reg[8] = read_tpidr_el3();
142 cpu_info->ErrCtxEl3Reg[9] = read_ttbr0_el3();
143}
144
145/* CPU RAS interrupt handler */
Rohit Mathew0ec6ed92024-02-03 18:39:10 +0000146int nrd_ras_cpu_intr_handler(const struct err_record_info *err_rec,
Omkar Anand Kulkarni1ab5c602023-06-27 16:32:47 +0530147 int probe_data,
148 const struct err_handler_data *const data)
149{
Rohit Mathew0ec6ed92024-02-03 18:39:10 +0000150 struct nrd_ras_ev_map *ras_map;
Omkar Anand Kulkarni1ab5c602023-06-27 16:32:47 +0530151 mm_communicate_header_t *header;
152 cpu_err_info cpu_info = {0};
153 uint64_t clear_status;
154 uint32_t intr;
155 int ret;
156
157 cm_el1_sysregs_context_save(NON_SECURE);
158 intr = data->interrupt;
159
160 INFO("[CPU RAS] CPU intr received = %d on cpu_id = %d\n",
161 intr, plat_my_core_pos());
162
163 INFO("[CPU RAS] ERXMISC0_EL1 = 0x%lx\n", read_erxmisc0_el1());
164 INFO("[CPU RAS] ERXSTATUS_EL1 = 0x%lx\n", read_erxstatus_el1());
165 INFO("[CPU RAS] ERXADDR_EL1 = 0x%lx\n", read_erxaddr_el1());
166
167 /* Populate CPU Error Source Information. */
168 populate_cpu_err_data(&cpu_info, get_interrupt_src_ss(data->flags));
169
170 /* Clear the interrupt. */
171 clear_status = read_erxstatus_el1();
172 write_erxstatus_el1(clear_status);
173 plat_ic_end_of_interrupt(intr);
174
175 header = (void *) PLAT_SPM_BUF_BASE;
176 memset(header, 0, sizeof(*header));
177 memcpy(&header->data, &cpu_info, sizeof(cpu_info));
178 header->message_len = sizeof(cpu_info);
179 memcpy(&header->header_guid, (void *) &cpu_ecc_event_guid,
180 sizeof(struct efi_guid));
181
182 spm_mm_sp_call(MM_COMMUNICATE_AARCH64, (uint64_t)header, 0,
183 plat_my_core_pos());
184
185 /*
186 * Find if this is a RAS interrupt. There must be an event against
187 * this interrupt
188 */
Rohit Mathew0ec6ed92024-02-03 18:39:10 +0000189 ras_map = nrd_find_ras_event_map_by_intr(intr);
Omkar Anand Kulkarni1ab5c602023-06-27 16:32:47 +0530190 if (ras_map == NULL) {
191 ERROR("SGI: RAS error info for interrupt id: %d not found\n",
192 intr);
193 return -1;
194 }
195
196 /* Dispatch the event to the SDEI client */
197 ret = sdei_dispatch_event(ras_map->sdei_ev_num);
198 if (ret != 0) {
199 /*
200 * sdei_dispatch_event() may return failing result in some
201 * cases, for example kernel may not have registered a handler
202 * or RAS event may happen early during boot. We restore the NS
203 * context when sdei_dispatch_event() returns failing result.
204 */
205 ERROR("SDEI dispatch failed: %d", ret);
206 cm_el1_sysregs_context_restore(NON_SECURE);
207 cm_set_next_eret_context(NON_SECURE);
208 }
209
210 return ret;
211}