Commit 181a1269 authored by Will Deacon's avatar Will Deacon
Browse files

Merge branch 'for-next/insn' into for-next/core

Refactoring of our instruction decoding routines and addition of some
missing encodings.

* for-next/insn:
  arm64: insn: avoid circular include dependency
  arm64: insn: move AARCH64_INSN_SIZE into <asm/insn.h>
  arm64: insn: decouple patching from insn code
  arm64: insn: Add load/store decoding helpers
  arm64: insn: Add some opcodes to instruction decoder
  arm64: insn: Add barrier encodings
  arm64: insn: Add SVE instruction class
  arm64: Move instruction encoder/decoder under lib/
  arm64: Move aarch32 condition check functions
  arm64: Move patching utilities out of instruction encoding/decoding
parents 6cf61e06 69bb0585
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
@@ -3,12 +3,10 @@
#define __ASM_ALTERNATIVE_MACROS_H

#include <asm/cpucaps.h>
#include <asm/insn-def.h>

#define ARM64_CB_PATCH ARM64_NCAPS

/* A64 instructions are always 32 bits. */
#define	AARCH64_INSN_SIZE		4

#ifndef __ASSEMBLY__

#include <linux/stringify.h>
+9 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */

#ifndef __ASM_INSN_DEF_H
#define __ASM_INSN_DEF_H

/* A64 instructions are always 32 bits. */
#define	AARCH64_INSN_SIZE		4

#endif /* __ASM_INSN_DEF_H */
+61 −6
Original line number Diff line number Diff line
@@ -10,7 +10,7 @@
#include <linux/build_bug.h>
#include <linux/types.h>

#include <asm/alternative.h>
#include <asm/insn-def.h>

#ifndef __ASSEMBLY__
/*
@@ -30,6 +30,7 @@
 */
enum aarch64_insn_encoding_class {
	AARCH64_INSN_CLS_UNKNOWN,	/* UNALLOCATED */
	AARCH64_INSN_CLS_SVE,		/* SVE instructions */
	AARCH64_INSN_CLS_DP_IMM,	/* Data processing - immediate */
	AARCH64_INSN_CLS_DP_REG,	/* Data processing - register */
	AARCH64_INSN_CLS_DP_FPSIMD,	/* Data processing - SIMD and FP */
@@ -294,6 +295,12 @@ __AARCH64_INSN_FUNCS(adr, 0x9F000000, 0x10000000)
__AARCH64_INSN_FUNCS(adrp,	0x9F000000, 0x90000000)
__AARCH64_INSN_FUNCS(prfm,	0x3FC00000, 0x39800000)
__AARCH64_INSN_FUNCS(prfm_lit,	0xFF000000, 0xD8000000)
__AARCH64_INSN_FUNCS(store_imm,	0x3FC00000, 0x39000000)
__AARCH64_INSN_FUNCS(load_imm,	0x3FC00000, 0x39400000)
__AARCH64_INSN_FUNCS(store_pre,	0x3FE00C00, 0x38000C00)
__AARCH64_INSN_FUNCS(load_pre,	0x3FE00C00, 0x38400C00)
__AARCH64_INSN_FUNCS(store_post,	0x3FE00C00, 0x38000400)
__AARCH64_INSN_FUNCS(load_post,	0x3FE00C00, 0x38400400)
__AARCH64_INSN_FUNCS(str_reg,	0x3FE0EC00, 0x38206800)
__AARCH64_INSN_FUNCS(ldadd,	0x3F20FC00, 0x38200000)
__AARCH64_INSN_FUNCS(ldr_reg,	0x3FE0EC00, 0x38606800)
@@ -302,6 +309,8 @@ __AARCH64_INSN_FUNCS(ldrsw_lit, 0xFF000000, 0x98000000)
__AARCH64_INSN_FUNCS(exclusive,	0x3F800000, 0x08000000)
__AARCH64_INSN_FUNCS(load_ex,	0x3F400000, 0x08400000)
__AARCH64_INSN_FUNCS(store_ex,	0x3F400000, 0x08000000)
__AARCH64_INSN_FUNCS(stp,	0x7FC00000, 0x29000000)
__AARCH64_INSN_FUNCS(ldp,	0x7FC00000, 0x29400000)
__AARCH64_INSN_FUNCS(stp_post,	0x7FC00000, 0x28800000)
__AARCH64_INSN_FUNCS(ldp_post,	0x7FC00000, 0x28C00000)
__AARCH64_INSN_FUNCS(stp_pre,	0x7FC00000, 0x29800000)
@@ -334,6 +343,7 @@ __AARCH64_INSN_FUNCS(rev64, 0x7FFFFC00, 0x5AC00C00)
__AARCH64_INSN_FUNCS(and,	0x7F200000, 0x0A000000)
__AARCH64_INSN_FUNCS(bic,	0x7F200000, 0x0A200000)
__AARCH64_INSN_FUNCS(orr,	0x7F200000, 0x2A000000)
__AARCH64_INSN_FUNCS(mov_reg,	0x7FE0FFE0, 0x2A0003E0)
__AARCH64_INSN_FUNCS(orn,	0x7F200000, 0x2A200000)
__AARCH64_INSN_FUNCS(eor,	0x7F200000, 0x4A000000)
__AARCH64_INSN_FUNCS(eon,	0x7F200000, 0x4A200000)
@@ -368,6 +378,14 @@ __AARCH64_INSN_FUNCS(eret_auth, 0xFFFFFBFF, 0xD69F0BFF)
__AARCH64_INSN_FUNCS(mrs,	0xFFF00000, 0xD5300000)
__AARCH64_INSN_FUNCS(msr_imm,	0xFFF8F01F, 0xD500401F)
__AARCH64_INSN_FUNCS(msr_reg,	0xFFF00000, 0xD5100000)
__AARCH64_INSN_FUNCS(dmb,	0xFFFFF0FF, 0xD50330BF)
__AARCH64_INSN_FUNCS(dsb_base,	0xFFFFF0FF, 0xD503309F)
__AARCH64_INSN_FUNCS(dsb_nxs,	0xFFFFF3FF, 0xD503323F)
__AARCH64_INSN_FUNCS(isb,	0xFFFFF0FF, 0xD50330DF)
__AARCH64_INSN_FUNCS(sb,	0xFFFFFFFF, 0xD50330FF)
__AARCH64_INSN_FUNCS(clrex,	0xFFFFF0FF, 0xD503305F)
__AARCH64_INSN_FUNCS(ssbb,	0xFFFFFFFF, 0xD503309F)
__AARCH64_INSN_FUNCS(pssbb,	0xFFFFFFFF, 0xD503349F)

#undef	__AARCH64_INSN_FUNCS

@@ -379,8 +397,47 @@ static inline bool aarch64_insn_is_adr_adrp(u32 insn)
	return aarch64_insn_is_adr(insn) || aarch64_insn_is_adrp(insn);
}

int aarch64_insn_read(void *addr, u32 *insnp);
int aarch64_insn_write(void *addr, u32 insn);
static inline bool aarch64_insn_is_dsb(u32 insn)
{
	return aarch64_insn_is_dsb_base(insn) || aarch64_insn_is_dsb_nxs(insn);
}

static inline bool aarch64_insn_is_barrier(u32 insn)
{
	return aarch64_insn_is_dmb(insn) || aarch64_insn_is_dsb(insn) ||
	       aarch64_insn_is_isb(insn) || aarch64_insn_is_sb(insn) ||
	       aarch64_insn_is_clrex(insn) || aarch64_insn_is_ssbb(insn) ||
	       aarch64_insn_is_pssbb(insn);
}

static inline bool aarch64_insn_is_store_single(u32 insn)
{
	return aarch64_insn_is_store_imm(insn) ||
	       aarch64_insn_is_store_pre(insn) ||
	       aarch64_insn_is_store_post(insn);
}

static inline bool aarch64_insn_is_store_pair(u32 insn)
{
	return aarch64_insn_is_stp(insn) ||
	       aarch64_insn_is_stp_pre(insn) ||
	       aarch64_insn_is_stp_post(insn);
}

static inline bool aarch64_insn_is_load_single(u32 insn)
{
	return aarch64_insn_is_load_imm(insn) ||
	       aarch64_insn_is_load_pre(insn) ||
	       aarch64_insn_is_load_post(insn);
}

static inline bool aarch64_insn_is_load_pair(u32 insn)
{
	return aarch64_insn_is_ldp(insn) ||
	       aarch64_insn_is_ldp_pre(insn) ||
	       aarch64_insn_is_ldp_post(insn);
}

enum aarch64_insn_encoding_class aarch64_get_insn_class(u32 insn);
bool aarch64_insn_uses_literal(u32 insn);
bool aarch64_insn_is_branch(u32 insn);
@@ -487,9 +544,6 @@ u32 aarch64_insn_gen_prefetch(enum aarch64_insn_register base,
s32 aarch64_get_branch_offset(u32 insn);
u32 aarch64_set_branch_offset(u32 insn, s32 offset);

int aarch64_insn_patch_text_nosync(void *addr, u32 insn);
int aarch64_insn_patch_text(void *addrs[], u32 insns[], int cnt);

s32 aarch64_insn_adrp_get_offset(u32 insn);
u32 aarch64_insn_adrp_set_offset(u32 insn, s32 offset);

@@ -506,6 +560,7 @@ u32 aarch32_insn_mcr_extract_crm(u32 insn);

typedef bool (pstate_check_t)(unsigned long);
extern pstate_check_t * const aarch32_opcode_cond_checks[16];

#endif /* __ASSEMBLY__ */

#endif	/* __ASM_INSN_H */
+1 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
#define __ARM_KVM_ASM_H__

#include <asm/hyp_image.h>
#include <asm/insn.h>
#include <asm/virt.h>

#define ARM_EXIT_WITH_SERROR_BIT  31
+13 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef	__ASM_PATCHING_H
#define	__ASM_PATCHING_H

#include <linux/types.h>

int aarch64_insn_read(void *addr, u32 *insnp);
int aarch64_insn_write(void *addr, u32 insn);

int aarch64_insn_patch_text_nosync(void *addr, u32 insn);
int aarch64_insn_patch_text(void *addrs[], u32 insns[], int cnt);

#endif	/* __ASM_PATCHING_H */
Loading