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

selftests/rseq: s390: Template memory ordering and percpu access mode

Introduce a rseq-s390-bits.h template header which is internally included
to generate the static inline functions covering:

- relaxed and release memory ordering,
- per-cpu-id and per-mm-cid per-cpu data access.

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-17-mathieu.desnoyers@efficios.com

authored by

Mathieu Desnoyers and committed by
Peter Zijlstra
a94af3c5 e61bd94c

+498 -466
+474
tools/testing/selftests/rseq/rseq-s390-bits.h
··· 1 + /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ 2 + 3 + #include "rseq-bits-template.h" 4 + 5 + #if defined(RSEQ_TEMPLATE_MO_RELAXED) && \ 6 + (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID)) 7 + 8 + static inline __attribute__((always_inline)) 9 + int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_storev)(intptr_t *v, intptr_t expect, intptr_t newv, int cpu) 10 + { 11 + RSEQ_INJECT_C(9) 12 + 13 + __asm__ __volatile__ goto ( 14 + RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 15 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 16 + #ifdef RSEQ_COMPARE_TWICE 17 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 18 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 19 + #endif 20 + /* Start rseq by storing table entry pointer into rseq_cs. */ 21 + RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 22 + RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 23 + RSEQ_INJECT_ASM(3) 24 + LONG_CMP " %[expect], %[v]\n\t" 25 + "jnz %l[cmpfail]\n\t" 26 + RSEQ_INJECT_ASM(4) 27 + #ifdef RSEQ_COMPARE_TWICE 28 + RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 29 + LONG_CMP " %[expect], %[v]\n\t" 30 + "jnz %l[error2]\n\t" 31 + #endif 32 + /* final store */ 33 + LONG_S " %[newv], %[v]\n\t" 34 + "2:\n\t" 35 + RSEQ_INJECT_ASM(5) 36 + RSEQ_ASM_DEFINE_ABORT(4, "", abort) 37 + : /* gcc asm goto does not allow outputs */ 38 + : [cpu_id] "r" (cpu), 39 + [current_cpu_id] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD), 40 + [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr), 41 + [v] "m" (*v), 42 + [expect] "r" (expect), 43 + [newv] "r" (newv) 44 + RSEQ_INJECT_INPUT 45 + : "memory", "cc", "r0" 46 + RSEQ_INJECT_CLOBBER 47 + : abort, cmpfail 48 + #ifdef RSEQ_COMPARE_TWICE 49 + , error1, error2 50 + #endif 51 + ); 52 + rseq_after_asm_goto(); 53 + return 0; 54 + abort: 55 + rseq_after_asm_goto(); 56 + RSEQ_INJECT_FAILED 57 + return -1; 58 + cmpfail: 59 + rseq_after_asm_goto(); 60 + return 1; 61 + #ifdef RSEQ_COMPARE_TWICE 62 + error1: 63 + rseq_after_asm_goto(); 64 + rseq_bug("cpu_id comparison failed"); 65 + error2: 66 + rseq_after_asm_goto(); 67 + rseq_bug("expected value comparison failed"); 68 + #endif 69 + } 70 + 71 + /* 72 + * Compare @v against @expectnot. When it does _not_ match, load @v 73 + * into @load, and store the content of *@v + voffp into @v. 74 + */ 75 + static inline __attribute__((always_inline)) 76 + int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpnev_storeoffp_load)(intptr_t *v, intptr_t expectnot, 77 + long voffp, intptr_t *load, int cpu) 78 + { 79 + RSEQ_INJECT_C(9) 80 + 81 + __asm__ __volatile__ goto ( 82 + RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 83 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 84 + #ifdef RSEQ_COMPARE_TWICE 85 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 86 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 87 + #endif 88 + /* Start rseq by storing table entry pointer into rseq_cs. */ 89 + RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 90 + RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 91 + RSEQ_INJECT_ASM(3) 92 + LONG_L " %%r1, %[v]\n\t" 93 + LONG_CMP_R " %%r1, %[expectnot]\n\t" 94 + "je %l[cmpfail]\n\t" 95 + RSEQ_INJECT_ASM(4) 96 + #ifdef RSEQ_COMPARE_TWICE 97 + RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 98 + LONG_L " %%r1, %[v]\n\t" 99 + LONG_CMP_R " %%r1, %[expectnot]\n\t" 100 + "je %l[error2]\n\t" 101 + #endif 102 + LONG_S " %%r1, %[load]\n\t" 103 + LONG_ADD_R " %%r1, %[voffp]\n\t" 104 + LONG_L " %%r1, 0(%%r1)\n\t" 105 + /* final store */ 106 + LONG_S " %%r1, %[v]\n\t" 107 + "2:\n\t" 108 + RSEQ_INJECT_ASM(5) 109 + RSEQ_ASM_DEFINE_ABORT(4, "", abort) 110 + : /* gcc asm goto does not allow outputs */ 111 + : [cpu_id] "r" (cpu), 112 + [current_cpu_id] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD), 113 + [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr), 114 + /* final store input */ 115 + [v] "m" (*v), 116 + [expectnot] "r" (expectnot), 117 + [voffp] "r" (voffp), 118 + [load] "m" (*load) 119 + RSEQ_INJECT_INPUT 120 + : "memory", "cc", "r0", "r1" 121 + RSEQ_INJECT_CLOBBER 122 + : abort, cmpfail 123 + #ifdef RSEQ_COMPARE_TWICE 124 + , error1, error2 125 + #endif 126 + ); 127 + rseq_after_asm_goto(); 128 + return 0; 129 + abort: 130 + rseq_after_asm_goto(); 131 + RSEQ_INJECT_FAILED 132 + return -1; 133 + cmpfail: 134 + rseq_after_asm_goto(); 135 + return 1; 136 + #ifdef RSEQ_COMPARE_TWICE 137 + error1: 138 + rseq_after_asm_goto(); 139 + rseq_bug("cpu_id comparison failed"); 140 + error2: 141 + rseq_after_asm_goto(); 142 + rseq_bug("expected value comparison failed"); 143 + #endif 144 + } 145 + 146 + static inline __attribute__((always_inline)) 147 + int RSEQ_TEMPLATE_IDENTIFIER(rseq_addv)(intptr_t *v, intptr_t count, int cpu) 148 + { 149 + RSEQ_INJECT_C(9) 150 + 151 + __asm__ __volatile__ goto ( 152 + RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 153 + #ifdef RSEQ_COMPARE_TWICE 154 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 155 + #endif 156 + /* Start rseq by storing table entry pointer into rseq_cs. */ 157 + RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 158 + RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 159 + RSEQ_INJECT_ASM(3) 160 + #ifdef RSEQ_COMPARE_TWICE 161 + RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 162 + #endif 163 + LONG_L " %%r0, %[v]\n\t" 164 + LONG_ADD_R " %%r0, %[count]\n\t" 165 + /* final store */ 166 + LONG_S " %%r0, %[v]\n\t" 167 + "2:\n\t" 168 + RSEQ_INJECT_ASM(4) 169 + RSEQ_ASM_DEFINE_ABORT(4, "", abort) 170 + : /* gcc asm goto does not allow outputs */ 171 + : [cpu_id] "r" (cpu), 172 + [current_cpu_id] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD), 173 + [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr), 174 + /* final store input */ 175 + [v] "m" (*v), 176 + [count] "r" (count) 177 + RSEQ_INJECT_INPUT 178 + : "memory", "cc", "r0" 179 + RSEQ_INJECT_CLOBBER 180 + : abort 181 + #ifdef RSEQ_COMPARE_TWICE 182 + , error1 183 + #endif 184 + ); 185 + rseq_after_asm_goto(); 186 + return 0; 187 + abort: 188 + rseq_after_asm_goto(); 189 + RSEQ_INJECT_FAILED 190 + return -1; 191 + #ifdef RSEQ_COMPARE_TWICE 192 + error1: 193 + rseq_after_asm_goto(); 194 + rseq_bug("cpu_id comparison failed"); 195 + #endif 196 + } 197 + 198 + static inline __attribute__((always_inline)) 199 + int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_cmpeqv_storev)(intptr_t *v, intptr_t expect, 200 + intptr_t *v2, intptr_t expect2, 201 + intptr_t newv, int cpu) 202 + { 203 + RSEQ_INJECT_C(9) 204 + 205 + __asm__ __volatile__ goto ( 206 + RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 207 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 208 + #ifdef RSEQ_COMPARE_TWICE 209 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 210 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 211 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error3]) 212 + #endif 213 + /* Start rseq by storing table entry pointer into rseq_cs. */ 214 + RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 215 + RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 216 + RSEQ_INJECT_ASM(3) 217 + LONG_CMP " %[expect], %[v]\n\t" 218 + "jnz %l[cmpfail]\n\t" 219 + RSEQ_INJECT_ASM(4) 220 + LONG_CMP " %[expect2], %[v2]\n\t" 221 + "jnz %l[cmpfail]\n\t" 222 + RSEQ_INJECT_ASM(5) 223 + #ifdef RSEQ_COMPARE_TWICE 224 + RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 225 + LONG_CMP " %[expect], %[v]\n\t" 226 + "jnz %l[error2]\n\t" 227 + LONG_CMP " %[expect2], %[v2]\n\t" 228 + "jnz %l[error3]\n\t" 229 + #endif 230 + /* final store */ 231 + LONG_S " %[newv], %[v]\n\t" 232 + "2:\n\t" 233 + RSEQ_INJECT_ASM(6) 234 + RSEQ_ASM_DEFINE_ABORT(4, "", abort) 235 + : /* gcc asm goto does not allow outputs */ 236 + : [cpu_id] "r" (cpu), 237 + [current_cpu_id] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD), 238 + [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr), 239 + /* cmp2 input */ 240 + [v2] "m" (*v2), 241 + [expect2] "r" (expect2), 242 + /* final store input */ 243 + [v] "m" (*v), 244 + [expect] "r" (expect), 245 + [newv] "r" (newv) 246 + RSEQ_INJECT_INPUT 247 + : "memory", "cc", "r0" 248 + RSEQ_INJECT_CLOBBER 249 + : abort, cmpfail 250 + #ifdef RSEQ_COMPARE_TWICE 251 + , error1, error2, error3 252 + #endif 253 + ); 254 + rseq_after_asm_goto(); 255 + return 0; 256 + abort: 257 + rseq_after_asm_goto(); 258 + RSEQ_INJECT_FAILED 259 + return -1; 260 + cmpfail: 261 + rseq_after_asm_goto(); 262 + return 1; 263 + #ifdef RSEQ_COMPARE_TWICE 264 + error1: 265 + rseq_after_asm_goto(); 266 + rseq_bug("cpu_id comparison failed"); 267 + error2: 268 + rseq_after_asm_goto(); 269 + rseq_bug("1st expected value comparison failed"); 270 + error3: 271 + rseq_after_asm_goto(); 272 + rseq_bug("2nd expected value comparison failed"); 273 + #endif 274 + } 275 + 276 + #endif /* #if defined(RSEQ_TEMPLATE_MO_RELAXED) && 277 + (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID)) */ 278 + 279 + #if (defined(RSEQ_TEMPLATE_MO_RELAXED) || defined(RSEQ_TEMPLATE_MO_RELEASE)) && \ 280 + (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID)) 281 + 282 + /* s390 is TSO. */ 283 + static inline __attribute__((always_inline)) 284 + int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_trystorev_storev)(intptr_t *v, intptr_t expect, 285 + intptr_t *v2, intptr_t newv2, 286 + intptr_t newv, int cpu) 287 + { 288 + RSEQ_INJECT_C(9) 289 + 290 + __asm__ __volatile__ goto ( 291 + RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 292 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 293 + #ifdef RSEQ_COMPARE_TWICE 294 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 295 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 296 + #endif 297 + /* Start rseq by storing table entry pointer into rseq_cs. */ 298 + RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 299 + RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 300 + RSEQ_INJECT_ASM(3) 301 + LONG_CMP " %[expect], %[v]\n\t" 302 + "jnz %l[cmpfail]\n\t" 303 + RSEQ_INJECT_ASM(4) 304 + #ifdef RSEQ_COMPARE_TWICE 305 + RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 306 + LONG_CMP " %[expect], %[v]\n\t" 307 + "jnz %l[error2]\n\t" 308 + #endif 309 + /* try store */ 310 + LONG_S " %[newv2], %[v2]\n\t" 311 + RSEQ_INJECT_ASM(5) 312 + /* final store */ 313 + LONG_S " %[newv], %[v]\n\t" 314 + "2:\n\t" 315 + RSEQ_INJECT_ASM(6) 316 + RSEQ_ASM_DEFINE_ABORT(4, "", abort) 317 + : /* gcc asm goto does not allow outputs */ 318 + : [cpu_id] "r" (cpu), 319 + [current_cpu_id] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD), 320 + [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr), 321 + /* try store input */ 322 + [v2] "m" (*v2), 323 + [newv2] "r" (newv2), 324 + /* final store input */ 325 + [v] "m" (*v), 326 + [expect] "r" (expect), 327 + [newv] "r" (newv) 328 + RSEQ_INJECT_INPUT 329 + : "memory", "cc", "r0" 330 + RSEQ_INJECT_CLOBBER 331 + : abort, cmpfail 332 + #ifdef RSEQ_COMPARE_TWICE 333 + , error1, error2 334 + #endif 335 + ); 336 + rseq_after_asm_goto(); 337 + return 0; 338 + abort: 339 + rseq_after_asm_goto(); 340 + RSEQ_INJECT_FAILED 341 + return -1; 342 + cmpfail: 343 + rseq_after_asm_goto(); 344 + return 1; 345 + #ifdef RSEQ_COMPARE_TWICE 346 + error1: 347 + rseq_after_asm_goto(); 348 + rseq_bug("cpu_id comparison failed"); 349 + error2: 350 + rseq_after_asm_goto(); 351 + rseq_bug("expected value comparison failed"); 352 + #endif 353 + } 354 + 355 + /* s390 is TSO. */ 356 + static inline __attribute__((always_inline)) 357 + int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_trymemcpy_storev)(intptr_t *v, intptr_t expect, 358 + void *dst, void *src, size_t len, 359 + intptr_t newv, int cpu) 360 + { 361 + uint64_t rseq_scratch[3]; 362 + 363 + RSEQ_INJECT_C(9) 364 + 365 + __asm__ __volatile__ goto ( 366 + RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 367 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 368 + #ifdef RSEQ_COMPARE_TWICE 369 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 370 + RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 371 + #endif 372 + LONG_S " %[src], %[rseq_scratch0]\n\t" 373 + LONG_S " %[dst], %[rseq_scratch1]\n\t" 374 + LONG_S " %[len], %[rseq_scratch2]\n\t" 375 + /* Start rseq by storing table entry pointer into rseq_cs. */ 376 + RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 377 + RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 378 + RSEQ_INJECT_ASM(3) 379 + LONG_CMP " %[expect], %[v]\n\t" 380 + "jnz 5f\n\t" 381 + RSEQ_INJECT_ASM(4) 382 + #ifdef RSEQ_COMPARE_TWICE 383 + RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 6f) 384 + LONG_CMP " %[expect], %[v]\n\t" 385 + "jnz 7f\n\t" 386 + #endif 387 + /* try memcpy */ 388 + LONG_LT_R " %[len], %[len]\n\t" 389 + "jz 333f\n\t" 390 + "222:\n\t" 391 + "ic %%r0,0(%[src])\n\t" 392 + "stc %%r0,0(%[dst])\n\t" 393 + LONG_ADDI " %[src], 1\n\t" 394 + LONG_ADDI " %[dst], 1\n\t" 395 + LONG_ADDI " %[len], -1\n\t" 396 + "jnz 222b\n\t" 397 + "333:\n\t" 398 + RSEQ_INJECT_ASM(5) 399 + /* final store */ 400 + LONG_S " %[newv], %[v]\n\t" 401 + "2:\n\t" 402 + RSEQ_INJECT_ASM(6) 403 + /* teardown */ 404 + LONG_L " %[len], %[rseq_scratch2]\n\t" 405 + LONG_L " %[dst], %[rseq_scratch1]\n\t" 406 + LONG_L " %[src], %[rseq_scratch0]\n\t" 407 + RSEQ_ASM_DEFINE_ABORT(4, 408 + LONG_L " %[len], %[rseq_scratch2]\n\t" 409 + LONG_L " %[dst], %[rseq_scratch1]\n\t" 410 + LONG_L " %[src], %[rseq_scratch0]\n\t", 411 + abort) 412 + RSEQ_ASM_DEFINE_CMPFAIL(5, 413 + LONG_L " %[len], %[rseq_scratch2]\n\t" 414 + LONG_L " %[dst], %[rseq_scratch1]\n\t" 415 + LONG_L " %[src], %[rseq_scratch0]\n\t", 416 + cmpfail) 417 + #ifdef RSEQ_COMPARE_TWICE 418 + RSEQ_ASM_DEFINE_CMPFAIL(6, 419 + LONG_L " %[len], %[rseq_scratch2]\n\t" 420 + LONG_L " %[dst], %[rseq_scratch1]\n\t" 421 + LONG_L " %[src], %[rseq_scratch0]\n\t", 422 + error1) 423 + RSEQ_ASM_DEFINE_CMPFAIL(7, 424 + LONG_L " %[len], %[rseq_scratch2]\n\t" 425 + LONG_L " %[dst], %[rseq_scratch1]\n\t" 426 + LONG_L " %[src], %[rseq_scratch0]\n\t", 427 + error2) 428 + #endif 429 + : /* gcc asm goto does not allow outputs */ 430 + : [cpu_id] "r" (cpu), 431 + [current_cpu_id] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD), 432 + [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr), 433 + /* final store input */ 434 + [v] "m" (*v), 435 + [expect] "r" (expect), 436 + [newv] "r" (newv), 437 + /* try memcpy input */ 438 + [dst] "r" (dst), 439 + [src] "r" (src), 440 + [len] "r" (len), 441 + [rseq_scratch0] "m" (rseq_scratch[0]), 442 + [rseq_scratch1] "m" (rseq_scratch[1]), 443 + [rseq_scratch2] "m" (rseq_scratch[2]) 444 + RSEQ_INJECT_INPUT 445 + : "memory", "cc", "r0" 446 + RSEQ_INJECT_CLOBBER 447 + : abort, cmpfail 448 + #ifdef RSEQ_COMPARE_TWICE 449 + , error1, error2 450 + #endif 451 + ); 452 + rseq_after_asm_goto(); 453 + return 0; 454 + abort: 455 + rseq_after_asm_goto(); 456 + RSEQ_INJECT_FAILED 457 + return -1; 458 + cmpfail: 459 + rseq_after_asm_goto(); 460 + return 1; 461 + #ifdef RSEQ_COMPARE_TWICE 462 + error1: 463 + rseq_after_asm_goto(); 464 + rseq_bug("cpu_id comparison failed"); 465 + error2: 466 + rseq_after_asm_goto(); 467 + rseq_bug("expected value comparison failed"); 468 + #endif 469 + } 470 + 471 + #endif /* #if (defined(RSEQ_TEMPLATE_MO_RELAXED) || defined(RSEQ_TEMPLATE_MO_RELEASE)) && 472 + (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID)) */ 473 + 474 + #include "rseq-bits-reset.h"
+24 -466
tools/testing/selftests/rseq/rseq-s390.h
··· 130 130 "jg %l[" __rseq_str(cmpfail_label) "]\n\t" \ 131 131 ".popsection\n\t" 132 132 133 - static inline __attribute__((always_inline)) 134 - int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu) 135 - { 136 - RSEQ_INJECT_C(9) 133 + /* Per-cpu-id indexing. */ 137 134 138 - __asm__ __volatile__ goto ( 139 - RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 140 - RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 141 - #ifdef RSEQ_COMPARE_TWICE 142 - RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 143 - RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 144 - #endif 145 - /* Start rseq by storing table entry pointer into rseq_cs. */ 146 - RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 147 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 148 - RSEQ_INJECT_ASM(3) 149 - LONG_CMP " %[expect], %[v]\n\t" 150 - "jnz %l[cmpfail]\n\t" 151 - RSEQ_INJECT_ASM(4) 152 - #ifdef RSEQ_COMPARE_TWICE 153 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 154 - LONG_CMP " %[expect], %[v]\n\t" 155 - "jnz %l[error2]\n\t" 156 - #endif 157 - /* final store */ 158 - LONG_S " %[newv], %[v]\n\t" 159 - "2:\n\t" 160 - RSEQ_INJECT_ASM(5) 161 - RSEQ_ASM_DEFINE_ABORT(4, "", abort) 162 - : /* gcc asm goto does not allow outputs */ 163 - : [cpu_id] "r" (cpu), 164 - [current_cpu_id] "m" (rseq_get_abi()->cpu_id), 165 - [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr), 166 - [v] "m" (*v), 167 - [expect] "r" (expect), 168 - [newv] "r" (newv) 169 - RSEQ_INJECT_INPUT 170 - : "memory", "cc", "r0" 171 - RSEQ_INJECT_CLOBBER 172 - : abort, cmpfail 173 - #ifdef RSEQ_COMPARE_TWICE 174 - , error1, error2 175 - #endif 176 - ); 177 - rseq_after_asm_goto(); 178 - return 0; 179 - abort: 180 - rseq_after_asm_goto(); 181 - RSEQ_INJECT_FAILED 182 - return -1; 183 - cmpfail: 184 - rseq_after_asm_goto(); 185 - return 1; 186 - #ifdef RSEQ_COMPARE_TWICE 187 - error1: 188 - rseq_after_asm_goto(); 189 - rseq_bug("cpu_id comparison failed"); 190 - error2: 191 - rseq_after_asm_goto(); 192 - rseq_bug("expected value comparison failed"); 193 - #endif 194 - } 135 + #define RSEQ_TEMPLATE_CPU_ID 136 + #define RSEQ_TEMPLATE_MO_RELAXED 137 + #include "rseq-s390-bits.h" 138 + #undef RSEQ_TEMPLATE_MO_RELAXED 195 139 196 - /* 197 - * Compare @v against @expectnot. When it does _not_ match, load @v 198 - * into @load, and store the content of *@v + voffp into @v. 199 - */ 200 - static inline __attribute__((always_inline)) 201 - int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot, 202 - long voffp, intptr_t *load, int cpu) 203 - { 204 - RSEQ_INJECT_C(9) 140 + #define RSEQ_TEMPLATE_MO_RELEASE 141 + #include "rseq-s390-bits.h" 142 + #undef RSEQ_TEMPLATE_MO_RELEASE 143 + #undef RSEQ_TEMPLATE_CPU_ID 205 144 206 - __asm__ __volatile__ goto ( 207 - RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 208 - RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 209 - #ifdef RSEQ_COMPARE_TWICE 210 - RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 211 - RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 212 - #endif 213 - /* Start rseq by storing table entry pointer into rseq_cs. */ 214 - RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 215 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 216 - RSEQ_INJECT_ASM(3) 217 - LONG_L " %%r1, %[v]\n\t" 218 - LONG_CMP_R " %%r1, %[expectnot]\n\t" 219 - "je %l[cmpfail]\n\t" 220 - RSEQ_INJECT_ASM(4) 221 - #ifdef RSEQ_COMPARE_TWICE 222 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 223 - LONG_L " %%r1, %[v]\n\t" 224 - LONG_CMP_R " %%r1, %[expectnot]\n\t" 225 - "je %l[error2]\n\t" 226 - #endif 227 - LONG_S " %%r1, %[load]\n\t" 228 - LONG_ADD_R " %%r1, %[voffp]\n\t" 229 - LONG_L " %%r1, 0(%%r1)\n\t" 230 - /* final store */ 231 - LONG_S " %%r1, %[v]\n\t" 232 - "2:\n\t" 233 - RSEQ_INJECT_ASM(5) 234 - RSEQ_ASM_DEFINE_ABORT(4, "", abort) 235 - : /* gcc asm goto does not allow outputs */ 236 - : [cpu_id] "r" (cpu), 237 - [current_cpu_id] "m" (rseq_get_abi()->cpu_id), 238 - [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr), 239 - /* final store input */ 240 - [v] "m" (*v), 241 - [expectnot] "r" (expectnot), 242 - [voffp] "r" (voffp), 243 - [load] "m" (*load) 244 - RSEQ_INJECT_INPUT 245 - : "memory", "cc", "r0", "r1" 246 - RSEQ_INJECT_CLOBBER 247 - : abort, cmpfail 248 - #ifdef RSEQ_COMPARE_TWICE 249 - , error1, error2 250 - #endif 251 - ); 252 - rseq_after_asm_goto(); 253 - return 0; 254 - abort: 255 - rseq_after_asm_goto(); 256 - RSEQ_INJECT_FAILED 257 - return -1; 258 - cmpfail: 259 - rseq_after_asm_goto(); 260 - return 1; 261 - #ifdef RSEQ_COMPARE_TWICE 262 - error1: 263 - rseq_after_asm_goto(); 264 - rseq_bug("cpu_id comparison failed"); 265 - error2: 266 - rseq_after_asm_goto(); 267 - rseq_bug("expected value comparison failed"); 268 - #endif 269 - } 145 + /* Per-mm-cid indexing. */ 270 146 271 - static inline __attribute__((always_inline)) 272 - int rseq_addv(intptr_t *v, intptr_t count, int cpu) 273 - { 274 - RSEQ_INJECT_C(9) 147 + #define RSEQ_TEMPLATE_MM_CID 148 + #define RSEQ_TEMPLATE_MO_RELAXED 149 + #include "rseq-s390-bits.h" 150 + #undef RSEQ_TEMPLATE_MO_RELAXED 275 151 276 - __asm__ __volatile__ goto ( 277 - RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 278 - #ifdef RSEQ_COMPARE_TWICE 279 - RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 280 - #endif 281 - /* Start rseq by storing table entry pointer into rseq_cs. */ 282 - RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 283 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 284 - RSEQ_INJECT_ASM(3) 285 - #ifdef RSEQ_COMPARE_TWICE 286 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 287 - #endif 288 - LONG_L " %%r0, %[v]\n\t" 289 - LONG_ADD_R " %%r0, %[count]\n\t" 290 - /* final store */ 291 - LONG_S " %%r0, %[v]\n\t" 292 - "2:\n\t" 293 - RSEQ_INJECT_ASM(4) 294 - RSEQ_ASM_DEFINE_ABORT(4, "", abort) 295 - : /* gcc asm goto does not allow outputs */ 296 - : [cpu_id] "r" (cpu), 297 - [current_cpu_id] "m" (rseq_get_abi()->cpu_id), 298 - [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr), 299 - /* final store input */ 300 - [v] "m" (*v), 301 - [count] "r" (count) 302 - RSEQ_INJECT_INPUT 303 - : "memory", "cc", "r0" 304 - RSEQ_INJECT_CLOBBER 305 - : abort 306 - #ifdef RSEQ_COMPARE_TWICE 307 - , error1 308 - #endif 309 - ); 310 - rseq_after_asm_goto(); 311 - return 0; 312 - abort: 313 - rseq_after_asm_goto(); 314 - RSEQ_INJECT_FAILED 315 - return -1; 316 - #ifdef RSEQ_COMPARE_TWICE 317 - error1: 318 - rseq_after_asm_goto(); 319 - rseq_bug("cpu_id comparison failed"); 320 - #endif 321 - } 152 + #define RSEQ_TEMPLATE_MO_RELEASE 153 + #include "rseq-s390-bits.h" 154 + #undef RSEQ_TEMPLATE_MO_RELEASE 155 + #undef RSEQ_TEMPLATE_MM_CID 322 156 323 - static inline __attribute__((always_inline)) 324 - int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect, 325 - intptr_t *v2, intptr_t newv2, 326 - intptr_t newv, int cpu) 327 - { 328 - RSEQ_INJECT_C(9) 157 + /* APIs which are not based on cpu ids. */ 329 158 330 - __asm__ __volatile__ goto ( 331 - RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 332 - RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 333 - #ifdef RSEQ_COMPARE_TWICE 334 - RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 335 - RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 336 - #endif 337 - /* Start rseq by storing table entry pointer into rseq_cs. */ 338 - RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 339 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 340 - RSEQ_INJECT_ASM(3) 341 - LONG_CMP " %[expect], %[v]\n\t" 342 - "jnz %l[cmpfail]\n\t" 343 - RSEQ_INJECT_ASM(4) 344 - #ifdef RSEQ_COMPARE_TWICE 345 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 346 - LONG_CMP " %[expect], %[v]\n\t" 347 - "jnz %l[error2]\n\t" 348 - #endif 349 - /* try store */ 350 - LONG_S " %[newv2], %[v2]\n\t" 351 - RSEQ_INJECT_ASM(5) 352 - /* final store */ 353 - LONG_S " %[newv], %[v]\n\t" 354 - "2:\n\t" 355 - RSEQ_INJECT_ASM(6) 356 - RSEQ_ASM_DEFINE_ABORT(4, "", abort) 357 - : /* gcc asm goto does not allow outputs */ 358 - : [cpu_id] "r" (cpu), 359 - [current_cpu_id] "m" (rseq_get_abi()->cpu_id), 360 - [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr), 361 - /* try store input */ 362 - [v2] "m" (*v2), 363 - [newv2] "r" (newv2), 364 - /* final store input */ 365 - [v] "m" (*v), 366 - [expect] "r" (expect), 367 - [newv] "r" (newv) 368 - RSEQ_INJECT_INPUT 369 - : "memory", "cc", "r0" 370 - RSEQ_INJECT_CLOBBER 371 - : abort, cmpfail 372 - #ifdef RSEQ_COMPARE_TWICE 373 - , error1, error2 374 - #endif 375 - ); 376 - rseq_after_asm_goto(); 377 - return 0; 378 - abort: 379 - rseq_after_asm_goto(); 380 - RSEQ_INJECT_FAILED 381 - return -1; 382 - cmpfail: 383 - rseq_after_asm_goto(); 384 - return 1; 385 - #ifdef RSEQ_COMPARE_TWICE 386 - error1: 387 - rseq_after_asm_goto(); 388 - rseq_bug("cpu_id comparison failed"); 389 - error2: 390 - rseq_after_asm_goto(); 391 - rseq_bug("expected value comparison failed"); 392 - #endif 393 - } 394 - 395 - /* s390 is TSO. */ 396 - static inline __attribute__((always_inline)) 397 - int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect, 398 - intptr_t *v2, intptr_t newv2, 399 - intptr_t newv, int cpu) 400 - { 401 - return rseq_cmpeqv_trystorev_storev(v, expect, v2, newv2, newv, cpu); 402 - } 403 - 404 - static inline __attribute__((always_inline)) 405 - int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect, 406 - intptr_t *v2, intptr_t expect2, 407 - intptr_t newv, int cpu) 408 - { 409 - RSEQ_INJECT_C(9) 410 - 411 - __asm__ __volatile__ goto ( 412 - RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 413 - RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 414 - #ifdef RSEQ_COMPARE_TWICE 415 - RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 416 - RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 417 - RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error3]) 418 - #endif 419 - /* Start rseq by storing table entry pointer into rseq_cs. */ 420 - RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 421 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 422 - RSEQ_INJECT_ASM(3) 423 - LONG_CMP " %[expect], %[v]\n\t" 424 - "jnz %l[cmpfail]\n\t" 425 - RSEQ_INJECT_ASM(4) 426 - LONG_CMP " %[expect2], %[v2]\n\t" 427 - "jnz %l[cmpfail]\n\t" 428 - RSEQ_INJECT_ASM(5) 429 - #ifdef RSEQ_COMPARE_TWICE 430 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 431 - LONG_CMP " %[expect], %[v]\n\t" 432 - "jnz %l[error2]\n\t" 433 - LONG_CMP " %[expect2], %[v2]\n\t" 434 - "jnz %l[error3]\n\t" 435 - #endif 436 - /* final store */ 437 - LONG_S " %[newv], %[v]\n\t" 438 - "2:\n\t" 439 - RSEQ_INJECT_ASM(6) 440 - RSEQ_ASM_DEFINE_ABORT(4, "", abort) 441 - : /* gcc asm goto does not allow outputs */ 442 - : [cpu_id] "r" (cpu), 443 - [current_cpu_id] "m" (rseq_get_abi()->cpu_id), 444 - [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr), 445 - /* cmp2 input */ 446 - [v2] "m" (*v2), 447 - [expect2] "r" (expect2), 448 - /* final store input */ 449 - [v] "m" (*v), 450 - [expect] "r" (expect), 451 - [newv] "r" (newv) 452 - RSEQ_INJECT_INPUT 453 - : "memory", "cc", "r0" 454 - RSEQ_INJECT_CLOBBER 455 - : abort, cmpfail 456 - #ifdef RSEQ_COMPARE_TWICE 457 - , error1, error2, error3 458 - #endif 459 - ); 460 - rseq_after_asm_goto(); 461 - return 0; 462 - abort: 463 - rseq_after_asm_goto(); 464 - RSEQ_INJECT_FAILED 465 - return -1; 466 - cmpfail: 467 - rseq_after_asm_goto(); 468 - return 1; 469 - #ifdef RSEQ_COMPARE_TWICE 470 - error1: 471 - rseq_after_asm_goto(); 472 - rseq_bug("cpu_id comparison failed"); 473 - error2: 474 - rseq_after_asm_goto(); 475 - rseq_bug("1st expected value comparison failed"); 476 - error3: 477 - rseq_after_asm_goto(); 478 - rseq_bug("2nd expected value comparison failed"); 479 - #endif 480 - } 481 - 482 - static inline __attribute__((always_inline)) 483 - int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect, 484 - void *dst, void *src, size_t len, 485 - intptr_t newv, int cpu) 486 - { 487 - uint64_t rseq_scratch[3]; 488 - 489 - RSEQ_INJECT_C(9) 490 - 491 - __asm__ __volatile__ goto ( 492 - RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */ 493 - RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail]) 494 - #ifdef RSEQ_COMPARE_TWICE 495 - RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1]) 496 - RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2]) 497 - #endif 498 - LONG_S " %[src], %[rseq_scratch0]\n\t" 499 - LONG_S " %[dst], %[rseq_scratch1]\n\t" 500 - LONG_S " %[len], %[rseq_scratch2]\n\t" 501 - /* Start rseq by storing table entry pointer into rseq_cs. */ 502 - RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs) 503 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 504 - RSEQ_INJECT_ASM(3) 505 - LONG_CMP " %[expect], %[v]\n\t" 506 - "jnz 5f\n\t" 507 - RSEQ_INJECT_ASM(4) 508 - #ifdef RSEQ_COMPARE_TWICE 509 - RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 6f) 510 - LONG_CMP " %[expect], %[v]\n\t" 511 - "jnz 7f\n\t" 512 - #endif 513 - /* try memcpy */ 514 - LONG_LT_R " %[len], %[len]\n\t" 515 - "jz 333f\n\t" 516 - "222:\n\t" 517 - "ic %%r0,0(%[src])\n\t" 518 - "stc %%r0,0(%[dst])\n\t" 519 - LONG_ADDI " %[src], 1\n\t" 520 - LONG_ADDI " %[dst], 1\n\t" 521 - LONG_ADDI " %[len], -1\n\t" 522 - "jnz 222b\n\t" 523 - "333:\n\t" 524 - RSEQ_INJECT_ASM(5) 525 - /* final store */ 526 - LONG_S " %[newv], %[v]\n\t" 527 - "2:\n\t" 528 - RSEQ_INJECT_ASM(6) 529 - /* teardown */ 530 - LONG_L " %[len], %[rseq_scratch2]\n\t" 531 - LONG_L " %[dst], %[rseq_scratch1]\n\t" 532 - LONG_L " %[src], %[rseq_scratch0]\n\t" 533 - RSEQ_ASM_DEFINE_ABORT(4, 534 - LONG_L " %[len], %[rseq_scratch2]\n\t" 535 - LONG_L " %[dst], %[rseq_scratch1]\n\t" 536 - LONG_L " %[src], %[rseq_scratch0]\n\t", 537 - abort) 538 - RSEQ_ASM_DEFINE_CMPFAIL(5, 539 - LONG_L " %[len], %[rseq_scratch2]\n\t" 540 - LONG_L " %[dst], %[rseq_scratch1]\n\t" 541 - LONG_L " %[src], %[rseq_scratch0]\n\t", 542 - cmpfail) 543 - #ifdef RSEQ_COMPARE_TWICE 544 - RSEQ_ASM_DEFINE_CMPFAIL(6, 545 - LONG_L " %[len], %[rseq_scratch2]\n\t" 546 - LONG_L " %[dst], %[rseq_scratch1]\n\t" 547 - LONG_L " %[src], %[rseq_scratch0]\n\t", 548 - error1) 549 - RSEQ_ASM_DEFINE_CMPFAIL(7, 550 - LONG_L " %[len], %[rseq_scratch2]\n\t" 551 - LONG_L " %[dst], %[rseq_scratch1]\n\t" 552 - LONG_L " %[src], %[rseq_scratch0]\n\t", 553 - error2) 554 - #endif 555 - : /* gcc asm goto does not allow outputs */ 556 - : [cpu_id] "r" (cpu), 557 - [current_cpu_id] "m" (rseq_get_abi()->cpu_id), 558 - [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr), 559 - /* final store input */ 560 - [v] "m" (*v), 561 - [expect] "r" (expect), 562 - [newv] "r" (newv), 563 - /* try memcpy input */ 564 - [dst] "r" (dst), 565 - [src] "r" (src), 566 - [len] "r" (len), 567 - [rseq_scratch0] "m" (rseq_scratch[0]), 568 - [rseq_scratch1] "m" (rseq_scratch[1]), 569 - [rseq_scratch2] "m" (rseq_scratch[2]) 570 - RSEQ_INJECT_INPUT 571 - : "memory", "cc", "r0" 572 - RSEQ_INJECT_CLOBBER 573 - : abort, cmpfail 574 - #ifdef RSEQ_COMPARE_TWICE 575 - , error1, error2 576 - #endif 577 - ); 578 - rseq_after_asm_goto(); 579 - return 0; 580 - abort: 581 - rseq_after_asm_goto(); 582 - RSEQ_INJECT_FAILED 583 - return -1; 584 - cmpfail: 585 - rseq_after_asm_goto(); 586 - return 1; 587 - #ifdef RSEQ_COMPARE_TWICE 588 - error1: 589 - rseq_after_asm_goto(); 590 - rseq_bug("cpu_id comparison failed"); 591 - error2: 592 - rseq_after_asm_goto(); 593 - rseq_bug("expected value comparison failed"); 594 - #endif 595 - } 596 - 597 - /* s390 is TSO. */ 598 - static inline __attribute__((always_inline)) 599 - int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect, 600 - void *dst, void *src, size_t len, 601 - intptr_t newv, int cpu) 602 - { 603 - return rseq_cmpeqv_trymemcpy_storev(v, expect, dst, src, len, 604 - newv, cpu); 605 - } 159 + #define RSEQ_TEMPLATE_CPU_ID_NONE 160 + #define RSEQ_TEMPLATE_MO_RELAXED 161 + #include "rseq-s390-bits.h" 162 + #undef RSEQ_TEMPLATE_MO_RELAXED 163 + #undef RSEQ_TEMPLATE_CPU_ID_NONE