2022-08-01 12:55:12

by Qing Zhang

[permalink] [raw]
Subject: [PATCH 0/4] LoongArch: Add unwinder support

This series in order to add stacktrace suport, Some upcoming features require
these changes, like trace, divide unwinder into guess unwinder and prologue
unwinder is to add new unwinders in the future, eg:unwind_frame, unwind_orc .etc.
Three stages when we do unwind,
1) unwind_start(), the prapare of unwinding, fill unwind_state.
2) unwind_done(), judge whether the unwind process is finished or not.
3) unwind_next_frame(), unwind the next frame.

you can test them by:
1) echo t > /proc/sysrq-trigger
2) cat /proc/*/stack
4) ftrace: function graph
5) uprobe: echo 1 > ./options/userstacktrace

Changes from v1 to v2:

- Add the judgment of the offset value of ra in the prologue.
(Suggested by Youling).
- Create an inline function to check the sign bit, which is convenient
for extending other types of immediates. (Suggested by Jinyang).
- Fix sparse warning :
arch/loongarch/include/asm/uaccess.h:232:32: sparse: sparse: incorrect
type in argument 2 (different address spaces) @@ expected void const
*from @@ got void const [noderef] __user *from @@
- Add USER_STACKTRACE support as a series.

Qing Zhang (4):
LoongArch: Add guess unwinder support
LoongArch: Add prologue unwinder support
LoongArch: Add stacktrace support
LoongArch: Add USER_STACKTRACE support

arch/loongarch/Kconfig | 6 +
arch/loongarch/Kconfig.debug | 28 ++++
arch/loongarch/include/asm/inst.h | 52 +++++++
arch/loongarch/include/asm/processor.h | 9 ++
arch/loongarch/include/asm/stacktrace.h | 22 +++
arch/loongarch/include/asm/switch_to.h | 14 +-
arch/loongarch/include/asm/uaccess.h | 4 +-
arch/loongarch/include/asm/unwind.h | 45 +++++++
arch/loongarch/kernel/Makefile | 4 +
arch/loongarch/kernel/asm-offsets.c | 2 +
arch/loongarch/kernel/process.c | 64 +++++++++
arch/loongarch/kernel/stacktrace.c | 79 +++++++++++
arch/loongarch/kernel/switch.S | 2 +
arch/loongarch/kernel/traps.c | 27 ++--
arch/loongarch/kernel/unwind_guess.c | 65 +++++++++
arch/loongarch/kernel/unwind_prologue.c | 172 ++++++++++++++++++++++++
16 files changed, 577 insertions(+), 18 deletions(-)
create mode 100644 arch/loongarch/include/asm/unwind.h
create mode 100644 arch/loongarch/kernel/stacktrace.c
create mode 100644 arch/loongarch/kernel/unwind_guess.c
create mode 100644 arch/loongarch/kernel/unwind_prologue.c

--
2.20.1



2022-08-01 12:55:18

by Qing Zhang

[permalink] [raw]
Subject: [PATCH 3/4] LoongArch: Add stacktrace support

Use common arch_stack_walk infrastructure to avoid duplicated code and
avoid taking care of the stack storage and filtering.
Add sra (means __schedule return address) and scfa (means __schedule call
frame address) to thread_info and store it in switch_to().

Now we can print the process stack by cat /proc/*/stack and can better
support ftrace.

Signed-off-by: Qing Zhang <[email protected]>
---
arch/loongarch/Kconfig | 5 ++++
arch/loongarch/include/asm/processor.h | 9 +++++++
arch/loongarch/include/asm/switch_to.h | 14 ++++++----
arch/loongarch/include/asm/uaccess.h | 4 +--
arch/loongarch/kernel/Makefile | 1 +
arch/loongarch/kernel/asm-offsets.c | 2 ++
arch/loongarch/kernel/process.c | 3 +++
arch/loongarch/kernel/stacktrace.c | 37 ++++++++++++++++++++++++++
arch/loongarch/kernel/switch.S | 2 ++
9 files changed, 70 insertions(+), 7 deletions(-)
create mode 100644 arch/loongarch/kernel/stacktrace.c

diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
index 62b5b07fa4e1..85d0fa3147cd 100644
--- a/arch/loongarch/Kconfig
+++ b/arch/loongarch/Kconfig
@@ -38,6 +38,7 @@ config LOONGARCH
select ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE if !PREEMPTION
select ARCH_MIGHT_HAVE_PC_PARPORT
select ARCH_MIGHT_HAVE_PC_SERIO
+ select ARCH_STACKWALK
select ARCH_SPARSEMEM_ENABLE
select ARCH_SUPPORTS_ACPI
select ARCH_SUPPORTS_ATOMIC_RMW
@@ -140,6 +141,10 @@ config LOCKDEP_SUPPORT
bool
default y

+config STACKTRACE_SUPPORT
+ bool
+ default y
+
# MACH_LOONGSON32 and MACH_LOONGSON64 are delibrately carried over from the
# MIPS Loongson code, to preserve Loongson-specific code paths in drivers that
# are shared between architectures, and specifically expecting the symbols.
diff --git a/arch/loongarch/include/asm/processor.h b/arch/loongarch/include/asm/processor.h
index 57ec45aa078e..1c4b4308378d 100644
--- a/arch/loongarch/include/asm/processor.h
+++ b/arch/loongarch/include/asm/processor.h
@@ -101,6 +101,10 @@ struct thread_struct {
unsigned long reg23, reg24, reg25, reg26; /* s0-s3 */
unsigned long reg27, reg28, reg29, reg30, reg31; /* s4-s8 */

+ /* __schedule() return address / call frame address */
+ unsigned long sched_ra;
+ unsigned long sched_cfa;
+
/* CSR registers */
unsigned long csr_prmd;
unsigned long csr_crmd;
@@ -129,6 +133,9 @@ struct thread_struct {
struct loongarch_fpu fpu FPU_ALIGN;
};

+#define thread_saved_ra(tsk) (tsk->thread.sched_ra)
+#define thread_saved_fp(tsk) (tsk->thread.sched_cfa)
+
#define INIT_THREAD { \
/* \
* Main processor registers \
@@ -145,6 +152,8 @@ struct thread_struct {
.reg29 = 0, \
.reg30 = 0, \
.reg31 = 0, \
+ .sched_ra = 0, \
+ .sched_cfa = 0, \
.csr_crmd = 0, \
.csr_prmd = 0, \
.csr_euen = 0, \
diff --git a/arch/loongarch/include/asm/switch_to.h b/arch/loongarch/include/asm/switch_to.h
index 2a8d04375574..43a5ab162d38 100644
--- a/arch/loongarch/include/asm/switch_to.h
+++ b/arch/loongarch/include/asm/switch_to.h
@@ -15,12 +15,15 @@ struct task_struct;
* @prev: The task previously executed.
* @next: The task to begin executing.
* @next_ti: task_thread_info(next).
+ * @sched_ra: __schedule return address.
+ * @sched_cfa: __schedule call frame address.
*
* This function is used whilst scheduling to save the context of prev & load
* the context of next. Returns prev.
*/
extern asmlinkage struct task_struct *__switch_to(struct task_struct *prev,
- struct task_struct *next, struct thread_info *next_ti);
+ struct task_struct *next, struct thread_info *next_ti,
+ void *sched_ra, void *sched_cfa);

/*
* For newly created kernel threads switch_to() will return to
@@ -28,10 +31,11 @@ extern asmlinkage struct task_struct *__switch_to(struct task_struct *prev,
* That is, everything following __switch_to() will be skipped for new threads.
* So everything that matters to new threads should be placed before __switch_to().
*/
-#define switch_to(prev, next, last) \
-do { \
- lose_fpu_inatomic(1, prev); \
- (last) = __switch_to(prev, next, task_thread_info(next)); \
+#define switch_to(prev, next, last) \
+do { \
+ lose_fpu_inatomic(1, prev); \
+ (last) = __switch_to(prev, next, task_thread_info(next), \
+ __builtin_return_address(0), __builtin_frame_address(0)); \
} while (0)

#endif /* _ASM_SWITCH_TO_H */
diff --git a/arch/loongarch/include/asm/uaccess.h b/arch/loongarch/include/asm/uaccess.h
index 2b44edc604a2..a8ae2af4025a 100644
--- a/arch/loongarch/include/asm/uaccess.h
+++ b/arch/loongarch/include/asm/uaccess.h
@@ -229,13 +229,13 @@ extern unsigned long __copy_user(void *to, const void *from, __kernel_size_t n);
static inline unsigned long __must_check
raw_copy_from_user(void *to, const void __user *from, unsigned long n)
{
- return __copy_user(to, from, n);
+ return __copy_user(to, (__force const void *)from, n);
}

static inline unsigned long __must_check
raw_copy_to_user(void __user *to, const void *from, unsigned long n)
{
- return __copy_user(to, from, n);
+ return __copy_user((__force void *)to, from, n);
}

#define INLINE_COPY_FROM_USER
diff --git a/arch/loongarch/kernel/Makefile b/arch/loongarch/kernel/Makefile
index 918600e7b30f..7449513eb08d 100644
--- a/arch/loongarch/kernel/Makefile
+++ b/arch/loongarch/kernel/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_EFI) += efi.o
obj-$(CONFIG_CPU_HAS_FPU) += fpu.o

obj-$(CONFIG_MODULES) += module.o module-sections.o
+obj-$(CONFIG_STACKTRACE) += stacktrace.o

obj-$(CONFIG_PROC_FS) += proc.o

diff --git a/arch/loongarch/kernel/asm-offsets.c b/arch/loongarch/kernel/asm-offsets.c
index 20cd9e16a95a..eb350f3ffae5 100644
--- a/arch/loongarch/kernel/asm-offsets.c
+++ b/arch/loongarch/kernel/asm-offsets.c
@@ -103,6 +103,8 @@ void output_thread_defines(void)
OFFSET(THREAD_REG29, task_struct, thread.reg29);
OFFSET(THREAD_REG30, task_struct, thread.reg30);
OFFSET(THREAD_REG31, task_struct, thread.reg31);
+ OFFSET(THREAD_SCHED_RA, task_struct, thread.sched_ra);
+ OFFSET(THREAD_SCHED_CFA, task_struct, thread.sched_cfa);
OFFSET(THREAD_CSRCRMD, task_struct,
thread.csr_crmd);
OFFSET(THREAD_CSRPRMD, task_struct,
diff --git a/arch/loongarch/kernel/process.c b/arch/loongarch/kernel/process.c
index 709b7a1664f8..34c3f2148714 100644
--- a/arch/loongarch/kernel/process.c
+++ b/arch/loongarch/kernel/process.c
@@ -135,6 +135,7 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
childregs = (struct pt_regs *) childksp - 1;
/* Put the stack after the struct pt_regs. */
childksp = (unsigned long) childregs;
+ p->thread.sched_cfa = 0;
p->thread.csr_euen = 0;
p->thread.csr_crmd = csr_read32(LOONGARCH_CSR_CRMD);
p->thread.csr_prmd = csr_read32(LOONGARCH_CSR_PRMD);
@@ -145,6 +146,7 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
p->thread.reg23 = (unsigned long)args->fn;
p->thread.reg24 = (unsigned long)args->fn_arg;
p->thread.reg01 = (unsigned long)ret_from_kernel_thread;
+ p->thread.sched_ra = (unsigned long)ret_from_kernel_thread;
memset(childregs, 0, sizeof(struct pt_regs));
childregs->csr_euen = p->thread.csr_euen;
childregs->csr_crmd = p->thread.csr_crmd;
@@ -161,6 +163,7 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)

p->thread.reg03 = (unsigned long) childregs;
p->thread.reg01 = (unsigned long) ret_from_fork;
+ p->thread.sched_ra = (unsigned long) ret_from_fork;

/*
* New tasks lose permission to use the fpu. This accelerates context
diff --git a/arch/loongarch/kernel/stacktrace.c b/arch/loongarch/kernel/stacktrace.c
new file mode 100644
index 000000000000..f4f4b8ad3917
--- /dev/null
+++ b/arch/loongarch/kernel/stacktrace.c
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Stack trace management functions
+ *
+ * Copyright (C) 2022 Loongson Technology Corporation Limited
+ */
+#include <linux/sched.h>
+#include <linux/stacktrace.h>
+
+#include <asm/stacktrace.h>
+#include <asm/unwind.h>
+
+void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie,
+ struct task_struct *task, struct pt_regs *regs)
+{
+ struct pt_regs dummyregs;
+ struct unwind_state state;
+ unsigned long addr;
+
+ regs = &dummyregs;
+
+ if (task == current) {
+ regs->csr_era = (unsigned long)__builtin_return_address(0);
+ regs->regs[3] = (unsigned long)__builtin_frame_address(0);
+ } else {
+ regs->csr_era = thread_saved_ra(task);
+ regs->regs[3] = thread_saved_fp(task);
+ }
+
+ regs->regs[1] = 0;
+ for (unwind_start(&state, task, regs);
+ !unwind_done(&state); unwind_next_frame(&state)) {
+ addr = unwind_get_return_address(&state);
+ if (!addr || !consume_entry(cookie, addr))
+ break;
+ }
+}
diff --git a/arch/loongarch/kernel/switch.S b/arch/loongarch/kernel/switch.S
index 37e84ac8ffc2..43ebbc3990f7 100644
--- a/arch/loongarch/kernel/switch.S
+++ b/arch/loongarch/kernel/switch.S
@@ -21,6 +21,8 @@ SYM_FUNC_START(__switch_to)

cpu_save_nonscratch a0
stptr.d ra, a0, THREAD_REG01
+ stptr.d a3, a0, THREAD_SCHED_RA
+ stptr.d a4, a0, THREAD_SCHED_CFA
move tp, a2
cpu_restore_nonscratch a1

--
2.20.1


2022-08-01 12:55:41

by Qing Zhang

[permalink] [raw]
Subject: [PATCH 2/4] LoongArch: Add prologue unwinder support

It unwind the stack frame based on prologue code analyze.
CONFIG_KALLSYMS is needed, at least the address and length
of each function.

Three stages when we do unwind,
(1)unwind_start(), the prapare of unwinding, fill unwind_state.
(2)unwind_done(), judge whether the unwind process is finished or not.
(3)unwind_next_frame(), unwind the next frame.

Dividing unwinder helps to add new unwinders in the future, eg:
unwind_frame, unwind_orc .etc

Signed-off-by: Qing Zhang <[email protected]>
---
arch/loongarch/Kconfig.debug | 19 +++
arch/loongarch/include/asm/inst.h | 52 +++++++
arch/loongarch/include/asm/unwind.h | 8 ++
arch/loongarch/kernel/Makefile | 1 +
arch/loongarch/kernel/traps.c | 5 +
arch/loongarch/kernel/unwind_prologue.c | 172 ++++++++++++++++++++++++
6 files changed, 257 insertions(+)
create mode 100644 arch/loongarch/kernel/unwind_prologue.c

diff --git a/arch/loongarch/Kconfig.debug b/arch/loongarch/Kconfig.debug
index 68634d4fa27b..57cdbe0cfd98 100644
--- a/arch/loongarch/Kconfig.debug
+++ b/arch/loongarch/Kconfig.debug
@@ -1,3 +1,11 @@
+choice
+ prompt "Choose kernel unwinder"
+ default UNWINDER_PROLOGUE if KALLSYMS
+ help
+ This determines which method will be used for unwinding kernel stack
+ traces for panics, oopses, bugs, warnings, perf, /proc/<pid>/stack,
+ lockdep, and more.
+
config UNWINDER_GUESS
bool "Guess unwinder"
help
@@ -7,3 +15,14 @@ config UNWINDER_GUESS

While this option often produces false positives, it can still be
useful in many cases.
+
+config UNWINDER_PROLOGUE
+ bool "Prologue unwinder"
+ depends on KALLSYMS
+ help
+ This option enables the "prologue" unwinder for unwinding kernel stack
+ traces. It unwind the stack frame based on prologue code analyze. Symbol
+ information is needed, at least the address and length of each function.
+ Some of the addresses it reports may be incorrect.
+
+endchoice
diff --git a/arch/loongarch/include/asm/inst.h b/arch/loongarch/include/asm/inst.h
index 575d1bb66ffb..b876907ca65a 100644
--- a/arch/loongarch/include/asm/inst.h
+++ b/arch/loongarch/include/asm/inst.h
@@ -23,12 +23,33 @@ enum reg1i20_op {
lu32id_op = 0x0b,
};

+enum reg1i21_op {
+ beqz_op = 0x10,
+ bnez_op = 0x11,
+};
+
enum reg2i12_op {
+ addiw_op = 0x0a,
+ addid_op = 0x0b,
lu52id_op = 0x0c,
+ ldb_op = 0xa0,
+ ldh_op = 0xa1,
+ ldw_op = 0xa2,
+ ldd_op = 0xa3,
+ stb_op = 0xa4,
+ sth_op = 0xa5,
+ stw_op = 0xa6,
+ std_op = 0xa7,
};

enum reg2i16_op {
jirl_op = 0x13,
+ beq_op = 0x16,
+ bne_op = 0x17,
+ blt_op = 0x18,
+ bge_op = 0x19,
+ bltu_op = 0x1a,
+ bgeu_op = 0x1b,
};

struct reg0i26_format {
@@ -110,6 +131,37 @@ enum loongarch_gpr {
LOONGARCH_GPR_MAX
};

+#define is_imm12_negative(val) is_imm_negative(val, 12)
+
+static inline bool is_imm_negative(unsigned long val, unsigned int bit)
+{
+ return val & (1UL << (bit - 1));
+}
+
+static inline bool is_stack_alloc_ins(union loongarch_instruction *ip)
+{
+ /* addi.d $sp, $sp, -imm */
+ return ip->reg2i12_format.opcode == addid_op &&
+ ip->reg2i12_format.rj == LOONGARCH_GPR_SP &&
+ ip->reg2i12_format.rd == LOONGARCH_GPR_SP &&
+ is_imm12_negative(ip->reg2i12_format.immediate);
+}
+
+static inline bool is_ra_save_ins(union loongarch_instruction *ip)
+{
+ /* st.d $ra, $sp, offset */
+ return ip->reg2i12_format.opcode == std_op &&
+ ip->reg2i12_format.rj == LOONGARCH_GPR_SP &&
+ ip->reg2i12_format.rd == LOONGARCH_GPR_RA &&
+ !is_imm12_negative(ip->reg2i12_format.immediate);
+}
+
+static inline bool is_branch_insn(union loongarch_instruction insn)
+{
+ return insn.reg1i21_format.opcode >= beqz_op &&
+ insn.reg1i21_format.opcode <= bgeu_op;
+}
+
u32 larch_insn_gen_lu32id(enum loongarch_gpr rd, int imm);
u32 larch_insn_gen_lu52id(enum loongarch_gpr rd, enum loongarch_gpr rj, int imm);
u32 larch_insn_gen_jirl(enum loongarch_gpr rd, enum loongarch_gpr rj, unsigned long pc, unsigned long dest);
diff --git a/arch/loongarch/include/asm/unwind.h b/arch/loongarch/include/asm/unwind.h
index 243330b39d0d..f9f73a26504e 100644
--- a/arch/loongarch/include/asm/unwind.h
+++ b/arch/loongarch/include/asm/unwind.h
@@ -14,6 +14,14 @@
struct unwind_state {
struct stack_info stack_info;
struct task_struct *task;
+#if defined(CONFIG_UNWINDER_PROLOGUE)
+ unsigned long ra;
+ bool enable;
+ /*
+ * Enable is the prologue analysis method
+ * otherwise is the way to guess.
+ */
+#endif
unsigned long sp, pc;
bool first;
bool error;
diff --git a/arch/loongarch/kernel/Makefile b/arch/loongarch/kernel/Makefile
index c5fa4adb23b6..918600e7b30f 100644
--- a/arch/loongarch/kernel/Makefile
+++ b/arch/loongarch/kernel/Makefile
@@ -23,5 +23,6 @@ obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_NUMA) += numa.o

obj-$(CONFIG_UNWINDER_GUESS) += unwind_guess.o
+obj-$(CONFIG_UNWINDER_PROLOGUE) += unwind_prologue.o

CPPFLAGS_vmlinux.lds := $(KBUILD_CFLAGS)
diff --git a/arch/loongarch/kernel/traps.c b/arch/loongarch/kernel/traps.c
index ef2c3aeb1dab..3e904fa12d48 100644
--- a/arch/loongarch/kernel/traps.c
+++ b/arch/loongarch/kernel/traps.c
@@ -73,6 +73,11 @@ static void show_backtrace(struct task_struct *task, const struct pt_regs *regs,

unwind_start(&state, task, pregs);

+#ifdef CONFIG_UNWINDER_PROLOGUE
+ if (user_mode(regs))
+ state.enable = false;
+#endif
+
printk("%sCall Trace:", loglvl);
for (; !unwind_done(&state); unwind_next_frame(&state)) {
addr = unwind_get_return_address(&state);
diff --git a/arch/loongarch/kernel/unwind_prologue.c b/arch/loongarch/kernel/unwind_prologue.c
new file mode 100644
index 000000000000..072d1f7bf4ac
--- /dev/null
+++ b/arch/loongarch/kernel/unwind_prologue.c
@@ -0,0 +1,172 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022 Loongson Technology Corporation Limited
+ */
+#include <linux/kallsyms.h>
+
+#include <asm/inst.h>
+#include <asm/ptrace.h>
+#include <asm/unwind.h>
+
+unsigned long unwind_get_return_address(struct unwind_state *state)
+{
+
+ if (unwind_done(state))
+ return 0;
+ else if (state->enable)
+ return state->pc;
+ else if (state->first)
+ return state->pc;
+
+ return *(unsigned long *)(state->sp);
+
+}
+EXPORT_SYMBOL_GPL(unwind_get_return_address);
+
+static bool unwind_by_prologue(struct unwind_state *state)
+{
+ struct stack_info *info = &state->stack_info;
+ union loongarch_instruction *ip, *ip_end;
+ unsigned long frame_size = 0, frame_ra = -1;
+ unsigned long size, offset, pc = state->pc;
+
+ if (state->sp >= info->end || state->sp < info->begin)
+ return false;
+
+ if (!kallsyms_lookup_size_offset(pc, &size, &offset))
+ return false;
+
+ ip = (union loongarch_instruction *)(pc - offset);
+ ip_end = (union loongarch_instruction *)pc;
+
+ while (ip < ip_end) {
+ if (is_stack_alloc_ins(ip)) {
+ frame_size = (1 << 12) - ip->reg2i12_format.immediate;
+ ip++;
+ break;
+ }
+ ip++;
+ }
+
+ if (!frame_size) {
+ if (state->first)
+ goto first;
+
+ return false;
+ }
+
+ while (ip < ip_end) {
+ if (is_ra_save_ins(ip)) {
+ frame_ra = ip->reg2i12_format.immediate;
+ break;
+ }
+ if (is_branch_insn(*ip))
+ break;
+ ip++;
+ }
+
+ if (frame_ra < 0) {
+ if (state->first) {
+ state->sp = state->sp + frame_size;
+ goto first;
+ }
+ return false;
+ }
+
+ if (state->first)
+ state->first = false;
+
+ state->pc = *(unsigned long *)(state->sp + frame_ra);
+ state->sp = state->sp + frame_size;
+ return !!__kernel_text_address(state->pc);
+
+first:
+ state->first = false;
+ if (state->pc == state->ra)
+ return false;
+
+ state->pc = state->ra;
+
+ return !!__kernel_text_address(state->ra);
+}
+
+static bool unwind_by_guess(struct unwind_state *state)
+{
+ struct stack_info *info = &state->stack_info;
+ unsigned long addr;
+
+ for (state->sp += sizeof(unsigned long);
+ state->sp < info->end;
+ state->sp += sizeof(unsigned long)) {
+ addr = *(unsigned long *)(state->sp);
+ if (__kernel_text_address(addr))
+ return true;
+ }
+
+ return false;
+}
+
+bool unwind_next_frame(struct unwind_state *state)
+{
+ struct stack_info *info = &state->stack_info;
+ struct pt_regs *regs;
+ unsigned long pc;
+
+ if (unwind_done(state))
+ return false;
+
+ do {
+ if (state->enable) {
+ if (unwind_by_prologue(state))
+ return true;
+
+ if (info->type == STACK_TYPE_IRQ &&
+ info->end == state->sp) {
+ regs = (struct pt_regs *)info->next_sp;
+ pc = regs->csr_era;
+ if (user_mode(regs) || !__kernel_text_address(pc))
+ return false;
+
+ state->pc = pc;
+ state->sp = regs->regs[3];
+ state->ra = regs->regs[1];
+ state->first = true;
+ get_stack_info(state->sp, state->task, info);
+
+ return true;
+ }
+ } else {
+ if (state->first)
+ state->first = false;
+ else if (unwind_by_guess(state))
+ return true;
+ }
+
+ state->sp = info->next_sp;
+
+ } while (!get_stack_info(state->sp, state->task, info));
+
+ return false;
+}
+EXPORT_SYMBOL_GPL(unwind_next_frame);
+
+void unwind_start(struct unwind_state *state, struct task_struct *task,
+ struct pt_regs *regs)
+{
+ memset(state, 0, sizeof(*state));
+
+ if (__kernel_text_address(regs->csr_era))
+ state->enable = true;
+
+ state->task = task;
+ state->pc = regs->csr_era;
+ state->sp = regs->regs[3];
+ state->ra = regs->regs[1];
+ state->first = true;
+
+ get_stack_info(state->sp, state->task, &state->stack_info);
+
+ if (!unwind_done(state) && !__kernel_text_address(state->pc))
+ unwind_next_frame(state);
+}
+EXPORT_SYMBOL_GPL(unwind_start);
--
2.20.1


2022-08-01 12:55:41

by Qing Zhang

[permalink] [raw]
Subject: [PATCH 1/4] LoongArch: Add guess unwinder support

Name "guess unwinder" comes from x86, It scans the stack and reports
every kernel text address it finds.

Three stages when we do unwind,
(1)unwind_start(), the prapare of unwinding, fill unwind_state.
(2)unwind_done(), judge whether the unwind process is finished or not.
(3)unwind_next_frame(), unwind the next frame.

Make the dump_stack process go through unwind process.
Add get_stack_info() to get stack info. At present we have irq stack and
task stack. Maybe add another type in future. The next_sp means the key
info between this type stack and next type stack.

Dividing unwinder helps to add new unwinders in the future.

Signed-off-by: Qing Zhang <[email protected]>
---
arch/loongarch/Kconfig.debug | 9 ++++
arch/loongarch/include/asm/stacktrace.h | 17 +++++++
arch/loongarch/include/asm/unwind.h | 37 ++++++++++++++
arch/loongarch/kernel/Makefile | 2 +
arch/loongarch/kernel/process.c | 61 +++++++++++++++++++++++
arch/loongarch/kernel/traps.c | 22 ++++-----
arch/loongarch/kernel/unwind_guess.c | 65 +++++++++++++++++++++++++
7 files changed, 202 insertions(+), 11 deletions(-)
create mode 100644 arch/loongarch/include/asm/unwind.h
create mode 100644 arch/loongarch/kernel/unwind_guess.c

diff --git a/arch/loongarch/Kconfig.debug b/arch/loongarch/Kconfig.debug
index e69de29bb2d1..68634d4fa27b 100644
--- a/arch/loongarch/Kconfig.debug
+++ b/arch/loongarch/Kconfig.debug
@@ -0,0 +1,9 @@
+config UNWINDER_GUESS
+ bool "Guess unwinder"
+ help
+ This option enables the "guess" unwinder for unwinding kernel stack
+ traces. It scans the stack and reports every kernel text address it
+ finds. Some of the addresses it reports may be incorrect.
+
+ While this option often produces false positives, it can still be
+ useful in many cases.
diff --git a/arch/loongarch/include/asm/stacktrace.h b/arch/loongarch/include/asm/stacktrace.h
index 6b5c2a7aa706..49cb89213aeb 100644
--- a/arch/loongarch/include/asm/stacktrace.h
+++ b/arch/loongarch/include/asm/stacktrace.h
@@ -10,6 +10,23 @@
#include <asm/loongarch.h>
#include <linux/stringify.h>

+enum stack_type {
+ STACK_TYPE_UNKNOWN,
+ STACK_TYPE_TASK,
+ STACK_TYPE_IRQ,
+};
+
+struct stack_info {
+ enum stack_type type;
+ unsigned long begin, end, next_sp;
+};
+
+bool in_task_stack(unsigned long stack, struct task_struct *task,
+ struct stack_info *info);
+bool in_irq_stack(unsigned long stack, struct stack_info *info);
+int get_stack_info(unsigned long stack, struct task_struct *task,
+ struct stack_info *info);
+
#define STR_LONG_L __stringify(LONG_L)
#define STR_LONG_S __stringify(LONG_S)
#define STR_LONGSIZE __stringify(LONGSIZE)
diff --git a/arch/loongarch/include/asm/unwind.h b/arch/loongarch/include/asm/unwind.h
new file mode 100644
index 000000000000..243330b39d0d
--- /dev/null
+++ b/arch/loongarch/include/asm/unwind.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Most of this ideas comes from x86.
+ *
+ * Copyright (C) 2022 Loongson Technology Corporation Limited
+ */
+#ifndef _ASM_UNWIND_H
+#define _ASM_UNWIND_H
+
+#include <linux/sched.h>
+
+#include <asm/stacktrace.h>
+
+struct unwind_state {
+ struct stack_info stack_info;
+ struct task_struct *task;
+ unsigned long sp, pc;
+ bool first;
+ bool error;
+};
+
+void unwind_start(struct unwind_state *state, struct task_struct *task,
+ struct pt_regs *regs);
+bool unwind_next_frame(struct unwind_state *state);
+unsigned long unwind_get_return_address(struct unwind_state *state);
+
+static inline bool unwind_done(struct unwind_state *state)
+{
+ return state->stack_info.type == STACK_TYPE_UNKNOWN;
+}
+
+static inline bool unwind_error(struct unwind_state *state)
+{
+ return state->error;
+}
+
+#endif /* _ASM_UNWIND_H */
diff --git a/arch/loongarch/kernel/Makefile b/arch/loongarch/kernel/Makefile
index 940de9173542..c5fa4adb23b6 100644
--- a/arch/loongarch/kernel/Makefile
+++ b/arch/loongarch/kernel/Makefile
@@ -22,4 +22,6 @@ obj-$(CONFIG_SMP) += smp.o

obj-$(CONFIG_NUMA) += numa.o

+obj-$(CONFIG_UNWINDER_GUESS) += unwind_guess.o
+
CPPFLAGS_vmlinux.lds := $(KBUILD_CFLAGS)
diff --git a/arch/loongarch/kernel/process.c b/arch/loongarch/kernel/process.c
index bfa0dfe8b7d7..709b7a1664f8 100644
--- a/arch/loongarch/kernel/process.c
+++ b/arch/loongarch/kernel/process.c
@@ -44,6 +44,7 @@
#include <asm/pgtable.h>
#include <asm/processor.h>
#include <asm/reg.h>
+#include <asm/unwind.h>
#include <asm/vdso.h>

/*
@@ -183,6 +184,66 @@ unsigned long __get_wchan(struct task_struct *task)
return 0;
}

+bool in_task_stack(unsigned long stack, struct task_struct *task,
+ struct stack_info *info)
+{
+ unsigned long begin = (unsigned long)task_stack_page(task);
+ unsigned long end = begin + THREAD_SIZE - 32;
+
+ if (stack < begin || stack >= end)
+ return false;
+
+ info->type = STACK_TYPE_TASK;
+ info->begin = begin;
+ info->end = end;
+ info->next_sp = 0;
+
+ return true;
+}
+
+bool in_irq_stack(unsigned long stack, struct stack_info *info)
+{
+ unsigned long nextsp;
+ unsigned long begin = (unsigned long)this_cpu_read(irq_stack);
+ unsigned long end = begin + IRQ_STACK_START;
+
+ if (stack < begin || stack >= end)
+ return false;
+
+ nextsp = *(unsigned long *)end;
+ if (nextsp & (SZREG - 1))
+ return false;
+
+ info->type = STACK_TYPE_IRQ;
+ info->begin = begin;
+ info->end = end;
+ info->next_sp = nextsp;
+
+ return true;
+}
+
+int get_stack_info(unsigned long stack, struct task_struct *task,
+ struct stack_info *info)
+{
+ task = task ? : current;
+
+ if (!stack || stack & (SZREG - 1))
+ goto unknown;
+
+ if (in_task_stack(stack, task, info))
+ return 0;
+
+ if (task != current)
+ goto unknown;
+
+ if (in_irq_stack(stack, info))
+ return 0;
+
+unknown:
+ info->type = STACK_TYPE_UNKNOWN;
+ return -EINVAL;
+}
+
unsigned long stack_top(void)
{
unsigned long top = TASK_SIZE & PAGE_MASK;
diff --git a/arch/loongarch/kernel/traps.c b/arch/loongarch/kernel/traps.c
index 1bf58c65e2bf..ef2c3aeb1dab 100644
--- a/arch/loongarch/kernel/traps.c
+++ b/arch/loongarch/kernel/traps.c
@@ -43,6 +43,7 @@
#include <asm/stacktrace.h>
#include <asm/tlb.h>
#include <asm/types.h>
+#include <asm/unwind.h>

#include "access-helper.h"

@@ -64,19 +65,18 @@ static void show_backtrace(struct task_struct *task, const struct pt_regs *regs,
const char *loglvl, bool user)
{
unsigned long addr;
- unsigned long *sp = (unsigned long *)(regs->regs[3] & ~3);
+ struct unwind_state state;
+ struct pt_regs *pregs = (struct pt_regs *)regs;
+
+ if (!task)
+ task = current;
+
+ unwind_start(&state, task, pregs);

printk("%sCall Trace:", loglvl);
-#ifdef CONFIG_KALLSYMS
- printk("%s\n", loglvl);
-#endif
- while (!kstack_end(sp)) {
- if (__get_addr(&addr, sp++, user)) {
- printk("%s (Bad stack address)", loglvl);
- break;
- }
- if (__kernel_text_address(addr))
- print_ip_sym(loglvl, addr);
+ for (; !unwind_done(&state); unwind_next_frame(&state)) {
+ addr = unwind_get_return_address(&state);
+ print_ip_sym(loglvl, addr);
}
printk("%s\n", loglvl);
}
diff --git a/arch/loongarch/kernel/unwind_guess.c b/arch/loongarch/kernel/unwind_guess.c
new file mode 100644
index 000000000000..7eeb3e1a989d
--- /dev/null
+++ b/arch/loongarch/kernel/unwind_guess.c
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022 Loongson Technology Corporation Limited
+ */
+#include <linux/kernel.h>
+
+#include <asm/unwind.h>
+
+unsigned long unwind_get_return_address(struct unwind_state *state)
+{
+ if (unwind_done(state))
+ return 0;
+ else if (state->first)
+ return state->pc;
+
+ return *(unsigned long *)(state->sp);
+}
+EXPORT_SYMBOL_GPL(unwind_get_return_address);
+
+bool unwind_next_frame(struct unwind_state *state)
+{
+ struct stack_info *info = &state->stack_info;
+ unsigned long addr;
+
+ if (unwind_done(state))
+ return false;
+
+ if (state->first)
+ state->first = false;
+
+ do {
+ for (state->sp += sizeof(unsigned long);
+ state->sp < info->end;
+ state->sp += sizeof(unsigned long)) {
+ addr = *(unsigned long *)(state->sp);
+
+ if (__kernel_text_address(addr))
+ return true;
+ }
+
+ state->sp = info->next_sp;
+
+ } while (!get_stack_info(state->sp, state->task, info));
+
+ return false;
+}
+EXPORT_SYMBOL_GPL(unwind_next_frame);
+
+void unwind_start(struct unwind_state *state, struct task_struct *task,
+ struct pt_regs *regs)
+{
+ memset(state, 0, sizeof(*state));
+
+ state->task = task;
+
+ state->sp = regs->regs[3];
+ state->pc = regs->csr_era;
+ state->first = true;
+
+ get_stack_info(state->sp, state->task, &state->stack_info);
+
+ if (!unwind_done(state) && !__kernel_text_address(state->pc))
+ unwind_next_frame(state);
+}
+EXPORT_SYMBOL_GPL(unwind_start);
--
2.20.1


2022-08-01 12:55:48

by Qing Zhang

[permalink] [raw]
Subject: [PATCH 4/4] LoongArch: Add USER_STACKTRACE support

To get the best output you can compile your userspace programs with
frame pointers (at least glibc + the app you are tracing export "CC
=gcc -fno-omit-frame-pointer".

...
echo 'p:malloc /usr/lib64/libc.so.6:0x0a4704 size=%r4:u64'
> uprobe_events
echo 'p:free /usr/lib64/libc.so.6:0x0a4d50 ptr=%r4:x64'
>> uprobe_events
echo 'comm == "demo"' > ./events/uprobes/malloc/filter
echo 'comm == "demo"' > ./events/uprobes/free/filter
echo 1 > ./options/userstacktrace
echo 1 > ./options/sym-userobj
...

Signed-off-by: Qing Zhang <[email protected]>
---
arch/loongarch/Kconfig | 1 +
arch/loongarch/include/asm/stacktrace.h | 5 +++
arch/loongarch/kernel/stacktrace.c | 42 +++++++++++++++++++++++++
3 files changed, 48 insertions(+)

diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
index 85d0fa3147cd..05906384d564 100644
--- a/arch/loongarch/Kconfig
+++ b/arch/loongarch/Kconfig
@@ -107,6 +107,7 @@ config LOONGARCH
select SWIOTLB
select TRACE_IRQFLAGS_SUPPORT
select USE_PERCPU_NUMA_NODE_ID
+ select USER_STACKTRACE_SUPPORT
select ZONE_DMA32
select MMU_GATHER_MERGE_VMAS if MMU

diff --git a/arch/loongarch/include/asm/stacktrace.h b/arch/loongarch/include/asm/stacktrace.h
index 49cb89213aeb..77fdb8ad662d 100644
--- a/arch/loongarch/include/asm/stacktrace.h
+++ b/arch/loongarch/include/asm/stacktrace.h
@@ -21,6 +21,11 @@ struct stack_info {
unsigned long begin, end, next_sp;
};

+struct stack_frame {
+ unsigned long fp;
+ unsigned long ra;
+};
+
bool in_task_stack(unsigned long stack, struct task_struct *task,
struct stack_info *info);
bool in_irq_stack(unsigned long stack, struct stack_info *info);
diff --git a/arch/loongarch/kernel/stacktrace.c b/arch/loongarch/kernel/stacktrace.c
index f4f4b8ad3917..344224c7cb0e 100644
--- a/arch/loongarch/kernel/stacktrace.c
+++ b/arch/loongarch/kernel/stacktrace.c
@@ -6,6 +6,7 @@
*/
#include <linux/sched.h>
#include <linux/stacktrace.h>
+#include <linux/uaccess.h>

#include <asm/stacktrace.h>
#include <asm/unwind.h>
@@ -35,3 +36,44 @@ void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie,
break;
}
}
+
+static int
+copy_stack_frame(unsigned long fp, struct stack_frame *frame)
+{
+ int ret;
+ unsigned long err;
+ unsigned long __user *user_frame_tail;
+
+ user_frame_tail = (unsigned long *)(fp - sizeof(struct stack_frame));
+ if (!access_ok(user_frame_tail, sizeof(*frame)))
+ return 0;
+
+ ret = 1;
+ pagefault_disable();
+ err = (__copy_from_user_inatomic(frame, user_frame_tail, sizeof(*frame)));
+ if (err || (unsigned long)user_frame_tail >= frame->fp)
+ ret = 0;
+ pagefault_enable();
+
+ return ret;
+}
+
+void arch_stack_walk_user(stack_trace_consume_fn consume_entry, void *cookie,
+ const struct pt_regs *regs)
+{
+ unsigned long fp = regs->regs[22];
+
+ while (fp && !((unsigned long)fp & 0xf)) {
+ struct stack_frame frame;
+
+ frame.fp = 0;
+ frame.ra = 0;
+ if (!copy_stack_frame(fp, &frame))
+ break;
+ if (!frame.ra)
+ break;
+ if (!consume_entry(cookie, frame.ra))
+ break;
+ fp = frame.fp;
+ }
+}
--
2.20.1


2022-08-01 15:29:45

by Huacai Chen

[permalink] [raw]
Subject: Re: [PATCH 2/4] LoongArch: Add prologue unwinder support

Hi, Qing,

On Mon, Aug 1, 2022 at 8:17 PM Qing Zhang <[email protected]> wrote:
>
> It unwind the stack frame based on prologue code analyze.
> CONFIG_KALLSYMS is needed, at least the address and length
> of each function.
>
> Three stages when we do unwind,
> (1)unwind_start(), the prapare of unwinding, fill unwind_state.
> (2)unwind_done(), judge whether the unwind process is finished or not.
> (3)unwind_next_frame(), unwind the next frame.
>
> Dividing unwinder helps to add new unwinders in the future, eg:
> unwind_frame, unwind_orc .etc
>
> Signed-off-by: Qing Zhang <[email protected]>
> ---
> arch/loongarch/Kconfig.debug | 19 +++
> arch/loongarch/include/asm/inst.h | 52 +++++++
> arch/loongarch/include/asm/unwind.h | 8 ++
> arch/loongarch/kernel/Makefile | 1 +
> arch/loongarch/kernel/traps.c | 5 +
> arch/loongarch/kernel/unwind_prologue.c | 172 ++++++++++++++++++++++++
> 6 files changed, 257 insertions(+)
> create mode 100644 arch/loongarch/kernel/unwind_prologue.c
>
> diff --git a/arch/loongarch/Kconfig.debug b/arch/loongarch/Kconfig.debug
> index 68634d4fa27b..57cdbe0cfd98 100644
> --- a/arch/loongarch/Kconfig.debug
> +++ b/arch/loongarch/Kconfig.debug
> @@ -1,3 +1,11 @@
> +choice
> + prompt "Choose kernel unwinder"
> + default UNWINDER_PROLOGUE if KALLSYMS
> + help
> + This determines which method will be used for unwinding kernel stack
> + traces for panics, oopses, bugs, warnings, perf, /proc/<pid>/stack,
> + lockdep, and more.
> +
> config UNWINDER_GUESS
> bool "Guess unwinder"
> help
> @@ -7,3 +15,14 @@ config UNWINDER_GUESS
>
> While this option often produces false positives, it can still be
> useful in many cases.
> +
> +config UNWINDER_PROLOGUE
> + bool "Prologue unwinder"
> + depends on KALLSYMS
> + help
> + This option enables the "prologue" unwinder for unwinding kernel stack
> + traces. It unwind the stack frame based on prologue code analyze. Symbol
> + information is needed, at least the address and length of each function.
> + Some of the addresses it reports may be incorrect.
> +
> +endchoice
> diff --git a/arch/loongarch/include/asm/inst.h b/arch/loongarch/include/asm/inst.h
> index 575d1bb66ffb..b876907ca65a 100644
> --- a/arch/loongarch/include/asm/inst.h
> +++ b/arch/loongarch/include/asm/inst.h
> @@ -23,12 +23,33 @@ enum reg1i20_op {
> lu32id_op = 0x0b,
> };
>
> +enum reg1i21_op {
> + beqz_op = 0x10,
> + bnez_op = 0x11,
> +};
> +
> enum reg2i12_op {
> + addiw_op = 0x0a,
> + addid_op = 0x0b,
> lu52id_op = 0x0c,
> + ldb_op = 0xa0,
> + ldh_op = 0xa1,
> + ldw_op = 0xa2,
> + ldd_op = 0xa3,
> + stb_op = 0xa4,
> + sth_op = 0xa5,
> + stw_op = 0xa6,
> + std_op = 0xa7,
> };
>
> enum reg2i16_op {
> jirl_op = 0x13,
> + beq_op = 0x16,
> + bne_op = 0x17,
> + blt_op = 0x18,
> + bge_op = 0x19,
> + bltu_op = 0x1a,
> + bgeu_op = 0x1b,
> };
>
> struct reg0i26_format {
> @@ -110,6 +131,37 @@ enum loongarch_gpr {
> LOONGARCH_GPR_MAX
> };
>
> +#define is_imm12_negative(val) is_imm_negative(val, 12)
> +
> +static inline bool is_imm_negative(unsigned long val, unsigned int bit)
> +{
> + return val & (1UL << (bit - 1));
> +}
> +
> +static inline bool is_stack_alloc_ins(union loongarch_instruction *ip)
> +{
> + /* addi.d $sp, $sp, -imm */
> + return ip->reg2i12_format.opcode == addid_op &&
> + ip->reg2i12_format.rj == LOONGARCH_GPR_SP &&
> + ip->reg2i12_format.rd == LOONGARCH_GPR_SP &&
> + is_imm12_negative(ip->reg2i12_format.immediate);
> +}
> +
> +static inline bool is_ra_save_ins(union loongarch_instruction *ip)
> +{
> + /* st.d $ra, $sp, offset */
> + return ip->reg2i12_format.opcode == std_op &&
> + ip->reg2i12_format.rj == LOONGARCH_GPR_SP &&
> + ip->reg2i12_format.rd == LOONGARCH_GPR_RA &&
> + !is_imm12_negative(ip->reg2i12_format.immediate);
> +}
> +
> +static inline bool is_branch_insn(union loongarch_instruction insn)
> +{
> + return insn.reg1i21_format.opcode >= beqz_op &&
> + insn.reg1i21_format.opcode <= bgeu_op;
> +}
> +
> u32 larch_insn_gen_lu32id(enum loongarch_gpr rd, int imm);
> u32 larch_insn_gen_lu52id(enum loongarch_gpr rd, enum loongarch_gpr rj, int imm);
> u32 larch_insn_gen_jirl(enum loongarch_gpr rd, enum loongarch_gpr rj, unsigned long pc, unsigned long dest);
> diff --git a/arch/loongarch/include/asm/unwind.h b/arch/loongarch/include/asm/unwind.h
> index 243330b39d0d..f9f73a26504e 100644
> --- a/arch/loongarch/include/asm/unwind.h
> +++ b/arch/loongarch/include/asm/unwind.h
> @@ -14,6 +14,14 @@
> struct unwind_state {
> struct stack_info stack_info;
> struct task_struct *task;
> +#if defined(CONFIG_UNWINDER_PROLOGUE)
> + unsigned long ra;
> + bool enable;
> + /*
> + * Enable is the prologue analysis method
> + * otherwise is the way to guess.
> + */
> +#endif
> unsigned long sp, pc;
> bool first;
> bool error;
This data struct makes me very uncomfortable, especially "enable" and
the #ifdef, maybe we can rework it like this?

#define UNWINDER_GUESS 0
#define UNWINDER_PROLOGURE 1
struct unwind_state {
char type; /* UNWINDER_xxx */
bool first, error;
unsigned long sp, pc, ra;
struct task_struct *task;
struct stack_info stack_info;
};

Huacai

> diff --git a/arch/loongarch/kernel/Makefile b/arch/loongarch/kernel/Makefile
> index c5fa4adb23b6..918600e7b30f 100644
> --- a/arch/loongarch/kernel/Makefile
> +++ b/arch/loongarch/kernel/Makefile
> @@ -23,5 +23,6 @@ obj-$(CONFIG_SMP) += smp.o
> obj-$(CONFIG_NUMA) += numa.o
>
> obj-$(CONFIG_UNWINDER_GUESS) += unwind_guess.o
> +obj-$(CONFIG_UNWINDER_PROLOGUE) += unwind_prologue.o
>
> CPPFLAGS_vmlinux.lds := $(KBUILD_CFLAGS)
> diff --git a/arch/loongarch/kernel/traps.c b/arch/loongarch/kernel/traps.c
> index ef2c3aeb1dab..3e904fa12d48 100644
> --- a/arch/loongarch/kernel/traps.c
> +++ b/arch/loongarch/kernel/traps.c
> @@ -73,6 +73,11 @@ static void show_backtrace(struct task_struct *task, const struct pt_regs *regs,
>
> unwind_start(&state, task, pregs);
>
> +#ifdef CONFIG_UNWINDER_PROLOGUE
> + if (user_mode(regs))
> + state.enable = false;
> +#endif
> +
> printk("%sCall Trace:", loglvl);
> for (; !unwind_done(&state); unwind_next_frame(&state)) {
> addr = unwind_get_return_address(&state);
> diff --git a/arch/loongarch/kernel/unwind_prologue.c b/arch/loongarch/kernel/unwind_prologue.c
> new file mode 100644
> index 000000000000..072d1f7bf4ac
> --- /dev/null
> +++ b/arch/loongarch/kernel/unwind_prologue.c
> @@ -0,0 +1,172 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2022 Loongson Technology Corporation Limited
> + */
> +#include <linux/kallsyms.h>
> +
> +#include <asm/inst.h>
> +#include <asm/ptrace.h>
> +#include <asm/unwind.h>
> +
> +unsigned long unwind_get_return_address(struct unwind_state *state)
> +{
> +
> + if (unwind_done(state))
> + return 0;
> + else if (state->enable)
> + return state->pc;
> + else if (state->first)
> + return state->pc;
> +
> + return *(unsigned long *)(state->sp);
> +
> +}
> +EXPORT_SYMBOL_GPL(unwind_get_return_address);
> +
> +static bool unwind_by_prologue(struct unwind_state *state)
> +{
> + struct stack_info *info = &state->stack_info;
> + union loongarch_instruction *ip, *ip_end;
> + unsigned long frame_size = 0, frame_ra = -1;
> + unsigned long size, offset, pc = state->pc;
> +
> + if (state->sp >= info->end || state->sp < info->begin)
> + return false;
> +
> + if (!kallsyms_lookup_size_offset(pc, &size, &offset))
> + return false;
> +
> + ip = (union loongarch_instruction *)(pc - offset);
> + ip_end = (union loongarch_instruction *)pc;
> +
> + while (ip < ip_end) {
> + if (is_stack_alloc_ins(ip)) {
> + frame_size = (1 << 12) - ip->reg2i12_format.immediate;
> + ip++;
> + break;
> + }
> + ip++;
> + }
> +
> + if (!frame_size) {
> + if (state->first)
> + goto first;
> +
> + return false;
> + }
> +
> + while (ip < ip_end) {
> + if (is_ra_save_ins(ip)) {
> + frame_ra = ip->reg2i12_format.immediate;
> + break;
> + }
> + if (is_branch_insn(*ip))
> + break;
> + ip++;
> + }
> +
> + if (frame_ra < 0) {
> + if (state->first) {
> + state->sp = state->sp + frame_size;
> + goto first;
> + }
> + return false;
> + }
> +
> + if (state->first)
> + state->first = false;
> +
> + state->pc = *(unsigned long *)(state->sp + frame_ra);
> + state->sp = state->sp + frame_size;
> + return !!__kernel_text_address(state->pc);
> +
> +first:
> + state->first = false;
> + if (state->pc == state->ra)
> + return false;
> +
> + state->pc = state->ra;
> +
> + return !!__kernel_text_address(state->ra);
> +}
> +
> +static bool unwind_by_guess(struct unwind_state *state)
> +{
> + struct stack_info *info = &state->stack_info;
> + unsigned long addr;
> +
> + for (state->sp += sizeof(unsigned long);
> + state->sp < info->end;
> + state->sp += sizeof(unsigned long)) {
> + addr = *(unsigned long *)(state->sp);
> + if (__kernel_text_address(addr))
> + return true;
> + }
> +
> + return false;
> +}
> +
> +bool unwind_next_frame(struct unwind_state *state)
> +{
> + struct stack_info *info = &state->stack_info;
> + struct pt_regs *regs;
> + unsigned long pc;
> +
> + if (unwind_done(state))
> + return false;
> +
> + do {
> + if (state->enable) {
> + if (unwind_by_prologue(state))
> + return true;
> +
> + if (info->type == STACK_TYPE_IRQ &&
> + info->end == state->sp) {
> + regs = (struct pt_regs *)info->next_sp;
> + pc = regs->csr_era;
> + if (user_mode(regs) || !__kernel_text_address(pc))
> + return false;
> +
> + state->pc = pc;
> + state->sp = regs->regs[3];
> + state->ra = regs->regs[1];
> + state->first = true;
> + get_stack_info(state->sp, state->task, info);
> +
> + return true;
> + }
> + } else {
> + if (state->first)
> + state->first = false;
> + else if (unwind_by_guess(state))
> + return true;
> + }
> +
> + state->sp = info->next_sp;
> +
> + } while (!get_stack_info(state->sp, state->task, info));
> +
> + return false;
> +}
> +EXPORT_SYMBOL_GPL(unwind_next_frame);
> +
> +void unwind_start(struct unwind_state *state, struct task_struct *task,
> + struct pt_regs *regs)
> +{
> + memset(state, 0, sizeof(*state));
> +
> + if (__kernel_text_address(regs->csr_era))
> + state->enable = true;
> +
> + state->task = task;
> + state->pc = regs->csr_era;
> + state->sp = regs->regs[3];
> + state->ra = regs->regs[1];
> + state->first = true;
> +
> + get_stack_info(state->sp, state->task, &state->stack_info);
> +
> + if (!unwind_done(state) && !__kernel_text_address(state->pc))
> + unwind_next_frame(state);
> +}
> +EXPORT_SYMBOL_GPL(unwind_start);
> --
> 2.20.1
>

2022-08-01 15:32:55

by Huacai Chen

[permalink] [raw]
Subject: Re: [PATCH 1/4] LoongArch: Add guess unwinder support

Hi, Qing,

On Mon, Aug 1, 2022 at 8:17 PM Qing Zhang <[email protected]> wrote:
>
> Name "guess unwinder" comes from x86, It scans the stack and reports
> every kernel text address it finds.
>
> Three stages when we do unwind,
> (1)unwind_start(), the prapare of unwinding, fill unwind_state.
> (2)unwind_done(), judge whether the unwind process is finished or not.
> (3)unwind_next_frame(), unwind the next frame.
>
> Make the dump_stack process go through unwind process.
> Add get_stack_info() to get stack info. At present we have irq stack and
> task stack. Maybe add another type in future. The next_sp means the key
> info between this type stack and next type stack.
>
> Dividing unwinder helps to add new unwinders in the future.
>
> Signed-off-by: Qing Zhang <[email protected]>
> ---
> arch/loongarch/Kconfig.debug | 9 ++++
> arch/loongarch/include/asm/stacktrace.h | 17 +++++++
> arch/loongarch/include/asm/unwind.h | 37 ++++++++++++++
> arch/loongarch/kernel/Makefile | 2 +
> arch/loongarch/kernel/process.c | 61 +++++++++++++++++++++++
> arch/loongarch/kernel/traps.c | 22 ++++-----
> arch/loongarch/kernel/unwind_guess.c | 65 +++++++++++++++++++++++++
> 7 files changed, 202 insertions(+), 11 deletions(-)
> create mode 100644 arch/loongarch/include/asm/unwind.h
> create mode 100644 arch/loongarch/kernel/unwind_guess.c
>
> diff --git a/arch/loongarch/Kconfig.debug b/arch/loongarch/Kconfig.debug
> index e69de29bb2d1..68634d4fa27b 100644
> --- a/arch/loongarch/Kconfig.debug
> +++ b/arch/loongarch/Kconfig.debug
> @@ -0,0 +1,9 @@
> +config UNWINDER_GUESS
> + bool "Guess unwinder"
> + help
> + This option enables the "guess" unwinder for unwinding kernel stack
> + traces. It scans the stack and reports every kernel text address it
> + finds. Some of the addresses it reports may be incorrect.
> +
> + While this option often produces false positives, it can still be
> + useful in many cases.
> diff --git a/arch/loongarch/include/asm/stacktrace.h b/arch/loongarch/include/asm/stacktrace.h
> index 6b5c2a7aa706..49cb89213aeb 100644
> --- a/arch/loongarch/include/asm/stacktrace.h
> +++ b/arch/loongarch/include/asm/stacktrace.h
> @@ -10,6 +10,23 @@
> #include <asm/loongarch.h>
> #include <linux/stringify.h>
>
> +enum stack_type {
> + STACK_TYPE_UNKNOWN,
> + STACK_TYPE_TASK,
> + STACK_TYPE_IRQ,
> +};
> +
> +struct stack_info {
> + enum stack_type type;
> + unsigned long begin, end, next_sp;
> +};
> +
> +bool in_task_stack(unsigned long stack, struct task_struct *task,
> + struct stack_info *info);
> +bool in_irq_stack(unsigned long stack, struct stack_info *info);
> +int get_stack_info(unsigned long stack, struct task_struct *task,
> + struct stack_info *info);
> +
> #define STR_LONG_L __stringify(LONG_L)
> #define STR_LONG_S __stringify(LONG_S)
> #define STR_LONGSIZE __stringify(LONGSIZE)
> diff --git a/arch/loongarch/include/asm/unwind.h b/arch/loongarch/include/asm/unwind.h
> new file mode 100644
> index 000000000000..243330b39d0d
> --- /dev/null
> +++ b/arch/loongarch/include/asm/unwind.h
> @@ -0,0 +1,37 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Most of this ideas comes from x86.
> + *
> + * Copyright (C) 2022 Loongson Technology Corporation Limited
> + */
> +#ifndef _ASM_UNWIND_H
> +#define _ASM_UNWIND_H
> +
> +#include <linux/sched.h>
> +
> +#include <asm/stacktrace.h>
> +
> +struct unwind_state {
> + struct stack_info stack_info;
> + struct task_struct *task;
> + unsigned long sp, pc;
> + bool first;
> + bool error;
> +};
> +
> +void unwind_start(struct unwind_state *state, struct task_struct *task,
> + struct pt_regs *regs);
> +bool unwind_next_frame(struct unwind_state *state);
> +unsigned long unwind_get_return_address(struct unwind_state *state);
> +
> +static inline bool unwind_done(struct unwind_state *state)
> +{
> + return state->stack_info.type == STACK_TYPE_UNKNOWN;
> +}
> +
> +static inline bool unwind_error(struct unwind_state *state)
> +{
> + return state->error;
> +}
> +
> +#endif /* _ASM_UNWIND_H */
> diff --git a/arch/loongarch/kernel/Makefile b/arch/loongarch/kernel/Makefile
> index 940de9173542..c5fa4adb23b6 100644
> --- a/arch/loongarch/kernel/Makefile
> +++ b/arch/loongarch/kernel/Makefile
> @@ -22,4 +22,6 @@ obj-$(CONFIG_SMP) += smp.o
>
> obj-$(CONFIG_NUMA) += numa.o
>
> +obj-$(CONFIG_UNWINDER_GUESS) += unwind_guess.o
> +
> CPPFLAGS_vmlinux.lds := $(KBUILD_CFLAGS)
> diff --git a/arch/loongarch/kernel/process.c b/arch/loongarch/kernel/process.c
> index bfa0dfe8b7d7..709b7a1664f8 100644
> --- a/arch/loongarch/kernel/process.c
> +++ b/arch/loongarch/kernel/process.c
> @@ -44,6 +44,7 @@
> #include <asm/pgtable.h>
> #include <asm/processor.h>
> #include <asm/reg.h>
> +#include <asm/unwind.h>
> #include <asm/vdso.h>
>
> /*
> @@ -183,6 +184,66 @@ unsigned long __get_wchan(struct task_struct *task)
> return 0;
> }
>
> +bool in_task_stack(unsigned long stack, struct task_struct *task,
> + struct stack_info *info)
> +{
> + unsigned long begin = (unsigned long)task_stack_page(task);
> + unsigned long end = begin + THREAD_SIZE - 32;
> +
> + if (stack < begin || stack >= end)
> + return false;
> +
> + info->type = STACK_TYPE_TASK;
> + info->begin = begin;
> + info->end = end;
> + info->next_sp = 0;
> +
> + return true;
> +}
> +
> +bool in_irq_stack(unsigned long stack, struct stack_info *info)
> +{
> + unsigned long nextsp;
> + unsigned long begin = (unsigned long)this_cpu_read(irq_stack);
> + unsigned long end = begin + IRQ_STACK_START;
> +
> + if (stack < begin || stack >= end)
> + return false;
> +
> + nextsp = *(unsigned long *)end;
> + if (nextsp & (SZREG - 1))
> + return false;
> +
> + info->type = STACK_TYPE_IRQ;
> + info->begin = begin;
> + info->end = end;
> + info->next_sp = nextsp;
> +
> + return true;
> +}
> +
> +int get_stack_info(unsigned long stack, struct task_struct *task,
> + struct stack_info *info)
> +{
> + task = task ? : current;
> +
> + if (!stack || stack & (SZREG - 1))
> + goto unknown;
> +
> + if (in_task_stack(stack, task, info))
> + return 0;
> +
> + if (task != current)
> + goto unknown;
> +
> + if (in_irq_stack(stack, info))
> + return 0;
> +
> +unknown:
> + info->type = STACK_TYPE_UNKNOWN;
> + return -EINVAL;
> +}
> +
> unsigned long stack_top(void)
> {
> unsigned long top = TASK_SIZE & PAGE_MASK;
> diff --git a/arch/loongarch/kernel/traps.c b/arch/loongarch/kernel/traps.c
> index 1bf58c65e2bf..ef2c3aeb1dab 100644
> --- a/arch/loongarch/kernel/traps.c
> +++ b/arch/loongarch/kernel/traps.c
> @@ -43,6 +43,7 @@
> #include <asm/stacktrace.h>
> #include <asm/tlb.h>
> #include <asm/types.h>
> +#include <asm/unwind.h>
>
> #include "access-helper.h"
>
> @@ -64,19 +65,18 @@ static void show_backtrace(struct task_struct *task, const struct pt_regs *regs,
> const char *loglvl, bool user)
> {
> unsigned long addr;
> - unsigned long *sp = (unsigned long *)(regs->regs[3] & ~3);
> + struct unwind_state state;
> + struct pt_regs *pregs = (struct pt_regs *)regs;
> +
> + if (!task)
> + task = current;
> +
> + unwind_start(&state, task, pregs);
>
> printk("%sCall Trace:", loglvl);
> -#ifdef CONFIG_KALLSYMS
> - printk("%s\n", loglvl);
> -#endif
They should be after unwind_start()? If not, moving unwind_start() to
the for-loop seems better.

> - while (!kstack_end(sp)) {
> - if (__get_addr(&addr, sp++, user)) {
> - printk("%s (Bad stack address)", loglvl);
> - break;
> - }
> - if (__kernel_text_address(addr))
> - print_ip_sym(loglvl, addr);
> + for (; !unwind_done(&state); unwind_next_frame(&state)) {
> + addr = unwind_get_return_address(&state);
> + print_ip_sym(loglvl, addr);
> }
> printk("%s\n", loglvl);
> }
> diff --git a/arch/loongarch/kernel/unwind_guess.c b/arch/loongarch/kernel/unwind_guess.c
> new file mode 100644
> index 000000000000..7eeb3e1a989d
> --- /dev/null
> +++ b/arch/loongarch/kernel/unwind_guess.c
> @@ -0,0 +1,65 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2022 Loongson Technology Corporation Limited
> + */
> +#include <linux/kernel.h>
> +
> +#include <asm/unwind.h>
> +
> +unsigned long unwind_get_return_address(struct unwind_state *state)
> +{
> + if (unwind_done(state))
> + return 0;
> + else if (state->first)
> + return state->pc;
> +
> + return *(unsigned long *)(state->sp);
> +}
> +EXPORT_SYMBOL_GPL(unwind_get_return_address);
> +
> +bool unwind_next_frame(struct unwind_state *state)
> +{
> + struct stack_info *info = &state->stack_info;
> + unsigned long addr;
> +
> + if (unwind_done(state))
> + return false;
> +
> + if (state->first)
> + state->first = false;
> +
> + do {
> + for (state->sp += sizeof(unsigned long);
> + state->sp < info->end;
> + state->sp += sizeof(unsigned long)) {
> + addr = *(unsigned long *)(state->sp);
> +
> + if (__kernel_text_address(addr))
> + return true;
> + }
> +
> + state->sp = info->next_sp;
> +
> + } while (!get_stack_info(state->sp, state->task, info));
> +
> + return false;
> +}
> +EXPORT_SYMBOL_GPL(unwind_next_frame);
Move this function after unwind_start() seems more natural.

Huacai

> +
> +void unwind_start(struct unwind_state *state, struct task_struct *task,
> + struct pt_regs *regs)
> +{
> + memset(state, 0, sizeof(*state));
> +
> + state->task = task;
> +
> + state->sp = regs->regs[3];
> + state->pc = regs->csr_era;
> + state->first = true;
> +
> + get_stack_info(state->sp, state->task, &state->stack_info);
> +
> + if (!unwind_done(state) && !__kernel_text_address(state->pc))
> + unwind_next_frame(state);
> +}
> +EXPORT_SYMBOL_GPL(unwind_start);
> --
> 2.20.1
>

2022-08-01 15:37:09

by Huacai Chen

[permalink] [raw]
Subject: Re: [PATCH 3/4] LoongArch: Add stacktrace support

Hi, Qing,

On Mon, Aug 1, 2022 at 8:17 PM Qing Zhang <[email protected]> wrote:
>
> Use common arch_stack_walk infrastructure to avoid duplicated code and
> avoid taking care of the stack storage and filtering.
> Add sra (means __schedule return address) and scfa (means __schedule call
> frame address) to thread_info and store it in switch_to().
>
> Now we can print the process stack by cat /proc/*/stack and can better
> support ftrace.
>
> Signed-off-by: Qing Zhang <[email protected]>
> ---
> arch/loongarch/Kconfig | 5 ++++
> arch/loongarch/include/asm/processor.h | 9 +++++++
> arch/loongarch/include/asm/switch_to.h | 14 ++++++----
> arch/loongarch/include/asm/uaccess.h | 4 +--
> arch/loongarch/kernel/Makefile | 1 +
> arch/loongarch/kernel/asm-offsets.c | 2 ++
> arch/loongarch/kernel/process.c | 3 +++
> arch/loongarch/kernel/stacktrace.c | 37 ++++++++++++++++++++++++++
> arch/loongarch/kernel/switch.S | 2 ++
> 9 files changed, 70 insertions(+), 7 deletions(-)
> create mode 100644 arch/loongarch/kernel/stacktrace.c
>
> diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
> index 62b5b07fa4e1..85d0fa3147cd 100644
> --- a/arch/loongarch/Kconfig
> +++ b/arch/loongarch/Kconfig
> @@ -38,6 +38,7 @@ config LOONGARCH
> select ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE if !PREEMPTION
> select ARCH_MIGHT_HAVE_PC_PARPORT
> select ARCH_MIGHT_HAVE_PC_SERIO
> + select ARCH_STACKWALK
> select ARCH_SPARSEMEM_ENABLE
> select ARCH_SUPPORTS_ACPI
> select ARCH_SUPPORTS_ATOMIC_RMW
> @@ -140,6 +141,10 @@ config LOCKDEP_SUPPORT
> bool
> default y
>
> +config STACKTRACE_SUPPORT
> + bool
> + default y
> +
> # MACH_LOONGSON32 and MACH_LOONGSON64 are delibrately carried over from the
> # MIPS Loongson code, to preserve Loongson-specific code paths in drivers that
> # are shared between architectures, and specifically expecting the symbols.
> diff --git a/arch/loongarch/include/asm/processor.h b/arch/loongarch/include/asm/processor.h
> index 57ec45aa078e..1c4b4308378d 100644
> --- a/arch/loongarch/include/asm/processor.h
> +++ b/arch/loongarch/include/asm/processor.h
> @@ -101,6 +101,10 @@ struct thread_struct {
> unsigned long reg23, reg24, reg25, reg26; /* s0-s3 */
> unsigned long reg27, reg28, reg29, reg30, reg31; /* s4-s8 */
>
> + /* __schedule() return address / call frame address */
> + unsigned long sched_ra;
> + unsigned long sched_cfa;
> +
> /* CSR registers */
> unsigned long csr_prmd;
> unsigned long csr_crmd;
> @@ -129,6 +133,9 @@ struct thread_struct {
> struct loongarch_fpu fpu FPU_ALIGN;
> };
>
> +#define thread_saved_ra(tsk) (tsk->thread.sched_ra)
> +#define thread_saved_fp(tsk) (tsk->thread.sched_cfa)
> +
> #define INIT_THREAD { \
> /* \
> * Main processor registers \
> @@ -145,6 +152,8 @@ struct thread_struct {
> .reg29 = 0, \
> .reg30 = 0, \
> .reg31 = 0, \
> + .sched_ra = 0, \
> + .sched_cfa = 0, \
> .csr_crmd = 0, \
> .csr_prmd = 0, \
> .csr_euen = 0, \
> diff --git a/arch/loongarch/include/asm/switch_to.h b/arch/loongarch/include/asm/switch_to.h
> index 2a8d04375574..43a5ab162d38 100644
> --- a/arch/loongarch/include/asm/switch_to.h
> +++ b/arch/loongarch/include/asm/switch_to.h
> @@ -15,12 +15,15 @@ struct task_struct;
> * @prev: The task previously executed.
> * @next: The task to begin executing.
> * @next_ti: task_thread_info(next).
> + * @sched_ra: __schedule return address.
> + * @sched_cfa: __schedule call frame address.
> *
> * This function is used whilst scheduling to save the context of prev & load
> * the context of next. Returns prev.
> */
> extern asmlinkage struct task_struct *__switch_to(struct task_struct *prev,
> - struct task_struct *next, struct thread_info *next_ti);
> + struct task_struct *next, struct thread_info *next_ti,
> + void *sched_ra, void *sched_cfa);
>
> /*
> * For newly created kernel threads switch_to() will return to
> @@ -28,10 +31,11 @@ extern asmlinkage struct task_struct *__switch_to(struct task_struct *prev,
> * That is, everything following __switch_to() will be skipped for new threads.
> * So everything that matters to new threads should be placed before __switch_to().
> */
> -#define switch_to(prev, next, last) \
> -do { \
> - lose_fpu_inatomic(1, prev); \
> - (last) = __switch_to(prev, next, task_thread_info(next)); \
> +#define switch_to(prev, next, last) \
> +do { \
> + lose_fpu_inatomic(1, prev); \
> + (last) = __switch_to(prev, next, task_thread_info(next), \
> + __builtin_return_address(0), __builtin_frame_address(0)); \
> } while (0)
>
> #endif /* _ASM_SWITCH_TO_H */
> diff --git a/arch/loongarch/include/asm/uaccess.h b/arch/loongarch/include/asm/uaccess.h
> index 2b44edc604a2..a8ae2af4025a 100644
> --- a/arch/loongarch/include/asm/uaccess.h
> +++ b/arch/loongarch/include/asm/uaccess.h
> @@ -229,13 +229,13 @@ extern unsigned long __copy_user(void *to, const void *from, __kernel_size_t n);
> static inline unsigned long __must_check
> raw_copy_from_user(void *to, const void __user *from, unsigned long n)
> {
> - return __copy_user(to, from, n);
> + return __copy_user(to, (__force const void *)from, n);
> }
>
> static inline unsigned long __must_check
> raw_copy_to_user(void __user *to, const void *from, unsigned long n)
> {
> - return __copy_user(to, from, n);
> + return __copy_user((__force void *)to, from, n);
Why this? Does it have something to do with stacktrace?

Huacai
> }
>
> #define INLINE_COPY_FROM_USER
> diff --git a/arch/loongarch/kernel/Makefile b/arch/loongarch/kernel/Makefile
> index 918600e7b30f..7449513eb08d 100644
> --- a/arch/loongarch/kernel/Makefile
> +++ b/arch/loongarch/kernel/Makefile
> @@ -15,6 +15,7 @@ obj-$(CONFIG_EFI) += efi.o
> obj-$(CONFIG_CPU_HAS_FPU) += fpu.o
>
> obj-$(CONFIG_MODULES) += module.o module-sections.o
> +obj-$(CONFIG_STACKTRACE) += stacktrace.o
>
> obj-$(CONFIG_PROC_FS) += proc.o
>
> diff --git a/arch/loongarch/kernel/asm-offsets.c b/arch/loongarch/kernel/asm-offsets.c
> index 20cd9e16a95a..eb350f3ffae5 100644
> --- a/arch/loongarch/kernel/asm-offsets.c
> +++ b/arch/loongarch/kernel/asm-offsets.c
> @@ -103,6 +103,8 @@ void output_thread_defines(void)
> OFFSET(THREAD_REG29, task_struct, thread.reg29);
> OFFSET(THREAD_REG30, task_struct, thread.reg30);
> OFFSET(THREAD_REG31, task_struct, thread.reg31);
> + OFFSET(THREAD_SCHED_RA, task_struct, thread.sched_ra);
> + OFFSET(THREAD_SCHED_CFA, task_struct, thread.sched_cfa);
> OFFSET(THREAD_CSRCRMD, task_struct,
> thread.csr_crmd);
> OFFSET(THREAD_CSRPRMD, task_struct,
> diff --git a/arch/loongarch/kernel/process.c b/arch/loongarch/kernel/process.c
> index 709b7a1664f8..34c3f2148714 100644
> --- a/arch/loongarch/kernel/process.c
> +++ b/arch/loongarch/kernel/process.c
> @@ -135,6 +135,7 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
> childregs = (struct pt_regs *) childksp - 1;
> /* Put the stack after the struct pt_regs. */
> childksp = (unsigned long) childregs;
> + p->thread.sched_cfa = 0;
> p->thread.csr_euen = 0;
> p->thread.csr_crmd = csr_read32(LOONGARCH_CSR_CRMD);
> p->thread.csr_prmd = csr_read32(LOONGARCH_CSR_PRMD);
> @@ -145,6 +146,7 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
> p->thread.reg23 = (unsigned long)args->fn;
> p->thread.reg24 = (unsigned long)args->fn_arg;
> p->thread.reg01 = (unsigned long)ret_from_kernel_thread;
> + p->thread.sched_ra = (unsigned long)ret_from_kernel_thread;
> memset(childregs, 0, sizeof(struct pt_regs));
> childregs->csr_euen = p->thread.csr_euen;
> childregs->csr_crmd = p->thread.csr_crmd;
> @@ -161,6 +163,7 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
>
> p->thread.reg03 = (unsigned long) childregs;
> p->thread.reg01 = (unsigned long) ret_from_fork;
> + p->thread.sched_ra = (unsigned long) ret_from_fork;
>
> /*
> * New tasks lose permission to use the fpu. This accelerates context
> diff --git a/arch/loongarch/kernel/stacktrace.c b/arch/loongarch/kernel/stacktrace.c
> new file mode 100644
> index 000000000000..f4f4b8ad3917
> --- /dev/null
> +++ b/arch/loongarch/kernel/stacktrace.c
> @@ -0,0 +1,37 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Stack trace management functions
> + *
> + * Copyright (C) 2022 Loongson Technology Corporation Limited
> + */
> +#include <linux/sched.h>
> +#include <linux/stacktrace.h>
> +
> +#include <asm/stacktrace.h>
> +#include <asm/unwind.h>
> +
> +void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie,
> + struct task_struct *task, struct pt_regs *regs)
> +{
> + struct pt_regs dummyregs;
> + struct unwind_state state;
> + unsigned long addr;
> +
> + regs = &dummyregs;
> +
> + if (task == current) {
> + regs->csr_era = (unsigned long)__builtin_return_address(0);
> + regs->regs[3] = (unsigned long)__builtin_frame_address(0);
> + } else {
> + regs->csr_era = thread_saved_ra(task);
> + regs->regs[3] = thread_saved_fp(task);
> + }
> +
> + regs->regs[1] = 0;
> + for (unwind_start(&state, task, regs);
> + !unwind_done(&state); unwind_next_frame(&state)) {
> + addr = unwind_get_return_address(&state);
> + if (!addr || !consume_entry(cookie, addr))
> + break;
> + }
> +}
> diff --git a/arch/loongarch/kernel/switch.S b/arch/loongarch/kernel/switch.S
> index 37e84ac8ffc2..43ebbc3990f7 100644
> --- a/arch/loongarch/kernel/switch.S
> +++ b/arch/loongarch/kernel/switch.S
> @@ -21,6 +21,8 @@ SYM_FUNC_START(__switch_to)
>
> cpu_save_nonscratch a0
> stptr.d ra, a0, THREAD_REG01
> + stptr.d a3, a0, THREAD_SCHED_RA
> + stptr.d a4, a0, THREAD_SCHED_CFA
> move tp, a2
> cpu_restore_nonscratch a1
>
> --
> 2.20.1
>

2022-08-01 15:43:35

by Huacai Chen

[permalink] [raw]
Subject: Re: [PATCH 4/4] LoongArch: Add USER_STACKTRACE support

Hi, Qing,

On Mon, Aug 1, 2022 at 8:17 PM Qing Zhang <[email protected]> wrote:
>
> To get the best output you can compile your userspace programs with
> frame pointers (at least glibc + the app you are tracing export "CC
> =gcc -fno-omit-frame-pointer".
>
> ...
> echo 'p:malloc /usr/lib64/libc.so.6:0x0a4704 size=%r4:u64'
> > uprobe_events
> echo 'p:free /usr/lib64/libc.so.6:0x0a4d50 ptr=%r4:x64'
> >> uprobe_events
> echo 'comm == "demo"' > ./events/uprobes/malloc/filter
> echo 'comm == "demo"' > ./events/uprobes/free/filter
> echo 1 > ./options/userstacktrace
> echo 1 > ./options/sym-userobj
> ...
>
> Signed-off-by: Qing Zhang <[email protected]>
> ---
> arch/loongarch/Kconfig | 1 +
> arch/loongarch/include/asm/stacktrace.h | 5 +++
> arch/loongarch/kernel/stacktrace.c | 42 +++++++++++++++++++++++++
> 3 files changed, 48 insertions(+)
>
> diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
> index 85d0fa3147cd..05906384d564 100644
> --- a/arch/loongarch/Kconfig
> +++ b/arch/loongarch/Kconfig
> @@ -107,6 +107,7 @@ config LOONGARCH
> select SWIOTLB
> select TRACE_IRQFLAGS_SUPPORT
> select USE_PERCPU_NUMA_NODE_ID
> + select USER_STACKTRACE_SUPPORT
> select ZONE_DMA32
> select MMU_GATHER_MERGE_VMAS if MMU
>
> diff --git a/arch/loongarch/include/asm/stacktrace.h b/arch/loongarch/include/asm/stacktrace.h
> index 49cb89213aeb..77fdb8ad662d 100644
> --- a/arch/loongarch/include/asm/stacktrace.h
> +++ b/arch/loongarch/include/asm/stacktrace.h
> @@ -21,6 +21,11 @@ struct stack_info {
> unsigned long begin, end, next_sp;
> };
>
> +struct stack_frame {
> + unsigned long fp;
> + unsigned long ra;
> +};
> +
> bool in_task_stack(unsigned long stack, struct task_struct *task,
> struct stack_info *info);
> bool in_irq_stack(unsigned long stack, struct stack_info *info);
> diff --git a/arch/loongarch/kernel/stacktrace.c b/arch/loongarch/kernel/stacktrace.c
> index f4f4b8ad3917..344224c7cb0e 100644
> --- a/arch/loongarch/kernel/stacktrace.c
> +++ b/arch/loongarch/kernel/stacktrace.c
> @@ -6,6 +6,7 @@
> */
> #include <linux/sched.h>
> #include <linux/stacktrace.h>
> +#include <linux/uaccess.h>
>
> #include <asm/stacktrace.h>
> #include <asm/unwind.h>
> @@ -35,3 +36,44 @@ void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie,
> break;
> }
> }
> +
> +static int
> +copy_stack_frame(unsigned long fp, struct stack_frame *frame)
> +{
> + int ret;
> + unsigned long err;
> + unsigned long __user *user_frame_tail;
> +
> + user_frame_tail = (unsigned long *)(fp - sizeof(struct stack_frame));
> + if (!access_ok(user_frame_tail, sizeof(*frame)))
> + return 0;
> +
> + ret = 1;
Maybe initializing it at its definition is better?

Huacai
> + pagefault_disable();
> + err = (__copy_from_user_inatomic(frame, user_frame_tail, sizeof(*frame)));
> + if (err || (unsigned long)user_frame_tail >= frame->fp)
> + ret = 0;
> + pagefault_enable();
> +
> + return ret;
> +}
> +
> +void arch_stack_walk_user(stack_trace_consume_fn consume_entry, void *cookie,
> + const struct pt_regs *regs)
> +{
> + unsigned long fp = regs->regs[22];
> +
> + while (fp && !((unsigned long)fp & 0xf)) {
> + struct stack_frame frame;
> +
> + frame.fp = 0;
> + frame.ra = 0;
> + if (!copy_stack_frame(fp, &frame))
> + break;
> + if (!frame.ra)
> + break;
> + if (!consume_entry(cookie, frame.ra))
> + break;
> + fp = frame.fp;
> + }
> +}
> --
> 2.20.1
>
>

2022-08-01 16:34:13

by Huacai Chen

[permalink] [raw]
Subject: Re: [PATCH 0/4] LoongArch: Add unwinder support

Hi, Qing,

I think we don't need to CC linux-kernel; on the other hand, CC
linux-arch and Arnd is worthy.
BTW, it seems you are missing V2 in the title.

Huacai

On Mon, Aug 1, 2022 at 8:17 PM Qing Zhang <[email protected]> wrote:
>
> This series in order to add stacktrace suport, Some upcoming features require
> these changes, like trace, divide unwinder into guess unwinder and prologue
> unwinder is to add new unwinders in the future, eg:unwind_frame, unwind_orc .etc.
> Three stages when we do unwind,
> 1) unwind_start(), the prapare of unwinding, fill unwind_state.
> 2) unwind_done(), judge whether the unwind process is finished or not.
> 3) unwind_next_frame(), unwind the next frame.
>
> you can test them by:
> 1) echo t > /proc/sysrq-trigger
> 2) cat /proc/*/stack
> 4) ftrace: function graph
> 5) uprobe: echo 1 > ./options/userstacktrace
>
> Changes from v1 to v2:
>
> - Add the judgment of the offset value of ra in the prologue.
> (Suggested by Youling).
> - Create an inline function to check the sign bit, which is convenient
> for extending other types of immediates. (Suggested by Jinyang).
> - Fix sparse warning :
> arch/loongarch/include/asm/uaccess.h:232:32: sparse: sparse: incorrect
> type in argument 2 (different address spaces) @@ expected void const
> *from @@ got void const [noderef] __user *from @@
> - Add USER_STACKTRACE support as a series.
>
> Qing Zhang (4):
> LoongArch: Add guess unwinder support
> LoongArch: Add prologue unwinder support
> LoongArch: Add stacktrace support
> LoongArch: Add USER_STACKTRACE support
>
> arch/loongarch/Kconfig | 6 +
> arch/loongarch/Kconfig.debug | 28 ++++
> arch/loongarch/include/asm/inst.h | 52 +++++++
> arch/loongarch/include/asm/processor.h | 9 ++
> arch/loongarch/include/asm/stacktrace.h | 22 +++
> arch/loongarch/include/asm/switch_to.h | 14 +-
> arch/loongarch/include/asm/uaccess.h | 4 +-
> arch/loongarch/include/asm/unwind.h | 45 +++++++
> arch/loongarch/kernel/Makefile | 4 +
> arch/loongarch/kernel/asm-offsets.c | 2 +
> arch/loongarch/kernel/process.c | 64 +++++++++
> arch/loongarch/kernel/stacktrace.c | 79 +++++++++++
> arch/loongarch/kernel/switch.S | 2 +
> arch/loongarch/kernel/traps.c | 27 ++--
> arch/loongarch/kernel/unwind_guess.c | 65 +++++++++
> arch/loongarch/kernel/unwind_prologue.c | 172 ++++++++++++++++++++++++
> 16 files changed, 577 insertions(+), 18 deletions(-)
> create mode 100644 arch/loongarch/include/asm/unwind.h
> create mode 100644 arch/loongarch/kernel/stacktrace.c
> create mode 100644 arch/loongarch/kernel/unwind_guess.c
> create mode 100644 arch/loongarch/kernel/unwind_prologue.c
>
> --
> 2.20.1
>
>

2022-08-02 01:20:56

by Xi Ruoyao

[permalink] [raw]
Subject: Re: [PATCH 0/4] LoongArch: Add unwinder support

On Mon, 2022-08-01 at 23:34 +0800, Huacai Chen wrote:
> Hi, Qing,
>
> I think we don't need to CC linux-kernel; on the other hand, CC
> linux-arch and Arnd is worthy.
> BTW, it seems you are missing V2 in the title.

https://www.kernel.org/doc/html/latest/process/submitting-patches.html#select-the-recipients-for-your-patch:
"[email protected] should be used by default for all
patches".

--
Xi Ruoyao <[email protected]>
School of Aerospace Science and Technology, Xidian University

2022-08-02 01:40:07

by Qing Zhang

[permalink] [raw]
Subject: Re: [PATCH 3/4] LoongArch: Add stacktrace support



On 2022/8/1 下午11:30, Huacai Chen wrote:
> Hi, Qing,
>
> On Mon, Aug 1, 2022 at 8:17 PM Qing Zhang <[email protected]> wrote:
>>
>> Use common arch_stack_walk infrastructure to avoid duplicated code and
>> avoid taking care of the stack storage and filtering.
>> Add sra (means __schedule return address) and scfa (means __schedule call
>> frame address) to thread_info and store it in switch_to().
>>
>> Now we can print the process stack by cat /proc/*/stack and can better
>> support ftrace.
>>
>> Signed-off-by: Qing Zhang <[email protected]>
>> ---
>> arch/loongarch/Kconfig | 5 ++++
>> arch/loongarch/include/asm/processor.h | 9 +++++++
>> arch/loongarch/include/asm/switch_to.h | 14 ++++++----
>> arch/loongarch/include/asm/uaccess.h | 4 +--
>> arch/loongarch/kernel/Makefile | 1 +
>> arch/loongarch/kernel/asm-offsets.c | 2 ++
>> arch/loongarch/kernel/process.c | 3 +++
>> arch/loongarch/kernel/stacktrace.c | 37 ++++++++++++++++++++++++++
>> arch/loongarch/kernel/switch.S | 2 ++
>> 9 files changed, 70 insertions(+), 7 deletions(-)
>> create mode 100644 arch/loongarch/kernel/stacktrace.c
>>
>> diff --git a/arch/loongarch/include/asm/uaccess.h b/arch/loongarch/include/asm/uaccess.h
>> index 2b44edc604a2..a8ae2af4025a 100644
>> --- a/arch/loongarch/include/asm/uaccess.h
>> +++ b/arch/loongarch/include/asm/uaccess.h
>> @@ -229,13 +229,13 @@ extern unsigned long __copy_user(void *to, const void *from, __kernel_size_t n);
>> static inline unsigned long __must_check
>> raw_copy_from_user(void *to, const void __user *from, unsigned long n)
>> {
>> - return __copy_user(to, from, n);
>> + return __copy_user(to, (__force const void *)from, n);
>> }
>>
>> static inline unsigned long __must_check
>> raw_copy_to_user(void __user *to, const void *from, unsigned long n)
>> {
>> - return __copy_user(to, from, n);
>> + return __copy_user((__force void *)to, from, n);
> Why this? Does it have something to do with stacktrace?
>
> Huacai

Hi, huacai

This is kernel test robot report sparse warnings:
I reproduced locally and found that other architectures calling
__copy_user also use __force conversion, Is this modification appropriate?

kernel/trace/trace_events_user.c: note: in included file (through
include/linux/uaccess.h, include/linux/sched/task.h,
include/linux/sched/signal.h, ...):
arch/loongarch/include/asm/uaccess.h:232:32: sparse: sparse:
incorrect type in argument 2 (different address spaces) @@ expected
void const *from @@ got void const [noderef] __user *from @@
arch/loongarch/include/asm/uaccess.h:232:32: sparse: expected
void const *from
arch/loongarch/include/asm/uaccess.h:232:32: sparse: got void
const [noderef] __user *from

Thanks,
-Qing



2022-08-02 01:40:44

by Huacai Chen

[permalink] [raw]
Subject: Re: [PATCH 2/4] LoongArch: Add prologue unwinder support

Hi, Youling,

On Tue, Aug 2, 2022 at 9:30 AM Youling Tang <[email protected]> wrote:
>
>
>
> On 08/01/2022 11:26 PM, Huacai Chen wrote:
> >> diff --git a/arch/loongarch/include/asm/unwind.h b/arch/loongarch/include/asm/unwind.h
> >> index 243330b39d0d..f9f73a26504e 100644
> >> --- a/arch/loongarch/include/asm/unwind.h
> >> +++ b/arch/loongarch/include/asm/unwind.h
> >> @@ -14,6 +14,14 @@
> >> struct unwind_state {
> >> struct stack_info stack_info;
> >> struct task_struct *task;
> >> +#if defined(CONFIG_UNWINDER_PROLOGUE)
> >> + unsigned long ra;
> >> + bool enable;
> >> + /*
> >> + * Enable is the prologue analysis method
> >> + * otherwise is the way to guess.
> >> + */
> >> +#endif
> >> unsigned long sp, pc;
> >> bool first;
> >> bool error;
> > This data struct makes me very uncomfortable, especially "enable" and
> > the #ifdef, maybe we can rework it like this?
> >
> > #define UNWINDER_GUESS 0
> > #define UNWINDER_PROLOGURE 1
>
> Maybe it's better to define with enum type?
> enum unwind_type {
> UNWINDER_GUESS,
> UNWINDER_PROLOGURE,
> };
Both macro and enum are acceptable, but enum is essentially "int",
while the "type" member is "char" here.

Huacai
>
> Youling
>
> > struct unwind_state {
> > char type; /* UNWINDER_xxx */
> > bool first, error;
> > unsigned long sp, pc, ra;
> > struct task_struct *task;
> > struct stack_info stack_info;
> > };
> >
> > Huacai
>
>

2022-08-02 01:41:41

by Youling Tang

[permalink] [raw]
Subject: Re: [PATCH 2/4] LoongArch: Add prologue unwinder support



On 08/01/2022 11:26 PM, Huacai Chen wrote:
>> diff --git a/arch/loongarch/include/asm/unwind.h b/arch/loongarch/include/asm/unwind.h
>> index 243330b39d0d..f9f73a26504e 100644
>> --- a/arch/loongarch/include/asm/unwind.h
>> +++ b/arch/loongarch/include/asm/unwind.h
>> @@ -14,6 +14,14 @@
>> struct unwind_state {
>> struct stack_info stack_info;
>> struct task_struct *task;
>> +#if defined(CONFIG_UNWINDER_PROLOGUE)
>> + unsigned long ra;
>> + bool enable;
>> + /*
>> + * Enable is the prologue analysis method
>> + * otherwise is the way to guess.
>> + */
>> +#endif
>> unsigned long sp, pc;
>> bool first;
>> bool error;
> This data struct makes me very uncomfortable, especially "enable" and
> the #ifdef, maybe we can rework it like this?
>
> #define UNWINDER_GUESS 0
> #define UNWINDER_PROLOGURE 1

Maybe it's better to define with enum type?
enum unwind_type {
UNWINDER_GUESS,
UNWINDER_PROLOGURE,
};

Youling

> struct unwind_state {
> char type; /* UNWINDER_xxx */
> bool first, error;
> unsigned long sp, pc, ra;
> struct task_struct *task;
> struct stack_info stack_info;
> };
>
> Huacai


2022-08-02 01:47:31

by Xi Ruoyao

[permalink] [raw]
Subject: Re: [PATCH 2/4] LoongArch: Add prologue unwinder support

On Tue, 2022-08-02 at 09:34 +0800, Huacai Chen wrote:
> > > #define UNWINDER_GUESS     0
> > > #define UNWINDER_PROLOGURE 1
> >
> > Maybe it's better to define with enum type?
> > enum unwind_type {
> >          UNWINDER_GUESS,
> >          UNWINDER_PROLOGURE,
> > };
> Both macro and enum are acceptable, but enum is essentially "int",
> while the "type" member is "char" here.

"0" or "1" will also be "int" (C99 6.4.4.1 para 5).

--
Xi Ruoyao <[email protected]>
School of Aerospace Science and Technology, Xidian University

2022-08-02 02:18:08

by Huacai Chen

[permalink] [raw]
Subject: Re: [PATCH 3/4] LoongArch: Add stacktrace support

Hi, Qing,

On Tue, Aug 2, 2022 at 9:20 AM zhangqing <[email protected]> wrote:
>
>
>
> On 2022/8/1 下午11:30, Huacai Chen wrote:
> > Hi, Qing,
> >
> > On Mon, Aug 1, 2022 at 8:17 PM Qing Zhang <[email protected]> wrote:
> >>
> >> Use common arch_stack_walk infrastructure to avoid duplicated code and
> >> avoid taking care of the stack storage and filtering.
> >> Add sra (means __schedule return address) and scfa (means __schedule call
> >> frame address) to thread_info and store it in switch_to().
> >>
> >> Now we can print the process stack by cat /proc/*/stack and can better
> >> support ftrace.
> >>
> >> Signed-off-by: Qing Zhang <[email protected]>
> >> ---
> >> arch/loongarch/Kconfig | 5 ++++
> >> arch/loongarch/include/asm/processor.h | 9 +++++++
> >> arch/loongarch/include/asm/switch_to.h | 14 ++++++----
> >> arch/loongarch/include/asm/uaccess.h | 4 +--
> >> arch/loongarch/kernel/Makefile | 1 +
> >> arch/loongarch/kernel/asm-offsets.c | 2 ++
> >> arch/loongarch/kernel/process.c | 3 +++
> >> arch/loongarch/kernel/stacktrace.c | 37 ++++++++++++++++++++++++++
> >> arch/loongarch/kernel/switch.S | 2 ++
> >> 9 files changed, 70 insertions(+), 7 deletions(-)
> >> create mode 100644 arch/loongarch/kernel/stacktrace.c
> >>
> >> diff --git a/arch/loongarch/include/asm/uaccess.h b/arch/loongarch/include/asm/uaccess.h
> >> index 2b44edc604a2..a8ae2af4025a 100644
> >> --- a/arch/loongarch/include/asm/uaccess.h
> >> +++ b/arch/loongarch/include/asm/uaccess.h
> >> @@ -229,13 +229,13 @@ extern unsigned long __copy_user(void *to, const void *from, __kernel_size_t n);
> >> static inline unsigned long __must_check
> >> raw_copy_from_user(void *to, const void __user *from, unsigned long n)
> >> {
> >> - return __copy_user(to, from, n);
> >> + return __copy_user(to, (__force const void *)from, n);
> >> }
> >>
> >> static inline unsigned long __must_check
> >> raw_copy_to_user(void __user *to, const void *from, unsigned long n)
> >> {
> >> - return __copy_user(to, from, n);
> >> + return __copy_user((__force void *)to, from, n);
> > Why this? Does it have something to do with stacktrace?
> >
> > Huacai
>
> Hi, huacai
>
> This is kernel test robot report sparse warnings:
> I reproduced locally and found that other architectures calling
> __copy_user also use __force conversion, Is this modification appropriate?
>
> kernel/trace/trace_events_user.c: note: in included file (through
> include/linux/uaccess.h, include/linux/sched/task.h,
> include/linux/sched/signal.h, ...):
> arch/loongarch/include/asm/uaccess.h:232:32: sparse: sparse:
> incorrect type in argument 2 (different address spaces) @@ expected
> void const *from @@ got void const [noderef] __user *from @@
> arch/loongarch/include/asm/uaccess.h:232:32: sparse: expected
> void const *from
> arch/loongarch/include/asm/uaccess.h:232:32: sparse: got void
> const [noderef] __user *from
The modification might be correct, but should it be in this patch?

Huacai
>
> Thanks,
> -Qing
>
>
>

2022-08-02 02:18:54

by Huacai Chen

[permalink] [raw]
Subject: Re: [PATCH 2/4] LoongArch: Add prologue unwinder support

Hi, Ruoyao,

On Tue, Aug 2, 2022 at 9:39 AM Xi Ruoyao <[email protected]> wrote:
>
> On Tue, 2022-08-02 at 09:34 +0800, Huacai Chen wrote:
> > > > #define UNWINDER_GUESS 0
> > > > #define UNWINDER_PROLOGURE 1
> > >
> > > Maybe it's better to define with enum type?
> > > enum unwind_type {
> > > UNWINDER_GUESS,
> > > UNWINDER_PROLOGURE,
> > > };
> > Both macro and enum are acceptable, but enum is essentially "int",
> > while the "type" member is "char" here.
>
> "0" or "1" will also be "int" (C99 6.4.4.1 para 5).
OK, then Zhang Qing has her rights to choose. :)

Huacai
>
> --
> Xi Ruoyao <[email protected]>
> School of Aerospace Science and Technology, Xidian University

2022-08-02 02:21:29

by Qing Zhang

[permalink] [raw]
Subject: Re: [PATCH 0/4] LoongArch: Add unwinder support



On 2022/8/1 下午11:34, Huacai Chen wrote:
> Hi, Qing,
>
> I think we don't need to CC linux-kernel; on the other hand, CC
> linux-arch and Arnd is worthy.
> BTW, it seems you are missing V2 in the title.
>
> Huacai

Hi, Huacai

Made a careless error...

Thanks,
-Qing


2022-08-02 03:05:56

by Qing Zhang

[permalink] [raw]
Subject: Re: [PATCH 3/4] LoongArch: Add stacktrace support



On 2022/8/2 上午9:30, Huacai Chen wrote:
> Hi, Qing,
>
> On Tue, Aug 2, 2022 at 9:20 AM zhangqing <[email protected]> wrote:
>>
>>
>>
>> On 2022/8/1 下午11:30, Huacai Chen wrote:
>>> Hi, Qing,
>>>
>>> On Mon, Aug 1, 2022 at 8:17 PM Qing Zhang <[email protected]> wrote:
>>>>
>>>> Use common arch_stack_walk infrastructure to avoid duplicated code and
>>>> avoid taking care of the stack storage and filtering.
>>>> Add sra (means __schedule return address) and scfa (means __schedule call
>>>> frame address) to thread_info and store it in switch_to().
>>>>
>>>> Now we can print the process stack by cat /proc/*/stack and can better
>>>> support ftrace.
>>>>
>>>> Signed-off-by: Qing Zhang <[email protected]>
>>>> ---
>>>> arch/loongarch/Kconfig | 5 ++++
>>>> arch/loongarch/include/asm/processor.h | 9 +++++++
>>>> arch/loongarch/include/asm/switch_to.h | 14 ++++++----
>>>> arch/loongarch/include/asm/uaccess.h | 4 +--
>>>> arch/loongarch/kernel/Makefile | 1 +
>>>> arch/loongarch/kernel/asm-offsets.c | 2 ++
>>>> arch/loongarch/kernel/process.c | 3 +++
>>>> arch/loongarch/kernel/stacktrace.c | 37 ++++++++++++++++++++++++++
>>>> arch/loongarch/kernel/switch.S | 2 ++
>>>> 9 files changed, 70 insertions(+), 7 deletions(-)
>>>> create mode 100644 arch/loongarch/kernel/stacktrace.c
>>>>
>>>> diff --git a/arch/loongarch/include/asm/uaccess.h b/arch/loongarch/include/asm/uaccess.h
>>>> index 2b44edc604a2..a8ae2af4025a 100644
>>>> --- a/arch/loongarch/include/asm/uaccess.h
>>>> +++ b/arch/loongarch/include/asm/uaccess.h
>>>> @@ -229,13 +229,13 @@ extern unsigned long __copy_user(void *to, const void *from, __kernel_size_t n);
>>>> static inline unsigned long __must_check
>>>> raw_copy_from_user(void *to, const void __user *from, unsigned long n)
>>>> {
>>>> - return __copy_user(to, from, n);
>>>> + return __copy_user(to, (__force const void *)from, n);
>>>> }
>>>>
>>>> static inline unsigned long __must_check
>>>> raw_copy_to_user(void __user *to, const void *from, unsigned long n)
>>>> {
>>>> - return __copy_user(to, from, n);
>>>> + return __copy_user((__force void *)to, from, n);
>>> Why this? Does it have something to do with stacktrace?
>>>
>>> Huacai
>>
>> Hi, huacai
>>
>> This is kernel test robot report sparse warnings:
>> I reproduced locally and found that other architectures calling
>> __copy_user also use __force conversion, Is this modification appropriate?
>>
>> kernel/trace/trace_events_user.c: note: in included file (through
>> include/linux/uaccess.h, include/linux/sched/task.h,
>> include/linux/sched/signal.h, ...):
>> arch/loongarch/include/asm/uaccess.h:232:32: sparse: sparse:
>> incorrect type in argument 2 (different address spaces) @@ expected
>> void const *from @@ got void const [noderef] __user *from @@
>> arch/loongarch/include/asm/uaccess.h:232:32: sparse: expected
>> void const *from
>> arch/loongarch/include/asm/uaccess.h:232:32: sparse: got void
>> const [noderef] __user *from
> The modification might be correct, but should it be in this patch?
>
> Huacai
I will send this patch separately, it has nothing to do with the series
patch.

arch/loongarch/kernel/ptrace.c: note: in included file (through
include/linux/uaccess.h, include/linux/sched/task.h,
include/linux/sched/signal.h, include/linux/ptrace.h, include/linux/audit.h)

-Qing
>>
>> Thanks,
>> -Qing
>>
>>
>>


2022-08-13 22:31:57

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH 3/4] LoongArch: Add stacktrace support

Hi Qing,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[also build test WARNING on v5.19]
[cannot apply to next-20220812]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Qing-Zhang/LoongArch-Add-unwinder-support/20220801-204020
base: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 3d7cb6b04c3f3115719235cc6866b10326de34cd
config: loongarch-randconfig-s041-20220814 (https://download.01.org/0day-ci/archive/20220814/[email protected]/config)
compiler: loongarch64-linux-gcc (GCC) 12.1.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# apt-get install sparse
# sparse version: v0.6.4-39-gce1a6720-dirty
# https://github.com/intel-lab-lkp/linux/commit/102a43b57dafc9c0058a458a62d4133eb8020cbc
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Qing-Zhang/LoongArch-Add-unwinder-support/20220801-204020
git checkout 102a43b57dafc9c0058a458a62d4133eb8020cbc
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=loongarch SHELL=/bin/bash kernel/time/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <[email protected]>

sparse warnings: (new ones prefixed by >>)
>> kernel/time/tick-sched.c:1151:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/time/tick-sched.c:1151:9: sparse: expected void *ptr
kernel/time/tick-sched.c:1151:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/time/tick-sched.c:1151:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/time/tick-sched.c:1151:9: sparse: expected void *ptr
kernel/time/tick-sched.c:1151:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/time/tick-sched.c:1151:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/time/tick-sched.c:1151:9: sparse: expected void *ptr
kernel/time/tick-sched.c:1151:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/time/tick-sched.c:1151:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/time/tick-sched.c:1151:9: sparse: expected void *ptr
kernel/time/tick-sched.c:1151:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/time/tick-sched.c:1151:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/time/tick-sched.c:1151:9: sparse: expected void *ptr
kernel/time/tick-sched.c:1151:9: sparse: got int [noderef] __percpu *
>> kernel/time/tick-sched.c:1151:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/time/tick-sched.c:1151:9: sparse: expected void *ptr
kernel/time/tick-sched.c:1151:9: sparse: got int [noderef] __percpu *
>> kernel/time/tick-sched.c:1151:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/time/tick-sched.c:1151:9: sparse: expected void *ptr
kernel/time/tick-sched.c:1151:9: sparse: got int [noderef] __percpu *
>> kernel/time/tick-sched.c:1151:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/time/tick-sched.c:1151:9: sparse: expected void *ptr
kernel/time/tick-sched.c:1151:9: sparse: got int [noderef] __percpu *

vim +1151 kernel/time/tick-sched.c

554c8aa8ecade2 Rafael J. Wysocki 2018-04-03 1141
0e7767687fdabf Rafael J. Wysocki 2018-04-05 1142 /**
0e7767687fdabf Rafael J. Wysocki 2018-04-05 1143 * tick_nohz_idle_enter - prepare for entering idle on the current CPU
2bbb6817c0ac1b Frederic Weisbecker 2011-10-08 1144 *
0e7767687fdabf Rafael J. Wysocki 2018-04-05 1145 * Called when we start the idle loop.
280f06774afedf Frederic Weisbecker 2011-10-07 1146 */
1268fbc746ea1c Frederic Weisbecker 2011-11-17 1147 void tick_nohz_idle_enter(void)
280f06774afedf Frederic Weisbecker 2011-10-07 1148 {
280f06774afedf Frederic Weisbecker 2011-10-07 1149 struct tick_sched *ts;
280f06774afedf Frederic Weisbecker 2011-10-07 1150
ebf3adbad012b8 Frederic Weisbecker 2017-11-06 @1151 lockdep_assert_irqs_enabled();
0db49b72bce263 Linus Torvalds 2012-01-06 1152
1268fbc746ea1c Frederic Weisbecker 2011-11-17 1153 local_irq_disable();
1268fbc746ea1c Frederic Weisbecker 2011-11-17 1154
22127e93c587af Christoph Lameter 2014-08-17 1155 ts = this_cpu_ptr(&tick_cpu_sched);
23a8d888107ce4 Rafael J. Wysocki 2018-04-05 1156
23a8d888107ce4 Rafael J. Wysocki 2018-04-05 1157 WARN_ON_ONCE(ts->timer_expires_base);
23a8d888107ce4 Rafael J. Wysocki 2018-04-05 1158
280f06774afedf Frederic Weisbecker 2011-10-07 1159 ts->inidle = 1;
0e7767687fdabf Rafael J. Wysocki 2018-04-05 1160 tick_nohz_start_idle(ts);
1268fbc746ea1c Frederic Weisbecker 2011-11-17 1161
1268fbc746ea1c Frederic Weisbecker 2011-11-17 1162 local_irq_enable();
280f06774afedf Frederic Weisbecker 2011-10-07 1163 }
280f06774afedf Frederic Weisbecker 2011-10-07 1164

--
0-DAY CI Kernel Test Service
https://01.org/lkp

2022-08-14 05:41:18

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH 3/4] LoongArch: Add stacktrace support

Hi Qing,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[also build test WARNING on v5.19]
[cannot apply to next-20220812]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Qing-Zhang/LoongArch-Add-unwinder-support/20220801-204020
base: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 3d7cb6b04c3f3115719235cc6866b10326de34cd
config: loongarch-randconfig-s033-20220814 (https://download.01.org/0day-ci/archive/20220814/[email protected]/config)
compiler: loongarch64-linux-gcc (GCC) 12.1.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# apt-get install sparse
# sparse version: v0.6.4-39-gce1a6720-dirty
# https://github.com/intel-lab-lkp/linux/commit/102a43b57dafc9c0058a458a62d4133eb8020cbc
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Qing-Zhang/LoongArch-Add-unwinder-support/20220801-204020
git checkout 102a43b57dafc9c0058a458a62d4133eb8020cbc
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=loongarch SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <[email protected]>

sparse warnings: (new ones prefixed by >>)
>> kernel/smp.c:571:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/smp.c:571:9: sparse: expected void *ptr
kernel/smp.c:571:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/smp.c:571:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/smp.c:571:9: sparse: expected void *ptr
kernel/smp.c:571:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/smp.c:571:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/smp.c:571:9: sparse: expected void *ptr
kernel/smp.c:571:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/smp.c:571:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/smp.c:571:9: sparse: expected void *ptr
kernel/smp.c:571:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/smp.c:571:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/smp.c:571:9: sparse: expected void *ptr
kernel/smp.c:571:9: sparse: got int [noderef] __percpu *
>> kernel/smp.c:571:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/smp.c:571:9: sparse: expected void *ptr
kernel/smp.c:571:9: sparse: got int [noderef] __percpu *
>> kernel/smp.c:571:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/smp.c:571:9: sparse: expected void *ptr
kernel/smp.c:571:9: sparse: got int [noderef] __percpu *
>> kernel/smp.c:571:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/smp.c:571:9: sparse: expected void *ptr
kernel/smp.c:571:9: sparse: got int [noderef] __percpu *
kernel/smp.c:895:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/smp.c:895:9: sparse: expected void *ptr
kernel/smp.c:895:9: sparse: got unsigned int [noderef] __percpu *
kernel/smp.c:895:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/smp.c:895:9: sparse: expected void *ptr
kernel/smp.c:895:9: sparse: got unsigned int [noderef] __percpu *
kernel/smp.c:895:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/smp.c:895:9: sparse: expected void *ptr
kernel/smp.c:895:9: sparse: got unsigned int [noderef] __percpu *
kernel/smp.c:895:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/smp.c:895:9: sparse: expected void *ptr
kernel/smp.c:895:9: sparse: got unsigned int [noderef] __percpu *
kernel/smp.c:895:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/smp.c:895:9: sparse: expected void *ptr
kernel/smp.c:895:9: sparse: got int [noderef] __percpu *
kernel/smp.c:895:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/smp.c:895:9: sparse: expected void *ptr
kernel/smp.c:895:9: sparse: got int [noderef] __percpu *
kernel/smp.c:895:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/smp.c:895:9: sparse: expected void *ptr
kernel/smp.c:895:9: sparse: got int [noderef] __percpu *
kernel/smp.c:895:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/smp.c:895:9: sparse: expected void *ptr
kernel/smp.c:895:9: sparse: got int [noderef] __percpu *
kernel/smp.c:905:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/smp.c:905:17: sparse: expected void *ptr
kernel/smp.c:905:17: sparse: got unsigned int [noderef] __percpu *
kernel/smp.c:905:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/smp.c:905:17: sparse: expected void *ptr
kernel/smp.c:905:17: sparse: got unsigned int [noderef] __percpu *
kernel/smp.c:905:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/smp.c:905:17: sparse: expected void *ptr
kernel/smp.c:905:17: sparse: got unsigned int [noderef] __percpu *
kernel/smp.c:905:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/smp.c:905:17: sparse: expected void *ptr
kernel/smp.c:905:17: sparse: got unsigned int [noderef] __percpu *
kernel/smp.c:905:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/smp.c:905:17: sparse: expected void *ptr
kernel/smp.c:905:17: sparse: got int [noderef] __percpu *
kernel/smp.c:905:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/smp.c:905:17: sparse: expected void *ptr
kernel/smp.c:905:17: sparse: got int [noderef] __percpu *
kernel/smp.c:905:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/smp.c:905:17: sparse: expected void *ptr
kernel/smp.c:905:17: sparse: got int [noderef] __percpu *
kernel/smp.c:905:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/smp.c:905:17: sparse: expected void *ptr
kernel/smp.c:905:17: sparse: got int [noderef] __percpu *
--
>> kernel/sched/fair.c:6475:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/sched/fair.c:6475:9: sparse: expected void *ptr
kernel/sched/fair.c:6475:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/sched/fair.c:6475:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/sched/fair.c:6475:9: sparse: expected void *ptr
kernel/sched/fair.c:6475:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/sched/fair.c:6475:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/sched/fair.c:6475:9: sparse: expected void *ptr
kernel/sched/fair.c:6475:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/sched/fair.c:6475:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/sched/fair.c:6475:9: sparse: expected void *ptr
kernel/sched/fair.c:6475:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/sched/fair.c:6475:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/sched/fair.c:6475:9: sparse: expected void *ptr
kernel/sched/fair.c:6475:9: sparse: got int [noderef] __percpu *
>> kernel/sched/fair.c:6475:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/sched/fair.c:6475:9: sparse: expected void *ptr
kernel/sched/fair.c:6475:9: sparse: got int [noderef] __percpu *
>> kernel/sched/fair.c:6475:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/sched/fair.c:6475:9: sparse: expected void *ptr
kernel/sched/fair.c:6475:9: sparse: got int [noderef] __percpu *
>> kernel/sched/fair.c:6475:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/sched/fair.c:6475:9: sparse: expected void *ptr
kernel/sched/fair.c:6475:9: sparse: got int [noderef] __percpu *
kernel/sched/fair.c:930:34: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct sched_entity *se @@ got struct sched_entity [noderef] __rcu * @@
kernel/sched/fair.c:930:34: sparse: expected struct sched_entity *se
kernel/sched/fair.c:930:34: sparse: got struct sched_entity [noderef] __rcu *
kernel/sched/fair.c:10928:9: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct sched_domain *[assigned] sd @@ got struct sched_domain [noderef] __rcu *parent @@
kernel/sched/fair.c:10928:9: sparse: expected struct sched_domain *[assigned] sd
kernel/sched/fair.c:10928:9: sparse: got struct sched_domain [noderef] __rcu *parent
kernel/sched/fair.c:5591:38: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct task_struct *curr @@ got struct task_struct [noderef] __rcu *curr @@
kernel/sched/fair.c:5591:38: sparse: expected struct task_struct *curr
kernel/sched/fair.c:5591:38: sparse: got struct task_struct [noderef] __rcu *curr
kernel/sched/fair.c:5846:1: sparse: sparse: symbol '__pcpu_scope_load_balance_mask' was not declared. Should it be static?
kernel/sched/fair.c:5847:1: sparse: sparse: symbol '__pcpu_scope_select_idle_mask' was not declared. Should it be static?
kernel/sched/fair.c:6774:20: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct sched_domain *[assigned] sd @@ got struct sched_domain [noderef] __rcu *parent @@
kernel/sched/fair.c:6774:20: sparse: expected struct sched_domain *[assigned] sd
kernel/sched/fair.c:6774:20: sparse: got struct sched_domain [noderef] __rcu *parent
kernel/sched/fair.c:6908:9: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct sched_domain *[assigned] tmp @@ got struct sched_domain [noderef] __rcu *parent @@
kernel/sched/fair.c:6908:9: sparse: expected struct sched_domain *[assigned] tmp
kernel/sched/fair.c:6908:9: sparse: got struct sched_domain [noderef] __rcu *parent
kernel/sched/fair.c:7106:38: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct task_struct *curr @@ got struct task_struct [noderef] __rcu *curr @@
kernel/sched/fair.c:7106:38: sparse: expected struct task_struct *curr
kernel/sched/fair.c:7106:38: sparse: got struct task_struct [noderef] __rcu *curr
kernel/sched/fair.c:7404:38: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct task_struct *curr @@ got struct task_struct [noderef] __rcu *curr @@
kernel/sched/fair.c:7404:38: sparse: expected struct task_struct *curr
kernel/sched/fair.c:7404:38: sparse: got struct task_struct [noderef] __rcu *curr
kernel/sched/fair.c:8389:40: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct sched_domain *child @@ got struct sched_domain [noderef] __rcu *child @@
kernel/sched/fair.c:8389:40: sparse: expected struct sched_domain *child
kernel/sched/fair.c:8389:40: sparse: got struct sched_domain [noderef] __rcu *child
kernel/sched/fair.c:8933:22: sparse: sparse: incompatible types in comparison expression (different address spaces):
kernel/sched/fair.c:8933:22: sparse: struct task_struct [noderef] __rcu *
kernel/sched/fair.c:8933:22: sparse: struct task_struct *
kernel/sched/fair.c:10203:9: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct sched_domain *[assigned] sd @@ got struct sched_domain [noderef] __rcu *parent @@
kernel/sched/fair.c:10203:9: sparse: expected struct sched_domain *[assigned] sd
kernel/sched/fair.c:10203:9: sparse: got struct sched_domain [noderef] __rcu *parent
kernel/sched/fair.c:9863:44: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct sched_domain *sd_parent @@ got struct sched_domain [noderef] __rcu *parent @@
kernel/sched/fair.c:9863:44: sparse: expected struct sched_domain *sd_parent
kernel/sched/fair.c:9863:44: sparse: got struct sched_domain [noderef] __rcu *parent
kernel/sched/fair.c:10299:9: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct sched_domain *[assigned] sd @@ got struct sched_domain [noderef] __rcu *parent @@
kernel/sched/fair.c:10299:9: sparse: expected struct sched_domain *[assigned] sd
kernel/sched/fair.c:10299:9: sparse: got struct sched_domain [noderef] __rcu *parent
kernel/sched/fair.c:5520:35: sparse: sparse: marked inline, but without a definition
kernel/sched/fair.c: note: in included file:
kernel/sched/sched.h:2018:25: sparse: sparse: incompatible types in comparison expression (different address spaces):
kernel/sched/sched.h:2018:25: sparse: struct task_struct [noderef] __rcu *
kernel/sched/sched.h:2018:25: sparse: struct task_struct *
kernel/sched/sched.h:2176:9: sparse: sparse: incompatible types in comparison expression (different address spaces):
kernel/sched/sched.h:2176:9: sparse: struct task_struct [noderef] __rcu *
kernel/sched/sched.h:2176:9: sparse: struct task_struct *
kernel/sched/sched.h:2018:25: sparse: sparse: incompatible types in comparison expression (different address spaces):
kernel/sched/sched.h:2018:25: sparse: struct task_struct [noderef] __rcu *
kernel/sched/sched.h:2018:25: sparse: struct task_struct *
kernel/sched/sched.h:2018:25: sparse: sparse: incompatible types in comparison expression (different address spaces):
kernel/sched/sched.h:2018:25: sparse: struct task_struct [noderef] __rcu *
kernel/sched/sched.h:2018:25: sparse: struct task_struct *
--
>> kernel/sched/core.c:597:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/sched/core.c:597:9: sparse: expected void *ptr
kernel/sched/core.c:597:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/sched/core.c:597:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/sched/core.c:597:9: sparse: expected void *ptr
kernel/sched/core.c:597:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/sched/core.c:597:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/sched/core.c:597:9: sparse: expected void *ptr
kernel/sched/core.c:597:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/sched/core.c:597:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/sched/core.c:597:9: sparse: expected void *ptr
kernel/sched/core.c:597:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/sched/core.c:597:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/sched/core.c:597:9: sparse: expected void *ptr
kernel/sched/core.c:597:9: sparse: got int [noderef] __percpu *
>> kernel/sched/core.c:597:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/sched/core.c:597:9: sparse: expected void *ptr
kernel/sched/core.c:597:9: sparse: got int [noderef] __percpu *
>> kernel/sched/core.c:597:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/sched/core.c:597:9: sparse: expected void *ptr
kernel/sched/core.c:597:9: sparse: got int [noderef] __percpu *
>> kernel/sched/core.c:597:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/sched/core.c:597:9: sparse: expected void *ptr
kernel/sched/core.c:597:9: sparse: got int [noderef] __percpu *
kernel/sched/core.c:780:48: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected struct task_struct *p @@ got struct task_struct [noderef] __rcu *curr @@
kernel/sched/core.c:780:48: sparse: expected struct task_struct *p
kernel/sched/core.c:780:48: sparse: got struct task_struct [noderef] __rcu *curr
kernel/sched/core.c:1033:38: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct task_struct *curr @@ got struct task_struct [noderef] __rcu *curr @@
kernel/sched/core.c:1033:38: sparse: expected struct task_struct *curr
kernel/sched/core.c:1033:38: sparse: got struct task_struct [noderef] __rcu *curr
kernel/sched/core.c:1091:9: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct sched_domain *[assigned] sd @@ got struct sched_domain [noderef] __rcu *parent @@
kernel/sched/core.c:1091:9: sparse: expected struct sched_domain *[assigned] sd
kernel/sched/core.c:1091:9: sparse: got struct sched_domain [noderef] __rcu *parent
kernel/sched/core.c:2197:33: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct task_struct *p @@ got struct task_struct [noderef] __rcu *curr @@
kernel/sched/core.c:2197:33: sparse: expected struct task_struct *p
kernel/sched/core.c:2197:33: sparse: got struct task_struct [noderef] __rcu *curr
kernel/sched/core.c:2197:68: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct task_struct *tsk @@ got struct task_struct [noderef] __rcu *curr @@
kernel/sched/core.c:2197:68: sparse: expected struct task_struct *tsk
kernel/sched/core.c:2197:68: sparse: got struct task_struct [noderef] __rcu *curr
kernel/sched/core.c:3597:17: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct sched_domain *[assigned] sd @@ got struct sched_domain [noderef] __rcu *parent @@
kernel/sched/core.c:3597:17: sparse: expected struct sched_domain *[assigned] sd
kernel/sched/core.c:3597:17: sparse: got struct sched_domain [noderef] __rcu *parent
kernel/sched/core.c:3794:28: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct task_struct const *p @@ got struct task_struct [noderef] __rcu *curr @@
kernel/sched/core.c:3794:28: sparse: expected struct task_struct const *p
kernel/sched/core.c:3794:28: sparse: got struct task_struct [noderef] __rcu *curr
kernel/sched/core.c:9084:43: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct task_struct *push_task @@ got struct task_struct [noderef] __rcu *curr @@
kernel/sched/core.c:9084:43: sparse: expected struct task_struct *push_task
kernel/sched/core.c:9084:43: sparse: got struct task_struct [noderef] __rcu *curr
kernel/sched/core.c:5404:38: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected struct task_struct *curr @@ got struct task_struct [noderef] __rcu *curr @@
kernel/sched/core.c:5404:38: sparse: expected struct task_struct *curr
kernel/sched/core.c:5404:38: sparse: got struct task_struct [noderef] __rcu *curr
kernel/sched/core.c:5495:14: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct task_struct *curr @@ got struct task_struct [noderef] __rcu *curr @@
kernel/sched/core.c:5495:14: sparse: expected struct task_struct *curr
kernel/sched/core.c:5495:14: sparse: got struct task_struct [noderef] __rcu *curr
kernel/sched/core.c:6350:14: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected struct task_struct *prev @@ got struct task_struct [noderef] __rcu *curr @@
kernel/sched/core.c:6350:14: sparse: expected struct task_struct *prev
kernel/sched/core.c:6350:14: sparse: got struct task_struct [noderef] __rcu *curr
kernel/sched/core.c:6872:17: sparse: sparse: incompatible types in comparison expression (different address spaces):
kernel/sched/core.c:6872:17: sparse: struct task_struct *
kernel/sched/core.c:6872:17: sparse: struct task_struct [noderef] __rcu *
kernel/sched/core.c:7076:22: sparse: sparse: incompatible types in comparison expression (different address spaces):
kernel/sched/core.c:7076:22: sparse: struct task_struct [noderef] __rcu *
kernel/sched/core.c:7076:22: sparse: struct task_struct *
kernel/sched/core.c:11116:25: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct task_struct *p @@ got struct task_struct [noderef] __rcu *curr @@
kernel/sched/core.c:11116:25: sparse: expected struct task_struct *p
kernel/sched/core.c:11116:25: sparse: got struct task_struct [noderef] __rcu *curr
kernel/sched/core.c:537:6: sparse: sparse: context imbalance in 'raw_spin_rq_lock_nested' - wrong count at exit
kernel/sched/core.c:562:6: sparse: sparse: context imbalance in 'raw_spin_rq_trylock' - wrong count at exit
kernel/sched/core.c:586:6: sparse: sparse: context imbalance in 'raw_spin_rq_unlock' - unexpected unlock
kernel/sched/core.c:624:36: sparse: sparse: context imbalance in '__task_rq_lock' - wrong count at exit
kernel/sched/core.c:665:36: sparse: sparse: context imbalance in 'task_rq_lock' - wrong count at exit
kernel/sched/core.c: note: in included file:
kernel/sched/pelt.h:78:13: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected struct task_struct const *p @@ got struct task_struct [noderef] __rcu *curr @@
kernel/sched/pelt.h:78:13: sparse: expected struct task_struct const *p
kernel/sched/pelt.h:78:13: sparse: got struct task_struct [noderef] __rcu *curr
kernel/sched/core.c:780:11: sparse: sparse: dereference of noderef expression
kernel/sched/core.c:2188:33: sparse: sparse: dereference of noderef expression
kernel/sched/core.c:2189:19: sparse: sparse: dereference of noderef expression
kernel/sched/core.c:2190:18: sparse: sparse: dereference of noderef expression
kernel/sched/core.c: note: in included file:
kernel/sched/sched.h:2018:25: sparse: sparse: incompatible types in comparison expression (different address spaces):
kernel/sched/sched.h:2018:25: sparse: struct task_struct [noderef] __rcu *
kernel/sched/sched.h:2018:25: sparse: struct task_struct *
kernel/sched/sched.h:2176:9: sparse: sparse: incompatible types in comparison expression (different address spaces):
kernel/sched/sched.h:2176:9: sparse: struct task_struct [noderef] __rcu *
kernel/sched/sched.h:2176:9: sparse: struct task_struct *
kernel/sched/core.c:2163:38: sparse: sparse: incompatible types in comparison expression (different address spaces):
kernel/sched/core.c:2163:38: sparse: struct task_struct [noderef] __rcu *
kernel/sched/core.c:2163:38: sparse: struct task_struct const *
kernel/sched/sched.h:2018:25: sparse: sparse: incompatible types in comparison expression (different address spaces):
kernel/sched/sched.h:2018:25: sparse: struct task_struct [noderef] __rcu *
kernel/sched/sched.h:2018:25: sparse: struct task_struct *
kernel/sched/sched.h:2176:9: sparse: sparse: incompatible types in comparison expression (different address spaces):
kernel/sched/sched.h:2176:9: sparse: struct task_struct [noderef] __rcu *
kernel/sched/sched.h:2176:9: sparse: struct task_struct *
kernel/sched/sched.h:2176:9: sparse: sparse: incompatible types in comparison expression (different address spaces):
kernel/sched/sched.h:2176:9: sparse: struct task_struct [noderef] __rcu *
kernel/sched/sched.h:2176:9: sparse: struct task_struct *
kernel/sched/core.c: note: in included file (through arch/loongarch/include/asm/cpu-info.h, arch/loongarch/include/asm/processor.h, ...):
arch/loongarch/include/asm/loongarch.h:242:9: sparse: sparse: undefined identifier '__builtin_loongarch_csrwr_w'
arch/loongarch/include/asm/loongarch.h:242:9: sparse: sparse: cast from unknown type
arch/loongarch/include/asm/loongarch.h:247:9: sparse: sparse: undefined identifier '__builtin_loongarch_csrwr_d'
arch/loongarch/include/asm/loongarch.h:247:9: sparse: sparse: cast from unknown type
arch/loongarch/include/asm/loongarch.h:247:9: sparse: sparse: cast from unknown type
arch/loongarch/include/asm/loongarch.h:232:16: sparse: sparse: undefined identifier '__builtin_loongarch_csrrd_w'
arch/loongarch/include/asm/loongarch.h:232:16: sparse: sparse: cast from unknown type
arch/loongarch/include/asm/loongarch.h:242:9: sparse: sparse: cast from unknown type
kernel/sched/core.c: note: in included file:
kernel/sched/sched.h:2018:25: sparse: sparse: incompatible types in comparison expression (different address spaces):
kernel/sched/sched.h:2018:25: sparse: struct task_struct [noderef] __rcu *
kernel/sched/sched.h:2018:25: sparse: struct task_struct *
kernel/sched/sched.h:2176:9: sparse: sparse: incompatible types in comparison expression (different address spaces):
kernel/sched/sched.h:2176:9: sparse: struct task_struct [noderef] __rcu *
kernel/sched/sched.h:2176:9: sparse: struct task_struct *
kernel/sched/sched.h:2018:25: sparse: sparse: incompatible types in comparison expression (different address spaces):
kernel/sched/sched.h:2018:25: sparse: struct task_struct [noderef] __rcu *
kernel/sched/sched.h:2018:25: sparse: struct task_struct *
kernel/sched/sched.h:2176:9: sparse: sparse: incompatible types in comparison expression (different address spaces):
kernel/sched/sched.h:2176:9: sparse: struct task_struct [noderef] __rcu *
kernel/sched/sched.h:2176:9: sparse: struct task_struct *
kernel/sched/sched.h:2018:25: sparse: sparse: incompatible types in comparison expression (different address spaces):
kernel/sched/sched.h:2018:25: sparse: struct task_struct [noderef] __rcu *
--
>> kernel/locking/mutex.c:357:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/locking/mutex.c:357:9: sparse: expected void *ptr
kernel/locking/mutex.c:357:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/locking/mutex.c:357:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/locking/mutex.c:357:9: sparse: expected void *ptr
kernel/locking/mutex.c:357:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/locking/mutex.c:357:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/locking/mutex.c:357:9: sparse: expected void *ptr
kernel/locking/mutex.c:357:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/locking/mutex.c:357:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/locking/mutex.c:357:9: sparse: expected void *ptr
kernel/locking/mutex.c:357:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/locking/mutex.c:357:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/locking/mutex.c:357:9: sparse: expected void *ptr
kernel/locking/mutex.c:357:9: sparse: got int [noderef] __percpu *
>> kernel/locking/mutex.c:357:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/locking/mutex.c:357:9: sparse: expected void *ptr
kernel/locking/mutex.c:357:9: sparse: got int [noderef] __percpu *
>> kernel/locking/mutex.c:357:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/locking/mutex.c:357:9: sparse: expected void *ptr
kernel/locking/mutex.c:357:9: sparse: got int [noderef] __percpu *
>> kernel/locking/mutex.c:357:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/locking/mutex.c:357:9: sparse: expected void *ptr
kernel/locking/mutex.c:357:9: sparse: got int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got unsigned int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got unsigned int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got unsigned int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got unsigned int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got unsigned int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got unsigned int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got unsigned int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got unsigned int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got unsigned int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got unsigned int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got unsigned int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got unsigned int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got unsigned int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got unsigned int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got unsigned int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got unsigned int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
kernel/locking/mutex.c:397:9: sparse: got int [noderef] __percpu *
kernel/locking/mutex.c:397:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/locking/mutex.c:397:9: sparse: expected void *ptr
--
>> kernel/locking/rwsem.c:751:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/locking/rwsem.c:751:9: sparse: expected void *ptr
kernel/locking/rwsem.c:751:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/locking/rwsem.c:751:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/locking/rwsem.c:751:9: sparse: expected void *ptr
kernel/locking/rwsem.c:751:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/locking/rwsem.c:751:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/locking/rwsem.c:751:9: sparse: expected void *ptr
kernel/locking/rwsem.c:751:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/locking/rwsem.c:751:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/locking/rwsem.c:751:9: sparse: expected void *ptr
kernel/locking/rwsem.c:751:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/locking/rwsem.c:751:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/locking/rwsem.c:751:9: sparse: expected void *ptr
kernel/locking/rwsem.c:751:9: sparse: got int [noderef] __percpu *
>> kernel/locking/rwsem.c:751:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/locking/rwsem.c:751:9: sparse: expected void *ptr
kernel/locking/rwsem.c:751:9: sparse: got int [noderef] __percpu *
>> kernel/locking/rwsem.c:751:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/locking/rwsem.c:751:9: sparse: expected void *ptr
kernel/locking/rwsem.c:751:9: sparse: got int [noderef] __percpu *
>> kernel/locking/rwsem.c:751:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/locking/rwsem.c:751:9: sparse: expected void *ptr
kernel/locking/rwsem.c:751:9: sparse: got int [noderef] __percpu *
--
kernel/rcu/tree.c: note: in included file:
>> kernel/rcu/tree_exp.h:807:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_exp.h:807:9: sparse: expected void *ptr
kernel/rcu/tree_exp.h:807:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/rcu/tree_exp.h:807:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_exp.h:807:9: sparse: expected void *ptr
kernel/rcu/tree_exp.h:807:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/rcu/tree_exp.h:807:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_exp.h:807:9: sparse: expected void *ptr
kernel/rcu/tree_exp.h:807:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/rcu/tree_exp.h:807:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_exp.h:807:9: sparse: expected void *ptr
kernel/rcu/tree_exp.h:807:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/rcu/tree_exp.h:807:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_exp.h:807:9: sparse: expected void *ptr
kernel/rcu/tree_exp.h:807:9: sparse: got int [noderef] __percpu *
>> kernel/rcu/tree_exp.h:807:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_exp.h:807:9: sparse: expected void *ptr
kernel/rcu/tree_exp.h:807:9: sparse: got int [noderef] __percpu *
>> kernel/rcu/tree_exp.h:807:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_exp.h:807:9: sparse: expected void *ptr
kernel/rcu/tree_exp.h:807:9: sparse: got int [noderef] __percpu *
>> kernel/rcu/tree_exp.h:807:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_exp.h:807:9: sparse: expected void *ptr
kernel/rcu/tree_exp.h:807:9: sparse: got int [noderef] __percpu *
kernel/rcu/tree.c: note: in included file:
>> kernel/rcu/tree_plugin.h:720:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_plugin.h:720:9: sparse: expected void *ptr
kernel/rcu/tree_plugin.h:720:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/rcu/tree_plugin.h:720:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_plugin.h:720:9: sparse: expected void *ptr
kernel/rcu/tree_plugin.h:720:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/rcu/tree_plugin.h:720:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_plugin.h:720:9: sparse: expected void *ptr
kernel/rcu/tree_plugin.h:720:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/rcu/tree_plugin.h:720:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_plugin.h:720:9: sparse: expected void *ptr
kernel/rcu/tree_plugin.h:720:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/rcu/tree_plugin.h:720:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_plugin.h:720:9: sparse: expected void *ptr
kernel/rcu/tree_plugin.h:720:9: sparse: got int [noderef] __percpu *
>> kernel/rcu/tree_plugin.h:720:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_plugin.h:720:9: sparse: expected void *ptr
kernel/rcu/tree_plugin.h:720:9: sparse: got int [noderef] __percpu *
>> kernel/rcu/tree_plugin.h:720:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_plugin.h:720:9: sparse: expected void *ptr
kernel/rcu/tree_plugin.h:720:9: sparse: got int [noderef] __percpu *
>> kernel/rcu/tree_plugin.h:720:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_plugin.h:720:9: sparse: expected void *ptr
kernel/rcu/tree_plugin.h:720:9: sparse: got int [noderef] __percpu *
kernel/rcu/tree_plugin.h:1242:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_plugin.h:1242:9: sparse: expected void *ptr
kernel/rcu/tree_plugin.h:1242:9: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_plugin.h:1242:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_plugin.h:1242:9: sparse: expected void *ptr
kernel/rcu/tree_plugin.h:1242:9: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_plugin.h:1242:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_plugin.h:1242:9: sparse: expected void *ptr
kernel/rcu/tree_plugin.h:1242:9: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_plugin.h:1242:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_plugin.h:1242:9: sparse: expected void *ptr
kernel/rcu/tree_plugin.h:1242:9: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_plugin.h:1242:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_plugin.h:1242:9: sparse: expected void *ptr
kernel/rcu/tree_plugin.h:1242:9: sparse: got int [noderef] __percpu *
kernel/rcu/tree_plugin.h:1242:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_plugin.h:1242:9: sparse: expected void *ptr
kernel/rcu/tree_plugin.h:1242:9: sparse: got int [noderef] __percpu *
kernel/rcu/tree_plugin.h:1242:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_plugin.h:1242:9: sparse: expected void *ptr
kernel/rcu/tree_plugin.h:1242:9: sparse: got int [noderef] __percpu *
kernel/rcu/tree_plugin.h:1242:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_plugin.h:1242:9: sparse: expected void *ptr
kernel/rcu/tree_plugin.h:1242:9: sparse: got int [noderef] __percpu *
kernel/rcu/tree.c: note: in included file:
>> kernel/rcu/tree_nocb.h:377:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:377:9: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:377:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/rcu/tree_nocb.h:377:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:377:9: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:377:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/rcu/tree_nocb.h:377:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:377:9: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:377:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/rcu/tree_nocb.h:377:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:377:9: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:377:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/rcu/tree_nocb.h:377:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:377:9: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:377:9: sparse: got int [noderef] __percpu *
>> kernel/rcu/tree_nocb.h:377:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:377:9: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:377:9: sparse: got int [noderef] __percpu *
>> kernel/rcu/tree_nocb.h:377:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:377:9: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:377:9: sparse: got int [noderef] __percpu *
>> kernel/rcu/tree_nocb.h:377:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:377:9: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:377:9: sparse: got int [noderef] __percpu *
kernel/rcu/tree_nocb.h:154:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:154:9: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:154:9: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_nocb.h:154:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:154:9: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:154:9: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_nocb.h:154:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:154:9: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:154:9: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_nocb.h:154:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:154:9: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:154:9: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_nocb.h:154:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:154:9: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:154:9: sparse: got int [noderef] __percpu *
kernel/rcu/tree_nocb.h:154:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:154:9: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:154:9: sparse: got int [noderef] __percpu *
kernel/rcu/tree_nocb.h:154:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:154:9: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:154:9: sparse: got int [noderef] __percpu *
kernel/rcu/tree_nocb.h:154:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:154:9: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:154:9: sparse: got int [noderef] __percpu *
kernel/rcu/tree_nocb.h:167:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:167:17: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:167:17: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_nocb.h:167:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:167:17: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:167:17: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_nocb.h:167:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:167:17: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:167:17: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_nocb.h:167:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:167:17: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:167:17: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_nocb.h:167:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:167:17: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:167:17: sparse: got int [noderef] __percpu *
kernel/rcu/tree_nocb.h:167:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:167:17: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:167:17: sparse: got int [noderef] __percpu *
kernel/rcu/tree_nocb.h:167:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:167:17: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:167:17: sparse: got int [noderef] __percpu *
kernel/rcu/tree_nocb.h:167:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:167:17: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:167:17: sparse: got int [noderef] __percpu *
kernel/rcu/tree_nocb.h:180:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:180:17: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:180:17: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_nocb.h:180:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:180:17: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:180:17: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_nocb.h:180:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:180:17: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:180:17: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_nocb.h:180:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:180:17: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:180:17: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_nocb.h:180:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:180:17: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:180:17: sparse: got int [noderef] __percpu *
kernel/rcu/tree_nocb.h:180:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:180:17: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:180:17: sparse: got int [noderef] __percpu *
kernel/rcu/tree_nocb.h:180:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:180:17: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:180:17: sparse: got int [noderef] __percpu *
kernel/rcu/tree_nocb.h:180:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:180:17: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:180:17: sparse: got int [noderef] __percpu *
kernel/rcu/tree_nocb.h:190:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:190:9: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:190:9: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_nocb.h:190:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:190:9: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:190:9: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_nocb.h:190:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:190:9: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:190:9: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_nocb.h:190:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:190:9: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:190:9: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_nocb.h:190:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:190:9: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:190:9: sparse: got int [noderef] __percpu *
kernel/rcu/tree_nocb.h:190:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:190:9: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:190:9: sparse: got int [noderef] __percpu *
kernel/rcu/tree_nocb.h:190:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:190:9: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:190:9: sparse: got int [noderef] __percpu *
kernel/rcu/tree_nocb.h:190:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_nocb.h:190:9: sparse: expected void *ptr
kernel/rcu/tree_nocb.h:190:9: sparse: got int [noderef] __percpu *
kernel/rcu/tree.c: note: in included file:
>> kernel/rcu/tree_stall.h:224:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:224:9: sparse: expected void *ptr
kernel/rcu/tree_stall.h:224:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/rcu/tree_stall.h:224:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:224:9: sparse: expected void *ptr
kernel/rcu/tree_stall.h:224:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/rcu/tree_stall.h:224:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:224:9: sparse: expected void *ptr
kernel/rcu/tree_stall.h:224:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/rcu/tree_stall.h:224:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:224:9: sparse: expected void *ptr
kernel/rcu/tree_stall.h:224:9: sparse: got unsigned int [noderef] __percpu *
>> kernel/rcu/tree_stall.h:224:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:224:9: sparse: expected void *ptr
kernel/rcu/tree_stall.h:224:9: sparse: got int [noderef] __percpu *
>> kernel/rcu/tree_stall.h:224:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:224:9: sparse: expected void *ptr
kernel/rcu/tree_stall.h:224:9: sparse: got int [noderef] __percpu *
>> kernel/rcu/tree_stall.h:224:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:224:9: sparse: expected void *ptr
kernel/rcu/tree_stall.h:224:9: sparse: got int [noderef] __percpu *
>> kernel/rcu/tree_stall.h:224:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:224:9: sparse: expected void *ptr
kernel/rcu/tree_stall.h:224:9: sparse: got int [noderef] __percpu *
kernel/rcu/tree_stall.h:700:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:700:9: sparse: expected void *ptr
kernel/rcu/tree_stall.h:700:9: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_stall.h:700:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:700:9: sparse: expected void *ptr
kernel/rcu/tree_stall.h:700:9: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_stall.h:700:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:700:9: sparse: expected void *ptr
kernel/rcu/tree_stall.h:700:9: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_stall.h:700:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:700:9: sparse: expected void *ptr
kernel/rcu/tree_stall.h:700:9: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_stall.h:700:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:700:9: sparse: expected void *ptr
kernel/rcu/tree_stall.h:700:9: sparse: got int [noderef] __percpu *
kernel/rcu/tree_stall.h:700:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:700:9: sparse: expected void *ptr
kernel/rcu/tree_stall.h:700:9: sparse: got int [noderef] __percpu *
kernel/rcu/tree_stall.h:700:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:700:9: sparse: expected void *ptr
kernel/rcu/tree_stall.h:700:9: sparse: got int [noderef] __percpu *
kernel/rcu/tree_stall.h:700:9: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:700:9: sparse: expected void *ptr
kernel/rcu/tree_stall.h:700:9: sparse: got int [noderef] __percpu *
kernel/rcu/tree_stall.h:941:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:941:17: sparse: expected void *ptr
kernel/rcu/tree_stall.h:941:17: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_stall.h:941:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:941:17: sparse: expected void *ptr
kernel/rcu/tree_stall.h:941:17: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_stall.h:941:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:941:17: sparse: expected void *ptr
kernel/rcu/tree_stall.h:941:17: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_stall.h:941:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:941:17: sparse: expected void *ptr
kernel/rcu/tree_stall.h:941:17: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_stall.h:941:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:941:17: sparse: expected void *ptr
kernel/rcu/tree_stall.h:941:17: sparse: got int [noderef] __percpu *
kernel/rcu/tree_stall.h:941:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:941:17: sparse: expected void *ptr
kernel/rcu/tree_stall.h:941:17: sparse: got int [noderef] __percpu *
kernel/rcu/tree_stall.h:941:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:941:17: sparse: expected void *ptr
kernel/rcu/tree_stall.h:941:17: sparse: got int [noderef] __percpu *
kernel/rcu/tree_stall.h:941:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:941:17: sparse: expected void *ptr
kernel/rcu/tree_stall.h:941:17: sparse: got int [noderef] __percpu *
kernel/rcu/tree_stall.h:957:25: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:957:25: sparse: expected void *ptr
kernel/rcu/tree_stall.h:957:25: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_stall.h:957:25: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:957:25: sparse: expected void *ptr
kernel/rcu/tree_stall.h:957:25: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_stall.h:957:25: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:957:25: sparse: expected void *ptr
kernel/rcu/tree_stall.h:957:25: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_stall.h:957:25: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:957:25: sparse: expected void *ptr
kernel/rcu/tree_stall.h:957:25: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_stall.h:957:25: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:957:25: sparse: expected void *ptr
kernel/rcu/tree_stall.h:957:25: sparse: got int [noderef] __percpu *
kernel/rcu/tree_stall.h:957:25: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:957:25: sparse: expected void *ptr
kernel/rcu/tree_stall.h:957:25: sparse: got int [noderef] __percpu *
kernel/rcu/tree_stall.h:957:25: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:957:25: sparse: expected void *ptr
kernel/rcu/tree_stall.h:957:25: sparse: got int [noderef] __percpu *
kernel/rcu/tree_stall.h:957:25: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:957:25: sparse: expected void *ptr
kernel/rcu/tree_stall.h:957:25: sparse: got int [noderef] __percpu *
kernel/rcu/tree_stall.h:958:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:958:17: sparse: expected void *ptr
kernel/rcu/tree_stall.h:958:17: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_stall.h:958:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:958:17: sparse: expected void *ptr
kernel/rcu/tree_stall.h:958:17: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_stall.h:958:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/rcu/tree_stall.h:958:17: sparse: expected void *ptr
kernel/rcu/tree_stall.h:958:17: sparse: got unsigned int [noderef] __percpu *
kernel/rcu/tree_stall.h:958:17: sparse: sparse: too many warnings
--
>> kernel/time/timer.c:1432:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/time/timer.c:1432:17: sparse: expected void *ptr
kernel/time/timer.c:1432:17: sparse: got unsigned int [noderef] __percpu *
>> kernel/time/timer.c:1432:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/time/timer.c:1432:17: sparse: expected void *ptr
kernel/time/timer.c:1432:17: sparse: got unsigned int [noderef] __percpu *
>> kernel/time/timer.c:1432:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/time/timer.c:1432:17: sparse: expected void *ptr
kernel/time/timer.c:1432:17: sparse: got unsigned int [noderef] __percpu *
>> kernel/time/timer.c:1432:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got unsigned int [noderef] __percpu * @@
kernel/time/timer.c:1432:17: sparse: expected void *ptr
kernel/time/timer.c:1432:17: sparse: got unsigned int [noderef] __percpu *
>> kernel/time/timer.c:1432:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/time/timer.c:1432:17: sparse: expected void *ptr
kernel/time/timer.c:1432:17: sparse: got int [noderef] __percpu *
>> kernel/time/timer.c:1432:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/time/timer.c:1432:17: sparse: expected void *ptr
kernel/time/timer.c:1432:17: sparse: got int [noderef] __percpu *
>> kernel/time/timer.c:1432:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/time/timer.c:1432:17: sparse: expected void *ptr
kernel/time/timer.c:1432:17: sparse: got int [noderef] __percpu *
>> kernel/time/timer.c:1432:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *ptr @@ got int [noderef] __percpu * @@
kernel/time/timer.c:1432:17: sparse: expected void *ptr
kernel/time/timer.c:1432:17: sparse: got int [noderef] __percpu *

vim +571 kernel/smp.c

8d056c48e48624 Srivatsa S. Bhat 2014-06-23 549
8d056c48e48624 Srivatsa S. Bhat 2014-06-23 550 /**
16bf5a5e1ec564 Thomas Gleixner 2022-04-13 551 * __flush_smp_call_function_queue - Flush pending smp-call-function callbacks
8d056c48e48624 Srivatsa S. Bhat 2014-06-23 552 *
8d056c48e48624 Srivatsa S. Bhat 2014-06-23 553 * @warn_cpu_offline: If set to 'true', warn if callbacks were queued on an
8d056c48e48624 Srivatsa S. Bhat 2014-06-23 554 * offline CPU. Skip this check if set to 'false'.
8d056c48e48624 Srivatsa S. Bhat 2014-06-23 555 *
8d056c48e48624 Srivatsa S. Bhat 2014-06-23 556 * Flush any pending smp-call-function callbacks queued on this CPU. This is
8d056c48e48624 Srivatsa S. Bhat 2014-06-23 557 * invoked by the generic IPI handler, as well as by a CPU about to go offline,
8d056c48e48624 Srivatsa S. Bhat 2014-06-23 558 * to ensure that all pending IPI callbacks are run before it goes completely
8d056c48e48624 Srivatsa S. Bhat 2014-06-23 559 * offline.
8d056c48e48624 Srivatsa S. Bhat 2014-06-23 560 *
8d056c48e48624 Srivatsa S. Bhat 2014-06-23 561 * Loop through the call_single_queue and run all the queued callbacks.
8d056c48e48624 Srivatsa S. Bhat 2014-06-23 562 * Must be called with interrupts disabled.
8d056c48e48624 Srivatsa S. Bhat 2014-06-23 563 */
16bf5a5e1ec564 Thomas Gleixner 2022-04-13 564 static void __flush_smp_call_function_queue(bool warn_cpu_offline)
8d056c48e48624 Srivatsa S. Bhat 2014-06-23 565 {
966a967116e699 Ying Huang 2017-08-08 566 call_single_data_t *csd, *csd_next;
52103be07d8b08 Peter Zijlstra 2020-05-26 567 struct llist_node *entry, *prev;
52103be07d8b08 Peter Zijlstra 2020-05-26 568 struct llist_head *head;
a219ccf4637396 Srivatsa S. Bhat 2014-06-06 569 static bool warned;
a219ccf4637396 Srivatsa S. Bhat 2014-06-06 570
83efcbd028ad3a Frederic Weisbecker 2017-11-06 @571 lockdep_assert_irqs_disabled();
8d056c48e48624 Srivatsa S. Bhat 2014-06-23 572
bb964a92ce70ac Christoph Lameter 2014-08-17 573 head = this_cpu_ptr(&call_single_queue);
a5aabace5fb8ab Juergen Gross 2021-03-01 574 cfd_seq_store(this_cpu_ptr(&cfd_seq_local)->handle, CFD_SEQ_NOCPU,
a5aabace5fb8ab Juergen Gross 2021-03-01 575 smp_processor_id(), CFD_SEQ_HANDLE);
8d056c48e48624 Srivatsa S. Bhat 2014-06-23 576 entry = llist_del_all(head);
a5aabace5fb8ab Juergen Gross 2021-03-01 577 cfd_seq_store(this_cpu_ptr(&cfd_seq_local)->dequeue,
a5aabace5fb8ab Juergen Gross 2021-03-01 578 /* Special meaning of source cpu: 0 == queue empty */
a5aabace5fb8ab Juergen Gross 2021-03-01 579 entry ? CFD_SEQ_NOCPU : 0,
a5aabace5fb8ab Juergen Gross 2021-03-01 580 smp_processor_id(), CFD_SEQ_DEQUEUE);
a219ccf4637396 Srivatsa S. Bhat 2014-06-06 581 entry = llist_reverse_order(entry);
3d4422332711ef Jens Axboe 2008-06-26 582
8d056c48e48624 Srivatsa S. Bhat 2014-06-23 583 /* There shouldn't be any pending callbacks on an offline CPU. */
8d056c48e48624 Srivatsa S. Bhat 2014-06-23 584 if (unlikely(warn_cpu_offline && !cpu_online(smp_processor_id()) &&
9e949a3886356f Nadav Amit 2022-03-19 585 !warned && entry != NULL)) {
a219ccf4637396 Srivatsa S. Bhat 2014-06-06 586 warned = true;
a219ccf4637396 Srivatsa S. Bhat 2014-06-06 587 WARN(1, "IPI on offline CPU %d\n", smp_processor_id());
269c861baa2fe7 Suresh Siddha 2009-08-19 588
a219ccf4637396 Srivatsa S. Bhat 2014-06-06 589 /*
a219ccf4637396 Srivatsa S. Bhat 2014-06-06 590 * We don't have to use the _safe() variant here
a219ccf4637396 Srivatsa S. Bhat 2014-06-06 591 * because we are not invoking the IPI handlers yet.
a219ccf4637396 Srivatsa S. Bhat 2014-06-06 592 */
545b8c8df41f9e Peter Zijlstra 2020-06-15 593 llist_for_each_entry(csd, entry, node.llist) {
4b44a21dd640b6 Peter Zijlstra 2020-05-26 594 switch (CSD_TYPE(csd)) {
4b44a21dd640b6 Peter Zijlstra 2020-05-26 595 case CSD_TYPE_ASYNC:
4b44a21dd640b6 Peter Zijlstra 2020-05-26 596 case CSD_TYPE_SYNC:
4b44a21dd640b6 Peter Zijlstra 2020-05-26 597 case CSD_TYPE_IRQ_WORK:
a219ccf4637396 Srivatsa S. Bhat 2014-06-06 598 pr_warn("IPI callback %pS sent to offline CPU\n",
a219ccf4637396 Srivatsa S. Bhat 2014-06-06 599 csd->func);
4b44a21dd640b6 Peter Zijlstra 2020-05-26 600 break;
4b44a21dd640b6 Peter Zijlstra 2020-05-26 601
a148866489fbe2 Peter Zijlstra 2020-05-26 602 case CSD_TYPE_TTWU:
a148866489fbe2 Peter Zijlstra 2020-05-26 603 pr_warn("IPI task-wakeup sent to offline CPU\n");
a148866489fbe2 Peter Zijlstra 2020-05-26 604 break;
a148866489fbe2 Peter Zijlstra 2020-05-26 605
4b44a21dd640b6 Peter Zijlstra 2020-05-26 606 default:
4b44a21dd640b6 Peter Zijlstra 2020-05-26 607 pr_warn("IPI callback, unknown type %d, sent to offline CPU\n",
4b44a21dd640b6 Peter Zijlstra 2020-05-26 608 CSD_TYPE(csd));
4b44a21dd640b6 Peter Zijlstra 2020-05-26 609 break;
4b44a21dd640b6 Peter Zijlstra 2020-05-26 610 }
4b44a21dd640b6 Peter Zijlstra 2020-05-26 611 }
a219ccf4637396 Srivatsa S. Bhat 2014-06-06 612 }
3d4422332711ef Jens Axboe 2008-06-26 613
52103be07d8b08 Peter Zijlstra 2020-05-26 614 /*
52103be07d8b08 Peter Zijlstra 2020-05-26 615 * First; run all SYNC callbacks, people are waiting for us.
52103be07d8b08 Peter Zijlstra 2020-05-26 616 */
52103be07d8b08 Peter Zijlstra 2020-05-26 617 prev = NULL;
545b8c8df41f9e Peter Zijlstra 2020-06-15 618 llist_for_each_entry_safe(csd, csd_next, entry, node.llist) {
4b44a21dd640b6 Peter Zijlstra 2020-05-26 619 /* Do we wait until *after* callback? */
4b44a21dd640b6 Peter Zijlstra 2020-05-26 620 if (CSD_TYPE(csd) == CSD_TYPE_SYNC) {
8053871d0f7f67 Linus Torvalds 2015-02-11 621 smp_call_func_t func = csd->func;
8053871d0f7f67 Linus Torvalds 2015-02-11 622 void *info = csd->info;
8053871d0f7f67 Linus Torvalds 2015-02-11 623
52103be07d8b08 Peter Zijlstra 2020-05-26 624 if (prev) {
545b8c8df41f9e Peter Zijlstra 2020-06-15 625 prev->next = &csd_next->node.llist;
52103be07d8b08 Peter Zijlstra 2020-05-26 626 } else {
545b8c8df41f9e Peter Zijlstra 2020-06-15 627 entry = &csd_next->node.llist;
52103be07d8b08 Peter Zijlstra 2020-05-26 628 }
4b44a21dd640b6 Peter Zijlstra 2020-05-26 629
35feb60474bf4f Paul E. McKenney 2020-06-30 630 csd_lock_record(csd);
8053871d0f7f67 Linus Torvalds 2015-02-11 631 func(info);
8053871d0f7f67 Linus Torvalds 2015-02-11 632 csd_unlock(csd);
35feb60474bf4f Paul E. McKenney 2020-06-30 633 csd_lock_record(NULL);
8053871d0f7f67 Linus Torvalds 2015-02-11 634 } else {
545b8c8df41f9e Peter Zijlstra 2020-06-15 635 prev = &csd->node.llist;
52103be07d8b08 Peter Zijlstra 2020-05-26 636 }
52103be07d8b08 Peter Zijlstra 2020-05-26 637 }
52103be07d8b08 Peter Zijlstra 2020-05-26 638
a5aabace5fb8ab Juergen Gross 2021-03-01 639 if (!entry) {
a5aabace5fb8ab Juergen Gross 2021-03-01 640 cfd_seq_store(this_cpu_ptr(&cfd_seq_local)->hdlend,
a5aabace5fb8ab Juergen Gross 2021-03-01 641 0, smp_processor_id(),
a5aabace5fb8ab Juergen Gross 2021-03-01 642 CFD_SEQ_HDLEND);
a148866489fbe2 Peter Zijlstra 2020-05-26 643 return;
a5aabace5fb8ab Juergen Gross 2021-03-01 644 }
a148866489fbe2 Peter Zijlstra 2020-05-26 645
52103be07d8b08 Peter Zijlstra 2020-05-26 646 /*
52103be07d8b08 Peter Zijlstra 2020-05-26 647 * Second; run all !SYNC callbacks.
52103be07d8b08 Peter Zijlstra 2020-05-26 648 */
a148866489fbe2 Peter Zijlstra 2020-05-26 649 prev = NULL;
545b8c8df41f9e Peter Zijlstra 2020-06-15 650 llist_for_each_entry_safe(csd, csd_next, entry, node.llist) {
4b44a21dd640b6 Peter Zijlstra 2020-05-26 651 int type = CSD_TYPE(csd);
4b44a21dd640b6 Peter Zijlstra 2020-05-26 652
a148866489fbe2 Peter Zijlstra 2020-05-26 653 if (type != CSD_TYPE_TTWU) {
a148866489fbe2 Peter Zijlstra 2020-05-26 654 if (prev) {
545b8c8df41f9e Peter Zijlstra 2020-06-15 655 prev->next = &csd_next->node.llist;
a148866489fbe2 Peter Zijlstra 2020-05-26 656 } else {
545b8c8df41f9e Peter Zijlstra 2020-06-15 657 entry = &csd_next->node.llist;
a148866489fbe2 Peter Zijlstra 2020-05-26 658 }
a148866489fbe2 Peter Zijlstra 2020-05-26 659
4b44a21dd640b6 Peter Zijlstra 2020-05-26 660 if (type == CSD_TYPE_ASYNC) {
52103be07d8b08 Peter Zijlstra 2020-05-26 661 smp_call_func_t func = csd->func;
52103be07d8b08 Peter Zijlstra 2020-05-26 662 void *info = csd->info;
52103be07d8b08 Peter Zijlstra 2020-05-26 663
35feb60474bf4f Paul E. McKenney 2020-06-30 664 csd_lock_record(csd);
e1d12f327037a5 Andrew Morton 2013-04-30 665 csd_unlock(csd);
8053871d0f7f67 Linus Torvalds 2015-02-11 666 func(info);
35feb60474bf4f Paul E. McKenney 2020-06-30 667 csd_lock_record(NULL);
4b44a21dd640b6 Peter Zijlstra 2020-05-26 668 } else if (type == CSD_TYPE_IRQ_WORK) {
4b44a21dd640b6 Peter Zijlstra 2020-05-26 669 irq_work_single(csd);
4b44a21dd640b6 Peter Zijlstra 2020-05-26 670 }
a148866489fbe2 Peter Zijlstra 2020-05-26 671
a148866489fbe2 Peter Zijlstra 2020-05-26 672 } else {
545b8c8df41f9e Peter Zijlstra 2020-06-15 673 prev = &csd->node.llist;
8053871d0f7f67 Linus Torvalds 2015-02-11 674 }
3d4422332711ef Jens Axboe 2008-06-26 675 }
478850160636c4 Frederic Weisbecker 2014-05-08 676
478850160636c4 Frederic Weisbecker 2014-05-08 677 /*
a148866489fbe2 Peter Zijlstra 2020-05-26 678 * Third; only CSD_TYPE_TTWU is left, issue those.
478850160636c4 Frederic Weisbecker 2014-05-08 679 */
a148866489fbe2 Peter Zijlstra 2020-05-26 680 if (entry)
a148866489fbe2 Peter Zijlstra 2020-05-26 681 sched_ttwu_pending(entry);
a5aabace5fb8ab Juergen Gross 2021-03-01 682
a5aabace5fb8ab Juergen Gross 2021-03-01 683 cfd_seq_store(this_cpu_ptr(&cfd_seq_local)->hdlend, CFD_SEQ_NOCPU,
a5aabace5fb8ab Juergen Gross 2021-03-01 684 smp_processor_id(), CFD_SEQ_HDLEND);
a148866489fbe2 Peter Zijlstra 2020-05-26 685 }
a148866489fbe2 Peter Zijlstra 2020-05-26 686

--
0-DAY CI Kernel Test Service
https://01.org/lkp