| 1 |
|
| 2 | |
| 3 | * Author: Paul Burton <[email protected]>
|
| 4 | * (C) Copyright 2018 MIPS Tech LLC
|
| 5 | * (C) Copyright 2016-2022 - Mathieu Desnoyers <[email protected]>
|
| 6 |
|
| 7 |
|
| 8 | |
| 9 | * RSEQ_SIG uses the break instruction. The instruction pattern is:
|
| 10 | *
|
| 11 | * On MIPS:
|
| 12 | * 0350000d break 0x350
|
| 13 | *
|
| 14 | * On nanoMIPS:
|
| 15 | * 00100350 break 0x350
|
| 16 | *
|
| 17 | * On microMIPS:
|
| 18 | * 0000d407 break 0x350
|
| 19 | *
|
| 20 | * For nanoMIPS32 and microMIPS, the instruction stream is encoded as 16-bit
|
| 21 | * halfwords, so the signature halfwords need to be swapped accordingly for
|
| 22 | * little-endian.
|
| 23 |
|
| 24 | #if defined(__nanomips__)
|
| 25 | # ifdef __MIPSEL__
|
| 26 | # define RSEQ_SIG 0x03500010
|
| 27 | # else
|
| 28 | # define RSEQ_SIG 0x00100350
|
| 29 | # endif
|
| 30 | #elif defined(__mips_micromips)
|
| 31 | # ifdef __MIPSEL__
|
| 32 | # define RSEQ_SIG 0xd4070000
|
| 33 | # else
|
| 34 | # define RSEQ_SIG 0x0000d407
|
| 35 | # endif
|
| 36 | #elif defined(__mips__)
|
| 37 | # define RSEQ_SIG 0x0350000d
|
| 38 | #else
|
| 39 |
|
| 40 | #endif
|
| 41 |
|
| 42 | #define rseq_smp_mb() __asm__ __volatile__ ("sync" ::: "memory")
|
| 43 | #define rseq_smp_rmb() rseq_smp_mb()
|
| 44 | #define rseq_smp_wmb() rseq_smp_mb()
|
| 45 |
|
| 46 | #define rseq_smp_load_acquire(p) \
|
| 47 | __extension__ ({ \
|
| 48 | rseq_unqual_scalar_typeof(*(p)) ____p1 = RSEQ_READ_ONCE(*(p)); \
|
| 49 | rseq_smp_mb(); \
|
| 50 | ____p1; \
|
| 51 | })
|
| 52 |
|
| 53 | #define rseq_smp_acquire__after_ctrl_dep() rseq_smp_rmb()
|
| 54 |
|
| 55 | #define rseq_smp_store_release(p, v) \
|
| 56 | do { \
|
| 57 | rseq_smp_mb(); \
|
| 58 | RSEQ_WRITE_ONCE(*(p), v); \
|
| 59 | } while (0)
|
| 60 |
|
| 61 | #if _MIPS_SZLONG == 64
|
| 62 | # define LONG ".dword"
|
| 63 | # define LONG_LA "dla"
|
| 64 | # define LONG_L "ld"
|
| 65 | # define LONG_S "sd"
|
| 66 | # define LONG_ADDI "daddiu"
|
| 67 | # define U32_U64_PAD(x) x
|
| 68 | #elif _MIPS_SZLONG == 32
|
| 69 | # define LONG ".word"
|
| 70 | # define LONG_LA "la"
|
| 71 | # define LONG_L "lw"
|
| 72 | # define LONG_S "sw"
|
| 73 | # define LONG_ADDI "addiu"
|
| 74 | # ifdef __BIG_ENDIAN
|
| 75 | # define U32_U64_PAD(x) "0x0, " x
|
| 76 | # else
|
| 77 | # define U32_U64_PAD(x) x ", 0x0"
|
| 78 | # endif
|
| 79 | #else
|
| 80 | # error unsupported _MIPS_SZLONG
|
| 81 | #endif
|
| 82 |
|
| 83 | #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, start_ip, \
|
| 84 | post_commit_offset, abort_ip) \
|
| 85 | ".pushsection __rseq_cs, \"aw\"\n\t" \
|
| 86 | ".balign 32\n\t" \
|
| 87 | __rseq_str(label) ":\n\t" \
|
| 88 | ".word " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \
|
| 89 | LONG " " U32_U64_PAD(__rseq_str(start_ip)) "\n\t" \
|
| 90 | LONG " " U32_U64_PAD(__rseq_str(post_commit_offset)) "\n\t" \
|
| 91 | LONG " " U32_U64_PAD(__rseq_str(abort_ip)) "\n\t" \
|
| 92 | ".popsection\n\t" \
|
| 93 | ".pushsection __rseq_cs_ptr_array, \"aw\"\n\t" \
|
| 94 | LONG " " U32_U64_PAD(__rseq_str(label) "b") "\n\t" \
|
| 95 | ".popsection\n\t"
|
| 96 |
|
| 97 | #define RSEQ_ASM_DEFINE_TABLE(label, start_ip, post_commit_ip, abort_ip) \
|
| 98 | __RSEQ_ASM_DEFINE_TABLE(label, 0x0, 0x0, start_ip, \
|
| 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\t" \
|
| 111 | LONG " " U32_U64_PAD(__rseq_str(start_ip)) "\n\t" \
|
| 112 | LONG " " U32_U64_PAD(__rseq_str(exit_ip)) "\n\t" \
|
| 113 | ".popsection\n\t"
|
| 114 |
|
| 115 | #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs) \
|
| 116 | RSEQ_INJECT_ASM(1) \
|
| 117 | LONG_LA " $4, " __rseq_str(cs_label) "\n\t" \
|
| 118 | LONG_S " $4, %[" __rseq_str(rseq_cs) "]\n\t" \
|
| 119 | __rseq_str(label) ":\n\t"
|
| 120 |
|
| 121 | #define RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, label) \
|
| 122 | RSEQ_INJECT_ASM(2) \
|
| 123 | "lw $4, %[" __rseq_str(current_cpu_id) "]\n\t" \
|
| 124 | "bne $4, %[" __rseq_str(cpu_id) "], " __rseq_str(label) "\n\t"
|
| 125 |
|
| 126 | #define __RSEQ_ASM_DEFINE_ABORT(table_label, label, teardown, \
|
| 127 | abort_label, version, flags, \
|
| 128 | start_ip, post_commit_offset, abort_ip) \
|
| 129 | ".balign 32\n\t" \
|
| 130 | __rseq_str(table_label) ":\n\t" \
|
| 131 | ".word " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \
|
| 132 | LONG " " U32_U64_PAD(__rseq_str(start_ip)) "\n\t" \
|
| 133 | LONG " " U32_U64_PAD(__rseq_str(post_commit_offset)) "\n\t" \
|
| 134 | LONG " " U32_U64_PAD(__rseq_str(abort_ip)) "\n\t" \
|
| 135 | ".word " __rseq_str(RSEQ_SIG) "\n\t" \
|
| 136 | __rseq_str(label) ":\n\t" \
|
| 137 | teardown \
|
| 138 | "b %l[" __rseq_str(abort_label) "]\n\t"
|
| 139 |
|
| 140 | #define RSEQ_ASM_DEFINE_ABORT(table_label, label, teardown, abort_label, \
|
| 141 | start_ip, post_commit_ip, abort_ip) \
|
| 142 | __RSEQ_ASM_DEFINE_ABORT(table_label, label, teardown, \
|
| 143 | abort_label, 0x0, 0x0, start_ip, \
|
| 144 | (post_commit_ip - start_ip), abort_ip)
|
| 145 |
|
| 146 | #define RSEQ_ASM_DEFINE_CMPFAIL(label, teardown, cmpfail_label) \
|
| 147 | __rseq_str(label) ":\n\t" \
|
| 148 | teardown \
|
| 149 | "b %l[" __rseq_str(cmpfail_label) "]\n\t"
|
| 150 |
|
| 151 |
|
| 152 |
|
| 153 | #define RSEQ_TEMPLATE_CPU_ID
|
| 154 | #define RSEQ_TEMPLATE_MO_RELAXED
|
| 155 | #include "rseq-mips-bits.h"
|
| 156 | #undef RSEQ_TEMPLATE_MO_RELAXED
|
| 157 |
|
| 158 | #define RSEQ_TEMPLATE_MO_RELEASE
|
| 159 | #include "rseq-mips-bits.h"
|
| 160 | #undef RSEQ_TEMPLATE_MO_RELEASE
|
| 161 | #undef RSEQ_TEMPLATE_CPU_ID
|
| 162 |
|
| 163 |
|
| 164 |
|
| 165 | #define RSEQ_TEMPLATE_MM_CID
|
| 166 | #define RSEQ_TEMPLATE_MO_RELAXED
|
| 167 | #include "rseq-mips-bits.h"
|
| 168 | #undef RSEQ_TEMPLATE_MO_RELAXED
|
| 169 |
|
| 170 | #define RSEQ_TEMPLATE_MO_RELEASE
|
| 171 | #include "rseq-mips-bits.h"
|
| 172 | #undef RSEQ_TEMPLATE_MO_RELEASE
|
| 173 | #undef RSEQ_TEMPLATE_MM_CID
|
| 174 |
|
| 175 |
|
| 176 |
|
| 177 | #define RSEQ_TEMPLATE_CPU_ID_NONE
|
| 178 | #define RSEQ_TEMPLATE_MO_RELAXED
|
| 179 | #include "rseq-mips-bits.h"
|
| 180 | #undef RSEQ_TEMPLATE_MO_RELAXED
|
| 181 | #undef RSEQ_TEMPLATE_CPU_ID_NONE
|