xref: /rk3399_ARM-atf/services/std_svc/errata_abi/errata_abi_main.c (revision c9f2634387b4ea29f61234c4fe0fc0515ad32f2b)
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 "cpu_errata_info.h"
9 #include <lib/cpus/cpu_ops.h>
10 #include <lib/cpus/errata.h>
11 #include <lib/smccc.h>
12 #include <lib/utils_def.h>
13 #include <services/errata_abi_svc.h>
14 #include <smccc_helpers.h>
15 
16 
17 /*
18  * Global pointer that points to the specific
19  * structure based on the MIDR part number
20  */
21 struct em_cpu_list *cpu_ptr;
22 
23 /* Structure array that holds CPU specific errata information */
24 struct em_cpu_list cpu_list[] = {
25 #if CORTEX_A78_H_INC
26 {
27 	.cpu_partnumber = CORTEX_A78_MIDR,
28 	.cpu_errata_list = {
29 		[0] = {2712571, 0x00, 0x12, ERRATA_A78_2712571, ERRATA_NON_ARM_INTERCONNECT},
30 		[1 ... ERRATA_LIST_END] = UNDEF_ERRATA,
31 	}
32 },
33 #endif /* CORTEX_A78_H_INC */
34 
35 #if CORTEX_A78_AE_H_INC
36 {
37 	.cpu_partnumber = CORTEX_A78_AE_MIDR,
38 	.cpu_errata_list = {
39 		[0] = {2712574, 0x00, 0x02, ERRATA_A78_AE_2712574, ERRATA_NON_ARM_INTERCONNECT},
40 		[1 ... ERRATA_LIST_END] = UNDEF_ERRATA,
41 	}
42 },
43 #endif /* CORTEX_A78_AE_H_INC */
44 
45 #if CORTEX_A78C_H_INC
46 {
47 	.cpu_partnumber = CORTEX_A78C_MIDR,
48 	.cpu_errata_list = {
49 		[0] = {2712575, 0x01, 0x02, ERRATA_A78C_2712575, ERRATA_NON_ARM_INTERCONNECT},
50 		[1 ... ERRATA_LIST_END] = UNDEF_ERRATA,
51 	}
52 },
53 #endif /* CORTEX_A78C_H_INC */
54 
55 #if NEOVERSE_V1_H_INC
56 {
57 	.cpu_partnumber = NEOVERSE_V1_MIDR,
58 	.cpu_errata_list = {
59 		[0] = {2701953, 0x00, 0x11, ERRATA_V1_2701953, ERRATA_NON_ARM_INTERCONNECT},
60 		[1 ... ERRATA_LIST_END] = UNDEF_ERRATA,
61 	}
62 },
63 #endif /* NEOVERSE_V1_H_INC */
64 
65 #if CORTEX_A710_H_INC
66 {
67 	.cpu_partnumber = CORTEX_A710_MIDR,
68 	.cpu_errata_list = {
69 		[0] = {2701952, 0x00, 0x21, ERRATA_A710_2701952, ERRATA_NON_ARM_INTERCONNECT},
70 		[1 ... ERRATA_LIST_END] = UNDEF_ERRATA,
71 	}
72 },
73 #endif /* CORTEX_A710_H_INC */
74 
75 #if NEOVERSE_N2_H_INC
76 {
77 	.cpu_partnumber = NEOVERSE_N2_MIDR,
78 	.cpu_errata_list = {
79 		[0] = {2728475, 0x00, 0x02, ERRATA_N2_2728475, ERRATA_NON_ARM_INTERCONNECT},
80 		[1 ... ERRATA_LIST_END] = UNDEF_ERRATA,
81 	}
82 },
83 #endif /* NEOVERSE_N2_H_INC */
84 
85 #if CORTEX_X2_H_INC
86 {
87 	.cpu_partnumber = CORTEX_X2_MIDR,
88 	.cpu_errata_list = {
89 		[0] = {2701952, 0x00, 0x21, ERRATA_X2_2701952, ERRATA_NON_ARM_INTERCONNECT},
90 		[1 ... ERRATA_LIST_END] = UNDEF_ERRATA,
91 	}
92 },
93 #endif /* CORTEX_X2_H_INC */
94 
95 #if NEOVERSE_V2_H_INC
96 {
97 	.cpu_partnumber = NEOVERSE_V2_MIDR,
98 	.cpu_errata_list = {
99 		[0] = {2719103, 0x00, 0x01, ERRATA_V2_2719103, ERRATA_NON_ARM_INTERCONNECT},
100 		[1 ... ERRATA_LIST_END] = UNDEF_ERRATA,
101 	}
102 },
103 #endif /* NEOVERSE_V2_H_INC */
104 
105 #if CORTEX_A715_H_INC
106 {
107 	.cpu_partnumber = CORTEX_A715_MIDR,
108 	.cpu_errata_list = {
109 		[0] = {2701951, 0x00, 0x11, ERRATA_A715_2701951, ERRATA_NON_ARM_INTERCONNECT},
110 		[1 ... ERRATA_LIST_END] = UNDEF_ERRATA,
111 	}
112 },
113 #endif /* CORTEX_A715_H_INC */
114 
115 };
116 
117 /* Function to check if the errata exists for the specific CPU and rxpx */
118 int32_t verify_errata_implemented(uint32_t errata_id, uint32_t forward_flag)
119 {
120 	int32_t ret_val;
121 	struct cpu_ops *cpu_ops;
122 	struct erratum_entry *entry, *end;
123 	long rev_var;
124 
125 	ret_val = EM_UNKNOWN_ERRATUM;
126 
127 	cpu_ops = get_cpu_ops_ptr();
128 	assert(cpu_ops != NULL);
129 
130 	entry = cpu_ops->errata_list_start;
131 	assert(entry != NULL);
132 
133 	end = cpu_ops->errata_list_end;
134 	assert(end != NULL);
135 
136 	rev_var = cpu_get_rev_var();
137 
138 	end--; /* point to the last erratum entry of the queried cpu */
139 
140 	while (entry <= end) {
141 		if (entry->id == errata_id) {
142 			if (entry->check_func(rev_var)) {
143 				if (entry->chosen)
144 					return EM_HIGHER_EL_MITIGATION;
145 				else
146 					return EM_AFFECTED;
147 			}
148 			return EM_NOT_AFFECTED;
149 		}
150 		entry += 1;
151 	}
152 	return ret_val;
153 }
154 
155 /* Predicate indicating that a function id is part of EM_ABI */
156 bool is_errata_fid(uint32_t smc_fid)
157 {
158 	return ((smc_fid == ARM_EM_VERSION) ||
159 		(smc_fid == ARM_EM_FEATURES) ||
160 		(smc_fid == ARM_EM_CPU_ERRATUM_FEATURES));
161 
162 }
163 
164 bool validate_spsr_mode(void)
165 {
166 	/* In AArch64, if the caller is EL1, return true */
167 
168 	#if __aarch64__
169 		if (GET_EL(read_spsr_el3()) == MODE_EL1) {
170 			return true;
171 		}
172 		return false;
173 	#else
174 
175 	/* In AArch32, if in system/svc mode, return true */
176 		uint8_t read_el_state = GET_M32(read_spsr());
177 
178 		if ((read_el_state == (MODE32_svc)) || (read_el_state == MODE32_sys)) {
179 			return true;
180 		}
181 		return false;
182 	#endif /* __aarch64__ */
183 }
184 
185 uintptr_t errata_abi_smc_handler(uint32_t smc_fid, u_register_t x1,
186 				u_register_t x2, u_register_t x3, u_register_t x4,
187 				void *cookie, void *handle, u_register_t flags)
188 {
189 	int32_t ret_id = EM_UNKNOWN_ERRATUM;
190 
191 	switch (smc_fid) {
192 	case ARM_EM_VERSION:
193 		SMC_RET1(handle, MAKE_SMCCC_VERSION(
194 			EM_VERSION_MAJOR, EM_VERSION_MINOR
195 		));
196 		break; /* unreachable */
197 	case ARM_EM_FEATURES:
198 		if (is_errata_fid((uint32_t)x1)) {
199 			SMC_RET1(handle, EM_SUCCESS);
200 		}
201 
202 		SMC_RET1(handle, EM_NOT_SUPPORTED);
203 		break; /* unreachable */
204 	case ARM_EM_CPU_ERRATUM_FEATURES:
205 
206 		/*
207 		 * If the forward flag is greater than zero and the calling EL
208 		 * is EL1 in AArch64 or in system mode or svc mode in case of AArch32,
209 		 * return Invalid Parameters.
210 		 */
211 		if (((uint32_t)x2 != 0) && (validate_spsr_mode())) {
212 			SMC_RET1(handle, EM_INVALID_PARAMETERS);
213 		}
214 		ret_id = verify_errata_implemented((uint32_t)x1, (uint32_t)x2);
215 		SMC_RET1(handle, ret_id);
216 		break; /* unreachable */
217 	default:
218 		{
219 		   WARN("Unimplemented Errata ABI Service Call: 0x%x\n", smc_fid);
220 		   SMC_RET1(handle, EM_UNKNOWN_ERRATUM);
221 		   break; /* unreachable */
222 		}
223 	}
224 }
225