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

selftests/rseq: Implement basic percpu ops mm_cid test

Adapt to the rseq.h API changes introduced by commits
"selftests/rseq: <arch>: Template memory ordering and percpu access mode".

Build a new basic_percpu_ops_mm_cid_test to test the new "mm_cid" rseq
field.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/20221122203932.231377-19-mathieu.desnoyers@efficios.com

authored by

Mathieu Desnoyers and committed by
Peter Zijlstra
cead7206 171586a6

+44 -8
+1
tools/testing/selftests/rseq/.gitignore
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 basic_percpu_ops_test 3 + basic_percpu_ops_mm_cid_test 3 4 basic_test 4 5 basic_rseq_op_test 5 6 param_test
+4 -1
tools/testing/selftests/rseq/Makefile
··· 12 12 # still track changes to header files and depend on shared object. 13 13 OVERRIDE_TARGETS = 1 14 14 15 - TEST_GEN_PROGS = basic_test basic_percpu_ops_test param_test \ 15 + TEST_GEN_PROGS = basic_test basic_percpu_ops_test basic_percpu_ops_mm_cid_test param_test \ 16 16 param_test_benchmark param_test_compare_twice 17 17 18 18 TEST_GEN_PROGS_EXTENDED = librseq.so ··· 28 28 29 29 $(OUTPUT)/%: %.c $(TEST_GEN_PROGS_EXTENDED) rseq.h rseq-*.h 30 30 $(CC) $(CFLAGS) $< $(LDLIBS) -lrseq -o $@ 31 + 32 + $(OUTPUT)/basic_percpu_ops_mm_cid_test: basic_percpu_ops_test.c $(TEST_GEN_PROGS_EXTENDED) rseq.h rseq-*.h 33 + $(CC) $(CFLAGS) -DBUILDOPT_RSEQ_PERCPU_MM_CID_ID $< $(LDLIBS) -lrseq -o $@ 31 34 32 35 $(OUTPUT)/param_test_benchmark: param_test.c $(TEST_GEN_PROGS_EXTENDED) \ 33 36 rseq.h rseq-*.h
+39 -7
tools/testing/selftests/rseq/basic_percpu_ops_test.c
··· 12 12 #include "../kselftest.h" 13 13 #include "rseq.h" 14 14 15 + #ifdef BUILDOPT_RSEQ_PERCPU_MM_CID 16 + # define RSEQ_PERCPU RSEQ_PERCPU_MM_CID 17 + static 18 + int get_current_cpu_id(void) 19 + { 20 + return rseq_current_mm_cid(); 21 + } 22 + static 23 + bool rseq_validate_cpu_id(void) 24 + { 25 + return rseq_mm_cid_available(); 26 + } 27 + #else 28 + # define RSEQ_PERCPU RSEQ_PERCPU_CPU_ID 29 + static 30 + int get_current_cpu_id(void) 31 + { 32 + return rseq_cpu_start(); 33 + } 34 + static 35 + bool rseq_validate_cpu_id(void) 36 + { 37 + return rseq_current_cpu_raw() >= 0; 38 + } 39 + #endif 40 + 15 41 struct percpu_lock_entry { 16 42 intptr_t v; 17 43 } __attribute__((aligned(128))); ··· 77 51 for (;;) { 78 52 int ret; 79 53 80 - cpu = rseq_cpu_start(); 81 - ret = rseq_cmpeqv_storev(&lock->c[cpu].v, 82 - 0, 1, cpu); 54 + cpu = get_current_cpu_id(); 55 + ret = rseq_cmpeqv_storev(RSEQ_MO_RELAXED, RSEQ_PERCPU, 56 + &lock->c[cpu].v, 0, 1, cpu); 83 57 if (rseq_likely(!ret)) 84 58 break; 85 59 /* Retry if comparison fails or rseq aborts. */ ··· 167 141 intptr_t *targetptr, newval, expect; 168 142 int ret; 169 143 170 - cpu = rseq_cpu_start(); 144 + cpu = get_current_cpu_id(); 171 145 /* Load list->c[cpu].head with single-copy atomicity. */ 172 146 expect = (intptr_t)RSEQ_READ_ONCE(list->c[cpu].head); 173 147 newval = (intptr_t)node; 174 148 targetptr = (intptr_t *)&list->c[cpu].head; 175 149 node->next = (struct percpu_list_node *)expect; 176 - ret = rseq_cmpeqv_storev(targetptr, expect, newval, cpu); 150 + ret = rseq_cmpeqv_storev(RSEQ_MO_RELAXED, RSEQ_PERCPU, 151 + targetptr, expect, newval, cpu); 177 152 if (rseq_likely(!ret)) 178 153 break; 179 154 /* Retry if comparison fails or rseq aborts. */ ··· 197 170 long offset; 198 171 int ret, cpu; 199 172 200 - cpu = rseq_cpu_start(); 173 + cpu = get_current_cpu_id(); 201 174 targetptr = (intptr_t *)&list->c[cpu].head; 202 175 expectnot = (intptr_t)NULL; 203 176 offset = offsetof(struct percpu_list_node, next); 204 177 load = (intptr_t *)&head; 205 - ret = rseq_cmpnev_storeoffp_load(targetptr, expectnot, 178 + ret = rseq_cmpnev_storeoffp_load(RSEQ_MO_RELAXED, RSEQ_PERCPU, 179 + targetptr, expectnot, 206 180 offset, load, cpu); 207 181 if (rseq_likely(!ret)) { 208 182 if (_cpu) ··· 321 293 if (rseq_register_current_thread()) { 322 294 fprintf(stderr, "Error: rseq_register_current_thread(...) failed(%d): %s\n", 323 295 errno, strerror(errno)); 296 + goto error; 297 + } 298 + if (!rseq_validate_cpu_id()) { 299 + fprintf(stderr, "Error: cpu id getter unavailable\n"); 324 300 goto error; 325 301 } 326 302 printf("spinlock\n");