Comment riscv macros implementation
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 27 Feb 2024 22:04:44 +0000 (17:04 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 27 Feb 2024 22:28:07 +0000 (17:28 -0500)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Change-Id: I4299061a38443bff9ff0701b73752153d2c3df54

include/rseq/rseq-riscv.h

index 95ade6ec2302f40256e11ec63a69270304c1b0b8..d1e0719f42e4a879a6dfbf887e8c0d27c4bac3f7 100644 (file)
@@ -1,5 +1,15 @@
 /* SPDX-License-Identifier: MIT */
 /* SPDX-FileCopyrightText: 2022 Vincent Chen <vincent.chen@sifive.com> */
+/* SPDX-FileCopyrightText: 2024 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> */
+
+/*
+ * rseq-riscv.h
+ */
+
+/*
+ * RSEQ_ASM_*() macro helpers are internal to the librseq headers. Those
+ * are not part of the public API.
+ */
 
 /*
  * Select the instruction "csrw mhartid, x0" as the RSEQ_SIG. Unlike
 #error "Currently, RSEQ only supports Little-Endian version"
 #endif
 
+/*
+ * Instruction selection between 32-bit/64-bit. Used internally in the
+ * rseq headers.
+ */
 #if __riscv_xlen == 64
 #define __RSEQ_ASM_REG_SEL(a, b)       a
 #elif __riscv_xlen == 32
 #define RSEQ_ASM_REG_L __RSEQ_ASM_REG_SEL("ld ", "lw ")
 #define RSEQ_ASM_REG_S __RSEQ_ASM_REG_SEL("sd ", "sw ")
 
+/*
+ * Refer to the Linux kernel memory model (LKMM) for documentation of
+ * the memory barriers.
+ */
+
+/* Only used internally in rseq headers. */
 #define RSEQ_ASM_RISCV_FENCE(p, s) \
        __asm__ __volatile__ ("fence " #p "," #s : : : "memory")
+/* CPU memory barrier. */
 #define rseq_smp_mb()  RSEQ_ASM_RISCV_FENCE(rw, rw)
+/* CPU read memory barrier */
 #define rseq_smp_rmb() RSEQ_ASM_RISCV_FENCE(r, r)
+/* CPU write memory barrier */
 #define rseq_smp_wmb() RSEQ_ASM_RISCV_FENCE(w, w)
-#define RSEQ_ASM_TMP_REG_1     "t6"
-#define RSEQ_ASM_TMP_REG_2     "t5"
-#define RSEQ_ASM_TMP_REG_3     "t4"
-#define RSEQ_ASM_TMP_REG_4     "t3"
 
+/* Acquire: One-way permeable barrier. */
 #define rseq_smp_load_acquire(p)                                       \
 __extension__ ({                                                       \
        rseq_unqual_scalar_typeof(*(p)) ____p1 = RSEQ_READ_ONCE(*(p));  \
@@ -43,14 +63,23 @@ __extension__ ({                                                    \
        ____p1;                                                         \
 })
 
+/* Acquire barrier after control dependency. */
 #define rseq_smp_acquire__after_ctrl_dep()     rseq_smp_rmb()
 
+/* Release: One-way permeable barrier. */
 #define rseq_smp_store_release(p, v)                                   \
 do {                                                                   \
        RSEQ_ASM_RISCV_FENCE(rw, w);                                    \
        RSEQ_WRITE_ONCE(*(p), v);                                       \
 } while (0)
 
+/* Temporary registers. */
+#define RSEQ_ASM_TMP_REG_1     "t6"
+#define RSEQ_ASM_TMP_REG_2     "t5"
+#define RSEQ_ASM_TMP_REG_3     "t4"
+#define RSEQ_ASM_TMP_REG_4     "t3"
+
+/* Only used in RSEQ_ASM_DEFINE_TABLE. */
 #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, start_ip,       \
                                post_commit_offset, abort_ip)           \
        ".pushsection   __rseq_cs, \"aw\"\n"                            \
@@ -65,11 +94,36 @@ do {                                                                        \
        ".quad " __rseq_str(label) "b\n"                                \
        ".popsection\n"
 
+/*
+ * Define an rseq critical section structure of version 0 with no flags.
+ *
+ *  @label:
+ *    Local label for the beginning of the critical section descriptor
+ *    structure.
+ *  @start_ip:
+ *    Pointer to the first instruction of the sequence of consecutive assembly
+ *    instructions.
+ *  @post_commit_ip:
+ *    Pointer to the instruction after the last instruction of the sequence of
+ *    consecutive assembly instructions.
+ *  @abort_ip:
+ *    Pointer to the instruction where to move the execution flow in case of
+ *    abort of the sequence of consecutive assembly instructions.
+ */
 #define RSEQ_ASM_DEFINE_TABLE(label, start_ip, post_commit_ip, abort_ip) \
        __RSEQ_ASM_DEFINE_TABLE(label, 0x0, 0x0, start_ip,               \
                                ((post_commit_ip) - (start_ip)), abort_ip)
 
 /*
+ * Define the @exit_ip pointer as an exit point for the sequence of consecutive
+ * assembly instructions at @start_ip.
+ *
+ *  @start_ip:
+ *    Pointer to the first instruction of the sequence of consecutive assembly
+ *    instructions.
+ *  @exit_ip:
+ *    Pointer to an exit point instruction.
+ *
  * Exit points of a rseq critical section consist of all instructions outside
  * of the critical section where a critical section can either branch to or
  * reach through the normal course of its execution. The abort IP and the
@@ -82,12 +136,16 @@ do {                                                                       \
        ".quad " __rseq_str(start_ip) ", " __rseq_str(exit_ip) "\n"     \
        ".popsection\n"
 
-#define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs)               \
-       RSEQ_INJECT_ASM(1)                                              \
-       "la     " RSEQ_ASM_TMP_REG_1 ", " __rseq_str(cs_label) "\n"     \
-       RSEQ_ASM_REG_S  RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(rseq_cs) "]\n" \
-       __rseq_str(label) ":\n"
-
+/*
+ * Define a critical section abort handler.
+ *
+ *  @label:
+ *    Local label to the abort handler.
+ *  @teardown:
+ *    Sequence of instructions to run on abort.
+ *  @abort_label:
+ *    C label to jump to at the end of the sequence.
+ */
 #define RSEQ_ASM_DEFINE_ABORT(label, teardown, abort_label)            \
        "j      222f\n"                                                 \
        ".balign        4\n"                                            \
@@ -97,56 +155,91 @@ do {                                                                       \
        "j      %l[" __rseq_str(abort_label) "]\n"                      \
        "222:\n"
 
+/* Jump to local label @label when @cpu_id != @current_cpu_id. */
+#define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs)               \
+       RSEQ_INJECT_ASM(1)                                              \
+       "la     " RSEQ_ASM_TMP_REG_1 ", " __rseq_str(cs_label) "\n"     \
+       RSEQ_ASM_REG_S  RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(rseq_cs) "]\n" \
+       __rseq_str(label) ":\n"
+
+/* Store @value to address @var. */
 #define RSEQ_ASM_OP_STORE(value, var)                                  \
        RSEQ_ASM_REG_S  "%[" __rseq_str(value) "], %[" __rseq_str(var) "]\n"
 
+/* Jump to local label @label when @var != @expect. */
 #define RSEQ_ASM_OP_CBNE(var, expect, label)                           \
        RSEQ_ASM_REG_L  RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(var) "]\n" \
        "bne    " RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(expect) "] ,"    \
                  __rseq_str(label) "\n"
 
+/*
+ * Jump to local label @label when @var != @expect (32-bit register
+ * comparison).
+ */
 #define RSEQ_ASM_OP_CBNE32(var, expect, label)                         \
        "lw     " RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(var) "]\n"       \
        "bne    " RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(expect) "] ,"    \
                  __rseq_str(label) "\n"
 
+/* Jump to local label @label when @var == @expect. */
 #define RSEQ_ASM_OP_CBEQ(var, expect, label)                           \
        RSEQ_ASM_REG_L  RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(var) "]\n" \
        "beq    " RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(expect) "] ,"    \
                  __rseq_str(label) "\n"
 
+/* Jump to local label @label when @cpu_id != @current_cpu_id. */
 #define RSEQ_ASM_CBNE_CPU_ID(cpu_id, current_cpu_id, label)            \
        RSEQ_INJECT_ASM(2)                                              \
        RSEQ_ASM_OP_CBNE32(current_cpu_id, cpu_id, label)
 
+/* Load @var into temporary register. */
 #define RSEQ_ASM_OP_R_LOAD(var)                                                \
        RSEQ_ASM_REG_L  RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(var) "]\n"
 
+/* Store from temporary register into @var. */
 #define RSEQ_ASM_OP_R_STORE(var)                                       \
        RSEQ_ASM_REG_S  RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(var) "]\n"
 
+/* Load from address in temporary register+@offset into temporary register. */
 #define RSEQ_ASM_OP_R_LOAD_OFF(offset)                                 \
        "add    " RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(offset) "], "    \
                 RSEQ_ASM_TMP_REG_1 "\n"                                \
        RSEQ_ASM_REG_L  RSEQ_ASM_TMP_REG_1 ", (" RSEQ_ASM_TMP_REG_1 ")\n"
 
+/* Add @count to temporary register. */
 #define RSEQ_ASM_OP_R_ADD(count)                                       \
        "add    " RSEQ_ASM_TMP_REG_1 ", " RSEQ_ASM_TMP_REG_1            \
                ", %[" __rseq_str(count) "]\n"
 
+/*
+ * End-of-sequence store of @value to address @var. Emit
+ * @post_commit_label label after the store instruction.
+ */
 #define RSEQ_ASM_OP_FINAL_STORE(value, var, post_commit_label)         \
        RSEQ_ASM_OP_STORE(value, var)                                   \
        __rseq_str(post_commit_label) ":\n"
 
+/*
+ * End-of-sequence store-release of @value to address @var. Emit
+ * @post_commit_label label after the store instruction.
+ */
 #define RSEQ_ASM_OP_FINAL_STORE_RELEASE(value, var, post_commit_label) \
        "fence  rw, w\n"                                                \
        RSEQ_ASM_OP_STORE(value, var)                                   \
        __rseq_str(post_commit_label) ":\n"
 
+/*
+ * End-of-sequence store of temporary register to address @var. Emit
+ * @post_commit_label label after the store instruction.
+ */
 #define RSEQ_ASM_OP_R_FINAL_STORE(var, post_commit_label)              \
        RSEQ_ASM_REG_S  RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(var) "]\n" \
        __rseq_str(post_commit_label) ":\n"
 
+/*
+ * Copy @len bytes from @src to @dst. This is an inefficient bytewise
+ * copy and could be improved in the future.
+ */
 #define RSEQ_ASM_OP_R_BYTEWISE_MEMCPY(dst, src, len)                   \
        "beqz   %[" __rseq_str(len) "], 333f\n"                         \
        "mv     " RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(len) "]\n"       \
@@ -161,6 +254,10 @@ do {                                                                       \
        "bnez   " RSEQ_ASM_TMP_REG_1 ", 222b\n"                         \
        "333:\n"
 
+/*
+ * Load pointer address from @ptr. Add @off to offset from this pointer.
+ * Add @inc to the resulting address as an end-of-sequence store.
+ */
 #define RSEQ_ASM_OP_R_DEREF_ADDV(ptr, off, inc, post_commit_label)     \
        "mv     " RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(ptr) "]\n"       \
        RSEQ_ASM_OP_R_ADD(off)                                          \
This page took 0.046194 seconds and 4 git commands to generate.