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

Merge tag 'linux-kselftest-5.2-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest

Pull more kselftest updates from Shuah Khan:

- kselftest framework bpf build/test workflow regression fix

- Fix to kselftest install to use default install path

- Fix to kselftest KBUILD_OUTPUT builds to not clutter main
KBUILD_OUTPUT directory with selftest objects

- .gitignore fixes (Kelsey Skunberg)

- rseq selftests updates (Mathieu Desnoyers and Martin Schwidefsky)

They change the per-architecture pre-abort signatures to ensure those
are valid trap instructions.

The way exit points are presented to debuggers is enhanced, ensuring
all exit points are present, so debuggers don't have to disassemble
rseq critical section to properly skip over them.

Discussions with the glibc community is reaching a consensus of
exposing a __rseq_handled symbol from glibc to coexist with rseq
early adopters. Update the rseq selftest code to expose and use this
symbol.

Support for compiling asm goto with clang is added with the
"-no-integrated-as" compiler switch, similarly to the top level
kernel Makefile.

- kselftest Makefile test run output refactoring and making test output
TAP13 compliant from Kees Cook:

This re-factors the selftest Makefiles to extract the test running
logic to be reused between "run_tests" and "emit_tests", while also
fixing up the test output to be TAP version 13 compliant:
- added "plan" line
- fixed result line syntax
- moved all test output to be "# "-prefixed as TAP "diagnostic"
lines

The prefixing code includes a fallback mode for limited execution
environments.

Additionally, the plan lines are fixed for all callers of
kselftest.h.

* tag 'linux-kselftest-5.2-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest: (25 commits)
selftests: avoid KBUILD_OUTPUT dir cluttering with selftest objects
selftests: drivers: Create .gitignore to include /dma-buf/udmabuf
selftests: pidfd: Create .gitignore to include pidfd_test
selftests: fix bpf build/test workflow regression when KBUILD_OUTPUT is set
selftests: fix install target to use default install path
rseq/selftests: add -no-integrated-as for clang
rseq/selftests: mips: use break instruction for RSEQ_SIG
rseq/selftests: powerpc code signature: generate valid instructions
rseq/selftests: aarch64 code signature: handle big-endian environment
rseq/selftests: arm: use udf instruction for RSEQ_SIG
rseq/selftests: s390: use trap4 for RSEQ_SIG
rseq/selftests: x86: use ud1 instruction as RSEQ_SIG opcode
rseq/selftests: s390: use jg instruction for jumps outside of the asm
rseq/selftests: Use __rseq_handled symbol to coexist with glibc
rseq/selftests: Introduce __rseq_cs_ptr_array, rename __rseq_table to __rseq_cs
rseq/selftests: Add __rseq_exit_point_array section for debuggers
rseq/selftests: x86: Work-around bogus gcc-8 optimisation
selftests: Add test plan API to kselftest.h and adjust callers
selftests: Remove KSFT_TAP_LEVEL
selftests: Move test output to diagnostic lines
...

+875 -220
-1
tools/testing/selftests/.gitignore
··· 1 - kselftest 2 1 gpiogpio-event-mon 3 2 gpiogpio-hammer 4 3 gpioinclude/
+20 -19
tools/testing/selftests/Makefile
··· 71 71 override MAKEFLAGS = 72 72 endif 73 73 74 + # Append kselftest to KBUILD_OUTPUT to avoid cluttering 75 + # KBUILD_OUTPUT with selftest objects and headers installed 76 + # by selftests Makefile or lib.mk. 74 77 ifneq ($(KBUILD_SRC),) 75 78 override LDFLAGS = 76 79 endif ··· 82 79 BUILD := $(O) 83 80 else 84 81 ifneq ($(KBUILD_OUTPUT),) 85 - BUILD := $(KBUILD_OUTPUT) 82 + BUILD := $(KBUILD_OUTPUT)/kselftest 86 83 else 87 84 BUILD := $(shell pwd) 88 85 DEFAULT_INSTALL_HDR_PATH := 1 89 86 endif 90 87 endif 91 - 92 - # KSFT_TAP_LEVEL is used from KSFT framework to prevent nested TAP header 93 - # printing from tests. Applicable to run_tests case where run_tests adds 94 - # TAP header prior running tests and when a test program invokes another 95 - # with system() call. Export it here to cover override RUN_TESTS defines. 96 - export KSFT_TAP_LEVEL=`echo 1` 97 88 98 89 # Prepare for headers install 99 90 top_srcdir ?= ../../.. ··· 166 169 run_pstore_crash: 167 170 make -C pstore run_crash 168 171 169 - INSTALL_PATH ?= install 172 + # Use $BUILD as the default install root. $BUILD points to the 173 + # right output location for the following cases: 174 + # 1. output_dir=kernel_src 175 + # 2. a separate output directory is specified using O= KBUILD_OUTPUT 176 + # 3. a separate output directory is specified using KBUILD_OUTPUT 177 + # 178 + INSTALL_PATH ?= $(BUILD)/install 170 179 INSTALL_PATH := $(abspath $(INSTALL_PATH)) 171 180 ALL_SCRIPT := $(INSTALL_PATH)/run_kselftest.sh 172 181 173 - install: 182 + install: all 174 183 ifdef INSTALL_PATH 175 184 @# Ask all targets to install their files 176 - mkdir -p $(INSTALL_PATH) 185 + mkdir -p $(INSTALL_PATH)/kselftest 186 + install -m 744 kselftest/runner.sh $(INSTALL_PATH)/kselftest/ 187 + install -m 744 kselftest/prefix.pl $(INSTALL_PATH)/kselftest/ 177 188 @for TARGET in $(TARGETS); do \ 178 189 BUILD_TARGET=$$BUILD/$$TARGET; \ 179 190 make OUTPUT=$$BUILD_TARGET -C $$TARGET INSTALL_PATH=$(INSTALL_PATH)/$$TARGET install; \ ··· 191 186 echo "#!/bin/sh" > $(ALL_SCRIPT) 192 187 echo "BASE_DIR=\$$(realpath \$$(dirname \$$0))" >> $(ALL_SCRIPT) 193 188 echo "cd \$$BASE_DIR" >> $(ALL_SCRIPT) 189 + echo ". ./kselftest/runner.sh" >> $(ALL_SCRIPT) 194 190 echo "ROOT=\$$PWD" >> $(ALL_SCRIPT) 195 191 echo "if [ \"\$$1\" = \"--summary\" ]; then" >> $(ALL_SCRIPT) 196 - echo " OUTPUT=\$$BASE_DIR/output.log" >> $(ALL_SCRIPT) 197 - echo " cat /dev/null > \$$OUTPUT" >> $(ALL_SCRIPT) 198 - echo "else" >> $(ALL_SCRIPT) 199 - echo " OUTPUT=/dev/stdout" >> $(ALL_SCRIPT) 192 + echo " logfile=\$$BASE_DIR/output.log" >> $(ALL_SCRIPT) 193 + echo " cat /dev/null > \$$logfile" >> $(ALL_SCRIPT) 200 194 echo "fi" >> $(ALL_SCRIPT) 201 - echo "export KSFT_TAP_LEVEL=1" >> $(ALL_SCRIPT) 202 - echo "export skip=4" >> $(ALL_SCRIPT) 203 195 204 196 for TARGET in $(TARGETS); do \ 205 197 BUILD_TARGET=$$BUILD/$$TARGET; \ 206 - echo "echo ; echo TAP version 13" >> $(ALL_SCRIPT); \ 207 - echo "echo Running tests in $$TARGET" >> $(ALL_SCRIPT); \ 208 - echo "echo ========================================" >> $(ALL_SCRIPT); \ 209 198 echo "[ -w /dev/kmsg ] && echo \"kselftest: Running tests in $$TARGET\" >> /dev/kmsg" >> $(ALL_SCRIPT); \ 210 199 echo "cd $$TARGET" >> $(ALL_SCRIPT); \ 200 + echo -n "run_many" >> $(ALL_SCRIPT); \ 211 201 make -s --no-print-directory OUTPUT=$$BUILD_TARGET -C $$TARGET emit_tests >> $(ALL_SCRIPT); \ 202 + echo "" >> $(ALL_SCRIPT); \ 212 203 echo "cd \$$ROOT" >> $(ALL_SCRIPT); \ 213 204 done; 214 205
+12 -3
tools/testing/selftests/breakpoints/breakpoint_test.c
··· 21 21 22 22 #include "../kselftest.h" 23 23 24 + #define COUNT_ISN_BPS 4 25 + #define COUNT_WPS 4 24 26 25 27 /* Breakpoint access modes */ 26 28 enum { ··· 222 220 if (!local && !global) 223 221 continue; 224 222 225 - for (i = 0; i < 4; i++) { 223 + for (i = 0; i < COUNT_ISN_BPS; i++) { 226 224 dummy_funcs[i](); 227 225 check_trapped(); 228 226 } ··· 294 292 { 295 293 int i; 296 294 297 - for (i = 0; i < 4; i++) { 295 + for (i = 0; i < COUNT_ISN_BPS; i++) { 298 296 set_breakpoint_addr(dummy_funcs[i], i); 299 297 toggle_breakpoint(i, BP_X, 1, local, global, 1); 300 298 ptrace(PTRACE_CONT, child_pid, NULL, 0); ··· 316 314 else 317 315 mode_str = "read"; 318 316 319 - for (i = 0; i < 4; i++) { 317 + for (i = 0; i < COUNT_WPS; i++) { 320 318 set_breakpoint_addr(&dummy_var[i], i); 321 319 toggle_breakpoint(i, mode, len, local, global, 1); 322 320 ptrace(PTRACE_CONT, child_pid, NULL, 0); ··· 332 330 static void launch_tests(void) 333 331 { 334 332 char buf[1024]; 333 + unsigned int tests = 0; 335 334 int len, local, global, i; 335 + 336 + tests += 3 * COUNT_ISN_BPS; 337 + tests += sizeof(long) / 2 * 3 * COUNT_WPS; 338 + tests += sizeof(long) / 2 * 3 * COUNT_WPS; 339 + tests += 2; 340 + ksft_set_plan(tests); 336 341 337 342 /* Instruction breakpoints */ 338 343 for (local = 0; local < 2; local++) {
+2 -1
tools/testing/selftests/breakpoints/breakpoint_test_arm64.c
··· 118 118 return false; 119 119 } 120 120 121 - static bool run_test(int wr_size, int wp_size, int wr, int wp) 121 + static bool arun_test(int wr_size, int wp_size, int wr, int wp) 122 122 { 123 123 int status; 124 124 siginfo_t siginfo; ··· 214 214 bool result; 215 215 216 216 ksft_print_header(); 217 + ksft_set_plan(213); 217 218 218 219 act.sa_handler = sigalrm; 219 220 sigemptyset(&act.sa_mask);
+8
tools/testing/selftests/breakpoints/step_after_suspend_test.c
··· 173 173 int opt; 174 174 bool do_suspend = true; 175 175 bool succeeded = true; 176 + unsigned int tests = 0; 176 177 cpu_set_t available_cpus; 177 178 int err; 178 179 int cpu; ··· 191 190 return -1; 192 191 } 193 192 } 193 + 194 + for (cpu = 0; cpu < CPU_SETSIZE; cpu++) { 195 + if (!CPU_ISSET(cpu, &available_cpus)) 196 + continue; 197 + tests++; 198 + } 199 + ksft_set_plan(tests); 194 200 195 201 if (do_suspend) 196 202 suspend();
+4 -2
tools/testing/selftests/capabilities/test_execve.c
··· 430 430 { 431 431 char *tmp1, *tmp2, *our_path; 432 432 433 - ksft_print_header(); 434 - 435 433 /* Find our path */ 436 434 tmp1 = strdup(argv[0]); 437 435 if (!tmp1) ··· 443 445 mpid = getpid(); 444 446 445 447 if (fork_wait()) { 448 + ksft_print_header(); 449 + ksft_set_plan(12); 446 450 ksft_print_msg("[RUN]\t+++ Tests with uid == 0 +++\n"); 447 451 return do_tests(0, our_path); 448 452 } ··· 452 452 ksft_print_msg("==================================================\n"); 453 453 454 454 if (fork_wait()) { 455 + ksft_print_header(); 456 + ksft_set_plan(9); 455 457 ksft_print_msg("[RUN]\t+++ Tests with uid != 0 +++\n"); 456 458 return do_tests(1, our_path); 457 459 }
+1
tools/testing/selftests/drivers/.gitignore
··· 1 + /dma-buf/udmabuf
+1
tools/testing/selftests/futex/functional/futex_requeue_pi.c
··· 395 395 } 396 396 397 397 ksft_print_header(); 398 + ksft_set_plan(1); 398 399 ksft_print_msg("%s: Test requeue functionality\n", basename(argv[0])); 399 400 ksft_print_msg( 400 401 "\tArguments: broadcast=%d locked=%d owner=%d timeout=%ldns\n",
+1
tools/testing/selftests/futex/functional/futex_requeue_pi_mismatched_ops.c
··· 79 79 } 80 80 81 81 ksft_print_header(); 82 + ksft_set_plan(1); 82 83 ksft_print_msg("%s: Detect mismatched requeue_pi operations\n", 83 84 basename(argv[0])); 84 85
+1
tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c
··· 144 144 } 145 145 146 146 ksft_print_header(); 147 + ksft_set_plan(1); 147 148 ksft_print_msg("%s: Test signal handling during requeue_pi\n", 148 149 basename(argv[0])); 149 150 ksft_print_msg("\tArguments: <none>\n");
+1
tools/testing/selftests/futex/functional/futex_wait_private_mapped_file.c
··· 98 98 } 99 99 100 100 ksft_print_header(); 101 + ksft_set_plan(1); 101 102 ksft_print_msg( 102 103 "%s: Test the futex value of private file mappings in FUTEX_WAIT\n", 103 104 basename(argv[0]));
+1
tools/testing/selftests/futex/functional/futex_wait_timeout.c
··· 69 69 } 70 70 71 71 ksft_print_header(); 72 + ksft_set_plan(1); 72 73 ksft_print_msg("%s: Block on a futex and wait for timeout\n", 73 74 basename(argv[0])); 74 75 ksft_print_msg("\tArguments: timeout=%ldns\n", timeout_ns);
+1
tools/testing/selftests/futex/functional/futex_wait_uninitialized_heap.c
··· 100 100 } 101 101 102 102 ksft_print_header(); 103 + ksft_set_plan(1); 103 104 ksft_print_msg("%s: Test the uninitialized futex value in FUTEX_WAIT\n", 104 105 basename(argv[0])); 105 106
+1
tools/testing/selftests/futex/functional/futex_wait_wouldblock.c
··· 65 65 } 66 66 67 67 ksft_print_header(); 68 + ksft_set_plan(1); 68 69 ksft_print_msg("%s: Test the unexpected futex value in FUTEX_WAIT\n", 69 70 basename(argv[0])); 70 71
+13 -4
tools/testing/selftests/kselftest.h
··· 33 33 }; 34 34 35 35 static struct ksft_count ksft_cnt; 36 + static unsigned int ksft_plan; 36 37 37 38 static inline int ksft_test_num(void) 38 39 { ··· 62 61 printf("TAP version 13\n"); 63 62 } 64 63 64 + static inline void ksft_set_plan(unsigned int plan) 65 + { 66 + ksft_plan = plan; 67 + printf("1..%d\n", ksft_plan); 68 + } 69 + 65 70 static inline void ksft_print_cnts(void) 66 71 { 67 - printf("Pass %d Fail %d Xfail %d Xpass %d Skip %d Error %d\n", 72 + if (ksft_plan != ksft_test_num()) 73 + printf("# Planned tests != run tests (%u != %u)\n", 74 + ksft_plan, ksft_test_num()); 75 + printf("# Pass %d Fail %d Xfail %d Xpass %d Skip %d Error %d\n", 68 76 ksft_cnt.ksft_pass, ksft_cnt.ksft_fail, 69 77 ksft_cnt.ksft_xfail, ksft_cnt.ksft_xpass, 70 78 ksft_cnt.ksft_xskip, ksft_cnt.ksft_error); 71 - printf("1..%d\n", ksft_test_num()); 72 79 } 73 80 74 81 static inline void ksft_print_msg(const char *msg, ...) ··· 120 111 ksft_cnt.ksft_xskip++; 121 112 122 113 va_start(args, msg); 123 - printf("ok %d # skip ", ksft_test_num()); 114 + printf("not ok %d # SKIP ", ksft_test_num()); 124 115 vprintf(msg, args); 125 116 va_end(args); 126 117 } ··· 181 172 va_list args; 182 173 183 174 va_start(args, msg); 184 - printf("1..%d # Skipped: ", ksft_test_num()); 175 + printf("not ok %d # SKIP ", 1 + ksft_test_num()); 185 176 vprintf(msg, args); 186 177 va_end(args); 187 178 } else {
+23
tools/testing/selftests/kselftest/prefix.pl
··· 1 + #!/usr/bin/perl 2 + # SPDX-License-Identifier: GPL-2.0 3 + # Prefix all lines with "# ", unbuffered. Command being piped in may need 4 + # to have unbuffering forced with "stdbuf -i0 -o0 -e0 $cmd". 5 + use strict; 6 + 7 + binmode STDIN; 8 + binmode STDOUT; 9 + 10 + STDOUT->autoflush(1); 11 + 12 + my $needed = 1; 13 + while (1) { 14 + my $char; 15 + my $bytes = sysread(STDIN, $char, 1); 16 + exit 0 if ($bytes == 0); 17 + if ($needed) { 18 + print "# "; 19 + $needed = 0; 20 + } 21 + print $char; 22 + $needed = 1 if ($char eq "\n"); 23 + }
+86
tools/testing/selftests/kselftest/runner.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0 3 + # 4 + # Runs a set of tests in a given subdirectory. 5 + export skip_rc=4 6 + export logfile=/dev/stdout 7 + export per_test_logging= 8 + 9 + # There isn't a shell-agnostic way to find the path of a sourced file, 10 + # so we must rely on BASE_DIR being set to find other tools. 11 + if [ -z "$BASE_DIR" ]; then 12 + echo "Error: BASE_DIR must be set before sourcing." >&2 13 + exit 1 14 + fi 15 + 16 + # If Perl is unavailable, we must fall back to line-at-a-time prefixing 17 + # with sed instead of unbuffered output. 18 + tap_prefix() 19 + { 20 + if [ ! -x /usr/bin/perl ]; then 21 + sed -e 's/^/# /' 22 + else 23 + "$BASE_DIR"/kselftest/prefix.pl 24 + fi 25 + } 26 + 27 + # If stdbuf is unavailable, we must fall back to line-at-a-time piping. 28 + tap_unbuffer() 29 + { 30 + if ! which stdbuf >/dev/null ; then 31 + "$@" 32 + else 33 + stdbuf -i0 -o0 -e0 "$@" 34 + fi 35 + } 36 + 37 + run_one() 38 + { 39 + DIR="$1" 40 + TEST="$2" 41 + NUM="$3" 42 + 43 + BASENAME_TEST=$(basename $TEST) 44 + 45 + TEST_HDR_MSG="selftests: $DIR: $BASENAME_TEST" 46 + echo "# $TEST_HDR_MSG" 47 + if [ ! -x "$TEST" ]; then 48 + echo -n "# Warning: file $TEST is " 49 + if [ ! -e "$TEST" ]; then 50 + echo "missing!" 51 + else 52 + echo "not executable, correct this." 53 + fi 54 + echo "not ok $test_num $TEST_HDR_MSG" 55 + else 56 + cd `dirname $TEST` > /dev/null 57 + (((((tap_unbuffer ./$BASENAME_TEST 2>&1; echo $? >&3) | 58 + tap_prefix >&4) 3>&1) | 59 + (read xs; exit $xs)) 4>>"$logfile" && 60 + echo "ok $test_num $TEST_HDR_MSG") || 61 + (if [ $? -eq $skip_rc ]; then \ 62 + echo "not ok $test_num $TEST_HDR_MSG # SKIP" 63 + else 64 + echo "not ok $test_num $TEST_HDR_MSG" 65 + fi) 66 + cd - >/dev/null 67 + fi 68 + } 69 + 70 + run_many() 71 + { 72 + echo "TAP version 13" 73 + DIR=$(basename "$PWD") 74 + test_num=0 75 + total=$(echo "$@" | wc -w) 76 + echo "1..$total" 77 + for TEST in "$@"; do 78 + BASENAME_TEST=$(basename $TEST) 79 + test_num=$(( test_num + 1 )) 80 + if [ -n "$per_test_logging" ]; then 81 + logfile="/tmp/$BASENAME_TEST" 82 + cat /dev/null > "$logfile" 83 + fi 84 + run_one "$DIR" "$TEST" "$test_num" 85 + done 86 + }
+14 -62
tools/testing/selftests/lib.mk
··· 3 3 CC := $(CROSS_COMPILE)gcc 4 4 5 5 ifeq (0,$(MAKELEVEL)) 6 - ifneq ($(O),) 7 - OUTPUT := $(O) 8 - else 9 - ifneq ($(KBUILD_OUTPUT),) 10 - OUTPUT := $(KBUILD_OUTPUT) 11 - else 12 - OUTPUT := $(shell pwd) 13 - DEFAULT_INSTALL_HDR_PATH := 1 14 - endif 6 + ifeq ($(OUTPUT),) 7 + OUTPUT := $(shell pwd) 8 + DEFAULT_INSTALL_HDR_PATH := 1 15 9 endif 16 10 endif 11 + selfdir = $(realpath $(dir $(filter %/lib.mk,$(MAKEFILE_LIST)))) 17 12 18 13 # The following are built by lib.mk common compile rules. 19 14 # TEST_CUSTOM_PROGS should be used by tests that require ··· 60 65 endif 61 66 62 67 .ONESHELL: 63 - define RUN_TEST_PRINT_RESULT 64 - TEST_HDR_MSG="selftests: "`basename $$PWD`:" $$BASENAME_TEST"; \ 65 - echo $$TEST_HDR_MSG; \ 66 - echo "========================================"; \ 67 - if [ ! -x $$TEST ]; then \ 68 - echo "$$TEST_HDR_MSG: Warning: file $$BASENAME_TEST is not executable, correct this.";\ 69 - echo "not ok 1..$$test_num $$TEST_HDR_MSG [FAIL]"; \ 70 - else \ 71 - cd `dirname $$TEST` > /dev/null; \ 72 - if [ "X$(summary)" != "X" ]; then \ 73 - (./$$BASENAME_TEST > /tmp/$$BASENAME_TEST 2>&1 && \ 74 - echo "ok 1..$$test_num $$TEST_HDR_MSG [PASS]") || \ 75 - (if [ $$? -eq $$skip ]; then \ 76 - echo "not ok 1..$$test_num $$TEST_HDR_MSG [SKIP]"; \ 77 - else echo "not ok 1..$$test_num $$TEST_HDR_MSG [FAIL]"; \ 78 - fi;) \ 79 - else \ 80 - (./$$BASENAME_TEST && \ 81 - echo "ok 1..$$test_num $$TEST_HDR_MSG [PASS]") || \ 82 - (if [ $$? -eq $$skip ]; then \ 83 - echo "not ok 1..$$test_num $$TEST_HDR_MSG [SKIP]"; \ 84 - else echo "not ok 1..$$test_num $$TEST_HDR_MSG [FAIL]"; \ 85 - fi;) \ 86 - fi; \ 87 - cd - > /dev/null; \ 88 - fi; 89 - endef 90 - 91 68 define RUN_TESTS 92 - @export KSFT_TAP_LEVEL=`echo 1`; \ 93 - test_num=`echo 0`; \ 94 - skip=`echo 4`; \ 95 - echo "TAP version 13"; \ 96 - for TEST in $(1); do \ 97 - BASENAME_TEST=`basename $$TEST`; \ 98 - test_num=`echo $$test_num+1 | bc`; \ 99 - $(call RUN_TEST_PRINT_RESULT,$(TEST),$(BASENAME_TEST),$(test_num),$(skip)) \ 100 - done; 69 + @BASE_DIR="$(selfdir)"; \ 70 + . $(selfdir)/kselftest/runner.sh; \ 71 + if [ "X$(summary)" != "X" ]; then \ 72 + per_test_logging=1; \ 73 + fi; \ 74 + run_many $(1) 101 75 endef 102 76 103 77 run_tests: all ··· 103 139 $(error Error: set INSTALL_PATH to use install) 104 140 endif 105 141 106 - define EMIT_TESTS 107 - @test_num=`echo 0`; \ 142 + emit_tests: 108 143 for TEST in $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_PROGS); do \ 109 144 BASENAME_TEST=`basename $$TEST`; \ 110 - test_num=`echo $$test_num+1 | bc`; \ 111 - TEST_HDR_MSG="selftests: "`basename $$PWD`:" $$BASENAME_TEST"; \ 112 - echo "echo $$TEST_HDR_MSG"; \ 113 - if [ ! -x $$TEST ]; then \ 114 - echo "echo \"$$TEST_HDR_MSG: Warning: file $$BASENAME_TEST is not executable, correct this.\""; \ 115 - echo "echo \"not ok 1..$$test_num $$TEST_HDR_MSG [FAIL]\""; \ 116 - else 117 - echo "(./$$BASENAME_TEST >> \$$OUTPUT 2>&1 && echo \"ok 1..$$test_num $$TEST_HDR_MSG [PASS]\") || (if [ \$$? -eq \$$skip ]; then echo \"not ok 1..$$test_num $$TEST_HDR_MSG [SKIP]\"; else echo \"not ok 1..$$test_num $$TEST_HDR_MSG [FAIL]\"; fi;)"; \ 118 - fi; \ 119 - done; 120 - endef 121 - 122 - emit_tests: 123 - $(EMIT_TESTS) 145 + echo " \\"; \ 146 + echo -n " \"$$BASENAME_TEST\""; \ 147 + done; \ 124 148 125 149 # define if isn't already. It is undefined in make O= case. 126 150 ifeq ($(RM),)
+1
tools/testing/selftests/membarrier/membarrier_test.c
··· 304 304 int main(int argc, char **argv) 305 305 { 306 306 ksft_print_header(); 307 + ksft_set_plan(13); 307 308 308 309 test_membarrier_query(); 309 310 test_membarrier();
+1
tools/testing/selftests/pidfd/.gitignore
··· 1 + pidfd_test
+1
tools/testing/selftests/pidfd/pidfd_test.c
··· 371 371 int main(int argc, char **argv) 372 372 { 373 373 ksft_print_header(); 374 + ksft_set_plan(4); 374 375 375 376 test_pidfd_send_signal_syscall_support(); 376 377 test_pidfd_send_signal_simple_success();
+7 -1
tools/testing/selftests/rseq/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0+ OR MIT 2 - CFLAGS += -O2 -Wall -g -I./ -I../../../../usr/include/ -L./ -Wl,-rpath=./ 2 + 3 + ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),) 4 + CLANG_FLAGS += -no-integrated-as 5 + endif 6 + 7 + CFLAGS += -O2 -Wall -g -I./ -I../../../../usr/include/ -L./ -Wl,-rpath=./ \ 8 + $(CLANG_FLAGS) 3 9 LDLIBS += -lpthread 4 10 5 11 # Own dependencies because we only want to build against 1st prerequisite, but
+118 -14
tools/testing/selftests/rseq/rseq-arm.h
··· 5 5 * (C) Copyright 2016-2018 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> 6 6 */ 7 7 8 - #define RSEQ_SIG 0x53053053 8 + /* 9 + * RSEQ_SIG uses the udf A32 instruction with an uncommon immediate operand 10 + * value 0x5de3. This traps if user-space reaches this instruction by mistake, 11 + * and the uncommon operand ensures the kernel does not move the instruction 12 + * pointer to attacker-controlled code on rseq abort. 13 + * 14 + * The instruction pattern in the A32 instruction set is: 15 + * 16 + * e7f5def3 udf #24035 ; 0x5de3 17 + * 18 + * This translates to the following instruction pattern in the T16 instruction 19 + * set: 20 + * 21 + * little endian: 22 + * def3 udf #243 ; 0xf3 23 + * e7f5 b.n <7f5> 24 + * 25 + * pre-ARMv6 big endian code: 26 + * e7f5 b.n <7f5> 27 + * def3 udf #243 ; 0xf3 28 + * 29 + * ARMv6+ -mbig-endian generates mixed endianness code vs data: little-endian 30 + * code and big-endian data. Ensure the RSEQ_SIG data signature matches code 31 + * endianness. Prior to ARMv6, -mbig-endian generates big-endian code and data 32 + * (which match), so there is no need to reverse the endianness of the data 33 + * representation of the signature. However, the choice between BE32 and BE8 34 + * is done by the linker, so we cannot know whether code and data endianness 35 + * will be mixed before the linker is invoked. 36 + */ 37 + 38 + #define RSEQ_SIG_CODE 0xe7f5def3 39 + 40 + #ifndef __ASSEMBLER__ 41 + 42 + #define RSEQ_SIG_DATA \ 43 + ({ \ 44 + int sig; \ 45 + asm volatile ("b 2f\n\t" \ 46 + "1: .inst " __rseq_str(RSEQ_SIG_CODE) "\n\t" \ 47 + "2:\n\t" \ 48 + "ldr %[sig], 1b\n\t" \ 49 + : [sig] "=r" (sig)); \ 50 + sig; \ 51 + }) 52 + 53 + #define RSEQ_SIG RSEQ_SIG_DATA 54 + 55 + #endif 9 56 10 57 #define rseq_smp_mb() __asm__ __volatile__ ("dmb" ::: "memory", "cc") 11 58 #define rseq_smp_rmb() __asm__ __volatile__ ("dmb" ::: "memory", "cc") ··· 77 30 #include "rseq-skip.h" 78 31 #else /* !RSEQ_SKIP_FASTPATH */ 79 32 80 - #define __RSEQ_ASM_DEFINE_TABLE(version, flags, start_ip, \ 33 + #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, start_ip, \ 81 34 post_commit_offset, abort_ip) \ 82 - ".pushsection __rseq_table, \"aw\"\n\t" \ 35 + ".pushsection __rseq_cs, \"aw\"\n\t" \ 83 36 ".balign 32\n\t" \ 37 + __rseq_str(label) ":\n\t" \ 84 38 ".word " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \ 85 39 ".word " __rseq_str(start_ip) ", 0x0, " __rseq_str(post_commit_offset) ", 0x0, " __rseq_str(abort_ip) ", 0x0\n\t" \ 40 + ".popsection\n\t" \ 41 + ".pushsection __rseq_cs_ptr_array, \"aw\"\n\t" \ 42 + ".word " __rseq_str(label) "b, 0x0\n\t" \ 86 43 ".popsection\n\t" 87 44 88 - #define RSEQ_ASM_DEFINE_TABLE(start_ip, post_commit_ip, abort_ip) \ 89 - __RSEQ_ASM_DEFINE_TABLE(0x0, 0x0, start_ip, \ 45 + #define RSEQ_ASM_DEFINE_TABLE(label, start_ip, post_commit_ip, abort_ip) \ 46 + __RSEQ_ASM_DEFINE_TABLE(label, 0x0, 0x0, start_ip, \ 90 47 (post_commit_ip - start_ip), abort_ip) 48 + 49 + /* 50 + * Exit points of a rseq critical section consist of all instructions outside 51 + * of the critical section where a critical section can either branch to or 52 + * reach through the normal course of its execution. The abort IP and the 53 + * post-commit IP are already part of the __rseq_cs section and should not be 54 + * explicitly defined as additional exit points. Knowing all exit points is 55 + * useful to assist debuggers stepping over the critical section. 56 + */ 57 + #define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip) \ 58 + ".pushsection __rseq_exit_point_array, \"aw\"\n\t" \ 59 + ".word " __rseq_str(start_ip) ", 0x0, " __rseq_str(exit_ip) ", 0x0\n\t" \ 60 + ".popsection\n\t" 91 61 92 62 #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs) \ 93 63 RSEQ_INJECT_ASM(1) \ ··· 125 61 __rseq_str(table_label) ":\n\t" \ 126 62 ".word " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \ 127 63 ".word " __rseq_str(start_ip) ", 0x0, " __rseq_str(post_commit_offset) ", 0x0, " __rseq_str(abort_ip) ", 0x0\n\t" \ 128 - ".word " __rseq_str(RSEQ_SIG) "\n\t" \ 64 + ".arm\n\t" \ 65 + ".inst " __rseq_str(RSEQ_SIG_CODE) "\n\t" \ 129 66 __rseq_str(label) ":\n\t" \ 130 67 teardown \ 131 68 "b %l[" __rseq_str(abort_label) "]\n\t" ··· 151 86 152 87 rseq_workaround_gcc_asm_size_guess(); 153 88 __asm__ __volatile__ goto ( 154 - RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */ 89 + RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */ 90 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 91 + #ifdef RSEQ_COMPARE_TWICE 92 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 93 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 94 + #endif 155 95 /* Start rseq by storing table entry pointer into rseq_cs. */ 156 96 RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs) 157 97 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) ··· 218 148 219 149 rseq_workaround_gcc_asm_size_guess(); 220 150 __asm__ __volatile__ goto ( 221 - RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */ 151 + RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */ 152 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 153 + #ifdef RSEQ_COMPARE_TWICE 154 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 155 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 156 + #endif 222 157 /* Start rseq by storing table entry pointer into rseq_cs. */ 223 158 RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs) 224 159 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) ··· 289 214 290 215 rseq_workaround_gcc_asm_size_guess(); 291 216 __asm__ __volatile__ goto ( 292 - RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */ 217 + RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */ 218 + #ifdef RSEQ_COMPARE_TWICE 219 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 220 + #endif 293 221 /* Start rseq by storing table entry pointer into rseq_cs. */ 294 222 RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs) 295 223 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) ··· 344 266 345 267 rseq_workaround_gcc_asm_size_guess(); 346 268 __asm__ __volatile__ goto ( 347 - RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */ 269 + RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */ 270 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 271 + #ifdef RSEQ_COMPARE_TWICE 272 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 273 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 274 + #endif 348 275 /* Start rseq by storing table entry pointer into rseq_cs. */ 349 276 RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs) 350 277 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) ··· 419 336 420 337 rseq_workaround_gcc_asm_size_guess(); 421 338 __asm__ __volatile__ goto ( 422 - RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */ 339 + RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */ 340 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 341 + #ifdef RSEQ_COMPARE_TWICE 342 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 343 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 344 + #endif 423 345 /* Start rseq by storing table entry pointer into rseq_cs. */ 424 346 RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs) 425 347 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) ··· 495 407 496 408 rseq_workaround_gcc_asm_size_guess(); 497 409 __asm__ __volatile__ goto ( 498 - RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */ 410 + RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */ 411 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 412 + #ifdef RSEQ_COMPARE_TWICE 413 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 414 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 415 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error3]) 416 + #endif 499 417 /* Start rseq by storing table entry pointer into rseq_cs. */ 500 418 RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs) 501 419 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) ··· 579 485 580 486 rseq_workaround_gcc_asm_size_guess(); 581 487 __asm__ __volatile__ goto ( 582 - RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */ 488 + RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */ 489 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 490 + #ifdef RSEQ_COMPARE_TWICE 491 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 492 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 493 + #endif 583 494 "str %[src], %[rseq_scratch0]\n\t" 584 495 "str %[dst], %[rseq_scratch1]\n\t" 585 496 "str %[len], %[rseq_scratch2]\n\t" ··· 703 604 704 605 rseq_workaround_gcc_asm_size_guess(); 705 606 __asm__ __volatile__ goto ( 706 - RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */ 607 + RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */ 608 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 609 + #ifdef RSEQ_COMPARE_TWICE 610 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 611 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 612 + #endif 707 613 "str %[src], %[rseq_scratch0]\n\t" 708 614 "str %[dst], %[rseq_scratch1]\n\t" 709 615 "str %[len], %[rseq_scratch2]\n\t"
+71 -3
tools/testing/selftests/rseq/rseq-arm64.h
··· 6 6 * (C) Copyright 2018 - Will Deacon <will.deacon@arm.com> 7 7 */ 8 8 9 - #define RSEQ_SIG 0xd428bc00 /* BRK #0x45E0 */ 9 + /* 10 + * aarch64 -mbig-endian generates mixed endianness code vs data: 11 + * little-endian code and big-endian data. Ensure the RSEQ_SIG signature 12 + * matches code endianness. 13 + */ 14 + #define RSEQ_SIG_CODE 0xd428bc00 /* BRK #0x45E0. */ 15 + 16 + #ifdef __AARCH64EB__ 17 + #define RSEQ_SIG_DATA 0x00bc28d4 /* BRK #0x45E0. */ 18 + #else 19 + #define RSEQ_SIG_DATA RSEQ_SIG_CODE 20 + #endif 21 + 22 + #define RSEQ_SIG RSEQ_SIG_DATA 10 23 11 24 #define rseq_smp_mb() __asm__ __volatile__ ("dmb ish" ::: "memory") 12 25 #define rseq_smp_rmb() __asm__ __volatile__ ("dmb ishld" ::: "memory") ··· 95 82 96 83 #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, start_ip, \ 97 84 post_commit_offset, abort_ip) \ 98 - " .pushsection __rseq_table, \"aw\"\n" \ 85 + " .pushsection __rseq_cs, \"aw\"\n" \ 99 86 " .balign 32\n" \ 100 87 __rseq_str(label) ":\n" \ 101 88 " .long " __rseq_str(version) ", " __rseq_str(flags) "\n" \ 102 89 " .quad " __rseq_str(start_ip) ", " \ 103 90 __rseq_str(post_commit_offset) ", " \ 104 91 __rseq_str(abort_ip) "\n" \ 92 + " .popsection\n\t" \ 93 + " .pushsection __rseq_cs_ptr_array, \"aw\"\n" \ 94 + " .quad " __rseq_str(label) "b\n" \ 105 95 " .popsection\n" 106 96 107 97 #define RSEQ_ASM_DEFINE_TABLE(label, start_ip, post_commit_ip, abort_ip) \ 108 98 __RSEQ_ASM_DEFINE_TABLE(label, 0x0, 0x0, start_ip, \ 109 99 (post_commit_ip - start_ip), abort_ip) 100 + 101 + /* 102 + * Exit points of a rseq critical section consist of all instructions outside 103 + * of the critical section where a critical section can either branch to or 104 + * reach through the normal course of its execution. The abort IP and the 105 + * post-commit IP are already part of the __rseq_cs section and should not be 106 + * explicitly defined as additional exit points. Knowing all exit points is 107 + * useful to assist debuggers stepping over the critical section. 108 + */ 109 + #define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip) \ 110 + " .pushsection __rseq_exit_point_array, \"aw\"\n" \ 111 + " .quad " __rseq_str(start_ip) ", " __rseq_str(exit_ip) "\n" \ 112 + " .popsection\n" 110 113 111 114 #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs) \ 112 115 RSEQ_INJECT_ASM(1) \ ··· 134 105 135 106 #define RSEQ_ASM_DEFINE_ABORT(label, abort_label) \ 136 107 " b 222f\n" \ 137 - " .inst " __rseq_str(RSEQ_SIG) "\n" \ 108 + " .inst " __rseq_str(RSEQ_SIG_CODE) "\n" \ 138 109 __rseq_str(label) ":\n" \ 139 110 " b %l[" __rseq_str(abort_label) "]\n" \ 140 111 "222:\n" ··· 211 182 212 183 __asm__ __volatile__ goto ( 213 184 RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f) 185 + RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[cmpfail]) 186 + #ifdef RSEQ_COMPARE_TWICE 187 + RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1]) 188 + RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error2]) 189 + #endif 214 190 RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs) 215 191 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 216 192 RSEQ_INJECT_ASM(3) ··· 265 231 266 232 __asm__ __volatile__ goto ( 267 233 RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f) 234 + RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[cmpfail]) 235 + #ifdef RSEQ_COMPARE_TWICE 236 + RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1]) 237 + RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error2]) 238 + #endif 268 239 RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs) 269 240 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 270 241 RSEQ_INJECT_ASM(3) ··· 321 282 322 283 __asm__ __volatile__ goto ( 323 284 RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f) 285 + #ifdef RSEQ_COMPARE_TWICE 286 + RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1]) 287 + #endif 324 288 RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs) 325 289 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 326 290 RSEQ_INJECT_ASM(3) ··· 367 325 368 326 __asm__ __volatile__ goto ( 369 327 RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f) 328 + RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[cmpfail]) 329 + #ifdef RSEQ_COMPARE_TWICE 330 + RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1]) 331 + RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error2]) 332 + #endif 370 333 RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs) 371 334 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 372 335 RSEQ_INJECT_ASM(3) ··· 426 379 427 380 __asm__ __volatile__ goto ( 428 381 RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f) 382 + RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[cmpfail]) 383 + #ifdef RSEQ_COMPARE_TWICE 384 + RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1]) 385 + RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error2]) 386 + #endif 429 387 RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs) 430 388 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 431 389 RSEQ_INJECT_ASM(3) ··· 485 433 486 434 __asm__ __volatile__ goto ( 487 435 RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f) 436 + RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[cmpfail]) 437 + #ifdef RSEQ_COMPARE_TWICE 438 + RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1]) 439 + RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error2]) 440 + RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error3]) 441 + #endif 488 442 RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs) 489 443 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 490 444 RSEQ_INJECT_ASM(3) ··· 548 490 549 491 __asm__ __volatile__ goto ( 550 492 RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f) 493 + RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[cmpfail]) 494 + #ifdef RSEQ_COMPARE_TWICE 495 + RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1]) 496 + RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error2]) 497 + #endif 551 498 RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs) 552 499 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 553 500 RSEQ_INJECT_ASM(3) ··· 608 545 609 546 __asm__ __volatile__ goto ( 610 547 RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f) 548 + RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[cmpfail]) 549 + #ifdef RSEQ_COMPARE_TWICE 550 + RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error1]) 551 + RSEQ_ASM_DEFINE_EXIT_POINT(2f, %l[error2]) 552 + #endif 611 553 RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs) 612 554 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 613 555 RSEQ_INJECT_ASM(3)
+102 -13
tools/testing/selftests/rseq/rseq-mips.h
··· 7 7 * (C) Copyright 2016-2018 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> 8 8 */ 9 9 10 - #define RSEQ_SIG 0x53053053 10 + /* 11 + * RSEQ_SIG uses the break instruction. The instruction pattern is: 12 + * 13 + * On MIPS: 14 + * 0350000d break 0x350 15 + * 16 + * On nanoMIPS: 17 + * 00100350 break 0x350 18 + * 19 + * On microMIPS: 20 + * 0000d407 break 0x350 21 + * 22 + * For nanoMIPS32 and microMIPS, the instruction stream is encoded as 16-bit 23 + * halfwords, so the signature halfwords need to be swapped accordingly for 24 + * little-endian. 25 + */ 26 + #if defined(__nanomips__) 27 + # ifdef __MIPSEL__ 28 + # define RSEQ_SIG 0x03500010 29 + # else 30 + # define RSEQ_SIG 0x00100350 31 + # endif 32 + #elif defined(__mips_micromips) 33 + # ifdef __MIPSEL__ 34 + # define RSEQ_SIG 0xd4070000 35 + # else 36 + # define RSEQ_SIG 0x0000d407 37 + # endif 38 + #elif defined(__mips__) 39 + # define RSEQ_SIG 0x0350000d 40 + #else 41 + /* Unknown MIPS architecture. */ 42 + #endif 11 43 12 44 #define rseq_smp_mb() __asm__ __volatile__ ("sync" ::: "memory") 13 45 #define rseq_smp_rmb() rseq_smp_mb() ··· 86 54 # error unsupported _MIPS_SZLONG 87 55 #endif 88 56 89 - #define __RSEQ_ASM_DEFINE_TABLE(version, flags, start_ip, \ 57 + #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, start_ip, \ 90 58 post_commit_offset, abort_ip) \ 91 - ".pushsection __rseq_table, \"aw\"\n\t" \ 59 + ".pushsection __rseq_cs, \"aw\"\n\t" \ 92 60 ".balign 32\n\t" \ 61 + __rseq_str(label) ":\n\t" \ 93 62 ".word " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \ 94 63 LONG " " U32_U64_PAD(__rseq_str(start_ip)) "\n\t" \ 95 64 LONG " " U32_U64_PAD(__rseq_str(post_commit_offset)) "\n\t" \ 96 65 LONG " " U32_U64_PAD(__rseq_str(abort_ip)) "\n\t" \ 66 + ".popsection\n\t" \ 67 + ".pushsection __rseq_cs_ptr_array, \"aw\"\n\t" \ 68 + LONG " " U32_U64_PAD(__rseq_str(label) "b") "\n\t" \ 97 69 ".popsection\n\t" 98 70 99 - #define RSEQ_ASM_DEFINE_TABLE(start_ip, post_commit_ip, abort_ip) \ 100 - __RSEQ_ASM_DEFINE_TABLE(0x0, 0x0, start_ip, \ 71 + #define RSEQ_ASM_DEFINE_TABLE(label, start_ip, post_commit_ip, abort_ip) \ 72 + __RSEQ_ASM_DEFINE_TABLE(label, 0x0, 0x0, start_ip, \ 101 73 (post_commit_ip - start_ip), abort_ip) 74 + 75 + /* 76 + * Exit points of a rseq critical section consist of all instructions outside 77 + * of the critical section where a critical section can either branch to or 78 + * reach through the normal course of its execution. The abort IP and the 79 + * post-commit IP are already part of the __rseq_cs section and should not be 80 + * explicitly defined as additional exit points. Knowing all exit points is 81 + * useful to assist debuggers stepping over the critical section. 82 + */ 83 + #define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip) \ 84 + ".pushsection __rseq_exit_point_array, \"aw\"\n\t" \ 85 + LONG " " U32_U64_PAD(__rseq_str(start_ip)) "\n\t" \ 86 + LONG " " U32_U64_PAD(__rseq_str(exit_ip)) "\n\t" \ 87 + ".popsection\n\t" 102 88 103 89 #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs) \ 104 90 RSEQ_INJECT_ASM(1) \ ··· 163 113 164 114 rseq_workaround_gcc_asm_size_guess(); 165 115 __asm__ __volatile__ goto ( 166 - RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */ 116 + RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */ 117 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 118 + #ifdef RSEQ_COMPARE_TWICE 119 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 120 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 121 + #endif 167 122 /* Start rseq by storing table entry pointer into rseq_cs. */ 168 123 RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs) 169 124 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) ··· 228 173 229 174 rseq_workaround_gcc_asm_size_guess(); 230 175 __asm__ __volatile__ goto ( 231 - RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */ 176 + RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */ 177 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 178 + #ifdef RSEQ_COMPARE_TWICE 179 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 180 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 181 + #endif 232 182 /* Start rseq by storing table entry pointer into rseq_cs. */ 233 183 RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs) 234 184 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) ··· 297 237 298 238 rseq_workaround_gcc_asm_size_guess(); 299 239 __asm__ __volatile__ goto ( 300 - RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */ 240 + RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */ 241 + #ifdef RSEQ_COMPARE_TWICE 242 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 243 + #endif 301 244 /* Start rseq by storing table entry pointer into rseq_cs. */ 302 245 RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs) 303 246 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) ··· 352 289 353 290 rseq_workaround_gcc_asm_size_guess(); 354 291 __asm__ __volatile__ goto ( 355 - RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */ 292 + RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */ 293 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 294 + #ifdef RSEQ_COMPARE_TWICE 295 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 296 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 297 + #endif 356 298 /* Start rseq by storing table entry pointer into rseq_cs. */ 357 299 RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs) 358 300 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) ··· 425 357 426 358 rseq_workaround_gcc_asm_size_guess(); 427 359 __asm__ __volatile__ goto ( 428 - RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */ 360 + RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */ 361 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 362 + #ifdef RSEQ_COMPARE_TWICE 363 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 364 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 365 + #endif 429 366 /* Start rseq by storing table entry pointer into rseq_cs. */ 430 367 RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs) 431 368 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) ··· 499 426 500 427 rseq_workaround_gcc_asm_size_guess(); 501 428 __asm__ __volatile__ goto ( 502 - RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */ 429 + RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */ 430 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 431 + #ifdef RSEQ_COMPARE_TWICE 432 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 433 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 434 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error3]) 435 + #endif 503 436 /* Start rseq by storing table entry pointer into rseq_cs. */ 504 437 RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs) 505 438 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) ··· 579 500 580 501 rseq_workaround_gcc_asm_size_guess(); 581 502 __asm__ __volatile__ goto ( 582 - RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */ 503 + RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */ 504 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 505 + #ifdef RSEQ_COMPARE_TWICE 506 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 507 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 508 + #endif 583 509 LONG_S " %[src], %[rseq_scratch0]\n\t" 584 510 LONG_S " %[dst], %[rseq_scratch1]\n\t" 585 511 LONG_S " %[len], %[rseq_scratch2]\n\t" ··· 700 616 701 617 rseq_workaround_gcc_asm_size_guess(); 702 618 __asm__ __volatile__ goto ( 703 - RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */ 619 + RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */ 620 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 621 + #ifdef RSEQ_COMPARE_TWICE 622 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 623 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 624 + #endif 704 625 LONG_S " %[src], %[rseq_scratch0]\n\t" 705 626 LONG_S " %[dst], %[rseq_scratch1]\n\t" 706 627 LONG_S " %[len], %[rseq_scratch2]\n\t"
+85 -5
tools/testing/selftests/rseq/rseq-ppc.h
··· 6 6 * (C) Copyright 2016-2018 - Boqun Feng <boqun.feng@gmail.com> 7 7 */ 8 8 9 - #define RSEQ_SIG 0x53053053 9 + /* 10 + * RSEQ_SIG is used with the following trap instruction: 11 + * 12 + * powerpc-be: 0f e5 00 0b twui r5,11 13 + * powerpc64-le: 0b 00 e5 0f twui r5,11 14 + * powerpc64-be: 0f e5 00 0b twui r5,11 15 + */ 16 + 17 + #define RSEQ_SIG 0x0fe5000b 10 18 11 19 #define rseq_smp_mb() __asm__ __volatile__ ("sync" ::: "memory", "cc") 12 20 #define rseq_smp_lwsync() __asm__ __volatile__ ("lwsync" ::: "memory", "cc") ··· 41 33 #else /* !RSEQ_SKIP_FASTPATH */ 42 34 43 35 /* 44 - * The __rseq_table section can be used by debuggers to better handle 45 - * single-stepping through the restartable critical sections. 36 + * The __rseq_cs_ptr_array and __rseq_cs sections can be used by debuggers to 37 + * better handle single-stepping through the restartable critical sections. 46 38 */ 47 39 48 40 #ifdef __PPC64__ ··· 54 46 55 47 #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, \ 56 48 start_ip, post_commit_offset, abort_ip) \ 57 - ".pushsection __rseq_table, \"aw\"\n\t" \ 49 + ".pushsection __rseq_cs, \"aw\"\n\t" \ 58 50 ".balign 32\n\t" \ 59 51 __rseq_str(label) ":\n\t" \ 60 52 ".long " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \ 61 53 ".quad " __rseq_str(start_ip) ", " __rseq_str(post_commit_offset) ", " __rseq_str(abort_ip) "\n\t" \ 54 + ".popsection\n\t" \ 55 + ".pushsection __rseq_cs_ptr_array, \"aw\"\n\t" \ 56 + ".quad " __rseq_str(label) "b\n\t" \ 62 57 ".popsection\n\t" 63 58 64 59 #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs) \ ··· 74 63 "std %%r17, %[" __rseq_str(rseq_cs) "]\n\t" \ 75 64 __rseq_str(label) ":\n\t" 76 65 66 + /* 67 + * Exit points of a rseq critical section consist of all instructions outside 68 + * of the critical section where a critical section can either branch to or 69 + * reach through the normal course of its execution. The abort IP and the 70 + * post-commit IP are already part of the __rseq_cs section and should not be 71 + * explicitly defined as additional exit points. Knowing all exit points is 72 + * useful to assist debuggers stepping over the critical section. 73 + */ 74 + #define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip) \ 75 + ".pushsection __rseq_exit_point_array, \"aw\"\n\t" \ 76 + ".quad " __rseq_str(start_ip) ", " __rseq_str(exit_ip) "\n\t" \ 77 + ".popsection\n\t" 78 + 77 79 #else /* #ifdef __PPC64__ */ 78 80 79 81 #define STORE_WORD "stw " ··· 96 72 97 73 #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, \ 98 74 start_ip, post_commit_offset, abort_ip) \ 99 - ".pushsection __rseq_table, \"aw\"\n\t" \ 75 + ".pushsection __rseq_cs, \"aw\"\n\t" \ 100 76 ".balign 32\n\t" \ 101 77 __rseq_str(label) ":\n\t" \ 102 78 ".long " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \ 103 79 /* 32-bit only supported on BE */ \ 104 80 ".long 0x0, " __rseq_str(start_ip) ", 0x0, " __rseq_str(post_commit_offset) ", 0x0, " __rseq_str(abort_ip) "\n\t" \ 81 + ".popsection\n\t" \ 82 + ".pushsection __rseq_cs_ptr_array, \"aw\"\n\t" \ 83 + ".long 0x0, " __rseq_str(label) "b\n\t" \ 84 + ".popsection\n\t" 85 + 86 + /* 87 + * Exit points of a rseq critical section consist of all instructions outside 88 + * of the critical section where a critical section can either branch to or 89 + * reach through the normal course of its execution. The abort IP and the 90 + * post-commit IP are already part of the __rseq_cs section and should not be 91 + * explicitly defined as additional exit points. Knowing all exit points is 92 + * useful to assist debuggers stepping over the critical section. 93 + */ 94 + #define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip) \ 95 + ".pushsection __rseq_exit_point_array, \"aw\"\n\t" \ 96 + /* 32-bit only supported on BE */ \ 97 + ".long 0x0, " __rseq_str(start_ip) ", 0x0, " __rseq_str(exit_ip) "\n\t" \ 105 98 ".popsection\n\t" 106 99 107 100 #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs) \ ··· 210 169 211 170 __asm__ __volatile__ goto ( 212 171 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 172 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 173 + #ifdef RSEQ_COMPARE_TWICE 174 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 175 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 176 + #endif 213 177 /* Start rseq by storing table entry pointer into rseq_cs. */ 214 178 RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 215 179 /* cmp cpuid */ ··· 270 224 271 225 __asm__ __volatile__ goto ( 272 226 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 227 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 228 + #ifdef RSEQ_COMPARE_TWICE 229 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 230 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 231 + #endif 273 232 /* Start rseq by storing table entry pointer into rseq_cs. */ 274 233 RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 275 234 /* cmp cpuid */ ··· 337 286 338 287 __asm__ __volatile__ goto ( 339 288 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 289 + #ifdef RSEQ_COMPARE_TWICE 290 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 291 + #endif 340 292 /* Start rseq by storing table entry pointer into rseq_cs. */ 341 293 RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 342 294 /* cmp cpuid */ ··· 391 337 392 338 __asm__ __volatile__ goto ( 393 339 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 340 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 341 + #ifdef RSEQ_COMPARE_TWICE 342 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 343 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 344 + #endif 394 345 /* Start rseq by storing table entry pointer into rseq_cs. */ 395 346 RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 396 347 /* cmp cpuid */ ··· 459 400 460 401 __asm__ __volatile__ goto ( 461 402 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 403 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 404 + #ifdef RSEQ_COMPARE_TWICE 405 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 406 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 407 + #endif 462 408 /* Start rseq by storing table entry pointer into rseq_cs. */ 463 409 RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 464 410 /* cmp cpuid */ ··· 529 465 530 466 __asm__ __volatile__ goto ( 531 467 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 468 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 469 + #ifdef RSEQ_COMPARE_TWICE 470 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 471 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 472 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error3]) 473 + #endif 532 474 /* Start rseq by storing table entry pointer into rseq_cs. */ 533 475 RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 534 476 /* cmp cpuid */ ··· 602 532 603 533 __asm__ __volatile__ goto ( 604 534 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 535 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 536 + #ifdef RSEQ_COMPARE_TWICE 537 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 538 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 539 + #endif 605 540 /* setup for mempcy */ 606 541 "mr %%r19, %[len]\n\t" 607 542 "mr %%r20, %[src]\n\t" ··· 676 601 677 602 __asm__ __volatile__ goto ( 678 603 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 604 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 605 + #ifdef RSEQ_COMPARE_TWICE 606 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 607 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 608 + #endif 679 609 /* setup for mempcy */ 680 610 "mr %%r19, %[len]\n\t" 681 611 "mr %%r20, %[src]\n\t"
+65 -4
tools/testing/selftests/rseq/rseq-s390.h
··· 44 44 45 45 #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, \ 46 46 start_ip, post_commit_offset, abort_ip) \ 47 - ".pushsection __rseq_table, \"aw\"\n\t" \ 47 + ".pushsection __rseq_cs, \"aw\"\n\t" \ 48 48 ".balign 32\n\t" \ 49 49 __rseq_str(label) ":\n\t" \ 50 50 ".long " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \ 51 51 ".quad " __rseq_str(start_ip) ", " __rseq_str(post_commit_offset) ", " __rseq_str(abort_ip) "\n\t" \ 52 + ".popsection\n\t" \ 53 + ".pushsection __rseq_cs_ptr_array, \"aw\"\n\t" \ 54 + ".quad " __rseq_str(label) "b\n\t" \ 55 + ".popsection\n\t" 56 + 57 + /* 58 + * Exit points of a rseq critical section consist of all instructions outside 59 + * of the critical section where a critical section can either branch to or 60 + * reach through the normal course of its execution. The abort IP and the 61 + * post-commit IP are already part of the __rseq_cs section and should not be 62 + * explicitly defined as additional exit points. Knowing all exit points is 63 + * useful to assist debuggers stepping over the critical section. 64 + */ 65 + #define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip) \ 66 + ".pushsection __rseq_exit_point_array, \"aw\"\n\t" \ 67 + ".quad " __rseq_str(start_ip) ", " __rseq_str(exit_ip) "\n\t" \ 52 68 ".popsection\n\t" 53 69 54 70 #elif __s390__ 55 71 56 72 #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, \ 57 73 start_ip, post_commit_offset, abort_ip) \ 58 - ".pushsection __rseq_table, \"aw\"\n\t" \ 74 + ".pushsection __rseq_cs, \"aw\"\n\t" \ 59 75 ".balign 32\n\t" \ 60 76 __rseq_str(label) ":\n\t" \ 61 77 ".long " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \ 62 78 ".long 0x0, " __rseq_str(start_ip) ", 0x0, " __rseq_str(post_commit_offset) ", 0x0, " __rseq_str(abort_ip) "\n\t" \ 79 + ".popsection\n\t" \ 80 + ".pushsection __rseq_cs_ptr_array, \"aw\"\n\t" \ 81 + ".long 0x0, " __rseq_str(label) "b\n\t" \ 82 + ".popsection\n\t" 83 + 84 + /* 85 + * Exit points of a rseq critical section consist of all instructions outside 86 + * of the critical section where a critical section can either branch to or 87 + * reach through the normal course of its execution. The abort IP and the 88 + * post-commit IP are already part of the __rseq_cs section and should not be 89 + * explicitly defined as additional exit points. Knowing all exit points is 90 + * useful to assist debuggers stepping over the critical section. 91 + */ 92 + #define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip) \ 93 + ".pushsection __rseq_exit_point_array, \"aw\"\n\t" \ 94 + ".long 0x0, " __rseq_str(start_ip) ", 0x0, " __rseq_str(exit_ip) "\n\t" \ 63 95 ".popsection\n\t" 64 96 65 97 #define LONG_L "l" ··· 124 92 ".long " __rseq_str(RSEQ_SIG) "\n\t" \ 125 93 __rseq_str(label) ":\n\t" \ 126 94 teardown \ 127 - "j %l[" __rseq_str(abort_label) "]\n\t" \ 95 + "jg %l[" __rseq_str(abort_label) "]\n\t" \ 128 96 ".popsection\n\t" 129 97 130 98 #define RSEQ_ASM_DEFINE_CMPFAIL(label, teardown, cmpfail_label) \ 131 99 ".pushsection __rseq_failure, \"ax\"\n\t" \ 132 100 __rseq_str(label) ":\n\t" \ 133 101 teardown \ 134 - "j %l[" __rseq_str(cmpfail_label) "]\n\t" \ 102 + "jg %l[" __rseq_str(cmpfail_label) "]\n\t" \ 135 103 ".popsection\n\t" 136 104 137 105 static inline __attribute__((always_inline)) ··· 141 109 142 110 __asm__ __volatile__ goto ( 143 111 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 112 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 113 + #ifdef RSEQ_COMPARE_TWICE 114 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 115 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 116 + #endif 144 117 /* Start rseq by storing table entry pointer into rseq_cs. */ 145 118 RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 146 119 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) ··· 204 167 205 168 __asm__ __volatile__ goto ( 206 169 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 170 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 171 + #ifdef RSEQ_COMPARE_TWICE 172 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 173 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 174 + #endif 207 175 /* Start rseq by storing table entry pointer into rseq_cs. */ 208 176 RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 209 177 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) ··· 269 227 270 228 __asm__ __volatile__ goto ( 271 229 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 230 + #ifdef RSEQ_COMPARE_TWICE 231 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 232 + #endif 272 233 /* Start rseq by storing table entry pointer into rseq_cs. */ 273 234 RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 274 235 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) ··· 320 275 321 276 __asm__ __volatile__ goto ( 322 277 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 278 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 279 + #ifdef RSEQ_COMPARE_TWICE 280 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 281 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 282 + #endif 323 283 /* Start rseq by storing table entry pointer into rseq_cs. */ 324 284 RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 325 285 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) ··· 396 346 397 347 __asm__ __volatile__ goto ( 398 348 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 349 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 350 + #ifdef RSEQ_COMPARE_TWICE 351 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 352 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 353 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error3]) 354 + #endif 399 355 /* Start rseq by storing table entry pointer into rseq_cs. */ 400 356 RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 401 357 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) ··· 470 414 471 415 __asm__ __volatile__ goto ( 472 416 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 417 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 418 + #ifdef RSEQ_COMPARE_TWICE 419 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 420 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 421 + #endif 473 422 LONG_S " %[src], %[rseq_scratch0]\n\t" 474 423 LONG_S " %[dst], %[rseq_scratch1]\n\t" 475 424 LONG_S " %[len], %[rseq_scratch2]\n\t"
+184 -80
tools/testing/selftests/rseq/rseq-x86.h
··· 7 7 8 8 #include <stdint.h> 9 9 10 + /* 11 + * RSEQ_SIG is used with the following reserved undefined instructions, which 12 + * trap in user-space: 13 + * 14 + * x86-32: 0f b9 3d 53 30 05 53 ud1 0x53053053,%edi 15 + * x86-64: 0f b9 3d 53 30 05 53 ud1 0x53053053(%rip),%edi 16 + */ 10 17 #define RSEQ_SIG 0x53053053 18 + 19 + /* 20 + * Due to a compiler optimization bug in gcc-8 with asm goto and TLS asm input 21 + * operands, we cannot use "m" input operands, and rather pass the __rseq_abi 22 + * address through a "r" input operand. 23 + */ 24 + 25 + /* Offset of cpu_id and rseq_cs fields in struct rseq. */ 26 + #define RSEQ_CPU_ID_OFFSET 4 27 + #define RSEQ_CS_OFFSET 8 11 28 12 29 #ifdef __x86_64__ 13 30 ··· 54 37 55 38 #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, \ 56 39 start_ip, post_commit_offset, abort_ip) \ 57 - ".pushsection __rseq_table, \"aw\"\n\t" \ 40 + ".pushsection __rseq_cs, \"aw\"\n\t" \ 58 41 ".balign 32\n\t" \ 59 42 __rseq_str(label) ":\n\t" \ 60 43 ".long " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \ 61 44 ".quad " __rseq_str(start_ip) ", " __rseq_str(post_commit_offset) ", " __rseq_str(abort_ip) "\n\t" \ 45 + ".popsection\n\t" \ 46 + ".pushsection __rseq_cs_ptr_array, \"aw\"\n\t" \ 47 + ".quad " __rseq_str(label) "b\n\t" \ 62 48 ".popsection\n\t" 49 + 63 50 64 51 #define RSEQ_ASM_DEFINE_TABLE(label, start_ip, post_commit_ip, abort_ip) \ 65 52 __RSEQ_ASM_DEFINE_TABLE(label, 0x0, 0x0, start_ip, \ 66 53 (post_commit_ip - start_ip), abort_ip) 67 54 55 + /* 56 + * Exit points of a rseq critical section consist of all instructions outside 57 + * of the critical section where a critical section can either branch to or 58 + * reach through the normal course of its execution. The abort IP and the 59 + * post-commit IP are already part of the __rseq_cs section and should not be 60 + * explicitly defined as additional exit points. Knowing all exit points is 61 + * useful to assist debuggers stepping over the critical section. 62 + */ 63 + #define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip) \ 64 + ".pushsection __rseq_exit_point_array, \"aw\"\n\t" \ 65 + ".quad " __rseq_str(start_ip) ", " __rseq_str(exit_ip) "\n\t" \ 66 + ".popsection\n\t" 67 + 68 68 #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs) \ 69 69 RSEQ_INJECT_ASM(1) \ 70 70 "leaq " __rseq_str(cs_label) "(%%rip), %%rax\n\t" \ 71 - "movq %%rax, %[" __rseq_str(rseq_cs) "]\n\t" \ 71 + "movq %%rax, " __rseq_str(rseq_cs) "\n\t" \ 72 72 __rseq_str(label) ":\n\t" 73 73 74 74 #define RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, label) \ 75 75 RSEQ_INJECT_ASM(2) \ 76 - "cmpl %[" __rseq_str(cpu_id) "], %[" __rseq_str(current_cpu_id) "]\n\t" \ 76 + "cmpl %[" __rseq_str(cpu_id) "], " __rseq_str(current_cpu_id) "\n\t" \ 77 77 "jnz " __rseq_str(label) "\n\t" 78 78 79 79 #define RSEQ_ASM_DEFINE_ABORT(label, teardown, abort_label) \ 80 80 ".pushsection __rseq_failure, \"ax\"\n\t" \ 81 - /* Disassembler-friendly signature: nopl <sig>(%rip). */\ 82 - ".byte 0x0f, 0x1f, 0x05\n\t" \ 81 + /* Disassembler-friendly signature: ud1 <sig>(%rip),%edi. */ \ 82 + ".byte 0x0f, 0xb9, 0x3d\n\t" \ 83 83 ".long " __rseq_str(RSEQ_SIG) "\n\t" \ 84 84 __rseq_str(label) ":\n\t" \ 85 85 teardown \ ··· 117 83 118 84 __asm__ __volatile__ goto ( 119 85 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 86 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 87 + #ifdef RSEQ_COMPARE_TWICE 88 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 89 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 90 + #endif 120 91 /* Start rseq by storing table entry pointer into rseq_cs. */ 121 - RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 122 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 92 + RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi])) 93 + RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f) 123 94 RSEQ_INJECT_ASM(3) 124 95 "cmpq %[v], %[expect]\n\t" 125 96 "jnz %l[cmpfail]\n\t" 126 97 RSEQ_INJECT_ASM(4) 127 98 #ifdef RSEQ_COMPARE_TWICE 128 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 99 + RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1]) 129 100 "cmpq %[v], %[expect]\n\t" 130 101 "jnz %l[error2]\n\t" 131 102 #endif ··· 141 102 RSEQ_ASM_DEFINE_ABORT(4, "", abort) 142 103 : /* gcc asm goto does not allow outputs */ 143 104 : [cpu_id] "r" (cpu), 144 - [current_cpu_id] "m" (__rseq_abi.cpu_id), 145 - [rseq_cs] "m" (__rseq_abi.rseq_cs), 105 + [rseq_abi] "r" (&__rseq_abi), 146 106 [v] "m" (*v), 147 107 [expect] "r" (expect), 148 108 [newv] "r" (newv) ··· 178 140 179 141 __asm__ __volatile__ goto ( 180 142 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 143 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 144 + #ifdef RSEQ_COMPARE_TWICE 145 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 146 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 147 + #endif 181 148 /* Start rseq by storing table entry pointer into rseq_cs. */ 182 - RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 183 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 149 + RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi])) 150 + RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f) 184 151 RSEQ_INJECT_ASM(3) 185 152 "movq %[v], %%rbx\n\t" 186 153 "cmpq %%rbx, %[expectnot]\n\t" 187 154 "je %l[cmpfail]\n\t" 188 155 RSEQ_INJECT_ASM(4) 189 156 #ifdef RSEQ_COMPARE_TWICE 190 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 157 + RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1]) 191 158 "movq %[v], %%rbx\n\t" 192 159 "cmpq %%rbx, %[expectnot]\n\t" 193 160 "je %l[error2]\n\t" ··· 207 164 RSEQ_ASM_DEFINE_ABORT(4, "", abort) 208 165 : /* gcc asm goto does not allow outputs */ 209 166 : [cpu_id] "r" (cpu), 210 - [current_cpu_id] "m" (__rseq_abi.cpu_id), 211 - [rseq_cs] "m" (__rseq_abi.rseq_cs), 167 + [rseq_abi] "r" (&__rseq_abi), 212 168 /* final store input */ 213 169 [v] "m" (*v), 214 170 [expectnot] "r" (expectnot), ··· 241 199 242 200 __asm__ __volatile__ goto ( 243 201 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 202 + #ifdef RSEQ_COMPARE_TWICE 203 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 204 + #endif 244 205 /* Start rseq by storing table entry pointer into rseq_cs. */ 245 - RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 246 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 206 + RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi])) 207 + RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f) 247 208 RSEQ_INJECT_ASM(3) 248 209 #ifdef RSEQ_COMPARE_TWICE 249 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 210 + RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1]) 250 211 #endif 251 212 /* final store */ 252 213 "addq %[count], %[v]\n\t" ··· 258 213 RSEQ_ASM_DEFINE_ABORT(4, "", abort) 259 214 : /* gcc asm goto does not allow outputs */ 260 215 : [cpu_id] "r" (cpu), 261 - [current_cpu_id] "m" (__rseq_abi.cpu_id), 262 - [rseq_cs] "m" (__rseq_abi.rseq_cs), 216 + [rseq_abi] "r" (&__rseq_abi), 263 217 /* final store input */ 264 218 [v] "m" (*v), 265 219 [count] "er" (count) ··· 288 244 289 245 __asm__ __volatile__ goto ( 290 246 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 247 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 248 + #ifdef RSEQ_COMPARE_TWICE 249 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 250 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 251 + #endif 291 252 /* Start rseq by storing table entry pointer into rseq_cs. */ 292 - RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 293 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 253 + RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi])) 254 + RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f) 294 255 RSEQ_INJECT_ASM(3) 295 256 "cmpq %[v], %[expect]\n\t" 296 257 "jnz %l[cmpfail]\n\t" 297 258 RSEQ_INJECT_ASM(4) 298 259 #ifdef RSEQ_COMPARE_TWICE 299 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 260 + RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1]) 300 261 "cmpq %[v], %[expect]\n\t" 301 262 "jnz %l[error2]\n\t" 302 263 #endif ··· 315 266 RSEQ_ASM_DEFINE_ABORT(4, "", abort) 316 267 : /* gcc asm goto does not allow outputs */ 317 268 : [cpu_id] "r" (cpu), 318 - [current_cpu_id] "m" (__rseq_abi.cpu_id), 319 - [rseq_cs] "m" (__rseq_abi.rseq_cs), 269 + [rseq_abi] "r" (&__rseq_abi), 320 270 /* try store input */ 321 271 [v2] "m" (*v2), 322 272 [newv2] "r" (newv2), ··· 362 314 363 315 __asm__ __volatile__ goto ( 364 316 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 317 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 318 + #ifdef RSEQ_COMPARE_TWICE 319 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 320 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 321 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error3]) 322 + #endif 365 323 /* Start rseq by storing table entry pointer into rseq_cs. */ 366 - RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 367 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 324 + RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi])) 325 + RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f) 368 326 RSEQ_INJECT_ASM(3) 369 327 "cmpq %[v], %[expect]\n\t" 370 328 "jnz %l[cmpfail]\n\t" ··· 379 325 "jnz %l[cmpfail]\n\t" 380 326 RSEQ_INJECT_ASM(5) 381 327 #ifdef RSEQ_COMPARE_TWICE 382 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 328 + RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1]) 383 329 "cmpq %[v], %[expect]\n\t" 384 330 "jnz %l[error2]\n\t" 385 331 "cmpq %[v2], %[expect2]\n\t" ··· 392 338 RSEQ_ASM_DEFINE_ABORT(4, "", abort) 393 339 : /* gcc asm goto does not allow outputs */ 394 340 : [cpu_id] "r" (cpu), 395 - [current_cpu_id] "m" (__rseq_abi.cpu_id), 396 - [rseq_cs] "m" (__rseq_abi.rseq_cs), 341 + [rseq_abi] "r" (&__rseq_abi), 397 342 /* cmp2 input */ 398 343 [v2] "m" (*v2), 399 344 [expect2] "r" (expect2), ··· 434 381 435 382 __asm__ __volatile__ goto ( 436 383 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 384 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 385 + #ifdef RSEQ_COMPARE_TWICE 386 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 387 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 388 + #endif 437 389 "movq %[src], %[rseq_scratch0]\n\t" 438 390 "movq %[dst], %[rseq_scratch1]\n\t" 439 391 "movq %[len], %[rseq_scratch2]\n\t" 440 392 /* Start rseq by storing table entry pointer into rseq_cs. */ 441 - RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 442 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 393 + RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi])) 394 + RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f) 443 395 RSEQ_INJECT_ASM(3) 444 396 "cmpq %[v], %[expect]\n\t" 445 397 "jnz 5f\n\t" 446 398 RSEQ_INJECT_ASM(4) 447 399 #ifdef RSEQ_COMPARE_TWICE 448 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 6f) 400 + RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 6f) 449 401 "cmpq %[v], %[expect]\n\t" 450 402 "jnz 7f\n\t" 451 403 #endif ··· 498 440 #endif 499 441 : /* gcc asm goto does not allow outputs */ 500 442 : [cpu_id] "r" (cpu), 501 - [current_cpu_id] "m" (__rseq_abi.cpu_id), 502 - [rseq_cs] "m" (__rseq_abi.rseq_cs), 443 + [rseq_abi] "r" (&__rseq_abi), 503 444 /* final store input */ 504 445 [v] "m" (*v), 505 446 [expect] "r" (expect), ··· 577 520 */ 578 521 #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, \ 579 522 start_ip, post_commit_offset, abort_ip) \ 580 - ".pushsection __rseq_table, \"aw\"\n\t" \ 523 + ".pushsection __rseq_cs, \"aw\"\n\t" \ 581 524 ".balign 32\n\t" \ 582 525 __rseq_str(label) ":\n\t" \ 583 526 ".long " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \ 584 527 ".long " __rseq_str(start_ip) ", 0x0, " __rseq_str(post_commit_offset) ", 0x0, " __rseq_str(abort_ip) ", 0x0\n\t" \ 528 + ".popsection\n\t" \ 529 + ".pushsection __rseq_cs_ptr_array, \"aw\"\n\t" \ 530 + ".long " __rseq_str(label) "b, 0x0\n\t" \ 585 531 ".popsection\n\t" 586 532 587 533 #define RSEQ_ASM_DEFINE_TABLE(label, start_ip, post_commit_ip, abort_ip) \ 588 534 __RSEQ_ASM_DEFINE_TABLE(label, 0x0, 0x0, start_ip, \ 589 535 (post_commit_ip - start_ip), abort_ip) 590 536 537 + /* 538 + * Exit points of a rseq critical section consist of all instructions outside 539 + * of the critical section where a critical section can either branch to or 540 + * reach through the normal course of its execution. The abort IP and the 541 + * post-commit IP are already part of the __rseq_cs section and should not be 542 + * explicitly defined as additional exit points. Knowing all exit points is 543 + * useful to assist debuggers stepping over the critical section. 544 + */ 545 + #define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip) \ 546 + ".pushsection __rseq_exit_point_array, \"aw\"\n\t" \ 547 + ".long " __rseq_str(start_ip) ", 0x0, " __rseq_str(exit_ip) ", 0x0\n\t" \ 548 + ".popsection\n\t" 549 + 591 550 #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs) \ 592 551 RSEQ_INJECT_ASM(1) \ 593 - "movl $" __rseq_str(cs_label) ", %[rseq_cs]\n\t" \ 552 + "movl $" __rseq_str(cs_label) ", " __rseq_str(rseq_cs) "\n\t" \ 594 553 __rseq_str(label) ":\n\t" 595 554 596 555 #define RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, label) \ 597 556 RSEQ_INJECT_ASM(2) \ 598 - "cmpl %[" __rseq_str(cpu_id) "], %[" __rseq_str(current_cpu_id) "]\n\t" \ 557 + "cmpl %[" __rseq_str(cpu_id) "], " __rseq_str(current_cpu_id) "\n\t" \ 599 558 "jnz " __rseq_str(label) "\n\t" 600 559 601 560 #define RSEQ_ASM_DEFINE_ABORT(label, teardown, abort_label) \ 602 561 ".pushsection __rseq_failure, \"ax\"\n\t" \ 603 - /* Disassembler-friendly signature: nopl <sig>. */ \ 604 - ".byte 0x0f, 0x1f, 0x05\n\t" \ 562 + /* Disassembler-friendly signature: ud1 <sig>,%edi. */ \ 563 + ".byte 0x0f, 0xb9, 0x3d\n\t" \ 605 564 ".long " __rseq_str(RSEQ_SIG) "\n\t" \ 606 565 __rseq_str(label) ":\n\t" \ 607 566 teardown \ ··· 638 565 639 566 __asm__ __volatile__ goto ( 640 567 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 568 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 569 + #ifdef RSEQ_COMPARE_TWICE 570 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 571 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 572 + #endif 641 573 /* Start rseq by storing table entry pointer into rseq_cs. */ 642 - RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 643 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 574 + RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi])) 575 + RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f) 644 576 RSEQ_INJECT_ASM(3) 645 577 "cmpl %[v], %[expect]\n\t" 646 578 "jnz %l[cmpfail]\n\t" 647 579 RSEQ_INJECT_ASM(4) 648 580 #ifdef RSEQ_COMPARE_TWICE 649 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 581 + RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1]) 650 582 "cmpl %[v], %[expect]\n\t" 651 583 "jnz %l[error2]\n\t" 652 584 #endif ··· 662 584 RSEQ_ASM_DEFINE_ABORT(4, "", abort) 663 585 : /* gcc asm goto does not allow outputs */ 664 586 : [cpu_id] "r" (cpu), 665 - [current_cpu_id] "m" (__rseq_abi.cpu_id), 666 - [rseq_cs] "m" (__rseq_abi.rseq_cs), 587 + [rseq_abi] "r" (&__rseq_abi), 667 588 [v] "m" (*v), 668 589 [expect] "r" (expect), 669 590 [newv] "r" (newv) ··· 699 622 700 623 __asm__ __volatile__ goto ( 701 624 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 625 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 626 + #ifdef RSEQ_COMPARE_TWICE 627 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 628 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 629 + #endif 702 630 /* Start rseq by storing table entry pointer into rseq_cs. */ 703 - RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 704 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 631 + RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi])) 632 + RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f) 705 633 RSEQ_INJECT_ASM(3) 706 634 "movl %[v], %%ebx\n\t" 707 635 "cmpl %%ebx, %[expectnot]\n\t" 708 636 "je %l[cmpfail]\n\t" 709 637 RSEQ_INJECT_ASM(4) 710 638 #ifdef RSEQ_COMPARE_TWICE 711 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 639 + RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1]) 712 640 "movl %[v], %%ebx\n\t" 713 641 "cmpl %%ebx, %[expectnot]\n\t" 714 642 "je %l[error2]\n\t" ··· 728 646 RSEQ_ASM_DEFINE_ABORT(4, "", abort) 729 647 : /* gcc asm goto does not allow outputs */ 730 648 : [cpu_id] "r" (cpu), 731 - [current_cpu_id] "m" (__rseq_abi.cpu_id), 732 - [rseq_cs] "m" (__rseq_abi.rseq_cs), 649 + [rseq_abi] "r" (&__rseq_abi), 733 650 /* final store input */ 734 651 [v] "m" (*v), 735 652 [expectnot] "r" (expectnot), ··· 762 681 763 682 __asm__ __volatile__ goto ( 764 683 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 684 + #ifdef RSEQ_COMPARE_TWICE 685 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 686 + #endif 765 687 /* Start rseq by storing table entry pointer into rseq_cs. */ 766 - RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 767 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 688 + RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi])) 689 + RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f) 768 690 RSEQ_INJECT_ASM(3) 769 691 #ifdef RSEQ_COMPARE_TWICE 770 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 692 + RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1]) 771 693 #endif 772 694 /* final store */ 773 695 "addl %[count], %[v]\n\t" ··· 779 695 RSEQ_ASM_DEFINE_ABORT(4, "", abort) 780 696 : /* gcc asm goto does not allow outputs */ 781 697 : [cpu_id] "r" (cpu), 782 - [current_cpu_id] "m" (__rseq_abi.cpu_id), 783 - [rseq_cs] "m" (__rseq_abi.rseq_cs), 698 + [rseq_abi] "r" (&__rseq_abi), 784 699 /* final store input */ 785 700 [v] "m" (*v), 786 701 [count] "ir" (count) ··· 809 726 810 727 __asm__ __volatile__ goto ( 811 728 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 729 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 730 + #ifdef RSEQ_COMPARE_TWICE 731 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 732 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 733 + #endif 812 734 /* Start rseq by storing table entry pointer into rseq_cs. */ 813 - RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 814 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 735 + RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi])) 736 + RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f) 815 737 RSEQ_INJECT_ASM(3) 816 738 "cmpl %[v], %[expect]\n\t" 817 739 "jnz %l[cmpfail]\n\t" 818 740 RSEQ_INJECT_ASM(4) 819 741 #ifdef RSEQ_COMPARE_TWICE 820 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 742 + RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1]) 821 743 "cmpl %[v], %[expect]\n\t" 822 744 "jnz %l[error2]\n\t" 823 745 #endif ··· 837 749 RSEQ_ASM_DEFINE_ABORT(4, "", abort) 838 750 : /* gcc asm goto does not allow outputs */ 839 751 : [cpu_id] "r" (cpu), 840 - [current_cpu_id] "m" (__rseq_abi.cpu_id), 841 - [rseq_cs] "m" (__rseq_abi.rseq_cs), 752 + [rseq_abi] "r" (&__rseq_abi), 842 753 /* try store input */ 843 754 [v2] "m" (*v2), 844 755 [newv2] "m" (newv2), ··· 875 788 876 789 __asm__ __volatile__ goto ( 877 790 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 791 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 792 + #ifdef RSEQ_COMPARE_TWICE 793 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 794 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 795 + #endif 878 796 /* Start rseq by storing table entry pointer into rseq_cs. */ 879 - RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 880 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 797 + RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi])) 798 + RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f) 881 799 RSEQ_INJECT_ASM(3) 882 800 "movl %[expect], %%eax\n\t" 883 801 "cmpl %[v], %%eax\n\t" 884 802 "jnz %l[cmpfail]\n\t" 885 803 RSEQ_INJECT_ASM(4) 886 804 #ifdef RSEQ_COMPARE_TWICE 887 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 805 + RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1]) 888 806 "movl %[expect], %%eax\n\t" 889 807 "cmpl %[v], %%eax\n\t" 890 808 "jnz %l[error2]\n\t" ··· 905 813 RSEQ_ASM_DEFINE_ABORT(4, "", abort) 906 814 : /* gcc asm goto does not allow outputs */ 907 815 : [cpu_id] "r" (cpu), 908 - [current_cpu_id] "m" (__rseq_abi.cpu_id), 909 - [rseq_cs] "m" (__rseq_abi.rseq_cs), 816 + [rseq_abi] "r" (&__rseq_abi), 910 817 /* try store input */ 911 818 [v2] "m" (*v2), 912 819 [newv2] "r" (newv2), ··· 944 853 945 854 __asm__ __volatile__ goto ( 946 855 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 856 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 857 + #ifdef RSEQ_COMPARE_TWICE 858 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 859 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 860 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error3]) 861 + #endif 947 862 /* Start rseq by storing table entry pointer into rseq_cs. */ 948 - RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 949 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 863 + RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi])) 864 + RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f) 950 865 RSEQ_INJECT_ASM(3) 951 866 "cmpl %[v], %[expect]\n\t" 952 867 "jnz %l[cmpfail]\n\t" ··· 961 864 "jnz %l[cmpfail]\n\t" 962 865 RSEQ_INJECT_ASM(5) 963 866 #ifdef RSEQ_COMPARE_TWICE 964 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 867 + RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1]) 965 868 "cmpl %[v], %[expect]\n\t" 966 869 "jnz %l[error2]\n\t" 967 870 "cmpl %[expect2], %[v2]\n\t" ··· 975 878 RSEQ_ASM_DEFINE_ABORT(4, "", abort) 976 879 : /* gcc asm goto does not allow outputs */ 977 880 : [cpu_id] "r" (cpu), 978 - [current_cpu_id] "m" (__rseq_abi.cpu_id), 979 - [rseq_cs] "m" (__rseq_abi.rseq_cs), 881 + [rseq_abi] "r" (&__rseq_abi), 980 882 /* cmp2 input */ 981 883 [v2] "m" (*v2), 982 884 [expect2] "r" (expect2), ··· 1018 922 1019 923 __asm__ __volatile__ goto ( 1020 924 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 925 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 926 + #ifdef RSEQ_COMPARE_TWICE 927 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 928 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 929 + #endif 1021 930 "movl %[src], %[rseq_scratch0]\n\t" 1022 931 "movl %[dst], %[rseq_scratch1]\n\t" 1023 932 "movl %[len], %[rseq_scratch2]\n\t" 1024 933 /* Start rseq by storing table entry pointer into rseq_cs. */ 1025 - RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 1026 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 934 + RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi])) 935 + RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f) 1027 936 RSEQ_INJECT_ASM(3) 1028 937 "movl %[expect], %%eax\n\t" 1029 938 "cmpl %%eax, %[v]\n\t" 1030 939 "jnz 5f\n\t" 1031 940 RSEQ_INJECT_ASM(4) 1032 941 #ifdef RSEQ_COMPARE_TWICE 1033 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 6f) 942 + RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 6f) 1034 943 "movl %[expect], %%eax\n\t" 1035 944 "cmpl %%eax, %[v]\n\t" 1036 945 "jnz 7f\n\t" ··· 1085 984 #endif 1086 985 : /* gcc asm goto does not allow outputs */ 1087 986 : [cpu_id] "r" (cpu), 1088 - [current_cpu_id] "m" (__rseq_abi.cpu_id), 1089 - [rseq_cs] "m" (__rseq_abi.rseq_cs), 987 + [rseq_abi] "r" (&__rseq_abi), 1090 988 /* final store input */ 1091 989 [v] "m" (*v), 1092 990 [expect] "m" (expect), ··· 1130 1030 1131 1031 __asm__ __volatile__ goto ( 1132 1032 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 1033 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 1034 + #ifdef RSEQ_COMPARE_TWICE 1035 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 1036 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 1037 + #endif 1133 1038 "movl %[src], %[rseq_scratch0]\n\t" 1134 1039 "movl %[dst], %[rseq_scratch1]\n\t" 1135 1040 "movl %[len], %[rseq_scratch2]\n\t" 1136 1041 /* Start rseq by storing table entry pointer into rseq_cs. */ 1137 - RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 1138 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 1042 + RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi])) 1043 + RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f) 1139 1044 RSEQ_INJECT_ASM(3) 1140 1045 "movl %[expect], %%eax\n\t" 1141 1046 "cmpl %%eax, %[v]\n\t" 1142 1047 "jnz 5f\n\t" 1143 1048 RSEQ_INJECT_ASM(4) 1144 1049 #ifdef RSEQ_COMPARE_TWICE 1145 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 6f) 1050 + RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 6f) 1146 1051 "movl %[expect], %%eax\n\t" 1147 1052 "cmpl %%eax, %[v]\n\t" 1148 1053 "jnz 7f\n\t" ··· 1198 1093 #endif 1199 1094 : /* gcc asm goto does not allow outputs */ 1200 1095 : [cpu_id] "r" (cpu), 1201 - [current_cpu_id] "m" (__rseq_abi.cpu_id), 1202 - [rseq_cs] "m" (__rseq_abi.rseq_cs), 1096 + [rseq_abi] "r" (&__rseq_abi), 1203 1097 /* final store input */ 1204 1098 [v] "m" (*v), 1205 1099 [expect] "m" (expect),
+47 -8
tools/testing/selftests/rseq/rseq.c
··· 25 25 #include <syscall.h> 26 26 #include <assert.h> 27 27 #include <signal.h> 28 + #include <limits.h> 28 29 29 30 #include "rseq.h" 30 31 31 32 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 32 33 33 - __attribute__((tls_model("initial-exec"))) __thread 34 - volatile struct rseq __rseq_abi = { 34 + __thread volatile struct rseq __rseq_abi = { 35 35 .cpu_id = RSEQ_CPU_ID_UNINITIALIZED, 36 36 }; 37 37 38 - static __attribute__((tls_model("initial-exec"))) __thread 39 - volatile int refcount; 38 + /* 39 + * Shared with other libraries. This library may take rseq ownership if it is 40 + * still 0 when executing the library constructor. Set to 1 by library 41 + * constructor when handling rseq. Set to 0 in destructor if handling rseq. 42 + */ 43 + int __rseq_handled; 44 + 45 + /* Whether this library have ownership of rseq registration. */ 46 + static int rseq_ownership; 47 + 48 + static __thread volatile uint32_t __rseq_refcount; 40 49 41 50 static void signal_off_save(sigset_t *oldset) 42 51 { ··· 78 69 int rc, ret = 0; 79 70 sigset_t oldset; 80 71 72 + if (!rseq_ownership) 73 + return 0; 81 74 signal_off_save(&oldset); 82 - if (refcount++) 75 + if (__rseq_refcount == UINT_MAX) { 76 + ret = -1; 77 + goto end; 78 + } 79 + if (__rseq_refcount++) 83 80 goto end; 84 81 rc = sys_rseq(&__rseq_abi, sizeof(struct rseq), 0, RSEQ_SIG); 85 82 if (!rc) { ··· 93 78 goto end; 94 79 } 95 80 if (errno != EBUSY) 96 - __rseq_abi.cpu_id = -2; 81 + __rseq_abi.cpu_id = RSEQ_CPU_ID_REGISTRATION_FAILED; 97 82 ret = -1; 98 - refcount--; 83 + __rseq_refcount--; 99 84 end: 100 85 signal_restore(oldset); 101 86 return ret; ··· 106 91 int rc, ret = 0; 107 92 sigset_t oldset; 108 93 94 + if (!rseq_ownership) 95 + return 0; 109 96 signal_off_save(&oldset); 110 - if (--refcount) 97 + if (!__rseq_refcount) { 98 + ret = -1; 99 + goto end; 100 + } 101 + if (--__rseq_refcount) 111 102 goto end; 112 103 rc = sys_rseq(&__rseq_abi, sizeof(struct rseq), 113 104 RSEQ_FLAG_UNREGISTER, RSEQ_SIG); 114 105 if (!rc) 115 106 goto end; 107 + __rseq_refcount = 1; 116 108 ret = -1; 117 109 end: 118 110 signal_restore(oldset); ··· 136 114 abort(); 137 115 } 138 116 return cpu; 117 + } 118 + 119 + void __attribute__((constructor)) rseq_init(void) 120 + { 121 + /* Check whether rseq is handled by another library. */ 122 + if (__rseq_handled) 123 + return; 124 + __rseq_handled = 1; 125 + rseq_ownership = 1; 126 + } 127 + 128 + void __attribute__((destructor)) rseq_fini(void) 129 + { 130 + if (!rseq_ownership) 131 + return; 132 + __rseq_handled = 0; 133 + rseq_ownership = 0; 139 134 }
+1
tools/testing/selftests/rseq/rseq.h
··· 44 44 #endif 45 45 46 46 extern __thread volatile struct rseq __rseq_abi; 47 + extern int __rseq_handled; 47 48 48 49 #define rseq_likely(x) __builtin_expect(!!(x), 1) 49 50 #define rseq_unlikely(x) __builtin_expect(!!(x), 0)
+1
tools/testing/selftests/sigaltstack/sas.c
··· 109 109 int err; 110 110 111 111 ksft_print_header(); 112 + ksft_set_plan(3); 112 113 113 114 sigemptyset(&act.sa_mask); 114 115 act.sa_flags = SA_ONSTACK | SA_SIGINFO;
+1
tools/testing/selftests/sync/sync_test.c
··· 86 86 int err; 87 87 88 88 ksft_print_header(); 89 + ksft_set_plan(3 + 7); 89 90 90 91 sync_api_supported(); 91 92