linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH v4 00/37] objtool: add base support for arm64
@ 2022-04-29  9:43 Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 01/37] tools: Add some generic functions and headers Chen Zhongjin
                   ` (36 more replies)
  0 siblings, 37 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

This series enables objtool to start doing stack validation/check 
on arm64 kernel builds.

Gathering Julien's previous work[1][2], now objtool can check build
on arm64 build for defconfig and yesconfig, with only few unreachable
warning.

This series includes objtool part (1-15) and arm64 part (16-37), if
necessary it can be taken apart as two series.

I'm not sure that UNWIND_HINT added to entry (33-36) is complete
and correct, because after Julien finished it there was a
refactoring for entry. It will be fully tested after I implement
unwinder_orc for arm64.

[1] https://lkml.org/lkml/2021/3/3/1135
[2] https://github.com/julien-thierry/linux.git

---
Changes v3 -> v4:
- [1] fix EX_ENTRY_SIZE from 8 to 12.
- [14-37] modify arm64 for supporting objtool, including annotation,
	asm code modification, ignoring some validation, to make objtool
	be enable to pass arm64 builds.

Changes v2 -> v3:
- [04] rebase Julien's version to mainstream and solve conflicts.
- [05, 06, 08] Merge dumplicate "*type = INSN_OTHER".
- [08, 09, 10] When meeting unrecognized instructions such as  datas
	in .text code or 0x0 padding insns, last version used
	"loc->ignorable" to mark and remove them from objtool insn list.

	However there are two problems to do so:
	1. when meeting insns can't be decoded or excluded, objtool will
	just stop.
	
	2. deleting every insn can cause problems in fellow procedure.

	So I changed "record_invalid_insn" that we can delete one insn or
	just set it ignored. Now check will throw an error and going on when
	meeting undecodable instructions.

	Also, to prevent the confusion between "loc->ignorable" and
	"insn->ignore" I changed "ignore" to "delete".

Changes v1 -> v2:
	- Drop gcc plugin in favor of -fno-jump-tables
	- miscelaneous fixes and cleanups

--->
Chen Zhongjin (6):
  arm64: Add annotate_reachable() for objtools
  arm64: irq-gic: Replace unreachable() with -EINVAL
  arm64: ftrace: Skip validation of entry-ftrace.o
  arm64: bpf: Skip validation of ___bpf_prog_run
  arm64: Annotate ASM symbols with unknown stack state
  arm64: entry: Align stack size for alternative

Julien Thierry (29):
  tools: Add some generic functions and headers
  tools: arm64: Make aarch64 instruction decoder available to tools
  tools: bug: Remove duplicate definition
  objtool: arm64: Add base definition for arm64 backend
  objtool: arm64: Decode add/sub instructions
  objtool: arm64: Decode jump and call related instructions
  objtool: arm64: Decode other system instructions
  objtool: arm64: Decode load/store instructions
  objtool: arm64: Decode LDR instructions
  objtool: arm64: Accept non-instruction data in code sections
  objtool: arm64: Handle supported relocations in alternatives
  objtool: arm64: Ignore replacement section for alternative callback
  objtool: check: Support data in text section
  objtool: arm64: Add unwind_hint support
  arm64: bug: Add reachable annotation to warning macros
  arm64: kgdb: Mark code following kgdb brk as reachable
  arm64: Set intra-function call annotations
  arm64: kernel: Skip validation of proton-pack.c.c and hibernate.c
  arm64: kernel: Skip validation of sigreturn32.o
  arm64: crypto: Remove unnecessary stackframe
  arm64: sleep: Properly set frame pointer before call
  arm64: Change symbol annotations
  arm64: efi-header: Mark efi header as data
  arm64: head: Mark constants as data
  arm64: proc: Mark constant as data
  arm64: crypto: Mark data in code sections
  arm64: entry: Annotate valid stack in kernel entry
  arm64: entry: Annotate code switching to tasks
  arm64: kvm: Annotate stack state for guest enter/exit code

Raphael Gault (2):
  objtool: arm64: Enable stack validation for arm64
  arm64: kernel: Skip validation of kuser32.o

 arch/arm64/Kconfig                            |    1 +
 arch/arm64/Makefile                           |    4 +
 arch/arm64/crypto/aes-neonbs-core.S           |   14 +-
 arch/arm64/crypto/crct10dif-ce-core.S         |    5 +
 arch/arm64/crypto/poly1305-armv8.pl           |    4 +
 arch/arm64/crypto/sha512-armv8.pl             |   29 +-
 arch/arm64/include/asm/assembler.h            |    2 +
 arch/arm64/include/asm/bug.h                  |    6 +-
 arch/arm64/include/asm/kgdb.h                 |    1 +
 arch/arm64/include/asm/unwind_hints.h         |   27 +
 arch/arm64/kernel/Makefile                    |   10 +
 arch/arm64/kernel/cpu-reset.S                 |    2 +
 arch/arm64/kernel/efi-entry.S                 |    2 +
 arch/arm64/kernel/efi-header.S                |    2 +
 arch/arm64/kernel/entry.S                     |   29 +-
 arch/arm64/kernel/head.S                      |   75 +-
 arch/arm64/kernel/hibernate-asm.S             |    2 +
 arch/arm64/kernel/hibernate.c                 |    2 +
 arch/arm64/kernel/proton-pack.c               |    2 +
 arch/arm64/kernel/relocate_kernel.S           |    2 +
 arch/arm64/kernel/sleep.S                     |    8 +-
 arch/arm64/kvm/hyp/entry.S                    |    7 +-
 arch/arm64/kvm/hyp/hyp-entry.S                |    3 +
 arch/arm64/kvm/hyp/vgic-v3-sr.c               |    7 +-
 arch/arm64/mm/proc.S                          |    4 +-
 drivers/irqchip/irq-gic-v3.c                  |    2 +-
 include/linux/compiler.h                      |    9 +
 kernel/bpf/core.c                             |    3 +
 tools/arch/arm64/include/asm/insn.h           |  565 +++++++
 tools/arch/arm64/include/asm/unwind_hints.h   |   27 +
 tools/arch/arm64/lib/insn.c                   | 1464 +++++++++++++++++
 tools/include/asm-generic/bitops/__ffs.h      |   11 +
 tools/include/linux/bug.h                     |    6 +-
 tools/include/linux/kernel.h                  |   21 +
 tools/include/linux/printk.h                  |   40 +
 tools/objtool/Makefile                        |    5 +
 tools/objtool/arch/arm64/Build                |    8 +
 tools/objtool/arch/arm64/decode.c             |  506 ++++++
 .../arch/arm64/include/arch/cfi_regs.h        |   14 +
 tools/objtool/arch/arm64/include/arch/elf.h   |    8 +
 .../arch/arm64/include/arch/endianness.h      |    9 +
 .../objtool/arch/arm64/include/arch/special.h |   22 +
 tools/objtool/arch/arm64/special.c            |   36 +
 tools/objtool/arch/x86/decode.c               |    5 +
 tools/objtool/check.c                         |   25 +-
 tools/objtool/elf.c                           |   14 +
 tools/objtool/include/objtool/arch.h          |    3 +
 tools/objtool/include/objtool/elf.h           |    1 +
 tools/objtool/sync-check.sh                   |    5 +
 49 files changed, 2985 insertions(+), 74 deletions(-)
 create mode 100644 arch/arm64/include/asm/unwind_hints.h
 create mode 100644 tools/arch/arm64/include/asm/insn.h
 create mode 100644 tools/arch/arm64/include/asm/unwind_hints.h
 create mode 100644 tools/arch/arm64/lib/insn.c
 create mode 100644 tools/include/linux/printk.h
 create mode 100644 tools/objtool/arch/arm64/Build
 create mode 100644 tools/objtool/arch/arm64/decode.c
 create mode 100644 tools/objtool/arch/arm64/include/arch/cfi_regs.h
 create mode 100644 tools/objtool/arch/arm64/include/arch/elf.h
 create mode 100644 tools/objtool/arch/arm64/include/arch/endianness.h
 create mode 100644 tools/objtool/arch/arm64/include/arch/special.h
 create mode 100644 tools/objtool/arch/arm64/special.c

-- 
2.17.1


^ permalink raw reply	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 01/37] tools: Add some generic functions and headers
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 02/37] tools: arm64: Make aarch64 instruction decoder available to tools Chen Zhongjin
                   ` (35 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

These will be needed to be able to use arm64 instruction decoder in
userland tools.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
---
 tools/include/asm-generic/bitops/__ffs.h | 11 +++++++
 tools/include/linux/kernel.h             | 21 +++++++++++++
 tools/include/linux/printk.h             | 40 ++++++++++++++++++++++++
 3 files changed, 72 insertions(+)
 create mode 100644 tools/include/linux/printk.h

diff --git a/tools/include/asm-generic/bitops/__ffs.h b/tools/include/asm-generic/bitops/__ffs.h
index 9d1310519497..963f8a22212f 100644
--- a/tools/include/asm-generic/bitops/__ffs.h
+++ b/tools/include/asm-generic/bitops/__ffs.h
@@ -42,4 +42,15 @@ static __always_inline unsigned long __ffs(unsigned long word)
 	return num;
 }
 
+static inline unsigned long __ffs64(u64 word)
+{
+#if BITS_PER_LONG == 32
+	if (((u32)word) == 0UL)
+		return __ffs((u32)(word >> 32)) + 32;
+#elif BITS_PER_LONG != 64
+#error BITS_PER_LONG not 32 or 64
+#endif
+	return __ffs((unsigned long)word);
+}
+
 #endif /* _TOOLS_LINUX_ASM_GENERIC_BITOPS___FFS_H_ */
diff --git a/tools/include/linux/kernel.h b/tools/include/linux/kernel.h
index 4b0673bf52c2..47f24f07e8f1 100644
--- a/tools/include/linux/kernel.h
+++ b/tools/include/linux/kernel.h
@@ -102,6 +102,27 @@ int scnprintf_pad(char * buf, size_t size, const char * fmt, ...);
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
 #endif
 
+/**
+ * upper_32_bits - return bits 32-63 of a number
+ * @n: the number we're accessing
+ *
+ * A basic shift-right of a 64- or 32-bit quantity.  Use this to suppress
+ * the "right shift count >= width of type" warning when that quantity is
+ * 32-bits.
+ */
+#define upper_32_bits(n) ((u32)(((n) >> 16) >> 16))
+
+/**
+ * lower_32_bits - return bits 0-31 of a number
+ * @n: the number we're accessing
+ */
+#define lower_32_bits(n) ((u32)(n))
+
+/* Inspired from ALIGN_*_KERNEL */
+#define __ALIGN_MASK(x, mask)	(((x) + (mask)) & ~(mask))
+#define __ALIGN(x, a)		__ALIGN_MASK(x, (typeof(x))(a) - 1)
+#define ALIGN_DOWN(x, a)	__ALIGN((x) - ((a) - 1), (a))
+
 #define current_gfp_context(k) 0
 #define synchronize_rcu()
 
diff --git a/tools/include/linux/printk.h b/tools/include/linux/printk.h
new file mode 100644
index 000000000000..515ebdc47e6e
--- /dev/null
+++ b/tools/include/linux/printk.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _TOOLS_LINUX_KERNEL_PRINTK_H_
+#define _TOOLS_LINUX_KERNEL_PRINTK_H_
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define printk(fmt, ...) fprintf(stdout, fmt, ##__VA_ARGS__)
+#define pr_info printk
+#define pr_notice printk
+#define pr_cont printk
+
+#define pr_warn(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
+#define pr_err pr_warn
+#define pr_alert pr_warn
+#define pr_emerg pr_warn
+#define pr_crit pr_warn
+
+/*
+ * Dummy printk for disabled debugging statements to use whilst maintaining
+ * gcc's format checking.
+ */
+#define no_printk(fmt, ...)				\
+({							\
+	if (0)						\
+		printk(fmt, ##__VA_ARGS__);		\
+	0;						\
+})
+
+/* pr_devel() should produce zero code unless DEBUG is defined */
+#ifdef DEBUG
+#define pr_devel(fmt, ...) printk
+#else
+#define pr_devel(fmt, ...) no_printk
+#endif
+
+#define pr_debug pr_devel
+
+#endif /* _TOOLS_LINUX_KERNEL_PRINTK_H_ */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 02/37] tools: arm64: Make aarch64 instruction decoder available to tools
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 01/37] tools: Add some generic functions and headers Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 03/37] tools: bug: Remove duplicate definition Chen Zhongjin
                   ` (34 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

Add aarch64 encoder/decoder implementation under tools/ as well
as the necessary arm64 headers.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
---
 tools/arch/arm64/include/asm/insn.h |  565 +++++++++++
 tools/arch/arm64/lib/insn.c         | 1464 +++++++++++++++++++++++++++
 2 files changed, 2029 insertions(+)
 create mode 100644 tools/arch/arm64/include/asm/insn.h
 create mode 100644 tools/arch/arm64/lib/insn.c

diff --git a/tools/arch/arm64/include/asm/insn.h b/tools/arch/arm64/include/asm/insn.h
new file mode 100644
index 000000000000..71de52d1532f
--- /dev/null
+++ b/tools/arch/arm64/include/asm/insn.h
@@ -0,0 +1,565 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2013 Huawei Ltd.
+ * Author: Jiang Liu <liuj97@gmail.com>
+ *
+ * Copyright (C) 2014 Zi Shen Lim <zlim.lnx@gmail.com>
+ */
+#ifndef	__ASM_INSN_H
+#define	__ASM_INSN_H
+#include <linux/build_bug.h>
+#include <linux/types.h>
+
+/* A64 instructions are always 32 bits. */
+#define AARCH64_INSN_SIZE	4
+
+#ifndef __ASSEMBLY__
+/*
+ * ARM Architecture Reference Manual for ARMv8 Profile-A, Issue A.a
+ * Section C3.1 "A64 instruction index by encoding":
+ * AArch64 main encoding table
+ *  Bit position
+ *   28 27 26 25	Encoding Group
+ *   0  0  -  -		Unallocated
+ *   1  0  0  -		Data processing, immediate
+ *   1  0  1  -		Branch, exception generation and system instructions
+ *   -  1  -  0		Loads and stores
+ *   -  1  0  1		Data processing - register
+ *   0  1  1  1		Data processing - SIMD and floating point
+ *   1  1  1  1		Data processing - SIMD and floating point
+ * "-" means "don't care"
+ */
+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 */
+	AARCH64_INSN_CLS_LDST,		/* Loads and stores */
+	AARCH64_INSN_CLS_BR_SYS,	/* Branch, exception generation and
+					 * system instructions */
+};
+
+enum aarch64_insn_hint_cr_op {
+	AARCH64_INSN_HINT_NOP	= 0x0 << 5,
+	AARCH64_INSN_HINT_YIELD	= 0x1 << 5,
+	AARCH64_INSN_HINT_WFE	= 0x2 << 5,
+	AARCH64_INSN_HINT_WFI	= 0x3 << 5,
+	AARCH64_INSN_HINT_SEV	= 0x4 << 5,
+	AARCH64_INSN_HINT_SEVL	= 0x5 << 5,
+
+	AARCH64_INSN_HINT_XPACLRI    = 0x07 << 5,
+	AARCH64_INSN_HINT_PACIA_1716 = 0x08 << 5,
+	AARCH64_INSN_HINT_PACIB_1716 = 0x0A << 5,
+	AARCH64_INSN_HINT_AUTIA_1716 = 0x0C << 5,
+	AARCH64_INSN_HINT_AUTIB_1716 = 0x0E << 5,
+	AARCH64_INSN_HINT_PACIAZ     = 0x18 << 5,
+	AARCH64_INSN_HINT_PACIASP    = 0x19 << 5,
+	AARCH64_INSN_HINT_PACIBZ     = 0x1A << 5,
+	AARCH64_INSN_HINT_PACIBSP    = 0x1B << 5,
+	AARCH64_INSN_HINT_AUTIAZ     = 0x1C << 5,
+	AARCH64_INSN_HINT_AUTIASP    = 0x1D << 5,
+	AARCH64_INSN_HINT_AUTIBZ     = 0x1E << 5,
+	AARCH64_INSN_HINT_AUTIBSP    = 0x1F << 5,
+
+	AARCH64_INSN_HINT_ESB  = 0x10 << 5,
+	AARCH64_INSN_HINT_PSB  = 0x11 << 5,
+	AARCH64_INSN_HINT_TSB  = 0x12 << 5,
+	AARCH64_INSN_HINT_CSDB = 0x14 << 5,
+
+	AARCH64_INSN_HINT_BTI   = 0x20 << 5,
+	AARCH64_INSN_HINT_BTIC  = 0x22 << 5,
+	AARCH64_INSN_HINT_BTIJ  = 0x24 << 5,
+	AARCH64_INSN_HINT_BTIJC = 0x26 << 5,
+};
+
+enum aarch64_insn_imm_type {
+	AARCH64_INSN_IMM_ADR,
+	AARCH64_INSN_IMM_26,
+	AARCH64_INSN_IMM_19,
+	AARCH64_INSN_IMM_16,
+	AARCH64_INSN_IMM_14,
+	AARCH64_INSN_IMM_12,
+	AARCH64_INSN_IMM_9,
+	AARCH64_INSN_IMM_7,
+	AARCH64_INSN_IMM_6,
+	AARCH64_INSN_IMM_S,
+	AARCH64_INSN_IMM_R,
+	AARCH64_INSN_IMM_N,
+	AARCH64_INSN_IMM_MAX
+};
+
+enum aarch64_insn_register_type {
+	AARCH64_INSN_REGTYPE_RT,
+	AARCH64_INSN_REGTYPE_RN,
+	AARCH64_INSN_REGTYPE_RT2,
+	AARCH64_INSN_REGTYPE_RM,
+	AARCH64_INSN_REGTYPE_RD,
+	AARCH64_INSN_REGTYPE_RA,
+	AARCH64_INSN_REGTYPE_RS,
+};
+
+enum aarch64_insn_register {
+	AARCH64_INSN_REG_0  = 0,
+	AARCH64_INSN_REG_1  = 1,
+	AARCH64_INSN_REG_2  = 2,
+	AARCH64_INSN_REG_3  = 3,
+	AARCH64_INSN_REG_4  = 4,
+	AARCH64_INSN_REG_5  = 5,
+	AARCH64_INSN_REG_6  = 6,
+	AARCH64_INSN_REG_7  = 7,
+	AARCH64_INSN_REG_8  = 8,
+	AARCH64_INSN_REG_9  = 9,
+	AARCH64_INSN_REG_10 = 10,
+	AARCH64_INSN_REG_11 = 11,
+	AARCH64_INSN_REG_12 = 12,
+	AARCH64_INSN_REG_13 = 13,
+	AARCH64_INSN_REG_14 = 14,
+	AARCH64_INSN_REG_15 = 15,
+	AARCH64_INSN_REG_16 = 16,
+	AARCH64_INSN_REG_17 = 17,
+	AARCH64_INSN_REG_18 = 18,
+	AARCH64_INSN_REG_19 = 19,
+	AARCH64_INSN_REG_20 = 20,
+	AARCH64_INSN_REG_21 = 21,
+	AARCH64_INSN_REG_22 = 22,
+	AARCH64_INSN_REG_23 = 23,
+	AARCH64_INSN_REG_24 = 24,
+	AARCH64_INSN_REG_25 = 25,
+	AARCH64_INSN_REG_26 = 26,
+	AARCH64_INSN_REG_27 = 27,
+	AARCH64_INSN_REG_28 = 28,
+	AARCH64_INSN_REG_29 = 29,
+	AARCH64_INSN_REG_FP = 29, /* Frame pointer */
+	AARCH64_INSN_REG_30 = 30,
+	AARCH64_INSN_REG_LR = 30, /* Link register */
+	AARCH64_INSN_REG_ZR = 31, /* Zero: as source register */
+	AARCH64_INSN_REG_SP = 31  /* Stack pointer: as load/store base reg */
+};
+
+enum aarch64_insn_special_register {
+	AARCH64_INSN_SPCLREG_SPSR_EL1	= 0xC200,
+	AARCH64_INSN_SPCLREG_ELR_EL1	= 0xC201,
+	AARCH64_INSN_SPCLREG_SP_EL0	= 0xC208,
+	AARCH64_INSN_SPCLREG_SPSEL	= 0xC210,
+	AARCH64_INSN_SPCLREG_CURRENTEL	= 0xC212,
+	AARCH64_INSN_SPCLREG_DAIF	= 0xDA11,
+	AARCH64_INSN_SPCLREG_NZCV	= 0xDA10,
+	AARCH64_INSN_SPCLREG_FPCR	= 0xDA20,
+	AARCH64_INSN_SPCLREG_DSPSR_EL0	= 0xDA28,
+	AARCH64_INSN_SPCLREG_DLR_EL0	= 0xDA29,
+	AARCH64_INSN_SPCLREG_SPSR_EL2	= 0xE200,
+	AARCH64_INSN_SPCLREG_ELR_EL2	= 0xE201,
+	AARCH64_INSN_SPCLREG_SP_EL1	= 0xE208,
+	AARCH64_INSN_SPCLREG_SPSR_INQ	= 0xE218,
+	AARCH64_INSN_SPCLREG_SPSR_ABT	= 0xE219,
+	AARCH64_INSN_SPCLREG_SPSR_UND	= 0xE21A,
+	AARCH64_INSN_SPCLREG_SPSR_FIQ	= 0xE21B,
+	AARCH64_INSN_SPCLREG_SPSR_EL3	= 0xF200,
+	AARCH64_INSN_SPCLREG_ELR_EL3	= 0xF201,
+	AARCH64_INSN_SPCLREG_SP_EL2	= 0xF210
+};
+
+enum aarch64_insn_variant {
+	AARCH64_INSN_VARIANT_32BIT,
+	AARCH64_INSN_VARIANT_64BIT
+};
+
+enum aarch64_insn_condition {
+	AARCH64_INSN_COND_EQ = 0x0, /* == */
+	AARCH64_INSN_COND_NE = 0x1, /* != */
+	AARCH64_INSN_COND_CS = 0x2, /* unsigned >= */
+	AARCH64_INSN_COND_CC = 0x3, /* unsigned < */
+	AARCH64_INSN_COND_MI = 0x4, /* < 0 */
+	AARCH64_INSN_COND_PL = 0x5, /* >= 0 */
+	AARCH64_INSN_COND_VS = 0x6, /* overflow */
+	AARCH64_INSN_COND_VC = 0x7, /* no overflow */
+	AARCH64_INSN_COND_HI = 0x8, /* unsigned > */
+	AARCH64_INSN_COND_LS = 0x9, /* unsigned <= */
+	AARCH64_INSN_COND_GE = 0xa, /* signed >= */
+	AARCH64_INSN_COND_LT = 0xb, /* signed < */
+	AARCH64_INSN_COND_GT = 0xc, /* signed > */
+	AARCH64_INSN_COND_LE = 0xd, /* signed <= */
+	AARCH64_INSN_COND_AL = 0xe, /* always */
+};
+
+enum aarch64_insn_branch_type {
+	AARCH64_INSN_BRANCH_NOLINK,
+	AARCH64_INSN_BRANCH_LINK,
+	AARCH64_INSN_BRANCH_RETURN,
+	AARCH64_INSN_BRANCH_COMP_ZERO,
+	AARCH64_INSN_BRANCH_COMP_NONZERO,
+};
+
+enum aarch64_insn_size_type {
+	AARCH64_INSN_SIZE_8,
+	AARCH64_INSN_SIZE_16,
+	AARCH64_INSN_SIZE_32,
+	AARCH64_INSN_SIZE_64,
+};
+
+enum aarch64_insn_ldst_type {
+	AARCH64_INSN_LDST_LOAD_REG_OFFSET,
+	AARCH64_INSN_LDST_STORE_REG_OFFSET,
+	AARCH64_INSN_LDST_LOAD_PAIR_PRE_INDEX,
+	AARCH64_INSN_LDST_STORE_PAIR_PRE_INDEX,
+	AARCH64_INSN_LDST_LOAD_PAIR_POST_INDEX,
+	AARCH64_INSN_LDST_STORE_PAIR_POST_INDEX,
+	AARCH64_INSN_LDST_LOAD_EX,
+	AARCH64_INSN_LDST_STORE_EX,
+};
+
+enum aarch64_insn_adsb_type {
+	AARCH64_INSN_ADSB_ADD,
+	AARCH64_INSN_ADSB_SUB,
+	AARCH64_INSN_ADSB_ADD_SETFLAGS,
+	AARCH64_INSN_ADSB_SUB_SETFLAGS
+};
+
+enum aarch64_insn_movewide_type {
+	AARCH64_INSN_MOVEWIDE_ZERO,
+	AARCH64_INSN_MOVEWIDE_KEEP,
+	AARCH64_INSN_MOVEWIDE_INVERSE
+};
+
+enum aarch64_insn_bitfield_type {
+	AARCH64_INSN_BITFIELD_MOVE,
+	AARCH64_INSN_BITFIELD_MOVE_UNSIGNED,
+	AARCH64_INSN_BITFIELD_MOVE_SIGNED
+};
+
+enum aarch64_insn_data1_type {
+	AARCH64_INSN_DATA1_REVERSE_16,
+	AARCH64_INSN_DATA1_REVERSE_32,
+	AARCH64_INSN_DATA1_REVERSE_64,
+};
+
+enum aarch64_insn_data2_type {
+	AARCH64_INSN_DATA2_UDIV,
+	AARCH64_INSN_DATA2_SDIV,
+	AARCH64_INSN_DATA2_LSLV,
+	AARCH64_INSN_DATA2_LSRV,
+	AARCH64_INSN_DATA2_ASRV,
+	AARCH64_INSN_DATA2_RORV,
+};
+
+enum aarch64_insn_data3_type {
+	AARCH64_INSN_DATA3_MADD,
+	AARCH64_INSN_DATA3_MSUB,
+};
+
+enum aarch64_insn_logic_type {
+	AARCH64_INSN_LOGIC_AND,
+	AARCH64_INSN_LOGIC_BIC,
+	AARCH64_INSN_LOGIC_ORR,
+	AARCH64_INSN_LOGIC_ORN,
+	AARCH64_INSN_LOGIC_EOR,
+	AARCH64_INSN_LOGIC_EON,
+	AARCH64_INSN_LOGIC_AND_SETFLAGS,
+	AARCH64_INSN_LOGIC_BIC_SETFLAGS
+};
+
+enum aarch64_insn_prfm_type {
+	AARCH64_INSN_PRFM_TYPE_PLD,
+	AARCH64_INSN_PRFM_TYPE_PLI,
+	AARCH64_INSN_PRFM_TYPE_PST,
+};
+
+enum aarch64_insn_prfm_target {
+	AARCH64_INSN_PRFM_TARGET_L1,
+	AARCH64_INSN_PRFM_TARGET_L2,
+	AARCH64_INSN_PRFM_TARGET_L3,
+};
+
+enum aarch64_insn_prfm_policy {
+	AARCH64_INSN_PRFM_POLICY_KEEP,
+	AARCH64_INSN_PRFM_POLICY_STRM,
+};
+
+enum aarch64_insn_adr_type {
+	AARCH64_INSN_ADR_TYPE_ADRP,
+	AARCH64_INSN_ADR_TYPE_ADR,
+};
+
+#define	__AARCH64_INSN_FUNCS(abbr, mask, val)				\
+static __always_inline bool aarch64_insn_is_##abbr(u32 code)		\
+{									\
+	BUILD_BUG_ON(~(mask) & (val));					\
+	return (code & (mask)) == (val);				\
+}									\
+static __always_inline u32 aarch64_insn_get_##abbr##_value(void)	\
+{									\
+	return (val);							\
+}
+
+__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)
+__AARCH64_INSN_FUNCS(ldr_lit,	0xBF000000, 0x18000000)
+__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)
+__AARCH64_INSN_FUNCS(ldp_pre,	0x7FC00000, 0x29C00000)
+__AARCH64_INSN_FUNCS(add_imm,	0x7F000000, 0x11000000)
+__AARCH64_INSN_FUNCS(adds_imm,	0x7F000000, 0x31000000)
+__AARCH64_INSN_FUNCS(sub_imm,	0x7F000000, 0x51000000)
+__AARCH64_INSN_FUNCS(subs_imm,	0x7F000000, 0x71000000)
+__AARCH64_INSN_FUNCS(movn,	0x7F800000, 0x12800000)
+__AARCH64_INSN_FUNCS(sbfm,	0x7F800000, 0x13000000)
+__AARCH64_INSN_FUNCS(bfm,	0x7F800000, 0x33000000)
+__AARCH64_INSN_FUNCS(movz,	0x7F800000, 0x52800000)
+__AARCH64_INSN_FUNCS(ubfm,	0x7F800000, 0x53000000)
+__AARCH64_INSN_FUNCS(movk,	0x7F800000, 0x72800000)
+__AARCH64_INSN_FUNCS(add,	0x7F200000, 0x0B000000)
+__AARCH64_INSN_FUNCS(adds,	0x7F200000, 0x2B000000)
+__AARCH64_INSN_FUNCS(sub,	0x7F200000, 0x4B000000)
+__AARCH64_INSN_FUNCS(subs,	0x7F200000, 0x6B000000)
+__AARCH64_INSN_FUNCS(madd,	0x7FE08000, 0x1B000000)
+__AARCH64_INSN_FUNCS(msub,	0x7FE08000, 0x1B008000)
+__AARCH64_INSN_FUNCS(udiv,	0x7FE0FC00, 0x1AC00800)
+__AARCH64_INSN_FUNCS(sdiv,	0x7FE0FC00, 0x1AC00C00)
+__AARCH64_INSN_FUNCS(lslv,	0x7FE0FC00, 0x1AC02000)
+__AARCH64_INSN_FUNCS(lsrv,	0x7FE0FC00, 0x1AC02400)
+__AARCH64_INSN_FUNCS(asrv,	0x7FE0FC00, 0x1AC02800)
+__AARCH64_INSN_FUNCS(rorv,	0x7FE0FC00, 0x1AC02C00)
+__AARCH64_INSN_FUNCS(rev16,	0x7FFFFC00, 0x5AC00400)
+__AARCH64_INSN_FUNCS(rev32,	0x7FFFFC00, 0x5AC00800)
+__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)
+__AARCH64_INSN_FUNCS(ands,	0x7F200000, 0x6A000000)
+__AARCH64_INSN_FUNCS(bics,	0x7F200000, 0x6A200000)
+__AARCH64_INSN_FUNCS(and_imm,	0x7F800000, 0x12000000)
+__AARCH64_INSN_FUNCS(orr_imm,	0x7F800000, 0x32000000)
+__AARCH64_INSN_FUNCS(eor_imm,	0x7F800000, 0x52000000)
+__AARCH64_INSN_FUNCS(ands_imm,	0x7F800000, 0x72000000)
+__AARCH64_INSN_FUNCS(extr,	0x7FA00000, 0x13800000)
+__AARCH64_INSN_FUNCS(b,		0xFC000000, 0x14000000)
+__AARCH64_INSN_FUNCS(bl,	0xFC000000, 0x94000000)
+__AARCH64_INSN_FUNCS(cbz,	0x7F000000, 0x34000000)
+__AARCH64_INSN_FUNCS(cbnz,	0x7F000000, 0x35000000)
+__AARCH64_INSN_FUNCS(tbz,	0x7F000000, 0x36000000)
+__AARCH64_INSN_FUNCS(tbnz,	0x7F000000, 0x37000000)
+__AARCH64_INSN_FUNCS(bcond,	0xFF000010, 0x54000000)
+__AARCH64_INSN_FUNCS(svc,	0xFFE0001F, 0xD4000001)
+__AARCH64_INSN_FUNCS(hvc,	0xFFE0001F, 0xD4000002)
+__AARCH64_INSN_FUNCS(smc,	0xFFE0001F, 0xD4000003)
+__AARCH64_INSN_FUNCS(brk,	0xFFE0001F, 0xD4200000)
+__AARCH64_INSN_FUNCS(exception,	0xFF000000, 0xD4000000)
+__AARCH64_INSN_FUNCS(hint,	0xFFFFF01F, 0xD503201F)
+__AARCH64_INSN_FUNCS(br,	0xFFFFFC1F, 0xD61F0000)
+__AARCH64_INSN_FUNCS(br_auth,	0xFEFFF800, 0xD61F0800)
+__AARCH64_INSN_FUNCS(blr,	0xFFFFFC1F, 0xD63F0000)
+__AARCH64_INSN_FUNCS(blr_auth,	0xFEFFF800, 0xD63F0800)
+__AARCH64_INSN_FUNCS(ret,	0xFFFFFC1F, 0xD65F0000)
+__AARCH64_INSN_FUNCS(ret_auth,	0xFFFFFBFF, 0xD65F0BFF)
+__AARCH64_INSN_FUNCS(eret,	0xFFFFFFFF, 0xD69F03E0)
+__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
+
+bool aarch64_insn_is_steppable_hint(u32 insn);
+bool aarch64_insn_is_branch_imm(u32 insn);
+
+static inline bool aarch64_insn_is_adr_adrp(u32 insn)
+{
+	return aarch64_insn_is_adr(insn) || aarch64_insn_is_adrp(insn);
+}
+
+static inline bool aarch64_insn_is_dsb(u32 insn)
+{
+	return (aarch64_insn_is_dsb_base(insn) && (insn & 0xb00)) ||
+		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);
+u64 aarch64_insn_decode_immediate(enum aarch64_insn_imm_type type, u32 insn);
+u32 aarch64_insn_encode_immediate(enum aarch64_insn_imm_type type,
+				  u32 insn, u64 imm);
+u32 aarch64_insn_decode_register(enum aarch64_insn_register_type type,
+					 u32 insn);
+u32 aarch64_insn_gen_branch_imm(unsigned long pc, unsigned long addr,
+				enum aarch64_insn_branch_type type);
+u32 aarch64_insn_gen_comp_branch_imm(unsigned long pc, unsigned long addr,
+				     enum aarch64_insn_register reg,
+				     enum aarch64_insn_variant variant,
+				     enum aarch64_insn_branch_type type);
+u32 aarch64_insn_gen_cond_branch_imm(unsigned long pc, unsigned long addr,
+				     enum aarch64_insn_condition cond);
+u32 aarch64_insn_gen_hint(enum aarch64_insn_hint_cr_op op);
+u32 aarch64_insn_gen_nop(void);
+u32 aarch64_insn_gen_branch_reg(enum aarch64_insn_register reg,
+				enum aarch64_insn_branch_type type);
+u32 aarch64_insn_gen_load_store_reg(enum aarch64_insn_register reg,
+				    enum aarch64_insn_register base,
+				    enum aarch64_insn_register offset,
+				    enum aarch64_insn_size_type size,
+				    enum aarch64_insn_ldst_type type);
+u32 aarch64_insn_gen_load_store_pair(enum aarch64_insn_register reg1,
+				     enum aarch64_insn_register reg2,
+				     enum aarch64_insn_register base,
+				     int offset,
+				     enum aarch64_insn_variant variant,
+				     enum aarch64_insn_ldst_type type);
+u32 aarch64_insn_gen_load_store_ex(enum aarch64_insn_register reg,
+				   enum aarch64_insn_register base,
+				   enum aarch64_insn_register state,
+				   enum aarch64_insn_size_type size,
+				   enum aarch64_insn_ldst_type type);
+u32 aarch64_insn_gen_ldadd(enum aarch64_insn_register result,
+			   enum aarch64_insn_register address,
+			   enum aarch64_insn_register value,
+			   enum aarch64_insn_size_type size);
+u32 aarch64_insn_gen_stadd(enum aarch64_insn_register address,
+			   enum aarch64_insn_register value,
+			   enum aarch64_insn_size_type size);
+u32 aarch64_insn_gen_add_sub_imm(enum aarch64_insn_register dst,
+				 enum aarch64_insn_register src,
+				 int imm, enum aarch64_insn_variant variant,
+				 enum aarch64_insn_adsb_type type);
+u32 aarch64_insn_gen_adr(unsigned long pc, unsigned long addr,
+			 enum aarch64_insn_register reg,
+			 enum aarch64_insn_adr_type type);
+u32 aarch64_insn_gen_bitfield(enum aarch64_insn_register dst,
+			      enum aarch64_insn_register src,
+			      int immr, int imms,
+			      enum aarch64_insn_variant variant,
+			      enum aarch64_insn_bitfield_type type);
+u32 aarch64_insn_gen_movewide(enum aarch64_insn_register dst,
+			      int imm, int shift,
+			      enum aarch64_insn_variant variant,
+			      enum aarch64_insn_movewide_type type);
+u32 aarch64_insn_gen_add_sub_shifted_reg(enum aarch64_insn_register dst,
+					 enum aarch64_insn_register src,
+					 enum aarch64_insn_register reg,
+					 int shift,
+					 enum aarch64_insn_variant variant,
+					 enum aarch64_insn_adsb_type type);
+u32 aarch64_insn_gen_data1(enum aarch64_insn_register dst,
+			   enum aarch64_insn_register src,
+			   enum aarch64_insn_variant variant,
+			   enum aarch64_insn_data1_type type);
+u32 aarch64_insn_gen_data2(enum aarch64_insn_register dst,
+			   enum aarch64_insn_register src,
+			   enum aarch64_insn_register reg,
+			   enum aarch64_insn_variant variant,
+			   enum aarch64_insn_data2_type type);
+u32 aarch64_insn_gen_data3(enum aarch64_insn_register dst,
+			   enum aarch64_insn_register src,
+			   enum aarch64_insn_register reg1,
+			   enum aarch64_insn_register reg2,
+			   enum aarch64_insn_variant variant,
+			   enum aarch64_insn_data3_type type);
+u32 aarch64_insn_gen_logical_shifted_reg(enum aarch64_insn_register dst,
+					 enum aarch64_insn_register src,
+					 enum aarch64_insn_register reg,
+					 int shift,
+					 enum aarch64_insn_variant variant,
+					 enum aarch64_insn_logic_type type);
+u32 aarch64_insn_gen_move_reg(enum aarch64_insn_register dst,
+			      enum aarch64_insn_register src,
+			      enum aarch64_insn_variant variant);
+u32 aarch64_insn_gen_logical_immediate(enum aarch64_insn_logic_type type,
+				       enum aarch64_insn_variant variant,
+				       enum aarch64_insn_register Rn,
+				       enum aarch64_insn_register Rd,
+				       u64 imm);
+u32 aarch64_insn_gen_extr(enum aarch64_insn_variant variant,
+			  enum aarch64_insn_register Rm,
+			  enum aarch64_insn_register Rn,
+			  enum aarch64_insn_register Rd,
+			  u8 lsb);
+u32 aarch64_insn_gen_prefetch(enum aarch64_insn_register base,
+			      enum aarch64_insn_prfm_type type,
+			      enum aarch64_insn_prfm_target target,
+			      enum aarch64_insn_prfm_policy policy);
+s32 aarch64_get_branch_offset(u32 insn);
+u32 aarch64_set_branch_offset(u32 insn, s32 offset);
+
+s32 aarch64_insn_adrp_get_offset(u32 insn);
+u32 aarch64_insn_adrp_set_offset(u32 insn, s32 offset);
+
+bool aarch32_insn_is_wide(u32 insn);
+
+#define A32_RN_OFFSET	16
+#define A32_RT_OFFSET	12
+#define A32_RT2_OFFSET	 0
+
+u32 aarch64_insn_extract_system_reg(u32 insn);
+u32 aarch32_insn_extract_reg_num(u32 insn, int offset);
+u32 aarch32_insn_mcr_extract_opc2(u32 insn);
+u32 aarch32_insn_mcr_extract_crm(u32 insn);
+
+#endif /* __ASSEMBLY__ */
+
+#endif	/* __ASM_INSN_H */
diff --git a/tools/arch/arm64/lib/insn.c b/tools/arch/arm64/lib/insn.c
new file mode 100644
index 000000000000..00611d305eaf
--- /dev/null
+++ b/tools/arch/arm64/lib/insn.c
@@ -0,0 +1,1464 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2013 Huawei Ltd.
+ * Author: Jiang Liu <liuj97@gmail.com>
+ *
+ * Copyright (C) 2014-2016 Zi Shen Lim <zlim.lnx@gmail.com>
+ */
+#include <linux/bitops.h>
+#include <linux/bug.h>
+#include <linux/printk.h>
+#include <linux/sizes.h>
+#include <linux/types.h>
+
+#include <asm/errno.h>
+#include <asm/insn.h>
+
+/* Hack needed to avoid depending on debug-monitors.h */
+#define AARCH64_BREAK_FAULT	0xBAD
+
+/* Hack needed to avoid depending on kprobes.h */
+#ifndef __kprobes
+#define __kprobes
+#endif
+
+#define AARCH64_INSN_SF_BIT	BIT(31)
+#define AARCH64_INSN_N_BIT	BIT(22)
+#define AARCH64_INSN_LSL_12	BIT(22)
+
+static const int aarch64_insn_encoding_class[] = {
+	AARCH64_INSN_CLS_UNKNOWN,
+	AARCH64_INSN_CLS_UNKNOWN,
+	AARCH64_INSN_CLS_SVE,
+	AARCH64_INSN_CLS_UNKNOWN,
+	AARCH64_INSN_CLS_LDST,
+	AARCH64_INSN_CLS_DP_REG,
+	AARCH64_INSN_CLS_LDST,
+	AARCH64_INSN_CLS_DP_FPSIMD,
+	AARCH64_INSN_CLS_DP_IMM,
+	AARCH64_INSN_CLS_DP_IMM,
+	AARCH64_INSN_CLS_BR_SYS,
+	AARCH64_INSN_CLS_BR_SYS,
+	AARCH64_INSN_CLS_LDST,
+	AARCH64_INSN_CLS_DP_REG,
+	AARCH64_INSN_CLS_LDST,
+	AARCH64_INSN_CLS_DP_FPSIMD,
+};
+
+enum aarch64_insn_encoding_class __kprobes aarch64_get_insn_class(u32 insn)
+{
+	return aarch64_insn_encoding_class[(insn >> 25) & 0xf];
+}
+
+bool __kprobes aarch64_insn_is_steppable_hint(u32 insn)
+{
+	if (!aarch64_insn_is_hint(insn))
+		return false;
+
+	switch (insn & 0xFE0) {
+	case AARCH64_INSN_HINT_XPACLRI:
+	case AARCH64_INSN_HINT_PACIA_1716:
+	case AARCH64_INSN_HINT_PACIB_1716:
+	case AARCH64_INSN_HINT_PACIAZ:
+	case AARCH64_INSN_HINT_PACIASP:
+	case AARCH64_INSN_HINT_PACIBZ:
+	case AARCH64_INSN_HINT_PACIBSP:
+	case AARCH64_INSN_HINT_BTI:
+	case AARCH64_INSN_HINT_BTIC:
+	case AARCH64_INSN_HINT_BTIJ:
+	case AARCH64_INSN_HINT_BTIJC:
+	case AARCH64_INSN_HINT_NOP:
+		return true;
+	default:
+		return false;
+	}
+}
+
+bool aarch64_insn_is_branch_imm(u32 insn)
+{
+	return (aarch64_insn_is_b(insn) || aarch64_insn_is_bl(insn) ||
+		aarch64_insn_is_tbz(insn) || aarch64_insn_is_tbnz(insn) ||
+		aarch64_insn_is_cbz(insn) || aarch64_insn_is_cbnz(insn) ||
+		aarch64_insn_is_bcond(insn));
+}
+
+bool __kprobes aarch64_insn_uses_literal(u32 insn)
+{
+	/* ldr/ldrsw (literal), prfm */
+
+	return aarch64_insn_is_ldr_lit(insn) ||
+		aarch64_insn_is_ldrsw_lit(insn) ||
+		aarch64_insn_is_adr_adrp(insn) ||
+		aarch64_insn_is_prfm_lit(insn);
+}
+
+bool __kprobes aarch64_insn_is_branch(u32 insn)
+{
+	/* b, bl, cb*, tb*, ret*, b.cond, br*, blr* */
+
+	return aarch64_insn_is_b(insn) ||
+		aarch64_insn_is_bl(insn) ||
+		aarch64_insn_is_cbz(insn) ||
+		aarch64_insn_is_cbnz(insn) ||
+		aarch64_insn_is_tbz(insn) ||
+		aarch64_insn_is_tbnz(insn) ||
+		aarch64_insn_is_ret(insn) ||
+		aarch64_insn_is_ret_auth(insn) ||
+		aarch64_insn_is_br(insn) ||
+		aarch64_insn_is_br_auth(insn) ||
+		aarch64_insn_is_blr(insn) ||
+		aarch64_insn_is_blr_auth(insn) ||
+		aarch64_insn_is_bcond(insn);
+}
+
+static int __kprobes aarch64_get_imm_shift_mask(enum aarch64_insn_imm_type type,
+						u32 *maskp, int *shiftp)
+{
+	u32 mask;
+	int shift;
+
+	switch (type) {
+	case AARCH64_INSN_IMM_26:
+		mask = BIT(26) - 1;
+		shift = 0;
+		break;
+	case AARCH64_INSN_IMM_19:
+		mask = BIT(19) - 1;
+		shift = 5;
+		break;
+	case AARCH64_INSN_IMM_16:
+		mask = BIT(16) - 1;
+		shift = 5;
+		break;
+	case AARCH64_INSN_IMM_14:
+		mask = BIT(14) - 1;
+		shift = 5;
+		break;
+	case AARCH64_INSN_IMM_12:
+		mask = BIT(12) - 1;
+		shift = 10;
+		break;
+	case AARCH64_INSN_IMM_9:
+		mask = BIT(9) - 1;
+		shift = 12;
+		break;
+	case AARCH64_INSN_IMM_7:
+		mask = BIT(7) - 1;
+		shift = 15;
+		break;
+	case AARCH64_INSN_IMM_6:
+	case AARCH64_INSN_IMM_S:
+		mask = BIT(6) - 1;
+		shift = 10;
+		break;
+	case AARCH64_INSN_IMM_R:
+		mask = BIT(6) - 1;
+		shift = 16;
+		break;
+	case AARCH64_INSN_IMM_N:
+		mask = 1;
+		shift = 22;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	*maskp = mask;
+	*shiftp = shift;
+
+	return 0;
+}
+
+#define ADR_IMM_HILOSPLIT	2
+#define ADR_IMM_SIZE		SZ_2M
+#define ADR_IMM_LOMASK		((1 << ADR_IMM_HILOSPLIT) - 1)
+#define ADR_IMM_HIMASK		((ADR_IMM_SIZE >> ADR_IMM_HILOSPLIT) - 1)
+#define ADR_IMM_LOSHIFT		29
+#define ADR_IMM_HISHIFT		5
+
+u64 aarch64_insn_decode_immediate(enum aarch64_insn_imm_type type, u32 insn)
+{
+	u32 immlo, immhi, mask;
+	int shift;
+
+	switch (type) {
+	case AARCH64_INSN_IMM_ADR:
+		shift = 0;
+		immlo = (insn >> ADR_IMM_LOSHIFT) & ADR_IMM_LOMASK;
+		immhi = (insn >> ADR_IMM_HISHIFT) & ADR_IMM_HIMASK;
+		insn = (immhi << ADR_IMM_HILOSPLIT) | immlo;
+		mask = ADR_IMM_SIZE - 1;
+		break;
+	default:
+		if (aarch64_get_imm_shift_mask(type, &mask, &shift) < 0) {
+			pr_err("aarch64_insn_decode_immediate: unknown immediate encoding %d\n",
+			       type);
+			return 0;
+		}
+	}
+
+	return (insn >> shift) & mask;
+}
+
+u32 __kprobes aarch64_insn_encode_immediate(enum aarch64_insn_imm_type type,
+				  u32 insn, u64 imm)
+{
+	u32 immlo, immhi, mask;
+	int shift;
+
+	if (insn == AARCH64_BREAK_FAULT)
+		return AARCH64_BREAK_FAULT;
+
+	switch (type) {
+	case AARCH64_INSN_IMM_ADR:
+		shift = 0;
+		immlo = (imm & ADR_IMM_LOMASK) << ADR_IMM_LOSHIFT;
+		imm >>= ADR_IMM_HILOSPLIT;
+		immhi = (imm & ADR_IMM_HIMASK) << ADR_IMM_HISHIFT;
+		imm = immlo | immhi;
+		mask = ((ADR_IMM_LOMASK << ADR_IMM_LOSHIFT) |
+			(ADR_IMM_HIMASK << ADR_IMM_HISHIFT));
+		break;
+	default:
+		if (aarch64_get_imm_shift_mask(type, &mask, &shift) < 0) {
+			pr_err("aarch64_insn_encode_immediate: unknown immediate encoding %d\n",
+			       type);
+			return AARCH64_BREAK_FAULT;
+		}
+	}
+
+	/* Update the immediate field. */
+	insn &= ~(mask << shift);
+	insn |= (imm & mask) << shift;
+
+	return insn;
+}
+
+u32 aarch64_insn_decode_register(enum aarch64_insn_register_type type,
+					u32 insn)
+{
+	int shift;
+
+	switch (type) {
+	case AARCH64_INSN_REGTYPE_RT:
+	case AARCH64_INSN_REGTYPE_RD:
+		shift = 0;
+		break;
+	case AARCH64_INSN_REGTYPE_RN:
+		shift = 5;
+		break;
+	case AARCH64_INSN_REGTYPE_RT2:
+	case AARCH64_INSN_REGTYPE_RA:
+		shift = 10;
+		break;
+	case AARCH64_INSN_REGTYPE_RM:
+		shift = 16;
+		break;
+	default:
+		pr_err("%s: unknown register type encoding %d\n", __func__,
+		       type);
+		return 0;
+	}
+
+	return (insn >> shift) & GENMASK(4, 0);
+}
+
+static u32 aarch64_insn_encode_register(enum aarch64_insn_register_type type,
+					u32 insn,
+					enum aarch64_insn_register reg)
+{
+	int shift;
+
+	if (insn == AARCH64_BREAK_FAULT)
+		return AARCH64_BREAK_FAULT;
+
+	if (reg < AARCH64_INSN_REG_0 || reg > AARCH64_INSN_REG_SP) {
+		pr_err("%s: unknown register encoding %d\n", __func__, reg);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	switch (type) {
+	case AARCH64_INSN_REGTYPE_RT:
+	case AARCH64_INSN_REGTYPE_RD:
+		shift = 0;
+		break;
+	case AARCH64_INSN_REGTYPE_RN:
+		shift = 5;
+		break;
+	case AARCH64_INSN_REGTYPE_RT2:
+	case AARCH64_INSN_REGTYPE_RA:
+		shift = 10;
+		break;
+	case AARCH64_INSN_REGTYPE_RM:
+	case AARCH64_INSN_REGTYPE_RS:
+		shift = 16;
+		break;
+	default:
+		pr_err("%s: unknown register type encoding %d\n", __func__,
+		       type);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	insn &= ~(GENMASK(4, 0) << shift);
+	insn |= reg << shift;
+
+	return insn;
+}
+
+static u32 aarch64_insn_encode_ldst_size(enum aarch64_insn_size_type type,
+					 u32 insn)
+{
+	u32 size;
+
+	switch (type) {
+	case AARCH64_INSN_SIZE_8:
+		size = 0;
+		break;
+	case AARCH64_INSN_SIZE_16:
+		size = 1;
+		break;
+	case AARCH64_INSN_SIZE_32:
+		size = 2;
+		break;
+	case AARCH64_INSN_SIZE_64:
+		size = 3;
+		break;
+	default:
+		pr_err("%s: unknown size encoding %d\n", __func__, type);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	insn &= ~GENMASK(31, 30);
+	insn |= size << 30;
+
+	return insn;
+}
+
+static inline long branch_imm_common(unsigned long pc, unsigned long addr,
+				     long range)
+{
+	long offset;
+
+	if ((pc & 0x3) || (addr & 0x3)) {
+		pr_err("%s: A64 instructions must be word aligned\n", __func__);
+		return range;
+	}
+
+	offset = ((long)addr - (long)pc);
+
+	if (offset < -range || offset >= range) {
+		pr_err("%s: offset out of range\n", __func__);
+		return range;
+	}
+
+	return offset;
+}
+
+u32 __kprobes aarch64_insn_gen_branch_imm(unsigned long pc, unsigned long addr,
+					  enum aarch64_insn_branch_type type)
+{
+	u32 insn;
+	long offset;
+
+	/*
+	 * B/BL support [-128M, 128M) offset
+	 * ARM64 virtual address arrangement guarantees all kernel and module
+	 * texts are within +/-128M.
+	 */
+	offset = branch_imm_common(pc, addr, SZ_128M);
+	if (offset >= SZ_128M)
+		return AARCH64_BREAK_FAULT;
+
+	switch (type) {
+	case AARCH64_INSN_BRANCH_LINK:
+		insn = aarch64_insn_get_bl_value();
+		break;
+	case AARCH64_INSN_BRANCH_NOLINK:
+		insn = aarch64_insn_get_b_value();
+		break;
+	default:
+		pr_err("%s: unknown branch encoding %d\n", __func__, type);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_26, insn,
+					     offset >> 2);
+}
+
+u32 aarch64_insn_gen_comp_branch_imm(unsigned long pc, unsigned long addr,
+				     enum aarch64_insn_register reg,
+				     enum aarch64_insn_variant variant,
+				     enum aarch64_insn_branch_type type)
+{
+	u32 insn;
+	long offset;
+
+	offset = branch_imm_common(pc, addr, SZ_1M);
+	if (offset >= SZ_1M)
+		return AARCH64_BREAK_FAULT;
+
+	switch (type) {
+	case AARCH64_INSN_BRANCH_COMP_ZERO:
+		insn = aarch64_insn_get_cbz_value();
+		break;
+	case AARCH64_INSN_BRANCH_COMP_NONZERO:
+		insn = aarch64_insn_get_cbnz_value();
+		break;
+	default:
+		pr_err("%s: unknown branch encoding %d\n", __func__, type);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	switch (variant) {
+	case AARCH64_INSN_VARIANT_32BIT:
+		break;
+	case AARCH64_INSN_VARIANT_64BIT:
+		insn |= AARCH64_INSN_SF_BIT;
+		break;
+	default:
+		pr_err("%s: unknown variant encoding %d\n", __func__, variant);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT, insn, reg);
+
+	return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_19, insn,
+					     offset >> 2);
+}
+
+u32 aarch64_insn_gen_cond_branch_imm(unsigned long pc, unsigned long addr,
+				     enum aarch64_insn_condition cond)
+{
+	u32 insn;
+	long offset;
+
+	offset = branch_imm_common(pc, addr, SZ_1M);
+
+	insn = aarch64_insn_get_bcond_value();
+
+	if (cond < AARCH64_INSN_COND_EQ || cond > AARCH64_INSN_COND_AL) {
+		pr_err("%s: unknown condition encoding %d\n", __func__, cond);
+		return AARCH64_BREAK_FAULT;
+	}
+	insn |= cond;
+
+	return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_19, insn,
+					     offset >> 2);
+}
+
+u32 __kprobes aarch64_insn_gen_hint(enum aarch64_insn_hint_cr_op op)
+{
+	return aarch64_insn_get_hint_value() | op;
+}
+
+u32 __kprobes aarch64_insn_gen_nop(void)
+{
+	return aarch64_insn_gen_hint(AARCH64_INSN_HINT_NOP);
+}
+
+u32 aarch64_insn_gen_branch_reg(enum aarch64_insn_register reg,
+				enum aarch64_insn_branch_type type)
+{
+	u32 insn;
+
+	switch (type) {
+	case AARCH64_INSN_BRANCH_NOLINK:
+		insn = aarch64_insn_get_br_value();
+		break;
+	case AARCH64_INSN_BRANCH_LINK:
+		insn = aarch64_insn_get_blr_value();
+		break;
+	case AARCH64_INSN_BRANCH_RETURN:
+		insn = aarch64_insn_get_ret_value();
+		break;
+	default:
+		pr_err("%s: unknown branch encoding %d\n", __func__, type);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, reg);
+}
+
+u32 aarch64_insn_gen_load_store_reg(enum aarch64_insn_register reg,
+				    enum aarch64_insn_register base,
+				    enum aarch64_insn_register offset,
+				    enum aarch64_insn_size_type size,
+				    enum aarch64_insn_ldst_type type)
+{
+	u32 insn;
+
+	switch (type) {
+	case AARCH64_INSN_LDST_LOAD_REG_OFFSET:
+		insn = aarch64_insn_get_ldr_reg_value();
+		break;
+	case AARCH64_INSN_LDST_STORE_REG_OFFSET:
+		insn = aarch64_insn_get_str_reg_value();
+		break;
+	default:
+		pr_err("%s: unknown load/store encoding %d\n", __func__, type);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	insn = aarch64_insn_encode_ldst_size(size, insn);
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT, insn, reg);
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn,
+					    base);
+
+	return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn,
+					    offset);
+}
+
+u32 aarch64_insn_gen_load_store_pair(enum aarch64_insn_register reg1,
+				     enum aarch64_insn_register reg2,
+				     enum aarch64_insn_register base,
+				     int offset,
+				     enum aarch64_insn_variant variant,
+				     enum aarch64_insn_ldst_type type)
+{
+	u32 insn;
+	int shift;
+
+	switch (type) {
+	case AARCH64_INSN_LDST_LOAD_PAIR_PRE_INDEX:
+		insn = aarch64_insn_get_ldp_pre_value();
+		break;
+	case AARCH64_INSN_LDST_STORE_PAIR_PRE_INDEX:
+		insn = aarch64_insn_get_stp_pre_value();
+		break;
+	case AARCH64_INSN_LDST_LOAD_PAIR_POST_INDEX:
+		insn = aarch64_insn_get_ldp_post_value();
+		break;
+	case AARCH64_INSN_LDST_STORE_PAIR_POST_INDEX:
+		insn = aarch64_insn_get_stp_post_value();
+		break;
+	default:
+		pr_err("%s: unknown load/store encoding %d\n", __func__, type);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	switch (variant) {
+	case AARCH64_INSN_VARIANT_32BIT:
+		if ((offset & 0x3) || (offset < -256) || (offset > 252)) {
+			pr_err("%s: offset must be multiples of 4 in the range of [-256, 252] %d\n",
+			       __func__, offset);
+			return AARCH64_BREAK_FAULT;
+		}
+		shift = 2;
+		break;
+	case AARCH64_INSN_VARIANT_64BIT:
+		if ((offset & 0x7) || (offset < -512) || (offset > 504)) {
+			pr_err("%s: offset must be multiples of 8 in the range of [-512, 504] %d\n",
+			       __func__, offset);
+			return AARCH64_BREAK_FAULT;
+		}
+		shift = 3;
+		insn |= AARCH64_INSN_SF_BIT;
+		break;
+	default:
+		pr_err("%s: unknown variant encoding %d\n", __func__, variant);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT, insn,
+					    reg1);
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT2, insn,
+					    reg2);
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn,
+					    base);
+
+	return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_7, insn,
+					     offset >> shift);
+}
+
+u32 aarch64_insn_gen_load_store_ex(enum aarch64_insn_register reg,
+				   enum aarch64_insn_register base,
+				   enum aarch64_insn_register state,
+				   enum aarch64_insn_size_type size,
+				   enum aarch64_insn_ldst_type type)
+{
+	u32 insn;
+
+	switch (type) {
+	case AARCH64_INSN_LDST_LOAD_EX:
+		insn = aarch64_insn_get_load_ex_value();
+		break;
+	case AARCH64_INSN_LDST_STORE_EX:
+		insn = aarch64_insn_get_store_ex_value();
+		break;
+	default:
+		pr_err("%s: unknown load/store exclusive encoding %d\n", __func__, type);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	insn = aarch64_insn_encode_ldst_size(size, insn);
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT, insn,
+					    reg);
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn,
+					    base);
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT2, insn,
+					    AARCH64_INSN_REG_ZR);
+
+	return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RS, insn,
+					    state);
+}
+
+u32 aarch64_insn_gen_ldadd(enum aarch64_insn_register result,
+			   enum aarch64_insn_register address,
+			   enum aarch64_insn_register value,
+			   enum aarch64_insn_size_type size)
+{
+	u32 insn = aarch64_insn_get_ldadd_value();
+
+	switch (size) {
+	case AARCH64_INSN_SIZE_32:
+	case AARCH64_INSN_SIZE_64:
+		break;
+	default:
+		pr_err("%s: unimplemented size encoding %d\n", __func__, size);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	insn = aarch64_insn_encode_ldst_size(size, insn);
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT, insn,
+					    result);
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn,
+					    address);
+
+	return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RS, insn,
+					    value);
+}
+
+u32 aarch64_insn_gen_stadd(enum aarch64_insn_register address,
+			   enum aarch64_insn_register value,
+			   enum aarch64_insn_size_type size)
+{
+	/*
+	 * STADD is simply encoded as an alias for LDADD with XZR as
+	 * the destination register.
+	 */
+	return aarch64_insn_gen_ldadd(AARCH64_INSN_REG_ZR, address,
+				      value, size);
+}
+
+static u32 aarch64_insn_encode_prfm_imm(enum aarch64_insn_prfm_type type,
+					enum aarch64_insn_prfm_target target,
+					enum aarch64_insn_prfm_policy policy,
+					u32 insn)
+{
+	u32 imm_type = 0, imm_target = 0, imm_policy = 0;
+
+	switch (type) {
+	case AARCH64_INSN_PRFM_TYPE_PLD:
+		break;
+	case AARCH64_INSN_PRFM_TYPE_PLI:
+		imm_type = BIT(0);
+		break;
+	case AARCH64_INSN_PRFM_TYPE_PST:
+		imm_type = BIT(1);
+		break;
+	default:
+		pr_err("%s: unknown prfm type encoding %d\n", __func__, type);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	switch (target) {
+	case AARCH64_INSN_PRFM_TARGET_L1:
+		break;
+	case AARCH64_INSN_PRFM_TARGET_L2:
+		imm_target = BIT(0);
+		break;
+	case AARCH64_INSN_PRFM_TARGET_L3:
+		imm_target = BIT(1);
+		break;
+	default:
+		pr_err("%s: unknown prfm target encoding %d\n", __func__, target);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	switch (policy) {
+	case AARCH64_INSN_PRFM_POLICY_KEEP:
+		break;
+	case AARCH64_INSN_PRFM_POLICY_STRM:
+		imm_policy = BIT(0);
+		break;
+	default:
+		pr_err("%s: unknown prfm policy encoding %d\n", __func__, policy);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	/* In this case, imm5 is encoded into Rt field. */
+	insn &= ~GENMASK(4, 0);
+	insn |= imm_policy | (imm_target << 1) | (imm_type << 3);
+
+	return insn;
+}
+
+u32 aarch64_insn_gen_prefetch(enum aarch64_insn_register base,
+			      enum aarch64_insn_prfm_type type,
+			      enum aarch64_insn_prfm_target target,
+			      enum aarch64_insn_prfm_policy policy)
+{
+	u32 insn = aarch64_insn_get_prfm_value();
+
+	insn = aarch64_insn_encode_ldst_size(AARCH64_INSN_SIZE_64, insn);
+
+	insn = aarch64_insn_encode_prfm_imm(type, target, policy, insn);
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn,
+					    base);
+
+	return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_12, insn, 0);
+}
+
+u32 aarch64_insn_gen_add_sub_imm(enum aarch64_insn_register dst,
+				 enum aarch64_insn_register src,
+				 int imm, enum aarch64_insn_variant variant,
+				 enum aarch64_insn_adsb_type type)
+{
+	u32 insn;
+
+	switch (type) {
+	case AARCH64_INSN_ADSB_ADD:
+		insn = aarch64_insn_get_add_imm_value();
+		break;
+	case AARCH64_INSN_ADSB_SUB:
+		insn = aarch64_insn_get_sub_imm_value();
+		break;
+	case AARCH64_INSN_ADSB_ADD_SETFLAGS:
+		insn = aarch64_insn_get_adds_imm_value();
+		break;
+	case AARCH64_INSN_ADSB_SUB_SETFLAGS:
+		insn = aarch64_insn_get_subs_imm_value();
+		break;
+	default:
+		pr_err("%s: unknown add/sub encoding %d\n", __func__, type);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	switch (variant) {
+	case AARCH64_INSN_VARIANT_32BIT:
+		break;
+	case AARCH64_INSN_VARIANT_64BIT:
+		insn |= AARCH64_INSN_SF_BIT;
+		break;
+	default:
+		pr_err("%s: unknown variant encoding %d\n", __func__, variant);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	/* We can't encode more than a 24bit value (12bit + 12bit shift) */
+	if (imm & ~(BIT(24) - 1))
+		goto out;
+
+	/* If we have something in the top 12 bits... */
+	if (imm & ~(SZ_4K - 1)) {
+		/* ... and in the low 12 bits -> error */
+		if (imm & (SZ_4K - 1))
+			goto out;
+
+		imm >>= 12;
+		insn |= AARCH64_INSN_LSL_12;
+	}
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst);
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, src);
+
+	return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_12, insn, imm);
+
+out:
+	pr_err("%s: invalid immediate encoding %d\n", __func__, imm);
+	return AARCH64_BREAK_FAULT;
+}
+
+u32 aarch64_insn_gen_bitfield(enum aarch64_insn_register dst,
+			      enum aarch64_insn_register src,
+			      int immr, int imms,
+			      enum aarch64_insn_variant variant,
+			      enum aarch64_insn_bitfield_type type)
+{
+	u32 insn;
+	u32 mask;
+
+	switch (type) {
+	case AARCH64_INSN_BITFIELD_MOVE:
+		insn = aarch64_insn_get_bfm_value();
+		break;
+	case AARCH64_INSN_BITFIELD_MOVE_UNSIGNED:
+		insn = aarch64_insn_get_ubfm_value();
+		break;
+	case AARCH64_INSN_BITFIELD_MOVE_SIGNED:
+		insn = aarch64_insn_get_sbfm_value();
+		break;
+	default:
+		pr_err("%s: unknown bitfield encoding %d\n", __func__, type);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	switch (variant) {
+	case AARCH64_INSN_VARIANT_32BIT:
+		mask = GENMASK(4, 0);
+		break;
+	case AARCH64_INSN_VARIANT_64BIT:
+		insn |= AARCH64_INSN_SF_BIT | AARCH64_INSN_N_BIT;
+		mask = GENMASK(5, 0);
+		break;
+	default:
+		pr_err("%s: unknown variant encoding %d\n", __func__, variant);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	if (immr & ~mask) {
+		pr_err("%s: invalid immr encoding %d\n", __func__, immr);
+		return AARCH64_BREAK_FAULT;
+	}
+	if (imms & ~mask) {
+		pr_err("%s: invalid imms encoding %d\n", __func__, imms);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst);
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, src);
+
+	insn = aarch64_insn_encode_immediate(AARCH64_INSN_IMM_R, insn, immr);
+
+	return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_S, insn, imms);
+}
+
+u32 aarch64_insn_gen_movewide(enum aarch64_insn_register dst,
+			      int imm, int shift,
+			      enum aarch64_insn_variant variant,
+			      enum aarch64_insn_movewide_type type)
+{
+	u32 insn;
+
+	switch (type) {
+	case AARCH64_INSN_MOVEWIDE_ZERO:
+		insn = aarch64_insn_get_movz_value();
+		break;
+	case AARCH64_INSN_MOVEWIDE_KEEP:
+		insn = aarch64_insn_get_movk_value();
+		break;
+	case AARCH64_INSN_MOVEWIDE_INVERSE:
+		insn = aarch64_insn_get_movn_value();
+		break;
+	default:
+		pr_err("%s: unknown movewide encoding %d\n", __func__, type);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	if (imm & ~(SZ_64K - 1)) {
+		pr_err("%s: invalid immediate encoding %d\n", __func__, imm);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	switch (variant) {
+	case AARCH64_INSN_VARIANT_32BIT:
+		if (shift != 0 && shift != 16) {
+			pr_err("%s: invalid shift encoding %d\n", __func__,
+			       shift);
+			return AARCH64_BREAK_FAULT;
+		}
+		break;
+	case AARCH64_INSN_VARIANT_64BIT:
+		insn |= AARCH64_INSN_SF_BIT;
+		if (shift != 0 && shift != 16 && shift != 32 && shift != 48) {
+			pr_err("%s: invalid shift encoding %d\n", __func__,
+			       shift);
+			return AARCH64_BREAK_FAULT;
+		}
+		break;
+	default:
+		pr_err("%s: unknown variant encoding %d\n", __func__, variant);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	insn |= (shift >> 4) << 21;
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst);
+
+	return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_16, insn, imm);
+}
+
+u32 aarch64_insn_gen_add_sub_shifted_reg(enum aarch64_insn_register dst,
+					 enum aarch64_insn_register src,
+					 enum aarch64_insn_register reg,
+					 int shift,
+					 enum aarch64_insn_variant variant,
+					 enum aarch64_insn_adsb_type type)
+{
+	u32 insn;
+
+	switch (type) {
+	case AARCH64_INSN_ADSB_ADD:
+		insn = aarch64_insn_get_add_value();
+		break;
+	case AARCH64_INSN_ADSB_SUB:
+		insn = aarch64_insn_get_sub_value();
+		break;
+	case AARCH64_INSN_ADSB_ADD_SETFLAGS:
+		insn = aarch64_insn_get_adds_value();
+		break;
+	case AARCH64_INSN_ADSB_SUB_SETFLAGS:
+		insn = aarch64_insn_get_subs_value();
+		break;
+	default:
+		pr_err("%s: unknown add/sub encoding %d\n", __func__, type);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	switch (variant) {
+	case AARCH64_INSN_VARIANT_32BIT:
+		if (shift & ~(SZ_32 - 1)) {
+			pr_err("%s: invalid shift encoding %d\n", __func__,
+			       shift);
+			return AARCH64_BREAK_FAULT;
+		}
+		break;
+	case AARCH64_INSN_VARIANT_64BIT:
+		insn |= AARCH64_INSN_SF_BIT;
+		if (shift & ~(SZ_64 - 1)) {
+			pr_err("%s: invalid shift encoding %d\n", __func__,
+			       shift);
+			return AARCH64_BREAK_FAULT;
+		}
+		break;
+	default:
+		pr_err("%s: unknown variant encoding %d\n", __func__, variant);
+		return AARCH64_BREAK_FAULT;
+	}
+
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst);
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, src);
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn, reg);
+
+	return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_6, insn, shift);
+}
+
+u32 aarch64_insn_gen_data1(enum aarch64_insn_register dst,
+			   enum aarch64_insn_register src,
+			   enum aarch64_insn_variant variant,
+			   enum aarch64_insn_data1_type type)
+{
+	u32 insn;
+
+	switch (type) {
+	case AARCH64_INSN_DATA1_REVERSE_16:
+		insn = aarch64_insn_get_rev16_value();
+		break;
+	case AARCH64_INSN_DATA1_REVERSE_32:
+		insn = aarch64_insn_get_rev32_value();
+		break;
+	case AARCH64_INSN_DATA1_REVERSE_64:
+		if (variant != AARCH64_INSN_VARIANT_64BIT) {
+			pr_err("%s: invalid variant for reverse64 %d\n",
+			       __func__, variant);
+			return AARCH64_BREAK_FAULT;
+		}
+		insn = aarch64_insn_get_rev64_value();
+		break;
+	default:
+		pr_err("%s: unknown data1 encoding %d\n", __func__, type);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	switch (variant) {
+	case AARCH64_INSN_VARIANT_32BIT:
+		break;
+	case AARCH64_INSN_VARIANT_64BIT:
+		insn |= AARCH64_INSN_SF_BIT;
+		break;
+	default:
+		pr_err("%s: unknown variant encoding %d\n", __func__, variant);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst);
+
+	return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, src);
+}
+
+u32 aarch64_insn_gen_data2(enum aarch64_insn_register dst,
+			   enum aarch64_insn_register src,
+			   enum aarch64_insn_register reg,
+			   enum aarch64_insn_variant variant,
+			   enum aarch64_insn_data2_type type)
+{
+	u32 insn;
+
+	switch (type) {
+	case AARCH64_INSN_DATA2_UDIV:
+		insn = aarch64_insn_get_udiv_value();
+		break;
+	case AARCH64_INSN_DATA2_SDIV:
+		insn = aarch64_insn_get_sdiv_value();
+		break;
+	case AARCH64_INSN_DATA2_LSLV:
+		insn = aarch64_insn_get_lslv_value();
+		break;
+	case AARCH64_INSN_DATA2_LSRV:
+		insn = aarch64_insn_get_lsrv_value();
+		break;
+	case AARCH64_INSN_DATA2_ASRV:
+		insn = aarch64_insn_get_asrv_value();
+		break;
+	case AARCH64_INSN_DATA2_RORV:
+		insn = aarch64_insn_get_rorv_value();
+		break;
+	default:
+		pr_err("%s: unknown data2 encoding %d\n", __func__, type);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	switch (variant) {
+	case AARCH64_INSN_VARIANT_32BIT:
+		break;
+	case AARCH64_INSN_VARIANT_64BIT:
+		insn |= AARCH64_INSN_SF_BIT;
+		break;
+	default:
+		pr_err("%s: unknown variant encoding %d\n", __func__, variant);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst);
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, src);
+
+	return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn, reg);
+}
+
+u32 aarch64_insn_gen_data3(enum aarch64_insn_register dst,
+			   enum aarch64_insn_register src,
+			   enum aarch64_insn_register reg1,
+			   enum aarch64_insn_register reg2,
+			   enum aarch64_insn_variant variant,
+			   enum aarch64_insn_data3_type type)
+{
+	u32 insn;
+
+	switch (type) {
+	case AARCH64_INSN_DATA3_MADD:
+		insn = aarch64_insn_get_madd_value();
+		break;
+	case AARCH64_INSN_DATA3_MSUB:
+		insn = aarch64_insn_get_msub_value();
+		break;
+	default:
+		pr_err("%s: unknown data3 encoding %d\n", __func__, type);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	switch (variant) {
+	case AARCH64_INSN_VARIANT_32BIT:
+		break;
+	case AARCH64_INSN_VARIANT_64BIT:
+		insn |= AARCH64_INSN_SF_BIT;
+		break;
+	default:
+		pr_err("%s: unknown variant encoding %d\n", __func__, variant);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst);
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RA, insn, src);
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn,
+					    reg1);
+
+	return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn,
+					    reg2);
+}
+
+u32 aarch64_insn_gen_logical_shifted_reg(enum aarch64_insn_register dst,
+					 enum aarch64_insn_register src,
+					 enum aarch64_insn_register reg,
+					 int shift,
+					 enum aarch64_insn_variant variant,
+					 enum aarch64_insn_logic_type type)
+{
+	u32 insn;
+
+	switch (type) {
+	case AARCH64_INSN_LOGIC_AND:
+		insn = aarch64_insn_get_and_value();
+		break;
+	case AARCH64_INSN_LOGIC_BIC:
+		insn = aarch64_insn_get_bic_value();
+		break;
+	case AARCH64_INSN_LOGIC_ORR:
+		insn = aarch64_insn_get_orr_value();
+		break;
+	case AARCH64_INSN_LOGIC_ORN:
+		insn = aarch64_insn_get_orn_value();
+		break;
+	case AARCH64_INSN_LOGIC_EOR:
+		insn = aarch64_insn_get_eor_value();
+		break;
+	case AARCH64_INSN_LOGIC_EON:
+		insn = aarch64_insn_get_eon_value();
+		break;
+	case AARCH64_INSN_LOGIC_AND_SETFLAGS:
+		insn = aarch64_insn_get_ands_value();
+		break;
+	case AARCH64_INSN_LOGIC_BIC_SETFLAGS:
+		insn = aarch64_insn_get_bics_value();
+		break;
+	default:
+		pr_err("%s: unknown logical encoding %d\n", __func__, type);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	switch (variant) {
+	case AARCH64_INSN_VARIANT_32BIT:
+		if (shift & ~(SZ_32 - 1)) {
+			pr_err("%s: invalid shift encoding %d\n", __func__,
+			       shift);
+			return AARCH64_BREAK_FAULT;
+		}
+		break;
+	case AARCH64_INSN_VARIANT_64BIT:
+		insn |= AARCH64_INSN_SF_BIT;
+		if (shift & ~(SZ_64 - 1)) {
+			pr_err("%s: invalid shift encoding %d\n", __func__,
+			       shift);
+			return AARCH64_BREAK_FAULT;
+		}
+		break;
+	default:
+		pr_err("%s: unknown variant encoding %d\n", __func__, variant);
+		return AARCH64_BREAK_FAULT;
+	}
+
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst);
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, src);
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn, reg);
+
+	return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_6, insn, shift);
+}
+
+/*
+ * MOV (register) is architecturally an alias of ORR (shifted register) where
+ * MOV <*d>, <*m> is equivalent to ORR <*d>, <*ZR>, <*m>
+ */
+u32 aarch64_insn_gen_move_reg(enum aarch64_insn_register dst,
+			      enum aarch64_insn_register src,
+			      enum aarch64_insn_variant variant)
+{
+	return aarch64_insn_gen_logical_shifted_reg(dst, AARCH64_INSN_REG_ZR,
+						    src, 0, variant,
+						    AARCH64_INSN_LOGIC_ORR);
+}
+
+u32 aarch64_insn_gen_adr(unsigned long pc, unsigned long addr,
+			 enum aarch64_insn_register reg,
+			 enum aarch64_insn_adr_type type)
+{
+	u32 insn;
+	s32 offset;
+
+	switch (type) {
+	case AARCH64_INSN_ADR_TYPE_ADR:
+		insn = aarch64_insn_get_adr_value();
+		offset = addr - pc;
+		break;
+	case AARCH64_INSN_ADR_TYPE_ADRP:
+		insn = aarch64_insn_get_adrp_value();
+		offset = (addr - ALIGN_DOWN(pc, SZ_4K)) >> 12;
+		break;
+	default:
+		pr_err("%s: unknown adr encoding %d\n", __func__, type);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	if (offset < -SZ_1M || offset >= SZ_1M)
+		return AARCH64_BREAK_FAULT;
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, reg);
+
+	return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_ADR, insn, offset);
+}
+
+/*
+ * Decode the imm field of a branch, and return the byte offset as a
+ * signed value (so it can be used when computing a new branch
+ * target).
+ */
+s32 aarch64_get_branch_offset(u32 insn)
+{
+	s32 imm;
+
+	if (aarch64_insn_is_b(insn) || aarch64_insn_is_bl(insn)) {
+		imm = aarch64_insn_decode_immediate(AARCH64_INSN_IMM_26, insn);
+		return (imm << 6) >> 4;
+	}
+
+	if (aarch64_insn_is_cbz(insn) || aarch64_insn_is_cbnz(insn) ||
+	    aarch64_insn_is_bcond(insn)) {
+		imm = aarch64_insn_decode_immediate(AARCH64_INSN_IMM_19, insn);
+		return (imm << 13) >> 11;
+	}
+
+	if (aarch64_insn_is_tbz(insn) || aarch64_insn_is_tbnz(insn)) {
+		imm = aarch64_insn_decode_immediate(AARCH64_INSN_IMM_14, insn);
+		return (imm << 18) >> 16;
+	}
+
+	/* Unhandled instruction */
+	BUG();
+}
+
+/*
+ * Encode the displacement of a branch in the imm field and return the
+ * updated instruction.
+ */
+u32 aarch64_set_branch_offset(u32 insn, s32 offset)
+{
+	if (aarch64_insn_is_b(insn) || aarch64_insn_is_bl(insn))
+		return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_26, insn,
+						     offset >> 2);
+
+	if (aarch64_insn_is_cbz(insn) || aarch64_insn_is_cbnz(insn) ||
+	    aarch64_insn_is_bcond(insn))
+		return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_19, insn,
+						     offset >> 2);
+
+	if (aarch64_insn_is_tbz(insn) || aarch64_insn_is_tbnz(insn))
+		return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_14, insn,
+						     offset >> 2);
+
+	/* Unhandled instruction */
+	BUG();
+}
+
+s32 aarch64_insn_adrp_get_offset(u32 insn)
+{
+	BUG_ON(!aarch64_insn_is_adrp(insn));
+	return aarch64_insn_decode_immediate(AARCH64_INSN_IMM_ADR, insn) << 12;
+}
+
+u32 aarch64_insn_adrp_set_offset(u32 insn, s32 offset)
+{
+	BUG_ON(!aarch64_insn_is_adrp(insn));
+	return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_ADR, insn,
+						offset >> 12);
+}
+
+/*
+ * Extract the Op/CR data from a msr/mrs instruction.
+ */
+u32 aarch64_insn_extract_system_reg(u32 insn)
+{
+	return (insn & 0x1FFFE0) >> 5;
+}
+
+bool aarch32_insn_is_wide(u32 insn)
+{
+	return insn >= 0xe800;
+}
+
+/*
+ * Macros/defines for extracting register numbers from instruction.
+ */
+u32 aarch32_insn_extract_reg_num(u32 insn, int offset)
+{
+	return (insn & (0xf << offset)) >> offset;
+}
+
+#define OPC2_MASK	0x7
+#define OPC2_OFFSET	5
+u32 aarch32_insn_mcr_extract_opc2(u32 insn)
+{
+	return (insn & (OPC2_MASK << OPC2_OFFSET)) >> OPC2_OFFSET;
+}
+
+#define CRM_MASK	0xf
+u32 aarch32_insn_mcr_extract_crm(u32 insn)
+{
+	return insn & CRM_MASK;
+}
+
+static bool range_of_ones(u64 val)
+{
+	/* Doesn't handle full ones or full zeroes */
+	u64 sval = val >> __ffs64(val);
+
+	/* One of Sean Eron Anderson's bithack tricks */
+	return ((sval + 1) & (sval)) == 0;
+}
+
+static u32 aarch64_encode_immediate(u64 imm,
+				    enum aarch64_insn_variant variant,
+				    u32 insn)
+{
+	unsigned int immr, imms, n, ones, ror, esz, tmp;
+	u64 mask;
+
+	switch (variant) {
+	case AARCH64_INSN_VARIANT_32BIT:
+		esz = 32;
+		break;
+	case AARCH64_INSN_VARIANT_64BIT:
+		insn |= AARCH64_INSN_SF_BIT;
+		esz = 64;
+		break;
+	default:
+		pr_err("%s: unknown variant encoding %d\n", __func__, variant);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	mask = GENMASK(esz - 1, 0);
+
+	/* Can't encode full zeroes, full ones, or value wider than the mask */
+	if (!imm || imm == mask || imm & ~mask)
+		return AARCH64_BREAK_FAULT;
+
+	/*
+	 * Inverse of Replicate(). Try to spot a repeating pattern
+	 * with a pow2 stride.
+	 */
+	for (tmp = esz / 2; tmp >= 2; tmp /= 2) {
+		u64 emask = BIT(tmp) - 1;
+
+		if ((imm & emask) != ((imm >> tmp) & emask))
+			break;
+
+		esz = tmp;
+		mask = emask;
+	}
+
+	/* N is only set if we're encoding a 64bit value */
+	n = esz == 64;
+
+	/* Trim imm to the element size */
+	imm &= mask;
+
+	/* That's how many ones we need to encode */
+	ones = hweight64(imm);
+
+	/*
+	 * imms is set to (ones - 1), prefixed with a string of ones
+	 * and a zero if they fit. Cap it to 6 bits.
+	 */
+	imms  = ones - 1;
+	imms |= 0xf << ffs(esz);
+	imms &= BIT(6) - 1;
+
+	/* Compute the rotation */
+	if (range_of_ones(imm)) {
+		/*
+		 * Pattern: 0..01..10..0
+		 *
+		 * Compute how many rotate we need to align it right
+		 */
+		ror = __ffs64(imm);
+	} else {
+		/*
+		 * Pattern: 0..01..10..01..1
+		 *
+		 * Fill the unused top bits with ones, and check if
+		 * the result is a valid immediate (all ones with a
+		 * contiguous ranges of zeroes).
+		 */
+		imm |= ~mask;
+		if (!range_of_ones(~imm))
+			return AARCH64_BREAK_FAULT;
+
+		/*
+		 * Compute the rotation to get a continuous set of
+		 * ones, with the first bit set at position 0
+		 */
+		ror = fls(~imm);
+	}
+
+	/*
+	 * immr is the number of bits we need to rotate back to the
+	 * original set of ones. Note that this is relative to the
+	 * element size...
+	 */
+	immr = (esz - ror) % esz;
+
+	insn = aarch64_insn_encode_immediate(AARCH64_INSN_IMM_N, insn, n);
+	insn = aarch64_insn_encode_immediate(AARCH64_INSN_IMM_R, insn, immr);
+	return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_S, insn, imms);
+}
+
+u32 aarch64_insn_gen_logical_immediate(enum aarch64_insn_logic_type type,
+				       enum aarch64_insn_variant variant,
+				       enum aarch64_insn_register Rn,
+				       enum aarch64_insn_register Rd,
+				       u64 imm)
+{
+	u32 insn;
+
+	switch (type) {
+	case AARCH64_INSN_LOGIC_AND:
+		insn = aarch64_insn_get_and_imm_value();
+		break;
+	case AARCH64_INSN_LOGIC_ORR:
+		insn = aarch64_insn_get_orr_imm_value();
+		break;
+	case AARCH64_INSN_LOGIC_EOR:
+		insn = aarch64_insn_get_eor_imm_value();
+		break;
+	case AARCH64_INSN_LOGIC_AND_SETFLAGS:
+		insn = aarch64_insn_get_ands_imm_value();
+		break;
+	default:
+		pr_err("%s: unknown logical encoding %d\n", __func__, type);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, Rd);
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, Rn);
+	return aarch64_encode_immediate(imm, variant, insn);
+}
+
+u32 aarch64_insn_gen_extr(enum aarch64_insn_variant variant,
+			  enum aarch64_insn_register Rm,
+			  enum aarch64_insn_register Rn,
+			  enum aarch64_insn_register Rd,
+			  u8 lsb)
+{
+	u32 insn;
+
+	insn = aarch64_insn_get_extr_value();
+
+	switch (variant) {
+	case AARCH64_INSN_VARIANT_32BIT:
+		if (lsb > 31)
+			return AARCH64_BREAK_FAULT;
+		break;
+	case AARCH64_INSN_VARIANT_64BIT:
+		if (lsb > 63)
+			return AARCH64_BREAK_FAULT;
+		insn |= AARCH64_INSN_SF_BIT;
+		insn = aarch64_insn_encode_immediate(AARCH64_INSN_IMM_N, insn, 1);
+		break;
+	default:
+		pr_err("%s: unknown variant encoding %d\n", __func__, variant);
+		return AARCH64_BREAK_FAULT;
+	}
+
+	insn = aarch64_insn_encode_immediate(AARCH64_INSN_IMM_S, insn, lsb);
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, Rd);
+	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, Rn);
+	return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn, Rm);
+}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 03/37] tools: bug: Remove duplicate definition
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 01/37] tools: Add some generic functions and headers Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 02/37] tools: arm64: Make aarch64 instruction decoder available to tools Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 04/37] objtool: arm64: Add base definition for arm64 backend Chen Zhongjin
                   ` (33 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

Under tools, bug.h only defines BUILD_BUG_ON_ZERO() which is already
defined in build_bug.h. This prevents a file to include both headers at
the same time.

Have bug.h include build_bug.h instead.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
---
 tools/include/linux/bug.h | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/tools/include/linux/bug.h b/tools/include/linux/bug.h
index 85f80258a15f..548be7cffa8e 100644
--- a/tools/include/linux/bug.h
+++ b/tools/include/linux/bug.h
@@ -2,10 +2,6 @@
 #ifndef _TOOLS_PERF_LINUX_BUG_H
 #define _TOOLS_PERF_LINUX_BUG_H
 
-/* Force a compilation error if condition is true, but also produce a
-   result (of value 0 and type size_t), so the expression can be used
-   e.g. in a structure initializer (or where-ever else comma expressions
-   aren't permitted). */
-#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
+#include <linux/build_bug.h>
 
 #endif	/* _TOOLS_PERF_LINUX_BUG_H */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 04/37] objtool: arm64: Add base definition for arm64 backend
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (2 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 03/37] tools: bug: Remove duplicate definition Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 05/37] objtool: arm64: Decode add/sub instructions Chen Zhongjin
                   ` (32 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

Provide needed definitions for a new architecture instruction decoder.
No proper decoding is done yet.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
---
 tools/objtool/Makefile                        |   5 +
 tools/objtool/arch/arm64/Build                |   8 ++
 tools/objtool/arch/arm64/decode.c             | 136 ++++++++++++++++++
 .../arch/arm64/include/arch/cfi_regs.h        |  14 ++
 tools/objtool/arch/arm64/include/arch/elf.h   |   8 ++
 .../arch/arm64/include/arch/endianness.h      |   9 ++
 .../objtool/arch/arm64/include/arch/special.h |  22 +++
 tools/objtool/arch/arm64/special.c            |  21 +++
 tools/objtool/sync-check.sh                   |   5 +
 9 files changed, 228 insertions(+)
 create mode 100644 tools/objtool/arch/arm64/Build
 create mode 100644 tools/objtool/arch/arm64/decode.c
 create mode 100644 tools/objtool/arch/arm64/include/arch/cfi_regs.h
 create mode 100644 tools/objtool/arch/arm64/include/arch/elf.h
 create mode 100644 tools/objtool/arch/arm64/include/arch/endianness.h
 create mode 100644 tools/objtool/arch/arm64/include/arch/special.h
 create mode 100644 tools/objtool/arch/arm64/special.c

diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile
index 0dbd397f319d..d62102f55f69 100644
--- a/tools/objtool/Makefile
+++ b/tools/objtool/Makefile
@@ -47,6 +47,11 @@ ifeq ($(SRCARCH),x86)
 	SUBCMD_ORC := y
 endif
 
+ifeq ($(SRCARCH),arm64)
+	SUBCMD_CHECK := y
+	CFLAGS  += -Wno-nested-externs
+endif
+
 export SUBCMD_CHECK SUBCMD_ORC
 export srctree OUTPUT CFLAGS SRCARCH AWK
 include $(srctree)/tools/build/Makefile.include
diff --git a/tools/objtool/arch/arm64/Build b/tools/objtool/arch/arm64/Build
new file mode 100644
index 000000000000..f3de3a50d541
--- /dev/null
+++ b/tools/objtool/arch/arm64/Build
@@ -0,0 +1,8 @@
+objtool-y += special.o
+objtool-y += decode.o
+
+objtool-y += libhweight.o
+
+$(OUTPUT)arch/arm64/libhweight.o: ../lib/hweight.c FORCE
+	$(call rule_mkdir)
+	$(call if_changed_dep,cc_o_c)
diff --git a/tools/objtool/arch/arm64/decode.c b/tools/objtool/arch/arm64/decode.c
new file mode 100644
index 000000000000..42a9ce4aab87
--- /dev/null
+++ b/tools/objtool/arch/arm64/decode.c
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include <asm/insn.h>
+
+#include <objtool/check.h>
+#include <objtool/arch.h>
+#include <objtool/elf.h>
+#include <objtool/warn.h>
+#include <objtool/builtin.h>
+#include <arch/cfi_regs.h>
+
+bool arch_callee_saved_reg(unsigned char reg)
+{
+	switch (reg) {
+	case AARCH64_INSN_REG_19:
+	case AARCH64_INSN_REG_20:
+	case AARCH64_INSN_REG_21:
+	case AARCH64_INSN_REG_22:
+	case AARCH64_INSN_REG_23:
+	case AARCH64_INSN_REG_24:
+	case AARCH64_INSN_REG_25:
+	case AARCH64_INSN_REG_26:
+	case AARCH64_INSN_REG_27:
+	case AARCH64_INSN_REG_28:
+	case AARCH64_INSN_REG_FP:
+	case AARCH64_INSN_REG_LR:
+		return true;
+	default:
+		return false;
+	}
+}
+
+void arch_initial_func_cfi_state(struct cfi_init_state *state)
+{
+	int i;
+
+	for (i = 0; i < CFI_NUM_REGS; i++) {
+		state->regs[i].base = CFI_UNDEFINED;
+		state->regs[i].offset = 0;
+	}
+
+	/* initial CFA (call frame address) */
+	state->cfa.base = CFI_SP;
+	state->cfa.offset = 0;
+}
+
+unsigned long arch_dest_reloc_offset(int addend)
+{
+	return addend;
+}
+
+unsigned long arch_jump_destination(struct instruction *insn)
+{
+	return insn->offset + insn->immediate;
+}
+
+const char *arch_nop_insn(int len)
+{
+	static u32 nop;
+
+	if (len != AARCH64_INSN_SIZE)
+		WARN("invalid NOP size: %d\n", len);
+
+	if (!nop)
+		nop = aarch64_insn_gen_nop();
+
+	return (const char *)&nop;
+}
+
+const char *arch_ret_insn(int len)
+{
+	static u32 ret;
+
+	if (len != AARCH64_INSN_SIZE)
+		WARN("invalid RET size: %d\n", len);
+
+	if (!ret) {
+		ret = aarch64_insn_gen_branch_reg(AARCH64_INSN_REG_LR,
+				AARCH64_INSN_BRANCH_RETURN);
+	}
+
+	return (const char *)&ret;
+}
+
+static int is_arm64(const struct elf *elf)
+{
+	switch (elf->ehdr.e_machine) {
+	case EM_AARCH64: //0xB7
+		return 1;
+	default:
+		WARN("unexpected ELF machine type %x",
+		     elf->ehdr.e_machine);
+		return 0;
+	}
+}
+
+int arch_decode_hint_reg(u8 sp_reg, int *base)
+{
+	return -1;
+}
+
+int arch_decode_instruction(struct objtool_file *file, const struct section *sec,
+			    unsigned long offset, unsigned int maxlen,
+			    unsigned int *len, enum insn_type *type,
+			    unsigned long *immediate,
+			    struct list_head *ops_list)
+{
+	const struct elf *elf = file->elf;
+	u32 insn;
+
+	if (!is_arm64(elf))
+		return -1;
+
+	if (maxlen < AARCH64_INSN_SIZE)
+		return 0;
+
+	*len = AARCH64_INSN_SIZE;
+	*immediate = 0;
+	*type = INSN_OTHER;
+
+	insn = *(u32 *)(sec->data->d_buf + offset);
+
+	switch (aarch64_get_insn_class(insn)) {
+	case AARCH64_INSN_CLS_UNKNOWN:
+		WARN("can't decode instruction at %s:0x%lx", sec->name, offset);
+		return -1;
+	default:
+		break;
+	}
+
+	return 0;
+}
diff --git a/tools/objtool/arch/arm64/include/arch/cfi_regs.h b/tools/objtool/arch/arm64/include/arch/cfi_regs.h
new file mode 100644
index 000000000000..a5185649686b
--- /dev/null
+++ b/tools/objtool/arch/arm64/include/arch/cfi_regs.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef _OBJTOOL_CFI_REGS_H
+#define _OBJTOOL_CFI_REGS_H
+
+#include <asm/insn.h>
+
+#define CFI_BP			AARCH64_INSN_REG_FP
+#define CFI_RA			AARCH64_INSN_REG_LR
+#define CFI_SP			AARCH64_INSN_REG_SP
+
+#define CFI_NUM_REGS		32
+
+#endif /* _OBJTOOL_CFI_REGS_H */
diff --git a/tools/objtool/arch/arm64/include/arch/elf.h b/tools/objtool/arch/arm64/include/arch/elf.h
new file mode 100644
index 000000000000..e8c78cfc5fe1
--- /dev/null
+++ b/tools/objtool/arch/arm64/include/arch/elf.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
+
+#ifndef _OBJTOOL_ARCH_ELF
+#define _OBJTOOL_ARCH_ELF
+
+#define R_NONE R_AARCH64_NONE
+
+#endif /* _OBJTOOL_ARCH_ELF */
diff --git a/tools/objtool/arch/arm64/include/arch/endianness.h b/tools/objtool/arch/arm64/include/arch/endianness.h
new file mode 100644
index 000000000000..7c362527da20
--- /dev/null
+++ b/tools/objtool/arch/arm64/include/arch/endianness.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#ifndef _ARCH_ENDIANNESS_H
+#define _ARCH_ENDIANNESS_H
+
+#include <endian.h>
+
+#define __TARGET_BYTE_ORDER __LITTLE_ENDIAN
+
+#endif /* _ARCH_ENDIANNESS_H */
diff --git a/tools/objtool/arch/arm64/include/arch/special.h b/tools/objtool/arch/arm64/include/arch/special.h
new file mode 100644
index 000000000000..63a705c622a4
--- /dev/null
+++ b/tools/objtool/arch/arm64/include/arch/special.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef _ARM64_ARCH_SPECIAL_H
+#define _ARM64_ARCH_SPECIAL_H
+
+#define EX_ENTRY_SIZE		12
+#define EX_ORIG_OFFSET		0
+#define EX_NEW_OFFSET		4
+
+#define JUMP_ENTRY_SIZE		16
+#define JUMP_ORIG_OFFSET	0
+#define JUMP_NEW_OFFSET		4
+#define JUMP_KEY_OFFSET		8
+
+#define ALT_ENTRY_SIZE		12
+#define ALT_ORIG_OFFSET		0
+#define ALT_NEW_OFFSET		4
+#define ALT_FEATURE_OFFSET	8
+#define ALT_ORIG_LEN_OFFSET	10
+#define ALT_NEW_LEN_OFFSET	11
+
+#endif /* _ARM64_ARCH_SPECIAL_H */
diff --git a/tools/objtool/arch/arm64/special.c b/tools/objtool/arch/arm64/special.c
new file mode 100644
index 000000000000..45f283283091
--- /dev/null
+++ b/tools/objtool/arch/arm64/special.c
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <objtool/special.h>
+
+void arch_handle_alternative(unsigned short feature, struct special_alt *alt)
+{
+}
+
+bool arch_support_alt_relocation(struct special_alt *special_alt,
+				 struct instruction *insn,
+				 struct reloc *reloc)
+{
+	return false;
+}
+
+
+struct reloc *arch_find_switch_table(struct objtool_file *file,
+				     struct instruction *insn)
+{
+	return NULL;
+}
diff --git a/tools/objtool/sync-check.sh b/tools/objtool/sync-check.sh
index 105a291ff8e7..14bb89100d70 100755
--- a/tools/objtool/sync-check.sh
+++ b/tools/objtool/sync-check.sh
@@ -25,6 +25,11 @@ arch/x86/include/asm/insn.h
 arch/x86/lib/inat.c
 arch/x86/lib/insn.c
 '
+elif [ "$SRCARCH" = "arm64" ]; then
+FILES="$FILES
+arch/arm64/include/asm/insn.h
+arch/arm64/lib/insn.c -I '^#include [\"<]\(asm/\)*kprobes.h[\">]' -I '^#include [\"<]\(asm/\)*debug-monitors.h[\">]'
+"
 fi
 
 check_2 () {
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 05/37] objtool: arm64: Decode add/sub instructions
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (3 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 04/37] objtool: arm64: Add base definition for arm64 backend Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 06/37] objtool: arm64: Decode jump and call related instructions Chen Zhongjin
                   ` (31 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

Decode aarch64 additions and substractions and create stack_ops for
instructions interacting with SP or FP.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
---
 tools/objtool/arch/arm64/decode.c | 91 +++++++++++++++++++++++++++++++
 1 file changed, 91 insertions(+)

diff --git a/tools/objtool/arch/arm64/decode.c b/tools/objtool/arch/arm64/decode.c
index 42a9ce4aab87..84daec62006a 100644
--- a/tools/objtool/arch/arm64/decode.c
+++ b/tools/objtool/arch/arm64/decode.c
@@ -13,6 +13,15 @@
 #include <objtool/builtin.h>
 #include <arch/cfi_regs.h>
 
+#include "../../../arch/arm64/lib/insn.c"
+
+static unsigned long sign_extend(unsigned long x, int nbits)
+{
+	unsigned long sign_bit = (x >> (nbits - 1)) & 1;
+
+	return ((~0UL + (sign_bit ^ 1)) << nbits) | x;
+}
+
 bool arch_callee_saved_reg(unsigned char reg)
 {
 	switch (reg) {
@@ -103,6 +112,59 @@ int arch_decode_hint_reg(u8 sp_reg, int *base)
 	return -1;
 }
 
+static struct stack_op *arm_make_add_op(enum aarch64_insn_register dest,
+					enum aarch64_insn_register src,
+					int val)
+{
+	struct stack_op *op;
+
+	op = calloc(1, sizeof(*op));
+	if (!op) {
+		WARN("calloc failed");
+		return NULL;
+	}
+	op->dest.type = OP_DEST_REG;
+	op->dest.reg = dest;
+	op->src.reg = src;
+	op->src.type = val != 0 ? OP_SRC_ADD : OP_SRC_REG;
+	op->src.offset = val;
+
+	return op;
+}
+
+static int arm_decode_add_sub_imm(u32 instr, bool set_flags,
+				  unsigned long *immediate,
+				  struct list_head *ops_list)
+{
+	u32 rd = aarch64_insn_decode_register(AARCH64_INSN_REGTYPE_RD, instr);
+	u32 rn = aarch64_insn_decode_register(AARCH64_INSN_REGTYPE_RN, instr);
+
+	*immediate = aarch64_insn_decode_immediate(AARCH64_INSN_IMM_12, instr);
+
+	if (instr & AARCH64_INSN_LSL_12)
+		*immediate <<= 12;
+
+	if ((!set_flags && rd == AARCH64_INSN_REG_SP) ||
+	    rd == AARCH64_INSN_REG_FP ||
+	    rn == AARCH64_INSN_REG_FP ||
+	    rn == AARCH64_INSN_REG_SP) {
+		struct stack_op *op;
+		int value;
+
+		if (aarch64_insn_is_subs_imm(instr) || aarch64_insn_is_sub_imm(instr))
+			value = -*immediate;
+		else
+			value = *immediate;
+
+		op = arm_make_add_op(rd, rn, value);
+		if (!op)
+			return -1;
+		list_add_tail(&op->list, ops_list);
+	}
+
+	return 0;
+}
+
 int arch_decode_instruction(struct objtool_file *file, const struct section *sec,
 			    unsigned long offset, unsigned int maxlen,
 			    unsigned int *len, enum insn_type *type,
@@ -128,6 +190,35 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
 	case AARCH64_INSN_CLS_UNKNOWN:
 		WARN("can't decode instruction at %s:0x%lx", sec->name, offset);
 		return -1;
+	case AARCH64_INSN_CLS_DP_IMM:
+		/* Mov register to and from SP are aliases of add_imm */
+		if (aarch64_insn_is_add_imm(insn) ||
+		    aarch64_insn_is_sub_imm(insn))
+			return arm_decode_add_sub_imm(insn, false, immediate,
+						      ops_list);
+		else if (aarch64_insn_is_adds_imm(insn) ||
+			     aarch64_insn_is_subs_imm(insn))
+			return arm_decode_add_sub_imm(insn, true, immediate,
+						      ops_list);
+		break;
+	case AARCH64_INSN_CLS_DP_REG:
+		if (aarch64_insn_is_mov_reg(insn)) {
+			enum aarch64_insn_register rd;
+			enum aarch64_insn_register rm;
+
+			rd = aarch64_insn_decode_register(AARCH64_INSN_REGTYPE_RD, insn);
+			rm = aarch64_insn_decode_register(AARCH64_INSN_REGTYPE_RM, insn);
+			if (rd == AARCH64_INSN_REG_FP || rm == AARCH64_INSN_REG_FP) {
+				struct stack_op *op;
+
+				op = arm_make_add_op(rd, rm, 0);
+				if (!op)
+					return -1;
+
+				list_add_tail(&op->list, ops_list);
+			}
+		}
+		break;
 	default:
 		break;
 	}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 06/37] objtool: arm64: Decode jump and call related instructions
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (4 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 05/37] objtool: arm64: Decode add/sub instructions Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 07/37] objtool: arm64: Decode other system instructions Chen Zhongjin
                   ` (30 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

Decode branch, branch and link (aarch64's call) and return instructions.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
---
 tools/objtool/arch/arm64/decode.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/tools/objtool/arch/arm64/decode.c b/tools/objtool/arch/arm64/decode.c
index 84daec62006a..351f8b1bbd6d 100644
--- a/tools/objtool/arch/arm64/decode.c
+++ b/tools/objtool/arch/arm64/decode.c
@@ -219,6 +219,27 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
 			}
 		}
 		break;
+	case AARCH64_INSN_CLS_BR_SYS:
+		if (aarch64_insn_is_ret(insn) &&
+		    aarch64_insn_decode_register(AARCH64_INSN_REGTYPE_RN, insn)
+			== AARCH64_INSN_REG_LR) {
+			*type = INSN_RETURN;
+		} else if (aarch64_insn_is_bl(insn)) {
+			*type = INSN_CALL;
+			*immediate = aarch64_get_branch_offset(insn);
+		} else if (aarch64_insn_is_blr(insn)) {
+			*type = INSN_CALL_DYNAMIC;
+		} else if (aarch64_insn_is_b(insn)) {
+			*type = INSN_JUMP_UNCONDITIONAL;
+			*immediate = aarch64_get_branch_offset(insn);
+		} else if (aarch64_insn_is_br(insn)) {
+			*type = INSN_JUMP_DYNAMIC;
+		} else if (aarch64_insn_is_branch_imm(insn)) {
+			/* Remaining branch opcodes are conditional */
+			*type = INSN_JUMP_CONDITIONAL;
+			*immediate = aarch64_get_branch_offset(insn);
+		}
+		break;
 	default:
 		break;
 	}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 07/37] objtool: arm64: Decode other system instructions
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (5 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 06/37] objtool: arm64: Decode jump and call related instructions Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 08/37] objtool: arm64: Decode load/store instructions Chen Zhongjin
                   ` (29 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

Decode ERET, BRK and NOPs

Signed-off-by: Julien Thierry <jthierry@redhat.com>
---
 tools/objtool/arch/arm64/decode.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/tools/objtool/arch/arm64/decode.c b/tools/objtool/arch/arm64/decode.c
index 351f8b1bbd6d..b07e0f51637e 100644
--- a/tools/objtool/arch/arm64/decode.c
+++ b/tools/objtool/arch/arm64/decode.c
@@ -238,6 +238,13 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
 			/* Remaining branch opcodes are conditional */
 			*type = INSN_JUMP_CONDITIONAL;
 			*immediate = aarch64_get_branch_offset(insn);
+		} else if (aarch64_insn_is_eret(insn)) {
+			*type = INSN_CONTEXT_SWITCH;
+		} else if (aarch64_insn_is_steppable_hint(insn)) {
+			*type = INSN_NOP;
+		} else if (aarch64_insn_is_brk(insn)) {
+			*type = INSN_BUG;
+			*immediate = aarch64_insn_decode_immediate(AARCH64_INSN_IMM_16, insn);
 		}
 		break;
 	default:
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 08/37] objtool: arm64: Decode load/store instructions
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (6 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 07/37] objtool: arm64: Decode other system instructions Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 09/37] objtool: arm64: Decode LDR instructions Chen Zhongjin
                   ` (28 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

Decode load/store operations and create corresponding stack_ops for
operations targeting SP or FP.

Operations storing/loading multiple registers are split into separate
stack_ops storing single registers.

Operations modifying the base register get an additional stack_op
for the register update. Since the atomic register(s) load/store + base
register update gets split into multiple operations, to make sure
objtool always sees a valid stack, consider store instruction to perform
stack allocations (i.e. modifying the base pointer before the storing)
and loads de-allocations (i.e. modifying the base pointer after the
load).

Signed-off-by: Julien Thierry <jthierry@redhat.com>
Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
---
 tools/objtool/arch/arm64/decode.c | 144 ++++++++++++++++++++++++++++++
 1 file changed, 144 insertions(+)

diff --git a/tools/objtool/arch/arm64/decode.c b/tools/objtool/arch/arm64/decode.c
index b07e0f51637e..4a868945dcfb 100644
--- a/tools/objtool/arch/arm64/decode.c
+++ b/tools/objtool/arch/arm64/decode.c
@@ -112,6 +112,48 @@ int arch_decode_hint_reg(u8 sp_reg, int *base)
 	return -1;
 }
 
+static struct stack_op *arm_make_store_op(enum aarch64_insn_register base,
+					  enum aarch64_insn_register reg,
+					  int offset)
+{
+	struct stack_op *op;
+
+	op = calloc(1, sizeof(*op));
+	if (!op) {
+		WARN("calloc failed");
+		return NULL;
+	}
+	op->dest.type = OP_DEST_REG_INDIRECT;
+	op->dest.reg = base;
+	op->dest.offset = offset;
+	op->src.type = OP_SRC_REG;
+	op->src.reg = reg;
+	op->src.offset = 0;
+
+	return op;
+}
+
+static struct stack_op *arm_make_load_op(enum aarch64_insn_register base,
+					 enum aarch64_insn_register reg,
+					 int offset)
+{
+	struct stack_op *op;
+
+	op = calloc(1, sizeof(*op));
+	if (!op) {
+		WARN("calloc failed");
+		return NULL;
+	}
+	op->dest.type = OP_DEST_REG;
+	op->dest.reg = reg;
+	op->dest.offset = 0;
+	op->src.type = OP_SRC_REG_INDIRECT;
+	op->src.reg = base;
+	op->src.offset = offset;
+
+	return op;
+}
+
 static struct stack_op *arm_make_add_op(enum aarch64_insn_register dest,
 					enum aarch64_insn_register src,
 					int val)
@@ -132,6 +174,98 @@ static struct stack_op *arm_make_add_op(enum aarch64_insn_register dest,
 	return op;
 }
 
+static int arm_decode_load_store(u32 insn, unsigned long *immediate,
+				 struct list_head *ops_list)
+{
+	enum aarch64_insn_register base;
+	enum aarch64_insn_register rt;
+	struct stack_op *op;
+	int size;
+	int offset;
+
+	if (aarch64_insn_is_store_single(insn) ||
+	    aarch64_insn_is_load_single(insn))
+		size = 1 << ((insn & GENMASK(31, 30)) >> 30);
+	else
+		size = 4 << ((insn >> 31) & 1);
+
+	if (aarch64_insn_is_store_imm(insn) || aarch64_insn_is_load_imm(insn))
+		*immediate = size * aarch64_insn_decode_immediate(AARCH64_INSN_IMM_12,
+								  insn);
+	else if (aarch64_insn_is_store_pre(insn) ||
+		 aarch64_insn_is_load_pre(insn) ||
+		 aarch64_insn_is_store_post(insn) ||
+		 aarch64_insn_is_load_post(insn))
+		*immediate = sign_extend(aarch64_insn_decode_immediate(AARCH64_INSN_IMM_9,
+								       insn),
+					 9);
+	else if (aarch64_insn_is_stp(insn) || aarch64_insn_is_ldp(insn) ||
+		 aarch64_insn_is_stp_pre(insn) ||
+		 aarch64_insn_is_ldp_pre(insn) ||
+		 aarch64_insn_is_stp_post(insn) ||
+		 aarch64_insn_is_ldp_post(insn))
+		*immediate = size * sign_extend(aarch64_insn_decode_immediate(AARCH64_INSN_IMM_7,
+									      insn),
+						7);
+	else
+		return 1;
+
+	base = aarch64_insn_decode_register(AARCH64_INSN_REGTYPE_RN, insn);
+	if (base != AARCH64_INSN_REG_FP && base != AARCH64_INSN_REG_SP)
+		return 0;
+
+	offset = *immediate;
+
+	if (aarch64_insn_is_store_pre(insn) || aarch64_insn_is_stp_pre(insn) ||
+	    aarch64_insn_is_store_post(insn) || aarch64_insn_is_stp_post(insn)) {
+		op = arm_make_add_op(base, base, *immediate);
+		list_add_tail(&op->list, ops_list);
+
+		if (aarch64_insn_is_store_post(insn) || aarch64_insn_is_stp_post(insn))
+			offset = -*immediate;
+		else
+			offset = 0;
+	} else if (aarch64_insn_is_load_post(insn) || aarch64_insn_is_ldp_post(insn)) {
+		offset = 0;
+	}
+
+	/* First register */
+	rt = aarch64_insn_decode_register(AARCH64_INSN_REGTYPE_RT, insn);
+	if (aarch64_insn_is_store_single(insn) ||
+	    aarch64_insn_is_store_pair(insn))
+		op = arm_make_store_op(base, rt, offset);
+	else
+		op = arm_make_load_op(base, rt, offset);
+
+	if (!op)
+		return -1;
+	list_add_tail(&op->list, ops_list);
+
+	/* Second register (if present) */
+	if (aarch64_insn_is_store_pair(insn) ||
+	    aarch64_insn_is_load_pair(insn)) {
+		rt = aarch64_insn_decode_register(AARCH64_INSN_REGTYPE_RT2,
+						  insn);
+		if (aarch64_insn_is_store_pair(insn))
+			op = arm_make_store_op(base, rt, offset + size);
+		else
+			op = arm_make_load_op(base, rt, offset + size);
+		if (!op)
+			return -1;
+		list_add_tail(&op->list, ops_list);
+	}
+
+	if (aarch64_insn_is_load_pre(insn) || aarch64_insn_is_ldp_pre(insn) ||
+	    aarch64_insn_is_load_post(insn) || aarch64_insn_is_ldp_post(insn)) {
+		op = arm_make_add_op(base, base, *immediate);
+		if (!op)
+			return -1;
+		list_add_tail(&op->list, ops_list);
+	}
+
+	return 0;
+}
+
 static int arm_decode_add_sub_imm(u32 instr, bool set_flags,
 				  unsigned long *immediate,
 				  struct list_head *ops_list)
@@ -247,6 +381,16 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
 			*immediate = aarch64_insn_decode_immediate(AARCH64_INSN_IMM_16, insn);
 		}
 		break;
+	case AARCH64_INSN_CLS_LDST:
+	{
+		int ret;
+
+		ret = arm_decode_load_store(insn, immediate, ops_list);
+		if (ret <= 0)
+			return ret;
+
+		break;
+	}
 	default:
 		break;
 	}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 09/37] objtool: arm64: Decode LDR instructions
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (7 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 08/37] objtool: arm64: Decode load/store instructions Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 10/37] objtool: arm64: Accept non-instruction data in code sections Chen Zhongjin
                   ` (27 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

Load literal instructions can generate constants inside code sections.
Record the locations of the constants in order to be able to remove
their corresponding "struct instruction".

Signed-off-by: Julien Thierry <jthierry@redhat.com>
Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
---
 tools/objtool/arch/arm64/decode.c    | 86 ++++++++++++++++++++++++++++
 tools/objtool/arch/x86/decode.c      |  5 ++
 tools/objtool/check.c                |  3 +
 tools/objtool/include/objtool/arch.h |  3 +
 4 files changed, 97 insertions(+)

diff --git a/tools/objtool/arch/arm64/decode.c b/tools/objtool/arch/arm64/decode.c
index 4a868945dcfb..b62addece734 100644
--- a/tools/objtool/arch/arm64/decode.c
+++ b/tools/objtool/arch/arm64/decode.c
@@ -22,6 +22,73 @@ static unsigned long sign_extend(unsigned long x, int nbits)
 	return ((~0UL + (sign_bit ^ 1)) << nbits) | x;
 }
 
+struct insn_loc {
+	const struct section *sec;
+	unsigned long offset;
+	struct hlist_node hnode;
+	bool delete;
+};
+
+DEFINE_HASHTABLE(invalid_insns, 16);
+
+static int record_invalid_insn(const struct section *sec,
+			       unsigned long offset,
+			       bool delete)
+{
+	struct insn_loc *loc;
+	struct hlist_head *l;
+
+	l = &invalid_insns[hash_min(offset, HASH_BITS(invalid_insns))];
+	if (!hlist_empty(l)) {
+		loc = hlist_entry(l->first, struct insn_loc, hnode);
+		loc->delete |= delete;
+		return 0;
+	}
+
+	loc = malloc(sizeof(*loc));
+	if (!loc) {
+		WARN("malloc failed");
+		return -1;
+	}
+
+	loc->sec = sec;
+	loc->offset = offset;
+	loc->delete = delete;
+
+	hash_add(invalid_insns, &loc->hnode, loc->offset);
+
+	return 0;
+}
+
+int arch_post_process_instructions(struct objtool_file *file)
+{
+	struct hlist_node *tmp;
+	struct insn_loc *loc;
+	unsigned int bkt;
+	int res = 0;
+
+	hash_for_each_safe(invalid_insns, bkt, tmp, loc, hnode) {
+		struct instruction *insn;
+
+		insn = find_insn(file, (struct section *) loc->sec, loc->offset);
+		if (insn) {
+			if (loc->delete) {
+				list_del(&insn->list);
+				hash_del(&insn->hash);
+				free(insn);
+			} else {
+				WARN_FUNC("can't decode instruction", insn->sec, insn->offset);
+				insn->ignore = true;
+			}
+		}
+
+		hash_del(&loc->hnode);
+		free(loc);
+	}
+
+	return res;
+}
+
 bool arch_callee_saved_reg(unsigned char reg)
 {
 	switch (reg) {
@@ -389,6 +456,25 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
 		if (ret <= 0)
 			return ret;
 
+		if (aarch64_insn_is_ldr_lit(insn)) {
+			long pc_offset;
+
+			pc_offset = insn & GENMASK(23, 5);
+			/* Sign extend and multiply by 4 */
+			pc_offset = (pc_offset << (64 - 23));
+			pc_offset = ((pc_offset >> (64 - 23)) >> 5) << 2;
+
+			if (record_invalid_insn(sec, offset + pc_offset, true))
+				return -1;
+
+			/* 64-bit literal */
+			if (insn & BIT(30)) {
+				if (record_invalid_insn(sec,
+							offset + pc_offset + 4,
+							true))
+					return -1;
+			}
+		}
 		break;
 	}
 	default:
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index 943cb41cddf7..c116b6a58898 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -693,6 +693,11 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
 	return 0;
 }
 
+int arch_post_process_instructions(struct objtool_file *file)
+{
+	return 0;
+}
+
 void arch_initial_func_cfi_state(struct cfi_init_state *state)
 {
 	int i;
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index bd0c2c828940..e71c2ab7327a 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -436,6 +436,9 @@ static int decode_instructions(struct objtool_file *file)
 	if (stats)
 		printf("nr_insns: %lu\n", nr_insns);
 
+	if (arch_post_process_instructions(file))
+		return -1;
+
 	return 0;
 
 err:
diff --git a/tools/objtool/include/objtool/arch.h b/tools/objtool/include/objtool/arch.h
index 9b19cc304195..ccd76ce1c92b 100644
--- a/tools/objtool/include/objtool/arch.h
+++ b/tools/objtool/include/objtool/arch.h
@@ -67,6 +67,7 @@ struct stack_op {
 	struct list_head list;
 };
 
+struct objtool_file;
 struct instruction;
 
 void arch_initial_func_cfi_state(struct cfi_init_state *state);
@@ -77,6 +78,8 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
 			    unsigned long *immediate,
 			    struct list_head *ops_list);
 
+int arch_post_process_instructions(struct objtool_file *file);
+
 bool arch_callee_saved_reg(unsigned char reg);
 
 unsigned long arch_jump_destination(struct instruction *insn);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 10/37] objtool: arm64: Accept non-instruction data in code sections
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (8 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 09/37] objtool: arm64: Decode LDR instructions Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 11/37] objtool: arm64: Handle supported relocations in alternatives Chen Zhongjin
                   ` (26 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

The compiler can generate some '0x0' words in code sections to pad the
end of functions. Also some pesudo-instructions can generate data in
code sections.
Record these instructions which can't be decoded as ignored for
objtool check.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
---
 tools/objtool/arch/arm64/decode.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/tools/objtool/arch/arm64/decode.c b/tools/objtool/arch/arm64/decode.c
index b62addece734..d2522ef43101 100644
--- a/tools/objtool/arch/arm64/decode.c
+++ b/tools/objtool/arch/arm64/decode.c
@@ -389,8 +389,23 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
 
 	switch (aarch64_get_insn_class(insn)) {
 	case AARCH64_INSN_CLS_UNKNOWN:
-		WARN("can't decode instruction at %s:0x%lx", sec->name, offset);
-		return -1;
+		/*
+		 * There are a few reasons that non-valid opcodes in code sections:
+		 * - For LDR ops, assembler can generate the data to be
+		 *   loaded in the code section
+		 * - Compiler/assembler can generate zeroes to pad function that
+		 *   do not end on 8-byte alignment
+		 * - Some pseudo-instructions can also generate data in code
+		 *   section
+		 *
+		 * Record these data as ignored so that they won't cause fault
+		 */
+		if (insn == 0x0)
+			*type = INSN_NOP;
+		else if (record_invalid_insn(sec, offset, false))
+			return -1;
+
+		break;
 	case AARCH64_INSN_CLS_DP_IMM:
 		/* Mov register to and from SP are aliases of add_imm */
 		if (aarch64_insn_is_add_imm(insn) ||
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 11/37] objtool: arm64: Handle supported relocations in alternatives
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (9 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 10/37] objtool: arm64: Accept non-instruction data in code sections Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 12/37] objtool: arm64: Ignore replacement section for alternative callback Chen Zhongjin
                   ` (25 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

Based on get_alt_insn() in arch/arm64/kernel/alternative.c, arm64
alternative code adapts offsets for static branches and adrp
instructions.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
---
 tools/objtool/arch/arm64/special.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/tools/objtool/arch/arm64/special.c b/tools/objtool/arch/arm64/special.c
index 45f283283091..a70b91e8bd7d 100644
--- a/tools/objtool/arch/arm64/special.c
+++ b/tools/objtool/arch/arm64/special.c
@@ -10,7 +10,11 @@ bool arch_support_alt_relocation(struct special_alt *special_alt,
 				 struct instruction *insn,
 				 struct reloc *reloc)
 {
-	return false;
+	u32 opcode = *(u32 *)(insn->sec->data->d_buf + insn->offset);
+
+	return aarch64_insn_is_branch_imm(opcode) ||
+	       aarch64_insn_is_adrp(opcode) ||
+	       !aarch64_insn_uses_literal(opcode);
 }
 
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 12/37] objtool: arm64: Ignore replacement section for alternative callback
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (10 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 11/37] objtool: arm64: Handle supported relocations in alternatives Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 13/37] objtool: arm64: Enable stack validation for arm64 Chen Zhongjin
                   ` (24 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

ARM64_CB_PATCH doesn't have static replacement instructions. Skip
trying to validate the alternative section.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
---
 tools/objtool/arch/arm64/special.c | 11 +++++++++++
 tools/objtool/check.c              |  3 +++
 2 files changed, 14 insertions(+)

diff --git a/tools/objtool/arch/arm64/special.c b/tools/objtool/arch/arm64/special.c
index a70b91e8bd7d..8bb1ebd2132a 100644
--- a/tools/objtool/arch/arm64/special.c
+++ b/tools/objtool/arch/arm64/special.c
@@ -4,6 +4,17 @@
 
 void arch_handle_alternative(unsigned short feature, struct special_alt *alt)
 {
+	/*
+	 * ARM64_CB_PATCH has no alternative instruction.
+	 * a callback is called at alternative replacement time
+	 * to dynamically change the original instructions.
+	 *
+	 * ARM64_CB_PATCH is the last ARM64 feature, it's value changes
+	 * every time a new feature is added. So the orig/alt region
+	 * length are used to detect those alternatives
+	 */
+	if (alt->orig_len && !alt->new_len)
+		alt->skip_alt = true;
 }
 
 bool arch_support_alt_relocation(struct special_alt *special_alt,
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index e71c2ab7327a..ae75e88c4885 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1667,6 +1667,9 @@ static int add_special_section_alts(struct objtool_file *file)
 				continue;
 			}
 
+			if (special_alt->skip_alt && !special_alt->new_len)
+				continue;
+
 			ret = handle_group_alt(file, special_alt, orig_insn,
 					       &new_insn);
 			if (ret)
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 13/37] objtool: arm64: Enable stack validation for arm64
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (11 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 12/37] objtool: arm64: Ignore replacement section for alternative callback Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 14/37] objtool: check: Support data in text section Chen Zhongjin
                   ` (23 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Raphael Gault <raphael.gault@arm.com>

Add build option to run stack validation at compile time.

When requiring stack validation, jump tables are disabled as it
simplifies objtool analysis (without having to introduce unreliable
artifacs). In local testing, this does not appear to significaly
affect final binary size nor system performance.

Signed-off-by: Raphael Gault <raphael.gault@arm.com>
Signed-off-by: Julien Thierry <jthierry@redhat.com>
---
 arch/arm64/Kconfig  | 1 +
 arch/arm64/Makefile | 4 ++++
 2 files changed, 5 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 20ea89d9ac2f..6d5ed978e317 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -199,6 +199,7 @@ config ARM64
 	select MMU_GATHER_RCU_TABLE_FREE
 	select HAVE_RSEQ
 	select HAVE_STACKPROTECTOR
+	select HAVE_STACK_VALIDATION
 	select HAVE_SYSCALL_TRACEPOINTS
 	select HAVE_KPROBES
 	select HAVE_KRETPROBES
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index 2f1de88651e6..ad2f4a5e8f6c 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -133,6 +133,10 @@ ifeq ($(CONFIG_DYNAMIC_FTRACE_WITH_REGS),y)
   CC_FLAGS_FTRACE := -fpatchable-function-entry=2
 endif
 
+ifeq ($(CONFIG_STACK_VALIDATION),y)
+KBUILD_CFLAGS	+= -fno-jump-tables
+endif
+
 # Default value
 head-y		:= arch/arm64/kernel/head.o
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 14/37] objtool: check: Support data in text section
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (12 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 13/37] objtool: arm64: Enable stack validation for arm64 Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 15/37] objtool: arm64: Add unwind_hint support Chen Zhongjin
                   ` (22 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

Assembly code can mix code and data in text sections through the use
of SYM_DATA_*() macros. Skip the content of these symbols when decoding
instructions of text sections.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
---
 tools/objtool/check.c               | 19 +++++++++++++++++--
 tools/objtool/elf.c                 | 14 ++++++++++++++
 tools/objtool/include/objtool/elf.h |  1 +
 3 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index ae75e88c4885..52978b8f2ae9 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -356,7 +356,7 @@ static int decode_instructions(struct objtool_file *file)
 {
 	struct section *sec;
 	struct symbol *func;
-	unsigned long offset;
+	unsigned long offset, next_offset;
 	struct instruction *insn;
 	int ret;
 
@@ -374,7 +374,14 @@ static int decode_instructions(struct objtool_file *file)
 		    !strcmp(sec->name, ".entry.text"))
 			sec->noinstr = true;
 
-		for (offset = 0; offset < sec->sh.sh_size; offset += insn->len) {
+		for (offset = 0; offset < sec->sh.sh_size; offset = next_offset) {
+			struct symbol *obj_sym = find_object_containing(sec, offset);
+			if (obj_sym) {
+				/* This is data in the middle of text section, skip it */
+				next_offset = obj_sym->offset + obj_sym->len;
+				continue;
+			}
+
 			insn = malloc(sizeof(*insn));
 			if (!insn) {
 				WARN("malloc failed");
@@ -407,6 +414,14 @@ static int decode_instructions(struct objtool_file *file)
 			hash_add(file->insn_hash, &insn->hash, sec_offset_hash(sec, insn->offset));
 			list_add_tail(&insn->list, &file->insn_list);
 			nr_insns++;
+
+			/* This case is rare, but can cause infinite loop */
+			if (!insn->len) {
+				WARN("zero instruction length");
+				return -1;
+			}
+
+			next_offset = offset + insn->len;
 		}
 
 		list_for_each_entry(func, &sec->symbol_list, list) {
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index d7b99a737496..5b35d89b54d4 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -236,6 +236,20 @@ struct symbol *find_func_containing(struct section *sec, unsigned long offset)
 	return NULL;
 }
 
+struct symbol *find_object_containing(struct section *sec, unsigned long offset)
+{
+	struct rb_node *node;
+
+	rb_for_each(node, &offset, &sec->symbol_tree, symbol_by_offset) {
+		struct symbol *s = rb_entry(node, struct symbol, node);
+
+		if (s->type == STT_OBJECT)
+			return s;
+	}
+
+	return NULL;
+}
+
 struct symbol *find_symbol_by_name(const struct elf *elf, const char *name)
 {
 	struct symbol *sym;
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index 22ba7e2b816e..52ecf1e23cb6 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -157,6 +157,7 @@ struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, uns
 struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec,
 				     unsigned long offset, unsigned int len);
 struct symbol *find_func_containing(struct section *sec, unsigned long offset);
+struct symbol *find_object_containing(struct section *sec, unsigned long offset);
 
 #define for_each_sec(file, sec)						\
 	list_for_each_entry(sec, &file->elf->sections, list)
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 15/37] objtool: arm64: Add unwind_hint support
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (13 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 14/37] objtool: check: Support data in text section Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 16/37] arm64: Add annotate_reachable() for objtools Chen Zhongjin
                   ` (21 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

Provide unwind hint defines for arm64 and objtool hint decoding.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
---
 arch/arm64/include/asm/unwind_hints.h       | 27 +++++++++++++++++++++
 tools/arch/arm64/include/asm/unwind_hints.h | 27 +++++++++++++++++++++
 tools/objtool/arch/arm64/decode.c           |  8 +++++-
 3 files changed, 61 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/include/asm/unwind_hints.h
 create mode 100644 tools/arch/arm64/include/asm/unwind_hints.h

diff --git a/arch/arm64/include/asm/unwind_hints.h b/arch/arm64/include/asm/unwind_hints.h
new file mode 100644
index 000000000000..60f866e4e12c
--- /dev/null
+++ b/arch/arm64/include/asm/unwind_hints.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __ASM_UNWIND_HINTS_H
+#define __ASM_UNWIND_HINTS_H
+
+#include <linux/objtool.h>
+
+#define UNWIND_HINT_REG_UNDEFINED	0xff
+#define UNWIND_HINT_REG_SP		31
+
+#ifdef __ASSEMBLY__
+
+.macro UNWIND_HINT_EMPTY
+	UNWIND_HINT sp_reg=UNWIND_HINT_REG_UNDEFINED type=UNWIND_HINT_TYPE_CALL
+.endm
+
+.macro UNWIND_HINT_FUNC sp_offset=0
+	UNWIND_HINT sp_reg=UNWIND_HINT_REG_SP sp_offset=\sp_offset type=UNWIND_HINT_TYPE_CALL
+.endm
+
+.macro UNWIND_HINT_REGS base=UNWIND_HINT_REG_SP offset=0
+	UNWIND_HINT sp_reg=\base sp_offset=\offset type=UNWIND_HINT_TYPE_REGS
+.endm
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_UNWIND_HINTS_H */
diff --git a/tools/arch/arm64/include/asm/unwind_hints.h b/tools/arch/arm64/include/asm/unwind_hints.h
new file mode 100644
index 000000000000..60f866e4e12c
--- /dev/null
+++ b/tools/arch/arm64/include/asm/unwind_hints.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __ASM_UNWIND_HINTS_H
+#define __ASM_UNWIND_HINTS_H
+
+#include <linux/objtool.h>
+
+#define UNWIND_HINT_REG_UNDEFINED	0xff
+#define UNWIND_HINT_REG_SP		31
+
+#ifdef __ASSEMBLY__
+
+.macro UNWIND_HINT_EMPTY
+	UNWIND_HINT sp_reg=UNWIND_HINT_REG_UNDEFINED type=UNWIND_HINT_TYPE_CALL
+.endm
+
+.macro UNWIND_HINT_FUNC sp_offset=0
+	UNWIND_HINT sp_reg=UNWIND_HINT_REG_SP sp_offset=\sp_offset type=UNWIND_HINT_TYPE_CALL
+.endm
+
+.macro UNWIND_HINT_REGS base=UNWIND_HINT_REG_SP offset=0
+	UNWIND_HINT sp_reg=\base sp_offset=\offset type=UNWIND_HINT_TYPE_REGS
+.endm
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_UNWIND_HINTS_H */
diff --git a/tools/objtool/arch/arm64/decode.c b/tools/objtool/arch/arm64/decode.c
index d2522ef43101..2e7affca1ec9 100644
--- a/tools/objtool/arch/arm64/decode.c
+++ b/tools/objtool/arch/arm64/decode.c
@@ -5,6 +5,7 @@
 #include <stdint.h>
 
 #include <asm/insn.h>
+#include <asm/unwind_hints.h>
 
 #include <objtool/check.h>
 #include <objtool/arch.h>
@@ -176,7 +177,12 @@ static int is_arm64(const struct elf *elf)
 
 int arch_decode_hint_reg(u8 sp_reg, int *base)
 {
-	return -1;
+	if (sp_reg == UNWIND_HINT_REG_UNDEFINED)
+		*base = CFI_UNDEFINED;
+	else
+		*base = sp_reg;
+
+	return 0;
 }
 
 static struct stack_op *arm_make_store_op(enum aarch64_insn_register base,
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 16/37] arm64: Add annotate_reachable() for objtools
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (14 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 15/37] objtool: arm64: Add unwind_hint support Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 17/37] arm64: bug: Add reachable annotation to warning macros Chen Zhongjin
                   ` (20 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

x86 removed annotate_reachable and replaced it with ASM_REACHABLE
which is not suitable for arm64 micro because there are some cases
GCC will merge duplicate inline asm.

Re-add annotation_reachable() for arm64.

Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
---
 include/linux/compiler.h | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 219aa5ddbc73..6a14e4bae37d 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -117,6 +117,14 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
  */
 #define __stringify_label(n) #n
 
+#define __annotate_reachable(c) ({					\
+	asm volatile(__stringify_label(c) ":\n\t"			\
+			".pushsection .discard.reachable\n\t"		\
+			".long " __stringify_label(c) "b - .\n\t"		\
+			".popsection\n\t");				\
+})
+#define annotate_reachable() __annotate_reachable(__COUNTER__)
+
 #define __annotate_unreachable(c) ({					\
 	asm volatile(__stringify_label(c) ":\n\t"			\
 		     ".pushsection .discard.unreachable\n\t"		\
@@ -129,6 +137,7 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
 #define __annotate_jump_table __section(".rodata..c_jump_table")
 
 #else
+#define annotate_reachable()
 #define annotate_unreachable()
 #define __annotate_jump_table
 #endif
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 17/37] arm64: bug: Add reachable annotation to warning macros
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (15 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 16/37] arm64: Add annotate_reachable() for objtools Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 18/37] arm64: kgdb: Mark code following kgdb brk as reachable Chen Zhongjin
                   ` (19 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

WARN* and BUG* both use brk #0x800 opcodes and the distinction is
provided by the contents of the bug table. This table is not accessible
to objtool, so add an annotation to WARN* macros to let objtool know
that brk handler will return an resume the execution of the instructions
following the WARN's brk.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
---
 arch/arm64/include/asm/bug.h | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/bug.h b/arch/arm64/include/asm/bug.h
index 28be048db3f6..9917429971d4 100644
--- a/arch/arm64/include/asm/bug.h
+++ b/arch/arm64/include/asm/bug.h
@@ -19,7 +19,11 @@
 	unreachable();					\
 } while (0)
 
-#define __WARN_FLAGS(flags) __BUG_FLAGS(BUGFLAG_WARNING|(flags))
+#define __WARN_FLAGS(flags)			\
+do {						\
+	__BUG_FLAGS(BUGFLAG_WARNING|(flags));	\
+	annotate_reachable();			\
+} while (0)
 
 #define HAVE_ARCH_BUG
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 18/37] arm64: kgdb: Mark code following kgdb brk as reachable
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (16 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 17/37] arm64: bug: Add reachable annotation to warning macros Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 19/37] arm64: irq-gic: Replace unreachable() with -EINVAL Chen Zhongjin
                   ` (18 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

In the general use case, KGDB breakpoint handler should return normally
to the instruction following the brk.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
---
 arch/arm64/include/asm/kgdb.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/include/asm/kgdb.h b/arch/arm64/include/asm/kgdb.h
index 21fc85e9d2be..a8cb91d8d59b 100644
--- a/arch/arm64/include/asm/kgdb.h
+++ b/arch/arm64/include/asm/kgdb.h
@@ -19,6 +19,7 @@
 static inline void arch_kgdb_breakpoint(void)
 {
 	asm ("brk %0" : : "I" (KGDB_COMPILED_DBG_BRK_IMM));
+	annotate_reachable();
 }
 
 extern void kgdb_handle_bus_error(void);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 19/37] arm64: irq-gic: Replace unreachable() with -EINVAL
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (17 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 18/37] arm64: kgdb: Mark code following kgdb brk as reachable Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 20/37] arm64: Set intra-function call annotations Chen Zhongjin
                   ` (17 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

Using unreachable() at end of function generates an extra NOP for
.unreachable section. It can confuse objtool to warn this NOP as
fall through instruction.

Considering that these branches are actually unreachable, replace
unreachable() with returning a -EINVAL value.

Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
---
 arch/arm64/kvm/hyp/vgic-v3-sr.c | 7 +++----
 drivers/irqchip/irq-gic-v3.c    | 2 +-
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/kvm/hyp/vgic-v3-sr.c b/arch/arm64/kvm/hyp/vgic-v3-sr.c
index 4fb419f7b8b6..f3cee92c3038 100644
--- a/arch/arm64/kvm/hyp/vgic-v3-sr.c
+++ b/arch/arm64/kvm/hyp/vgic-v3-sr.c
@@ -6,7 +6,6 @@
 
 #include <hyp/adjust_pc.h>
 
-#include <linux/compiler.h>
 #include <linux/irqchip/arm-gic-v3.h>
 #include <linux/kvm_host.h>
 
@@ -55,7 +54,7 @@ static u64 __gic_v3_get_lr(unsigned int lr)
 		return read_gicreg(ICH_LR15_EL2);
 	}
 
-	unreachable();
+	return -EINVAL;
 }
 
 static void __gic_v3_set_lr(u64 val, int lr)
@@ -166,7 +165,7 @@ static u32 __vgic_v3_read_ap0rn(int n)
 		val = read_gicreg(ICH_AP0R3_EL2);
 		break;
 	default:
-		unreachable();
+		val = -EINVAL;
 	}
 
 	return val;
@@ -190,7 +189,7 @@ static u32 __vgic_v3_read_ap1rn(int n)
 		val = read_gicreg(ICH_AP1R3_EL2);
 		break;
 	default:
-		unreachable();
+		val = -EINVAL;
 	}
 
 	return val;
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index b252d5534547..2ef98e32d257 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -475,7 +475,7 @@ static u32 __gic_get_ppi_index(irq_hw_number_t hwirq)
 	case EPPI_RANGE:
 		return hwirq - EPPI_BASE_INTID + 16;
 	default:
-		unreachable();
+		return -EINVAL;
 	}
 }
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 20/37] arm64: Set intra-function call annotations
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (18 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 19/37] arm64: irq-gic: Replace unreachable() with -EINVAL Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 21/37] arm64: kernel: Skip validation of proton-pack.c.c and hibernate.c Chen Zhongjin
                   ` (16 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

Stack validation requires BL instructions to an address,
within the symbol containing the BL should be annotated as intra-function
calls.

Make __pmull_p8_core normally set frame because there's a intra-function
call destinating middle of it and the caller have set the frame. When
analyzing the insns there will be a cfi state mismatch between normal-call
and intra-call.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
---
 arch/arm64/crypto/crct10dif-ce-core.S | 5 +++++
 arch/arm64/kernel/entry.S             | 2 ++
 2 files changed, 7 insertions(+)

diff --git a/arch/arm64/crypto/crct10dif-ce-core.S b/arch/arm64/crypto/crct10dif-ce-core.S
index dce6dcebfca1..a1b10d2fb06d 100644
--- a/arch/arm64/crypto/crct10dif-ce-core.S
+++ b/arch/arm64/crypto/crct10dif-ce-core.S
@@ -63,6 +63,7 @@
 //
 
 #include <linux/linkage.h>
+#include <linux/objtool.h>
 #include <asm/assembler.h>
 
 	.text
@@ -132,6 +133,8 @@
 	.endm
 
 SYM_FUNC_START_LOCAL(__pmull_p8_core)
+	stp		x29, x30, [sp, #-16]!
+	mov		x29, sp
 .L__pmull_p8_core:
 	ext		t4.8b, ad.8b, ad.8b, #1			// A1
 	ext		t5.8b, ad.8b, ad.8b, #2			// A2
@@ -193,6 +196,7 @@ SYM_FUNC_START_LOCAL(__pmull_p8_core)
 
 	eor		t4.16b, t4.16b, t5.16b
 	eor		t6.16b, t6.16b, t3.16b
+	ldp		x29, x30, [sp], #16
 	ret
 SYM_FUNC_END(__pmull_p8_core)
 
@@ -207,6 +211,7 @@ SYM_FUNC_END(__pmull_p8_core)
 	pmull2		\rq\().8h, \ad\().16b, \bd\().16b	// D = A*B
 	.endif
 
+	ANNOTATE_INTRA_FUNCTION_CALL
 	bl		.L__pmull_p8_core\i
 
 	eor		\rq\().16b, \rq\().16b, t4.16b
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index ede028dee81b..47829a3077be 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -10,6 +10,7 @@
 #include <linux/arm-smccc.h>
 #include <linux/init.h>
 #include <linux/linkage.h>
+#include <linux/objtool.h>
 
 #include <asm/alternative.h>
 #include <asm/assembler.h>
@@ -682,6 +683,7 @@ alternative_else_nop_endif
 	 * entry onto the return stack and using a RET instruction to
 	 * enter the full-fat kernel vectors.
 	 */
+	ANNOTATE_INTRA_FUNCTION_CALL
 	bl	2f
 	b	.
 2:
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 21/37] arm64: kernel: Skip validation of proton-pack.c.c and hibernate.c
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (19 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 20/37] arm64: Set intra-function call annotations Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 22/37] arm64: kernel: Skip validation of kuser32.o Chen Zhongjin
                   ` (15 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

Julien Said,
"""
This workaround code is more akin to an ancient incantation than
sensible code. And since the function does not call another function
than itself, unwinding from instructions in it should be reliable.
"""

Also add mark for swsusp_arch_resume. It's a noreturn function called
by special ABI.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
---
 arch/arm64/kernel/hibernate.c   | 2 ++
 arch/arm64/kernel/proton-pack.c | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c
index 6328308be272..f5422ae77dc6 100644
--- a/arch/arm64/kernel/hibernate.c
+++ b/arch/arm64/kernel/hibernate.c
@@ -16,6 +16,7 @@
 #include <linux/sched.h>
 #include <linux/suspend.h>
 #include <linux/utsname.h>
+#include <linux/objtool.h>
 
 #include <asm/barrier.h>
 #include <asm/cacheflush.h>
@@ -471,6 +472,7 @@ int swsusp_arch_resume(void)
 
 	return 0;
 }
+STACK_FRAME_NON_STANDARD(swsusp_arch_resume);
 
 int hibernate_resume_nonboot_cpu_disable(void)
 {
diff --git a/arch/arm64/kernel/proton-pack.c b/arch/arm64/kernel/proton-pack.c
index 40be3a7c2c53..9439e62d4b57 100644
--- a/arch/arm64/kernel/proton-pack.c
+++ b/arch/arm64/kernel/proton-pack.c
@@ -22,6 +22,7 @@
 #include <linux/cpu.h>
 #include <linux/device.h>
 #include <linux/nospec.h>
+#include <linux/objtool.h>
 #include <linux/prctl.h>
 #include <linux/sched/task_stack.h>
 
@@ -257,6 +258,7 @@ static noinstr void qcom_link_stack_sanitisation(void)
 		     "mov	x30, %0		\n"
 		     : "=&r" (tmp));
 }
+STACK_FRAME_NON_STANDARD(qcom_link_stack_sanitisation);
 
 static bp_hardening_cb_t spectre_v2_get_sw_mitigation_cb(void)
 {
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 22/37] arm64: kernel: Skip validation of kuser32.o
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (20 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 21/37] arm64: kernel: Skip validation of proton-pack.c.c and hibernate.c Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29 11:05   ` Peter Zijlstra
  2022-04-29  9:43 ` [RFC PATCH v4 23/37] arm64: kernel: Skip validation of sigreturn32.o Chen Zhongjin
                   ` (14 subsequent siblings)
  36 siblings, 1 reply; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Raphael Gault <raphael.gault@arm.com>

kuser32 being used for compatibility, it contains a32 instructions
which are not recognised by objtool when trying to analyse arm64
object files. Thus, we add an exception to skip validation on this
particular file.

Signed-off-by: Raphael Gault <raphael.gault@arm.com>
Signed-off-by: Julien Thierry <jthierry@redhat.com>
Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
---
 arch/arm64/kernel/Makefile | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 986837d7ec82..c4f01bfe79b4 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -41,6 +41,9 @@ obj-$(CONFIG_COMPAT)			+= sys32.o signal32.o			\
 					   sys_compat.o
 obj-$(CONFIG_COMPAT)			+= sigreturn32.o
 obj-$(CONFIG_KUSER_HELPERS)		+= kuser32.o
+
+OBJECT_FILES_NON_STANDARD_kuser32.o := y
+
 obj-$(CONFIG_FUNCTION_TRACER)		+= ftrace.o entry-ftrace.o
 obj-$(CONFIG_MODULES)			+= module.o
 obj-$(CONFIG_ARM64_MODULE_PLTS)		+= module-plts.o
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 23/37] arm64: kernel: Skip validation of sigreturn32.o
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (21 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 22/37] arm64: kernel: Skip validation of kuser32.o Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 24/37] arm64: ftrace: Skip validation of entry-ftrace.o Chen Zhongjin
                   ` (13 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

sigreturn32.o contains aarch32 getting copied to the VDSO for
compat user tasks.

This code shouldn't get validated by arm64 objtool.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
---
 arch/arm64/kernel/Makefile | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index c4f01bfe79b4..eee5eb7d782b 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -40,6 +40,9 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
 obj-$(CONFIG_COMPAT)			+= sys32.o signal32.o			\
 					   sys_compat.o
 obj-$(CONFIG_COMPAT)			+= sigreturn32.o
+ifeq ($(CONFIG_COMPAT), y)
+OBJECT_FILES_NON_STANDARD_sigreturn32.o := y
+endif
 obj-$(CONFIG_KUSER_HELPERS)		+= kuser32.o
 
 OBJECT_FILES_NON_STANDARD_kuser32.o := y
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 24/37] arm64: ftrace: Skip validation of entry-ftrace.o
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (22 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 23/37] arm64: kernel: Skip validation of sigreturn32.o Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 25/37] arm64: bpf: Skip validation of ___bpf_prog_run Chen Zhongjin
                   ` (12 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

Skip objtool validation of ftrace entry because it doesn't follow
standard calling ABI.

Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
---
 arch/arm64/kernel/Makefile | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index eee5eb7d782b..51fd3d45986f 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -47,6 +47,10 @@ obj-$(CONFIG_KUSER_HELPERS)		+= kuser32.o
 
 OBJECT_FILES_NON_STANDARD_kuser32.o := y
 
+ifdef CONFIG_FRAME_POINTER
+OBJECT_FILES_NON_STANDARD_entry-ftrace.o := y
+endif
+
 obj-$(CONFIG_FUNCTION_TRACER)		+= ftrace.o entry-ftrace.o
 obj-$(CONFIG_MODULES)			+= module.o
 obj-$(CONFIG_ARM64_MODULE_PLTS)		+= module-plts.o
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 25/37] arm64: bpf: Skip validation of ___bpf_prog_run
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (23 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 24/37] arm64: ftrace: Skip validation of entry-ftrace.o Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29 11:13   ` Peter Zijlstra
  2022-04-29  9:43 ` [RFC PATCH v4 26/37] arm64: crypto: Remove unnecessary stackframe Chen Zhongjin
                   ` (11 subsequent siblings)
  36 siblings, 1 reply; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

There is a jump table encoded in ___bpf_prog_run and objtool-arm64
can't deal with it now. Skip validate it for arm64.

Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
---
 kernel/bpf/core.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 13e9dbeeedf3..d702f1d83176 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -2022,6 +2022,9 @@ static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn)
 		BUG_ON(1);
 		return 0;
 }
+#ifdef CONFIG_ARM64
+STACK_FRAME_NON_STANDARD(___bpf_prog_run);
+#endif
 
 #define PROG_NAME(stack_size) __bpf_prog_run##stack_size
 #define DEFINE_BPF_PROG_RUN(stack_size) \
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 26/37] arm64: crypto: Remove unnecessary stackframe
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (24 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 25/37] arm64: bpf: Skip validation of ___bpf_prog_run Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 27/37] arm64: sleep: Properly set frame pointer before call Chen Zhongjin
                   ` (10 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

The way sha256_block_neon restore the stackframe confuses objtool.
But it turns out this function is a leaf function and does not use
FP nor LR as scratch register.

Do not create a stackframe in this function as it is not necessary.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
---
 arch/arm64/crypto/sha512-armv8.pl | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/arch/arm64/crypto/sha512-armv8.pl b/arch/arm64/crypto/sha512-armv8.pl
index 35ec9ae99fe1..dca0f22df07f 100644
--- a/arch/arm64/crypto/sha512-armv8.pl
+++ b/arch/arm64/crypto/sha512-armv8.pl
@@ -644,8 +644,6 @@ $code.=<<___;
 .align	4
 sha256_block_neon:
 .Lneon_entry:
-	stp	x29, x30, [sp, #-16]!
-	mov	x29, sp
 	sub	sp,sp,#16*4
 
 	adr	$Ktbl,.LK256
@@ -732,8 +730,7 @@ $code.=<<___;
 	 mov	$Xfer,sp
 	b.ne	.L_00_48
 
-	ldr	x29,[x29]
-	add	sp,sp,#16*4+16
+	add	sp,sp,#16*4
 	ret
 .size	sha256_block_neon,.-sha256_block_neon
 ___
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 27/37] arm64: sleep: Properly set frame pointer before call
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (25 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 26/37] arm64: crypto: Remove unnecessary stackframe Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 28/37] arm64: Change symbol annotations Chen Zhongjin
                   ` (9 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

In __cpu_suspend_enter, the FP and LR are properly saved on the stack to
form a stack frame, but the frame pointer is not set afterwards.

Have the frame pointer point to the new frame.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
---
 arch/arm64/kernel/sleep.S | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S
index 4ea9392f86e0..3bb9b4b2df08 100644
--- a/arch/arm64/kernel/sleep.S
+++ b/arch/arm64/kernel/sleep.S
@@ -91,6 +91,7 @@ SYM_FUNC_START(__cpu_suspend_enter)
 	str	x0, [x1]
 	add	x0, x0, #SLEEP_STACK_DATA_SYSTEM_REGS
 	stp	x29, lr, [sp, #-16]!
+	mov	x29, sp
 	bl	cpu_do_suspend
 	ldp	x29, lr, [sp], #16
 	mov	x0, #1
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 28/37] arm64: Change symbol annotations
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (26 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 27/37] arm64: sleep: Properly set frame pointer before call Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 29/37] arm64: efi-header: Mark efi header as data Chen Zhongjin
                   ` (8 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

Code symbols not following the aarch64 procedure call convention should
be annotated with SYM_CODE_* instead of SYM_FUNC_*

Mark relevant symbols as generic code symbols.

Also replace SYM_INNER_LABEL for __swpan_entry_el0 becasuse
SYM_INNER_LABEL generates zero-size-label which can't be correctly loaded
in objtool.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
---
 arch/arm64/kernel/entry.S  | 10 +++++--
 arch/arm64/kernel/head.S   | 56 +++++++++++++++++++-------------------
 arch/arm64/kernel/sleep.S  |  4 +--
 arch/arm64/kvm/hyp/entry.S |  4 +--
 4 files changed, 39 insertions(+), 35 deletions(-)

diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 47829a3077be..0af74fd59510 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -461,11 +461,15 @@ SYM_CODE_START_LOCAL(__swpan_entry_el1)
 	orr	x23, x23, #PSR_PAN_BIT		// Set the emulated PAN in the saved SPSR
 	b.eq	1f				// TTBR0 access already disabled
 	and	x23, x23, #~PSR_PAN_BIT		// Clear the emulated PAN in the saved SPSR
-SYM_INNER_LABEL(__swpan_entry_el0, SYM_L_LOCAL)
 	__uaccess_ttbr0_disable x21
 1:	ret
 SYM_CODE_END(__swpan_entry_el1)
 
+SYM_CODE_START_LOCAL(__swpan_entry_el0)
+	__uaccess_ttbr0_disable x21
+1:	ret
+SYM_CODE_END(__swpan_entry_el0)
+
 	/*
 	 * Restore access to TTBR0_EL1. If returning to EL0, no need for SPSR
 	 * PAN bit checking.
@@ -759,11 +763,11 @@ SYM_CODE_START_NOALIGN(tramp_vectors)
 	generate_tramp_vector	kpti=1, bhb=BHB_MITIGATION_NONE
 SYM_CODE_END(tramp_vectors)
 
-SYM_CODE_START(tramp_exit_native)
+SYM_CODE_START_LOCAL(tramp_exit_native)
 	tramp_exit
 SYM_CODE_END(tramp_exit_native)
 
-SYM_CODE_START(tramp_exit_compat)
+SYM_CODE_START_LOCAL(tramp_exit_compat)
 	tramp_exit	32
 SYM_CODE_END(tramp_exit_compat)
 
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 6a98f1a38c29..6db9c3603bd8 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -259,7 +259,7 @@ SYM_CODE_END(preserve_boot_args)
  *   - first few MB of the kernel linear mapping to jump to once the MMU has
  *     been enabled
  */
-SYM_FUNC_START_LOCAL(__create_page_tables)
+SYM_CODE_START_LOCAL(__create_page_tables)
 	mov	x28, lr
 
 	/*
@@ -389,7 +389,7 @@ SYM_FUNC_START_LOCAL(__create_page_tables)
 	bl	dcache_inval_poc
 
 	ret	x28
-SYM_FUNC_END(__create_page_tables)
+SYM_CODE_END(__create_page_tables)
 
 	/*
 	 * Initialize CPU registers with task-specific and cpu-specific context.
@@ -422,7 +422,7 @@ SYM_FUNC_END(__create_page_tables)
  *
  *   x0 = __PHYS_OFFSET
  */
-SYM_FUNC_START_LOCAL(__primary_switched)
+SYM_CODE_START_LOCAL(__primary_switched)
 	adr_l	x4, init_task
 	init_cpu_task x4, x5, x6
 
@@ -467,7 +467,7 @@ SYM_FUNC_START_LOCAL(__primary_switched)
 	ldp	x29, x30, [sp], #16
 	bl	start_kernel
 	ASM_BUG()
-SYM_FUNC_END(__primary_switched)
+SYM_CODE_END(__primary_switched)
 
 	.pushsection ".rodata", "a"
 SYM_DATA_START(kimage_vaddr)
@@ -493,7 +493,7 @@ EXPORT_SYMBOL(kimage_vaddr)
  * Returns either BOOT_CPU_MODE_EL1 or BOOT_CPU_MODE_EL2 in w0 if
  * booted in EL1 or EL2 respectively.
  */
-SYM_FUNC_START(init_kernel_el)
+SYM_CODE_START(init_kernel_el)
 	mrs	x0, CurrentEL
 	cmp	x0, #CurrentEL_EL2
 	b.eq	init_el2
@@ -557,13 +557,13 @@ __cpu_stick_to_vhe:
 	hvc	#0
 	mov	x0, #BOOT_CPU_MODE_EL2
 	ret
-SYM_FUNC_END(init_kernel_el)
+SYM_CODE_END(init_kernel_el)
 
 /*
  * Sets the __boot_cpu_mode flag depending on the CPU boot mode passed
  * in w0. See arch/arm64/include/asm/virt.h for more info.
  */
-SYM_FUNC_START_LOCAL(set_cpu_boot_mode_flag)
+SYM_CODE_START_LOCAL(set_cpu_boot_mode_flag)
 	adr_l	x1, __boot_cpu_mode
 	cmp	w0, #BOOT_CPU_MODE_EL2
 	b.ne	1f
@@ -572,7 +572,7 @@ SYM_FUNC_START_LOCAL(set_cpu_boot_mode_flag)
 	dmb	sy
 	dc	ivac, x1			// Invalidate potentially stale cache line
 	ret
-SYM_FUNC_END(set_cpu_boot_mode_flag)
+SYM_CODE_END(set_cpu_boot_mode_flag)
 
 /*
  * These values are written with the MMU off, but read with the MMU on.
@@ -606,7 +606,7 @@ SYM_DATA_END(__early_cpu_boot_status)
 	 * This provides a "holding pen" for platforms to hold all secondary
 	 * cores are held until we're ready for them to initialise.
 	 */
-SYM_FUNC_START(secondary_holding_pen)
+SYM_CODE_START(secondary_holding_pen)
 	bl	init_kernel_el			// w0=cpu_boot_mode
 	bl	set_cpu_boot_mode_flag
 	mrs	x0, mpidr_el1
@@ -618,19 +618,19 @@ pen:	ldr	x4, [x3]
 	b.eq	secondary_startup
 	wfe
 	b	pen
-SYM_FUNC_END(secondary_holding_pen)
+SYM_CODE_END(secondary_holding_pen)
 
 	/*
 	 * Secondary entry point that jumps straight into the kernel. Only to
 	 * be used where CPUs are brought online dynamically by the kernel.
 	 */
-SYM_FUNC_START(secondary_entry)
+SYM_CODE_START(secondary_entry)
 	bl	init_kernel_el			// w0=cpu_boot_mode
 	bl	set_cpu_boot_mode_flag
 	b	secondary_startup
-SYM_FUNC_END(secondary_entry)
+SYM_CODE_END(secondary_entry)
 
-SYM_FUNC_START_LOCAL(secondary_startup)
+SYM_CODE_START_LOCAL(secondary_startup)
 	/*
 	 * Common entry point for secondary CPUs.
 	 */
@@ -641,9 +641,9 @@ SYM_FUNC_START_LOCAL(secondary_startup)
 	bl	__enable_mmu
 	ldr	x8, =__secondary_switched
 	br	x8
-SYM_FUNC_END(secondary_startup)
+SYM_CODE_END(secondary_startup)
 
-SYM_FUNC_START_LOCAL(__secondary_switched)
+SYM_CODE_START_LOCAL(__secondary_switched)
 	adr_l	x5, vectors
 	msr	vbar_el1, x5
 	isb
@@ -660,13 +660,13 @@ SYM_FUNC_START_LOCAL(__secondary_switched)
 
 	bl	secondary_start_kernel
 	ASM_BUG()
-SYM_FUNC_END(__secondary_switched)
+SYM_CODE_END(__secondary_switched)
 
-SYM_FUNC_START_LOCAL(__secondary_too_slow)
+SYM_CODE_START_LOCAL(__secondary_too_slow)
 	wfe
 	wfi
 	b	__secondary_too_slow
-SYM_FUNC_END(__secondary_too_slow)
+SYM_CODE_END(__secondary_too_slow)
 
 /*
  * The booting CPU updates the failed status @__early_cpu_boot_status,
@@ -698,7 +698,7 @@ SYM_FUNC_END(__secondary_too_slow)
  * Checks if the selected granule size is supported by the CPU.
  * If it isn't, park the CPU
  */
-SYM_FUNC_START(__enable_mmu)
+SYM_CODE_START(__enable_mmu)
 	mrs	x2, ID_AA64MMFR0_EL1
 	ubfx	x2, x2, #ID_AA64MMFR0_TGRAN_SHIFT, 4
 	cmp     x2, #ID_AA64MMFR0_TGRAN_SUPPORTED_MIN
@@ -717,9 +717,9 @@ SYM_FUNC_START(__enable_mmu)
 	set_sctlr_el1	x0
 
 	ret
-SYM_FUNC_END(__enable_mmu)
+SYM_CODE_END(__enable_mmu)
 
-SYM_FUNC_START(__cpu_secondary_check52bitva)
+SYM_CODE_START_LOCAL(__cpu_secondary_check52bitva)
 #ifdef CONFIG_ARM64_VA_BITS_52
 	ldr_l	x0, vabits_actual
 	cmp	x0, #52
@@ -737,9 +737,9 @@ SYM_FUNC_START(__cpu_secondary_check52bitva)
 
 #endif
 2:	ret
-SYM_FUNC_END(__cpu_secondary_check52bitva)
+SYM_CODE_END(__cpu_secondary_check52bitva)
 
-SYM_FUNC_START_LOCAL(__no_granule_support)
+SYM_CODE_START_LOCAL(__no_granule_support)
 	/* Indicate that this CPU can't boot and is stuck in the kernel */
 	update_early_cpu_boot_status \
 		CPU_STUCK_IN_KERNEL | CPU_STUCK_REASON_NO_GRAN, x1, x2
@@ -747,10 +747,10 @@ SYM_FUNC_START_LOCAL(__no_granule_support)
 	wfe
 	wfi
 	b	1b
-SYM_FUNC_END(__no_granule_support)
+SYM_CODE_END(__no_granule_support)
 
 #ifdef CONFIG_RELOCATABLE
-SYM_FUNC_START_LOCAL(__relocate_kernel)
+SYM_CODE_START_LOCAL(__relocate_kernel)
 	/*
 	 * Iterate over each entry in the relocation table, and apply the
 	 * relocations in place.
@@ -852,10 +852,10 @@ SYM_FUNC_START_LOCAL(__relocate_kernel)
 #endif
 	ret
 
-SYM_FUNC_END(__relocate_kernel)
+SYM_CODE_END(__relocate_kernel)
 #endif
 
-SYM_FUNC_START_LOCAL(__primary_switch)
+SYM_CODE_START_LOCAL(__primary_switch)
 #ifdef CONFIG_RANDOMIZE_BASE
 	mov	x19, x0				// preserve new SCTLR_EL1 value
 	mrs	x20, sctlr_el1			// preserve old SCTLR_EL1 value
@@ -895,4 +895,4 @@ SYM_FUNC_START_LOCAL(__primary_switch)
 	ldr	x8, =__primary_switched
 	adrp	x0, __PHYS_OFFSET
 	br	x8
-SYM_FUNC_END(__primary_switch)
+SYM_CODE_END(__primary_switch)
diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S
index 3bb9b4b2df08..e01a24b5c5f7 100644
--- a/arch/arm64/kernel/sleep.S
+++ b/arch/arm64/kernel/sleep.S
@@ -112,7 +112,7 @@ SYM_CODE_END(cpu_resume)
 	.ltorg
 	.popsection
 
-SYM_FUNC_START(_cpu_resume)
+SYM_CODE_START(_cpu_resume)
 	mrs	x1, mpidr_el1
 	adr_l	x8, mpidr_hash		// x8 = struct mpidr_hash virt address
 
@@ -148,4 +148,4 @@ SYM_FUNC_START(_cpu_resume)
 	ldp	x29, lr, [x29]
 	mov	x0, #0
 	ret
-SYM_FUNC_END(_cpu_resume)
+SYM_CODE_END(_cpu_resume)
diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S
index 435346ea1504..045d4481c820 100644
--- a/arch/arm64/kvm/hyp/entry.S
+++ b/arch/arm64/kvm/hyp/entry.S
@@ -21,7 +21,7 @@
 /*
  * u64 __guest_enter(struct kvm_vcpu *vcpu);
  */
-SYM_FUNC_START(__guest_enter)
+SYM_CODE_START(__guest_enter)
 	// x0: vcpu
 	// x1-x17: clobbered by macros
 	// x29: guest context
@@ -212,4 +212,4 @@ abort_guest_exit_end:
 	msr	spsr_el2, x4
 	orr	x0, x0, x5
 1:	ret
-SYM_FUNC_END(__guest_enter)
+SYM_CODE_END(__guest_enter)
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 29/37] arm64: efi-header: Mark efi header as data
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (27 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 28/37] arm64: Change symbol annotations Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 30/37] arm64: head: Mark constants " Chen Zhongjin
                   ` (7 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

This file only contains a set of constants forming the efi header.

Make the constants part of a data symbol.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
---
 arch/arm64/kernel/efi-header.S | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/kernel/efi-header.S b/arch/arm64/kernel/efi-header.S
index 28d8a5dca5f1..3eacd27ab761 100644
--- a/arch/arm64/kernel/efi-header.S
+++ b/arch/arm64/kernel/efi-header.S
@@ -28,6 +28,7 @@
 	.macro	__EFI_PE_HEADER
 #ifdef CONFIG_EFI
 	.set	.Lpe_header_offset, . - .L_head
+SYM_DATA_START_LOCAL(arm64_efi_header)
 	.long	PE_MAGIC
 	.short	IMAGE_FILE_MACHINE_ARM64		// Machine
 	.short	.Lsection_count				// NumberOfSections
@@ -160,6 +161,7 @@
 
 	.balign	SEGMENT_ALIGN
 .Lefi_header_end:
+SYM_DATA_END_LABEL(arm64_efi_header, SYM_L_LOCAL, efi_header_end)
 #else
 	.set	.Lpe_header_offset, 0x0
 #endif
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 30/37] arm64: head: Mark constants as data
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (28 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 29/37] arm64: efi-header: Mark efi header as data Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 31/37] arm64: proc: Mark constant " Chen Zhongjin
                   ` (6 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

Add data annotations to constants part of the image header.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
---
 arch/arm64/kernel/head.S | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 6db9c3603bd8..64527718d4c2 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -62,9 +62,10 @@
 	/*
 	 * DO NOT MODIFY. Image header expected by Linux boot-loaders.
 	 */
-	efi_signature_nop			// special NOP to identity as PE/COFF executable
+SYM_DATA_LOCAL(efi_nop, efi_signature_nop)	// special NOP to identity as PE/COFF executable
 	b	primary_entry			// branch to kernel start, magic
-	.quad	0				// Image load offset from start of RAM, little-endian
+SYM_DATA_LOCAL(_zero_reserved, .quad	0)	// Image load offset from start of RAM, little-endian
+SYM_DATA_START_LOCAL(_arm64_common_header)
 	le64sym	_kernel_size_le			// Effective size of kernel image, little-endian
 	le64sym	_kernel_flags_le		// Informative flags, little-endian
 	.quad	0				// reserved
@@ -72,6 +73,7 @@
 	.quad	0				// reserved
 	.ascii	ARM64_IMAGE_MAGIC		// Magic number
 	.long	.Lpe_header_offset		// Offset to the PE header.
+SYM_DATA_END(_arm64_common_header)
 
 	__EFI_PE_HEADER
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 31/37] arm64: proc: Mark constant as data
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (29 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 30/37] arm64: head: Mark constants " Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 32/37] arm64: crypto: Mark data in code sections Chen Zhongjin
                   ` (5 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

Label __idmap_kpti_flag represents the location of a constant.
Mark it as data symbol.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
---
 arch/arm64/mm/proc.S | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index 50bbed947bec..c34ea1778b1e 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -222,8 +222,8 @@ SYM_FUNC_END(idmap_cpu_replace_ttbr1)
  *
  * Called exactly once from stop_machine context by each CPU found during boot.
  */
-__idmap_kpti_flag:
-	.long	1
+SYM_DATA_LOCAL(__idmap_kpti_flag, .long	1)
+
 SYM_FUNC_START(idmap_kpti_install_ng_mappings)
 	cpu		.req	w0
 	num_cpus	.req	w1
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 32/37] arm64: crypto: Mark data in code sections
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (30 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 31/37] arm64: proc: Mark constant " Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 33/37] arm64: Annotate ASM symbols with unknown stack state Chen Zhongjin
                   ` (4 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

Use SYM_DATA_* macros to annotate data bytes in the middle of .text
sections.

For local symbols, ".L" prefix needs to be dropped as the assembler
exclude the symbols from the .o symbol table, making objtool unable
to see them.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
---
 arch/arm64/crypto/aes-neonbs-core.S | 14 +++++++-------
 arch/arm64/crypto/poly1305-armv8.pl |  4 ++++
 arch/arm64/crypto/sha512-armv8.pl   | 24 ++++++++++++++----------
 3 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/arch/arm64/crypto/aes-neonbs-core.S b/arch/arm64/crypto/aes-neonbs-core.S
index d427f4556b6e..fa161d1bf264 100644
--- a/arch/arm64/crypto/aes-neonbs-core.S
+++ b/arch/arm64/crypto/aes-neonbs-core.S
@@ -367,15 +367,15 @@
 
 
 	.align		6
-M0:	.octa		0x0004080c0105090d02060a0e03070b0f
+SYM_DATA_LOCAL(M0,	.octa		0x0004080c0105090d02060a0e03070b0f)
 
-M0SR:	.octa		0x0004080c05090d010a0e02060f03070b
-SR:	.octa		0x0f0e0d0c0a09080b0504070600030201
-SRM0:	.octa		0x01060b0c0207080d0304090e00050a0f
+SYM_DATA_LOCAL(M0SR,	.octa		0x0004080c05090d010a0e02060f03070b)
+SYM_DATA_LOCAL(SR,	.octa		0x0f0e0d0c0a09080b0504070600030201)
+SYM_DATA_LOCAL(SRM0,	.octa		0x01060b0c0207080d0304090e00050a0f)
 
-M0ISR:	.octa		0x0004080c0d0105090a0e0206070b0f03
-ISR:	.octa		0x0f0e0d0c080b0a090504070602010003
-ISRM0:	.octa		0x0306090c00070a0d01040b0e0205080f
+SYM_DATA_LOCAL(M0ISR,	.octa		0x0004080c0d0105090a0e0206070b0f03)
+SYM_DATA_LOCAL(ISR,	.octa		0x0f0e0d0c080b0a090504070602010003)
+SYM_DATA_LOCAL(ISRM0,	.octa		0x0306090c00070a0d01040b0e0205080f)
 
 	/*
 	 * void aesbs_convert_key(u8 out[], u32 const rk[], int rounds)
diff --git a/arch/arm64/crypto/poly1305-armv8.pl b/arch/arm64/crypto/poly1305-armv8.pl
index cbc980fb02e3..f460f33c127a 100644
--- a/arch/arm64/crypto/poly1305-armv8.pl
+++ b/arch/arm64/crypto/poly1305-armv8.pl
@@ -47,6 +47,8 @@ my ($mac,$nonce)=($inp,$len);
 my ($h0,$h1,$h2,$r0,$r1,$s1,$t0,$t1,$d0,$d1,$d2) = map("x$_",(4..14));
 
 $code.=<<___;
+#include <linux/linkage.h>
+
 #ifndef __KERNEL__
 # include "arm_arch.h"
 .extern	OPENSSL_armcap_P
@@ -888,8 +890,10 @@ poly1305_blocks_neon:
 .align	5
 .Lzeros:
 .long	0,0,0,0,0,0,0,0
+SYM_DATA_START_LOCAL(POLY1305_str)
 .asciz	"Poly1305 for ARMv8, CRYPTOGAMS by \@dot-asm"
 .align	2
+SYM_DATA_END(POLY1305_str)
 #if !defined(__KERNEL__) && !defined(_WIN64)
 .comm	OPENSSL_armcap_P,4,4
 .hidden	OPENSSL_armcap_P
diff --git a/arch/arm64/crypto/sha512-armv8.pl b/arch/arm64/crypto/sha512-armv8.pl
index dca0f22df07f..6e2a96e05c5a 100644
--- a/arch/arm64/crypto/sha512-armv8.pl
+++ b/arch/arm64/crypto/sha512-armv8.pl
@@ -193,6 +193,8 @@ ___
 }
 
 $code.=<<___;
+#include <linux/linkage.h>
+
 #ifndef	__KERNEL__
 # include "arm_arch.h"
 #endif
@@ -208,11 +210,11 @@ ___
 $code.=<<___	if ($SZ==4);
 #ifndef	__KERNEL__
 # ifdef	__ILP32__
-	ldrsw	x16,.LOPENSSL_armcap_P
+	ldrsw	x16,OPENSSL_armcap_P_rel
 # else
-	ldr	x16,.LOPENSSL_armcap_P
+	ldr	x16,OPENSSL_armcap_P_rel
 # endif
-	adr	x17,.LOPENSSL_armcap_P
+	adr	x17,OPENSSL_armcap_P_rel
 	add	x16,x16,x17
 	ldr	w16,[x16]
 	tst	w16,#ARMV8_SHA256
@@ -237,7 +239,7 @@ $code.=<<___;
 	ldp	$E,$F,[$ctx,#4*$SZ]
 	add	$num,$inp,$num,lsl#`log(16*$SZ)/log(2)`	// end of input
 	ldp	$G,$H,[$ctx,#6*$SZ]
-	adr	$Ktbl,.LK$BITS
+	adr	$Ktbl,K$BITS
 	stp	$ctx,$num,[x29,#96]
 
 .Loop:
@@ -287,8 +289,7 @@ $code.=<<___;
 .size	$func,.-$func
 
 .align	6
-.type	.LK$BITS,%object
-.LK$BITS:
+SYM_DATA_START_LOCAL(K$BITS)
 ___
 $code.=<<___ if ($SZ==8);
 	.quad	0x428a2f98d728ae22,0x7137449123ef65cd
@@ -353,18 +354,21 @@ $code.=<<___ if ($SZ==4);
 	.long	0	//terminator
 ___
 $code.=<<___;
-.size	.LK$BITS,.-.LK$BITS
+SYM_DATA_END(K$BITS)
 #ifndef	__KERNEL__
 .align	3
-.LOPENSSL_armcap_P:
+SYM_DATA_START_LOCAL(OPENSSL_armcap_P_rel)
 # ifdef	__ILP32__
 	.long	OPENSSL_armcap_P-.
 # else
 	.quad	OPENSSL_armcap_P-.
 # endif
+SYM_DATA_END(OPENSSL_armcap_P_rel)
 #endif
+SYM_DATA_START_LOCAL(OPENSSL_str)
 .asciz	"SHA$BITS block transform for ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
 .align	2
+SYM_DATA_END(OPENSSL_str)
 ___
 
 if ($SZ==4) {
@@ -385,7 +389,7 @@ sha256_block_armv8:
 	add		x29,sp,#0
 
 	ld1.32		{$ABCD,$EFGH},[$ctx]
-	adr		$Ktbl,.LK256
+	adr		$Ktbl,K256
 
 .Loop_hw:
 	ld1		{@MSG[0]-@MSG[3]},[$inp],#64
@@ -646,7 +650,7 @@ sha256_block_neon:
 .Lneon_entry:
 	sub	sp,sp,#16*4
 
-	adr	$Ktbl,.LK256
+	adr	$Ktbl,K256
 	add	$num,$inp,$num,lsl#6	// len to point at the end of inp
 
 	ld1.8	{@X[0]},[$inp], #16
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 33/37] arm64: Annotate ASM symbols with unknown stack state
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (31 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 32/37] arm64: crypto: Mark data in code sections Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 34/37] arm64: entry: Annotate valid stack in kernel entry Chen Zhongjin
                   ` (3 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

Some assembly symbols contain code that might be executed with an
unspecified stack state (e.g. invalid stack pointer,
no stackframe, ...).

Annotate those symbol with UNWIND_HINT_EMPTY to let objtool be aware of
them.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
---
 arch/arm64/include/asm/assembler.h  |  2 ++
 arch/arm64/kernel/cpu-reset.S       |  2 ++
 arch/arm64/kernel/efi-entry.S       |  2 ++
 arch/arm64/kernel/entry.S           |  5 +++++
 arch/arm64/kernel/head.S            | 13 +++++++++++++
 arch/arm64/kernel/hibernate-asm.S   |  2 ++
 arch/arm64/kernel/relocate_kernel.S |  2 ++
 arch/arm64/kernel/sleep.S           |  3 +++
 arch/arm64/kvm/hyp/hyp-entry.S      |  3 +++
 9 files changed, 34 insertions(+)

diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index 8c5a61aeaf8e..68db05428e4b 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -25,6 +25,7 @@
 #include <asm/pgtable-hwdef.h>
 #include <asm/ptrace.h>
 #include <asm/thread_info.h>
+#include <asm/unwind_hints.h>
 
 	/*
 	 * Provide a wxN alias for each wN register so what we can paste a xN
@@ -147,6 +148,7 @@ lr	.req	x30		// link register
  */
 	 .macro	ventry	label
 	.align	7
+	UNWIND_HINT_EMPTY
 	b	\label
 	.endm
 
diff --git a/arch/arm64/kernel/cpu-reset.S b/arch/arm64/kernel/cpu-reset.S
index 48a8af97faa9..c9022042bdec 100644
--- a/arch/arm64/kernel/cpu-reset.S
+++ b/arch/arm64/kernel/cpu-reset.S
@@ -10,6 +10,7 @@
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <asm/sysreg.h>
+#include <asm/unwind_hints.h>
 #include <asm/virt.h>
 
 .text
@@ -29,6 +30,7 @@
  * flat identity mapping.
  */
 SYM_CODE_START(cpu_soft_restart)
+	UNWIND_HINT_EMPTY
 	mov_q	x12, INIT_SCTLR_EL1_MMU_OFF
 	pre_disable_mmu_workaround
 	/*
diff --git a/arch/arm64/kernel/efi-entry.S b/arch/arm64/kernel/efi-entry.S
index 61a87fa1c305..9a1a94c3c4db 100644
--- a/arch/arm64/kernel/efi-entry.S
+++ b/arch/arm64/kernel/efi-entry.S
@@ -9,10 +9,12 @@
 #include <linux/init.h>
 
 #include <asm/assembler.h>
+#include <asm/unwind_hints.h>
 
 	__INIT
 
 SYM_CODE_START(efi_enter_kernel)
+	UNWIND_HINT_EMPTY
 	/*
 	 * efi_pe_entry() will have copied the kernel image if necessary and we
 	 * end up here with device tree address in x1 and the kernel entry
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 0af74fd59510..10fac8f13982 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -29,6 +29,7 @@
 #include <asm/thread_info.h>
 #include <asm/asm-uaccess.h>
 #include <asm/unistd.h>
+#include <asm/unwind_hints.h>
 
 	.macro	clear_gp_regs
 	.irp	n,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29
@@ -38,6 +39,7 @@
 
 	.macro kernel_ventry, el:req, ht:req, regsize:req, label:req
 	.align 7
+	UNWIND_HINT_EMPTY
 .Lventry_start\@:
 	.if	\el == 0
 	/*
@@ -663,6 +665,7 @@ alternative_else_nop_endif
 
 	.macro tramp_ventry, vector_start, regsize, kpti, bhb
 	.align	7
+	UNWIND_HINT_EMPTY
 1:
 	.if	\regsize == 64
 	msr	tpidrro_el0, x30	// Restored in kernel_ventry
@@ -764,10 +767,12 @@ SYM_CODE_START_NOALIGN(tramp_vectors)
 SYM_CODE_END(tramp_vectors)
 
 SYM_CODE_START_LOCAL(tramp_exit_native)
+	UNWIND_HINT_EMPTY
 	tramp_exit
 SYM_CODE_END(tramp_exit_native)
 
 SYM_CODE_START_LOCAL(tramp_exit_compat)
+	UNWIND_HINT_EMPTY
 	tramp_exit	32
 SYM_CODE_END(tramp_exit_compat)
 
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 64527718d4c2..e45e33f169b7 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -33,6 +33,7 @@
 #include <asm/smp.h>
 #include <asm/sysreg.h>
 #include <asm/thread_info.h>
+#include <asm/unwind_hints.h>
 #include <asm/virt.h>
 
 #include "efi-header.S"
@@ -63,6 +64,7 @@
 	 * DO NOT MODIFY. Image header expected by Linux boot-loaders.
 	 */
 SYM_DATA_LOCAL(efi_nop, efi_signature_nop)	// special NOP to identity as PE/COFF executable
+	UNWIND_HINT_EMPTY
 	b	primary_entry			// branch to kernel start, magic
 SYM_DATA_LOCAL(_zero_reserved, .quad	0)	// Image load offset from start of RAM, little-endian
 SYM_DATA_START_LOCAL(_arm64_common_header)
@@ -111,6 +113,7 @@ SYM_CODE_END(primary_entry)
  * Preserve the arguments passed by the bootloader in x0 .. x3
  */
 SYM_CODE_START_LOCAL(preserve_boot_args)
+	UNWIND_HINT_EMPTY
 	mov	x21, x0				// x21=FDT
 
 	adr_l	x0, boot_args			// record the contents of
@@ -262,6 +265,7 @@ SYM_CODE_END(preserve_boot_args)
  *     been enabled
  */
 SYM_CODE_START_LOCAL(__create_page_tables)
+	UNWIND_HINT_EMPTY
 	mov	x28, lr
 
 	/*
@@ -496,6 +500,7 @@ EXPORT_SYMBOL(kimage_vaddr)
  * booted in EL1 or EL2 respectively.
  */
 SYM_CODE_START(init_kernel_el)
+	UNWIND_HINT_EMPTY
 	mrs	x0, CurrentEL
 	cmp	x0, #CurrentEL_EL2
 	b.eq	init_el2
@@ -566,6 +571,7 @@ SYM_CODE_END(init_kernel_el)
  * in w0. See arch/arm64/include/asm/virt.h for more info.
  */
 SYM_CODE_START_LOCAL(set_cpu_boot_mode_flag)
+	UNWIND_HINT_EMPTY
 	adr_l	x1, __boot_cpu_mode
 	cmp	w0, #BOOT_CPU_MODE_EL2
 	b.ne	1f
@@ -609,6 +615,7 @@ SYM_DATA_END(__early_cpu_boot_status)
 	 * cores are held until we're ready for them to initialise.
 	 */
 SYM_CODE_START(secondary_holding_pen)
+	UNWIND_HINT_EMPTY
 	bl	init_kernel_el			// w0=cpu_boot_mode
 	bl	set_cpu_boot_mode_flag
 	mrs	x0, mpidr_el1
@@ -627,6 +634,7 @@ SYM_CODE_END(secondary_holding_pen)
 	 * be used where CPUs are brought online dynamically by the kernel.
 	 */
 SYM_CODE_START(secondary_entry)
+	UNWIND_HINT_EMPTY
 	bl	init_kernel_el			// w0=cpu_boot_mode
 	bl	set_cpu_boot_mode_flag
 	b	secondary_startup
@@ -646,6 +654,7 @@ SYM_CODE_START_LOCAL(secondary_startup)
 SYM_CODE_END(secondary_startup)
 
 SYM_CODE_START_LOCAL(__secondary_switched)
+	UNWIND_HINT_EMPTY
 	adr_l	x5, vectors
 	msr	vbar_el1, x5
 	isb
@@ -665,6 +674,7 @@ SYM_CODE_START_LOCAL(__secondary_switched)
 SYM_CODE_END(__secondary_switched)
 
 SYM_CODE_START_LOCAL(__secondary_too_slow)
+	UNWIND_HINT_EMPTY
 	wfe
 	wfi
 	b	__secondary_too_slow
@@ -701,6 +711,7 @@ SYM_CODE_END(__secondary_too_slow)
  * If it isn't, park the CPU
  */
 SYM_CODE_START(__enable_mmu)
+	UNWIND_HINT_EMPTY
 	mrs	x2, ID_AA64MMFR0_EL1
 	ubfx	x2, x2, #ID_AA64MMFR0_TGRAN_SHIFT, 4
 	cmp     x2, #ID_AA64MMFR0_TGRAN_SUPPORTED_MIN
@@ -722,6 +733,7 @@ SYM_CODE_START(__enable_mmu)
 SYM_CODE_END(__enable_mmu)
 
 SYM_CODE_START_LOCAL(__cpu_secondary_check52bitva)
+	UNWIND_HINT_EMPTY
 #ifdef CONFIG_ARM64_VA_BITS_52
 	ldr_l	x0, vabits_actual
 	cmp	x0, #52
@@ -753,6 +765,7 @@ SYM_CODE_END(__no_granule_support)
 
 #ifdef CONFIG_RELOCATABLE
 SYM_CODE_START_LOCAL(__relocate_kernel)
+	UNWIND_HINT_EMPTY
 	/*
 	 * Iterate over each entry in the relocation table, and apply the
 	 * relocations in place.
diff --git a/arch/arm64/kernel/hibernate-asm.S b/arch/arm64/kernel/hibernate-asm.S
index 0e1d9c3c6a93..c0bec20bf0e0 100644
--- a/arch/arm64/kernel/hibernate-asm.S
+++ b/arch/arm64/kernel/hibernate-asm.S
@@ -13,6 +13,7 @@
 #include <asm/cputype.h>
 #include <asm/memory.h>
 #include <asm/page.h>
+#include <asm/unwind_hints.h>
 #include <asm/virt.h>
 
 /*
@@ -46,6 +47,7 @@
  */
 .pushsection    ".hibernate_exit.text", "ax"
 SYM_CODE_START(swsusp_arch_suspend_exit)
+	UNWIND_HINT_EMPTY
 	/*
 	 * We execute from ttbr0, change ttbr1 to our copied linear map tables
 	 * with a break-before-make via the zero page
diff --git a/arch/arm64/kernel/relocate_kernel.S b/arch/arm64/kernel/relocate_kernel.S
index f0a3df9e18a3..f8cd8fcf2d4f 100644
--- a/arch/arm64/kernel/relocate_kernel.S
+++ b/arch/arm64/kernel/relocate_kernel.S
@@ -16,6 +16,7 @@
 #include <asm/page.h>
 #include <asm/sysreg.h>
 #include <asm/virt.h>
+#include <asm/unwind_hints.h>
 
 .macro turn_off_mmu tmp1, tmp2
 	mov_q   \tmp1, INIT_SCTLR_EL1_MMU_OFF
@@ -37,6 +38,7 @@
  * safe memory that has been set up to be preserved during the copy operation.
  */
 SYM_CODE_START(arm64_relocate_new_kernel)
+	UNWIND_HINT_EMPTY
 	/* Setup the list loop variables. */
 	ldr	x18, [x0, #KIMAGE_ARCH_ZERO_PAGE] /* x18 = zero page for BBM */
 	ldr	x17, [x0, #KIMAGE_ARCH_TTBR1]	/* x17 = linear map copy */
diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S
index e01a24b5c5f7..7fd276f3c532 100644
--- a/arch/arm64/kernel/sleep.S
+++ b/arch/arm64/kernel/sleep.S
@@ -4,6 +4,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/assembler.h>
 #include <asm/smp.h>
+#include <asm/unwind_hints.h>
 
 	.text
 /*
@@ -100,6 +101,7 @@ SYM_FUNC_END(__cpu_suspend_enter)
 
 	.pushsection ".idmap.text", "awx"
 SYM_CODE_START(cpu_resume)
+	UNWIND_HINT_EMPTY
 	bl	init_kernel_el
 	bl	switch_to_vhe
 	bl	__cpu_setup
@@ -113,6 +115,7 @@ SYM_CODE_END(cpu_resume)
 	.popsection
 
 SYM_CODE_START(_cpu_resume)
+	UNWIND_HINT_EMPTY
 	mrs	x1, mpidr_el1
 	adr_l	x8, mpidr_hash		// x8 = struct mpidr_hash virt address
 
diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S
index 7839d075729b..a93af0730da0 100644
--- a/arch/arm64/kvm/hyp/hyp-entry.S
+++ b/arch/arm64/kvm/hyp/hyp-entry.S
@@ -14,6 +14,7 @@
 #include <asm/kvm_asm.h>
 #include <asm/mmu.h>
 #include <asm/spectre.h>
+#include <asm/unwind_hints.h>
 
 .macro save_caller_saved_regs_vect
 	/* x0 and x1 were saved in the vector entry */
@@ -150,6 +151,7 @@ SYM_CODE_END(\label)
 
 .macro valid_vect target
 	.align 7
+        UNWIND_HINT_EMPTY
 661:
 	esb
 	stp	x0, x1, [sp, #-16]!
@@ -161,6 +163,7 @@ check_preamble_length 661b, 662b
 
 .macro invalid_vect target
 	.align 7
+        UNWIND_HINT_EMPTY
 661:
 	nop
 	stp	x0, x1, [sp, #-16]!
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 34/37] arm64: entry: Annotate valid stack in kernel entry
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (32 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 33/37] arm64: Annotate ASM symbols with unknown stack state Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 35/37] arm64: entry: Annotate code switching to tasks Chen Zhongjin
                   ` (2 subsequent siblings)
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

When taking an exception/interrupt, add unwind hints to indicate from
which point the stack pointer is known to be valid.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
---
 arch/arm64/kernel/entry.S | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 10fac8f13982..eeb576ec97ba 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -68,6 +68,7 @@
 	tbnz	x0, #THREAD_SHIFT, 0f
 	sub	x0, sp, x0			// x0'' = sp' - x0' = (sp + x0) - sp = x0
 	sub	sp, sp, x0			// sp'' = sp' - x0 = (sp + x0) - x0 = sp
+	UNWIND_HINT_FUNC sp_offset=S_FRAME_SIZE
 	b	el\el\ht\()_\regsize\()_\label
 
 0:
@@ -100,6 +101,7 @@
 	sub	sp, sp, x0
 	mrs	x0, tpidrro_el0
 #endif
+	UNWIND_HINT_FUNC sp_offset=S_FRAME_SIZE
 	b	el\el\ht\()_\regsize\()_\label
 .org .Lventry_start\@ + 128	// Did we overflow the ventry slot?
 	.endm
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 35/37] arm64: entry: Annotate code switching to tasks
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (33 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 34/37] arm64: entry: Annotate valid stack in kernel entry Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 36/37] arm64: entry: Align stack size for alternative Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 37/37] arm64: kvm: Annotate stack state for guest enter/exit code Chen Zhongjin
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

Add UNWIND_HINT_REGS in kernel_entry after saving pt_regs.

Whether returning to userland or creating a new task, sp is
pointing to a pt_regs frame.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
---
 arch/arm64/kernel/entry.S | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index eeb576ec97ba..c7ab5143949f 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -220,6 +220,7 @@ alternative_cb_end
 	stp	x24, x25, [sp, #16 * 12]
 	stp	x26, x27, [sp, #16 * 13]
 	stp	x28, x29, [sp, #16 * 14]
+	UNWIND_HINT_REGS
 
 	.if	\el == 0
 	clear_gp_regs
@@ -602,6 +603,7 @@ SYM_CODE_START_LOCAL(ret_to_kernel)
 SYM_CODE_END(ret_to_kernel)
 
 SYM_CODE_START_LOCAL(ret_to_user)
+	UNWIND_HINT_REGS
 	ldr	x19, [tsk, #TSK_TI_FLAGS]	// re-check for single-step
 	enable_step_tsk x19, x2
 #ifdef CONFIG_GCC_PLUGIN_STACKLEAK
@@ -874,6 +876,7 @@ NOKPROBE(cpu_switch_to)
  * This is how we return from a fork.
  */
 SYM_CODE_START(ret_from_fork)
+	UNWIND_HINT_REGS
 	bl	schedule_tail
 	cbz	x19, 1f				// not a kernel thread
 	mov	x0, x20
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 36/37] arm64: entry: Align stack size for alternative
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (34 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 35/37] arm64: entry: Annotate code switching to tasks Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  2022-04-29  9:43 ` [RFC PATCH v4 37/37] arm64: kvm: Annotate stack state for guest enter/exit code Chen Zhongjin
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

In kernel_exit there is a alternative branch for KPTI which causes
stack size conflict for two instruction boundaries.

To fix that, make both branch move the sp and then revert it in
tramp_exit branch.

Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
---
 arch/arm64/kernel/entry.S | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index c7ab5143949f..fa3c5a2cd2c3 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -429,7 +429,11 @@ alternative_if_not ARM64_UNMAP_KERNEL_AT_EL0
 	ldr	lr, [sp, #S_LR]
 	add	sp, sp, #PT_REGS_SIZE		// restore sp
 	eret
-alternative_else_nop_endif
+alternative_else
+	nop
+	add sp, sp, #PT_REGS_SIZE       // restore sp
+	nop
+alternative_endif
 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
 	bne	4f
 	msr	far_el1, x29
@@ -726,6 +730,7 @@ alternative_else_nop_endif
 	.endm
 
 	.macro tramp_exit, regsize = 64
+	sub sp, sp, #PT_REGS_SIZE       // revert sp
 	tramp_data_read_var	x30, this_cpu_vector
 	get_this_cpu_offset x29
 	ldr	x30, [x30, x29]
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [RFC PATCH v4 37/37] arm64: kvm: Annotate stack state for guest enter/exit code
  2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
                   ` (35 preceding siblings ...)
  2022-04-29  9:43 ` [RFC PATCH v4 36/37] arm64: entry: Align stack size for alternative Chen Zhongjin
@ 2022-04-29  9:43 ` Chen Zhongjin
  36 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-04-29  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-arch
  Cc: jthierry, catalin.marinas, will, masahiroy, jpoimboe, peterz,
	ycote, herbert, mark.rutland, davem, ardb, maz, tglx,
	luc.vanoostenryck, chenzhongjin

From: Julien Thierry <jthierry@redhat.com>

Symbol __guest_enter is called from C code, with a valid stack pointer.

Symbol __guest_exit is reached when resuming EL2 execution, and the
previous stack pointer gets restored.

Add adequate unwind hints.

Signed-off-by: Julien Thierry <jthierry@redhat.com>
---
 arch/arm64/kvm/hyp/entry.S | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S
index 045d4481c820..0c621b8389e2 100644
--- a/arch/arm64/kvm/hyp/entry.S
+++ b/arch/arm64/kvm/hyp/entry.S
@@ -15,6 +15,7 @@
 #include <asm/kvm_mmu.h>
 #include <asm/kvm_mte.h>
 #include <asm/kvm_ptrauth.h>
+#include <asm/unwind_hints.h>
 
 	.text
 
@@ -22,6 +23,7 @@
  * u64 __guest_enter(struct kvm_vcpu *vcpu);
  */
 SYM_CODE_START(__guest_enter)
+	UNWIND_HINT_FUNC
 	// x0: vcpu
 	// x1-x17: clobbered by macros
 	// x29: guest context
@@ -110,6 +112,7 @@ SYM_INNER_LABEL(__guest_exit, SYM_L_GLOBAL)
 	// x1: vcpu
 	// x2-x29,lr: vcpu regs
 	// vcpu x0-x1 on the stack
+	UNWIND_HINT_FUNC sp_offset=16
 
 	add	x1, x1, #VCPU_CONTEXT
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH v4 22/37] arm64: kernel: Skip validation of kuser32.o
  2022-04-29  9:43 ` [RFC PATCH v4 22/37] arm64: kernel: Skip validation of kuser32.o Chen Zhongjin
@ 2022-04-29 11:05   ` Peter Zijlstra
  2022-05-05  3:36     ` Chen Zhongjin
  0 siblings, 1 reply; 48+ messages in thread
From: Peter Zijlstra @ 2022-04-29 11:05 UTC (permalink / raw)
  To: Chen Zhongjin
  Cc: linux-kernel, linux-arm-kernel, linux-arch, jthierry,
	catalin.marinas, will, masahiroy, jpoimboe, ycote, herbert,
	mark.rutland, davem, ardb, maz, tglx, luc.vanoostenryck

On Fri, Apr 29, 2022 at 05:43:40PM +0800, Chen Zhongjin wrote:
> From: Raphael Gault <raphael.gault@arm.com>
> 
> kuser32 being used for compatibility, it contains a32 instructions
> which are not recognised by objtool when trying to analyse arm64
> object files. Thus, we add an exception to skip validation on this
> particular file.
> 
> Signed-off-by: Raphael Gault <raphael.gault@arm.com>
> Signed-off-by: Julien Thierry <jthierry@redhat.com>
> Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
> ---
>  arch/arm64/kernel/Makefile | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
> index 986837d7ec82..c4f01bfe79b4 100644
> --- a/arch/arm64/kernel/Makefile
> +++ b/arch/arm64/kernel/Makefile
> @@ -41,6 +41,9 @@ obj-$(CONFIG_COMPAT)			+= sys32.o signal32.o			\
>  					   sys_compat.o
>  obj-$(CONFIG_COMPAT)			+= sigreturn32.o
>  obj-$(CONFIG_KUSER_HELPERS)		+= kuser32.o
> +
> +OBJECT_FILES_NON_STANDARD_kuser32.o := y

File based skipping is depricated in the face of LTO and other link
target based objtool runs.

Please use function based blacklisting as per the previous patch.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH v4 25/37] arm64: bpf: Skip validation of ___bpf_prog_run
  2022-04-29  9:43 ` [RFC PATCH v4 25/37] arm64: bpf: Skip validation of ___bpf_prog_run Chen Zhongjin
@ 2022-04-29 11:13   ` Peter Zijlstra
  2022-04-29 20:09     ` Josh Poimboeuf
  0 siblings, 1 reply; 48+ messages in thread
From: Peter Zijlstra @ 2022-04-29 11:13 UTC (permalink / raw)
  To: Chen Zhongjin
  Cc: linux-kernel, linux-arm-kernel, linux-arch, jthierry,
	catalin.marinas, will, masahiroy, jpoimboe, ycote, herbert,
	mark.rutland, davem, ardb, maz, tglx, luc.vanoostenryck

On Fri, Apr 29, 2022 at 05:43:43PM +0800, Chen Zhongjin wrote:
> There is a jump table encoded in ___bpf_prog_run and objtool-arm64
> can't deal with it now. Skip validate it for arm64.

But, but, but, an earlier patch did -fno-jump-tables!

> 
> Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
> ---
>  kernel/bpf/core.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
> index 13e9dbeeedf3..d702f1d83176 100644
> --- a/kernel/bpf/core.c
> +++ b/kernel/bpf/core.c
> @@ -2022,6 +2022,9 @@ static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn)
>  		BUG_ON(1);
>  		return 0;
>  }
> +#ifdef CONFIG_ARM64
> +STACK_FRAME_NON_STANDARD(___bpf_prog_run);
> +#endif
>  
>  #define PROG_NAME(stack_size) __bpf_prog_run##stack_size
>  #define DEFINE_BPF_PROG_RUN(stack_size) \
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH v4 25/37] arm64: bpf: Skip validation of ___bpf_prog_run
  2022-04-29 11:13   ` Peter Zijlstra
@ 2022-04-29 20:09     ` Josh Poimboeuf
  0 siblings, 0 replies; 48+ messages in thread
From: Josh Poimboeuf @ 2022-04-29 20:09 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Chen Zhongjin, linux-kernel, linux-arm-kernel, linux-arch,
	jthierry, catalin.marinas, will, masahiroy, ycote, herbert,
	mark.rutland, davem, ardb, maz, tglx, luc.vanoostenryck

On Fri, Apr 29, 2022 at 01:13:40PM +0200, Peter Zijlstra wrote:
> On Fri, Apr 29, 2022 at 05:43:43PM +0800, Chen Zhongjin wrote:
> > There is a jump table encoded in ___bpf_prog_run and objtool-arm64
> > can't deal with it now. Skip validate it for arm64.
> 
> But, but, but, an earlier patch did -fno-jump-tables!

IIRC, -fno-jump-tables is specific to switch statements but this
function has a C-implemented jump table.

-- 
Josh


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH v4 22/37] arm64: kernel: Skip validation of kuser32.o
  2022-04-29 11:05   ` Peter Zijlstra
@ 2022-05-05  3:36     ` Chen Zhongjin
  2022-05-05  9:24       ` Peter Zijlstra
  0 siblings, 1 reply; 48+ messages in thread
From: Chen Zhongjin @ 2022-05-05  3:36 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-kernel, linux-arm-kernel, linux-arch, jthierry,
	catalin.marinas, will, masahiroy, jpoimboe, ycote, herbert,
	mark.rutland, davem, ardb, maz, tglx, luc.vanoostenryck

Hi Peter,

IIRC now the blacklist mechanisms all run on check stage, which after
decoding, but the problem of kuser32.S happens in decoding stage. Other
than that the assembly symbols in kuser32 is STT_NOTYPE and
STACK_FRAME_NON_STANDARD will throw an error for this.

OBJECT_FILES_NON_STANDARD works for the single file but as you said
after LTO it's invalid. However STACK_FRAME_NON_STANDARD doesn't work
for kuser32 case at all.

Now my strategy for undecodable instructions is: show an error message
and mark insn->ignore = true, but do not stop anything so decoding work
can going on.

To totally solve this my idea is that applying blacklist before decode.
However for this part objtool doesn't have any insn or func info, so we
should add a new blacklist just for this case...

On 2022/4/29 19:05, Peter Zijlstra wrote:
> On Fri, Apr 29, 2022 at 05:43:40PM +0800, Chen Zhongjin wrote:
>> From: Raphael Gault <raphael.gault@arm.com>
>>
>> kuser32 being used for compatibility, it contains a32 instructions
>> which are not recognised by objtool when trying to analyse arm64
>> object files. Thus, we add an exception to skip validation on this
>> particular file.
>>
>> Signed-off-by: Raphael Gault <raphael.gault@arm.com>
>> Signed-off-by: Julien Thierry <jthierry@redhat.com>
>> Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
>> ---
>>  arch/arm64/kernel/Makefile | 3 +++
>>  1 file changed, 3 insertions(+)
>>
>> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
>> index 986837d7ec82..c4f01bfe79b4 100644
>> --- a/arch/arm64/kernel/Makefile
>> +++ b/arch/arm64/kernel/Makefile
>> @@ -41,6 +41,9 @@ obj-$(CONFIG_COMPAT)			+= sys32.o signal32.o			\
>>  					   sys_compat.o
>>  obj-$(CONFIG_COMPAT)			+= sigreturn32.o
>>  obj-$(CONFIG_KUSER_HELPERS)		+= kuser32.o
>> +
>> +OBJECT_FILES_NON_STANDARD_kuser32.o := y
> 
> File based skipping is depricated in the face of LTO and other link
> target based objtool runs.
> 
> Please use function based blacklisting as per the previous patch.
> 
> .


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH v4 22/37] arm64: kernel: Skip validation of kuser32.o
  2022-05-05  3:36     ` Chen Zhongjin
@ 2022-05-05  9:24       ` Peter Zijlstra
  2022-05-05 10:56         ` Mark Rutland
  0 siblings, 1 reply; 48+ messages in thread
From: Peter Zijlstra @ 2022-05-05  9:24 UTC (permalink / raw)
  To: Chen Zhongjin
  Cc: linux-kernel, linux-arm-kernel, linux-arch, jthierry,
	catalin.marinas, will, masahiroy, jpoimboe, ycote, herbert,
	mark.rutland, davem, ardb, maz, tglx, luc.vanoostenryck

On Thu, May 05, 2022 at 11:36:12AM +0800, Chen Zhongjin wrote:
> Hi Peter,
> 
> IIRC now the blacklist mechanisms all run on check stage, which after
> decoding, but the problem of kuser32.S happens in decoding stage. Other
> than that the assembly symbols in kuser32 is STT_NOTYPE and
> STACK_FRAME_NON_STANDARD will throw an error for this.
> 
> OBJECT_FILES_NON_STANDARD works for the single file but as you said
> after LTO it's invalid. However STACK_FRAME_NON_STANDARD doesn't work
> for kuser32 case at all.
> 
> Now my strategy for undecodable instructions is: show an error message
> and mark insn->ignore = true, but do not stop anything so decoding work
> can going on.
> 
> To totally solve this my idea is that applying blacklist before decode.
> However for this part objtool doesn't have any insn or func info, so we
> should add a new blacklist just for this case...

OK, so Mark explained that this is 32bit userspace (VDSO) code.

And as such there's really no point in running objtool on it. Does all
that live in it's own section? Should it?


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH v4 22/37] arm64: kernel: Skip validation of kuser32.o
  2022-05-05  9:24       ` Peter Zijlstra
@ 2022-05-05 10:56         ` Mark Rutland
  2022-05-06  2:18           ` Chen Zhongjin
  2022-05-06 17:31           ` Josh Poimboeuf
  0 siblings, 2 replies; 48+ messages in thread
From: Mark Rutland @ 2022-05-05 10:56 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Chen Zhongjin, linux-kernel, linux-arm-kernel, linux-arch,
	jthierry, catalin.marinas, will, masahiroy, jpoimboe, ycote,
	herbert, davem, ardb, maz, tglx, luc.vanoostenryck

On Thu, May 05, 2022 at 11:24:48AM +0200, Peter Zijlstra wrote:
> On Thu, May 05, 2022 at 11:36:12AM +0800, Chen Zhongjin wrote:
> > Hi Peter,
> > 
> > IIRC now the blacklist mechanisms all run on check stage, which after
> > decoding, but the problem of kuser32.S happens in decoding stage. Other
> > than that the assembly symbols in kuser32 is STT_NOTYPE and
> > STACK_FRAME_NON_STANDARD will throw an error for this.
> > 
> > OBJECT_FILES_NON_STANDARD works for the single file but as you said
> > after LTO it's invalid. However STACK_FRAME_NON_STANDARD doesn't work
> > for kuser32 case at all.
> > 
> > Now my strategy for undecodable instructions is: show an error message
> > and mark insn->ignore = true, but do not stop anything so decoding work
> > can going on.
> > 
> > To totally solve this my idea is that applying blacklist before decode.
> > However for this part objtool doesn't have any insn or func info, so we
> > should add a new blacklist just for this case...
> 
> OK, so Mark explained that this is 32bit userspace (VDSO) code.
> 
> And as such there's really no point in running objtool on it. Does all
> that live in it's own section? Should it?

It's placed in .rodata by a linker script:

* The 32-bit vdso + kuser code is placed in .rodata, between the `vdso32_start`
  and `vdso32_end` symbols, as raw bytes (via .incbin).
  See arch/arm64/kernel/vdso32-wrap.S.

* The 64-bit vdso code is placed in .rodata, between the `vdso_start`
  and `vdso32` symbols, as raw bytes (via .incbin).
  See arch/arm64/kernel/vdso-wrap.S.

The objects under arch/arm64/kernel/{vdso,vdso32}/ are all userspace objects,
and from userspace's PoV the existing secrtions within those objects are
correct, so I don't think those should change.

How does x86 deal with its vdso objects?

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH v4 22/37] arm64: kernel: Skip validation of kuser32.o
  2022-05-05 10:56         ` Mark Rutland
@ 2022-05-06  2:18           ` Chen Zhongjin
  2022-05-06 10:06             ` Mark Rutland
  2022-05-06 17:31           ` Josh Poimboeuf
  1 sibling, 1 reply; 48+ messages in thread
From: Chen Zhongjin @ 2022-05-06  2:18 UTC (permalink / raw)
  To: Mark Rutland, Peter Zijlstra
  Cc: linux-kernel, linux-arm-kernel, linux-arch, jthierry,
	catalin.marinas, will, masahiroy, jpoimboe, ycote, herbert,
	davem, ardb, maz, tglx, luc.vanoostenryck

On 2022/5/5 18:56, Mark Rutland wrote:
> On Thu, May 05, 2022 at 11:24:48AM +0200, Peter Zijlstra wrote:
>> On Thu, May 05, 2022 at 11:36:12AM +0800, Chen Zhongjin wrote:
>>> Hi Peter,
>>>
>>> IIRC now the blacklist mechanisms all run on check stage, which after
>>> decoding, but the problem of kuser32.S happens in decoding stage. Other
>>> than that the assembly symbols in kuser32 is STT_NOTYPE and
>>> STACK_FRAME_NON_STANDARD will throw an error for this.
>>>
>>> OBJECT_FILES_NON_STANDARD works for the single file but as you said
>>> after LTO it's invalid. However STACK_FRAME_NON_STANDARD doesn't work
>>> for kuser32 case at all.
>>>
>>> Now my strategy for undecodable instructions is: show an error message
>>> and mark insn->ignore = true, but do not stop anything so decoding work
>>> can going on.
>>>
>>> To totally solve this my idea is that applying blacklist before decode.
>>> However for this part objtool doesn't have any insn or func info, so we
>>> should add a new blacklist just for this case...
>>
>> OK, so Mark explained that this is 32bit userspace (VDSO) code.
>>
>> And as such there's really no point in running objtool on it. Does all
>> that live in it's own section? Should it?
> 
> It's placed in .rodata by a linker script:
> 
> * The 32-bit vdso + kuser code is placed in .rodata, between the `vdso32_start`
>   and `vdso32_end` symbols, as raw bytes (via .incbin).
>   See arch/arm64/kernel/vdso32-wrap.S.
> 
> * The 64-bit vdso code is placed in .rodata, between the `vdso_start`
>   and `vdso32` symbols, as raw bytes (via .incbin).
>   See arch/arm64/kernel/vdso-wrap.S.
> 
> The objects under arch/arm64/kernel/{vdso,vdso32}/ are all userspace objects,
> and from userspace's PoV the existing secrtions within those objects are
> correct, so I don't think those should change.
> 
> How does x86 deal with its vdso objects?
> 
> Thanks,
> Mark.
> .

However for my build kuser32.o content is in .text and there is only
`vdso` symbol in .rodata without `vdso32`. And for defconfig the
CONFIG_KUSER_HELPERS=y is on.

According to your description, it seems something wrong here?

If all 32-bit asm is placed in .rodata it won't cause problem for
objtool check.

Thanks!


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH v4 22/37] arm64: kernel: Skip validation of kuser32.o
  2022-05-06  2:18           ` Chen Zhongjin
@ 2022-05-06 10:06             ` Mark Rutland
  2022-05-07  6:35               ` Chen Zhongjin
  0 siblings, 1 reply; 48+ messages in thread
From: Mark Rutland @ 2022-05-06 10:06 UTC (permalink / raw)
  To: Chen Zhongjin
  Cc: Peter Zijlstra, linux-kernel, linux-arm-kernel, linux-arch,
	jthierry, catalin.marinas, will, masahiroy, jpoimboe, ycote,
	herbert, davem, ardb, maz, tglx, luc.vanoostenryck

On Fri, May 06, 2022 at 10:18:10AM +0800, Chen Zhongjin wrote:
> On 2022/5/5 18:56, Mark Rutland wrote:
> > On Thu, May 05, 2022 at 11:24:48AM +0200, Peter Zijlstra wrote:
> >> On Thu, May 05, 2022 at 11:36:12AM +0800, Chen Zhongjin wrote:
> >>> Hi Peter,
> >>>
> >>> IIRC now the blacklist mechanisms all run on check stage, which after
> >>> decoding, but the problem of kuser32.S happens in decoding stage. Other
> >>> than that the assembly symbols in kuser32 is STT_NOTYPE and
> >>> STACK_FRAME_NON_STANDARD will throw an error for this.
> >>>
> >>> OBJECT_FILES_NON_STANDARD works for the single file but as you said
> >>> after LTO it's invalid. However STACK_FRAME_NON_STANDARD doesn't work
> >>> for kuser32 case at all.
> >>>
> >>> Now my strategy for undecodable instructions is: show an error message
> >>> and mark insn->ignore = true, but do not stop anything so decoding work
> >>> can going on.
> >>>
> >>> To totally solve this my idea is that applying blacklist before decode.
> >>> However for this part objtool doesn't have any insn or func info, so we
> >>> should add a new blacklist just for this case...
> >>
> >> OK, so Mark explained that this is 32bit userspace (VDSO) code.
> >>
> >> And as such there's really no point in running objtool on it. Does all
> >> that live in it's own section? Should it?
> > 
> > It's placed in .rodata by a linker script:
> > 
> > * The 32-bit vdso + kuser code is placed in .rodata, between the `vdso32_start`
> >   and `vdso32_end` symbols, as raw bytes (via .incbin).
> >   See arch/arm64/kernel/vdso32-wrap.S.
> > 
> > * The 64-bit vdso code is placed in .rodata, between the `vdso_start`
> >   and `vdso32` symbols, as raw bytes (via .incbin).
> >   See arch/arm64/kernel/vdso-wrap.S.
> > 
> > The objects under arch/arm64/kernel/{vdso,vdso32}/ are all userspace objects,
> > and from userspace's PoV the existing secrtions within those objects are
> > correct, so I don't think those should change.
> > 
> > How does x86 deal with its vdso objects?
> > 
> > Thanks,
> > Mark.
> > .
> 
> However for my build kuser32.o content is in .text 

We should be able to move that into .rodata; it's never executed in kernel context.

> and there is only `vdso` symbol in .rodata without `vdso32`.

That means you're not building with CROSS_COMPILE_COMPAT, and so we can't build
the 32-bit VDSO.

> And for defconfig the CONFIG_KUSER_HELPERS=y is on.

Yes.

> According to your description, it seems something wrong here?

Sorry, I was wrong about how we linked the kuser32 code.

I believe we can move that into .rodata by adding:

	.section .rodata

... to the start of that.

I think that'd be a nice cleanup to do regardless of objtool.

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH v4 22/37] arm64: kernel: Skip validation of kuser32.o
  2022-05-05 10:56         ` Mark Rutland
  2022-05-06  2:18           ` Chen Zhongjin
@ 2022-05-06 17:31           ` Josh Poimboeuf
  1 sibling, 0 replies; 48+ messages in thread
From: Josh Poimboeuf @ 2022-05-06 17:31 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Peter Zijlstra, Chen Zhongjin, linux-kernel, linux-arm-kernel,
	linux-arch, jthierry, catalin.marinas, will, masahiroy, jpoimboe,
	ycote, herbert, davem, ardb, maz, tglx, luc.vanoostenryck

On Thu, May 05, 2022 at 11:56:45AM +0100, Mark Rutland wrote:
> The objects under arch/arm64/kernel/{vdso,vdso32}/ are all userspace objects,
> and from userspace's PoV the existing secrtions within those objects are
> correct, so I don't think those should change.
> 
> How does x86 deal with its vdso objects?

On x86, we just use OBJECT_FILES_NON_STANDARD (like the up-thread patch)
to tell objtool to ignore all the vdso objects.

That should be fine for vdso, since it doesn't actually end up as text
in vmlinux.

-- 
Josh

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [RFC PATCH v4 22/37] arm64: kernel: Skip validation of kuser32.o
  2022-05-06 10:06             ` Mark Rutland
@ 2022-05-07  6:35               ` Chen Zhongjin
  0 siblings, 0 replies; 48+ messages in thread
From: Chen Zhongjin @ 2022-05-07  6:35 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Peter Zijlstra, linux-kernel, linux-arm-kernel, linux-arch,
	jthierry, catalin.marinas, will, masahiroy, jpoimboe, ycote,
	herbert, davem, ardb, maz, tglx, luc.vanoostenryck


On 2022/5/6 18:06, Mark Rutland wrote:
>> However for my build kuser32.o content is in .text 
> 
> We should be able to move that into .rodata; it's never executed in kernel context.
> 
>> and there is only `vdso` symbol in .rodata without `vdso32`.
> 
> That means you're not building with CROSS_COMPILE_COMPAT, and so we can't build
> the 32-bit VDSO.
> 
>> And for defconfig the CONFIG_KUSER_HELPERS=y is on.
> 
> Yes.
> 
>> According to your description, it seems something wrong here?
> 
> Sorry, I was wrong about how we linked the kuser32 code.
> 
> I believe we can move that into .rodata by adding:
> 
> 	.section .rodata
> 
> ... to the start of that.

It works.

Thanks!

> I think that'd be a nice cleanup to do regardless of objtool.
> 
> Thanks,
> Mark.
> .


^ permalink raw reply	[flat|nested] 48+ messages in thread

end of thread, other threads:[~2022-05-07  6:35 UTC | newest]

Thread overview: 48+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-29  9:43 [RFC PATCH v4 00/37] objtool: add base support for arm64 Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 01/37] tools: Add some generic functions and headers Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 02/37] tools: arm64: Make aarch64 instruction decoder available to tools Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 03/37] tools: bug: Remove duplicate definition Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 04/37] objtool: arm64: Add base definition for arm64 backend Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 05/37] objtool: arm64: Decode add/sub instructions Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 06/37] objtool: arm64: Decode jump and call related instructions Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 07/37] objtool: arm64: Decode other system instructions Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 08/37] objtool: arm64: Decode load/store instructions Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 09/37] objtool: arm64: Decode LDR instructions Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 10/37] objtool: arm64: Accept non-instruction data in code sections Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 11/37] objtool: arm64: Handle supported relocations in alternatives Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 12/37] objtool: arm64: Ignore replacement section for alternative callback Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 13/37] objtool: arm64: Enable stack validation for arm64 Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 14/37] objtool: check: Support data in text section Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 15/37] objtool: arm64: Add unwind_hint support Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 16/37] arm64: Add annotate_reachable() for objtools Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 17/37] arm64: bug: Add reachable annotation to warning macros Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 18/37] arm64: kgdb: Mark code following kgdb brk as reachable Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 19/37] arm64: irq-gic: Replace unreachable() with -EINVAL Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 20/37] arm64: Set intra-function call annotations Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 21/37] arm64: kernel: Skip validation of proton-pack.c.c and hibernate.c Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 22/37] arm64: kernel: Skip validation of kuser32.o Chen Zhongjin
2022-04-29 11:05   ` Peter Zijlstra
2022-05-05  3:36     ` Chen Zhongjin
2022-05-05  9:24       ` Peter Zijlstra
2022-05-05 10:56         ` Mark Rutland
2022-05-06  2:18           ` Chen Zhongjin
2022-05-06 10:06             ` Mark Rutland
2022-05-07  6:35               ` Chen Zhongjin
2022-05-06 17:31           ` Josh Poimboeuf
2022-04-29  9:43 ` [RFC PATCH v4 23/37] arm64: kernel: Skip validation of sigreturn32.o Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 24/37] arm64: ftrace: Skip validation of entry-ftrace.o Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 25/37] arm64: bpf: Skip validation of ___bpf_prog_run Chen Zhongjin
2022-04-29 11:13   ` Peter Zijlstra
2022-04-29 20:09     ` Josh Poimboeuf
2022-04-29  9:43 ` [RFC PATCH v4 26/37] arm64: crypto: Remove unnecessary stackframe Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 27/37] arm64: sleep: Properly set frame pointer before call Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 28/37] arm64: Change symbol annotations Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 29/37] arm64: efi-header: Mark efi header as data Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 30/37] arm64: head: Mark constants " Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 31/37] arm64: proc: Mark constant " Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 32/37] arm64: crypto: Mark data in code sections Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 33/37] arm64: Annotate ASM symbols with unknown stack state Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 34/37] arm64: entry: Annotate valid stack in kernel entry Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 35/37] arm64: entry: Annotate code switching to tasks Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 36/37] arm64: entry: Align stack size for alternative Chen Zhongjin
2022-04-29  9:43 ` [RFC PATCH v4 37/37] arm64: kvm: Annotate stack state for guest enter/exit code Chen Zhongjin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).