aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Earnshaw <rearnsha@arm.com>2018-08-23 09:47:34 +0000
committerRichard Earnshaw <rearnsha@gcc.gnu.org>2018-08-23 09:47:34 +0000
commitebdb6f237772df251378d2c08350d345135bcb9e (patch)
tree6a3c701b592c1d8f41cc87152a53e5dda03dd473 /gcc
parent60d91c7fae77fe6b7bd50a8b400a045b813e330f (diff)
downloadgcc-ebdb6f237772df251378d2c08350d345135bcb9e.zip
gcc-ebdb6f237772df251378d2c08350d345135bcb9e.tar.gz
gcc-ebdb6f237772df251378d2c08350d345135bcb9e.tar.bz2
PR target/86951 arm - Handle speculation barriers on pre-armv7 CPUs
The AArch32 instruction sets prior to Armv7 do not define the ISB and DSB instructions that are needed to form a speculation barrier. While I do not know of any instances of cores based on those instruction sets being vulnerable to speculative side channel attacks it is possible to run code built for those ISAs on more recent hardware where they would become vulnerable. This patch works around this by using a library call added to libgcc. That code can then take any platform-specific actions necessary to ensure safety. For the moment I've only handled two cases: the library code being built for armv7 or later anyway and running on Linux. On Linux we can handle this by calling the kernel function that will flush a small amount of cache. Such a sequence ends with a ISB+DSB sequence if running on an Armv7 or later CPU. gcc: PR target/86951 * config/arm/arm-protos.h (arm_emit_speculation_barrier): New prototype. * config/arm/arm.c (speculation_barrier_libfunc): New static variable. (arm_init_libfuncs): Initialize it. (arm_emit_speculation_barrier): New function. * config/arm/arm.md (speculation_barrier): Call arm_emit_speculation_barrier for architectures that do not have DSB or ISB. (speculation_barrier_insn): Only match on Armv7 or later. libgcc: PR target/86951 * config/arm/lib1funcs.asm (speculation_barrier): New function. * config/arm/t-arm (LIB1ASMFUNCS): Add it to list of functions to build. From-SVN: r263806
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/config/arm/arm-protos.h2
-rw-r--r--gcc/config/arm/arm.c15
-rw-r--r--gcc/config/arm/arm.md16
4 files changed, 41 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 89dfeb9..7b7c79b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,17 @@
+2018-08-23 Richard Earnshaw <rearnsha@arm.com>
+
+ PR target/86951
+ * config/arm/arm-protos.h (arm_emit_speculation_barrier): New
+ prototype.
+ * config/arm/arm.c (speculation_barrier_libfunc): New static
+ variable.
+ (arm_init_libfuncs): Initialize it.
+ (arm_emit_speculation_barrier): New function.
+ * config/arm/arm.md (speculation_barrier): Call
+ arm_emit_speculation_barrier for architectures that do not have
+ DSB or ISB.
+ (speculation_barrier_insn): Only match on Armv7 or later.
+
2018-08-23 Richard Biener <rguenther@suse.de>
PR middle-end/87024
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 8537262..0dfb3ac 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -56,6 +56,8 @@ extern void arm_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update
extern rtx arm_simd_vect_par_cnst_half (machine_mode mode, bool high);
extern bool arm_simd_check_vect_par_cnst_half_p (rtx op, machine_mode mode,
bool high);
+extern void arm_emit_speculation_barrier_function (void);
+
#ifdef RTX_CODE
extern void arm_gen_unlikely_cbranch (enum rtx_code, machine_mode cc_mode,
rtx label_ref);
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 1d97db5..c081216d 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -2466,8 +2466,9 @@ arm_set_fixed_conv_libfunc (convert_optab optable, machine_mode to,
set_conv_libfunc (optable, to, from, buffer);
}
-/* Set up library functions unique to ARM. */
+static GTY(()) rtx speculation_barrier_libfunc;
+/* Set up library functions unique to ARM. */
static void
arm_init_libfuncs (void)
{
@@ -2753,6 +2754,8 @@ arm_init_libfuncs (void)
if (TARGET_AAPCS_BASED)
synchronize_libfunc = init_one_libfunc ("__sync_synchronize");
+
+ speculation_barrier_libfunc = init_one_libfunc ("__speculation_barrier");
}
/* On AAPCS systems, this is the "struct __va_list". */
@@ -31528,6 +31531,16 @@ arm_constant_alignment (const_tree exp, HOST_WIDE_INT align)
return align;
}
+/* Emit a speculation barrier on target architectures that do not have
+ DSB/ISB directly. Such systems probably don't need a barrier
+ themselves, but if the code is ever run on a later architecture, it
+ might become a problem. */
+void
+arm_emit_speculation_barrier_function ()
+{
+ emit_library_call (speculation_barrier_libfunc, LCT_NORMAL, VOIDmode);
+}
+
#if CHECKING_P
namespace selftest {
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index ca2a2f5..270b8e4 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -12016,10 +12016,16 @@
[(unspec_volatile [(const_int 0)] VUNSPEC_SPECULATION_BARRIER)]
"TARGET_EITHER"
"
- /* Don't emit anything for Thumb1 and suppress the warning from the
- generic expansion. */
- if (!TARGET_32BIT)
- DONE;
+ /* For thumb1 (except Armv8 derivatives), and for pre-Armv7 we don't
+ have a usable barrier (and probably don't need one in practice).
+ But to be safe if such code is run on later architectures, call a
+ helper function in libgcc that will do the thing for the active
+ system. */
+ if (!(arm_arch7 || arm_arch8))
+ {
+ arm_emit_speculation_barrier_function ();
+ DONE;
+ }
"
)
@@ -12027,7 +12033,7 @@
;; tracking.
(define_insn "*speculation_barrier_insn"
[(unspec_volatile [(const_int 0)] VUNSPEC_SPECULATION_BARRIER)]
- "TARGET_32BIT"
+ "arm_arch7 || arm_arch8"
"isb\;dsb\\tsy"
[(set_attr "type" "block")
(set_attr "length" "8")]