mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2 0/3] riscv: Support trap-based WARN() and fix bug in do_trap_break
@ 2019-03-05  3:23 Vincent Chen
  2019-03-05  3:23 ` [PATCH v2 1/3] riscv: support trap-based WARN() Vincent Chen
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Vincent Chen @ 2019-03-05  3:23 UTC (permalink / raw)
  To: palmer, aou, ebiederm, jimw, linux-riscv, linux-kernel
  Cc: deanbo422, vincentc

Changes in v2:
  - Remove unnecessary non-functional diff
  - Rearrange the order of the patches
  - Edit the commit description

The trap-based WARN() will help developers to analyze the cause of WARN()
because if the debugger is connected, the control flow will be transferred
to debugging environment.

BUG() is currently not working properly. When the C extension is supported,
the assembler translates the "ebreak" to "c.ebreak" opcode. Hence the trap
is possibly triggered by "c.ebreak" instead of expected the "ebreak". This
will cause the check mechanism in is_valid_bugaddr(bugaddr) to think that
the trap triggered by "c.ebreak" occurs in an invalidate bug address. This
patch set will add "c.ebreak" into the check mechanism. In addition, BUG()
is also unable to work in the kernel module due to an inappropriate
condition in is_valid_bugaddr().

Vincent Chen (3):
  riscv: support trap-based WARN()
  riscv: Add the support for c.ebreak check in is_valid_bugaddr()
  riscv: Support BUG() in kernel module

 arch/riscv/include/asm/bug.h |   34 ++++++++++++++++++++++++----------
 arch/riscv/kernel/traps.c    |   22 ++++++++++++++++++----
 2 files changed, 42 insertions(+), 14 deletions(-)


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

* [PATCH v2 1/3] riscv: support trap-based WARN()
  2019-03-05  3:23 [PATCH v2 0/3] riscv: Support trap-based WARN() and fix bug in do_trap_break Vincent Chen
@ 2019-03-05  3:23 ` Vincent Chen
  2019-03-05  3:23 ` [PATCH v2 2/3] riscv: Add the support for c.ebreak check in is_valid_bugaddr() Vincent Chen
  2019-03-05  3:23 ` [PATCH v2 3/3] riscv: Support BUG() in kernel module Vincent Chen
  2 siblings, 0 replies; 4+ messages in thread
From: Vincent Chen @ 2019-03-05  3:23 UTC (permalink / raw)
  To: palmer, aou, ebiederm, jimw, linux-riscv, linux-kernel
  Cc: deanbo422, vincentc

The WARN() related function will trigger a debug exception. This can help
developers to analyze the cause of WARN() because if the debugger is
connected, the control flow will be transferred to debugging
environment.

Signed-off-by: Vincent Chen <vincentc@andestech.com>
---
 arch/riscv/include/asm/bug.h |   28 ++++++++++++++++++----------
 1 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/arch/riscv/include/asm/bug.h b/arch/riscv/include/asm/bug.h
index bfc7f09..4d906d8 100644
--- a/arch/riscv/include/asm/bug.h
+++ b/arch/riscv/include/asm/bug.h
@@ -38,38 +38,46 @@
 #define __BUG_ENTRY			\
 	__BUG_ENTRY_ADDR "\n\t"		\
 	__BUG_ENTRY_FILE "\n\t"		\
-	RISCV_SHORT " %1"
+	RISCV_SHORT " %1\n\t"		\
+	RISCV_SHORT " %2"
 #else
 #define __BUG_ENTRY			\
-	__BUG_ENTRY_ADDR
+	__BUG_ENTRY_ADDR "\n\t"		\
+	RISCV_SHORT " %2"
 #endif
 
-#define BUG()							\
+#define __BUG_FLAGS(flags)					\
 do {								\
 	__asm__ __volatile__ (					\
 		"1:\n\t"					\
 			"ebreak\n"				\
-			".pushsection __bug_table,\"a\"\n\t"	\
+			".pushsection __bug_table,\"aw\"\n\t"	\
 		"2:\n\t"					\
 			__BUG_ENTRY "\n\t"			\
-			".org 2b + %2\n\t"			\
+			".org 2b + %3\n\t"                      \
 			".popsection"				\
 		:						\
 		: "i" (__FILE__), "i" (__LINE__),		\
-		  "i" (sizeof(struct bug_entry)));		\
-	unreachable();						\
+		  "i" (flags),					\
+		  "i" (sizeof(struct bug_entry)));              \
 } while (0)
+
 #endif /* !__ASSEMBLY__ */
 #else /* CONFIG_GENERIC_BUG */
 #ifndef __ASSEMBLY__
-#define BUG()							\
-do {								\
+#define __BUG_FLAGS(flags) do {					\
 	__asm__ __volatile__ ("ebreak\n");			\
-	unreachable();						\
 } while (0)
 #endif /* !__ASSEMBLY__ */
 #endif /* CONFIG_GENERIC_BUG */
 
+#define BUG() do {						\
+	__BUG_FLAGS(0);						\
+	unreachable();						\
+} while (0)
+
+#define __WARN_FLAGS(flags) __BUG_FLAGS(BUGFLAG_WARNING|(flags))
+
 #define HAVE_ARCH_BUG
 
 #include <asm-generic/bug.h>
-- 
1.7.1


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

* [PATCH v2 2/3] riscv: Add the support for c.ebreak check in is_valid_bugaddr()
  2019-03-05  3:23 [PATCH v2 0/3] riscv: Support trap-based WARN() and fix bug in do_trap_break Vincent Chen
  2019-03-05  3:23 ` [PATCH v2 1/3] riscv: support trap-based WARN() Vincent Chen
@ 2019-03-05  3:23 ` Vincent Chen
  2019-03-05  3:23 ` [PATCH v2 3/3] riscv: Support BUG() in kernel module Vincent Chen
  2 siblings, 0 replies; 4+ messages in thread
From: Vincent Chen @ 2019-03-05  3:23 UTC (permalink / raw)
  To: palmer, aou, ebiederm, jimw, linux-riscv, linux-kernel
  Cc: deanbo422, vincentc

The macro __BUG_INSN currently is defined as the "ebreak" opcode.
The is_valid_bugaddr() function compares the instruction pointed to by
$sepc with macro __BUG_INSN to check whether the current trap exception
is caused by an "ebreak" instruction. However, this check flow is possibly
erroneous because if C extension is supported, the expected trap
instruction "ebreak" is possibly translated to "c.ebreak" by the assembler.
Therefore, it requires a mechanism to distinguish the length of the
instruction in $spec and compare it to the correct trap instruction.

Signed-off-by: Vincent Chen <vincentc@andestech.com>
---
 arch/riscv/include/asm/bug.h |    7 ++++++-
 arch/riscv/kernel/traps.c    |   20 +++++++++++++++++---
 2 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/arch/riscv/include/asm/bug.h b/arch/riscv/include/asm/bug.h
index 4d906d8..52a1fbd 100644
--- a/arch/riscv/include/asm/bug.h
+++ b/arch/riscv/include/asm/bug.h
@@ -21,7 +21,12 @@
 #include <asm/asm.h>
 
 #ifdef CONFIG_GENERIC_BUG
-#define __BUG_INSN	_AC(0x00100073, UL) /* ebreak */
+#define __INSN_LENGTH_MASK  _UL(0x3)
+#define __INSN_LENGTH_32    _UL(0x3)
+#define __COMPRESSED_INSN_MASK	_UL(0xffff)
+
+#define __BUG_INSN_32	_UL(0x00100073) /* ebreak */
+#define __BUG_INSN_16	_UL(0x9002) /* c.ebreak */
 
 #ifndef __ASSEMBLY__
 typedef u32 bug_insn_t;
diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c
index 24a9333..6423e1a 100644
--- a/arch/riscv/kernel/traps.c
+++ b/arch/riscv/kernel/traps.c
@@ -118,6 +118,17 @@ asmlinkage void name(struct pt_regs *regs)				\
 DO_ERROR_INFO(do_trap_ecall_m,
 	SIGILL, ILL_ILLTRP, "environment call from M-mode");
 
+#ifdef CONFIG_GENERIC_BUG
+static inline unsigned long get_break_insn_length(unsigned long pc)
+{
+	bug_insn_t insn;
+
+	if (probe_kernel_address((bug_insn_t *)pc, insn))
+		return 0;
+	return (((insn & __INSN_LENGTH_MASK) == __INSN_LENGTH_32) ? 4UL : 2UL);
+}
+#endif /* CONFIG_GENERIC_BUG */
+
 asmlinkage void do_trap_break(struct pt_regs *regs)
 {
 #ifdef CONFIG_GENERIC_BUG
@@ -129,8 +140,8 @@ asmlinkage void do_trap_break(struct pt_regs *regs)
 		case BUG_TRAP_TYPE_NONE:
 			break;
 		case BUG_TRAP_TYPE_WARN:
-			regs->sepc += sizeof(bug_insn_t);
-			return;
+			regs->sepc += get_break_insn_length(regs->sepc);
+			break;
 		case BUG_TRAP_TYPE_BUG:
 			die(regs, "Kernel BUG");
 		}
@@ -149,7 +160,10 @@ int is_valid_bugaddr(unsigned long pc)
 		return 0;
 	if (probe_kernel_address((bug_insn_t *)pc, insn))
 		return 0;
-	return (insn == __BUG_INSN);
+	if ((insn & __INSN_LENGTH_MASK) == __INSN_LENGTH_32)
+		return (insn == __BUG_INSN_32);
+	else
+		return ((insn & __COMPRESSED_INSN_MASK) == __BUG_INSN_16);
 }
 #endif /* CONFIG_GENERIC_BUG */
 
-- 
1.7.1


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

* [PATCH v2 3/3] riscv: Support BUG() in kernel module
  2019-03-05  3:23 [PATCH v2 0/3] riscv: Support trap-based WARN() and fix bug in do_trap_break Vincent Chen
  2019-03-05  3:23 ` [PATCH v2 1/3] riscv: support trap-based WARN() Vincent Chen
  2019-03-05  3:23 ` [PATCH v2 2/3] riscv: Add the support for c.ebreak check in is_valid_bugaddr() Vincent Chen
@ 2019-03-05  3:23 ` Vincent Chen
  2 siblings, 0 replies; 4+ messages in thread
From: Vincent Chen @ 2019-03-05  3:23 UTC (permalink / raw)
  To: palmer, aou, ebiederm, jimw, linux-riscv, linux-kernel
  Cc: deanbo422, vincentc

The kernel module is loaded into vmalloc region which is located below
to the PAGE_OFFSET. Hence the condition, pc < PAGE_OFFSET, in the
is_valid_bugaddr() will filter out all trap exceptions triggered
by kernel module. To support BUG() in kernel module, the condition is
changed to pc < VMALLOC_START.

Signed-off-by: Vincent Chen <vincentc@andestech.com>
---
 arch/riscv/kernel/traps.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c
index 0cd0137..9551388 100644
--- a/arch/riscv/kernel/traps.c
+++ b/arch/riscv/kernel/traps.c
@@ -156,7 +156,7 @@ int is_valid_bugaddr(unsigned long pc)
 {
 	bug_insn_t insn;
 
-	if (pc < PAGE_OFFSET)
+	if (pc < VMALLOC_START)
 		return 0;
 	if (probe_kernel_address((bug_insn_t *)pc, insn))
 		return 0;
-- 
1.7.1


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

end of thread, other threads:[~2019-03-05  3:24 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-03-05  3:23 [PATCH v2 0/3] riscv: Support trap-based WARN() and fix bug in do_trap_break Vincent Chen
2019-03-05  3:23 ` [PATCH v2 1/3] riscv: support trap-based WARN() Vincent Chen
2019-03-05  3:23 ` [PATCH v2 2/3] riscv: Add the support for c.ebreak check in is_valid_bugaddr() Vincent Chen
2019-03-05  3:23 ` [PATCH v2 3/3] riscv: Support BUG() in kernel module Vincent Chen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®