]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
arm64: insn: Add support for encoding DSB
authorJames Morse <james.morse@arm.com>
Sat, 7 Jun 2025 15:25:11 +0000 (15:25 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 27 Jun 2025 10:04:23 +0000 (11:04 +0100)
[ Upstream commit 63de8abd97ddb9b758bd8f915ecbd18e1f1a87a0 ]

To generate code in the eBPF epilogue that uses the DSB instruction,
insn.c needs a heler to encode the type and domain.

Re-use the crm encoding logic from the DMB instruction.

Signed-off-by: James Morse <james.morse@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Pu Lehui <pulehui@huawei.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/arm64/include/asm/insn.h
arch/arm64/kernel/insn.c

index 6edc7ca4aecd43ce1d4fc4d5657f70f88fe0b22e..1ef7bcc4a9b1f9d74c9abd8734caf4c0a6f91b07 100644 (file)
@@ -585,6 +585,7 @@ u32 aarch64_insn_gen_cas(enum aarch64_insn_register result,
 }
 #endif
 u32 aarch64_insn_gen_dmb(enum aarch64_insn_mb_type type);
+u32 aarch64_insn_gen_dsb(enum aarch64_insn_mb_type type);
 
 s32 aarch64_get_branch_offset(u32 insn);
 u32 aarch64_set_branch_offset(u32 insn, s32 offset);
index 7efa567ef0f6455159c4c5cc33ad5228701ee7c4..2d84453f5200f7b7ff7369c5401e6d5ee6f27cb7 100644 (file)
@@ -5,6 +5,7 @@
  *
  * Copyright (C) 2014-2016 Zi Shen Lim <zlim.lnx@gmail.com>
  */
+#include <linux/bitfield.h>
 #include <linux/bitops.h>
 #include <linux/bug.h>
 #include <linux/compiler.h>
@@ -1810,43 +1811,41 @@ u32 aarch64_insn_gen_extr(enum aarch64_insn_variant variant,
        return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn, Rm);
 }
 
-u32 aarch64_insn_gen_dmb(enum aarch64_insn_mb_type type)
+static u32 __get_barrier_crm_val(enum aarch64_insn_mb_type type)
 {
-       u32 opt;
-       u32 insn;
-
        switch (type) {
        case AARCH64_INSN_MB_SY:
-               opt = 0xf;
-               break;
+               return 0xf;
        case AARCH64_INSN_MB_ST:
-               opt = 0xe;
-               break;
+               return 0xe;
        case AARCH64_INSN_MB_LD:
-               opt = 0xd;
-               break;
+               return 0xd;
        case AARCH64_INSN_MB_ISH:
-               opt = 0xb;
-               break;
+               return 0xb;
        case AARCH64_INSN_MB_ISHST:
-               opt = 0xa;
-               break;
+               return 0xa;
        case AARCH64_INSN_MB_ISHLD:
-               opt = 0x9;
-               break;
+               return 0x9;
        case AARCH64_INSN_MB_NSH:
-               opt = 0x7;
-               break;
+               return 0x7;
        case AARCH64_INSN_MB_NSHST:
-               opt = 0x6;
-               break;
+               return 0x6;
        case AARCH64_INSN_MB_NSHLD:
-               opt = 0x5;
-               break;
+               return 0x5;
        default:
-               pr_err("%s: unknown dmb type %d\n", __func__, type);
+               pr_err("%s: unknown barrier type %d\n", __func__, type);
                return AARCH64_BREAK_FAULT;
        }
+}
+
+u32 aarch64_insn_gen_dmb(enum aarch64_insn_mb_type type)
+{
+       u32 opt;
+       u32 insn;
+
+       opt = __get_barrier_crm_val(type);
+       if (opt == AARCH64_BREAK_FAULT)
+               return AARCH64_BREAK_FAULT;
 
        insn = aarch64_insn_get_dmb_value();
        insn &= ~GENMASK(11, 8);
@@ -1854,3 +1853,18 @@ u32 aarch64_insn_gen_dmb(enum aarch64_insn_mb_type type)
 
        return insn;
 }
+
+u32 aarch64_insn_gen_dsb(enum aarch64_insn_mb_type type)
+{
+       u32 opt, insn;
+
+       opt = __get_barrier_crm_val(type);
+       if (opt == AARCH64_BREAK_FAULT)
+               return AARCH64_BREAK_FAULT;
+
+       insn = aarch64_insn_get_dsb_base_value();
+       insn &= ~GENMASK(11, 8);
+       insn |= (opt << 8);
+
+       return insn;
+}