2023-06-20 08:38:09

by Youling Tang

[permalink] [raw]
Subject: [RFC PATCH v1 20/23] LoongArch: Move some data definitions into the .data section

Make part of the data definition into the .data section, avoid objtool
to detect "unreachable instruction" warning.

At the same time, removing unreachable instruction flow operations
(b process_entry).

Co-developed-by: Jinyang He <[email protected]>
Signed-off-by: Jinyang He <[email protected]>
Signed-off-by: Youling Tang <[email protected]>
---
arch/loongarch/kernel/genex.S | 2 ++
arch/loongarch/kernel/relocate_kernel.S | 7 +++----
2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/arch/loongarch/kernel/genex.S b/arch/loongarch/kernel/genex.S
index 44ff1ff64260..883b718b5ffe 100644
--- a/arch/loongarch/kernel/genex.S
+++ b/arch/loongarch/kernel/genex.S
@@ -77,7 +77,9 @@ SYM_FUNC_END(except_vec_cex)
668:
RESTORE_ALL_AND_RET
SYM_FUNC_END(handle_\exception)
+ .pushsection ".data", "aw", %progbits
SYM_DATA(unwind_hint_\exception, .word 668b - 666b)
+ .popsection
.endm

BUILD_HANDLER ade ade badv
diff --git a/arch/loongarch/kernel/relocate_kernel.S b/arch/loongarch/kernel/relocate_kernel.S
index d0123fa2b511..1ea3df967b46 100644
--- a/arch/loongarch/kernel/relocate_kernel.S
+++ b/arch/loongarch/kernel/relocate_kernel.S
@@ -75,7 +75,6 @@ copy_word:
LONG_ADDI s5, s5, -1
beqz s5, process_entry
b copy_word
- b process_entry

done:
ibar 0
@@ -112,6 +111,6 @@ SYM_CODE_END(kexec_smp_wait)

relocate_new_kernel_end:

-SYM_DATA_START(relocate_new_kernel_size)
- PTR relocate_new_kernel_end - relocate_new_kernel
-SYM_DATA_END(relocate_new_kernel_size)
+.pushsection ".data", "aw", %progbits
+SYM_DATA(relocate_new_kernel_size, .long relocate_new_kernel_end - relocate_new_kernel)
+.popsection
--
2.39.2



2023-06-20 08:46:30

by Youling Tang

[permalink] [raw]
Subject: [RFC PATCH v1 21/23] objtool: Add arch-specific "noreturn" function handling

Fix the following warnings:
arch/loongarch/mm/fault.o: warning: objtool: no_context.part.0() falls through to
next function do_sigsegv()

It should mark 'dead_end' when the function is "noreturn/__noreturn".

Signed-off-by: Youling Tang <[email protected]>
---
tools/objtool/arch/loongarch/special.c | 5 +++++
tools/objtool/arch/powerpc/special.c | 3 +++
tools/objtool/arch/x86/special.c | 4 ++++
tools/objtool/check.c | 7 ++++++-
tools/objtool/include/objtool/special.h | 3 +++
5 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/tools/objtool/arch/loongarch/special.c b/tools/objtool/arch/loongarch/special.c
index 8669dbe44459..be4d5d83e331 100644
--- a/tools/objtool/arch/loongarch/special.c
+++ b/tools/objtool/arch/loongarch/special.c
@@ -5,6 +5,11 @@
#include <objtool/special.h>
#include <objtool/builtin.h>

+/* Architecture specific "noreturn" function */
+const char * const arch_noreturns[] = {
+ "die",
+};
+int arch_noreturns_size = ARRAY_SIZE(arch_noreturns);

bool arch_support_alt_relocation(struct special_alt *special_alt,
struct instruction *insn,
diff --git a/tools/objtool/arch/powerpc/special.c b/tools/objtool/arch/powerpc/special.c
index d33868147196..35107e6ae2f1 100644
--- a/tools/objtool/arch/powerpc/special.c
+++ b/tools/objtool/arch/powerpc/special.c
@@ -4,6 +4,9 @@
#include <objtool/special.h>
#include <objtool/builtin.h>

+/* Architecture specific "noreturn" function */
+const char * const arch_noreturns[] = {};
+int arch_noreturns_size = ARRAY_SIZE(arch_noreturns);

bool arch_support_alt_relocation(struct special_alt *special_alt,
struct instruction *insn,
diff --git a/tools/objtool/arch/x86/special.c b/tools/objtool/arch/x86/special.c
index 7c97b7391279..48fa72f564f9 100644
--- a/tools/objtool/arch/x86/special.c
+++ b/tools/objtool/arch/x86/special.c
@@ -7,6 +7,10 @@
#define X86_FEATURE_POPCNT (4 * 32 + 23)
#define X86_FEATURE_SMAP (9 * 32 + 20)

+/* Architecture specific "noreturn" function */
+const char * const arch_noreturns[] = {};
+int arch_noreturns_size = ARRAY_SIZE(arch_noreturns);
+
void arch_handle_alternative(unsigned short feature, struct special_alt *alt)
{
switch (feature) {
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index f91723010d6b..c637e54088f6 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -110,11 +110,16 @@ static bool __dead_end_function(struct objtool_file *file, struct symbol *func,
if (func->bind == STB_WEAK)
return false;

- if (func->bind == STB_GLOBAL)
+ if (func->bind == STB_GLOBAL) {
for (i = 0; i < ARRAY_SIZE(global_noreturns); i++)
if (!strcmp(func->name, global_noreturns[i]))
return true;

+ for (i = 0; i < arch_noreturns_size; i++)
+ if (!strcmp(func->name, arch_noreturns[i]))
+ return true;
+ }
+
if (!func->len)
return false;

diff --git a/tools/objtool/include/objtool/special.h b/tools/objtool/include/objtool/special.h
index 86d4af9c5aa9..f800817f0ed8 100644
--- a/tools/objtool/include/objtool/special.h
+++ b/tools/objtool/include/objtool/special.h
@@ -30,6 +30,9 @@ struct special_alt {
unsigned int orig_len, new_len; /* group only */
};

+extern const char * const arch_noreturns[];
+extern int arch_noreturns_size;
+
int special_get_alts(struct elf *elf, struct list_head *alts);

void arch_handle_alternative(unsigned short feature, struct special_alt *alt);
--
2.39.2


2023-06-20 08:55:48

by Youling Tang

[permalink] [raw]
Subject: [RFC PATCH v1 23/23] LoongArch: objtool: Mark non-standard object files and directories

Set OBJECT_FILES_NON_STANDARD for their related files and directories,
which will tell objtool to skip checking them. It's ok to skip them
because they don't affect runtime stack traces.

Signed-off-by: Youling Tang <[email protected]>
---
arch/loongarch/kernel/Makefile | 2 ++
arch/loongarch/power/Makefile | 2 ++
arch/loongarch/vdso/Makefile | 2 ++
3 files changed, 6 insertions(+)

diff --git a/arch/loongarch/kernel/Makefile b/arch/loongarch/kernel/Makefile
index fcbfa0f38b53..9ea4d6b93f4d 100644
--- a/arch/loongarch/kernel/Makefile
+++ b/arch/loongarch/kernel/Makefile
@@ -3,6 +3,8 @@
# Makefile for the Linux/LoongArch kernel.
#

+OBJECT_FILES_NON_STANDARD_head.o := y
+
extra-y := vmlinux.lds

obj-y += head.o cpu-probe.o cacheinfo.o env.o setup.o entry.o genex.o \
diff --git a/arch/loongarch/power/Makefile b/arch/loongarch/power/Makefile
index 58151d003e40..bbd1d4793e8b 100644
--- a/arch/loongarch/power/Makefile
+++ b/arch/loongarch/power/Makefile
@@ -1,3 +1,5 @@
+OBJECT_FILES_NON_STANDARD_suspend_asm.o := y
+
obj-y += platform.o

obj-$(CONFIG_SUSPEND) += suspend.o suspend_asm.o
diff --git a/arch/loongarch/vdso/Makefile b/arch/loongarch/vdso/Makefile
index d89e2ac75f7b..37c7795990b8 100644
--- a/arch/loongarch/vdso/Makefile
+++ b/arch/loongarch/vdso/Makefile
@@ -1,6 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
# Objects to go into the VDSO.

+OBJECT_FILES_NON_STANDARD := y
+
# Absolute relocation type $(ARCH_REL_TYPE_ABS) needs to be defined before
# the inclusion of generic Makefile.
ARCH_REL_TYPE_ABS := R_LARCH_32|R_LARCH_64|R_LARCH_MARK_LA|R_LARCH_JUMP_SLOT
--
2.39.2


2023-06-20 08:57:02

by Youling Tang

[permalink] [raw]
Subject: [RFC PATCH v1 22/23] objtool: Make update_cfi_state() arch-specific function

Currently update_cfi_state() is implemented for the x86_64 architecture. This
function is specific to the architecture. In order to avoid powerpc build
errors, define x86_64 as the default implementation and rename update_cfi_state()
to arch_update_cfi_state().

LoongArch will reimplement arch_update_cfi_state().

Co-developed-by: Jinyang He <[email protected]>
Signed-off-by: Jinyang He <[email protected]>
Signed-off-by: Youling Tang <[email protected]>
---
tools/objtool/arch/loongarch/decode.c | 76 +++++++++++++++++++++++++++
tools/objtool/check.c | 10 ++--
tools/objtool/include/objtool/arch.h | 3 ++
tools/objtool/include/objtool/check.h | 5 ++
4 files changed, 89 insertions(+), 5 deletions(-)

diff --git a/tools/objtool/arch/loongarch/decode.c b/tools/objtool/arch/loongarch/decode.c
index 90adbbeab8d4..6ca8cbad6813 100644
--- a/tools/objtool/arch/loongarch/decode.c
+++ b/tools/objtool/arch/loongarch/decode.c
@@ -4,6 +4,8 @@
#include <stdlib.h>

#include <linux/bitops.h>
+#include <linux/objtool.h>
+
#include <asm/inst.h>
#include <asm/orc_types.h>

@@ -274,3 +276,77 @@ void arch_initial_func_cfi_state(struct cfi_init_state *state)
state->cfa.base = CFI_SP;
state->cfa.offset = 0;
}
+
+
+int arch_update_cfi_state(struct instruction *insn,
+ struct instruction *next_insn,
+ struct cfi_state *cfi, struct stack_op *op)
+{
+ struct cfi_reg *cfa = &cfi->cfa;
+ struct cfi_reg *regs = cfi->regs;
+
+ /* stack operations don't make sense with an undefined CFA */
+ if (cfa->base == CFI_UNDEFINED) {
+ if (insn_func(insn)) {
+ WARN_FUNC("undefined stack state", insn->sec, insn->offset);
+ return -1;
+ }
+ return 0;
+ }
+
+ if (cfi->type == UNWIND_HINT_TYPE_REGS)
+ return update_cfi_state_regs(insn, cfi, op);
+
+
+ switch (op->dest.type) {
+ case OP_DEST_REG:
+ switch (op->src.type) {
+ case OP_SRC_ADD:
+ if (op->dest.reg == CFI_SP && op->src.reg == CFI_SP) {
+ /* addi.d sp, sp, imm */
+ cfi->stack_size -= op->src.offset;
+ if (cfa->base == CFI_SP)
+ cfa->offset -= op->src.offset;
+ } else if (op->dest.reg == CFI_FP && op->src.reg == CFI_SP) {
+ /* addi.d fp, sp, imm */
+ if (cfa->base == CFI_SP && cfa->offset == op->src.offset) {
+ cfa->base = CFI_FP;
+ cfa->offset = 0;
+ }
+ } else if (op->dest.reg == CFI_SP && op->src.reg == CFI_FP) {
+ /* addi.d sp, fp, imm */
+ if (cfa->base == CFI_FP && cfa->offset == 0) {
+ cfa->base = CFI_SP;
+ cfa->offset = -op->src.offset;
+ }
+ }
+ break;
+ case OP_SRC_REG_INDIRECT:
+ /* ld.d _reg, sp, imm */
+ if (op->src.reg == CFI_SP &&
+ op->src.offset == (regs[op->dest.reg].offset + cfi->stack_size)) {
+ restore_reg(cfi, op->dest.reg);
+ /* Gcc may not restore sp, we adjust it directly. */
+ if (cfa->base == CFI_FP && cfa->offset == 0) {
+ cfa->base = CFI_SP;
+ cfa->offset = cfi->stack_size;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ case OP_DEST_REG_INDIRECT:
+ if (op->src.type == OP_SRC_REG)
+ /* st.d _reg, sp, imm */
+ if (op->dest.offset)
+ save_reg(cfi, op->src.reg, CFI_CFA, op->dest.offset - cfi->stack_size);
+ break;
+ default:
+ WARN_FUNC("unknown stack-related instruction", insn->sec, insn->offset);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index c637e54088f6..42f87a33f558 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -2230,7 +2230,7 @@ static bool has_valid_stack_frame(struct insn_state *state)
return false;
}

-static int update_cfi_state_regs(struct instruction *insn,
+int update_cfi_state_regs(struct instruction *insn,
struct cfi_state *cfi,
struct stack_op *op)
{
@@ -2255,7 +2255,7 @@ static int update_cfi_state_regs(struct instruction *insn,
return 0;
}

-static void save_reg(struct cfi_state *cfi, unsigned char reg, int base, int offset)
+void save_reg(struct cfi_state *cfi, unsigned char reg, int base, int offset)
{
if (arch_callee_saved_reg(reg) &&
cfi->regs[reg].base == CFI_UNDEFINED) {
@@ -2264,7 +2264,7 @@ static void save_reg(struct cfi_state *cfi, unsigned char reg, int base, int off
}
}

-static void restore_reg(struct cfi_state *cfi, unsigned char reg)
+void restore_reg(struct cfi_state *cfi, unsigned char reg)
{
cfi->regs[reg].base = initial_func_cfi.regs[reg].base;
cfi->regs[reg].offset = initial_func_cfi.regs[reg].offset;
@@ -2323,7 +2323,7 @@ static void restore_reg(struct cfi_state *cfi, unsigned char reg)
* 41 5d pop %r13
* c3 retq
*/
-static int update_cfi_state(struct instruction *insn,
+int __weak arch_update_cfi_state(struct instruction *insn,
struct instruction *next_insn,
struct cfi_state *cfi, struct stack_op *op)
{
@@ -2795,7 +2795,7 @@ static int handle_insn_ops(struct instruction *insn,

for (op = insn->stack_ops; op; op = op->next) {

- if (update_cfi_state(insn, next_insn, &state->cfi, op))
+ if (arch_update_cfi_state(insn, next_insn, &state->cfi, op))
return 1;

if (!insn->alt_group)
diff --git a/tools/objtool/include/objtool/arch.h b/tools/objtool/include/objtool/arch.h
index 2b6d2ce4f9a5..88570c598752 100644
--- a/tools/objtool/include/objtool/arch.h
+++ b/tools/objtool/include/objtool/arch.h
@@ -95,4 +95,7 @@ int arch_rewrite_retpolines(struct objtool_file *file);

bool arch_pc_relative_reloc(struct reloc *reloc);

+int __weak arch_update_cfi_state(struct instruction *insn,
+ struct instruction *next_insn,
+ struct cfi_state *cfi, struct stack_op *op);
#endif /* _ARCH_H */
diff --git a/tools/objtool/include/objtool/check.h b/tools/objtool/include/objtool/check.h
index 34898364bf03..dd1b95c67620 100644
--- a/tools/objtool/include/objtool/check.h
+++ b/tools/objtool/include/objtool/check.h
@@ -33,4 +33,9 @@ struct alt_group {

extern unsigned long nr_insns;

+int update_cfi_state_regs(struct instruction *insn,
+ struct cfi_state *cfi,
+ struct stack_op *op);
+void save_reg(struct cfi_state *cfi, unsigned char reg, int base, int offset);
+void restore_reg(struct cfi_state *cfi, unsigned char reg);
#endif /* _CHECK_H */
--
2.39.2