1*ea1413e5SStafford Horne /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ 2*ea1413e5SStafford Horne 3*ea1413e5SStafford Horne #include "rseq-bits-template.h" 4*ea1413e5SStafford Horne 5*ea1413e5SStafford Horne #if defined(RSEQ_TEMPLATE_MO_RELAXED) && \ 6*ea1413e5SStafford Horne (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID)) 7*ea1413e5SStafford Horne 8*ea1413e5SStafford Horne static inline __always_inline 9*ea1413e5SStafford Horne int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_storev)(intptr_t *v, intptr_t expect, intptr_t newv, 10*ea1413e5SStafford Horne int cpu) 11*ea1413e5SStafford Horne { 12*ea1413e5SStafford Horne RSEQ_INJECT_C(9) 13*ea1413e5SStafford Horne 14*ea1413e5SStafford Horne __asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f) 15*ea1413e5SStafford Horne RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[cmpfail]") 16*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE 17*ea1413e5SStafford Horne RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]") 18*ea1413e5SStafford Horne RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error2]") 19*ea1413e5SStafford Horne #endif 20*ea1413e5SStafford Horne RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs) 21*ea1413e5SStafford Horne RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 22*ea1413e5SStafford Horne RSEQ_INJECT_ASM(3) 23*ea1413e5SStafford Horne RSEQ_ASM_OP_CMPEQ(v, expect, "%l[cmpfail]") 24*ea1413e5SStafford Horne RSEQ_INJECT_ASM(4) 25*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE 26*ea1413e5SStafford Horne RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]") 27*ea1413e5SStafford Horne RSEQ_ASM_OP_CMPEQ(v, expect, "%l[error2]") 28*ea1413e5SStafford Horne #endif 29*ea1413e5SStafford Horne RSEQ_ASM_OP_FINAL_STORE(v, newv, 3) 30*ea1413e5SStafford Horne RSEQ_INJECT_ASM(5) 31*ea1413e5SStafford Horne RSEQ_ASM_DEFINE_ABORT(4, abort) 32*ea1413e5SStafford Horne : /* gcc asm goto does not allow outputs */ 33*ea1413e5SStafford Horne : [cpu_id] "r" (cpu), 34*ea1413e5SStafford Horne [current_cpu_id] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD), 35*ea1413e5SStafford Horne [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr), 36*ea1413e5SStafford Horne [v] "m" (*v), 37*ea1413e5SStafford Horne [expect] "r" (expect), 38*ea1413e5SStafford Horne [newv] "r" (newv) 39*ea1413e5SStafford Horne RSEQ_INJECT_INPUT 40*ea1413e5SStafford Horne : "memory", RSEQ_ASM_TMP_REG_1 41*ea1413e5SStafford Horne RSEQ_INJECT_CLOBBER 42*ea1413e5SStafford Horne : abort, cmpfail 43*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE 44*ea1413e5SStafford Horne , error1, error2 45*ea1413e5SStafford Horne #endif 46*ea1413e5SStafford Horne ); 47*ea1413e5SStafford Horne 48*ea1413e5SStafford Horne return 0; 49*ea1413e5SStafford Horne abort: 50*ea1413e5SStafford Horne RSEQ_INJECT_FAILED 51*ea1413e5SStafford Horne return -1; 52*ea1413e5SStafford Horne cmpfail: 53*ea1413e5SStafford Horne return 1; 54*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE 55*ea1413e5SStafford Horne error1: 56*ea1413e5SStafford Horne rseq_bug("cpu_id comparison failed"); 57*ea1413e5SStafford Horne error2: 58*ea1413e5SStafford Horne rseq_bug("expected value comparison failed"); 59*ea1413e5SStafford Horne #endif 60*ea1413e5SStafford Horne } 61*ea1413e5SStafford Horne 62*ea1413e5SStafford Horne static inline __always_inline 63*ea1413e5SStafford Horne int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpnev_storeoffp_load)(intptr_t *v, intptr_t expectnot, 64*ea1413e5SStafford Horne off_t voffp, intptr_t *load, int cpu) 65*ea1413e5SStafford Horne { 66*ea1413e5SStafford Horne RSEQ_INJECT_C(9) 67*ea1413e5SStafford Horne 68*ea1413e5SStafford Horne __asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f) 69*ea1413e5SStafford Horne RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[cmpfail]") 70*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE 71*ea1413e5SStafford Horne RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]") 72*ea1413e5SStafford Horne RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error2]") 73*ea1413e5SStafford Horne #endif 74*ea1413e5SStafford Horne RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs) 75*ea1413e5SStafford Horne RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 76*ea1413e5SStafford Horne RSEQ_INJECT_ASM(3) 77*ea1413e5SStafford Horne RSEQ_ASM_OP_CMPNE(v, expectnot, "%l[cmpfail]") 78*ea1413e5SStafford Horne RSEQ_INJECT_ASM(4) 79*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE 80*ea1413e5SStafford Horne RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]") 81*ea1413e5SStafford Horne RSEQ_ASM_OP_CMPNE(v, expectnot, "%l[error2]") 82*ea1413e5SStafford Horne #endif 83*ea1413e5SStafford Horne RSEQ_ASM_OP_R_LOAD(v) 84*ea1413e5SStafford Horne RSEQ_ASM_OP_R_STORE(load) 85*ea1413e5SStafford Horne RSEQ_ASM_OP_R_LOAD_OFF(voffp) 86*ea1413e5SStafford Horne RSEQ_ASM_OP_R_FINAL_STORE(v, 3) 87*ea1413e5SStafford Horne RSEQ_INJECT_ASM(5) 88*ea1413e5SStafford Horne RSEQ_ASM_DEFINE_ABORT(4, abort) 89*ea1413e5SStafford Horne : /* gcc asm goto does not allow outputs */ 90*ea1413e5SStafford Horne : [cpu_id] "r" (cpu), 91*ea1413e5SStafford Horne [current_cpu_id] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD), 92*ea1413e5SStafford Horne [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr), 93*ea1413e5SStafford Horne [v] "m" (*v), 94*ea1413e5SStafford Horne [expectnot] "r" (expectnot), 95*ea1413e5SStafford Horne [load] "m" (*load), 96*ea1413e5SStafford Horne [voffp] "Ir" (voffp) 97*ea1413e5SStafford Horne RSEQ_INJECT_INPUT 98*ea1413e5SStafford Horne : "memory", RSEQ_ASM_TMP_REG_1 99*ea1413e5SStafford Horne RSEQ_INJECT_CLOBBER 100*ea1413e5SStafford Horne : abort, cmpfail 101*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE 102*ea1413e5SStafford Horne , error1, error2 103*ea1413e5SStafford Horne #endif 104*ea1413e5SStafford Horne ); 105*ea1413e5SStafford Horne return 0; 106*ea1413e5SStafford Horne abort: 107*ea1413e5SStafford Horne RSEQ_INJECT_FAILED 108*ea1413e5SStafford Horne return -1; 109*ea1413e5SStafford Horne cmpfail: 110*ea1413e5SStafford Horne return 1; 111*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE 112*ea1413e5SStafford Horne error1: 113*ea1413e5SStafford Horne rseq_bug("cpu_id comparison failed"); 114*ea1413e5SStafford Horne error2: 115*ea1413e5SStafford Horne rseq_bug("expected value comparison failed"); 116*ea1413e5SStafford Horne #endif 117*ea1413e5SStafford Horne } 118*ea1413e5SStafford Horne 119*ea1413e5SStafford Horne static inline __always_inline 120*ea1413e5SStafford Horne int RSEQ_TEMPLATE_IDENTIFIER(rseq_addv)(intptr_t *v, intptr_t count, int cpu) 121*ea1413e5SStafford Horne { 122*ea1413e5SStafford Horne RSEQ_INJECT_C(9) 123*ea1413e5SStafford Horne 124*ea1413e5SStafford Horne __asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f) 125*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE 126*ea1413e5SStafford Horne RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]") 127*ea1413e5SStafford Horne #endif 128*ea1413e5SStafford Horne RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs) 129*ea1413e5SStafford Horne RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 130*ea1413e5SStafford Horne RSEQ_INJECT_ASM(3) 131*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE 132*ea1413e5SStafford Horne RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]") 133*ea1413e5SStafford Horne #endif 134*ea1413e5SStafford Horne RSEQ_ASM_OP_R_LOAD(v) 135*ea1413e5SStafford Horne RSEQ_ASM_OP_R_ADD(count) 136*ea1413e5SStafford Horne RSEQ_ASM_OP_R_FINAL_STORE(v, 3) 137*ea1413e5SStafford Horne RSEQ_INJECT_ASM(4) 138*ea1413e5SStafford Horne RSEQ_ASM_DEFINE_ABORT(4, abort) 139*ea1413e5SStafford Horne : /* gcc asm goto does not allow outputs */ 140*ea1413e5SStafford Horne : [cpu_id] "r" (cpu), 141*ea1413e5SStafford Horne [current_cpu_id] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD), 142*ea1413e5SStafford Horne [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr), 143*ea1413e5SStafford Horne [v] "m" (*v), 144*ea1413e5SStafford Horne [count] "r" (count) 145*ea1413e5SStafford Horne RSEQ_INJECT_INPUT 146*ea1413e5SStafford Horne : "memory", RSEQ_ASM_TMP_REG_1 147*ea1413e5SStafford Horne RSEQ_INJECT_CLOBBER 148*ea1413e5SStafford Horne : abort 149*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE 150*ea1413e5SStafford Horne , error1 151*ea1413e5SStafford Horne #endif 152*ea1413e5SStafford Horne ); 153*ea1413e5SStafford Horne return 0; 154*ea1413e5SStafford Horne abort: 155*ea1413e5SStafford Horne RSEQ_INJECT_FAILED 156*ea1413e5SStafford Horne return -1; 157*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE 158*ea1413e5SStafford Horne error1: 159*ea1413e5SStafford Horne rseq_bug("cpu_id comparison failed"); 160*ea1413e5SStafford Horne #endif 161*ea1413e5SStafford Horne } 162*ea1413e5SStafford Horne 163*ea1413e5SStafford Horne static inline __always_inline 164*ea1413e5SStafford Horne int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_cmpeqv_storev)(intptr_t *v, intptr_t expect, 165*ea1413e5SStafford Horne intptr_t *v2, intptr_t expect2, 166*ea1413e5SStafford Horne intptr_t newv, int cpu) 167*ea1413e5SStafford Horne { 168*ea1413e5SStafford Horne RSEQ_INJECT_C(9) 169*ea1413e5SStafford Horne 170*ea1413e5SStafford Horne __asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f) 171*ea1413e5SStafford Horne RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[cmpfail]") 172*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE 173*ea1413e5SStafford Horne RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]") 174*ea1413e5SStafford Horne RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error2]") 175*ea1413e5SStafford Horne RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error3]") 176*ea1413e5SStafford Horne #endif 177*ea1413e5SStafford Horne RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs) 178*ea1413e5SStafford Horne RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 179*ea1413e5SStafford Horne RSEQ_INJECT_ASM(3) 180*ea1413e5SStafford Horne RSEQ_ASM_OP_CMPEQ(v, expect, "%l[cmpfail]") 181*ea1413e5SStafford Horne RSEQ_INJECT_ASM(4) 182*ea1413e5SStafford Horne RSEQ_ASM_OP_CMPEQ(v2, expect2, "%l[cmpfail]") 183*ea1413e5SStafford Horne RSEQ_INJECT_ASM(5) 184*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE 185*ea1413e5SStafford Horne RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]") 186*ea1413e5SStafford Horne RSEQ_ASM_OP_CMPEQ(v, expect, "%l[error2]") 187*ea1413e5SStafford Horne RSEQ_ASM_OP_CMPEQ(v2, expect2, "%l[error3]") 188*ea1413e5SStafford Horne #endif 189*ea1413e5SStafford Horne RSEQ_ASM_OP_FINAL_STORE(v, newv, 3) 190*ea1413e5SStafford Horne RSEQ_INJECT_ASM(6) 191*ea1413e5SStafford Horne RSEQ_ASM_DEFINE_ABORT(4, abort) 192*ea1413e5SStafford Horne : /* gcc asm goto does not allow outputs */ 193*ea1413e5SStafford Horne : [cpu_id] "r" (cpu), 194*ea1413e5SStafford Horne [current_cpu_id] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD), 195*ea1413e5SStafford Horne [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr), 196*ea1413e5SStafford Horne [v] "m" (*v), 197*ea1413e5SStafford Horne [expect] "r" (expect), 198*ea1413e5SStafford Horne [v2] "m" (*v2), 199*ea1413e5SStafford Horne [expect2] "r" (expect2), 200*ea1413e5SStafford Horne [newv] "r" (newv) 201*ea1413e5SStafford Horne RSEQ_INJECT_INPUT 202*ea1413e5SStafford Horne : "memory", RSEQ_ASM_TMP_REG_1 203*ea1413e5SStafford Horne RSEQ_INJECT_CLOBBER 204*ea1413e5SStafford Horne : abort, cmpfail 205*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE 206*ea1413e5SStafford Horne , error1, error2, error3 207*ea1413e5SStafford Horne #endif 208*ea1413e5SStafford Horne ); 209*ea1413e5SStafford Horne 210*ea1413e5SStafford Horne return 0; 211*ea1413e5SStafford Horne abort: 212*ea1413e5SStafford Horne RSEQ_INJECT_FAILED 213*ea1413e5SStafford Horne return -1; 214*ea1413e5SStafford Horne cmpfail: 215*ea1413e5SStafford Horne return 1; 216*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE 217*ea1413e5SStafford Horne error1: 218*ea1413e5SStafford Horne rseq_bug("cpu_id comparison failed"); 219*ea1413e5SStafford Horne error2: 220*ea1413e5SStafford Horne rseq_bug("expected value comparison failed"); 221*ea1413e5SStafford Horne error3: 222*ea1413e5SStafford Horne rseq_bug("2nd expected value comparison failed"); 223*ea1413e5SStafford Horne #endif 224*ea1413e5SStafford Horne } 225*ea1413e5SStafford Horne 226*ea1413e5SStafford Horne #define RSEQ_ARCH_HAS_OFFSET_DEREF_ADDV 227*ea1413e5SStafford Horne 228*ea1413e5SStafford Horne /* 229*ea1413e5SStafford Horne * pval = *(ptr+off) 230*ea1413e5SStafford Horne * *pval += inc; 231*ea1413e5SStafford Horne */ 232*ea1413e5SStafford Horne static inline __always_inline 233*ea1413e5SStafford Horne int RSEQ_TEMPLATE_IDENTIFIER(rseq_offset_deref_addv)(intptr_t *ptr, off_t off, intptr_t inc, 234*ea1413e5SStafford Horne int cpu) 235*ea1413e5SStafford Horne { 236*ea1413e5SStafford Horne RSEQ_INJECT_C(9) 237*ea1413e5SStafford Horne 238*ea1413e5SStafford Horne __asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f) 239*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE 240*ea1413e5SStafford Horne RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]") 241*ea1413e5SStafford Horne #endif 242*ea1413e5SStafford Horne RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs) 243*ea1413e5SStafford Horne RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 244*ea1413e5SStafford Horne RSEQ_INJECT_ASM(3) 245*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE 246*ea1413e5SStafford Horne RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]") 247*ea1413e5SStafford Horne #endif 248*ea1413e5SStafford Horne RSEQ_ASM_OP_R_DEREF_ADDV(ptr, off, inc, 3) 249*ea1413e5SStafford Horne RSEQ_INJECT_ASM(4) 250*ea1413e5SStafford Horne RSEQ_ASM_DEFINE_ABORT(4, abort) 251*ea1413e5SStafford Horne : /* gcc asm goto does not allow outputs */ 252*ea1413e5SStafford Horne : [cpu_id] "r" (cpu), 253*ea1413e5SStafford Horne [current_cpu_id] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD), 254*ea1413e5SStafford Horne [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr), 255*ea1413e5SStafford Horne [ptr] "r" (ptr), 256*ea1413e5SStafford Horne [off] "r" (off), 257*ea1413e5SStafford Horne [inc] "r" (inc) 258*ea1413e5SStafford Horne RSEQ_INJECT_INPUT 259*ea1413e5SStafford Horne : "memory", RSEQ_ASM_TMP_REG_1 260*ea1413e5SStafford Horne RSEQ_INJECT_CLOBBER 261*ea1413e5SStafford Horne : abort 262*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE 263*ea1413e5SStafford Horne , error1 264*ea1413e5SStafford Horne #endif 265*ea1413e5SStafford Horne ); 266*ea1413e5SStafford Horne return 0; 267*ea1413e5SStafford Horne abort: 268*ea1413e5SStafford Horne RSEQ_INJECT_FAILED 269*ea1413e5SStafford Horne return -1; 270*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE 271*ea1413e5SStafford Horne error1: 272*ea1413e5SStafford Horne rseq_bug("cpu_id comparison failed"); 273*ea1413e5SStafford Horne #endif 274*ea1413e5SStafford Horne } 275*ea1413e5SStafford Horne 276*ea1413e5SStafford Horne #endif /* #if defined(RSEQ_TEMPLATE_MO_RELAXED) && 277*ea1413e5SStafford Horne (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID)) */ 278*ea1413e5SStafford Horne 279*ea1413e5SStafford Horne #if (defined(RSEQ_TEMPLATE_MO_RELAXED) || defined(RSEQ_TEMPLATE_MO_RELEASE)) && \ 280*ea1413e5SStafford Horne (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID)) 281*ea1413e5SStafford Horne 282*ea1413e5SStafford Horne static inline __always_inline 283*ea1413e5SStafford Horne int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_trystorev_storev)(intptr_t *v, intptr_t expect, 284*ea1413e5SStafford Horne intptr_t *v2, intptr_t newv2, 285*ea1413e5SStafford Horne intptr_t newv, int cpu) 286*ea1413e5SStafford Horne { 287*ea1413e5SStafford Horne RSEQ_INJECT_C(9) 288*ea1413e5SStafford Horne 289*ea1413e5SStafford Horne __asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f) 290*ea1413e5SStafford Horne RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[cmpfail]") 291*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE 292*ea1413e5SStafford Horne RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]") 293*ea1413e5SStafford Horne RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error2]") 294*ea1413e5SStafford Horne #endif 295*ea1413e5SStafford Horne RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs) 296*ea1413e5SStafford Horne RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 297*ea1413e5SStafford Horne RSEQ_INJECT_ASM(3) 298*ea1413e5SStafford Horne RSEQ_ASM_OP_CMPEQ(v, expect, "%l[cmpfail]") 299*ea1413e5SStafford Horne RSEQ_INJECT_ASM(4) 300*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE 301*ea1413e5SStafford Horne RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]") 302*ea1413e5SStafford Horne RSEQ_ASM_OP_CMPEQ(v, expect, "%l[error2]") 303*ea1413e5SStafford Horne #endif 304*ea1413e5SStafford Horne RSEQ_ASM_OP_STORE(v2, newv2) 305*ea1413e5SStafford Horne RSEQ_INJECT_ASM(5) 306*ea1413e5SStafford Horne #ifdef RSEQ_TEMPLATE_MO_RELEASE 307*ea1413e5SStafford Horne RSEQ_ASM_OP_FINAL_STORE_RELEASE(v, newv, 3) 308*ea1413e5SStafford Horne #else 309*ea1413e5SStafford Horne RSEQ_ASM_OP_FINAL_STORE(v, newv, 3) 310*ea1413e5SStafford Horne #endif 311*ea1413e5SStafford Horne RSEQ_INJECT_ASM(6) 312*ea1413e5SStafford Horne RSEQ_ASM_DEFINE_ABORT(4, abort) 313*ea1413e5SStafford Horne : /* gcc asm goto does not allow outputs */ 314*ea1413e5SStafford Horne : [cpu_id] "r" (cpu), 315*ea1413e5SStafford Horne [current_cpu_id] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD), 316*ea1413e5SStafford Horne [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr), 317*ea1413e5SStafford Horne [expect] "r" (expect), 318*ea1413e5SStafford Horne [v] "m" (*v), 319*ea1413e5SStafford Horne [newv] "r" (newv), 320*ea1413e5SStafford Horne [v2] "m" (*v2), 321*ea1413e5SStafford Horne [newv2] "r" (newv2) 322*ea1413e5SStafford Horne RSEQ_INJECT_INPUT 323*ea1413e5SStafford Horne : "memory", RSEQ_ASM_TMP_REG_1 324*ea1413e5SStafford Horne RSEQ_INJECT_CLOBBER 325*ea1413e5SStafford Horne : abort, cmpfail 326*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE 327*ea1413e5SStafford Horne , error1, error2 328*ea1413e5SStafford Horne #endif 329*ea1413e5SStafford Horne ); 330*ea1413e5SStafford Horne 331*ea1413e5SStafford Horne return 0; 332*ea1413e5SStafford Horne abort: 333*ea1413e5SStafford Horne RSEQ_INJECT_FAILED 334*ea1413e5SStafford Horne return -1; 335*ea1413e5SStafford Horne cmpfail: 336*ea1413e5SStafford Horne return 1; 337*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE 338*ea1413e5SStafford Horne error1: 339*ea1413e5SStafford Horne rseq_bug("cpu_id comparison failed"); 340*ea1413e5SStafford Horne error2: 341*ea1413e5SStafford Horne rseq_bug("expected value comparison failed"); 342*ea1413e5SStafford Horne #endif 343*ea1413e5SStafford Horne } 344*ea1413e5SStafford Horne 345*ea1413e5SStafford Horne static inline __always_inline 346*ea1413e5SStafford Horne int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_trymemcpy_storev)(intptr_t *v, intptr_t expect, 347*ea1413e5SStafford Horne void *dst, void *src, size_t len, 348*ea1413e5SStafford Horne intptr_t newv, int cpu) 349*ea1413e5SStafford Horne { 350*ea1413e5SStafford Horne RSEQ_INJECT_C(9) 351*ea1413e5SStafford Horne __asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f) 352*ea1413e5SStafford Horne RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[cmpfail]") 353*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE 354*ea1413e5SStafford Horne RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]") 355*ea1413e5SStafford Horne RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error2]") 356*ea1413e5SStafford Horne #endif 357*ea1413e5SStafford Horne RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs) 358*ea1413e5SStafford Horne RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 359*ea1413e5SStafford Horne RSEQ_INJECT_ASM(3) 360*ea1413e5SStafford Horne RSEQ_ASM_OP_CMPEQ(v, expect, "%l[cmpfail]") 361*ea1413e5SStafford Horne RSEQ_INJECT_ASM(4) 362*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE 363*ea1413e5SStafford Horne RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]") 364*ea1413e5SStafford Horne RSEQ_ASM_OP_CMPEQ(v, expect, "%l[error2]") 365*ea1413e5SStafford Horne #endif 366*ea1413e5SStafford Horne RSEQ_ASM_OP_R_BAD_MEMCPY(dst, src, len) 367*ea1413e5SStafford Horne RSEQ_INJECT_ASM(5) 368*ea1413e5SStafford Horne #ifdef RSEQ_TEMPLATE_MO_RELEASE 369*ea1413e5SStafford Horne RSEQ_ASM_OP_FINAL_STORE_RELEASE(v, newv, 3) 370*ea1413e5SStafford Horne #else 371*ea1413e5SStafford Horne RSEQ_ASM_OP_FINAL_STORE(v, newv, 3) 372*ea1413e5SStafford Horne #endif 373*ea1413e5SStafford Horne RSEQ_INJECT_ASM(6) 374*ea1413e5SStafford Horne RSEQ_ASM_DEFINE_ABORT(4, abort) 375*ea1413e5SStafford Horne : /* gcc asm goto does not allow outputs */ 376*ea1413e5SStafford Horne : [cpu_id] "r" (cpu), 377*ea1413e5SStafford Horne [current_cpu_id] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD), 378*ea1413e5SStafford Horne [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr), 379*ea1413e5SStafford Horne [expect] "r" (expect), 380*ea1413e5SStafford Horne [v] "m" (*v), 381*ea1413e5SStafford Horne [newv] "r" (newv), 382*ea1413e5SStafford Horne [dst] "r" (dst), 383*ea1413e5SStafford Horne [src] "r" (src), 384*ea1413e5SStafford Horne [len] "r" (len) 385*ea1413e5SStafford Horne RSEQ_INJECT_INPUT 386*ea1413e5SStafford Horne : "memory", RSEQ_ASM_TMP_REG_1, RSEQ_ASM_TMP_REG_2, 387*ea1413e5SStafford Horne RSEQ_ASM_TMP_REG_3, RSEQ_ASM_TMP_REG_4 388*ea1413e5SStafford Horne RSEQ_INJECT_CLOBBER 389*ea1413e5SStafford Horne : abort, cmpfail 390*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE 391*ea1413e5SStafford Horne , error1, error2 392*ea1413e5SStafford Horne #endif 393*ea1413e5SStafford Horne ); 394*ea1413e5SStafford Horne 395*ea1413e5SStafford Horne return 0; 396*ea1413e5SStafford Horne abort: 397*ea1413e5SStafford Horne RSEQ_INJECT_FAILED 398*ea1413e5SStafford Horne return -1; 399*ea1413e5SStafford Horne cmpfail: 400*ea1413e5SStafford Horne return 1; 401*ea1413e5SStafford Horne #ifdef RSEQ_COMPARE_TWICE 402*ea1413e5SStafford Horne error1: 403*ea1413e5SStafford Horne rseq_bug("cpu_id comparison failed"); 404*ea1413e5SStafford Horne error2: 405*ea1413e5SStafford Horne rseq_bug("expected value comparison failed"); 406*ea1413e5SStafford Horne #endif 407*ea1413e5SStafford Horne } 408*ea1413e5SStafford Horne 409*ea1413e5SStafford Horne #endif /* #if (defined(RSEQ_TEMPLATE_MO_RELAXED) || defined(RSEQ_TEMPLATE_MO_RELEASE)) && 410*ea1413e5SStafford Horne (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID)) */ 411*ea1413e5SStafford Horne 412*ea1413e5SStafford Horne #include "rseq-bits-reset.h" 413