xref: /arm-trusted-firmware/services/std_svc/errata_abi/errata_abi_main.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <assert.h>
8*91f16700Schasinglulu #include "cpu_errata_info.h"
9*91f16700Schasinglulu #include <lib/smccc.h>
10*91f16700Schasinglulu #include <lib/utils_def.h>
11*91f16700Schasinglulu #include <services/errata_abi_svc.h>
12*91f16700Schasinglulu #include <smccc_helpers.h>
13*91f16700Schasinglulu 
14*91f16700Schasinglulu /*
15*91f16700Schasinglulu  * Global pointer that points to the specific
16*91f16700Schasinglulu  * structure based on the MIDR part number
17*91f16700Schasinglulu  */
18*91f16700Schasinglulu struct em_cpu_list *cpu_ptr;
19*91f16700Schasinglulu 
20*91f16700Schasinglulu extern uint8_t cpu_get_rev_var(void);
21*91f16700Schasinglulu 
22*91f16700Schasinglulu /* Structure array that holds CPU specific errata information */
23*91f16700Schasinglulu struct em_cpu_list cpu_list[] = {
24*91f16700Schasinglulu #if CORTEX_A9_H_INC
25*91f16700Schasinglulu {
26*91f16700Schasinglulu 	.cpu_partnumber = CORTEX_A9_MIDR,
27*91f16700Schasinglulu 	.cpu_errata_list = {
28*91f16700Schasinglulu 		[0] = {794073, 0x00, 0xFF, ERRATA_A9_794073},
29*91f16700Schasinglulu 		[1 ... ERRATA_LIST_END] = UNDEF_ERRATA,
30*91f16700Schasinglulu 	}
31*91f16700Schasinglulu },
32*91f16700Schasinglulu #endif /* CORTEX_A9_H_INC */
33*91f16700Schasinglulu 
34*91f16700Schasinglulu #if CORTEX_A15_H_INC
35*91f16700Schasinglulu {
36*91f16700Schasinglulu 	.cpu_partnumber = CORTEX_A15_MIDR,
37*91f16700Schasinglulu 	.cpu_errata_list = {
38*91f16700Schasinglulu 		[0] = {816470, 0x30, 0xFF, ERRATA_A15_816470},
39*91f16700Schasinglulu 		[1] = {827671, 0x30, 0xFF, ERRATA_A15_827671},
40*91f16700Schasinglulu 		[2 ... ERRATA_LIST_END] = UNDEF_ERRATA,
41*91f16700Schasinglulu 	}
42*91f16700Schasinglulu },
43*91f16700Schasinglulu #endif /* CORTEX_A15_H_INC */
44*91f16700Schasinglulu 
45*91f16700Schasinglulu #if CORTEX_A17_H_INC
46*91f16700Schasinglulu {
47*91f16700Schasinglulu 	.cpu_partnumber = CORTEX_A17_MIDR,
48*91f16700Schasinglulu 	.cpu_errata_list = {
49*91f16700Schasinglulu 		[0] = {852421, 0x00, 0x12, ERRATA_A17_852421},
50*91f16700Schasinglulu 		[1] = {852423, 0x00, 0x12, ERRATA_A17_852423},
51*91f16700Schasinglulu 		[2 ... ERRATA_LIST_END] = UNDEF_ERRATA,
52*91f16700Schasinglulu 	}
53*91f16700Schasinglulu },
54*91f16700Schasinglulu #endif /* CORTEX_A17_H_INC */
55*91f16700Schasinglulu 
56*91f16700Schasinglulu #if CORTEX_A35_H_INC
57*91f16700Schasinglulu {
58*91f16700Schasinglulu 	.cpu_partnumber = CORTEX_A35_MIDR,
59*91f16700Schasinglulu 	.cpu_errata_list = {
60*91f16700Schasinglulu 		[0] = {855472, 0x00, 0x00, ERRATA_A35_855472},
61*91f16700Schasinglulu 		[1 ... ERRATA_LIST_END] = UNDEF_ERRATA,
62*91f16700Schasinglulu 	}
63*91f16700Schasinglulu },
64*91f16700Schasinglulu #endif /* CORTEX_A35_H_INC */
65*91f16700Schasinglulu 
66*91f16700Schasinglulu #if CORTEX_A53_H_INC
67*91f16700Schasinglulu {
68*91f16700Schasinglulu 	.cpu_partnumber = CORTEX_A53_MIDR,
69*91f16700Schasinglulu 	.cpu_errata_list = {
70*91f16700Schasinglulu 		[0] = {819472, 0x00, 0x01, ERRATA_A53_819472},
71*91f16700Schasinglulu 		[1] = {824069, 0x00, 0x02, ERRATA_A53_824069},
72*91f16700Schasinglulu 		[2] = {826319, 0x00, 0x02, ERRATA_A53_826319},
73*91f16700Schasinglulu 		[3] = {827319, 0x00, 0x02, ERRATA_A53_827319},
74*91f16700Schasinglulu 		[4] = {835769, 0x00, 0x04, ERRATA_A53_835769},
75*91f16700Schasinglulu 		[5] = {836870, 0x00, 0x03, ERRATA_A53_836870},
76*91f16700Schasinglulu 		[6] = {843419, 0x00, 0x04, ERRATA_A53_843419},
77*91f16700Schasinglulu 		[7] = {855873, 0x03, 0xFF, ERRATA_A53_855873},
78*91f16700Schasinglulu 		[8] = {1530924, 0x00, 0xFF, ERRATA_A53_1530924},
79*91f16700Schasinglulu 		[9 ... ERRATA_LIST_END] = UNDEF_ERRATA,
80*91f16700Schasinglulu 	}
81*91f16700Schasinglulu },
82*91f16700Schasinglulu #endif /* CORTEX_A53_H_INC */
83*91f16700Schasinglulu 
84*91f16700Schasinglulu #if CORTEX_A55_H_INC
85*91f16700Schasinglulu {
86*91f16700Schasinglulu 	.cpu_partnumber = CORTEX_A55_MIDR,
87*91f16700Schasinglulu 	.cpu_errata_list = {
88*91f16700Schasinglulu 		[0] = {768277, 0x00, 0x00, ERRATA_A55_768277},
89*91f16700Schasinglulu 		[1] = {778703, 0x00, 0x00, ERRATA_A55_778703},
90*91f16700Schasinglulu 		[2] = {798797, 0x00, 0x00, ERRATA_A55_798797},
91*91f16700Schasinglulu 		[3] = {846532, 0x00, 0x01, ERRATA_A55_846532},
92*91f16700Schasinglulu 		[4] = {903758, 0x00, 0x01, ERRATA_A55_903758},
93*91f16700Schasinglulu 		[5] = {1221012, 0x00, 0x10, ERRATA_A55_1221012},
94*91f16700Schasinglulu 		[6] = {1530923, 0x00, 0xFF, ERRATA_A55_1530923},
95*91f16700Schasinglulu 		[7 ... ERRATA_LIST_END] = UNDEF_ERRATA,
96*91f16700Schasinglulu 	}
97*91f16700Schasinglulu },
98*91f16700Schasinglulu #endif /* CORTEX_A55_H_INC */
99*91f16700Schasinglulu 
100*91f16700Schasinglulu #if CORTEX_A57_H_INC
101*91f16700Schasinglulu {
102*91f16700Schasinglulu 	.cpu_partnumber = CORTEX_A57_MIDR,
103*91f16700Schasinglulu 	.cpu_errata_list = {
104*91f16700Schasinglulu 		[0] = {806969, 0x00, 0x00, ERRATA_A57_806969},
105*91f16700Schasinglulu 		[1] = {813419, 0x00, 0x00, ERRATA_A57_813419},
106*91f16700Schasinglulu 		[2] = {813420, 0x00, 0x00, ERRATA_A57_813420},
107*91f16700Schasinglulu 		[3] = {814670, 0x00, 0x00, ERRATA_A57_814670},
108*91f16700Schasinglulu 		[4] = {817169, 0x00, 0x01, ERRATA_A57_817169},
109*91f16700Schasinglulu 		[5] = {826974, 0x00, 0x11, ERRATA_A57_826974},
110*91f16700Schasinglulu 		[6] = {826977, 0x00, 0x11, ERRATA_A57_826977},
111*91f16700Schasinglulu 		[7] = {828024, 0x00, 0x11, ERRATA_A57_828024},
112*91f16700Schasinglulu 		[8] = {829520, 0x00, 0x12, ERRATA_A57_829520},
113*91f16700Schasinglulu 		[9] = {833471, 0x00, 0x12, ERRATA_A57_833471},
114*91f16700Schasinglulu 		[10] = {859972, 0x00, 0x13, ERRATA_A57_859972},
115*91f16700Schasinglulu 		[11] = {1319537, 0x00, 0xFF, ERRATA_A57_1319537},
116*91f16700Schasinglulu 		[12 ... ERRATA_LIST_END] = UNDEF_ERRATA,
117*91f16700Schasinglulu 	}
118*91f16700Schasinglulu },
119*91f16700Schasinglulu #endif /* CORTEX_A57_H_INC */
120*91f16700Schasinglulu 
121*91f16700Schasinglulu #if CORTEX_A72_H_INC
122*91f16700Schasinglulu {
123*91f16700Schasinglulu 	.cpu_partnumber = CORTEX_A72_MIDR,
124*91f16700Schasinglulu 	.cpu_errata_list = {
125*91f16700Schasinglulu 		[0] = {859971, 0x00, 0x03, ERRATA_A72_859971},
126*91f16700Schasinglulu 		[1] = {1319367, 0x00, 0xFF, ERRATA_A72_1319367},
127*91f16700Schasinglulu 		[2 ... ERRATA_LIST_END] = UNDEF_ERRATA,
128*91f16700Schasinglulu 	}
129*91f16700Schasinglulu },
130*91f16700Schasinglulu #endif /* CORTEX_A72_H_INC */
131*91f16700Schasinglulu 
132*91f16700Schasinglulu #if CORTEX_A73_H_INC
133*91f16700Schasinglulu {
134*91f16700Schasinglulu 	.cpu_partnumber = CORTEX_A73_MIDR,
135*91f16700Schasinglulu 	.cpu_errata_list = {
136*91f16700Schasinglulu 		[0] = {852427, 0x00, 0x00, ERRATA_A73_852427},
137*91f16700Schasinglulu 		[1] = {855423, 0x00, 0x01, ERRATA_A73_855423},
138*91f16700Schasinglulu 		[2 ... ERRATA_LIST_END] = UNDEF_ERRATA,
139*91f16700Schasinglulu 	}
140*91f16700Schasinglulu },
141*91f16700Schasinglulu #endif /* CORTEX_A73_H_INC */
142*91f16700Schasinglulu 
143*91f16700Schasinglulu #if CORTEX_A75_H_INC
144*91f16700Schasinglulu {
145*91f16700Schasinglulu 	.cpu_partnumber = CORTEX_A75_MIDR,
146*91f16700Schasinglulu 	.cpu_errata_list = {
147*91f16700Schasinglulu 		[0] = {764081, 0x00, 0x00, ERRATA_A75_764081},
148*91f16700Schasinglulu 		[1] = {790748, 0x00, 0x00, ERRATA_A75_790748},
149*91f16700Schasinglulu 		[2 ... ERRATA_LIST_END] = UNDEF_ERRATA,
150*91f16700Schasinglulu 	}
151*91f16700Schasinglulu },
152*91f16700Schasinglulu #endif /* CORTEX_A75_H_INC */
153*91f16700Schasinglulu 
154*91f16700Schasinglulu #if CORTEX_A76_H_INC
155*91f16700Schasinglulu {
156*91f16700Schasinglulu 	.cpu_partnumber = CORTEX_A76_MIDR,
157*91f16700Schasinglulu 	.cpu_errata_list = {
158*91f16700Schasinglulu 		[0] = {1073348, 0x00, 0x10, ERRATA_A76_1073348},
159*91f16700Schasinglulu 		[1] = {1130799, 0x00, 0x20, ERRATA_A76_1130799},
160*91f16700Schasinglulu 		[2] = {1165522, 0x00, 0xFF, ERRATA_A76_1165522},
161*91f16700Schasinglulu 		[3] = {1220197, 0x00, 0x20, ERRATA_A76_1220197},
162*91f16700Schasinglulu 		[4] = {1257314, 0x00, 0x30, ERRATA_A76_1257314},
163*91f16700Schasinglulu 		[5] = {1262606, 0x00, 0x30, ERRATA_A76_1262606},
164*91f16700Schasinglulu 		[6] = {1262888, 0x00, 0x30, ERRATA_A76_1262888},
165*91f16700Schasinglulu 		[7] = {1275112, 0x00, 0x30, ERRATA_A76_1275112},
166*91f16700Schasinglulu 		[8] = {1286807, 0x00, 0x30, ERRATA_A76_1286807},
167*91f16700Schasinglulu 		[9] = {1791580, 0x00, 0x40, ERRATA_A76_1791580},
168*91f16700Schasinglulu 		[10] = {1868343, 0x00, 0x40, ERRATA_A76_1868343},
169*91f16700Schasinglulu 		[11] = {1946160, 0x30, 0x41, ERRATA_A76_1946160},
170*91f16700Schasinglulu 		[12] = {2743102, 0x00, 0x41, ERRATA_A76_2743102},
171*91f16700Schasinglulu 		[13 ... ERRATA_LIST_END] = UNDEF_ERRATA,
172*91f16700Schasinglulu 	}
173*91f16700Schasinglulu },
174*91f16700Schasinglulu #endif /* CORTEX_A76_H_INC */
175*91f16700Schasinglulu 
176*91f16700Schasinglulu #if CORTEX_A77_H_INC
177*91f16700Schasinglulu {
178*91f16700Schasinglulu 	.cpu_partnumber = CORTEX_A77_MIDR,
179*91f16700Schasinglulu 	.cpu_errata_list = {
180*91f16700Schasinglulu 		[0] = {1508412, 0x00, 0x10, ERRATA_A77_1508412},
181*91f16700Schasinglulu 		[1] = {1791578, 0x00, 0x11, ERRATA_A77_1791578},
182*91f16700Schasinglulu 		[2] = {1800714, 0x00, 0x11, ERRATA_A77_1800714},
183*91f16700Schasinglulu 		[3] = {1925769, 0x00, 0x11, ERRATA_A77_1925769},
184*91f16700Schasinglulu 		[4] = {1946167, 0x00, 0x11, ERRATA_A77_1946167},
185*91f16700Schasinglulu 		[5] = {2356587, 0x00, 0x11, ERRATA_A77_2356587},
186*91f16700Schasinglulu 		[6] = {2743100, 0x00, 0x11, ERRATA_A77_2743100},
187*91f16700Schasinglulu 		[7 ... ERRATA_LIST_END] = UNDEF_ERRATA,
188*91f16700Schasinglulu 	}
189*91f16700Schasinglulu },
190*91f16700Schasinglulu #endif /* CORTEX_A77_H_INC */
191*91f16700Schasinglulu 
192*91f16700Schasinglulu #if CORTEX_A78_H_INC
193*91f16700Schasinglulu {
194*91f16700Schasinglulu 	.cpu_partnumber = CORTEX_A78_MIDR,
195*91f16700Schasinglulu 	.cpu_errata_list = {
196*91f16700Schasinglulu 		[0] = {1688305, 0x00, 0x10, ERRATA_A78_1688305},
197*91f16700Schasinglulu 		[1] = {1821534, 0x00, 0x10, ERRATA_A78_1821534},
198*91f16700Schasinglulu 		[2] = {1941498, 0x00, 0x11, ERRATA_A78_1941498},
199*91f16700Schasinglulu 		[3] = {1951500, 0x10, 0x11, ERRATA_A78_1951500},
200*91f16700Schasinglulu 		[4] = {1952683, 0x00, 0x00, ERRATA_A78_1952683},
201*91f16700Schasinglulu 		[5] = {2132060, 0x00, 0x12, ERRATA_A78_2132060},
202*91f16700Schasinglulu 		[6] = {2242635, 0x10, 0x12, ERRATA_A78_2242635},
203*91f16700Schasinglulu 		[7] = {2376745, 0x00, 0x12, ERRATA_A78_2376745},
204*91f16700Schasinglulu 		[8] = {2395406, 0x00, 0x12, ERRATA_A78_2395406},
205*91f16700Schasinglulu 		[9] = {2712571, 0x00, 0x12, ERRATA_A78_2712571, \
206*91f16700Schasinglulu 			ERRATA_NON_ARM_INTERCONNECT},
207*91f16700Schasinglulu 		[10] = {2742426, 0x00, 0x12, ERRATA_A78_2742426},
208*91f16700Schasinglulu 		[11] = {2772019, 0x00, 0x12, ERRATA_A78_2772019},
209*91f16700Schasinglulu 		[12] = {2779479, 0x00, 0x12, ERRATA_A78_2779479},
210*91f16700Schasinglulu 		[13 ... ERRATA_LIST_END] = UNDEF_ERRATA,
211*91f16700Schasinglulu 	}
212*91f16700Schasinglulu },
213*91f16700Schasinglulu #endif /* CORTEX_A78_H_INC */
214*91f16700Schasinglulu 
215*91f16700Schasinglulu #if CORTEX_A78_AE_H_INC
216*91f16700Schasinglulu {
217*91f16700Schasinglulu 	.cpu_partnumber = CORTEX_A78_AE_MIDR,
218*91f16700Schasinglulu 	.cpu_errata_list = {
219*91f16700Schasinglulu 		[0] = {1941500, 0x00, 0x01, ERRATA_A78_AE_1941500},
220*91f16700Schasinglulu 		[1] = {1951502, 0x00, 0x01, ERRATA_A78_AE_1951502},
221*91f16700Schasinglulu 		[2] = {2376748, 0x00, 0x02, ERRATA_A78_AE_2376748},
222*91f16700Schasinglulu 		[3] = {2395408, 0x00, 0x01, ERRATA_A78_AE_2395408},
223*91f16700Schasinglulu 		[4] = {2712574, 0x00, 0x02, ERRATA_A78_AE_2712574, \
224*91f16700Schasinglulu 			ERRATA_NON_ARM_INTERCONNECT},
225*91f16700Schasinglulu 		[5 ... ERRATA_LIST_END] = UNDEF_ERRATA,
226*91f16700Schasinglulu 	}
227*91f16700Schasinglulu },
228*91f16700Schasinglulu #endif /* CORTEX_A78_AE_H_INC */
229*91f16700Schasinglulu 
230*91f16700Schasinglulu #if CORTEX_A78C_H_INC
231*91f16700Schasinglulu {
232*91f16700Schasinglulu 	.cpu_partnumber = CORTEX_A78C_MIDR,
233*91f16700Schasinglulu 	.cpu_errata_list = {
234*91f16700Schasinglulu 		[0] = {1827430, 0x00, 0x00, ERRATA_A78C_1827430},
235*91f16700Schasinglulu 		[1] = {1827440, 0x00, 0x00, ERRATA_A78C_1827440},
236*91f16700Schasinglulu 		[2] = {2132064, 0x01, 0x02, ERRATA_A78C_2132064},
237*91f16700Schasinglulu 		[3] = {2242638, 0x01, 0x02, ERRATA_A78C_2242638},
238*91f16700Schasinglulu 		[4] = {2376749, 0x01, 0x02, ERRATA_A78C_2376749},
239*91f16700Schasinglulu 		[5] = {2395411, 0x01, 0x02, ERRATA_A78C_2395411},
240*91f16700Schasinglulu 		[6] = {2712575, 0x01, 0x02, ERRATA_A78C_2712575, \
241*91f16700Schasinglulu 			ERRATA_NON_ARM_INTERCONNECT},
242*91f16700Schasinglulu 		[7] = {2772121, 0x00, 0x02, ERRATA_A78C_2772121},
243*91f16700Schasinglulu 		[8] = {2779484, 0x01, 0x02, ERRATA_A78C_2779484},
244*91f16700Schasinglulu 		[9 ... ERRATA_LIST_END] = UNDEF_ERRATA,
245*91f16700Schasinglulu 	}
246*91f16700Schasinglulu },
247*91f16700Schasinglulu #endif /* CORTEX_A78C_H_INC */
248*91f16700Schasinglulu 
249*91f16700Schasinglulu #if CORTEX_X1_H_INC
250*91f16700Schasinglulu {
251*91f16700Schasinglulu 	.cpu_partnumber = CORTEX_X1_MIDR,
252*91f16700Schasinglulu 	.cpu_errata_list = {
253*91f16700Schasinglulu 		[0] = {1688305, 0x00, 0x10, ERRATA_X1_1688305},
254*91f16700Schasinglulu 		[1] = {1821534, 0x00, 0x10, ERRATA_X1_1821534},
255*91f16700Schasinglulu 		[2] = {1827429, 0x00, 0x10, ERRATA_X1_1827429},
256*91f16700Schasinglulu 		[3 ... ERRATA_LIST_END] = UNDEF_ERRATA,
257*91f16700Schasinglulu 	}
258*91f16700Schasinglulu },
259*91f16700Schasinglulu #endif /* CORTEX_X1_H_INC */
260*91f16700Schasinglulu 
261*91f16700Schasinglulu #if NEOVERSE_N1_H_INC
262*91f16700Schasinglulu {
263*91f16700Schasinglulu 	.cpu_partnumber = NEOVERSE_N1_MIDR,
264*91f16700Schasinglulu 	.cpu_errata_list = {
265*91f16700Schasinglulu 		[0] = {1043202, 0x00, 0x10, ERRATA_N1_1043202},
266*91f16700Schasinglulu 		[1] = {1073348, 0x00, 0x10, ERRATA_N1_1073348},
267*91f16700Schasinglulu 		[2] = {1130799, 0x00, 0x20, ERRATA_N1_1130799},
268*91f16700Schasinglulu 		[3] = {1165347, 0x00, 0x20, ERRATA_N1_1165347},
269*91f16700Schasinglulu 		[4] = {1207823, 0x00, 0x20, ERRATA_N1_1207823},
270*91f16700Schasinglulu 		[5] = {1220197, 0x00, 0x20, ERRATA_N1_1220197},
271*91f16700Schasinglulu 		[6] = {1257314, 0x00, 0x30, ERRATA_N1_1257314},
272*91f16700Schasinglulu 		[7] = {1262606, 0x00, 0x30, ERRATA_N1_1262606},
273*91f16700Schasinglulu 		[8] = {1262888, 0x00, 0x30, ERRATA_N1_1262888},
274*91f16700Schasinglulu 		[9] = {1275112, 0x00, 0x30, ERRATA_N1_1275112},
275*91f16700Schasinglulu 		[10] = {1315703, 0x00, 0x30, ERRATA_N1_1315703},
276*91f16700Schasinglulu 		[11] = {1542419, 0x30, 0x40, ERRATA_N1_1542419},
277*91f16700Schasinglulu 		[12] = {1868343, 0x00, 0x40, ERRATA_N1_1868343},
278*91f16700Schasinglulu 		[13] = {1946160, 0x30, 0x41, ERRATA_N1_1946160},
279*91f16700Schasinglulu 		[14] = {2743102, 0x00, 0x41, ERRATA_N1_2743102},
280*91f16700Schasinglulu 		[15 ... ERRATA_LIST_END] = UNDEF_ERRATA,
281*91f16700Schasinglulu 	}
282*91f16700Schasinglulu },
283*91f16700Schasinglulu #endif /* NEOVERSE_N1_H_INC */
284*91f16700Schasinglulu 
285*91f16700Schasinglulu #if NEOVERSE_V1_H_INC
286*91f16700Schasinglulu {
287*91f16700Schasinglulu 	.cpu_partnumber = NEOVERSE_V1_MIDR,
288*91f16700Schasinglulu 	.cpu_errata_list = {
289*91f16700Schasinglulu 		[0] = {1618635, 0x00, 0x00, ERRATA_V1_1618635},
290*91f16700Schasinglulu 		[1] = {1774420, 0x00, 0x10, ERRATA_V1_1774420},
291*91f16700Schasinglulu 		[2] = {1791573, 0x00, 0x10, ERRATA_V1_1791573},
292*91f16700Schasinglulu 		[3] = {1852267, 0x00, 0x10, ERRATA_V1_1852267},
293*91f16700Schasinglulu 		[4] = {1925756, 0x00, 0x11, ERRATA_V1_1925756},
294*91f16700Schasinglulu 		[5] = {1940577, 0x10, 0x11, ERRATA_V1_1940577},
295*91f16700Schasinglulu 		[6] = {1966096, 0x10, 0x11, ERRATA_V1_1966096},
296*91f16700Schasinglulu 		[7] = {2108267, 0x00, 0x12, ERRATA_V1_2108267},
297*91f16700Schasinglulu 		[8] = {2139242, 0x00, 0x11, ERRATA_V1_2139242},
298*91f16700Schasinglulu 		[9] = {2216392, 0x10, 0x11, ERRATA_V1_2216392},
299*91f16700Schasinglulu 		[10] = {2294912, 0x00, 0x12, ERRATA_V1_2294912},
300*91f16700Schasinglulu 		[11] = {2372203, 0x00, 0x11, ERRATA_V1_2372203},
301*91f16700Schasinglulu 		[12] = {2701953, 0x00, 0x11, ERRATA_V1_2701953, \
302*91f16700Schasinglulu 			ERRATA_NON_ARM_INTERCONNECT},
303*91f16700Schasinglulu 		[13] = {2743093, 0x00, 0x12, ERRATA_V1_2743093},
304*91f16700Schasinglulu 		[14] = {2743233, 0x00, 0x12, ERRATA_V1_2743233},
305*91f16700Schasinglulu 		[15] = {2779461, 0x00, 0x12, ERRATA_V1_2779461},
306*91f16700Schasinglulu 		[16 ... ERRATA_LIST_END] = UNDEF_ERRATA,
307*91f16700Schasinglulu 	}
308*91f16700Schasinglulu },
309*91f16700Schasinglulu #endif /* NEOVERSE_V1_H_INC */
310*91f16700Schasinglulu 
311*91f16700Schasinglulu #if CORTEX_A710_H_INC
312*91f16700Schasinglulu {
313*91f16700Schasinglulu 	.cpu_partnumber = CORTEX_A710_MIDR,
314*91f16700Schasinglulu 	.cpu_errata_list = {
315*91f16700Schasinglulu 		[0] = {1987031, 0x00, 0x20, ERRATA_A710_1987031},
316*91f16700Schasinglulu 		[1] = {2008768, 0x00, 0x20, ERRATA_A710_2008768},
317*91f16700Schasinglulu 		[2] = {2017096, 0x00, 0x20, ERRATA_A710_2017096},
318*91f16700Schasinglulu 		[3] = {2055002, 0x10, 0x20, ERRATA_A710_2055002},
319*91f16700Schasinglulu 		[4] = {2058056, 0x00, 0x21, ERRATA_A710_2058056},
320*91f16700Schasinglulu 		[5] = {2081180, 0x00, 0x20, ERRATA_A710_2081180},
321*91f16700Schasinglulu 		[6] = {2083908, 0x20, 0x20, ERRATA_A710_2083908},
322*91f16700Schasinglulu 		[7] = {2136059, 0x00, 0x20, ERRATA_A710_2136059},
323*91f16700Schasinglulu 		[8] = {2147715, 0x20, 0x20, ERRATA_A710_2147715},
324*91f16700Schasinglulu 		[9] = {2216384, 0x00, 0x20, ERRATA_A710_2216384},
325*91f16700Schasinglulu 		[10] = {2267065, 0x00, 0x20, ERRATA_A710_2267065},
326*91f16700Schasinglulu 		[11] = {2282622, 0x00, 0x21, ERRATA_A710_2282622},
327*91f16700Schasinglulu 		[12] = {2291219, 0x00, 0x20, ERRATA_A710_2291219},
328*91f16700Schasinglulu 		[13] = {2371105, 0x00, 0x20, ERRATA_A710_2371105},
329*91f16700Schasinglulu 		[14] = {2701952, 0x00, 0x21, ERRATA_A710_2701952, \
330*91f16700Schasinglulu 			ERRATA_NON_ARM_INTERCONNECT},
331*91f16700Schasinglulu 		[15] = {2742423, 0x00, 0x21, ERRATA_A710_2742423},
332*91f16700Schasinglulu 		[16] = {2768515, 0x00, 0x21, ERRATA_A710_2768515},
333*91f16700Schasinglulu 		[17 ... ERRATA_LIST_END] = UNDEF_ERRATA,
334*91f16700Schasinglulu 	}
335*91f16700Schasinglulu },
336*91f16700Schasinglulu #endif /* CORTEX_A710_H_INC */
337*91f16700Schasinglulu 
338*91f16700Schasinglulu #if NEOVERSE_N2_H_INC
339*91f16700Schasinglulu {
340*91f16700Schasinglulu 	.cpu_partnumber = NEOVERSE_N2_MIDR,
341*91f16700Schasinglulu 	.cpu_errata_list = {
342*91f16700Schasinglulu 		[0] = {2002655, 0x00, 0x00, ERRATA_N2_2002655},
343*91f16700Schasinglulu 		[1] = {2009478, 0x00, 0x00, ERRATA_N2_2009478},
344*91f16700Schasinglulu 		[2] = {2025414, 0x00, 0x00, ERRATA_N2_2025414},
345*91f16700Schasinglulu 		[3] = {2067956, 0x00, 0x00, ERRATA_N2_2067956},
346*91f16700Schasinglulu 		[4] = {2138953, 0x00, 0x03, ERRATA_N2_2138953},
347*91f16700Schasinglulu 		[5] = {2138956, 0x00, 0x00, ERRATA_N2_2138956},
348*91f16700Schasinglulu 		[6] = {2138958, 0x00, 0x00, ERRATA_N2_2138958},
349*91f16700Schasinglulu 		[7] = {2189731, 0x00, 0x00, ERRATA_N2_2189731},
350*91f16700Schasinglulu 		[8] = {2242400, 0x00, 0x00, ERRATA_N2_2242400},
351*91f16700Schasinglulu 		[9] = {2242415, 0x00, 0x00, ERRATA_N2_2242415},
352*91f16700Schasinglulu 		[10] = {2280757, 0x00, 0x00, ERRATA_N2_2280757},
353*91f16700Schasinglulu 		[11] = {2326639, 0x00, 0x00, ERRATA_N2_2326639},
354*91f16700Schasinglulu 		[12] = {2340933, 0x00, 0x00, ERRATA_N2_2340933},
355*91f16700Schasinglulu 		[13] = {2346952, 0x00, 0x02, ERRATA_N2_2346952},
356*91f16700Schasinglulu 		[14] = {2376738, 0x00, 0x00, ERRATA_N2_2376738},
357*91f16700Schasinglulu 		[15] = {2388450, 0x00, 0x00, ERRATA_N2_2388450},
358*91f16700Schasinglulu 		[16] = {2728475, 0x00, 0x02, ERRATA_N2_2728475, \
359*91f16700Schasinglulu 			ERRATA_NON_ARM_INTERCONNECT},
360*91f16700Schasinglulu 		[17] = {2743014, 0x00, 0x02, ERRATA_N2_2743014},
361*91f16700Schasinglulu 		[18] = {2743089, 0x00, 0x02, ERRATA_N2_2743089},
362*91f16700Schasinglulu 		[19] = {2779511, 0x00, 0x02, ERRATA_N2_2779511},
363*91f16700Schasinglulu 		[20 ... ERRATA_LIST_END] = UNDEF_ERRATA,
364*91f16700Schasinglulu 	}
365*91f16700Schasinglulu },
366*91f16700Schasinglulu #endif /* NEOVERSE_N2_H_INC */
367*91f16700Schasinglulu 
368*91f16700Schasinglulu #if CORTEX_X2_H_INC
369*91f16700Schasinglulu {
370*91f16700Schasinglulu 	.cpu_partnumber = CORTEX_X2_MIDR,
371*91f16700Schasinglulu 	.cpu_errata_list = {
372*91f16700Schasinglulu 		[0] = {2002765, 0x00, 0x20, ERRATA_X2_2002765},
373*91f16700Schasinglulu 		[1] = {2017096, 0x00, 0x20, ERRATA_X2_2017096},
374*91f16700Schasinglulu 		[2] = {2058056, 0x00, 0x21, ERRATA_X2_2058056},
375*91f16700Schasinglulu 		[3] = {2081180, 0x00, 0x20, ERRATA_X2_2081180},
376*91f16700Schasinglulu 		[4] = {2083908, 0x20, 0x20, ERRATA_X2_2083908},
377*91f16700Schasinglulu 		[5] = {2147715, 0x20, 0x20, ERRATA_X2_2147715},
378*91f16700Schasinglulu 		[6] = {2216384, 0x00, 0x20, ERRATA_X2_2216384},
379*91f16700Schasinglulu 		[7] = {2282622, 0x00, 0x21, ERRATA_X2_2282622},
380*91f16700Schasinglulu 		[8] = {2371105, 0x00, 0x20, ERRATA_X2_2371105},
381*91f16700Schasinglulu 		[9] = {2701952, 0x00, 0x21, ERRATA_X2_2701952, \
382*91f16700Schasinglulu 			ERRATA_NON_ARM_INTERCONNECT},
383*91f16700Schasinglulu 		[10] = {2742423, 0x00, 0x21, ERRATA_X2_2742423},
384*91f16700Schasinglulu 		[11] = {2768515, 0x00, 0x21, ERRATA_X2_2768515},
385*91f16700Schasinglulu 		[12 ... ERRATA_LIST_END] = UNDEF_ERRATA,
386*91f16700Schasinglulu 	}
387*91f16700Schasinglulu },
388*91f16700Schasinglulu #endif /* CORTEX_X2_H_INC */
389*91f16700Schasinglulu 
390*91f16700Schasinglulu #if CORTEX_A510_H_INC
391*91f16700Schasinglulu {
392*91f16700Schasinglulu 	.cpu_partnumber = CORTEX_A510_MIDR,
393*91f16700Schasinglulu 	.cpu_errata_list = {
394*91f16700Schasinglulu 		[0] = {1922240, 0x00, 0x00, ERRATA_A510_1922240},
395*91f16700Schasinglulu 		[1] = {2041909, 0x02, 0x02, ERRATA_A510_2041909},
396*91f16700Schasinglulu 		[2] = {2042739, 0x00, 0x02, ERRATA_A510_2042739},
397*91f16700Schasinglulu 		[3] = {2080326, 0x02, 0x02, ERRATA_A510_2080326},
398*91f16700Schasinglulu 		[4] = {2172148, 0x00, 0x10, ERRATA_A510_2172148},
399*91f16700Schasinglulu 		[5] = {2218950, 0x00, 0x10, ERRATA_A510_2218950},
400*91f16700Schasinglulu 		[6] = {2250311, 0x00, 0x10, ERRATA_A510_2250311},
401*91f16700Schasinglulu 		[7] = {2288014, 0x00, 0x10, ERRATA_A510_2288014},
402*91f16700Schasinglulu 		[8] = {2347730, 0x00, 0x11, ERRATA_A510_2347730},
403*91f16700Schasinglulu 		[9] = {2371937, 0x00, 0x11, ERRATA_A510_2371937},
404*91f16700Schasinglulu 		[10] = {2666669, 0x00, 0x11, ERRATA_A510_2666669},
405*91f16700Schasinglulu 		[11] = {2684597, 0x00, 0x12, ERRATA_A510_2684597},
406*91f16700Schasinglulu 		[12 ... ERRATA_LIST_END] = UNDEF_ERRATA,
407*91f16700Schasinglulu 	}
408*91f16700Schasinglulu },
409*91f16700Schasinglulu #endif /* CORTEX_A510_H_INC */
410*91f16700Schasinglulu 
411*91f16700Schasinglulu #if NEOVERSE_V2_H_INC
412*91f16700Schasinglulu {
413*91f16700Schasinglulu 	.cpu_partnumber = NEOVERSE_V2_MIDR,
414*91f16700Schasinglulu 	.cpu_errata_list = {
415*91f16700Schasinglulu 		[0] = {2331132, 0x00, 0x02, ERRATA_V2_2331132},
416*91f16700Schasinglulu 		[1] = {2719103, 0x00, 0x01, ERRATA_V2_2719103, \
417*91f16700Schasinglulu 			ERRATA_NON_ARM_INTERCONNECT},
418*91f16700Schasinglulu 		[2] = {2719105, 0x00, 0x01, ERRATA_V2_2719105},
419*91f16700Schasinglulu 		[3] = {2743011, 0x00, 0x01, ERRATA_V2_2743011},
420*91f16700Schasinglulu 		[4] = {2779510, 0x00, 0x01, ERRATA_V2_2779510},
421*91f16700Schasinglulu 		[5] = {2801372, 0x00, 0x01, ERRATA_V2_2801372},
422*91f16700Schasinglulu 		[6 ... ERRATA_LIST_END] = UNDEF_ERRATA,
423*91f16700Schasinglulu 	}
424*91f16700Schasinglulu },
425*91f16700Schasinglulu #endif /* NEOVERSE_V2_H_INC */
426*91f16700Schasinglulu 
427*91f16700Schasinglulu #if CORTEX_A715_H_INC
428*91f16700Schasinglulu {
429*91f16700Schasinglulu 	.cpu_partnumber = CORTEX_A715_MIDR,
430*91f16700Schasinglulu 	.cpu_errata_list = {
431*91f16700Schasinglulu 		[0] = {2701951, 0x00, 0x11, ERRATA_A715_2701951, \
432*91f16700Schasinglulu 			ERRATA_NON_ARM_INTERCONNECT},
433*91f16700Schasinglulu 		[1 ... ERRATA_LIST_END] = UNDEF_ERRATA,
434*91f16700Schasinglulu 	}
435*91f16700Schasinglulu },
436*91f16700Schasinglulu #endif /* CORTEX_A715_H_INC */
437*91f16700Schasinglulu 
438*91f16700Schasinglulu #if CORTEX_X3_H_INC
439*91f16700Schasinglulu {
440*91f16700Schasinglulu 	.cpu_partnumber = CORTEX_X3_MIDR,
441*91f16700Schasinglulu 	.cpu_errata_list = {
442*91f16700Schasinglulu 		[0] = {2070301, 0x00, 0x12, ERRATA_X3_2070301},
443*91f16700Schasinglulu 		[1] = {2313909, 0x00, 0x10, ERRATA_X3_2313909},
444*91f16700Schasinglulu 		[2] = {2615812, 0x00, 0x11, ERRATA_X3_2615812},
445*91f16700Schasinglulu 		[3] = {2742421, 0x00, 0x11, ERRATA_X3_2742421},
446*91f16700Schasinglulu 		[4 ... ERRATA_LIST_END] = UNDEF_ERRATA,
447*91f16700Schasinglulu 	}
448*91f16700Schasinglulu },
449*91f16700Schasinglulu #endif /* CORTEX_X3_H_INC */
450*91f16700Schasinglulu };
451*91f16700Schasinglulu 
452*91f16700Schasinglulu /*
453*91f16700Schasinglulu  * Function to do binary search and check for the specific errata ID
454*91f16700Schasinglulu  * in the array of structures specific to the cpu identified.
455*91f16700Schasinglulu  */
456*91f16700Schasinglulu int32_t binary_search(struct em_cpu_list *ptr, uint32_t erratum_id, uint8_t rxpx_val)
457*91f16700Schasinglulu {
458*91f16700Schasinglulu 	int low_index = 0U, mid_index = 0U;
459*91f16700Schasinglulu 
460*91f16700Schasinglulu 	int high_index = MAX_ERRATA_ENTRIES - 1;
461*91f16700Schasinglulu 
462*91f16700Schasinglulu 	assert(ptr != NULL);
463*91f16700Schasinglulu 
464*91f16700Schasinglulu 	/*
465*91f16700Schasinglulu 	 * Pointer to the errata list of the cpu that matches
466*91f16700Schasinglulu 	 * extracted partnumber in the cpu list
467*91f16700Schasinglulu 	 */
468*91f16700Schasinglulu 	struct em_cpu *erratum_ptr = NULL;
469*91f16700Schasinglulu 
470*91f16700Schasinglulu 	while (low_index <= high_index) {
471*91f16700Schasinglulu 		mid_index = (low_index + high_index) / 2;
472*91f16700Schasinglulu 
473*91f16700Schasinglulu 		erratum_ptr = &ptr->cpu_errata_list[mid_index];
474*91f16700Schasinglulu 		assert(erratum_ptr != NULL);
475*91f16700Schasinglulu 
476*91f16700Schasinglulu 		if (erratum_id < erratum_ptr->em_errata_id) {
477*91f16700Schasinglulu 			high_index = mid_index - 1;
478*91f16700Schasinglulu 		} else if (erratum_id > erratum_ptr->em_errata_id) {
479*91f16700Schasinglulu 			low_index = mid_index + 1;
480*91f16700Schasinglulu 		} else if (erratum_id == erratum_ptr->em_errata_id) {
481*91f16700Schasinglulu 			if (RXPX_RANGE(rxpx_val, erratum_ptr->em_rxpx_lo, \
482*91f16700Schasinglulu 				erratum_ptr->em_rxpx_hi)) {
483*91f16700Schasinglulu 				if ((erratum_ptr->errata_enabled) && \
484*91f16700Schasinglulu 				(!(erratum_ptr->non_arm_interconnect))) {
485*91f16700Schasinglulu 					return EM_HIGHER_EL_MITIGATION;
486*91f16700Schasinglulu 				}
487*91f16700Schasinglulu 				return EM_AFFECTED;
488*91f16700Schasinglulu 			}
489*91f16700Schasinglulu 			return EM_NOT_AFFECTED;
490*91f16700Schasinglulu 		}
491*91f16700Schasinglulu 	}
492*91f16700Schasinglulu 	/* no matching errata ID */
493*91f16700Schasinglulu 	return EM_UNKNOWN_ERRATUM;
494*91f16700Schasinglulu }
495*91f16700Schasinglulu 
496*91f16700Schasinglulu /* Function to check if the errata exists for the specific CPU and rxpx */
497*91f16700Schasinglulu int32_t verify_errata_implemented(uint32_t errata_id, uint32_t forward_flag)
498*91f16700Schasinglulu {
499*91f16700Schasinglulu 	/*
500*91f16700Schasinglulu 	 * Read MIDR value and extract the revision, variant and partnumber
501*91f16700Schasinglulu 	 */
502*91f16700Schasinglulu 	static uint32_t midr_val, cpu_partnum;
503*91f16700Schasinglulu 	static uint8_t  cpu_rxpx_val;
504*91f16700Schasinglulu 	int32_t ret_val = EM_UNKNOWN_ERRATUM;
505*91f16700Schasinglulu 
506*91f16700Schasinglulu 	/* Determine the number of cpu listed in the cpu list */
507*91f16700Schasinglulu 	uint8_t size_cpulist = ARRAY_SIZE(cpu_list);
508*91f16700Schasinglulu 
509*91f16700Schasinglulu 	/* Read the midr reg to extract cpu, revision and variant info */
510*91f16700Schasinglulu 	midr_val = read_midr();
511*91f16700Schasinglulu 
512*91f16700Schasinglulu 	/* Extract revision and variant from the MIDR register */
513*91f16700Schasinglulu 	cpu_rxpx_val = cpu_get_rev_var();
514*91f16700Schasinglulu 
515*91f16700Schasinglulu 	/* Extract the cpu partnumber and check if the cpu is in the cpu list */
516*91f16700Schasinglulu 	cpu_partnum = EXTRACT_PARTNUM(midr_val);
517*91f16700Schasinglulu 
518*91f16700Schasinglulu 	for (uint8_t i = 0; i < size_cpulist; i++) {
519*91f16700Schasinglulu 		cpu_ptr = &cpu_list[i];
520*91f16700Schasinglulu 		uint16_t partnum_extracted = EXTRACT_PARTNUM(cpu_ptr->cpu_partnumber);
521*91f16700Schasinglulu 
522*91f16700Schasinglulu 		if (partnum_extracted == cpu_partnum) {
523*91f16700Schasinglulu 			/*
524*91f16700Schasinglulu 			 * If the midr value is in the cpu list, binary search
525*91f16700Schasinglulu 			 * for the errata ID and specific revision in the list.
526*91f16700Schasinglulu 			 */
527*91f16700Schasinglulu 			ret_val = binary_search(cpu_ptr, errata_id, cpu_rxpx_val);
528*91f16700Schasinglulu 			break;
529*91f16700Schasinglulu 		}
530*91f16700Schasinglulu 	}
531*91f16700Schasinglulu 	return ret_val;
532*91f16700Schasinglulu }
533*91f16700Schasinglulu 
534*91f16700Schasinglulu /* Predicate indicating that a function id is part of EM_ABI */
535*91f16700Schasinglulu bool is_errata_fid(uint32_t smc_fid)
536*91f16700Schasinglulu {
537*91f16700Schasinglulu 	return ((smc_fid == ARM_EM_VERSION) ||
538*91f16700Schasinglulu 		(smc_fid == ARM_EM_FEATURES) ||
539*91f16700Schasinglulu 		(smc_fid == ARM_EM_CPU_ERRATUM_FEATURES));
540*91f16700Schasinglulu 
541*91f16700Schasinglulu }
542*91f16700Schasinglulu 
543*91f16700Schasinglulu bool validate_spsr_mode(void)
544*91f16700Schasinglulu {
545*91f16700Schasinglulu 	/* In AArch64, if the caller is EL1, return true */
546*91f16700Schasinglulu 
547*91f16700Schasinglulu 	#if __aarch64__
548*91f16700Schasinglulu 		if (GET_EL(read_spsr_el3()) == MODE_EL1) {
549*91f16700Schasinglulu 			return true;
550*91f16700Schasinglulu 		}
551*91f16700Schasinglulu 		return false;
552*91f16700Schasinglulu 	#else
553*91f16700Schasinglulu 
554*91f16700Schasinglulu 	/* In AArch32, if in system/svc mode, return true */
555*91f16700Schasinglulu 		uint8_t read_el_state = GET_M32(read_spsr());
556*91f16700Schasinglulu 
557*91f16700Schasinglulu 		if ((read_el_state == (MODE32_svc)) || (read_el_state == MODE32_sys)) {
558*91f16700Schasinglulu 			return true;
559*91f16700Schasinglulu 		}
560*91f16700Schasinglulu 		return false;
561*91f16700Schasinglulu 	#endif /* __aarch64__ */
562*91f16700Schasinglulu }
563*91f16700Schasinglulu 
564*91f16700Schasinglulu uintptr_t errata_abi_smc_handler(uint32_t smc_fid, u_register_t x1,
565*91f16700Schasinglulu 				u_register_t x2, u_register_t x3, u_register_t x4,
566*91f16700Schasinglulu 				void *cookie, void *handle, u_register_t flags)
567*91f16700Schasinglulu {
568*91f16700Schasinglulu 	int32_t ret_id = EM_UNKNOWN_ERRATUM;
569*91f16700Schasinglulu 
570*91f16700Schasinglulu 	switch (smc_fid) {
571*91f16700Schasinglulu 	case ARM_EM_VERSION:
572*91f16700Schasinglulu 		SMC_RET1(handle, MAKE_SMCCC_VERSION(
573*91f16700Schasinglulu 			EM_VERSION_MAJOR, EM_VERSION_MINOR
574*91f16700Schasinglulu 		));
575*91f16700Schasinglulu 		break; /* unreachable */
576*91f16700Schasinglulu 	case ARM_EM_FEATURES:
577*91f16700Schasinglulu 		if (is_errata_fid((uint32_t)x1)) {
578*91f16700Schasinglulu 			SMC_RET1(handle, EM_SUCCESS);
579*91f16700Schasinglulu 		}
580*91f16700Schasinglulu 
581*91f16700Schasinglulu 		SMC_RET1(handle, EM_NOT_SUPPORTED);
582*91f16700Schasinglulu 		break; /* unreachable */
583*91f16700Schasinglulu 	case ARM_EM_CPU_ERRATUM_FEATURES:
584*91f16700Schasinglulu 
585*91f16700Schasinglulu 		/*
586*91f16700Schasinglulu 		 * If the forward flag is greater than zero and the calling EL
587*91f16700Schasinglulu 		 * is EL1 in AArch64 or in system mode or svc mode in case of AArch32,
588*91f16700Schasinglulu 		 * return Invalid Parameters.
589*91f16700Schasinglulu 		 */
590*91f16700Schasinglulu 		if (((uint32_t)x2 != 0) && (validate_spsr_mode())) {
591*91f16700Schasinglulu 			SMC_RET1(handle, EM_INVALID_PARAMETERS);
592*91f16700Schasinglulu 		}
593*91f16700Schasinglulu 		ret_id = verify_errata_implemented((uint32_t)x1, (uint32_t)x2);
594*91f16700Schasinglulu 		SMC_RET1(handle, ret_id);
595*91f16700Schasinglulu 		break; /* unreachable */
596*91f16700Schasinglulu 	default:
597*91f16700Schasinglulu 		{
598*91f16700Schasinglulu 		   WARN("Unimplemented Errata ABI Service Call: 0x%x\n", smc_fid);
599*91f16700Schasinglulu 		   SMC_RET1(handle, EM_UNKNOWN_ERRATUM);
600*91f16700Schasinglulu 		   break; /* unreachable */
601*91f16700Schasinglulu 		}
602*91f16700Schasinglulu 	}
603*91f16700Schasinglulu }
604