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