All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] LoongArch: Add unwinder support
@ 2022-08-01 12:17 Qing Zhang
  2022-08-01 12:17 ` [PATCH 1/4] LoongArch: Add guess " Qing Zhang
                   ` (4 more replies)
  0 siblings, 5 replies; 21+ messages in thread
From: Qing Zhang @ 2022-08-01 12:17 UTC (permalink / raw)
  To: Huacai Chen
  Cc: WANG Xuerui, loongarch, linux-kernel, Jiaxun Yang, hejinyang, zhangqing

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


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

* [PATCH 1/4] LoongArch: Add guess unwinder support
  2022-08-01 12:17 [PATCH 0/4] LoongArch: Add unwinder support Qing Zhang
@ 2022-08-01 12:17 ` Qing Zhang
  2022-08-01 15:28   ` Huacai Chen
  2022-08-01 12:17 ` [PATCH 2/4] LoongArch: Add prologue " Qing Zhang
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 21+ messages in thread
From: Qing Zhang @ 2022-08-01 12:17 UTC (permalink / raw)
  To: Huacai Chen
  Cc: WANG Xuerui, loongarch, linux-kernel, Jiaxun Yang, hejinyang, zhangqing

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 <zhangqing@loongson.cn>
---
 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


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

* [PATCH 2/4] LoongArch: Add prologue unwinder support
  2022-08-01 12:17 [PATCH 0/4] LoongArch: Add unwinder support Qing Zhang
  2022-08-01 12:17 ` [PATCH 1/4] LoongArch: Add guess " Qing Zhang
@ 2022-08-01 12:17 ` Qing Zhang
  2022-08-01 15:26   ` Huacai Chen
  2022-08-01 12:17 ` [PATCH 3/4] LoongArch: Add stacktrace support Qing Zhang
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 21+ messages in thread
From: Qing Zhang @ 2022-08-01 12:17 UTC (permalink / raw)
  To: Huacai Chen
  Cc: WANG Xuerui, loongarch, linux-kernel, Jiaxun Yang, hejinyang, zhangqing

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 <zhangqing@loongson.cn>
---
 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


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

* [PATCH 3/4] LoongArch: Add stacktrace support
  2022-08-01 12:17 [PATCH 0/4] LoongArch: Add unwinder support Qing Zhang
  2022-08-01 12:17 ` [PATCH 1/4] LoongArch: Add guess " Qing Zhang
  2022-08-01 12:17 ` [PATCH 2/4] LoongArch: Add prologue " Qing Zhang
@ 2022-08-01 12:17 ` Qing Zhang
  2022-08-01 15:30   ` Huacai Chen
                     ` (2 more replies)
  2022-08-01 12:17 ` [PATCH 4/4] LoongArch: Add USER_STACKTRACE support Qing Zhang
  2022-08-01 15:34 ` [PATCH 0/4] LoongArch: Add unwinder support Huacai Chen
  4 siblings, 3 replies; 21+ messages in thread
From: Qing Zhang @ 2022-08-01 12:17 UTC (permalink / raw)
  To: Huacai Chen
  Cc: WANG Xuerui, loongarch, linux-kernel, Jiaxun Yang, hejinyang, zhangqing

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 <zhangqing@loongson.cn>
---
 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


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

* [PATCH 4/4] LoongArch: Add USER_STACKTRACE support
  2022-08-01 12:17 [PATCH 0/4] LoongArch: Add unwinder support Qing Zhang
                   ` (2 preceding siblings ...)
  2022-08-01 12:17 ` [PATCH 3/4] LoongArch: Add stacktrace support Qing Zhang
@ 2022-08-01 12:17 ` Qing Zhang
  2022-08-01 15:31   ` Huacai Chen
  2022-08-01 15:34 ` [PATCH 0/4] LoongArch: Add unwinder support Huacai Chen
  4 siblings, 1 reply; 21+ messages in thread
From: Qing Zhang @ 2022-08-01 12:17 UTC (permalink / raw)
  To: Huacai Chen
  Cc: WANG Xuerui, loongarch, linux-kernel, Jiaxun Yang, hejinyang, zhangqing

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 <zhangqing@loongson.cn>
---
 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


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

* Re: [PATCH 2/4] LoongArch: Add prologue unwinder support
  2022-08-01 12:17 ` [PATCH 2/4] LoongArch: Add prologue " Qing Zhang
@ 2022-08-01 15:26   ` Huacai Chen
  2022-08-02  1:30     ` Youling Tang
  0 siblings, 1 reply; 21+ messages in thread
From: Huacai Chen @ 2022-08-01 15:26 UTC (permalink / raw)
  To: Qing Zhang; +Cc: WANG Xuerui, loongarch, LKML, Jiaxun Yang, Jinyang He

Hi, Qing,

On Mon, Aug 1, 2022 at 8:17 PM Qing Zhang <zhangqing@loongson.cn> 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 <zhangqing@loongson.cn>
> ---
>  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
>

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

* Re: [PATCH 1/4] LoongArch: Add guess unwinder support
  2022-08-01 12:17 ` [PATCH 1/4] LoongArch: Add guess " Qing Zhang
@ 2022-08-01 15:28   ` Huacai Chen
  0 siblings, 0 replies; 21+ messages in thread
From: Huacai Chen @ 2022-08-01 15:28 UTC (permalink / raw)
  To: Qing Zhang; +Cc: WANG Xuerui, loongarch, LKML, Jiaxun Yang, Jinyang He

Hi, Qing,

On Mon, Aug 1, 2022 at 8:17 PM Qing Zhang <zhangqing@loongson.cn> 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 <zhangqing@loongson.cn>
> ---
>  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
>

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

* Re: [PATCH 3/4] LoongArch: Add stacktrace support
  2022-08-01 12:17 ` [PATCH 3/4] LoongArch: Add stacktrace support Qing Zhang
@ 2022-08-01 15:30   ` Huacai Chen
  2022-08-02  1:19     ` zhangqing
  2022-08-13 22:29   ` kernel test robot
  2022-08-14  5:31   ` kernel test robot
  2 siblings, 1 reply; 21+ messages in thread
From: Huacai Chen @ 2022-08-01 15:30 UTC (permalink / raw)
  To: Qing Zhang; +Cc: WANG Xuerui, loongarch, LKML, Jiaxun Yang, Jinyang He

Hi, Qing,

On Mon, Aug 1, 2022 at 8:17 PM Qing Zhang <zhangqing@loongson.cn> 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 <zhangqing@loongson.cn>
> ---
>  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
>

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

* Re: [PATCH 4/4] LoongArch: Add USER_STACKTRACE support
  2022-08-01 12:17 ` [PATCH 4/4] LoongArch: Add USER_STACKTRACE support Qing Zhang
@ 2022-08-01 15:31   ` Huacai Chen
  0 siblings, 0 replies; 21+ messages in thread
From: Huacai Chen @ 2022-08-01 15:31 UTC (permalink / raw)
  To: Qing Zhang; +Cc: WANG Xuerui, loongarch, LKML, Jiaxun Yang, Jinyang He

Hi, Qing,

On Mon, Aug 1, 2022 at 8:17 PM Qing Zhang <zhangqing@loongson.cn> 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 <zhangqing@loongson.cn>
> ---
>  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
>
>

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

* Re: [PATCH 0/4] LoongArch: Add unwinder support
  2022-08-01 12:17 [PATCH 0/4] LoongArch: Add unwinder support Qing Zhang
                   ` (3 preceding siblings ...)
  2022-08-01 12:17 ` [PATCH 4/4] LoongArch: Add USER_STACKTRACE support Qing Zhang
@ 2022-08-01 15:34 ` Huacai Chen
  2022-08-02  1:15   ` Xi Ruoyao
  2022-08-02  1:35   ` zhangqing
  4 siblings, 2 replies; 21+ messages in thread
From: Huacai Chen @ 2022-08-01 15:34 UTC (permalink / raw)
  To: Qing Zhang; +Cc: WANG Xuerui, loongarch, LKML, Jiaxun Yang, Jinyang He

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 <zhangqing@loongson.cn> 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
>
>

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

* Re: [PATCH 0/4] LoongArch: Add unwinder support
  2022-08-01 15:34 ` [PATCH 0/4] LoongArch: Add unwinder support Huacai Chen
@ 2022-08-02  1:15   ` Xi Ruoyao
  2022-08-02  1:35   ` zhangqing
  1 sibling, 0 replies; 21+ messages in thread
From: Xi Ruoyao @ 2022-08-02  1:15 UTC (permalink / raw)
  To: Huacai Chen, Qing Zhang
  Cc: WANG Xuerui, loongarch, LKML, Jiaxun Yang, Jinyang He

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:
"linux-kernel@vger.kernel.org should be used by default for all
patches".

-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

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

* Re: [PATCH 3/4] LoongArch: Add stacktrace support
  2022-08-01 15:30   ` Huacai Chen
@ 2022-08-02  1:19     ` zhangqing
  2022-08-02  1:30       ` Huacai Chen
  0 siblings, 1 reply; 21+ messages in thread
From: zhangqing @ 2022-08-02  1:19 UTC (permalink / raw)
  To: Huacai Chen; +Cc: WANG Xuerui, loongarch, LKML, Jiaxun Yang, Jinyang He



On 2022/8/1 下午11:30, Huacai Chen wrote:
> Hi, Qing,
> 
> On Mon, Aug 1, 2022 at 8:17 PM Qing Zhang <zhangqing@loongson.cn> 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 <zhangqing@loongson.cn>
>> ---
>>   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



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

* Re: [PATCH 2/4] LoongArch: Add prologue unwinder support
  2022-08-01 15:26   ` Huacai Chen
@ 2022-08-02  1:30     ` Youling Tang
  2022-08-02  1:34       ` Huacai Chen
  0 siblings, 1 reply; 21+ messages in thread
From: Youling Tang @ 2022-08-02  1:30 UTC (permalink / raw)
  To: Huacai Chen, Qing Zhang
  Cc: WANG Xuerui, loongarch, LKML, Jiaxun Yang, Jinyang He



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


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

* Re: [PATCH 3/4] LoongArch: Add stacktrace support
  2022-08-02  1:19     ` zhangqing
@ 2022-08-02  1:30       ` Huacai Chen
  2022-08-02  2:01         ` Qing Zhang
  0 siblings, 1 reply; 21+ messages in thread
From: Huacai Chen @ 2022-08-02  1:30 UTC (permalink / raw)
  To: zhangqing; +Cc: WANG Xuerui, loongarch, LKML, Jiaxun Yang, Jinyang He

Hi, Qing,

On Tue, Aug 2, 2022 at 9:20 AM zhangqing <zhangqing@loongson.cn> wrote:
>
>
>
> On 2022/8/1 下午11:30, Huacai Chen wrote:
> > Hi, Qing,
> >
> > On Mon, Aug 1, 2022 at 8:17 PM Qing Zhang <zhangqing@loongson.cn> 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 <zhangqing@loongson.cn>
> >> ---
> >>   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
>
>
>

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

* Re: [PATCH 2/4] LoongArch: Add prologue unwinder support
  2022-08-02  1:30     ` Youling Tang
@ 2022-08-02  1:34       ` Huacai Chen
  2022-08-02  1:39         ` Xi Ruoyao
  0 siblings, 1 reply; 21+ messages in thread
From: Huacai Chen @ 2022-08-02  1:34 UTC (permalink / raw)
  To: Youling Tang
  Cc: Qing Zhang, WANG Xuerui, loongarch, LKML, Jiaxun Yang, Jinyang He

Hi, Youling,

On Tue, Aug 2, 2022 at 9:30 AM Youling Tang <tangyouling@loongson.cn> 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
>
>

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

* Re: [PATCH 0/4] LoongArch: Add unwinder support
  2022-08-01 15:34 ` [PATCH 0/4] LoongArch: Add unwinder support Huacai Chen
  2022-08-02  1:15   ` Xi Ruoyao
@ 2022-08-02  1:35   ` zhangqing
  1 sibling, 0 replies; 21+ messages in thread
From: zhangqing @ 2022-08-02  1:35 UTC (permalink / raw)
  To: Huacai Chen; +Cc: WANG Xuerui, loongarch, LKML, Jiaxun Yang, Jinyang He



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


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

* Re: [PATCH 2/4] LoongArch: Add prologue unwinder support
  2022-08-02  1:34       ` Huacai Chen
@ 2022-08-02  1:39         ` Xi Ruoyao
  2022-08-02  1:53           ` Huacai Chen
  0 siblings, 1 reply; 21+ messages in thread
From: Xi Ruoyao @ 2022-08-02  1:39 UTC (permalink / raw)
  To: Huacai Chen, Youling Tang
  Cc: Qing Zhang, WANG Xuerui, loongarch, LKML, Jiaxun Yang, Jinyang He

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 <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

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

* Re: [PATCH 2/4] LoongArch: Add prologue unwinder support
  2022-08-02  1:39         ` Xi Ruoyao
@ 2022-08-02  1:53           ` Huacai Chen
  0 siblings, 0 replies; 21+ messages in thread
From: Huacai Chen @ 2022-08-02  1:53 UTC (permalink / raw)
  To: Xi Ruoyao
  Cc: Youling Tang, Qing Zhang, WANG Xuerui, loongarch, LKML,
	Jiaxun Yang, Jinyang He

Hi, Ruoyao,

On Tue, Aug 2, 2022 at 9:39 AM Xi Ruoyao <xry111@xry111.site> 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 <xry111@xry111.site>
> School of Aerospace Science and Technology, Xidian University

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

* Re: [PATCH 3/4] LoongArch: Add stacktrace support
  2022-08-02  1:30       ` Huacai Chen
@ 2022-08-02  2:01         ` Qing Zhang
  0 siblings, 0 replies; 21+ messages in thread
From: Qing Zhang @ 2022-08-02  2:01 UTC (permalink / raw)
  To: Huacai Chen; +Cc: WANG Xuerui, loongarch, LKML, Jiaxun Yang, Jinyang He



On 2022/8/2 上午9:30, Huacai Chen wrote:
> Hi, Qing,
> 
> On Tue, Aug 2, 2022 at 9:20 AM zhangqing <zhangqing@loongson.cn> wrote:
>>
>>
>>
>> On 2022/8/1 下午11:30, Huacai Chen wrote:
>>> Hi, Qing,
>>>
>>> On Mon, Aug 1, 2022 at 8:17 PM Qing Zhang <zhangqing@loongson.cn> 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 <zhangqing@loongson.cn>
>>>> ---
>>>>    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
>>
>>
>>


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

* Re: [PATCH 3/4] LoongArch: Add stacktrace support
  2022-08-01 12:17 ` [PATCH 3/4] LoongArch: Add stacktrace support Qing Zhang
  2022-08-01 15:30   ` Huacai Chen
@ 2022-08-13 22:29   ` kernel test robot
  2022-08-14  5:31   ` kernel test robot
  2 siblings, 0 replies; 21+ messages in thread
From: kernel test robot @ 2022-08-13 22:29 UTC (permalink / raw)
  To: Qing Zhang, Huacai Chen
  Cc: kbuild-all, WANG Xuerui, loongarch, linux-kernel, Jiaxun Yang,
	hejinyang, zhangqing

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/202208140621.UKarxp6n-lkp@intel.com/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 <lkp@intel.com>

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

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

* Re: [PATCH 3/4] LoongArch: Add stacktrace support
  2022-08-01 12:17 ` [PATCH 3/4] LoongArch: Add stacktrace support Qing Zhang
  2022-08-01 15:30   ` Huacai Chen
  2022-08-13 22:29   ` kernel test robot
@ 2022-08-14  5:31   ` kernel test robot
  2 siblings, 0 replies; 21+ messages in thread
From: kernel test robot @ 2022-08-14  5:31 UTC (permalink / raw)
  To: Qing Zhang, Huacai Chen
  Cc: kbuild-all, WANG Xuerui, loongarch, linux-kernel, Jiaxun Yang,
	hejinyang, zhangqing

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/202208141339.jCYoEcIL-lkp@intel.com/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 <lkp@intel.com>

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

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

end of thread, other threads:[~2022-08-14  5:31 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-01 12:17 [PATCH 0/4] LoongArch: Add unwinder support Qing Zhang
2022-08-01 12:17 ` [PATCH 1/4] LoongArch: Add guess " Qing Zhang
2022-08-01 15:28   ` Huacai Chen
2022-08-01 12:17 ` [PATCH 2/4] LoongArch: Add prologue " Qing Zhang
2022-08-01 15:26   ` Huacai Chen
2022-08-02  1:30     ` Youling Tang
2022-08-02  1:34       ` Huacai Chen
2022-08-02  1:39         ` Xi Ruoyao
2022-08-02  1:53           ` Huacai Chen
2022-08-01 12:17 ` [PATCH 3/4] LoongArch: Add stacktrace support Qing Zhang
2022-08-01 15:30   ` Huacai Chen
2022-08-02  1:19     ` zhangqing
2022-08-02  1:30       ` Huacai Chen
2022-08-02  2:01         ` Qing Zhang
2022-08-13 22:29   ` kernel test robot
2022-08-14  5:31   ` kernel test robot
2022-08-01 12:17 ` [PATCH 4/4] LoongArch: Add USER_STACKTRACE support Qing Zhang
2022-08-01 15:31   ` Huacai Chen
2022-08-01 15:34 ` [PATCH 0/4] LoongArch: Add unwinder support Huacai Chen
2022-08-02  1:15   ` Xi Ruoyao
2022-08-02  1:35   ` zhangqing

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.