1744f4be5SPaul Burton /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ 2744f4be5SPaul Burton /* 3744f4be5SPaul Burton * Author: Paul Burton <paul.burton@mips.com> 4744f4be5SPaul Burton * (C) Copyright 2018 MIPS Tech LLC 5431b6328SMathieu Desnoyers * (C) Copyright 2016-2022 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> 6744f4be5SPaul Burton */ 7744f4be5SPaul Burton 816b96b6eSMathieu Desnoyers /* 916b96b6eSMathieu Desnoyers * RSEQ_SIG uses the break instruction. The instruction pattern is: 1016b96b6eSMathieu Desnoyers * 1116b96b6eSMathieu Desnoyers * On MIPS: 1216b96b6eSMathieu Desnoyers * 0350000d break 0x350 1316b96b6eSMathieu Desnoyers * 1416b96b6eSMathieu Desnoyers * On nanoMIPS: 1516b96b6eSMathieu Desnoyers * 00100350 break 0x350 1616b96b6eSMathieu Desnoyers * 1716b96b6eSMathieu Desnoyers * On microMIPS: 1816b96b6eSMathieu Desnoyers * 0000d407 break 0x350 1916b96b6eSMathieu Desnoyers * 2016b96b6eSMathieu Desnoyers * For nanoMIPS32 and microMIPS, the instruction stream is encoded as 16-bit 2116b96b6eSMathieu Desnoyers * halfwords, so the signature halfwords need to be swapped accordingly for 2216b96b6eSMathieu Desnoyers * little-endian. 2316b96b6eSMathieu Desnoyers */ 2416b96b6eSMathieu Desnoyers #if defined(__nanomips__) 2516b96b6eSMathieu Desnoyers # ifdef __MIPSEL__ 2616b96b6eSMathieu Desnoyers # define RSEQ_SIG 0x03500010 2716b96b6eSMathieu Desnoyers # else 2816b96b6eSMathieu Desnoyers # define RSEQ_SIG 0x00100350 2916b96b6eSMathieu Desnoyers # endif 3016b96b6eSMathieu Desnoyers #elif defined(__mips_micromips) 3116b96b6eSMathieu Desnoyers # ifdef __MIPSEL__ 3216b96b6eSMathieu Desnoyers # define RSEQ_SIG 0xd4070000 3316b96b6eSMathieu Desnoyers # else 3416b96b6eSMathieu Desnoyers # define RSEQ_SIG 0x0000d407 3516b96b6eSMathieu Desnoyers # endif 3616b96b6eSMathieu Desnoyers #elif defined(__mips__) 3716b96b6eSMathieu Desnoyers # define RSEQ_SIG 0x0350000d 3816b96b6eSMathieu Desnoyers #else 3916b96b6eSMathieu Desnoyers /* Unknown MIPS architecture. */ 4016b96b6eSMathieu Desnoyers #endif 41744f4be5SPaul Burton 42744f4be5SPaul Burton #define rseq_smp_mb() __asm__ __volatile__ ("sync" ::: "memory") 43744f4be5SPaul Burton #define rseq_smp_rmb() rseq_smp_mb() 44744f4be5SPaul Burton #define rseq_smp_wmb() rseq_smp_mb() 45744f4be5SPaul Burton 46744f4be5SPaul Burton #define rseq_smp_load_acquire(p) \ 47744f4be5SPaul Burton __extension__ ({ \ 48*2b2fe605SMathieu Desnoyers rseq_unqual_scalar_typeof(*(p)) ____p1 = RSEQ_READ_ONCE(*(p)); \ 49744f4be5SPaul Burton rseq_smp_mb(); \ 50744f4be5SPaul Burton ____p1; \ 51744f4be5SPaul Burton }) 52744f4be5SPaul Burton 53744f4be5SPaul Burton #define rseq_smp_acquire__after_ctrl_dep() rseq_smp_rmb() 54744f4be5SPaul Burton 55744f4be5SPaul Burton #define rseq_smp_store_release(p, v) \ 56744f4be5SPaul Burton do { \ 57744f4be5SPaul Burton rseq_smp_mb(); \ 58*2b2fe605SMathieu Desnoyers RSEQ_WRITE_ONCE(*(p), v); \ 59744f4be5SPaul Burton } while (0) 60744f4be5SPaul Burton 61744f4be5SPaul Burton #if _MIPS_SZLONG == 64 62744f4be5SPaul Burton # define LONG ".dword" 63744f4be5SPaul Burton # define LONG_LA "dla" 64744f4be5SPaul Burton # define LONG_L "ld" 65744f4be5SPaul Burton # define LONG_S "sd" 66744f4be5SPaul Burton # define LONG_ADDI "daddiu" 67744f4be5SPaul Burton # define U32_U64_PAD(x) x 68744f4be5SPaul Burton #elif _MIPS_SZLONG == 32 69744f4be5SPaul Burton # define LONG ".word" 70744f4be5SPaul Burton # define LONG_LA "la" 71744f4be5SPaul Burton # define LONG_L "lw" 72744f4be5SPaul Burton # define LONG_S "sw" 73744f4be5SPaul Burton # define LONG_ADDI "addiu" 74744f4be5SPaul Burton # ifdef __BIG_ENDIAN 75744f4be5SPaul Burton # define U32_U64_PAD(x) "0x0, " x 76744f4be5SPaul Burton # else 77744f4be5SPaul Burton # define U32_U64_PAD(x) x ", 0x0" 78744f4be5SPaul Burton # endif 79744f4be5SPaul Burton #else 80744f4be5SPaul Burton # error unsupported _MIPS_SZLONG 81744f4be5SPaul Burton #endif 82744f4be5SPaul Burton 83a3e3131fSMathieu Desnoyers #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, start_ip, \ 84744f4be5SPaul Burton post_commit_offset, abort_ip) \ 85a3e3131fSMathieu Desnoyers ".pushsection __rseq_cs, \"aw\"\n\t" \ 86744f4be5SPaul Burton ".balign 32\n\t" \ 87a3e3131fSMathieu Desnoyers __rseq_str(label) ":\n\t" \ 88744f4be5SPaul Burton ".word " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \ 89744f4be5SPaul Burton LONG " " U32_U64_PAD(__rseq_str(start_ip)) "\n\t" \ 90744f4be5SPaul Burton LONG " " U32_U64_PAD(__rseq_str(post_commit_offset)) "\n\t" \ 91744f4be5SPaul Burton LONG " " U32_U64_PAD(__rseq_str(abort_ip)) "\n\t" \ 92a3e3131fSMathieu Desnoyers ".popsection\n\t" \ 93a3e3131fSMathieu Desnoyers ".pushsection __rseq_cs_ptr_array, \"aw\"\n\t" \ 94a3e3131fSMathieu Desnoyers LONG " " U32_U64_PAD(__rseq_str(label) "b") "\n\t" \ 95744f4be5SPaul Burton ".popsection\n\t" 96744f4be5SPaul Burton 97a3e3131fSMathieu Desnoyers #define RSEQ_ASM_DEFINE_TABLE(label, start_ip, post_commit_ip, abort_ip) \ 98a3e3131fSMathieu Desnoyers __RSEQ_ASM_DEFINE_TABLE(label, 0x0, 0x0, start_ip, \ 99744f4be5SPaul Burton (post_commit_ip - start_ip), abort_ip) 100744f4be5SPaul Burton 1014fe2088eSMathieu Desnoyers /* 1024fe2088eSMathieu Desnoyers * Exit points of a rseq critical section consist of all instructions outside 1034fe2088eSMathieu Desnoyers * of the critical section where a critical section can either branch to or 1044fe2088eSMathieu Desnoyers * reach through the normal course of its execution. The abort IP and the 105a3e3131fSMathieu Desnoyers * post-commit IP are already part of the __rseq_cs section and should not be 106a3e3131fSMathieu Desnoyers * explicitly defined as additional exit points. Knowing all exit points is 1074fe2088eSMathieu Desnoyers * useful to assist debuggers stepping over the critical section. 1084fe2088eSMathieu Desnoyers */ 1094fe2088eSMathieu Desnoyers #define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip) \ 1104fe2088eSMathieu Desnoyers ".pushsection __rseq_exit_point_array, \"aw\"\n\t" \ 1114fe2088eSMathieu Desnoyers LONG " " U32_U64_PAD(__rseq_str(start_ip)) "\n\t" \ 1124fe2088eSMathieu Desnoyers LONG " " U32_U64_PAD(__rseq_str(exit_ip)) "\n\t" \ 1134fe2088eSMathieu Desnoyers ".popsection\n\t" 1144fe2088eSMathieu Desnoyers 115744f4be5SPaul Burton #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs) \ 116744f4be5SPaul Burton RSEQ_INJECT_ASM(1) \ 117744f4be5SPaul Burton LONG_LA " $4, " __rseq_str(cs_label) "\n\t" \ 118744f4be5SPaul Burton LONG_S " $4, %[" __rseq_str(rseq_cs) "]\n\t" \ 119744f4be5SPaul Burton __rseq_str(label) ":\n\t" 120744f4be5SPaul Burton 121744f4be5SPaul Burton #define RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, label) \ 122744f4be5SPaul Burton RSEQ_INJECT_ASM(2) \ 123744f4be5SPaul Burton "lw $4, %[" __rseq_str(current_cpu_id) "]\n\t" \ 124744f4be5SPaul Burton "bne $4, %[" __rseq_str(cpu_id) "], " __rseq_str(label) "\n\t" 125744f4be5SPaul Burton 126744f4be5SPaul Burton #define __RSEQ_ASM_DEFINE_ABORT(table_label, label, teardown, \ 127744f4be5SPaul Burton abort_label, version, flags, \ 128744f4be5SPaul Burton start_ip, post_commit_offset, abort_ip) \ 129744f4be5SPaul Burton ".balign 32\n\t" \ 130744f4be5SPaul Burton __rseq_str(table_label) ":\n\t" \ 131744f4be5SPaul Burton ".word " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \ 132744f4be5SPaul Burton LONG " " U32_U64_PAD(__rseq_str(start_ip)) "\n\t" \ 133744f4be5SPaul Burton LONG " " U32_U64_PAD(__rseq_str(post_commit_offset)) "\n\t" \ 134744f4be5SPaul Burton LONG " " U32_U64_PAD(__rseq_str(abort_ip)) "\n\t" \ 135744f4be5SPaul Burton ".word " __rseq_str(RSEQ_SIG) "\n\t" \ 136744f4be5SPaul Burton __rseq_str(label) ":\n\t" \ 137744f4be5SPaul Burton teardown \ 138744f4be5SPaul Burton "b %l[" __rseq_str(abort_label) "]\n\t" 139744f4be5SPaul Burton 140744f4be5SPaul Burton #define RSEQ_ASM_DEFINE_ABORT(table_label, label, teardown, abort_label, \ 141744f4be5SPaul Burton start_ip, post_commit_ip, abort_ip) \ 142744f4be5SPaul Burton __RSEQ_ASM_DEFINE_ABORT(table_label, label, teardown, \ 143744f4be5SPaul Burton abort_label, 0x0, 0x0, start_ip, \ 144744f4be5SPaul Burton (post_commit_ip - start_ip), abort_ip) 145744f4be5SPaul Burton 146744f4be5SPaul Burton #define RSEQ_ASM_DEFINE_CMPFAIL(label, teardown, cmpfail_label) \ 147744f4be5SPaul Burton __rseq_str(label) ":\n\t" \ 148744f4be5SPaul Burton teardown \ 149744f4be5SPaul Burton "b %l[" __rseq_str(cmpfail_label) "]\n\t" 150744f4be5SPaul Burton 151431b6328SMathieu Desnoyers /* Per-cpu-id indexing. */ 152744f4be5SPaul Burton 153431b6328SMathieu Desnoyers #define RSEQ_TEMPLATE_CPU_ID 154431b6328SMathieu Desnoyers #define RSEQ_TEMPLATE_MO_RELAXED 155431b6328SMathieu Desnoyers #include "rseq-mips-bits.h" 156431b6328SMathieu Desnoyers #undef RSEQ_TEMPLATE_MO_RELAXED 157744f4be5SPaul Burton 158431b6328SMathieu Desnoyers #define RSEQ_TEMPLATE_MO_RELEASE 159431b6328SMathieu Desnoyers #include "rseq-mips-bits.h" 160431b6328SMathieu Desnoyers #undef RSEQ_TEMPLATE_MO_RELEASE 161431b6328SMathieu Desnoyers #undef RSEQ_TEMPLATE_CPU_ID 162744f4be5SPaul Burton 163431b6328SMathieu Desnoyers /* Per-mm-cid indexing. */ 164744f4be5SPaul Burton 165431b6328SMathieu Desnoyers #define RSEQ_TEMPLATE_MM_CID 166431b6328SMathieu Desnoyers #define RSEQ_TEMPLATE_MO_RELAXED 167431b6328SMathieu Desnoyers #include "rseq-mips-bits.h" 168431b6328SMathieu Desnoyers #undef RSEQ_TEMPLATE_MO_RELAXED 169744f4be5SPaul Burton 170431b6328SMathieu Desnoyers #define RSEQ_TEMPLATE_MO_RELEASE 171431b6328SMathieu Desnoyers #include "rseq-mips-bits.h" 172431b6328SMathieu Desnoyers #undef RSEQ_TEMPLATE_MO_RELEASE 173431b6328SMathieu Desnoyers #undef RSEQ_TEMPLATE_MM_CID 174744f4be5SPaul Burton 175431b6328SMathieu Desnoyers /* APIs which are not based on cpu ids. */ 176744f4be5SPaul Burton 177431b6328SMathieu Desnoyers #define RSEQ_TEMPLATE_CPU_ID_NONE 178431b6328SMathieu Desnoyers #define RSEQ_TEMPLATE_MO_RELAXED 179431b6328SMathieu Desnoyers #include "rseq-mips-bits.h" 180431b6328SMathieu Desnoyers #undef RSEQ_TEMPLATE_MO_RELAXED 181431b6328SMathieu Desnoyers #undef RSEQ_TEMPLATE_CPU_ID_NONE 182