Hi all,
This is a attempt to bring all low-level debugging print functions
together and provide a arm-like low-level debugging interface and
a further function to debug early exceptions.
The plan is to elimiate platform specific early_printk and
cps-vec-ns16550 by debug_ll and earlycon.
cps-vec-ns16550 is leave unchanged for now due to pending patch[1].
Hope you'll find them handy :-)
Happy hacking!
Thanks
Jiaxun
[1]: https://lore.kernel.org/linux-mips/[email protected]/
Signed-off-by: Jiaxun Yang <[email protected]>
---
Jiaxun Yang (8):
MIPS: asm: Move strings to .rodata.str section
MIPS: debug: Implement low-level debugging functions
MIPS: debug: Hook up DEBUG_LL with early printk
MIPS: debug: Provide an early exception vector for low-level debugging
MIPS: debug_ll: Add Kconfig symbols for some 8250 uarts
MIPS: debug_ll: Implement support for Alchemy uarts
MIPS: debug_ll: Implement support for AR933X uarts
MIPS: zboot: Convert to use debug_ll facilities
arch/mips/Kconfig | 12 +-
arch/mips/Kconfig.debug | 212 +++++++++++++++++++++++++++----
arch/mips/boot/compressed/Makefile | 9 +-
arch/mips/boot/compressed/dbg.c | 37 ------
arch/mips/boot/compressed/debug-vec.S | 3 +
arch/mips/boot/compressed/debug.S | 3 +
arch/mips/boot/compressed/decompress.c | 6 +-
arch/mips/boot/compressed/head.S | 6 +
arch/mips/boot/compressed/uart-16550.c | 47 -------
arch/mips/boot/compressed/uart-alchemy.c | 7 -
arch/mips/boot/compressed/uart-ath79.c | 2 -
arch/mips/boot/compressed/uart-prom.c | 7 -
arch/mips/include/asm/asm.h | 2 +-
arch/mips/include/debug/8250.S | 60 +++++++++
arch/mips/include/debug/alchemy.S | 46 +++++++
arch/mips/include/debug/ar933x.S | 41 ++++++
arch/mips/include/debug/uhi.S | 48 +++++++
arch/mips/kernel/Makefile | 3 +
arch/mips/kernel/debug-vec.S | 194 ++++++++++++++++++++++++++++
arch/mips/kernel/debug.S | 130 +++++++++++++++++++
arch/mips/kernel/early_printk.c | 19 +++
arch/mips/kernel/head.S | 4 +
22 files changed, 750 insertions(+), 148 deletions(-)
---
base-commit: 66f1e1ea3548378ff6387b1ce0b40955d54e86aa
change-id: 20231028-mips_debug_ll-ef9cce16767b
Best regards,
--
Jiaxun Yang <[email protected]>
Alchemy uart is a 8250 derivative that requires some special care
on barriers and readys, also they have a wired register layout.
Implement it as a special include.
Signed-off-by: Jiaxun Yang <[email protected]>
---
arch/mips/Kconfig.debug | 10 +++++++++
arch/mips/include/debug/alchemy.S | 46 +++++++++++++++++++++++++++++++++++++++
2 files changed, 56 insertions(+)
diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug
index 3609d298a9eb..aef116058654 100644
--- a/arch/mips/Kconfig.debug
+++ b/arch/mips/Kconfig.debug
@@ -257,11 +257,20 @@ choice
Say Y here if you want kernel low-level debugging support
on uart0 of Ingenic SoCs.
+ config DEBUG_ALCHEMY_UART
+ bool "Kernel low-level debugging messages via Alchemy UART"
+ depends on MIPS_ALCHEMY
+ select DEBUG_LL_UART
+ help
+ Say Y here if you want kernel low-level debugging support
+ on uart of alchemy SoCs.
+
endchoice
config DEBUG_LL_INCLUDE
string
default "debug/8250.S" if DEBUG_LL_UART_8250 || DEBUG_UART_8250
+ default "debug/alchemy.S" if DEBUG_ALCHEMY_UART
default "debug/uhi.S" if DEBUG_MIPS_UHI
default "debug-macro.S"
@@ -293,6 +302,7 @@ config DEBUG_UART_PHYS
default 0x1fd003f8 if DEBUG_LOONGSON3_UART
default 0x1fe00000 if DEBUG_LOONGSON2K_UART
default 0x10030000 if DEBUG_INGENIC_UART
+ default 0x11100000 if DEBUG_ALCHEMY_UART
help
This is the physical base address of the debug UART. It must be
accessible from unmapped kernel space (i.e. KSEG1 for 32bit kernels
diff --git a/arch/mips/include/debug/alchemy.S b/arch/mips/include/debug/alchemy.S
new file mode 100644
index 000000000000..933efc6e828c
--- /dev/null
+++ b/arch/mips/include/debug/alchemy.S
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2023, Jiaxun Yang <[email protected]>
+ * MIPS Low level debug include file for Au1xxx UART
+ * Dereived from drivers/tty/serial/8250/8250_rt288x.c
+ */
+
+#include <asm/addrspace.h>
+#include <asm/asm.h>
+#include <linux/serial_reg.h>
+
+#define DEBUG_LL_UART
+
+#define UART_BASE CKSEG1ADDR(CONFIG_DEBUG_UART_PHYS)
+
+#define UART_TX_OFS (1 << 2)
+#define UART_LSR_OFS (7 << 2)
+
+# define UART_L lw
+# define UART_S sw
+
+ .macro addruart,rd,rx
+ PTR_LA \rd, UART_BASE
+ .endm
+
+ .macro senduart,rd,rx
+ UART_S \rd, UART_TX_OFS(\rx)
+ sync /* wmb */
+ .endm
+
+ .macro busyuart,rd,rx
+1002:
+ UART_L \rd, UART_LSR_OFS(\rx)
+ andi \rd, \rd, (UART_LSR_TEMT | UART_LSR_THRE)
+ xori \rd, (UART_LSR_TEMT | UART_LSR_THRE)
+ sync /* cpu_relax */
+ bnez \rd, 1002b
+ .endm
+
+ .macro waituarttxrdy,rd,rx
+ busyuart \rd, \rx
+ .endm
+
+ /* Au1xxx has no MSR */
+ .macro waituartcts,rd,rx
+ .endm
--
2.34.1
Since now debug_ll facilities can cover all platforms supported
by zboot debug print, and it provides extra capability on debugging
exceptions, switch zboot to use those facilities.
Signed-off-by: Jiaxun Yang <[email protected]>
---
arch/mips/Kconfig | 12 ++------
arch/mips/Kconfig.debug | 46 +++++++++++++------------------
arch/mips/boot/compressed/Makefile | 9 ++----
arch/mips/boot/compressed/dbg.c | 37 -------------------------
arch/mips/boot/compressed/debug-vec.S | 3 ++
arch/mips/boot/compressed/debug.S | 3 ++
arch/mips/boot/compressed/decompress.c | 6 ++--
arch/mips/boot/compressed/head.S | 6 ++++
arch/mips/boot/compressed/uart-16550.c | 47 --------------------------------
arch/mips/boot/compressed/uart-alchemy.c | 7 -----
arch/mips/boot/compressed/uart-ath79.c | 2 --
arch/mips/boot/compressed/uart-prom.c | 7 -----
12 files changed, 39 insertions(+), 146 deletions(-)
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 76db82542519..0442b44da32f 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -232,7 +232,7 @@ config ATH79
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_SUPPORTS_MIPS16
- select SYS_SUPPORTS_ZBOOT_UART_PROM
+ select SYS_SUPPORTS_ZBOOT
select USE_OF
select USB_EHCI_ROOT_HUB_TT if USB_EHCI_HCD_PLATFORM
help
@@ -413,7 +413,7 @@ config MACH_INGENIC_SOC
bool "Ingenic SoC based machines"
select MIPS_GENERIC
select MACH_INGENIC
- select SYS_SUPPORTS_ZBOOT_UART16550
+ select SYS_SUPPORTS_ZBOOT
select CPU_SUPPORTS_CPUFREQ
select MIPS_EXTERNAL_TIMER
@@ -1727,14 +1727,6 @@ config SYS_SUPPORTS_ZBOOT
select HAVE_KERNEL_XZ
select HAVE_KERNEL_ZSTD
-config SYS_SUPPORTS_ZBOOT_UART16550
- bool
- select SYS_SUPPORTS_ZBOOT
-
-config SYS_SUPPORTS_ZBOOT_UART_PROM
- bool
- select SYS_SUPPORTS_ZBOOT
-
config CPU_LOONGSON2EF
bool
select CPU_SUPPORTS_32BIT_KERNEL
diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug
index a6687c503c34..0ce6d24d05b3 100644
--- a/arch/mips/Kconfig.debug
+++ b/arch/mips/Kconfig.debug
@@ -79,33 +79,6 @@ config SB1XXX_CORELIS
Select compile flags that produce code that can be processed by the
Corelis mksym utility and UDB Emulator.
-config DEBUG_ZBOOT
- bool "Enable compressed kernel support debugging"
- depends on DEBUG_KERNEL && SYS_SUPPORTS_ZBOOT
- default n
- help
- If you want to add compressed kernel support to a new board, and the
- board supports uart16550 compatible serial port, please select
- SYS_SUPPORTS_ZBOOT_UART16550 for your board and enable this option to
- debug it.
-
- If your board doesn't support uart16550 compatible serial port, you
- can try to select SYS_SUPPORTS_ZBOOT and use the other methods to
- debug it. for example, add a new serial port support just as
- arch/mips/boot/compressed/uart-16550.c does.
-
- After the compressed kernel support works, please disable this option
- to reduce the kernel image size and speed up the booting procedure a
- little.
-
-config ZBOOT_INGENIC_UART
- int "UART to use for compressed kernel debugging"
- depends on DEBUG_ZBOOT && MACH_INGENIC_SOC
- default 0
- range 0 4
- help
- Specify the UART that should be used for compressed kernel debugging.
-
config SPINLOCK_TEST
bool "Enable spinlock timing tests in debugfs"
depends on DEBUG_FS
@@ -328,3 +301,22 @@ config DEBUG_UART_8250_WIDTH
int "Register width for the 8250 debug UART"
depends on DEBUG_LL_UART_8250 || DEBUG_UART_8250
default 1
+
+config DEBUG_ZBOOT
+ bool "Enable compressed kernel debugging via DEBUG_LL output"
+ depends on DEBUG_LL && SYS_SUPPORTS_ZBOOT
+ help
+ Say Y here if you want to enable debugging of a compressed kernel
+ via the DEBUG_LL output. This is useful if you are debugging
+ decompressor issues.
+
+ If unsure, say N.
+
+config DEBUG_ZBOOT_EXCEPT
+ bool "Enable compressed kernel debugging of exceptions"
+ depends on DEBUG_ZBOOT
+ help
+ Say Y here if you want to enable debugging of exceptions happen
+ during decompression of a compressed kernel via the DEBUG_LL output.
+
+ If unsure, say N.
diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile
index 6cc28173bee8..78c65db8dd04 100644
--- a/arch/mips/boot/compressed/Makefile
+++ b/arch/mips/boot/compressed/Makefile
@@ -43,13 +43,8 @@ KCSAN_SANITIZE := n
# decompressor objects (linked with vmlinuz)
vmlinuzobjs-y := $(obj)/head.o $(obj)/decompress.o $(obj)/string.o $(obj)/bswapsi.o
-ifdef CONFIG_DEBUG_ZBOOT
-vmlinuzobjs-$(CONFIG_DEBUG_ZBOOT) += $(obj)/dbg.o
-vmlinuzobjs-$(CONFIG_SYS_SUPPORTS_ZBOOT_UART16550) += $(obj)/uart-16550.o
-vmlinuzobjs-$(CONFIG_SYS_SUPPORTS_ZBOOT_UART_PROM) += $(obj)/uart-prom.o
-vmlinuzobjs-$(CONFIG_MIPS_ALCHEMY) += $(obj)/uart-alchemy.o
-vmlinuzobjs-$(CONFIG_ATH79) += $(obj)/uart-ath79.o
-endif
+vmlinuzobjs-$(CONFIG_DEBUG_ZBOOT) += $(obj)/debug.o
+vmlinuzobjs-$(CONFIG_DEBUG_ZBOOT_EXCEPT) += $(obj)/debug-vec.o
vmlinuzobjs-$(CONFIG_KERNEL_XZ) += $(obj)/ashldi3.o
diff --git a/arch/mips/boot/compressed/dbg.c b/arch/mips/boot/compressed/dbg.c
deleted file mode 100644
index f6728a8fd1c3..000000000000
--- a/arch/mips/boot/compressed/dbg.c
+++ /dev/null
@@ -1,37 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * MIPS-specific debug support for pre-boot environment
- *
- * NOTE: putc() is board specific, if your board have a 16550 compatible uart,
- * please select SYS_SUPPORTS_ZBOOT_UART16550 for your machine. othewise, you
- * need to implement your own putc().
- */
-#include <linux/compiler.h>
-#include <linux/types.h>
-
-void __weak putc(char c)
-{
-}
-
-void puts(const char *s)
-{
- char c;
- while ((c = *s++) != '\0') {
- putc(c);
- if (c == '\n')
- putc('\r');
- }
-}
-
-void puthex(unsigned long long val)
-{
-
- unsigned char buf[10];
- int i;
- for (i = 7; i >= 0; i--) {
- buf[i] = "0123456789ABCDEF"[val & 0x0F];
- val >>= 4;
- }
- buf[8] = '\0';
- puts(buf);
-}
diff --git a/arch/mips/boot/compressed/debug-vec.S b/arch/mips/boot/compressed/debug-vec.S
new file mode 100644
index 000000000000..e7bedb183da8
--- /dev/null
+++ b/arch/mips/boot/compressed/debug-vec.S
@@ -0,0 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include "../../kernel/debug-vec.S"
diff --git a/arch/mips/boot/compressed/debug.S b/arch/mips/boot/compressed/debug.S
new file mode 100644
index 000000000000..0cf3da958f7e
--- /dev/null
+++ b/arch/mips/boot/compressed/debug.S
@@ -0,0 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include "../../kernel/debug.S"
diff --git a/arch/mips/boot/compressed/decompress.c b/arch/mips/boot/compressed/decompress.c
index c5dd415254d3..2317f44307e1 100644
--- a/arch/mips/boot/compressed/decompress.c
+++ b/arch/mips/boot/compressed/decompress.c
@@ -31,8 +31,10 @@ extern unsigned char __image_begin[], __image_end[];
/* debug interfaces */
#ifdef CONFIG_DEBUG_ZBOOT
-extern void puts(const char *s);
-extern void puthex(unsigned long long val);
+extern void printascii(const char *s);
+extern void printhexl(unsigned long val);
+#define puts(s) printascii(s)
+#define puthex(val) printhexl(val)
#else
#define puts(s) do {} while (0)
#define puthex(val) do {} while (0)
diff --git a/arch/mips/boot/compressed/head.S b/arch/mips/boot/compressed/head.S
index 5795d0af1e1b..c347d2273ae8 100644
--- a/arch/mips/boot/compressed/head.S
+++ b/arch/mips/boot/compressed/head.S
@@ -22,6 +22,12 @@
move s2, a2
move s3, a3
+#ifdef CONFIG_DEBUG_ZBOOT_EXCEP
+ /* Set up the exception vector */
+ PTR_LA t9, setup_debug_ll_exception
+ jalr t9
+#endif
+
/* Clear BSS */
PTR_LA a0, _edata
PTR_LA a2, _end
diff --git a/arch/mips/boot/compressed/uart-16550.c b/arch/mips/boot/compressed/uart-16550.c
deleted file mode 100644
index 09dcd2c561d9..000000000000
--- a/arch/mips/boot/compressed/uart-16550.c
+++ /dev/null
@@ -1,47 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 16550 compatible uart based serial debug support for zboot
- */
-
-#include <linux/types.h>
-#include <linux/serial_reg.h>
-
-#include <asm/addrspace.h>
-
-#if defined(CONFIG_MACH_LOONGSON64) || defined(CONFIG_MIPS_MALTA)
-#define UART_BASE 0x1fd003f8
-#define PORT(offset) (CKSEG1ADDR(UART_BASE) + (offset))
-#endif
-
-#ifdef CONFIG_MACH_INGENIC
-#define INGENIC_UART_BASE_ADDR (0x10030000 + 0x1000 * CONFIG_ZBOOT_INGENIC_UART)
-#define PORT(offset) (CKSEG1ADDR(INGENIC_UART_BASE_ADDR) + (4 * offset))
-#endif
-
-#ifndef IOTYPE
-#define IOTYPE char
-#endif
-
-#ifndef PORT
-#error please define the serial port address for your own machine
-#endif
-
-static inline unsigned int serial_in(int offset)
-{
- return *((volatile IOTYPE *)PORT(offset)) & 0xFF;
-}
-
-static inline void serial_out(int offset, int value)
-{
- *((volatile IOTYPE *)PORT(offset)) = value & 0xFF;
-}
-
-void putc(char c)
-{
- int timeout = 1000000;
-
- while (((serial_in(UART_LSR) & UART_LSR_THRE) == 0) && (timeout-- > 0))
- ;
-
- serial_out(UART_TX, c);
-}
diff --git a/arch/mips/boot/compressed/uart-alchemy.c b/arch/mips/boot/compressed/uart-alchemy.c
deleted file mode 100644
index 8ec63011e7dc..000000000000
--- a/arch/mips/boot/compressed/uart-alchemy.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <asm/mach-au1x00/au1000.h>
-
-void putc(char c)
-{
- alchemy_uart_putchar(AU1000_UART0_PHYS_ADDR, c);
-}
diff --git a/arch/mips/boot/compressed/uart-ath79.c b/arch/mips/boot/compressed/uart-ath79.c
deleted file mode 100644
index d686820921be..000000000000
--- a/arch/mips/boot/compressed/uart-ath79.c
+++ /dev/null
@@ -1,2 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-#include "../../ath79/early_printk.c"
diff --git a/arch/mips/boot/compressed/uart-prom.c b/arch/mips/boot/compressed/uart-prom.c
deleted file mode 100644
index a8a0a32e05d1..000000000000
--- a/arch/mips/boot/compressed/uart-prom.c
+++ /dev/null
@@ -1,7 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <asm/setup.h>
-
-void putc(char c)
-{
- prom_putchar(c);
-}
--
2.34.1
This is helpful for debugging of early boot crash when exceptions
happens before trap_init(), or for debugging SMP bringup code.
It will install exception handler very early on kernel_entry by
setting ebase or copy itself to start of CKSEG0, and print off
exception vectors and other status registers like:
Low level exception: ffffffff8011e180
GlobalNumber: 0x00000000
EBase: 0xffffffff8011e000
Xcontext: 0x0000000000000000
Cause: 0x0000000c
Status: 0x14000082
EPC: 0xffffffff80d324e0
BadVAddr: 0x0000000000000000
BadInstr: 0xac000000
Signed-off-by: Jiaxun Yang <[email protected]>
---
arch/mips/Kconfig.debug | 9 ++
arch/mips/kernel/Makefile | 1 +
arch/mips/kernel/debug-vec.S | 194 +++++++++++++++++++++++++++++++++++++++++++
arch/mips/kernel/head.S | 4 +
4 files changed, 208 insertions(+)
diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug
index 6ef42edc7d67..323ad3ec643b 100644
--- a/arch/mips/Kconfig.debug
+++ b/arch/mips/Kconfig.debug
@@ -180,6 +180,15 @@ config DEBUG_LL
this option should not be enabled for kernels that are intended to
be portable.
+config DEBUG_LL_EXCEPT
+ bool "Kernel low-level debugging of exceptions"
+ depends on DEBUG_LL
+ help
+ Say Y here to enable debugging prints for low-level exceptions.
+ This is helpful if you are debugging a early boot crash when
+ exceptions happens before trap_init(), or if you are debugging
+ SMP bringup code.
+
choice
prompt "Kernel low-level debugging port"
depends on DEBUG_LL
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 10c0a224efe4..400e35f9f82f 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -79,6 +79,7 @@ obj-$(CONFIG_MIPS32_N32) += scall64-n32.o signal_n32.o
obj-$(CONFIG_MIPS32_O32) += scall64-o32.o signal_o32.o
obj-$(CONFIG_DEBUG_LL) += debug.o
+obj-$(CONFIG_DEBUG_LL_EXCEPT) += debug-vec.o
obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_PROC_FS) += proc.o
diff --git a/arch/mips/kernel/debug-vec.S b/arch/mips/kernel/debug-vec.S
new file mode 100644
index 000000000000..4530bf3d5b75
--- /dev/null
+++ b/arch/mips/kernel/debug-vec.S
@@ -0,0 +1,194 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2023, Jiaxun Yang <[email protected]>
+ * MIPS Low level exception vectors and handler
+ */
+
+#include <asm/addrspace.h>
+#include <asm/asm.h>
+#include <asm/asm-offsets.h>
+#include <asm/asmmacro.h>
+
+
+.balign 0x1000
+LEAF(debug_ll_vecs)
+ .set push
+ .set noreorder
+ move a0, zero
+ PTR_LA t9, debug_ll_exception
+ jalr t9
+ nop
+ b .
+ nop
+
+.org 0x80
+ move a0, zero
+ PTR_LA t9, debug_ll_exception
+ jalr t9
+ nop
+ b .
+ nop
+
+.org 0x100
+ move a0, zero
+ PTR_LA t9, debug_ll_exception
+ jalr t9
+ nop
+ b .
+ nop
+
+.org 0x180
+ move a0, zero
+ PTR_LA t9, debug_ll_exception
+ jalr t9
+ nop
+ b .
+ nop
+
+.org 0x200
+ move a0, zero
+ PTR_LA t9, debug_ll_exception
+ jalr t9
+ nop
+ b .
+ nop
+
+.org 0x280
+ move a0, zero
+ PTR_LA t9, debug_ll_exception
+ jalr t9
+ nop
+ b .
+ nop
+
+.org 0x300
+ move a0, zero
+ PTR_LA t9, debug_ll_exception
+ jalr t9
+ nop
+ b .
+ nop
+
+.org 0x380
+ move a0, zero
+ PTR_LA t9, debug_ll_exception
+ jalr t9
+ nop
+ b .
+ nop
+
+.org 0x400
+ move a0, zero
+ PTR_LA t9, debug_ll_exception
+ jalr t9
+ nop
+ b .
+ nop
+
+.org 0x480
+ move a0, zero
+ PTR_LA t9, debug_ll_exception
+ jalr t9
+ nop
+ b .
+ nop
+
+ .set pop
+END(debug_ll_vecs)
+
+
+/**
+ * debug_ll_exception() - dump relevant exception state to LL outputs
+ * @a0: pointer to NULL-terminated ASCII string naming the exception
+ *
+ * If a0 is NULL, it will print out exception vector number calculated
+ * from the ra insted. This is useful for debugging exceptions that
+ * happen before the exception handler is set up, or routed from BEV.
+ */
+LEAF(debug_ll_exception)
+ move k0, ra
+ move k1, a0
+ PTR_LA t3, printascii
+
+ PTR_LA a0, str_newline
+ jalr t3 /* Call printascii */
+ PTR_LA a0, str_exp
+ jalr t3 /* Call printascii */
+ beqz k1, 1f
+ move a0, k1
+ jalr t3 /* Call printascii */
+ b 2f
+1:
+ PTR_SRL a0, k0, 7
+ PTR_SLL a0, a0, 7
+ PTR_LA t2, printhexl
+ jalr t2
+2:
+ PTR_LA a0, str_newline
+ jalr t3 /* Call printascii */
+ PTR_LA a0, str_newline
+ jalr t3 /* Call printascii */
+
+#define DUMP_COP0_REG(reg, name, sz, _mfc0) \
+ PTR_LA a0, 8f; \
+ jalr t3; \
+ _mfc0 a0, reg; \
+ PTR_LA t2, printhex##sz; \
+ jalr t2; \
+ PTR_LA a0, str_newline; \
+ jalr t3; \
+ TEXT(name)
+
+#if defined(CONFIG_SMP) && defined(CONFIG_CPU_MIPSR6)
+ DUMP_COP0_REG(CP0_GLOBALNUMBER, "GlobalNumber: 0x", 4, mfc0)
+#endif
+#if MIPS_ISA_REV >= 2
+ DUMP_COP0_REG(CP0_EBASE, "EBase: 0x", l, MFC0)
+#endif
+#ifdef CONFIG_64BIT
+ DUMP_COP0_REG(CP0_XCONTEXT, "Xcontext: 0x", 8, dmfc0)
+#else
+ DUMP_COP0_REG(CP0_CONTEXT, "Context: 0x", 4, mfc0)
+#endif
+ DUMP_COP0_REG(CP0_CAUSE, "Cause: 0x", 4, mfc0)
+ DUMP_COP0_REG(CP0_STATUS, "Status: 0x", 4, mfc0)
+ DUMP_COP0_REG(CP0_EPC, "EPC: 0x", l, MFC0)
+ DUMP_COP0_REG(CP0_BADVADDR, "BadVAddr: 0x", l, MFC0)
+#if MIPS_ISA_REV >= 6
+ DUMP_COP0_REG(CP0_BADINSTR, "BadInstr: 0x", 4, mfc0)
+#endif
+ PTR_LA a0, str_newline
+ jalr t3 /* Call printascii */
+ jr k0
+ END(debug_ll_exception)
+
+.pushsection .rodata.str
+str_exp: .asciiz "Low level exception: "
+str_newline: .asciiz "\r\n"
+.popsection
+
+NESTED(setup_debug_ll_exception, 0, ra)
+ PTR_LA t0, debug_ll_vecs
+#if MIPS_ISA_REV >= 2
+ /* Set ebase to debug_ll_vecs */
+#if defined (CONFIG_64BIT) && !defined(KBUILD_64BIT_SYM32)
+ ori t0, MIPS_EBASE_WG
+#endif
+ MTC0 t0, CP0_EBASE
+#else
+ /* Copy debug_ll_vecs to start of KSEG0 */
+ PTR_LI t1, CKSEG0
+ PTR_ADDIU t2, t0, 0x400 /* Only copy 0x400 as that is what reserved on old systems */
+copy_word:
+ PTR_LW t3, 0(t0)
+ PTR_SW t3, 0(t1)
+ PTR_ADDIU t0, t0, PTRSIZE
+ PTR_ADDIU t1, t1, PTRSIZE
+ PTR_BNE t0, t2, copy_word
+#endif
+ /* Clear BEV bit in status register */
+ mfc0 t0, CP0_STATUS
+ and t0, t0, ~ST0_BEV
+ mtc0 t0, CP0_STATUS
+ jr ra
+ END(setup_debug_ll_exception)
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index b825ed4476c7..9be1c4ce6324 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -106,6 +106,10 @@ NESTED(kernel_entry, 16, sp) # kernel entry point
LONG_S a2, fw_arg2
LONG_S a3, fw_arg3
+#ifdef CONFIG_DEBUG_LL_EXCEPT
+ jal setup_debug_ll_exception
+#endif
+
MTC0 zero, CP0_CONTEXT # clear context register
#ifdef CONFIG_64BIT
MTC0 zero, CP0_XCONTEXT
--
2.34.1
Currently we have three sets of early debugging functions
for MIPS: zboot putc/puts, cps-vec-ns16550, and prom_putc.
This is a attempt to bring them all to one by providing
a interface similar to arm's debug_ll, which is very portable
and allows you to support new platforms easily.
Two examples of output interfaces are provided, including
8250 uart and MIPS UHI semihosting, which already covered
most of the platforms.
Signed-off-by: Jiaxun Yang <[email protected]>
---
arch/mips/Kconfig.debug | 80 +++++++++++++++++++++++++
arch/mips/include/debug/8250.S | 60 +++++++++++++++++++
arch/mips/include/debug/uhi.S | 48 +++++++++++++++
arch/mips/kernel/Makefile | 2 +
arch/mips/kernel/debug.S | 130 +++++++++++++++++++++++++++++++++++++++++
5 files changed, 320 insertions(+)
diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug
index f4ae7900fcd3..892e31804982 100644
--- a/arch/mips/Kconfig.debug
+++ b/arch/mips/Kconfig.debug
@@ -164,3 +164,83 @@ config MIPS_CPS_NS16550_WIDTH
lb/sb instructions.
endif # MIPS_CPS_NS16550_BOOL
+
+# These options are only for real kernel hackers who want to get their hands dirty.
+config DEBUG_LL
+ bool "Kernel low-level debugging functions (read help!)"
+ depends on DEBUG_KERNEL
+ help
+ Say Y here to include definitions of printascii, printch, printhex
+ in the kernel. This is helpful if you are debugging code that
+ executes before the console is initialized.
+
+ Note that selecting this option will limit the kernel to a single
+ UART or semihosting definition, as specified below. Attempting to
+ boot the kernel image on a different platform *will not work*, so
+ this option should not be enabled for kernels that are intended to
+ be portable.
+
+choice
+ prompt "Kernel low-level debugging port"
+ depends on DEBUG_LL
+
+ config DEBUG_MIPS_UHI
+ bool "Kernel low-level debugging via UHI semihosting"
+ help
+ Say Y here if you want kernel low-level debugging support
+ via MIPS UHI semihosting.
+
+ config DEBUG_LL_UART_8250
+ bool "Kernel low-level debugging via 8250 UART"
+ select DEBUG_LL_UART
+ help
+ Say Y here if you wish the debug print routes to direct
+ their output to an 8250 UART. You can use this option
+ to provide the parameters for the 8250 UART rather than
+ selecting one of the platform specific options below if
+ you know the parameters for the port.
+
+endchoice
+
+config DEBUG_LL_INCLUDE
+ string
+ default "debug/8250.S" if DEBUG_LL_UART_8250 || DEBUG_UART_8250
+ default "debug/uhi.S" if DEBUG_MIPS_UHI
+ default "debug-macro.S"
+
+# Compatibility options for 8250
+config DEBUG_UART_8250
+ bool
+ select DEBUG_LL_UART
+
+config DEBUG_LL_UART
+ bool
+
+config DEBUG_UART_FLOW_CONTROL
+ bool "Enable flow control (CTS) for the debug UART"
+ depends on DEBUG_LL_UART
+ default n
+ help
+ Some UART ports are connected to terminals that will use modem
+ control signals to indicate whether they are ready to receive text.
+ In practice this means that the terminal is asserting the special
+ control signal CTS (Clear To Send). If your debug UART supports
+ this and your debug terminal will require it, enable this option.
+
+config DEBUG_UART_PHYS
+ hex "Physical base address of debug UART"
+ depends on DEBUG_LL_UART
+ help
+ This is the physical base address of the debug UART. It must be
+ accessible from unmapped kernel space (i.e. KSEG1 for 32bit kernels
+ or XKPHYS for 64bit kernels).
+
+config DEBUG_UART_8250_SHIFT
+ int "Register offset shift for the 8250 debug UART"
+ depends on DEBUG_LL_UART_8250 || DEBUG_UART_8250
+ default 2
+
+config DEBUG_UART_8250_WIDTH
+ int "Register width for the 8250 debug UART"
+ depends on DEBUG_LL_UART_8250 || DEBUG_UART_8250
+ default 1
diff --git a/arch/mips/include/debug/8250.S b/arch/mips/include/debug/8250.S
new file mode 100644
index 000000000000..f8608d3e271a
--- /dev/null
+++ b/arch/mips/include/debug/8250.S
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2023, Jiaxun Yang <[email protected]>
+ * MIPS Low level debug include file for 8250 UART
+ */
+
+#include <asm/addrspace.h>
+#include <asm/asm.h>
+#include <linux/serial_reg.h>
+
+#define DEBUG_LL_UART
+
+#define UART_BASE CKSEG1ADDR(CONFIG_DEBUG_UART_PHYS)
+
+#define UART_TX_OFS (UART_TX << CONFIG_DEBUG_UART_8250_SHIFT)
+#define UART_LSR_OFS (UART_LSR << CONFIG_DEBUG_UART_8250_SHIFT)
+#define UART_MSR_OFS (UART_MSR << CONFIG_DEBUG_UART_8250_SHIFT)
+
+#if CONFIG_DEBUG_UART_8250_WIDTH == 1
+# define UART_L lb
+# define UART_S sb
+#elif CONFIG_DEBUG_UART_8250_WIDTH == 2
+# define UART_L lh
+# define UART_S sh
+#elif CONFIG_DEBUG_UART_8250_WIDTH == 4
+# define UART_L lw
+# define UART_S sw
+#elif defined(CONFIG_64BIT) && CONFIG_DEBUG_UART_8250_WIDTH == 8
+# define UART_L ld
+# define UART_S sd
+#else
+# define UART_L lb
+# define UART_S sb
+#endif
+
+ .macro addruart,rd,rx
+ PTR_LA \rd, UART_BASE
+ .endm
+
+ .macro senduart,rd,rx
+ UART_S \rd, UART_TX_OFS(\rx)
+ .endm
+
+ .macro busyuart,rd,rx
+1002:
+ UART_L \rd, UART_LSR_OFS(\rx)
+ andi \rd, \rd, (UART_LSR_TEMT | UART_LSR_THRE)
+ xori \rd, (UART_LSR_TEMT | UART_LSR_THRE)
+ bnez \rd, 1002b
+ .endm
+
+ .macro waituarttxrdy,rd,rx
+ .endm
+
+ .macro waituartcts,rd,rx
+1001:
+ UART_L \rd, UART_MSR_OFS(\rx)
+ andi \rd, UART_MSR_CTS
+ beqz \rd, 1001b
+ .endm
diff --git a/arch/mips/include/debug/uhi.S b/arch/mips/include/debug/uhi.S
new file mode 100644
index 000000000000..20554523e151
--- /dev/null
+++ b/arch/mips/include/debug/uhi.S
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2023, Jiaxun Yang <[email protected]>
+ * MIPS Low level debug include file for UHI semihosting
+ */
+
+#include <asm/asm.h>
+
+/**
+ * printch() - write a character to UHI Plog
+ * @a0: ASCII character to write
+ *
+ * clobbers v0, t9
+ * UHI may clobber k0, k1
+ */
+ .pushsection .bss
+charbuf_addr: .space 8
+ .popsection
+NESTED(printch, 0, ra)
+ PTR_LI t9, charbuf_addr
+ sb a0, 0(t9)
+ sb zero, 1(t9)
+ move a0, t9
+ li v0, 0x1
+ li t9, 13 /* plog */
+ .set push
+ .set MIPS_ISA_LEVEL_RAW
+ sdbbp 1
+ .set pop
+ jr ra
+ END(printch)
+
+/**
+ * printascii() - write a string to UHI Plog
+ * @a0: pointer to NULL-terminated ASCII string
+ *
+ * clobbers v0
+ * UHI may clobber k0, k1
+ */
+NESTED(printascii, 0, ra)
+ li v0, 0x1
+ li t9, 13 /* plog */
+ .set push
+ .set MIPS_ISA_LEVEL_RAW
+ sdbbp 1
+ .set pop
+ jr ra
+ END(printascii)
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 853a43ee4b44..10c0a224efe4 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -78,6 +78,8 @@ obj-$(CONFIG_MIPS32_COMPAT) += linux32.o ptrace32.o signal32.o
obj-$(CONFIG_MIPS32_N32) += scall64-n32.o signal_n32.o
obj-$(CONFIG_MIPS32_O32) += scall64-o32.o signal_o32.o
+obj-$(CONFIG_DEBUG_LL) += debug.o
+
obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o
diff --git a/arch/mips/kernel/debug.S b/arch/mips/kernel/debug.S
new file mode 100644
index 000000000000..f71c6c969ef6
--- /dev/null
+++ b/arch/mips/kernel/debug.S
@@ -0,0 +1,130 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2023, Jiaxun Yang <[email protected]>
+ * MIPS Low level debug routines
+ *
+ * Note: Those functions are designed carefully to only clobber
+ * t0, t1, t9, so they can be used without stack. Also they are
+ * position independent to be called from any place.
+ */
+
+#include <linux/compiler.h>
+
+#include <asm/addrspace.h>
+#include <asm/asm.h>
+#include <asm/asm-offsets.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+
+#include CONFIG_DEBUG_LL_INCLUDE
+
+#ifdef DEBUG_LL_UART
+/**
+ * printch() - write a character to the UART
+ * @a0: ASCII character to write
+ *
+ * clobbers t0, t9
+ */
+NESTED(printch, 0, ra)
+ addruart t9, t0
+#ifdef CONFIG_DEBUG_UART_FLOW_CONTROL
+ waituartcts t0, t9
+#endif
+ waituarttxrdy t0, t9
+ senduart a0, t9
+ busyuart t0, t9
+ jr ra
+ END(printch)
+
+/**
+ * printascii() - write a string to the UART
+ * @a0: pointer to NULL-terminated ASCII string
+ *
+ * clobbers t0, t1, t9
+ *
+ * Write a null-terminated ASCII string to the UART.
+ */
+NESTED(printascii, 0, ra)
+ addruart t9, t0
+ move t1, a0
+
+1: lb a0, 0(t1)
+ beqz a0, 2f
+#ifdef CONFIG_DEBUG_UART_FLOW_CONTROL
+ waituartcts t0, t9
+#endif
+ waituarttxrdy t0, t9
+ senduart a0, t9
+ busyuart t0, t9
+ PTR_ADDIU t1, t1, 1
+ b 1b
+
+2: jr ra
+ END(printascii)
+#endif /* DEBUG_LL_UART */
+
+/**
+ * printhex() - write n byte hex value to the UART
+ * @a0: Hex value to write to the UART
+ * @a1: number of bytes to write to the UART
+ *
+ * clobbers: t0, t1, t9
+ */
+
+ .pushsection .bss
+hexbuf_addr: .space 32
+ .popsection
+
+NESTED(printhex, 0, ra)
+ PTR_LA t9, hexbuf_addr
+ sll a1, a1, 1
+1:
+ subu t0, a1, 1
+ sll t0, t0, 2
+ LONG_SRLV t0, a0, t0
+ andi t0, t0, 0xf
+ li t1, '0'
+ blt t0, 10, 2f
+ li t1, 'a'
+ addiu t0, t0, -10
+2:
+ addu t1, t1, t0
+ sb t1, 0(t9)
+ PTR_ADDIU t9, t9, 1
+ addiu a1, a1, -1
+ bnez a1, 1b
+ sb zero, 0(t9)
+
+ move a1, ra
+ PTR_LA a0, hexbuf_addr
+ bal printascii
+
+ jr a1
+ END(printhex)
+
+NESTED(printhex1, 0, ra)
+ li a1, 1
+ b printhex
+ END(printhex1)
+
+NESTED(printhex2, 0, ra)
+ li a1, 2
+ b printhex
+ END(printhex2)
+
+NESTED(printhex4, 0, ra)
+ li a1, 4
+ b printhex
+ END(printhex4)
+
+#ifdef CONFIG_64BIT
+NESTED(printhex8, 0, ra)
+ li a1, 8
+ b printhex
+ END(printhex8)
+#endif
+
+NESTED(printhexl, 0, ra)
+ li a1, PTRSIZE
+ b printhex
+ END(printhexl)
--
2.34.1
在2023年10月29日十月 上午2:53,Jiaxun Yang写道:
> Hi all,
Hi Thomas,
A gentle ping on this series :-)
I've got too much patch floating out there.
Thanks
- Jiaxun
>
> This is a attempt to bring all low-level debugging print functions
> together and provide a arm-like low-level debugging interface and
> a further function to debug early exceptions.
>
> The plan is to elimiate platform specific early_printk and
> cps-vec-ns16550 by debug_ll and earlycon.
>
> cps-vec-ns16550 is leave unchanged for now due to pending patch[1].
>
> Hope you'll find them handy :-)
>
> Happy hacking!
>
> Thanks
> Jiaxun
>
> [1]:
> https://lore.kernel.org/linux-mips/[email protected]/
>
> Signed-off-by: Jiaxun Yang <[email protected]>
> ---
> Jiaxun Yang (8):
> MIPS: asm: Move strings to .rodata.str section
> MIPS: debug: Implement low-level debugging functions
> MIPS: debug: Hook up DEBUG_LL with early printk
> MIPS: debug: Provide an early exception vector for low-level debugging
> MIPS: debug_ll: Add Kconfig symbols for some 8250 uarts
> MIPS: debug_ll: Implement support for Alchemy uarts
> MIPS: debug_ll: Implement support for AR933X uarts
> MIPS: zboot: Convert to use debug_ll facilities
>
> arch/mips/Kconfig | 12 +-
> arch/mips/Kconfig.debug | 212 +++++++++++++++++++++++++++----
> arch/mips/boot/compressed/Makefile | 9 +-
> arch/mips/boot/compressed/dbg.c | 37 ------
> arch/mips/boot/compressed/debug-vec.S | 3 +
> arch/mips/boot/compressed/debug.S | 3 +
> arch/mips/boot/compressed/decompress.c | 6 +-
> arch/mips/boot/compressed/head.S | 6 +
> arch/mips/boot/compressed/uart-16550.c | 47 -------
> arch/mips/boot/compressed/uart-alchemy.c | 7 -
> arch/mips/boot/compressed/uart-ath79.c | 2 -
> arch/mips/boot/compressed/uart-prom.c | 7 -
> arch/mips/include/asm/asm.h | 2 +-
> arch/mips/include/debug/8250.S | 60 +++++++++
> arch/mips/include/debug/alchemy.S | 46 +++++++
> arch/mips/include/debug/ar933x.S | 41 ++++++
> arch/mips/include/debug/uhi.S | 48 +++++++
> arch/mips/kernel/Makefile | 3 +
> arch/mips/kernel/debug-vec.S | 194 ++++++++++++++++++++++++++++
> arch/mips/kernel/debug.S | 130 +++++++++++++++++++
> arch/mips/kernel/early_printk.c | 19 +++
> arch/mips/kernel/head.S | 4 +
> 22 files changed, 750 insertions(+), 148 deletions(-)
> ---
> base-commit: 66f1e1ea3548378ff6387b1ce0b40955d54e86aa
> change-id: 20231028-mips_debug_ll-ef9cce16767b
>
> Best regards,
> --
> Jiaxun Yang <[email protected]>
--
- Jiaxun
On Sun, Oct 29, 2023 at 02:53:01AM +0000, Jiaxun Yang wrote:
> The plan is to elimiate platform specific early_printk and
> cps-vec-ns16550 by debug_ll and earlycon.
https://xkcd.com/927/ ?
sorry I don't think that just another new function is good approach.
Doing this will end up with another method for early debugging and
all other will stay.
Thomas.
--
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea. [ RFC1925, 2.3 ]
在2023年12月20日十二月 下午9:18,Thomas Bogendoerfer写道:
> On Sun, Oct 29, 2023 at 02:53:01AM +0000, Jiaxun Yang wrote:
>> The plan is to elimiate platform specific early_printk and
>> cps-vec-ns16550 by debug_ll and earlycon.
>
> https://xkcd.com/927/ ?
>
> sorry I don't think that just another new function is good approach.
> Doing this will end up with another method for early debugging and
> all other will stay.
All others will go (one of two already gone).
The thing is, I tried to get cps-vec-16550 and zboot work with UHI
semihosting, and soon find out that they are doing exactly the same
thing. So I tried to unify them.
I miss the good old day on Arm system that I can use handy debug_ll
functions for every low level debugging purpose, thus I just copied the
whole design.
There won't be any new debugging functions, zboot one already merged
into debug_ll in this series, cps-vec-ns16550 will be merged as well,
I've got patches prepared locally but depending on my XKPHYS changes.
We have extra functionality to debug early exception as well, that will
certainly make bring-up process easier.
Thanks.
>
> Thomas.
>
> --
> Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
> good idea. [ RFC1925, 2.3 ]
--
- Jiaxun
在2023年12月20日十二月 下午9:18,Thomas Bogendoerfer写道:
> On Sun, Oct 29, 2023 at 02:53:01AM +0000, Jiaxun Yang wrote:
>> The plan is to elimiate platform specific early_printk and
>> cps-vec-ns16550 by debug_ll and earlycon.
>
> https://xkcd.com/927/ ?
>
> sorry I don't think that just another new function is good approach.
> Doing this will end up with another method for early debugging and
> all other will stay.
To summarize how are we going to handle low-level debugging after this series:
1. You are lucky enough that the problem happens after console system initialized
and you have stack working: go earlycon, or on very few old platforms with platform
early_printk
2. You are debugging zboot: debug_ll
3. You are debugging SMP bootstrap code like cps-vec: debug_ll
4. Your kernel crashed at the middle of no where before trap_init: debug_ll
Thanks
>
> Thomas.
>
> --
> Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
> good idea. [ RFC1925, 2.3 ]
--
- Jiaxun