From: Chen Zhongjin <chenzhongjin@huawei.com>
To: <linux-kernel@vger.kernel.org>, <linux-arch@vger.kernel.org>,
<linuxppc-dev@lists.ozlabs.org>,
<linux-arm-kernel@lists.infradead.org>,
<linux-kbuild@vger.kernel.org>, <live-patching@vger.kernel.org>
Cc: mark.rutland@arm.com, madvenka@linux.microsoft.com,
michal.lkml@markovi.net, pasha.tatashin@soleen.com,
peterz@infradead.org, catalin.marinas@arm.com,
masahiroy@kernel.org, ndesaulniers@google.com,
chenzhongjin@huawei.com, rmk+kernel@armlinux.org.uk,
broonie@kernel.org, will@kernel.org, jpoimboe@kernel.org
Subject: [PATCH v5 13/33] objtool: arm64: Enable ORC for arm64
Date: Wed, 22 Jun 2022 23:49:00 +0800 [thread overview]
Message-ID: <20220622154920.95075-14-chenzhongjin@huawei.com> (raw)
In-Reply-To: <20220622154920.95075-1-chenzhongjin@huawei.com>
Add orc_type, orc build and ld options for arm64.
Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
---
arch/arm64/Kconfig.debug | 10 ++
arch/arm64/include/asm/module.h | 7 ++
arch/arm64/include/asm/orc_types.h | 68 +++++++++++++
arch/arm64/kernel/vmlinux.lds.S | 3 +
scripts/Makefile | 6 +-
tools/arch/arm64/include/asm/orc_types.h | 68 +++++++++++++
tools/objtool/Makefile | 1 +
tools/objtool/arch/arm64/Build | 1 +
tools/objtool/arch/arm64/orc.c | 117 +++++++++++++++++++++++
9 files changed, 280 insertions(+), 1 deletion(-)
create mode 100644 arch/arm64/include/asm/orc_types.h
create mode 100644 tools/arch/arm64/include/asm/orc_types.h
create mode 100644 tools/objtool/arch/arm64/orc.c
diff --git a/arch/arm64/Kconfig.debug b/arch/arm64/Kconfig.debug
index c2c68c6f7557..ec804a21c753 100644
--- a/arch/arm64/Kconfig.debug
+++ b/arch/arm64/Kconfig.debug
@@ -39,6 +39,16 @@ config UNWINDER_FRAME_POINTER
unwinder, but the kernel text size will grow by ~3% and the kernel's
overall performance will degrade by roughly 5-10%.
+config UNWINDER_ORC
+ bool "ORC unwinder"
+ select OBJTOOL
+ help
+ This option enables the ORC (Oops Rewind Capability) unwinder for
+ unwinding kernel stack traces. It uses a custom data format which is
+ a simplified version of the DWARF Call Frame Information standard.
+
+ The orc unwinder is not implemented on arm64 now, this option is only
+ used for testing orc data generation.
endchoice
source "drivers/hwtracing/coresight/Kconfig"
diff --git a/arch/arm64/include/asm/module.h b/arch/arm64/include/asm/module.h
index 4e7fa2623896..782ac8e120dd 100644
--- a/arch/arm64/include/asm/module.h
+++ b/arch/arm64/include/asm/module.h
@@ -6,6 +6,7 @@
#define __ASM_MODULE_H
#include <asm-generic/module.h>
+#include <asm/orc_types.h>
#ifdef CONFIG_ARM64_MODULE_PLTS
struct mod_plt_sec {
@@ -20,6 +21,12 @@ struct mod_arch_specific {
/* for CONFIG_DYNAMIC_FTRACE */
struct plt_entry *ftrace_trampolines;
+
+#ifdef CONFIG_UNWINDER_ORC
+ unsigned int num_orcs;
+ int *orc_unwind_ip;
+ struct orc_entry *orc_unwind;
+#endif
};
#endif
diff --git a/arch/arm64/include/asm/orc_types.h b/arch/arm64/include/asm/orc_types.h
new file mode 100644
index 000000000000..9c06e7a6ed55
--- /dev/null
+++ b/arch/arm64/include/asm/orc_types.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2017 Josh Poimboeuf <jpoimboe@redhat.com>
+ */
+
+#ifndef _ORC_TYPES_H
+#define _ORC_TYPES_H
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+
+/*
+ * The ORC_REG_* registers are base registers which are used to find other
+ * registers on the stack.
+ *
+ * ORC_REG_PREV_SP, also known as DWARF Call Frame Address (CFA), is the
+ * address of the previous frame: the caller's SP before it called the current
+ * function.
+ *
+ * ORC_REG_UNDEFINED means the corresponding register's value didn't change in
+ * the current frame.
+ *
+ * The most commonly used base registers are SP and BP -- which the previous SP
+ * is usually based on -- and PREV_SP and UNDEFINED -- which the previous BP is
+ * usually based on.
+ *
+ * The rest of the base registers are needed for special cases like entry code
+ * and GCC realigned stacks.
+ */
+#define ORC_REG_UNDEFINED 0
+#define ORC_REG_PREV_SP 1
+#define ORC_REG_BP 2
+#define ORC_REG_SP 3
+#define ORC_REG_BP_INDIRECT 4
+#define ORC_REG_SP_INDIRECT 5
+#define ORC_REG_MAX 6
+
+#ifndef __ASSEMBLY__
+#include <asm/byteorder.h>
+
+/*
+ * This struct is more or less a vastly simplified version of the DWARF Call
+ * Frame Information standard. It contains only the necessary parts of DWARF
+ * CFI, simplified for ease of access by the in-kernel unwinder. It tells the
+ * unwinder how to find the previous SP and BP (and sometimes entry regs) on
+ * the stack for a given code address. Each instance of the struct corresponds
+ * to one or more code locations.
+ */
+struct orc_entry {
+ s16 sp_offset;
+ s16 bp_offset;
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ unsigned sp_reg:4;
+ unsigned bp_reg:4;
+ unsigned type:2;
+ unsigned end:1;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ unsigned bp_reg:4;
+ unsigned sp_reg:4;
+ unsigned unused:5;
+ unsigned end:1;
+ unsigned type:2;
+#endif
+} __packed;
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ORC_TYPES_H */
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index edaf0faf766f..339cf3bf5ce2 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -61,6 +61,7 @@
#define RUNTIME_DISCARD_EXIT
#include <asm-generic/vmlinux.lds.h>
+#include <asm-generic/orc_lookup.h>
#include <asm/cache.h>
#include <asm/kernel-pgtable.h>
#include <asm/kexec.h>
@@ -306,6 +307,8 @@ SECTIONS
__pecoff_data_size = ABSOLUTE(. - __initdata_begin);
_end = .;
+ ORC_UNWIND_TABLE
+
STABS_DEBUG
DWARF_DEBUG
ELF_DETAILS
diff --git a/scripts/Makefile b/scripts/Makefile
index ce5aa9030b74..5be2552e4d02 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -20,8 +20,12 @@ HOSTLDLIBS_sign-file = $(shell pkg-config --libs libcrypto 2> /dev/null || echo
ifdef CONFIG_UNWINDER_ORC
ifeq ($(ARCH),x86_64)
ARCH := x86
-endif
HOSTCFLAGS_sorttable.o += -I$(srctree)/tools/arch/x86/include
+endif
+ifeq ($(ARCH),arm64)
+HOSTCFLAGS_sorttable.o += -I$(srctree)/tools/arch/arm64/include
+endif
+
HOSTCFLAGS_sorttable.o += -DUNWINDER_ORC_ENABLED
endif
diff --git a/tools/arch/arm64/include/asm/orc_types.h b/tools/arch/arm64/include/asm/orc_types.h
new file mode 100644
index 000000000000..9c06e7a6ed55
--- /dev/null
+++ b/tools/arch/arm64/include/asm/orc_types.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2017 Josh Poimboeuf <jpoimboe@redhat.com>
+ */
+
+#ifndef _ORC_TYPES_H
+#define _ORC_TYPES_H
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+
+/*
+ * The ORC_REG_* registers are base registers which are used to find other
+ * registers on the stack.
+ *
+ * ORC_REG_PREV_SP, also known as DWARF Call Frame Address (CFA), is the
+ * address of the previous frame: the caller's SP before it called the current
+ * function.
+ *
+ * ORC_REG_UNDEFINED means the corresponding register's value didn't change in
+ * the current frame.
+ *
+ * The most commonly used base registers are SP and BP -- which the previous SP
+ * is usually based on -- and PREV_SP and UNDEFINED -- which the previous BP is
+ * usually based on.
+ *
+ * The rest of the base registers are needed for special cases like entry code
+ * and GCC realigned stacks.
+ */
+#define ORC_REG_UNDEFINED 0
+#define ORC_REG_PREV_SP 1
+#define ORC_REG_BP 2
+#define ORC_REG_SP 3
+#define ORC_REG_BP_INDIRECT 4
+#define ORC_REG_SP_INDIRECT 5
+#define ORC_REG_MAX 6
+
+#ifndef __ASSEMBLY__
+#include <asm/byteorder.h>
+
+/*
+ * This struct is more or less a vastly simplified version of the DWARF Call
+ * Frame Information standard. It contains only the necessary parts of DWARF
+ * CFI, simplified for ease of access by the in-kernel unwinder. It tells the
+ * unwinder how to find the previous SP and BP (and sometimes entry regs) on
+ * the stack for a given code address. Each instance of the struct corresponds
+ * to one or more code locations.
+ */
+struct orc_entry {
+ s16 sp_offset;
+ s16 bp_offset;
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ unsigned sp_reg:4;
+ unsigned bp_reg:4;
+ unsigned type:2;
+ unsigned end:1;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ unsigned bp_reg:4;
+ unsigned sp_reg:4;
+ unsigned unused:5;
+ unsigned end:1;
+ unsigned type:2;
+#endif
+} __packed;
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ORC_TYPES_H */
diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile
index 3f7c7b54c741..e17c1fd90982 100644
--- a/tools/objtool/Makefile
+++ b/tools/objtool/Makefile
@@ -46,6 +46,7 @@ ifeq ($(SRCARCH),x86)
endif
ifeq ($(SRCARCH),arm64)
+ BUILD_ORC := y
CFLAGS += -Wno-nested-externs
endif
diff --git a/tools/objtool/arch/arm64/Build b/tools/objtool/arch/arm64/Build
index f3de3a50d541..00221087eefe 100644
--- a/tools/objtool/arch/arm64/Build
+++ b/tools/objtool/arch/arm64/Build
@@ -1,5 +1,6 @@
objtool-y += special.o
objtool-y += decode.o
+objtool-y += orc.o
objtool-y += libhweight.o
diff --git a/tools/objtool/arch/arm64/orc.c b/tools/objtool/arch/arm64/orc.c
new file mode 100644
index 000000000000..aa8404c482b6
--- /dev/null
+++ b/tools/objtool/arch/arm64/orc.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2017 Josh Poimboeuf <jpoimboe@redhat.com>
+ */
+
+#include <stdlib.h>
+
+#include <linux/objtool.h>
+
+#include <objtool/orc.h>
+#include <objtool/warn.h>
+
+int init_orc_entry(struct orc_entry *orc, struct cfi_state *cfi,
+ struct instruction *insn)
+{
+ struct cfi_reg *bp = &cfi->regs[CFI_BP];
+
+ memset(orc, 0, sizeof(*orc));
+
+ if (!cfi) {
+ orc->end = 0;
+ orc->sp_reg = ORC_REG_UNDEFINED;
+ return 0;
+ }
+
+ orc->end = cfi->end;
+
+ if (cfi->cfa.base == CFI_UNDEFINED) {
+ orc->sp_reg = ORC_REG_UNDEFINED;
+ return 0;
+ }
+
+ switch (cfi->cfa.base) {
+ case CFI_SP:
+ orc->sp_reg = ORC_REG_SP;
+ break;
+ case CFI_SP_INDIRECT:
+ orc->sp_reg = ORC_REG_SP_INDIRECT;
+ break;
+ case CFI_BP:
+ orc->sp_reg = ORC_REG_BP;
+ break;
+ case CFI_BP_INDIRECT:
+ orc->sp_reg = ORC_REG_BP_INDIRECT;
+ break;
+ default:
+ WARN_FUNC("unknown CFA base reg %d",
+ insn->sec, insn->offset, cfi->cfa.base);
+ return -1;
+ }
+
+ switch (bp->base) {
+ case CFI_UNDEFINED:
+ orc->bp_reg = ORC_REG_UNDEFINED;
+ break;
+ case CFI_CFA:
+ orc->bp_reg = ORC_REG_PREV_SP;
+ break;
+ case CFI_BP:
+ orc->bp_reg = ORC_REG_BP;
+ break;
+ default:
+ WARN_FUNC("unknown BP base reg %d",
+ insn->sec, insn->offset, bp->base);
+ return -1;
+ }
+
+ orc->sp_offset = cfi->cfa.offset;
+ orc->bp_offset = bp->offset;
+ orc->type = cfi->type;
+
+ return 0;
+}
+
+static const char *reg_name(unsigned int reg)
+{
+ switch (reg) {
+ case ORC_REG_PREV_SP:
+ return "prevsp";
+ case ORC_REG_BP:
+ return "fp";
+ case ORC_REG_SP:
+ return "sp";
+ case ORC_REG_BP_INDIRECT:
+ return "fp(ind)";
+ case ORC_REG_SP_INDIRECT:
+ return "sp(ind)";
+ default:
+ return "?";
+ }
+}
+
+const char *orc_type_name(unsigned int type)
+{
+ switch (type) {
+ case UNWIND_HINT_TYPE_CALL:
+ return "call";
+ case UNWIND_HINT_TYPE_REGS:
+ return "regs";
+ case UNWIND_HINT_TYPE_REGS_PARTIAL:
+ return "regs (partial)";
+ default:
+ return "?";
+ }
+}
+
+void orc_print_reg(unsigned int reg, int offset)
+{
+ if (reg == ORC_REG_BP_INDIRECT)
+ printf("(fp%+d)", offset);
+ else if (reg == ORC_REG_SP_INDIRECT)
+ printf("(sp%+d)", offset);
+ else if (reg == ORC_REG_UNDEFINED)
+ printf("(und)");
+ else
+ printf("%s%+d", reg_name(reg), offset);
+}
--
2.17.1
next prev parent reply other threads:[~2022-06-22 16:04 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-06-22 15:48 [PATCH v5 00/33] objtool: add base support for arm64 Chen Zhongjin
2022-06-22 15:48 ` [PATCH v5 01/33] tools: arm64: Make aarch64 instruction decoder available to tools Chen Zhongjin
2022-06-22 15:48 ` [PATCH v5 02/33] objtool: arm64: Add base definition for arm64 backend Chen Zhongjin
2022-06-22 15:48 ` [PATCH v5 03/33] objtool: arm64: Decode add/sub instructions Chen Zhongjin
2022-06-22 15:48 ` [PATCH v5 04/33] objtool: arm64: Decode jump and call related instructions Chen Zhongjin
2022-06-22 15:48 ` [PATCH v5 05/33] objtool: arm64: Decode other system instructions Chen Zhongjin
2022-06-22 15:48 ` [PATCH v5 06/33] objtool: arm64: Decode load/store instructions Chen Zhongjin
2022-06-22 15:48 ` [PATCH v5 07/33] objtool: arm64: Decode LDR instructions Chen Zhongjin
2022-06-22 15:48 ` [PATCH v5 08/33] objtool: arm64: Accept non-instruction data in code sections Chen Zhongjin
2022-06-22 15:48 ` [PATCH v5 09/33] objtool: check: Support data in text section Chen Zhongjin
2022-06-22 15:48 ` [PATCH v5 10/33] objtool: arm64: Handle supported relocations in alternatives Chen Zhongjin
2022-06-22 15:48 ` [PATCH v5 11/33] objtool: arm64: Ignore replacement section for alternative callback Chen Zhongjin
2022-06-22 15:48 ` [PATCH v5 12/33] objtool: arm64: Enable stack validation for arm64 Chen Zhongjin
2022-06-22 15:49 ` Chen Zhongjin [this message]
2022-06-22 15:49 ` [PATCH v5 14/33] objtool: arm64: Add annotate_reachable() for objtools Chen Zhongjin
2022-06-22 15:49 ` [PATCH v5 15/33] arm64: bug: Add reachable annotation to warning macros Chen Zhongjin
2022-06-22 15:49 ` [PATCH v5 16/33] arm64: kgdb: Add reachable annotation after kgdb brk Chen Zhongjin
2022-06-22 15:49 ` [PATCH v5 17/33] objtool: arm64: Add unwind_hint support Chen Zhongjin
2022-06-22 15:49 ` [PATCH v5 18/33] arm64: Change symbol type annotations Chen Zhongjin
2022-06-22 15:49 ` [PATCH v5 19/33] arm64: Annotate unwind_hint for symbols with empty stack Chen Zhongjin
2022-06-22 15:49 ` [PATCH v5 20/33] arm64: entry: Annotate unwind_hint for entry Chen Zhongjin
2022-06-22 15:49 ` [PATCH v5 21/33] arm64: kvm: Annotate unwind_hint for hyp entry Chen Zhongjin
2022-06-22 15:49 ` [PATCH v5 22/33] arm64: efi-header: Mark efi header as data Chen Zhongjin
2022-06-22 15:49 ` [PATCH v5 23/33] arm64: head: Mark constants " Chen Zhongjin
2022-06-22 15:49 ` [PATCH v5 24/33] arm64: proc: Mark constant " Chen Zhongjin
2022-06-22 15:49 ` [PATCH v5 25/33] arm64: crypto: " Chen Zhongjin
2022-06-22 15:49 ` [PATCH v5 26/33] arm64: crypto: Remove unnecessary stackframe Chen Zhongjin
2022-06-22 15:49 ` [PATCH v5 27/33] arm64: Set intra-function call annotations Chen Zhongjin
2022-06-22 15:49 ` [PATCH v5 28/33] arm64: sleep: Properly set frame pointer before call Chen Zhongjin
2022-06-22 15:49 ` [PATCH v5 29/33] arm64: compat: Move VDSO code to .rodata section Chen Zhongjin
2022-06-22 15:49 ` [PATCH v5 30/33] arm64: entry: Align stack size for alternative Chen Zhongjin
2022-06-22 15:49 ` [PATCH v5 31/33] arm64: kernel: Skip validation of proton-pack.c Chen Zhongjin
2022-06-22 15:49 ` [PATCH v5 32/33] arm64: irq-gic: Replace unreachable() with -EINVAL Chen Zhongjin
2022-06-22 15:49 ` [PATCH v5 33/33] objtool: revert c_file fallthrough detection for arm64 Chen Zhongjin
2022-06-22 17:19 ` [PATCH v5 00/33] objtool: add base support " Daniel Thompson
2022-06-23 1:37 ` Chen Zhongjin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220622154920.95075-14-chenzhongjin@huawei.com \
--to=chenzhongjin@huawei.com \
--cc=broonie@kernel.org \
--cc=catalin.marinas@arm.com \
--cc=jpoimboe@kernel.org \
--cc=linux-arch@vger.kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kbuild@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=live-patching@vger.kernel.org \
--cc=madvenka@linux.microsoft.com \
--cc=mark.rutland@arm.com \
--cc=masahiroy@kernel.org \
--cc=michal.lkml@markovi.net \
--cc=ndesaulniers@google.com \
--cc=pasha.tatashin@soleen.com \
--cc=peterz@infradead.org \
--cc=rmk+kernel@armlinux.org.uk \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).