aboutsummaryrefslogtreecommitdiff
path: root/libgcc
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 /libgcc
parent60d91c7fae77fe6b7bd50a8b400a045b813e330f (diff)
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 'libgcc')
-rw-r--r--libgcc/ChangeLog7
-rw-r--r--libgcc/config/arm/lib1funcs.S44
-rw-r--r--libgcc/config/arm/t-arm2
3 files changed, 52 insertions, 1 deletions
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index d003fd54c6e..280bd102868 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,10 @@
+2018-08-23 Richard Earnshaw <rearnsha@arm.com>
+
+ PR target/86951
+ * config/arm/lib1funcs.asm (speculation_barrier): New function.
+ * config/arm/t-arm (LIB1ASMFUNCS): Add it to list of functions
+ to build.
+
2018-08-22 Iain Sandoe <iain@sandoe.co.uk>
* config/unwind-dw2-fde-darwin.c
diff --git a/libgcc/config/arm/lib1funcs.S b/libgcc/config/arm/lib1funcs.S
index b9919aa966d..ff06d504a4c 100644
--- a/libgcc/config/arm/lib1funcs.S
+++ b/libgcc/config/arm/lib1funcs.S
@@ -1533,6 +1533,50 @@ LSYM(Lover12):
#error "This is only for ARM EABI GNU/Linux"
#endif
#endif /* L_clear_cache */
+
+#ifdef L_speculation_barrier
+ FUNC_START speculation_barrier
+#if __ARM_ARCH >= 7
+ isb
+ dsb sy
+#elif defined __ARM_EABI__ && defined __linux__
+ /* We don't have a speculation barrier directly for this
+ platform/architecture variant. But we can use a kernel
+ clear_cache service routine which will emit such instructions
+ if run on a later version of the architecture. We don't
+ really want to flush the cache, but we must give it a valid
+ address, so just clear pc..pc+1. */
+#if defined __thumb__ && !defined __thumb2__
+ push {r7}
+ mov r7, #0xf
+ lsl r7, #16
+ add r7, #2
+ adr r0, . + 4
+ add r1, r0, #1
+ mov r2, #0
+ svc 0
+ pop {r7}
+#else
+ do_push {r7}
+#ifdef __ARM_ARCH_6T2__
+ movw r7, #2
+ movt r7, #0xf
+#else
+ mov r7, #0xf0000
+ add r7, r7, #2
+#endif
+ add r0, pc, #0 /* ADR. */
+ add r1, r0, #1
+ mov r2, #0
+ svc 0
+ do_pop {r7}
+#endif /* Thumb1 only */
+#else
+#warning "No speculation barrier defined for this platform"
+#endif
+ RET
+ FUNC_END speculation_barrier
+#endif
/* ------------------------------------------------------------------------ */
/* Dword shift operations. */
/* All the following Dword shift variants rely on the fact that
diff --git a/libgcc/config/arm/t-arm b/libgcc/config/arm/t-arm
index 9e85ac06b14..274bf2a8ef3 100644
--- a/libgcc/config/arm/t-arm
+++ b/libgcc/config/arm/t-arm
@@ -1,6 +1,6 @@
LIB1ASMSRC = arm/lib1funcs.S
LIB1ASMFUNCS = _thumb1_case_sqi _thumb1_case_uqi _thumb1_case_shi \
- _thumb1_case_uhi _thumb1_case_si
+ _thumb1_case_uhi _thumb1_case_si _speculation_barrier
HAVE_CMSE:=$(findstring __ARM_FEATURE_CMSE,$(shell $(gcc_compile_bare) -dM -E - </dev/null))
ifneq ($(shell $(gcc_compile_bare) -E -mcmse - </dev/null 2>/dev/null),)