aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>2024-02-28 16:33:02 -0500
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>2024-02-28 16:54:43 -0500
commitf6b002478966576d42702807d47623a713c25716 (patch)
tree5219b821e47cd0d7f8256aa5797998e060b4905f
parentb52031b2fc0fc6ea19d2cbe230b2e1e79357617e (diff)
downloadlibrseq-f6b002478966576d42702807d47623a713c25716.tar.gz
ppc: Introduce code deduplication macros
Introduce RSEQ_ASM_U64_PTR() which expresses the type and instance of the defined variable, allowing deduplication of the following macros: - __RSEQ_ASM_DEFINE_TABLE, - RSEQ_ASM_DEFINE_EXIT_POINT. Separate load/store/op helper macros, RSEQ_ASM_STORE_RSEQ_CS, and RSEQ_ASM_U64_PTR into their respective ifdef regions, as the resulting documentation is clearer (and not duplicated). Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Change-Id: I7accb4925e1e294f2d65267641fd4c8dccb4837f
-rw-r--r--include/rseq/arch/ppc.h175
1 files changed, 69 insertions, 106 deletions
diff --git a/include/rseq/arch/ppc.h b/include/rseq/arch/ppc.h
index 3000e52..638d2ba 100644
--- a/include/rseq/arch/ppc.h
+++ b/include/rseq/arch/ppc.h
@@ -57,29 +57,38 @@ do { \
RSEQ_WRITE_ONCE(*(p), v); \
} while (0)
+/*
+ * Helper macros to define and access a variable of long integer type.
+ * Only used internally in rseq headers.
+ */
#ifdef RSEQ_ARCH_PPC64
+# define RSEQ_ASM_STORE_LONG(arg) "std%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] " /* To memory ("m" constraint) */
+# define RSEQ_ASM_STORE_INT(arg) "stw%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] " /* To memory ("m" constraint) */
+# define RSEQ_ASM_LOAD_LONG(arg) "ld%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] " /* From memory ("m" constraint) */
+# define RSEQ_ASM_LOAD_INT(arg) "lwz%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] " /* From memory ("m" constraint) */
+# define RSEQ_ASM_LOADX_LONG "ldx " /* From base register ("b" constraint) */
+# define RSEQ_ASM_CMP_LONG "cmpd " /* Register-to-register comparison */
+# define RSEQ_ASM_CMP_LONG_INT "cmpdi " /* Register-to-immediate comparison */
+#else
+# define RSEQ_ASM_STORE_LONG(arg) "stw%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] " /* To memory ("m" constraint) */
+# define RSEQ_ASM_STORE_INT(arg) RSEQ_ASM_STORE_LONG(arg) /* To memory ("m" constraint) */
+# define RSEQ_ASM_LOAD_LONG(arg) "lwz%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] " /* From memory ("m" constraint) */
+# define RSEQ_ASM_LOAD_INT(arg) RSEQ_ASM_LOAD_LONG(arg) /* From memory ("m" constraint) */
+# define RSEQ_ASM_LOADX_LONG "lwzx " /* From base register ("b" constraint) */
+# define RSEQ_ASM_CMP_LONG "cmpw " /* Register-to-register comparison */
+# define RSEQ_ASM_CMP_LONG_INT "cmpwi " /* Register-to-immediate comparison */
+#endif
-/* Helpers only used internally in this header. */
-#define RSEQ_ASM_STORE_LONG(arg) "std%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] " /* To memory ("m" constraint) */
-#define RSEQ_ASM_STORE_INT(arg) "stw%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] " /* To memory ("m" constraint) */
-#define RSEQ_ASM_LOAD_LONG(arg) "ld%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] " /* From memory ("m" constraint) */
-#define RSEQ_ASM_LOAD_INT(arg) "lwz%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] " /* From memory ("m" constraint) */
-#define RSEQ_ASM_LOADX_LONG "ldx " /* From base register ("b" constraint) */
-#define RSEQ_ASM_CMP_LONG "cmpd " /* Register-to-register comparison */
-#define RSEQ_ASM_CMP_LONG_INT "cmpdi " /* Register-to-immediate comparison */
-
-/* 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\t" \
- ".balign 32\n\t" \
- __rseq_str(label) ":\n\t" \
- ".long " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \
- ".quad " __rseq_str(start_ip) ", " __rseq_str(post_commit_offset) ", " __rseq_str(abort_ip) "\n\t" \
- ".popsection\n\t" \
- ".pushsection __rseq_cs_ptr_array, \"aw\"\n\t" \
- ".quad " __rseq_str(label) "b\n\t" \
- ".popsection\n\t"
+/*
+ * Helper macros to define a variable of pointer type stored in a 64-bit
+ * integer. Only used internally in rseq headers.
+ */
+#ifdef RSEQ_ARCH_PPC64
+# define RSEQ_ASM_U64_PTR(x) ".quad " x
+#else
+/* 32-bit only supported on big endian. */
+# define RSEQ_ASM_U64_PTR(x) ".long 0x0, " x
+#endif
/*
* Store the address of the critical section descriptor structure at
@@ -95,7 +104,8 @@ do { \
* Destination pointer where to store the address of the critical
* section descriptor structure.
*/
-#define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs) \
+#ifdef RSEQ_ARCH_PPC64
+# define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs) \
RSEQ_INJECT_ASM(1) \
"lis %%r17, (" __rseq_str(cs_label) ")@highest\n\t" \
"ori %%r17, %%r17, (" __rseq_str(cs_label) ")@higher\n\t" \
@@ -104,39 +114,14 @@ do { \
"ori %%r17, %%r17, (" __rseq_str(cs_label) ")@l\n\t" \
"std %%r17, %[" __rseq_str(rseq_cs) "]\n\t" \
__rseq_str(label) ":\n\t"
-
-/*
- * 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
- * post-commit IP are already part of the __rseq_cs section and should not be
- * explicitly defined as additional exit points. Knowing all exit points is
- * useful to assist debuggers stepping over the critical section.
- */
-#define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip) \
- ".pushsection __rseq_exit_point_array, \"aw\"\n\t" \
- ".quad " __rseq_str(start_ip) ", " __rseq_str(exit_ip) "\n\t" \
- ".popsection\n\t"
-
-#else /* #ifdef RSEQ_ARCH_PPC64 */
-
-/* Helpers only used internally in this header. */
-#define RSEQ_ASM_STORE_LONG(arg) "stw%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] " /* To memory ("m" constraint) */
-#define RSEQ_ASM_STORE_INT(arg) RSEQ_ASM_STORE_LONG(arg) /* To memory ("m" constraint) */
-#define RSEQ_ASM_LOAD_LONG(arg) "lwz%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] " /* From memory ("m" constraint) */
-#define RSEQ_ASM_LOAD_INT(arg) RSEQ_ASM_LOAD_LONG(arg) /* From memory ("m" constraint) */
-#define RSEQ_ASM_LOADX_LONG "lwzx " /* From base register ("b" constraint) */
-#define RSEQ_ASM_CMP_LONG "cmpw " /* Register-to-register comparison */
-#define RSEQ_ASM_CMP_LONG_INT "cmpwi " /* Register-to-immediate comparison */
+#else
+# define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs) \
+ RSEQ_INJECT_ASM(1) \
+ "lis %%r17, (" __rseq_str(cs_label) ")@ha\n\t" \
+ "addi %%r17, %%r17, (" __rseq_str(cs_label) ")@l\n\t" \
+ RSEQ_ASM_STORE_INT(rseq_cs) "%%r17, %[" __rseq_str(rseq_cs) "]\n\t" \
+ __rseq_str(label) ":\n\t"
+#endif
/* Only used in RSEQ_ASM_DEFINE_TABLE. */
#define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, \
@@ -145,60 +130,15 @@ do { \
".balign 32\n\t" \
__rseq_str(label) ":\n\t" \
".long " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \
- /* 32-bit only supported on BE */ \
- ".long 0x0, " __rseq_str(start_ip) ", 0x0, " __rseq_str(post_commit_offset) ", 0x0, " __rseq_str(abort_ip) "\n\t" \
- ".popsection\n\t" \
- ".pushsection __rseq_cs_ptr_array, \"aw\"\n\t" \
- ".long 0x0, " __rseq_str(label) "b\n\t" \
- ".popsection\n\t"
-
-/*
- * 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
- * post-commit IP are already part of the __rseq_cs section and should not be
- * explicitly defined as additional exit points. Knowing all exit points is
- * useful to assist debuggers stepping over the critical section.
- */
-#define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip) \
- ".pushsection __rseq_exit_point_array, \"aw\"\n\t" \
- /* 32-bit only supported on BE */ \
- ".long 0x0, " __rseq_str(start_ip) ", 0x0, " __rseq_str(exit_ip) "\n\t" \
+ RSEQ_ASM_U64_PTR(__rseq_str(start_ip)) "\n\t" \
+ RSEQ_ASM_U64_PTR(__rseq_str(post_commit_offset)) "\n\t" \
+ RSEQ_ASM_U64_PTR(__rseq_str(abort_ip)) "\n\t" \
+ ".popsection\n\t" \
+ ".pushsection __rseq_cs_ptr_array, \"aw\"\n\t" \
+ RSEQ_ASM_U64_PTR(__rseq_str(label) "b") "\n\t" \
".popsection\n\t"
/*
- * Store the address of the critical section descriptor structure at
- * @cs_label into the @rseq_cs pointer and emit the label @label, which
- * is the beginning of the sequence of consecutive assembly instructions.
- *
- * @label:
- * Local label to the beginning of the sequence of consecutive assembly
- * instructions.
- * @cs_label:
- * Source local label to the critical section descriptor structure.
- * @rseq_cs:
- * Destination pointer where to store the address of the critical
- * section descriptor structure.
- */
-#define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs) \
- RSEQ_INJECT_ASM(1) \
- "lis %%r17, (" __rseq_str(cs_label) ")@ha\n\t" \
- "addi %%r17, %%r17, (" __rseq_str(cs_label) ")@l\n\t" \
- RSEQ_ASM_STORE_INT(rseq_cs) "%%r17, %[" __rseq_str(rseq_cs) "]\n\t" \
- __rseq_str(label) ":\n\t"
-
-#endif /* #ifdef RSEQ_ARCH_PPC64 */
-
-/*
* Define an rseq critical section structure of version 0 with no flags.
*
* @label:
@@ -219,6 +159,29 @@ do { \
(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
+ * post-commit IP are already part of the __rseq_cs section and should not be
+ * explicitly defined as additional exit points. Knowing all exit points is
+ * useful to assist debuggers stepping over the critical section.
+ */
+#define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip) \
+ ".pushsection __rseq_exit_point_array, \"aw\"\n\t" \
+ RSEQ_ASM_U64_PTR(__rseq_str(start_ip)) "\n\t" \
+ RSEQ_ASM_U64_PTR(__rseq_str(exit_ip)) "\n\t" \
+ ".popsection\n\t"
+
+/*
* Define a critical section abort handler.
*
* @label: