Commit 63de8abd authored by James Morse's avatar James Morse
Browse files

arm64: insn: Add support for encoding DSB



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: default avatarJames Morse <james.morse@arm.com>
Reviewed-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
parent 92a09c47
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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);

+37 −23
Original line number Diff line number Diff line
@@ -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)
{