Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rseq/selftests: Fix Thumb mode build failure on arm32

Using ".arm .inst" for the arm signature introduces build issues for
programs compiled in Thumb mode because the assembler stays in the
arm mode for the rest of the inline assembly. Revert to using a ".word"
to express the signature as data instead.

The choice of signature is a valid trap instruction on arm32 little
endian, where both code and data are little endian.

ARMv6+ big endian (BE8) generates mixed endianness code vs data:
little-endian code and big-endian data. The data value of the signature
needs to have its byte order reversed to generate the trap instruction.

Prior to ARMv6, -mbig-endian generates big-endian code and data
(which match), so the endianness of the data representation of the
signature should not be reversed. However, the choice between BE32
and BE8 is done by the linker, so we cannot know whether code and
data endianness will be mixed before the linker is invoked. So rather
than try to play tricks with the linker, the rseq signature is simply
data (not a trap instruction) prior to ARMv6 on big endian. This is
why the signature is expressed as data (.word) rather than as
instruction (.inst) in assembler.

Because a ".word" is used to emit the signature, it will be interpreted
as a literal pool by a disassembler, not as an actual instruction.
Considering that the signature is not meant to be executed except in
scenarios where the program execution is completely bogus, this should
not be an issue.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Acked-by: Will Deacon <will.deacon@arm.com>
CC: Peter Zijlstra <peterz@infradead.org>
CC: Thomas Gleixner <tglx@linutronix.de>
CC: Joel Fernandes <joelaf@google.com>
CC: Catalin Marinas <catalin.marinas@arm.com>
CC: Dave Watson <davejwatson@fb.com>
CC: Will Deacon <will.deacon@arm.com>
CC: Shuah Khan <shuah@kernel.org>
CC: Andi Kleen <andi@firstfloor.org>
CC: linux-kselftest@vger.kernel.org
CC: "H . Peter Anvin" <hpa@zytor.com>
CC: Chris Lameter <cl@linux.com>
CC: Russell King <linux@arm.linux.org.uk>
CC: Michael Kerrisk <mtk.manpages@gmail.com>
CC: "Paul E . McKenney" <paulmck@linux.vnet.ibm.com>
CC: Paul Turner <pjt@google.com>
CC: Boqun Feng <boqun.feng@gmail.com>
CC: Josh Triplett <josh@joshtriplett.org>
CC: Steven Rostedt <rostedt@goodmis.org>
CC: Ben Maurer <bmaurer@fb.com>
CC: linux-api@vger.kernel.org
CC: Andy Lutomirski <luto@amacapital.net>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: Linus Torvalds <torvalds@linux-foundation.org>
CC: Carlos O'Donell <carlos@redhat.com>
CC: Florian Weimer <fweimer@redhat.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>

authored by

Mathieu Desnoyers and committed by
Shuah Khan
ee8a84c6 f4fb8a97

+33 -28
+33 -28
tools/testing/selftests/rseq/rseq-arm.h
··· 6 6 */ 7 7 8 8 /* 9 + * - ARM little endian 10 + * 9 11 * RSEQ_SIG uses the udf A32 instruction with an uncommon immediate operand 10 12 * value 0x5de3. This traps if user-space reaches this instruction by mistake, 11 13 * and the uncommon operand ensures the kernel does not move the instruction ··· 24 22 * def3 udf #243 ; 0xf3 25 23 * e7f5 b.n <7f5> 26 24 * 27 - * pre-ARMv6 big endian code: 28 - * e7f5 b.n <7f5> 29 - * def3 udf #243 ; 0xf3 25 + * - ARMv6+ big endian (BE8): 30 26 * 31 27 * ARMv6+ -mbig-endian generates mixed endianness code vs data: little-endian 32 - * code and big-endian data. Ensure the RSEQ_SIG data signature matches code 33 - * endianness. Prior to ARMv6, -mbig-endian generates big-endian code and data 34 - * (which match), so there is no need to reverse the endianness of the data 35 - * representation of the signature. However, the choice between BE32 and BE8 36 - * is done by the linker, so we cannot know whether code and data endianness 37 - * will be mixed before the linker is invoked. 28 + * code and big-endian data. The data value of the signature needs to have its 29 + * byte order reversed to generate the trap instruction: 30 + * 31 + * Data: 0xf3def5e7 32 + * 33 + * Translates to this A32 instruction pattern: 34 + * 35 + * e7f5def3 udf #24035 ; 0x5de3 36 + * 37 + * Translates to this T16 instruction pattern: 38 + * 39 + * def3 udf #243 ; 0xf3 40 + * e7f5 b.n <7f5> 41 + * 42 + * - Prior to ARMv6 big endian (BE32): 43 + * 44 + * Prior to ARMv6, -mbig-endian generates big-endian code and data 45 + * (which match), so the endianness of the data representation of the 46 + * signature should not be reversed. However, the choice between BE32 47 + * and BE8 is done by the linker, so we cannot know whether code and 48 + * data endianness will be mixed before the linker is invoked. So rather 49 + * than try to play tricks with the linker, the rseq signature is simply 50 + * data (not a trap instruction) prior to ARMv6 on big endian. This is 51 + * why the signature is expressed as data (.word) rather than as 52 + * instruction (.inst) in assembler. 38 53 */ 39 54 40 - #define RSEQ_SIG_CODE 0xe7f5def3 41 - 42 - #ifndef __ASSEMBLER__ 43 - 44 - #define RSEQ_SIG_DATA \ 45 - ({ \ 46 - int sig; \ 47 - asm volatile ("b 2f\n\t" \ 48 - "1: .inst " __rseq_str(RSEQ_SIG_CODE) "\n\t" \ 49 - "2:\n\t" \ 50 - "ldr %[sig], 1b\n\t" \ 51 - : [sig] "=r" (sig)); \ 52 - sig; \ 53 - }) 54 - 55 - #define RSEQ_SIG RSEQ_SIG_DATA 56 - 55 + #ifdef __ARMEB__ 56 + #define RSEQ_SIG 0xf3def5e7 /* udf #24035 ; 0x5de3 (ARMv6+) */ 57 + #else 58 + #define RSEQ_SIG 0xe7f5def3 /* udf #24035 ; 0x5de3 */ 57 59 #endif 58 60 59 61 #define rseq_smp_mb() __asm__ __volatile__ ("dmb" ::: "memory", "cc") ··· 131 125 __rseq_str(table_label) ":\n\t" \ 132 126 ".word " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \ 133 127 ".word " __rseq_str(start_ip) ", 0x0, " __rseq_str(post_commit_offset) ", 0x0, " __rseq_str(abort_ip) ", 0x0\n\t" \ 134 - ".arm\n\t" \ 135 - ".inst " __rseq_str(RSEQ_SIG_CODE) "\n\t" \ 128 + ".word " __rseq_str(RSEQ_SIG) "\n\t" \ 136 129 __rseq_str(label) ":\n\t" \ 137 130 teardown \ 138 131 "b %l[" __rseq_str(abort_label) "]\n\t"