Can I get some more acks from the arch maintainers? So far there's only one
ack from Peter Zijlstra for x86. But this touches arm, arm64, loongarch and
riscv too.

-- Steve


On Tue, 01 Oct 2024 13:30:01 +0000
Alice Ryhl <alicer...@google.com> wrote:

> To avoid duplication of inline asm between C and Rust, we need to
> import the inline asm from the relevant `jump_label.h` header into Rust.
> To make that easier, this patch updates the header files to expose the
> inline asm via a new ARCH_STATIC_BRANCH_ASM macro.
> 
> The header files are all updated to define a ARCH_STATIC_BRANCH_ASM that
> takes the same arguments in a consistent order so that Rust can use the
> same logic for every architecture.
> 
> Suggested-by: Peter Zijlstra (Intel) <pet...@infradead.org>
> Acked-by: Peter Zijlstra (Intel) <pet...@infradead.org>
> Co-developed-by: Miguel Ojeda <oj...@kernel.org>
> Signed-off-by: Miguel Ojeda <oj...@kernel.org>
> Signed-off-by: Alice Ryhl <alicer...@google.com>
> ---
>  arch/arm/include/asm/jump_label.h       | 14 +++++----
>  arch/arm64/include/asm/jump_label.h     | 20 ++++++++-----
>  arch/loongarch/include/asm/jump_label.h | 16 +++++++----
>  arch/riscv/include/asm/jump_label.h     | 50 
> ++++++++++++++++++---------------
>  arch/x86/include/asm/jump_label.h       | 38 ++++++++++---------------
>  5 files changed, 75 insertions(+), 63 deletions(-)
> 
> diff --git a/arch/arm/include/asm/jump_label.h 
> b/arch/arm/include/asm/jump_label.h
> index e4eb54f6cd9f..a35aba7f548c 100644
> --- a/arch/arm/include/asm/jump_label.h
> +++ b/arch/arm/include/asm/jump_label.h
> @@ -9,13 +9,17 @@
>  
>  #define JUMP_LABEL_NOP_SIZE 4
>  
> +/* This macro is also expanded on the Rust side. */
> +#define ARCH_STATIC_BRANCH_ASM(key, label)           \
> +     "1:\n\t"                                        \
> +     WASM(nop) "\n\t"                                \
> +     ".pushsection __jump_table,  \"aw\"\n\t"        \
> +     ".word 1b, " label ", " key "\n\t"              \
> +     ".popsection\n\t"                               \
> +
>  static __always_inline bool arch_static_branch(struct static_key *key, bool 
> branch)
>  {
> -     asm goto("1:\n\t"
> -              WASM(nop) "\n\t"
> -              ".pushsection __jump_table,  \"aw\"\n\t"
> -              ".word 1b, %l[l_yes], %c0\n\t"
> -              ".popsection\n\t"
> +     asm goto(ARCH_STATIC_BRANCH_ASM("%c0", "%l[l_yes]")
>                : :  "i" (&((char *)key)[branch]) :  : l_yes);
>  
>       return false;
> diff --git a/arch/arm64/include/asm/jump_label.h 
> b/arch/arm64/include/asm/jump_label.h
> index a0a5bbae7229..424ed421cd97 100644
> --- a/arch/arm64/include/asm/jump_label.h
> +++ b/arch/arm64/include/asm/jump_label.h
> @@ -19,10 +19,14 @@
>  #define JUMP_TABLE_ENTRY(key, label)                 \
>       ".pushsection   __jump_table, \"aw\"\n\t"       \
>       ".align         3\n\t"                          \
> -     ".long          1b - ., %l["#label"] - .\n\t"   \
> -     ".quad          %c0 - .\n\t"                    \
> -     ".popsection\n\t"                               \
> -     :  :  "i"(key) :  : label
> +     ".long          1b - ., " label " - .\n\t"      \
> +     ".quad          " key " - .\n\t"                \
> +     ".popsection\n\t"
> +
> +/* This macro is also expanded on the Rust side. */
> +#define ARCH_STATIC_BRANCH_ASM(key, label)           \
> +     "1:     nop\n\t"                                \
> +     JUMP_TABLE_ENTRY(key, label)
>  
>  static __always_inline bool arch_static_branch(struct static_key * const key,
>                                              const bool branch)
> @@ -30,8 +34,8 @@ static __always_inline bool arch_static_branch(struct 
> static_key * const key,
>       char *k = &((char *)key)[branch];
>  
>       asm goto(
> -             "1:     nop                                     \n\t"
> -             JUMP_TABLE_ENTRY(k, l_yes)
> +             ARCH_STATIC_BRANCH_ASM("%c0", "%l[l_yes]")
> +             :  :  "i"(k) :  : l_yes
>               );
>  
>       return false;
> @@ -43,9 +47,11 @@ static __always_inline bool arch_static_branch_jump(struct 
> static_key * const ke
>                                                   const bool branch)
>  {
>       char *k = &((char *)key)[branch];
> +
>       asm goto(
>               "1:     b               %l[l_yes]               \n\t"
> -             JUMP_TABLE_ENTRY(k, l_yes)
> +             JUMP_TABLE_ENTRY("%c0", "%l[l_yes]")
> +             :  :  "i"(k) :  : l_yes
>               );
>       return false;
>  l_yes:
> diff --git a/arch/loongarch/include/asm/jump_label.h 
> b/arch/loongarch/include/asm/jump_label.h
> index 29acfe3de3fa..8a924bd69d19 100644
> --- a/arch/loongarch/include/asm/jump_label.h
> +++ b/arch/loongarch/include/asm/jump_label.h
> @@ -13,18 +13,22 @@
>  
>  #define JUMP_LABEL_NOP_SIZE  4
>  
> -#define JUMP_TABLE_ENTRY                             \
> +/* This macro is also expanded on the Rust side. */
> +#define JUMP_TABLE_ENTRY(key, label)                 \
>        ".pushsection  __jump_table, \"aw\"    \n\t"   \
>        ".align        3                       \n\t"   \
> -      ".long         1b - ., %l[l_yes] - .   \n\t"   \
> -      ".quad         %0 - .                  \n\t"   \
> +      ".long         1b - ., " label " - .   \n\t"   \
> +      ".quad         " key " - .             \n\t"   \
>        ".popsection                           \n\t"
>  
> +#define ARCH_STATIC_BRANCH_ASM(key, label)           \
> +     "1:     nop                             \n\t"   \
> +     JUMP_TABLE_ENTRY(key, label)
> +
>  static __always_inline bool arch_static_branch(struct static_key * const 
> key, const bool branch)
>  {
>       asm goto(
> -             "1:     nop                     \n\t"
> -             JUMP_TABLE_ENTRY
> +             ARCH_STATIC_BRANCH_ASM("%0", "%l[l_yes]")
>               :  :  "i"(&((char *)key)[branch]) :  : l_yes);
>  
>       return false;
> @@ -37,7 +41,7 @@ static __always_inline bool arch_static_branch_jump(struct 
> static_key * const ke
>  {
>       asm goto(
>               "1:     b       %l[l_yes]       \n\t"
> -             JUMP_TABLE_ENTRY
> +             JUMP_TABLE_ENTRY("%0", "%l[l_yes]")
>               :  :  "i"(&((char *)key)[branch]) :  : l_yes);
>  
>       return false;
> diff --git a/arch/riscv/include/asm/jump_label.h 
> b/arch/riscv/include/asm/jump_label.h
> index 1c768d02bd0c..87a71cc6d146 100644
> --- a/arch/riscv/include/asm/jump_label.h
> +++ b/arch/riscv/include/asm/jump_label.h
> @@ -16,21 +16,28 @@
>  
>  #define JUMP_LABEL_NOP_SIZE 4
>  
> +#define JUMP_TABLE_ENTRY(key, label)                 \
> +     ".pushsection   __jump_table, \"aw\"    \n\t"   \
> +     ".align         " RISCV_LGPTR "         \n\t"   \
> +     ".long          1b - ., " label " - .   \n\t"   \
> +     "" RISCV_PTR "  " key " - .             \n\t"   \
> +     ".popsection                            \n\t"
> +
> +/* This macro is also expanded on the Rust side. */
> +#define ARCH_STATIC_BRANCH_ASM(key, label)           \
> +     "       .align          2               \n\t"   \
> +     "       .option push                    \n\t"   \
> +     "       .option norelax                 \n\t"   \
> +     "       .option norvc                   \n\t"   \
> +     "1:     nop                             \n\t"   \
> +     "       .option pop                     \n\t"   \
> +     JUMP_TABLE_ENTRY(key, label)
> +
>  static __always_inline bool arch_static_branch(struct static_key * const key,
>                                              const bool branch)
>  {
>       asm goto(
> -             "       .align          2                       \n\t"
> -             "       .option push                            \n\t"
> -             "       .option norelax                         \n\t"
> -             "       .option norvc                           \n\t"
> -             "1:     nop                                     \n\t"
> -             "       .option pop                             \n\t"
> -             "       .pushsection    __jump_table, \"aw\"    \n\t"
> -             "       .align          " RISCV_LGPTR "         \n\t"
> -             "       .long           1b - ., %l[label] - .   \n\t"
> -             "       " RISCV_PTR "   %0 - .                  \n\t"
> -             "       .popsection                             \n\t"
> +             ARCH_STATIC_BRANCH_ASM("%0", "%l[label]")
>               :  :  "i"(&((char *)key)[branch]) :  : label);
>  
>       return false;
> @@ -38,21 +45,20 @@ static __always_inline bool arch_static_branch(struct 
> static_key * const key,
>       return true;
>  }
>  
> +#define ARCH_STATIC_BRANCH_JUMP_ASM(key, label)              \
> +     "       .align          2               \n\t"   \
> +     "       .option push                    \n\t"   \
> +     "       .option norelax                 \n\t"   \
> +     "       .option norvc                   \n\t"   \
> +     "1:     j       " label "               \n\t" \
> +     "       .option pop                     \n\t"   \
> +     JUMP_TABLE_ENTRY(key, label)
> +
>  static __always_inline bool arch_static_branch_jump(struct static_key * 
> const key,
>                                                   const bool branch)
>  {
>       asm goto(
> -             "       .align          2                       \n\t"
> -             "       .option push                            \n\t"
> -             "       .option norelax                         \n\t"
> -             "       .option norvc                           \n\t"
> -             "1:     j               %l[label]               \n\t"
> -             "       .option pop                             \n\t"
> -             "       .pushsection    __jump_table, \"aw\"    \n\t"
> -             "       .align          " RISCV_LGPTR "         \n\t"
> -             "       .long           1b - ., %l[label] - .   \n\t"
> -             "       " RISCV_PTR "   %0 - .                  \n\t"
> -             "       .popsection                             \n\t"
> +             ARCH_STATIC_BRANCH_JUMP_ASM("%0", "%l[label]")
>               :  :  "i"(&((char *)key)[branch]) :  : label);
>  
>       return false;
> diff --git a/arch/x86/include/asm/jump_label.h 
> b/arch/x86/include/asm/jump_label.h
> index cbbef32517f0..fb79fa1cf70a 100644
> --- a/arch/x86/include/asm/jump_label.h
> +++ b/arch/x86/include/asm/jump_label.h
> @@ -12,49 +12,41 @@
>  #include <linux/stringify.h>
>  #include <linux/types.h>
>  
> -#define JUMP_TABLE_ENTRY                             \
> +#define JUMP_TABLE_ENTRY(key, label)                 \
>       ".pushsection __jump_table,  \"aw\" \n\t"       \
>       _ASM_ALIGN "\n\t"                               \
>       ".long 1b - . \n\t"                             \
> -     ".long %l[l_yes] - . \n\t"                      \
> -     _ASM_PTR "%c0 + %c1 - .\n\t"                    \
> +     ".long " label " - . \n\t"                      \
> +     _ASM_PTR " " key " - . \n\t"                    \
>       ".popsection \n\t"
>  
> +/* This macro is also expanded on the Rust side. */
>  #ifdef CONFIG_HAVE_JUMP_LABEL_HACK
> -
> -static __always_inline bool arch_static_branch(struct static_key *key, bool 
> branch)
> -{
> -     asm goto("1:"
> -             "jmp %l[l_yes] # objtool NOPs this \n\t"
> -             JUMP_TABLE_ENTRY
> -             : :  "i" (key), "i" (2 | branch) : : l_yes);
> -
> -     return false;
> -l_yes:
> -     return true;
> -}
> -
> +#define ARCH_STATIC_BRANCH_ASM(key, label)           \
> +     "1: jmp " label " # objtool NOPs this \n\t"     \
> +     JUMP_TABLE_ENTRY(key, label)
>  #else /* !CONFIG_HAVE_JUMP_LABEL_HACK */
> +#define ARCH_STATIC_BRANCH_ASM(key, label)           \
> +     "1: .byte " __stringify(BYTES_NOP5) "\n\t"      \
> +     JUMP_TABLE_ENTRY(key, label)
> +#endif /* CONFIG_HAVE_JUMP_LABEL_HACK */
>  
>  static __always_inline bool arch_static_branch(struct static_key * const 
> key, const bool branch)
>  {
> -     asm goto("1:"
> -             ".byte " __stringify(BYTES_NOP5) "\n\t"
> -             JUMP_TABLE_ENTRY
> -             : :  "i" (key), "i" (branch) : : l_yes);
> +     int hack_bit = IS_ENABLED(CONFIG_HAVE_JUMP_LABEL_HACK) ? 2 : 0;
> +     asm goto(ARCH_STATIC_BRANCH_ASM("%c0 + %c1", "%l[l_yes]")
> +             : :  "i" (key), "i" (hack_bit | branch) : : l_yes);
>  
>       return false;
>  l_yes:
>       return true;
>  }
>  
> -#endif /* CONFIG_HAVE_JUMP_LABEL_HACK */
> -
>  static __always_inline bool arch_static_branch_jump(struct static_key * 
> const key, const bool branch)
>  {
>       asm goto("1:"
>               "jmp %l[l_yes]\n\t"
> -             JUMP_TABLE_ENTRY
> +             JUMP_TABLE_ENTRY("%c0 + %c1", "%l[l_yes]")
>               : :  "i" (key), "i" (branch) : : l_yes);
>  
>       return false;
> 


Reply via email to