Andrew Geissler | b7d2861 | 2020-07-24 16:15:54 -0500 | [diff] [blame] | 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 | |