diff options
Diffstat (limited to 'meta/recipes-devtools/gcc/gcc-9.3/0002-aarch64-Introduce-SLS-mitigation-for-RET-and-BR-inst.patch')
-rw-r--r-- | meta/recipes-devtools/gcc/gcc-9.3/0002-aarch64-Introduce-SLS-mitigation-for-RET-and-BR-inst.patch | 600 |
1 files changed, 0 insertions, 600 deletions
diff --git a/meta/recipes-devtools/gcc/gcc-9.3/0002-aarch64-Introduce-SLS-mitigation-for-RET-and-BR-inst.patch b/meta/recipes-devtools/gcc/gcc-9.3/0002-aarch64-Introduce-SLS-mitigation-for-RET-and-BR-inst.patch deleted file mode 100644 index c972088d2b..0000000000 --- a/meta/recipes-devtools/gcc/gcc-9.3/0002-aarch64-Introduce-SLS-mitigation-for-RET-and-BR-inst.patch +++ /dev/null | |||
@@ -1,600 +0,0 @@ | |||
1 | CVE: CVE-2020-13844 | ||
2 | Upstream-Status: Backport | ||
3 | Signed-off-by: Ross Burton <ross.burton@arm.com> | ||
4 | |||
5 | From dc586a749228ecfb71f72ec2ca10e6f7b6874af3 Mon Sep 17 00:00:00 2001 | ||
6 | From: Matthew Malcomson <matthew.malcomson@arm.com> | ||
7 | Date: Thu, 9 Jul 2020 09:11:59 +0100 | ||
8 | Subject: [PATCH 2/3] aarch64: Introduce SLS mitigation for RET and BR | ||
9 | instructions | ||
10 | |||
11 | Instructions following RET or BR are not necessarily executed. In order | ||
12 | to avoid speculation past RET and BR we can simply append a speculation | ||
13 | barrier. | ||
14 | |||
15 | Since these speculation barriers will not be architecturally executed, | ||
16 | they are not expected to add a high performance penalty. | ||
17 | |||
18 | The speculation barrier is to be SB when targeting architectures which | ||
19 | have this enabled, and DSB SY + ISB otherwise. | ||
20 | |||
21 | We add tests for each of the cases where such an instruction was seen. | ||
22 | |||
23 | This is implemented by modifying each machine description pattern that | ||
24 | emits either a RET or a BR instruction. We choose not to use something | ||
25 | like `TARGET_ASM_FUNCTION_EPILOGUE` since it does not affect the | ||
26 | `indirect_jump`, `jump`, `sibcall_insn` and `sibcall_value_insn` | ||
27 | patterns and we find it preferable to implement the functionality in the | ||
28 | same way for every pattern. | ||
29 | |||
30 | There is one particular case which is slightly tricky. The | ||
31 | implementation of TARGET_ASM_TRAMPOLINE_TEMPLATE uses a BR which needs | ||
32 | to be mitigated against. The trampoline template is used *once* per | ||
33 | compilation unit, and the TRAMPOLINE_SIZE is exposed to the user via the | ||
34 | builtin macro __LIBGCC_TRAMPOLINE_SIZE__. | ||
35 | In the future we may implement function specific attributes to turn on | ||
36 | and off hardening on a per-function basis. | ||
37 | The fixed nature of the trampoline described above implies it will be | ||
38 | safer to ensure this speculation barrier is always used. | ||
39 | |||
40 | Testing: | ||
41 | Bootstrap and regtest done on aarch64-none-linux | ||
42 | Used a temporary hack(1) to use these options on every test in the | ||
43 | testsuite and a script to check that the output never emitted an | ||
44 | unmitigated RET or BR. | ||
45 | |||
46 | 1) Temporary hack was a change to the testsuite to always use | ||
47 | `-save-temps` and run a script on the assembly output of those | ||
48 | compilations which produced one to ensure every RET or BR is immediately | ||
49 | followed by a speculation barrier. | ||
50 | |||
51 | (cherry picked from be178ecd5ac1fe1510d960ff95c66d0ff831afe1) | ||
52 | |||
53 | gcc/ChangeLog: | ||
54 | |||
55 | * config/aarch64/aarch64-protos.h (aarch64_sls_barrier): New. | ||
56 | * config/aarch64/aarch64.c (aarch64_output_casesi): Emit | ||
57 | speculation barrier after BR instruction if needs be. | ||
58 | (aarch64_trampoline_init): Handle ptr_mode value & adjust size | ||
59 | of code copied. | ||
60 | (aarch64_sls_barrier): New. | ||
61 | (aarch64_asm_trampoline_template): Add needed barriers. | ||
62 | * config/aarch64/aarch64.h (AARCH64_ISA_SB): New. | ||
63 | (TARGET_SB): New. | ||
64 | (TRAMPOLINE_SIZE): Account for barrier. | ||
65 | * config/aarch64/aarch64.md (indirect_jump, *casesi_dispatch, | ||
66 | simple_return, *do_return, *sibcall_insn, *sibcall_value_insn): | ||
67 | Emit barrier if needs be, also account for possible barrier using | ||
68 | "sls_length" attribute. | ||
69 | (sls_length): New attribute. | ||
70 | (length): Determine default using any non-default sls_length | ||
71 | value. | ||
72 | |||
73 | gcc/testsuite/ChangeLog: | ||
74 | |||
75 | * gcc.target/aarch64/sls-mitigation/sls-miti-retbr.c: New test. | ||
76 | * gcc.target/aarch64/sls-mitigation/sls-miti-retbr-pacret.c: | ||
77 | New test. | ||
78 | * gcc.target/aarch64/sls-mitigation/sls-mitigation.exp: New file. | ||
79 | * lib/target-supports.exp (check_effective_target_aarch64_asm_sb_ok): | ||
80 | New proc. | ||
81 | --- | ||
82 | gcc/config/aarch64/aarch64-protos.h | 1 + | ||
83 | gcc/config/aarch64/aarch64.c | 41 +++++- | ||
84 | gcc/config/aarch64/aarch64.h | 10 +- | ||
85 | gcc/config/aarch64/aarch64.md | 75 ++++++++--- | ||
86 | .../sls-mitigation/sls-miti-retbr-pacret.c | 15 +++ | ||
87 | .../aarch64/sls-mitigation/sls-miti-retbr.c | 119 ++++++++++++++++++ | ||
88 | .../aarch64/sls-mitigation/sls-mitigation.exp | 73 +++++++++++ | ||
89 | gcc/testsuite/lib/target-supports.exp | 3 +- | ||
90 | 8 files changed, 312 insertions(+), 25 deletions(-) | ||
91 | create mode 100644 gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-miti-retbr-pacret.c | ||
92 | create mode 100644 gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-miti-retbr.c | ||
93 | create mode 100644 gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-mitigation.exp | ||
94 | |||
95 | diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h | ||
96 | index 31493f412..885eae893 100644 | ||
97 | --- a/gcc/config/aarch64/aarch64-protos.h | ||
98 | +++ b/gcc/config/aarch64/aarch64-protos.h | ||
99 | @@ -644,6 +644,7 @@ poly_uint64 aarch64_regmode_natural_size (machine_mode); | ||
100 | |||
101 | bool aarch64_high_bits_all_ones_p (HOST_WIDE_INT); | ||
102 | |||
103 | +const char *aarch64_sls_barrier (int); | ||
104 | extern bool aarch64_harden_sls_retbr_p (void); | ||
105 | extern bool aarch64_harden_sls_blr_p (void); | ||
106 | |||
107 | diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c | ||
108 | index 269ff6c92..dff61105c 100644 | ||
109 | --- a/gcc/config/aarch64/aarch64.c | ||
110 | +++ b/gcc/config/aarch64/aarch64.c | ||
111 | @@ -8412,8 +8412,8 @@ aarch64_return_addr (int count, rtx frame ATTRIBUTE_UNUSED) | ||
112 | static void | ||
113 | aarch64_asm_trampoline_template (FILE *f) | ||
114 | { | ||
115 | - int offset1 = 16; | ||
116 | - int offset2 = 20; | ||
117 | + int offset1 = 24; | ||
118 | + int offset2 = 28; | ||
119 | |||
120 | if (aarch64_bti_enabled ()) | ||
121 | { | ||
122 | @@ -8436,6 +8436,17 @@ aarch64_asm_trampoline_template (FILE *f) | ||
123 | } | ||
124 | asm_fprintf (f, "\tbr\t%s\n", reg_names [IP1_REGNUM]); | ||
125 | |||
126 | + /* We always emit a speculation barrier. | ||
127 | + This is because the same trampoline template is used for every nested | ||
128 | + function. Since nested functions are not particularly common or | ||
129 | + performant we don't worry too much about the extra instructions to copy | ||
130 | + around. | ||
131 | + This is not yet a problem, since we have not yet implemented function | ||
132 | + specific attributes to choose between hardening against straight line | ||
133 | + speculation or not, but such function specific attributes are likely to | ||
134 | + happen in the future. */ | ||
135 | + asm_fprintf (f, "\tdsb\tsy\n\tisb\n"); | ||
136 | + | ||
137 | /* The trampoline needs an extra padding instruction. In case if BTI is | ||
138 | enabled the padding instruction is replaced by the BTI instruction at | ||
139 | the beginning. */ | ||
140 | @@ -8450,10 +8461,14 @@ static void | ||
141 | aarch64_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) | ||
142 | { | ||
143 | rtx fnaddr, mem, a_tramp; | ||
144 | - const int tramp_code_sz = 16; | ||
145 | + const int tramp_code_sz = 24; | ||
146 | |||
147 | /* Don't need to copy the trailing D-words, we fill those in below. */ | ||
148 | - emit_block_move (m_tramp, assemble_trampoline_template (), | ||
149 | + /* We create our own memory address in Pmode so that `emit_block_move` can | ||
150 | + use parts of the backend which expect Pmode addresses. */ | ||
151 | + rtx temp = convert_memory_address (Pmode, XEXP (m_tramp, 0)); | ||
152 | + emit_block_move (gen_rtx_MEM (BLKmode, temp), | ||
153 | + assemble_trampoline_template (), | ||
154 | GEN_INT (tramp_code_sz), BLOCK_OP_NORMAL); | ||
155 | mem = adjust_address (m_tramp, ptr_mode, tramp_code_sz); | ||
156 | fnaddr = XEXP (DECL_RTL (fndecl), 0); | ||
157 | @@ -8640,6 +8655,8 @@ aarch64_output_casesi (rtx *operands) | ||
158 | output_asm_insn (buf, operands); | ||
159 | output_asm_insn (patterns[index][1], operands); | ||
160 | output_asm_insn ("br\t%3", operands); | ||
161 | + output_asm_insn (aarch64_sls_barrier (aarch64_harden_sls_retbr_p ()), | ||
162 | + operands); | ||
163 | assemble_label (asm_out_file, label); | ||
164 | return ""; | ||
165 | } | ||
166 | @@ -18976,6 +18993,22 @@ aarch64_file_end_indicate_exec_stack () | ||
167 | #undef GNU_PROPERTY_AARCH64_FEATURE_1_BTI | ||
168 | #undef GNU_PROPERTY_AARCH64_FEATURE_1_AND | ||
169 | |||
170 | +/* Helper function for straight line speculation. | ||
171 | + Return what barrier should be emitted for straight line speculation | ||
172 | + mitigation. | ||
173 | + When not mitigating against straight line speculation this function returns | ||
174 | + an empty string. | ||
175 | + When mitigating against straight line speculation, use: | ||
176 | + * SB when the v8.5-A SB extension is enabled. | ||
177 | + * DSB+ISB otherwise. */ | ||
178 | +const char * | ||
179 | +aarch64_sls_barrier (int mitigation_required) | ||
180 | +{ | ||
181 | + return mitigation_required | ||
182 | + ? (TARGET_SB ? "sb" : "dsb\tsy\n\tisb") | ||
183 | + : ""; | ||
184 | +} | ||
185 | + | ||
186 | /* Target-specific selftests. */ | ||
187 | |||
188 | #if CHECKING_P | ||
189 | diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h | ||
190 | index 772a97296..72ddc6fd9 100644 | ||
191 | --- a/gcc/config/aarch64/aarch64.h | ||
192 | +++ b/gcc/config/aarch64/aarch64.h | ||
193 | @@ -235,6 +235,7 @@ extern unsigned aarch64_architecture_version; | ||
194 | #define AARCH64_ISA_F16FML (aarch64_isa_flags & AARCH64_FL_F16FML) | ||
195 | #define AARCH64_ISA_RCPC8_4 (aarch64_isa_flags & AARCH64_FL_RCPC8_4) | ||
196 | #define AARCH64_ISA_V8_5 (aarch64_isa_flags & AARCH64_FL_V8_5) | ||
197 | +#define AARCH64_ISA_SB (aarch64_isa_flags & AARCH64_FL_SB) | ||
198 | |||
199 | /* Crypto is an optional extension to AdvSIMD. */ | ||
200 | #define TARGET_CRYPTO (TARGET_SIMD && AARCH64_ISA_CRYPTO) | ||
201 | @@ -285,6 +286,9 @@ extern unsigned aarch64_architecture_version; | ||
202 | #define TARGET_FIX_ERR_A53_835769_DEFAULT 1 | ||
203 | #endif | ||
204 | |||
205 | +/* SB instruction is enabled through +sb. */ | ||
206 | +#define TARGET_SB (AARCH64_ISA_SB) | ||
207 | + | ||
208 | /* Apply the workaround for Cortex-A53 erratum 835769. */ | ||
209 | #define TARGET_FIX_ERR_A53_835769 \ | ||
210 | ((aarch64_fix_a53_err835769 == 2) \ | ||
211 | @@ -931,8 +935,10 @@ typedef struct | ||
212 | |||
213 | #define RETURN_ADDR_RTX aarch64_return_addr | ||
214 | |||
215 | -/* BTI c + 3 insns + 2 pointer-sized entries. */ | ||
216 | -#define TRAMPOLINE_SIZE (TARGET_ILP32 ? 24 : 32) | ||
217 | +/* BTI c + 3 insns | ||
218 | + + sls barrier of DSB + ISB. | ||
219 | + + 2 pointer-sized entries. */ | ||
220 | +#define TRAMPOLINE_SIZE (24 + (TARGET_ILP32 ? 8 : 16)) | ||
221 | |||
222 | /* Trampolines contain dwords, so must be dword aligned. */ | ||
223 | #define TRAMPOLINE_ALIGNMENT 64 | ||
224 | diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md | ||
225 | index cc5a887d4..494aee964 100644 | ||
226 | --- a/gcc/config/aarch64/aarch64.md | ||
227 | +++ b/gcc/config/aarch64/aarch64.md | ||
228 | @@ -331,10 +331,25 @@ | ||
229 | ;; Attribute that specifies whether the alternative uses MOVPRFX. | ||
230 | (define_attr "movprfx" "no,yes" (const_string "no")) | ||
231 | |||
232 | +;; Attribute to specify that an alternative has the length of a single | ||
233 | +;; instruction plus a speculation barrier. | ||
234 | +(define_attr "sls_length" "none,retbr,casesi" (const_string "none")) | ||
235 | + | ||
236 | (define_attr "length" "" | ||
237 | (cond [(eq_attr "movprfx" "yes") | ||
238 | (const_int 8) | ||
239 | - ] (const_int 4))) | ||
240 | + | ||
241 | + (eq_attr "sls_length" "retbr") | ||
242 | + (cond [(match_test "!aarch64_harden_sls_retbr_p ()") (const_int 4) | ||
243 | + (match_test "TARGET_SB") (const_int 8)] | ||
244 | + (const_int 12)) | ||
245 | + | ||
246 | + (eq_attr "sls_length" "casesi") | ||
247 | + (cond [(match_test "!aarch64_harden_sls_retbr_p ()") (const_int 16) | ||
248 | + (match_test "TARGET_SB") (const_int 20)] | ||
249 | + (const_int 24)) | ||
250 | + ] | ||
251 | + (const_int 4))) | ||
252 | |||
253 | ;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has | ||
254 | ;; no predicated insns. | ||
255 | @@ -370,8 +385,12 @@ | ||
256 | (define_insn "indirect_jump" | ||
257 | [(set (pc) (match_operand:DI 0 "register_operand" "r"))] | ||
258 | "" | ||
259 | - "br\\t%0" | ||
260 | - [(set_attr "type" "branch")] | ||
261 | + { | ||
262 | + output_asm_insn ("br\\t%0", operands); | ||
263 | + return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ()); | ||
264 | + } | ||
265 | + [(set_attr "type" "branch") | ||
266 | + (set_attr "sls_length" "retbr")] | ||
267 | ) | ||
268 | |||
269 | (define_insn "jump" | ||
270 | @@ -657,7 +676,7 @@ | ||
271 | "* | ||
272 | return aarch64_output_casesi (operands); | ||
273 | " | ||
274 | - [(set_attr "length" "16") | ||
275 | + [(set_attr "sls_length" "casesi") | ||
276 | (set_attr "type" "branch")] | ||
277 | ) | ||
278 | |||
279 | @@ -736,14 +755,18 @@ | ||
280 | [(return)] | ||
281 | "" | ||
282 | { | ||
283 | + const char *ret = NULL; | ||
284 | if (aarch64_return_address_signing_enabled () | ||
285 | && TARGET_ARMV8_3 | ||
286 | && !crtl->calls_eh_return) | ||
287 | - return "retaa"; | ||
288 | - | ||
289 | - return "ret"; | ||
290 | + ret = "retaa"; | ||
291 | + else | ||
292 | + ret = "ret"; | ||
293 | + output_asm_insn (ret, operands); | ||
294 | + return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ()); | ||
295 | } | ||
296 | - [(set_attr "type" "branch")] | ||
297 | + [(set_attr "type" "branch") | ||
298 | + (set_attr "sls_length" "retbr")] | ||
299 | ) | ||
300 | |||
301 | (define_expand "return" | ||
302 | @@ -755,8 +778,12 @@ | ||
303 | (define_insn "simple_return" | ||
304 | [(simple_return)] | ||
305 | "aarch64_use_simple_return_insn_p ()" | ||
306 | - "ret" | ||
307 | - [(set_attr "type" "branch")] | ||
308 | + { | ||
309 | + output_asm_insn ("ret", operands); | ||
310 | + return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ()); | ||
311 | + } | ||
312 | + [(set_attr "type" "branch") | ||
313 | + (set_attr "sls_length" "retbr")] | ||
314 | ) | ||
315 | |||
316 | (define_insn "*cb<optab><mode>1" | ||
317 | @@ -947,10 +974,16 @@ | ||
318 | (match_operand 1 "" "")) | ||
319 | (return)] | ||
320 | "SIBLING_CALL_P (insn)" | ||
321 | - "@ | ||
322 | - br\\t%0 | ||
323 | - b\\t%c0" | ||
324 | - [(set_attr "type" "branch, branch")] | ||
325 | + { | ||
326 | + if (which_alternative == 0) | ||
327 | + { | ||
328 | + output_asm_insn ("br\\t%0", operands); | ||
329 | + return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ()); | ||
330 | + } | ||
331 | + return "b\\t%c0"; | ||
332 | + } | ||
333 | + [(set_attr "type" "branch, branch") | ||
334 | + (set_attr "sls_length" "retbr,none")] | ||
335 | ) | ||
336 | |||
337 | (define_insn "*sibcall_value_insn" | ||
338 | @@ -960,10 +993,16 @@ | ||
339 | (match_operand 2 "" ""))) | ||
340 | (return)] | ||
341 | "SIBLING_CALL_P (insn)" | ||
342 | - "@ | ||
343 | - br\\t%1 | ||
344 | - b\\t%c1" | ||
345 | - [(set_attr "type" "branch, branch")] | ||
346 | + { | ||
347 | + if (which_alternative == 0) | ||
348 | + { | ||
349 | + output_asm_insn ("br\\t%1", operands); | ||
350 | + return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ()); | ||
351 | + } | ||
352 | + return "b\\t%c1"; | ||
353 | + } | ||
354 | + [(set_attr "type" "branch, branch") | ||
355 | + (set_attr "sls_length" "retbr,none")] | ||
356 | ) | ||
357 | |||
358 | ;; Call subroutine returning any type. | ||
359 | diff --git a/gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-miti-retbr-pacret.c b/gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-miti-retbr-pacret.c | ||
360 | new file mode 100644 | ||
361 | index 000000000..7656123ee | ||
362 | --- /dev/null | ||
363 | +++ b/gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-miti-retbr-pacret.c | ||
364 | @@ -0,0 +1,15 @@ | ||
365 | +/* Avoid ILP32 since pacret is only available for LP64 */ | ||
366 | +/* { dg-do compile { target { ! ilp32 } } } */ | ||
367 | +/* { dg-additional-options "-mharden-sls=retbr -mbranch-protection=pac-ret -march=armv8.3-a" } */ | ||
368 | + | ||
369 | +/* Testing the do_return pattern for retaa. */ | ||
370 | +long retbr_subcall(void); | ||
371 | +long retbr_do_return_retaa(void) | ||
372 | +{ | ||
373 | + return retbr_subcall()+1; | ||
374 | +} | ||
375 | + | ||
376 | +/* Ensure there are no BR or RET instructions which are not directly followed | ||
377 | + by a speculation barrier. */ | ||
378 | +/* { dg-final { scan-assembler-not {\t(br|ret|retaa)\tx[0-9][0-9]?\n\t(?!dsb\tsy\n\tisb)} } } */ | ||
379 | +/* { dg-final { scan-assembler-not {ret\t} } } */ | ||
380 | diff --git a/gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-miti-retbr.c b/gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-miti-retbr.c | ||
381 | new file mode 100644 | ||
382 | index 000000000..573b30cdc | ||
383 | --- /dev/null | ||
384 | +++ b/gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-miti-retbr.c | ||
385 | @@ -0,0 +1,119 @@ | ||
386 | +/* We ensure that -Wpedantic is off since it complains about the trampolines | ||
387 | + we explicitly want to test. */ | ||
388 | +/* { dg-additional-options "-mharden-sls=retbr -Wno-pedantic " } */ | ||
389 | +/* | ||
390 | + Ensure that the SLS hardening of RET and BR leaves no unprotected RET/BR | ||
391 | + instructions. | ||
392 | + */ | ||
393 | +typedef int (foo) (int, int); | ||
394 | +typedef void (bar) (int, int); | ||
395 | +struct sls_testclass { | ||
396 | + foo *x; | ||
397 | + bar *y; | ||
398 | + int left; | ||
399 | + int right; | ||
400 | +}; | ||
401 | + | ||
402 | +int | ||
403 | +retbr_sibcall_value_insn (struct sls_testclass x) | ||
404 | +{ | ||
405 | + return x.x(x.left, x.right); | ||
406 | +} | ||
407 | + | ||
408 | +void | ||
409 | +retbr_sibcall_insn (struct sls_testclass x) | ||
410 | +{ | ||
411 | + x.y(x.left, x.right); | ||
412 | +} | ||
413 | + | ||
414 | +/* Aim to test two different returns. | ||
415 | + One that introduces a tail call in the middle of the function, and one that | ||
416 | + has a normal return. */ | ||
417 | +int | ||
418 | +retbr_multiple_returns (struct sls_testclass x) | ||
419 | +{ | ||
420 | + int temp; | ||
421 | + if (x.left % 10) | ||
422 | + return x.x(x.left, 100); | ||
423 | + else if (x.right % 20) | ||
424 | + { | ||
425 | + return x.x(x.left * x.right, 100); | ||
426 | + } | ||
427 | + temp = x.left % x.right; | ||
428 | + temp *= 100; | ||
429 | + temp /= 2; | ||
430 | + return temp % 3; | ||
431 | +} | ||
432 | + | ||
433 | +void | ||
434 | +retbr_multiple_returns_void (struct sls_testclass x) | ||
435 | +{ | ||
436 | + if (x.left % 10) | ||
437 | + { | ||
438 | + x.y(x.left, 100); | ||
439 | + } | ||
440 | + else if (x.right % 20) | ||
441 | + { | ||
442 | + x.y(x.left * x.right, 100); | ||
443 | + } | ||
444 | + return; | ||
445 | +} | ||
446 | + | ||
447 | +/* Testing the casesi jump via register. */ | ||
448 | +__attribute__ ((optimize ("Os"))) | ||
449 | +int | ||
450 | +retbr_casesi_dispatch (struct sls_testclass x) | ||
451 | +{ | ||
452 | + switch (x.left) | ||
453 | + { | ||
454 | + case -5: | ||
455 | + return -2; | ||
456 | + case -3: | ||
457 | + return -1; | ||
458 | + case 0: | ||
459 | + return 0; | ||
460 | + case 3: | ||
461 | + return 1; | ||
462 | + case 5: | ||
463 | + break; | ||
464 | + default: | ||
465 | + __builtin_unreachable (); | ||
466 | + } | ||
467 | + return x.right; | ||
468 | +} | ||
469 | + | ||
470 | +/* Testing the BR in trampolines is mitigated against. */ | ||
471 | +void f1 (void *); | ||
472 | +void f3 (void *, void (*)(void *)); | ||
473 | +void f2 (void *); | ||
474 | + | ||
475 | +int | ||
476 | +retbr_trampolines (void *a, int b) | ||
477 | +{ | ||
478 | + if (!b) | ||
479 | + { | ||
480 | + f1 (a); | ||
481 | + return 1; | ||
482 | + } | ||
483 | + if (b) | ||
484 | + { | ||
485 | + void retbr_tramp_internal (void *c) | ||
486 | + { | ||
487 | + if (c == a) | ||
488 | + f2 (c); | ||
489 | + } | ||
490 | + f3 (a, retbr_tramp_internal); | ||
491 | + } | ||
492 | + return 0; | ||
493 | +} | ||
494 | + | ||
495 | +/* Testing the indirect_jump pattern. */ | ||
496 | +void | ||
497 | +retbr_indirect_jump (int *buf) | ||
498 | +{ | ||
499 | + __builtin_longjmp(buf, 1); | ||
500 | +} | ||
501 | + | ||
502 | +/* Ensure there are no BR or RET instructions which are not directly followed | ||
503 | + by a speculation barrier. */ | ||
504 | +/* { dg-final { scan-assembler-not {\t(br|ret|retaa)\tx[0-9][0-9]?\n\t(?!dsb\tsy\n\tisb|sb)} } } */ | ||
505 | diff --git a/gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-mitigation.exp b/gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-mitigation.exp | ||
506 | new file mode 100644 | ||
507 | index 000000000..812250379 | ||
508 | --- /dev/null | ||
509 | +++ b/gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-mitigation.exp | ||
510 | @@ -0,0 +1,73 @@ | ||
511 | +# Regression driver for SLS mitigation on AArch64. | ||
512 | +# Copyright (C) 2020 Free Software Foundation, Inc. | ||
513 | +# Contributed by ARM Ltd. | ||
514 | +# | ||
515 | +# This file is part of GCC. | ||
516 | +# | ||
517 | +# GCC is free software; you can redistribute it and/or modify it | ||
518 | +# under the terms of the GNU General Public License as published by | ||
519 | +# the Free Software Foundation; either version 3, or (at your option) | ||
520 | +# any later version. | ||
521 | +# | ||
522 | +# GCC is distributed in the hope that it will be useful, but | ||
523 | +# WITHOUT ANY WARRANTY; without even the implied warranty of | ||
524 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
525 | +# General Public License for more details. | ||
526 | +# | ||
527 | +# You should have received a copy of the GNU General Public License | ||
528 | +# along with GCC; see the file COPYING3. If not see | ||
529 | +# <http://www.gnu.org/licenses/>. */ | ||
530 | + | ||
531 | +# Exit immediately if this isn't an AArch64 target. | ||
532 | +if {![istarget aarch64*-*-*] } then { | ||
533 | + return | ||
534 | +} | ||
535 | + | ||
536 | +# Load support procs. | ||
537 | +load_lib gcc-dg.exp | ||
538 | +load_lib torture-options.exp | ||
539 | + | ||
540 | +# If a testcase doesn't have special options, use these. | ||
541 | +global DEFAULT_CFLAGS | ||
542 | +if ![info exists DEFAULT_CFLAGS] then { | ||
543 | + set DEFAULT_CFLAGS " " | ||
544 | +} | ||
545 | + | ||
546 | +# Initialize `dg'. | ||
547 | +dg-init | ||
548 | +torture-init | ||
549 | + | ||
550 | +# Use different architectures as well as the normal optimisation options. | ||
551 | +# (i.e. use both SB and DSB+ISB barriers). | ||
552 | + | ||
553 | +set save-dg-do-what-default ${dg-do-what-default} | ||
554 | +# Main loop. | ||
555 | +# Run with torture tests (i.e. a bunch of different optimisation levels) just | ||
556 | +# to increase test coverage. | ||
557 | +set dg-do-what-default assemble | ||
558 | +gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \ | ||
559 | + "-save-temps" $DEFAULT_CFLAGS | ||
560 | + | ||
561 | +# Run the same tests but this time with SB extension. | ||
562 | +# Since not all supported assemblers will support that extension we decide | ||
563 | +# whether to assemble or just compile based on whether the extension is | ||
564 | +# supported for the available assembler. | ||
565 | + | ||
566 | +set templist {} | ||
567 | +foreach x $DG_TORTURE_OPTIONS { | ||
568 | + lappend templist "$x -march=armv8.3-a+sb " | ||
569 | + lappend templist "$x -march=armv8-a+sb " | ||
570 | +} | ||
571 | +set-torture-options $templist | ||
572 | +if { [check_effective_target_aarch64_asm_sb_ok] } { | ||
573 | + set dg-do-what-default assemble | ||
574 | +} else { | ||
575 | + set dg-do-what-default compile | ||
576 | +} | ||
577 | +gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \ | ||
578 | + "-save-temps" $DEFAULT_CFLAGS | ||
579 | +set dg-do-what-default ${save-dg-do-what-default} | ||
580 | + | ||
581 | +# All done. | ||
582 | +torture-finish | ||
583 | +dg-finish | ||
584 | diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp | ||
585 | index ea9a50ccb..79482f9b6 100644 | ||
586 | --- a/gcc/testsuite/lib/target-supports.exp | ||
587 | +++ b/gcc/testsuite/lib/target-supports.exp | ||
588 | @@ -8579,7 +8579,8 @@ proc check_effective_target_aarch64_tiny { } { | ||
589 | # Create functions to check that the AArch64 assembler supports the | ||
590 | # various architecture extensions via the .arch_extension pseudo-op. | ||
591 | |||
592 | -foreach { aarch64_ext } { "fp" "simd" "crypto" "crc" "lse" "dotprod" "sve"} { | ||
593 | +foreach { aarch64_ext } { "fp" "simd" "crypto" "crc" "lse" "dotprod" "sve" | ||
594 | + "sb"} { | ||
595 | eval [string map [list FUNC $aarch64_ext] { | ||
596 | proc check_effective_target_aarch64_asm_FUNC_ok { } { | ||
597 | if { [istarget aarch64*-*-*] } { | ||
598 | -- | ||
599 | 2.25.1 | ||
600 | |||