1 /*
2 * Copyright (c) 2023-2024, Arm Limited and Contributors. All rights reserved.
3 *
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
17 #include <nrd_ras.h>
18
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 */
28 struct 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 */
37 typedef 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 */
populate_cpu_err_data(cpu_err_info * cpu_info,uint64_t security_state)52 static 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_el1_ctx_common(get_el1_sysregs_ctx(ctx),
66 elr_el1);
67 cpu_info->ErrCtxEl1Reg[1] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
68 esr_el1);
69 cpu_info->ErrCtxEl1Reg[2] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
70 far_el1);
71 cpu_info->ErrCtxEl1Reg[3] = read_isr_el1();
72 cpu_info->ErrCtxEl1Reg[4] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
73 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_sctlr_el1_reg_errata(ctx);
77 cpu_info->ErrCtxEl1Reg[8] = read_ctx_reg(get_gpregs_ctx(ctx),
78 CTX_GPREG_SP_EL0);
79 cpu_info->ErrCtxEl1Reg[9] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
80 sp_el1);
81 cpu_info->ErrCtxEl1Reg[10] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
82 spsr_el1);
83 cpu_info->ErrCtxEl1Reg[11] = read_ctx_tcr_el1_reg_errata(ctx);
84 cpu_info->ErrCtxEl1Reg[12] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
85 tpidr_el0);
86 cpu_info->ErrCtxEl1Reg[13] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
87 tpidr_el1);
88 cpu_info->ErrCtxEl1Reg[14] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
89 tpidrro_el0);
90 cpu_info->ErrCtxEl1Reg[15] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
91 ttbr0_el1);
92 cpu_info->ErrCtxEl1Reg[16] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
93 ttbr1_el1);
94
95 #if (CTX_INCLUDE_EL2_REGS && IMAGE_BL31)
96 cpu_info->ErrCtxEl2Reg[0] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
97 elr_el2);
98 cpu_info->ErrCtxEl2Reg[1] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
99 esr_el2);
100 cpu_info->ErrCtxEl2Reg[2] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
101 far_el2);
102 cpu_info->ErrCtxEl2Reg[3] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
103 hacr_el2);
104 cpu_info->ErrCtxEl2Reg[4] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
105 hcr_el2);
106 cpu_info->ErrCtxEl2Reg[5] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
107 hpfar_el2);
108 cpu_info->ErrCtxEl2Reg[6] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
109 mair_el2);
110 cpu_info->ErrCtxEl2Reg[7] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
111 sctlr_el2);
112 cpu_info->ErrCtxEl2Reg[8] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
113 sp_el2);
114 cpu_info->ErrCtxEl2Reg[9] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
115 spsr_el2);
116 cpu_info->ErrCtxEl2Reg[10] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
117 tcr_el2);
118 cpu_info->ErrCtxEl2Reg[11] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
119 tpidr_el2);
120 cpu_info->ErrCtxEl2Reg[12] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
121 ttbr0_el2);
122 cpu_info->ErrCtxEl2Reg[13] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
123 vtcr_el2);
124 cpu_info->ErrCtxEl2Reg[14] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
125 vttbr_el2);
126 cpu_info->ErrCtxEl2Reg[15] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
127 esr_el2);
128 #endif /* (CTX_INCLUDE_EL2_REGS && IMAGE_BL31) */
129
130 cpu_info->ErrCtxEl3Reg[0] = read_ctx_reg(get_el3state_ctx(ctx),
131 CTX_ELR_EL3);
132 cpu_info->ErrCtxEl3Reg[1] = read_ctx_reg(get_el3state_ctx(ctx),
133 CTX_ESR_EL3);
134 cpu_info->ErrCtxEl3Reg[2] = read_far_el3();
135 cpu_info->ErrCtxEl3Reg[4] = read_mair_el3();
136 cpu_info->ErrCtxEl3Reg[5] = read_sctlr_el3();
137 cpu_info->ErrCtxEl3Reg[6] = 0; /* sp_el3 */
138 cpu_info->ErrCtxEl3Reg[7] = read_tcr_el3();
139 cpu_info->ErrCtxEl3Reg[8] = read_tpidr_el3();
140 cpu_info->ErrCtxEl3Reg[9] = read_ttbr0_el3();
141 }
142
143 /* CPU RAS interrupt handler */
nrd_ras_cpu_intr_handler(const struct err_record_info * err_rec,int probe_data,const struct err_handler_data * const data)144 int nrd_ras_cpu_intr_handler(const struct err_record_info *err_rec,
145 int probe_data,
146 const struct err_handler_data *const data)
147 {
148 struct nrd_ras_ev_map *ras_map;
149 mm_communicate_header_t *header;
150 cpu_err_info cpu_info = {0};
151 uint64_t clear_status;
152 uint32_t intr;
153 int ret;
154
155 cm_el1_sysregs_context_save(NON_SECURE);
156 intr = data->interrupt;
157
158 INFO("[CPU RAS] CPU intr received = %d on cpu_id = %d\n",
159 intr, plat_my_core_pos());
160
161 INFO("[CPU RAS] ERXMISC0_EL1 = 0x%lx\n", read_erxmisc0_el1());
162 INFO("[CPU RAS] ERXSTATUS_EL1 = 0x%lx\n", read_erxstatus_el1());
163 INFO("[CPU RAS] ERXADDR_EL1 = 0x%lx\n", read_erxaddr_el1());
164
165 /* Populate CPU Error Source Information. */
166 populate_cpu_err_data(&cpu_info, get_interrupt_src_ss(data->flags));
167
168 /* Clear the interrupt. */
169 clear_status = read_erxstatus_el1();
170 write_erxstatus_el1(clear_status);
171 plat_ic_end_of_interrupt(intr);
172
173 header = (void *) PLAT_SPM_BUF_BASE;
174 memset(header, 0, sizeof(*header));
175 memcpy(&header->data, &cpu_info, sizeof(cpu_info));
176 header->message_len = sizeof(cpu_info);
177 memcpy(&header->header_guid, (void *) &cpu_ecc_event_guid,
178 sizeof(struct efi_guid));
179
180 spm_mm_sp_call(MM_COMMUNICATE_AARCH64, (uint64_t)header, 0,
181 plat_my_core_pos());
182
183 /*
184 * Find if this is a RAS interrupt. There must be an event against
185 * this interrupt
186 */
187 ras_map = nrd_find_ras_event_map_by_intr(intr);
188 if (ras_map == NULL) {
189 ERROR("NRD: RAS error info for interrupt id: %d not found\n",
190 intr);
191 return -1;
192 }
193
194 /* Dispatch the event to the SDEI client */
195 ret = sdei_dispatch_event(ras_map->sdei_ev_num);
196 if (ret != 0) {
197 /*
198 * sdei_dispatch_event() may return failing result in some
199 * cases, for example kernel may not have registered a handler
200 * or RAS event may happen early during boot. We restore the NS
201 * context when sdei_dispatch_event() returns failing result.
202 */
203 ERROR("SDEI dispatch failed: %d", ret);
204 cm_el1_sysregs_context_restore(NON_SECURE);
205 cm_set_next_eret_context(NON_SECURE);
206 }
207
208 return ret;
209 }
210