]> git.ipfire.org Git - thirdparty/kernel/stable.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)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 18 May 2025 06:24:10 +0000 (08:24 +0200)
commit 63de8abd97ddb9b758bd8f915ecbd18e1f1a87a0 upstream.

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: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/arm64/include/asm/insn.h
arch/arm64/lib/insn.c

index 0ccf51afde31a600cb7efbb3008f8ec17f4ed7dd..12c0278294e3f6856810c630b4f54b7478e14b04 100644 (file)
@@ -687,6 +687,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 a635ab83fee359421cd7c26bf6b59324feb21522..7232b1e70a125f34f9f7d0cc05d51d89b8d40d1a 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>
@@ -1471,43 +1472,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);
@@ -1515,3 +1514,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;
+}