]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
arm64: insn: Add support for encoding DSB
authorJames Morse <james.morse@arm.com>
Thu, 9 Dec 2021 15:12:19 +0000 (15:12 +0000)
committerJames Morse <james.morse@arm.com>
Thu, 8 May 2025 14:28:29 +0000 (15:28 +0100)
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>
arch/arm64/include/asm/insn.h
arch/arm64/lib/insn.c

index 39577f1d079a98c8a0660e0af7dc1f6ae2a174e1..18c7811774d301f1d58e1f53ebd8ae972ec5277b 100644 (file)
@@ -706,6 +706,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);
 u32 aarch64_insn_gen_mrs(enum aarch64_insn_register result,
                         enum aarch64_insn_system_register sysreg);
 
index 9bef696e2230be11ead86438eaf007a719194eac..4e298baddc2e5667e9f5d7928315f667af602ec3 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/printk.h>
@@ -1500,43 +1501,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);
@@ -1545,6 +1544,21 @@ 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;
+}
+
 u32 aarch64_insn_gen_mrs(enum aarch64_insn_register result,
                         enum aarch64_insn_system_register sysreg)
 {