mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/3] serial, MIPS: Add MIPS UHI semihosting support
@ 2023-10-27 18:26 Jiaxun Yang
  2023-10-27 18:26 ` [PATCH 1/3] MIPS: Add header for UHI semihosting defines Jiaxun Yang
                   ` (6 more replies)
  0 siblings, 7 replies; 10+ messages in thread
From: Jiaxun Yang @ 2023-10-27 18:26 UTC (permalink / raw)
  To: linux-mips
  Cc: linux-serial, linux-kernel, tsbogend, gregkh, jirislaby, Jiaxun Yang

Hi all,

This patchset adds support for MIPS UHI semihosting.
It has been implemented on many debugers such as MIPS CodeScape debugger
and OpenOCD.

It is also supported by QEMU's -semihosting option.

I didn't add MAINTAINERS entry for this driver because I find other
simple earlycon drivers don't have one either. Do let me know if it
should be added.

Thanks
Jiaxun

Jiaxun Yang (3):
  MIPS: Add header for UHI semihosting defines
  MIPS: zboot: Add UHI semihosting debug print support
  serial: Add an earlycon driver for MIPS UHI semihosting

 arch/mips/Kconfig.debug                |  11 +
 arch/mips/boot/compressed/Makefile     |   1 +
 arch/mips/boot/compressed/dbg-uhi.c    |  11 +
 arch/mips/boot/compressed/dbg.c        |   4 +-
 arch/mips/boot/compressed/decompress.c |   4 +
 arch/mips/include/asm/uhi.h            | 309 +++++++++++++++++++++++++
 drivers/tty/serial/Kconfig             |  13 ++
 drivers/tty/serial/Makefile            |   1 +
 drivers/tty/serial/earlycon-mips-uhi.c |  85 +++++++
 9 files changed, 437 insertions(+), 2 deletions(-)
 create mode 100644 arch/mips/boot/compressed/dbg-uhi.c
 create mode 100644 arch/mips/include/asm/uhi.h
 create mode 100644 drivers/tty/serial/earlycon-mips-uhi.c

-- 
2.34.1


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

* [PATCH 1/3] MIPS: Add header for UHI semihosting defines
  2023-10-27 18:26 [PATCH 0/3] serial, MIPS: Add MIPS UHI semihosting support Jiaxun Yang
@ 2023-10-27 18:26 ` Jiaxun Yang
  2023-10-27 18:26 ` [PATCH 2/3] MIPS: zboot: Add UHI semihosting debug print support Jiaxun Yang
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Jiaxun Yang @ 2023-10-27 18:26 UTC (permalink / raw)
  To: linux-mips
  Cc: linux-serial, linux-kernel, tsbogend, gregkh, jirislaby, Jiaxun Yang

Add a header for MIPS UHI semihosting defines.
Including calling number, data structures and functions
to do UHI calls.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 arch/mips/include/asm/uhi.h | 309 ++++++++++++++++++++++++++++++++++++
 1 file changed, 309 insertions(+)
 create mode 100644 arch/mips/include/asm/uhi.h

diff --git a/arch/mips/include/asm/uhi.h b/arch/mips/include/asm/uhi.h
new file mode 100644
index 000000000000..5e72fd5a67fb
--- /dev/null
+++ b/arch/mips/include/asm/uhi.h
@@ -0,0 +1,309 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * MIPS UHI semihosting define and helpers
+ *
+ * Based on MD01069 - Unified Hosting Interface Reference Manual
+ *
+ * Copyright (C) 2023 Jiaxun Yang <jiaxun.yang@flygoat.com>
+ */
+
+
+#ifndef _MIPS_UHI_H_
+#define _MIPS_UHI_H_
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+
+#define UHI_NR_exit		1
+#define UHI_NR_open		2
+#define UHI_NR_close		3
+#define UHI_NR_read		4
+#define UHI_NR_write		5
+#define UHI_NR_lseek		6
+#define UHI_NR_unlink		7
+#define UHI_NR_fstat		8
+#define UHI_NR_argc		9
+#define UHI_NR_argnlen		10
+#define UHI_NR_argn		11
+#define UHI_NR_plog		13
+#define UHI_NR_assert		14
+#define UHI_NR_pread		19
+#define UHI_NR_pwrite		20
+#define UHI_NR_link		22
+#define UHI_NR_bootfailure	23
+
+/* For SDDBP code and R2 */
+#define UHI_CALL_CODE		"1"
+#define UHI_CALL_CODE_RAW	1
+
+struct uhi_stat {
+	int16_t st_dev;
+	uint16_t st_ino;
+	uint32_t st_mode;
+	uint16_t st_nlink;
+	uint16_t st_uid;
+	uint16_t st_gid;
+	int16_t st_rdev;
+	uint64_t st_size;
+	uint64_t st_atime;
+	uint64_t st_spare1;
+	uint64_t st_mtime;
+	uint64_t st_spare2;
+	uint64_t st_ctime;
+	uint64_t st_spare3;
+	uint64_t st_blksize;
+	uint64_t st_blocks;
+	uint64_t st_spare4[2];
+};
+
+#define UHI_O_RDONLY	0x0
+#define UHI_O_WRONLY	0x1
+#define UHI_O_RDWR	0x2
+#define UHI_O_APPEND	0x8
+#define UHI_O_CREAT	0x200
+#define UHI_O_TRUNC	0x400
+#define UHI_O_EXCL	0x800
+
+#define UHI_EACCESS		13
+#define UHI_EAGAIN		11
+#define UHI_EBADF		9
+#define UHI_EBADMSG		77
+#define UHI_EBUSY		16
+#define UHI_ECONNRESET		104
+#define UHI_EEXIST		17
+#define UHI_EFBIG		27
+#define UHI_EINTR		4
+#define UHI_EINVAL		22
+#define UHI_EIO			5
+#define UHI_EISDIR		21
+#define UHI_ELOOP		92
+#define UHI_EMFILE		24
+#define UHI_EMLINK		31
+#define UHI_ENAMETOOLONG	91
+#define UHI_ENETDOWN		115
+#define UHI_ENETUNREACH		114
+#define UHI_ENFILE		23
+#define UHI_ENOBUFS		105
+#define UHI_ENOENT		2
+#define UHI_ENOMEM		12
+#define UHI_ENOSPC		28
+#define UHI_ENOSR		63
+#define UHI_ENOTCONN		128
+#define UHI_ENOTDIR		20
+#define UHI_ENXIO		6
+#define UHI_EOVERFLOW		139
+#define UHI_EPERM		1
+#define UHI_EPIPE		32
+#define UHI_ERANGE		34
+#define UHI_EROFS		30
+#define UHI_ESPIPE		29
+#define UHI_ETIMEDOUT		116
+#define UHI_ETXTBSY		26
+#define UHI_EWOULDBLOCK		11
+#define UHI_EXDEV		18
+
+
+struct uhi_gpctx {
+	unsigned long r[31];
+	unsigned long epc;
+	unsigned long badvaddr;
+	unsigned long hi;
+	unsigned long lo;
+	void *link;
+	uint32_t status;
+	uint32_t cause;
+	uint32_t badinstr;
+	uint32_t badpinstr;
+};
+
+static inline long __uhi_call0(long n)
+{
+	register long r2 __asm__("$2");
+	register long r25 __asm__("$25") = n;
+	register long r3 __asm__("$3");
+
+	__asm__ __volatile__ (
+		".set	push   \n"
+		".set	" MIPS_ISA_LEVEL " \n"
+		"addu $2,$0,%2 \n"
+		"sdbbp " UHI_CALL_CODE "   \n"
+		".set	pop	\n"
+		: "=&r"(r2), "=r"(r3)
+		: "ir"(UHI_CALL_CODE_RAW), "0"(r2), "r"(r25)
+		: "memory");
+
+	return r2 == -1 ? -r3 : r2;
+}
+
+static inline long __uhi_call1(long n, long a)
+{
+	register long r2 __asm__("$2");
+	register long r25 __asm__("$25") = n;
+	register long r4 __asm__("$4") = a;
+	register long r3 __asm__("$3");
+
+	__asm__ __volatile__ (
+		".set	push   \n"
+		".set	" MIPS_ISA_LEVEL " \n"
+		"addu $2,$0,%2 \n"
+		"sdbbp " UHI_CALL_CODE "   \n"
+		".set	pop	\n"
+		: "=&r"(r2), "=r"(r3)
+		: "ir"(UHI_CALL_CODE_RAW), "0"(r2), "r"(r25), "r"(r4)
+		: "memory");
+
+	return r2 == -1 ? -r3 : r2;
+}
+
+static inline long __uhi_call2(long n, long a, long b)
+{
+	register long r2 __asm__("$2");
+	register long r25 __asm__("$25") = n;
+	register long r4 __asm__("$4") = a;
+	register long r5 __asm__("$5") = b;
+	register long r3 __asm__("$3");
+
+	__asm__ __volatile__ (
+		".set	push   \n"
+		".set	" MIPS_ISA_LEVEL " \n"
+		"addu $2,$0,%2 \n"
+		"sdbbp " UHI_CALL_CODE "   \n"
+		".set	pop	\n"
+		: "=&r"(r2), "=r"(r3)
+		: "ir"(UHI_CALL_CODE_RAW), "0"(r2), "r"(r25), "r"(r4), "r"(r5)
+		: "memory");
+
+	return r2 == -1 ? -r3 : r2;
+}
+
+static inline long __uhi_call3(long n, long a, long b, long c)
+{
+	register long r2 __asm__("$2");
+	register long r25 __asm__("$25") = n;
+	register long r4 __asm__("$4") = a;
+	register long r5 __asm__("$5") = b;
+	register long r6 __asm__("$6") = c;
+	register long r3 __asm__("$3");
+
+	__asm__ __volatile__ (
+		".set	push   \n"
+		".set	" MIPS_ISA_LEVEL " \n"
+		"addu $2,$0,%2 \n"
+		"sdbbp " UHI_CALL_CODE "   \n"
+		".set	pop	\n"
+		: "=&r"(r2), "=r"(r3)
+		: "ir"(UHI_CALL_CODE_RAW), "0"(r2), "r"(r25), "r"(r4), "r"(r5), "r"(r6)
+		: "memory");
+
+	return r2 == -1 ? -r3 : r2;
+}
+
+static inline long __uhi_call4(long n, long a, long b, long c, long d)
+{
+	register long r2 __asm__("$2");
+	register long r25 __asm__("$25") = n;
+	register long r4 __asm__("$4") = a;
+	register long r5 __asm__("$5") = b;
+	register long r6 __asm__("$6") = c;
+	register long r7 __asm__("$7") = d;
+	register long r3 __asm__("$3");
+
+	__asm__ __volatile__ (
+		".set	push   \n"
+		".set	" MIPS_ISA_LEVEL " \n"
+		"addu $2,$0,%2 \n"
+		"sdbbp " UHI_CALL_CODE "   \n"
+		".set	pop	\n"
+		: "=&r"(r2), "=r"(r3)
+		: "ir"(UHI_CALL_CODE_RAW), "0"(r2), "r"(r25), "r"(r4), "r"(r5), "r"(r6), "r"(r7)
+		: "memory");
+
+	return r2 == -1 ? -r3 : r2;
+}
+
+static inline int32_t uhi_exit(int32_t code)
+{
+	return __uhi_call1(UHI_NR_exit, code);
+}
+
+static inline int32_t uhi_open(const char *path, int32_t flags, int32_t mode)
+{
+	return __uhi_call3(UHI_NR_open, (long)path, flags, mode);
+}
+
+static inline int32_t uhi_close(int32_t fd)
+{
+	return __uhi_call1(UHI_NR_close, fd);
+}
+
+static inline int32_t uhi_read(int32_t fd, char *buf, long num)
+{
+	return __uhi_call3(UHI_NR_read, fd, (long)buf, num);
+}
+
+static inline long uhi_write(int32_t fd, const char *buf, long num)
+{
+	return __uhi_call3(UHI_NR_write, fd, (long)buf, num);
+}
+
+static inline int32_t uhi_lseek(int32_t fd, long offset, int32_t whence)
+{
+	return __uhi_call3(UHI_NR_lseek, fd, offset, whence);
+}
+
+static inline int32_t uhi_unlink(const char *path)
+{
+	return __uhi_call1(UHI_NR_unlink, (long)path);
+}
+
+static inline int32_t uhi_fstat(int32_t fd, struct uhi_stat *buf)
+{
+	return __uhi_call2(UHI_NR_fstat, fd, (long)buf);
+}
+
+static inline int32_t uhi_argc(void)
+{
+	return __uhi_call0(UHI_NR_argc);
+}
+
+static inline int32_t uhi_argnlen(int32_t n)
+{
+	return __uhi_call1(UHI_NR_argnlen, n);
+}
+
+static inline int32_t uhi_argn(int32_t n, char *buf, int32_t num)
+{
+	return __uhi_call3(UHI_NR_argn, n, (long)buf, num);
+}
+
+static inline int32_t uhi_plog(const char *buf, int32_t num)
+{
+	return __uhi_call2(UHI_NR_plog, (long)buf, num);
+}
+
+static inline void uhi_assert(const char *msg, const char *file, int32_t line)
+{
+	__uhi_call3(UHI_NR_assert, (long)msg, (long)file, line);
+}
+
+static inline int32_t uhi_link(const char *oldpath, const char *newpath)
+{
+	return __uhi_call2(UHI_NR_link, (long)oldpath, (long)newpath);
+}
+
+static inline int32_t uhi_pread(int32_t fd, char *buf, long num, long offset)
+{
+	return __uhi_call4(UHI_NR_pread, fd, (long)buf, num, offset);
+}
+
+static inline int32_t uhi_pwrite(int32_t fd, const char *buf, long num, long offset)
+{
+	return __uhi_call4(UHI_NR_pwrite, fd, (long)buf, num, offset);
+}
+
+static inline void uhi_bootfailure(int reason)
+{
+	__uhi_call1(UHI_NR_bootfailure, reason);
+}
+
+#endif
-- 
2.34.1


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

* [PATCH 2/3] MIPS: zboot: Add UHI semihosting debug print support
  2023-10-27 18:26 [PATCH 0/3] serial, MIPS: Add MIPS UHI semihosting support Jiaxun Yang
  2023-10-27 18:26 ` [PATCH 1/3] MIPS: Add header for UHI semihosting defines Jiaxun Yang
@ 2023-10-27 18:26 ` Jiaxun Yang
  2023-10-27 18:26 ` [PATCH 3/3] serial: Add an earlycon driver for MIPS UHI semihosting Jiaxun Yang
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Jiaxun Yang @ 2023-10-27 18:26 UTC (permalink / raw)
  To: linux-mips
  Cc: linux-serial, linux-kernel, tsbogend, gregkh, jirislaby, Jiaxun Yang

Support print debug message via MIPS UHI semihosting Plog
functions.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 arch/mips/Kconfig.debug                | 11 +++++++++++
 arch/mips/boot/compressed/Makefile     |  1 +
 arch/mips/boot/compressed/dbg-uhi.c    | 11 +++++++++++
 arch/mips/boot/compressed/dbg.c        |  4 ++--
 arch/mips/boot/compressed/decompress.c |  4 ++++
 5 files changed, 29 insertions(+), 2 deletions(-)
 create mode 100644 arch/mips/boot/compressed/dbg-uhi.c

diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug
index f4ae7900fcd3..1393bdb33f5c 100644
--- a/arch/mips/Kconfig.debug
+++ b/arch/mips/Kconfig.debug
@@ -98,6 +98,17 @@ config DEBUG_ZBOOT
 	  to reduce the kernel image size and speed up the booting procedure a
 	  little.
 
+config ZBOOT_DBG_UHI
+	bool "Enable UHI debugging"
+	depends on DEBUG_ZBOOT
+	default n
+	help
+	  Enable this option to debug compressed kernel support via UHI.
+	  Logs will be outputed to the host machine via UHI Plog function.
+	  You MUST connect system to a debugger with UHI semihosting support
+	  or use a boot montor implemented UHI exceptions, otherwise the
+	  system will hang.
+
 config ZBOOT_INGENIC_UART
 	int "UART to use for compressed kernel debugging"
 	depends on DEBUG_ZBOOT && MACH_INGENIC_SOC
diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile
index 6cc28173bee8..5667597c3584 100644
--- a/arch/mips/boot/compressed/Makefile
+++ b/arch/mips/boot/compressed/Makefile
@@ -45,6 +45,7 @@ vmlinuzobjs-y := $(obj)/head.o $(obj)/decompress.o $(obj)/string.o $(obj)/bswaps
 
 ifdef CONFIG_DEBUG_ZBOOT
 vmlinuzobjs-$(CONFIG_DEBUG_ZBOOT)		   += $(obj)/dbg.o
+vmlinuzobjs-$(CONFIG_ZBOOT_DBG_UHI)		   += $(obj)/dbg-uhi.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
diff --git a/arch/mips/boot/compressed/dbg-uhi.c b/arch/mips/boot/compressed/dbg-uhi.c
new file mode 100644
index 000000000000..7daa8de717b0
--- /dev/null
+++ b/arch/mips/boot/compressed/dbg-uhi.c
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * zboot debug output for MIPS UHI semihosting
+ */
+
+#include <asm/uhi.h>
+
+void puts(const char *s)
+{
+	uhi_plog(s, 0);
+}
diff --git a/arch/mips/boot/compressed/dbg.c b/arch/mips/boot/compressed/dbg.c
index f6728a8fd1c3..7fa5242e2b7d 100644
--- a/arch/mips/boot/compressed/dbg.c
+++ b/arch/mips/boot/compressed/dbg.c
@@ -4,7 +4,7 @@
  *
  * 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().
+ * need to implement your own putc() or puts().
  */
 #include <linux/compiler.h>
 #include <linux/types.h>
@@ -13,7 +13,7 @@ void __weak putc(char c)
 {
 }
 
-void puts(const char *s)
+void __weak puts(const char *s)
 {
 	char c;
 	while ((c = *s++) != '\0') {
diff --git a/arch/mips/boot/compressed/decompress.c b/arch/mips/boot/compressed/decompress.c
index c5dd415254d3..f4e69dfe2923 100644
--- a/arch/mips/boot/compressed/decompress.c
+++ b/arch/mips/boot/compressed/decompress.c
@@ -17,6 +17,7 @@
 
 #include <asm/addrspace.h>
 #include <asm/unaligned.h>
+#include <asm/uhi.h>
 #include <asm-generic/vmlinux.lds.h>
 
 /*
@@ -46,6 +47,9 @@ void error(char *x)
 	puts(x);
 	puts("\n\n -- System halted");
 
+#ifdef CONFIG_ZBOOT_DBG_UHI
+	uhi_bootfailure(0);
+#endif
 	while (1)
 		;	/* Halt */
 }
-- 
2.34.1


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

* [PATCH 3/3] serial: Add an earlycon driver for MIPS UHI semihosting
  2023-10-27 18:26 [PATCH 0/3] serial, MIPS: Add MIPS UHI semihosting support Jiaxun Yang
  2023-10-27 18:26 ` [PATCH 1/3] MIPS: Add header for UHI semihosting defines Jiaxun Yang
  2023-10-27 18:26 ` [PATCH 2/3] MIPS: zboot: Add UHI semihosting debug print support Jiaxun Yang
@ 2023-10-27 18:26 ` Jiaxun Yang
  2023-10-27 18:26 ` [PATCH 0/3] serial, MIPS: Add MIPS UHI semihosting support Jiaxun Yang
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Jiaxun Yang @ 2023-10-27 18:26 UTC (permalink / raw)
  To: linux-mips
  Cc: linux-serial, linux-kernel, tsbogend, gregkh, jirislaby, Jiaxun Yang

UHI is MIPS's implementation of semihosting.
Add an earlycon driver to help with debugging on boot.

This driver is capable for print log using UHI's "Plog" or interact
with KGDB using UHI's stdio function.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 drivers/tty/serial/Kconfig             | 13 ++++
 drivers/tty/serial/Makefile            |  1 +
 drivers/tty/serial/earlycon-mips-uhi.c | 85 ++++++++++++++++++++++++++
 3 files changed, 99 insertions(+)
 create mode 100644 drivers/tty/serial/earlycon-mips-uhi.c

diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index bdc568a4ab66..04c62c6b45cd 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -85,6 +85,19 @@ config SERIAL_EARLYCON_SEMIHOST
 	  This is enabled with "earlycon=smh" on the kernel command line.
 	  The console is enabled when early_param is processed.
 
+config SERIAL_EARLYCON_UHI
+	bool "Early console using MIPS UHI semihosting"
+	depends on MIPS
+	select SERIAL_CORE
+	select SERIAL_CORE_CONSOLE
+	select SERIAL_EARLYCON
+	help
+	  Support for early debug console using UHI semihosting.
+	  This enables the console before standard serial driver is probed.
+	  This is enabled with "earlycon=uhi" or "earlycon=uhi_stdio" on the
+	  kernel command line.
+	  The console is enabled when early_param is processed.
+
 config SERIAL_EARLYCON_RISCV_SBI
 	bool "Early console using RISC-V SBI"
 	depends on RISCV_SBI_V01
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index f6b8c220dcfb..ef5e9c87aea1 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -9,6 +9,7 @@ serial_base-y := serial_core.o serial_base_bus.o serial_ctrl.o serial_port.o
 obj-$(CONFIG_SERIAL_EARLYCON) += earlycon.o
 obj-$(CONFIG_SERIAL_EARLYCON_SEMIHOST) += earlycon-semihost.o
 obj-$(CONFIG_SERIAL_EARLYCON_RISCV_SBI) += earlycon-riscv-sbi.o
+obj-$(CONFIG_SERIAL_EARLYCON_MIPS_UHI) += earlycon-mips-uhi.o
 
 # These Sparc drivers have to appear before others such as 8250
 # which share ttySx minor node space.  Otherwise console device
diff --git a/drivers/tty/serial/earlycon-mips-uhi.c b/drivers/tty/serial/earlycon-mips-uhi.c
new file mode 100644
index 000000000000..002bb2c37064
--- /dev/null
+++ b/drivers/tty/serial/earlycon-mips-uhi.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MIPS UHI semihosting based earlycon
+ *
+ * Copyright (C) 2023 Jiaxun Yang <jiaxun.yang@flygoat.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <asm/uhi.h>
+
+static int stdin_fd = -1;
+static int stdout_fd = -1;
+
+static void uhi_plog_write(struct console *con, const char *s, unsigned int n)
+{
+	uhi_plog(s, 0);
+}
+
+static void uhi_stdout_write(struct console *con, const char *s, unsigned int n)
+{
+	if (stdout_fd < 0)
+		return;
+
+	uhi_write(stdout_fd, s, n);
+}
+
+#ifdef CONFIG_CONSOLE_POLL
+static int uhi_stdin_read(struct console *con, char *s, unsigned int n)
+{
+	if (stdin_fd < 0)
+		return 0;
+
+	return uhi_read(stdin_fd, s, n);
+}
+#endif
+
+static int uhi_stdio_fd_open(struct console *co, char *options)
+{
+	/*
+	 * You have to open both stdin and stdout to get console work
+	 * properly on some old CodeScape debugger.
+	 */
+	stdin_fd = uhi_open("/dev/stdin", UHI_O_RDONLY, 0);
+	stdout_fd = uhi_open("/dev/stdout", UHI_O_WRONLY, 0);
+
+	return (stdin_fd < 0 || stdout_fd < 0) ? -ENODEV : 0;
+}
+
+static int uhi_stdio_fd_close(struct console *co)
+{
+	int ret1 = 0, ret2 = 0;
+
+	if (stdin_fd >= 0)
+		ret1 = uhi_close(stdin_fd);
+	if (stdout_fd >= 0)
+		ret2 = uhi_close(stdout_fd);
+
+	return (ret1 < 0 || ret2 < 0) ? -ENODEV : 0;
+}
+
+static int
+__init early_uhi_setup(struct earlycon_device *device, const char *opt)
+{
+	device->con->write = uhi_plog_write;
+	return 0;
+}
+
+static int
+__init early_uhi_stdio_setup(struct earlycon_device *device, const char *opt)
+{
+
+	device->con->setup = uhi_stdio_fd_open;
+	device->con->exit = uhi_stdio_fd_close;
+	device->con->write = uhi_stdout_write;
+#ifdef CONFIG_CONSOLE_POLL
+	device->con->read = uhi_stdin_read;
+#endif
+	return 0;
+}
+
+EARLYCON_DECLARE(uhi, early_uhi_setup);
+EARLYCON_DECLARE(uhi_stdio, early_uhi_stdio_setup);
-- 
2.34.1


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

* [PATCH 0/3] serial, MIPS: Add MIPS UHI semihosting support
  2023-10-27 18:26 [PATCH 0/3] serial, MIPS: Add MIPS UHI semihosting support Jiaxun Yang
                   ` (2 preceding siblings ...)
  2023-10-27 18:26 ` [PATCH 3/3] serial: Add an earlycon driver for MIPS UHI semihosting Jiaxun Yang
@ 2023-10-27 18:26 ` Jiaxun Yang
  2023-10-27 18:26 ` [PATCH 1/3] MIPS: Add header for UHI semihosting defines Jiaxun Yang
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Jiaxun Yang @ 2023-10-27 18:26 UTC (permalink / raw)
  To: linux-mips
  Cc: linux-serial, linux-kernel, tsbogend, gregkh, jirislaby, Jiaxun Yang

Hi all,

This patchset adds support for MIPS UHI semihosting.
It has been implemented on many debugers such as MIPS CodeScape debugger
and OpenOCD.

It is also supported by QEMU's -semihosting option.

I didn't add MAINTAINERS entry for this driver because I find other
simple earlycon drivers don't have one either. Do let me know if it
should be added.

Thanks
Jiaxun

Jiaxun Yang (3):
  MIPS: Add header for UHI semihosting defines
  MIPS: zboot: Add UHI semihosting debug print support
  serial: Add an earlycon driver for MIPS UHI semihosting

 arch/mips/Kconfig.debug                |  11 +
 arch/mips/boot/compressed/Makefile     |   1 +
 arch/mips/boot/compressed/dbg-uhi.c    |  11 +
 arch/mips/boot/compressed/dbg.c        |   4 +-
 arch/mips/boot/compressed/decompress.c |   4 +
 arch/mips/include/asm/uhi.h            | 309 +++++++++++++++++++++++++
 drivers/tty/serial/Kconfig             |  13 ++
 drivers/tty/serial/Makefile            |   1 +
 drivers/tty/serial/earlycon-mips-uhi.c |  85 +++++++
 9 files changed, 437 insertions(+), 2 deletions(-)
 create mode 100644 arch/mips/boot/compressed/dbg-uhi.c
 create mode 100644 arch/mips/include/asm/uhi.h
 create mode 100644 drivers/tty/serial/earlycon-mips-uhi.c

-- 
2.34.1


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

* [PATCH 1/3] MIPS: Add header for UHI semihosting defines
  2023-10-27 18:26 [PATCH 0/3] serial, MIPS: Add MIPS UHI semihosting support Jiaxun Yang
                   ` (3 preceding siblings ...)
  2023-10-27 18:26 ` [PATCH 0/3] serial, MIPS: Add MIPS UHI semihosting support Jiaxun Yang
@ 2023-10-27 18:26 ` Jiaxun Yang
  2023-10-27 18:26 ` [PATCH 2/3] MIPS: zboot: Add UHI semihosting debug print support Jiaxun Yang
  2023-10-27 18:26 ` [PATCH 3/3] serial: Add an earlycon driver for MIPS UHI semihosting Jiaxun Yang
  6 siblings, 0 replies; 10+ messages in thread
From: Jiaxun Yang @ 2023-10-27 18:26 UTC (permalink / raw)
  To: linux-mips
  Cc: linux-serial, linux-kernel, tsbogend, gregkh, jirislaby, Jiaxun Yang

Add a header for MIPS UHI semihosting defines.
Including calling number, data structures and functions
to do UHI calls.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 arch/mips/include/asm/uhi.h | 309 ++++++++++++++++++++++++++++++++++++
 1 file changed, 309 insertions(+)
 create mode 100644 arch/mips/include/asm/uhi.h

diff --git a/arch/mips/include/asm/uhi.h b/arch/mips/include/asm/uhi.h
new file mode 100644
index 000000000000..5e72fd5a67fb
--- /dev/null
+++ b/arch/mips/include/asm/uhi.h
@@ -0,0 +1,309 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * MIPS UHI semihosting define and helpers
+ *
+ * Based on MD01069 - Unified Hosting Interface Reference Manual
+ *
+ * Copyright (C) 2023 Jiaxun Yang <jiaxun.yang@flygoat.com>
+ */
+
+
+#ifndef _MIPS_UHI_H_
+#define _MIPS_UHI_H_
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+
+#define UHI_NR_exit		1
+#define UHI_NR_open		2
+#define UHI_NR_close		3
+#define UHI_NR_read		4
+#define UHI_NR_write		5
+#define UHI_NR_lseek		6
+#define UHI_NR_unlink		7
+#define UHI_NR_fstat		8
+#define UHI_NR_argc		9
+#define UHI_NR_argnlen		10
+#define UHI_NR_argn		11
+#define UHI_NR_plog		13
+#define UHI_NR_assert		14
+#define UHI_NR_pread		19
+#define UHI_NR_pwrite		20
+#define UHI_NR_link		22
+#define UHI_NR_bootfailure	23
+
+/* For SDDBP code and R2 */
+#define UHI_CALL_CODE		"1"
+#define UHI_CALL_CODE_RAW	1
+
+struct uhi_stat {
+	int16_t st_dev;
+	uint16_t st_ino;
+	uint32_t st_mode;
+	uint16_t st_nlink;
+	uint16_t st_uid;
+	uint16_t st_gid;
+	int16_t st_rdev;
+	uint64_t st_size;
+	uint64_t st_atime;
+	uint64_t st_spare1;
+	uint64_t st_mtime;
+	uint64_t st_spare2;
+	uint64_t st_ctime;
+	uint64_t st_spare3;
+	uint64_t st_blksize;
+	uint64_t st_blocks;
+	uint64_t st_spare4[2];
+};
+
+#define UHI_O_RDONLY	0x0
+#define UHI_O_WRONLY	0x1
+#define UHI_O_RDWR	0x2
+#define UHI_O_APPEND	0x8
+#define UHI_O_CREAT	0x200
+#define UHI_O_TRUNC	0x400
+#define UHI_O_EXCL	0x800
+
+#define UHI_EACCESS		13
+#define UHI_EAGAIN		11
+#define UHI_EBADF		9
+#define UHI_EBADMSG		77
+#define UHI_EBUSY		16
+#define UHI_ECONNRESET		104
+#define UHI_EEXIST		17
+#define UHI_EFBIG		27
+#define UHI_EINTR		4
+#define UHI_EINVAL		22
+#define UHI_EIO			5
+#define UHI_EISDIR		21
+#define UHI_ELOOP		92
+#define UHI_EMFILE		24
+#define UHI_EMLINK		31
+#define UHI_ENAMETOOLONG	91
+#define UHI_ENETDOWN		115
+#define UHI_ENETUNREACH		114
+#define UHI_ENFILE		23
+#define UHI_ENOBUFS		105
+#define UHI_ENOENT		2
+#define UHI_ENOMEM		12
+#define UHI_ENOSPC		28
+#define UHI_ENOSR		63
+#define UHI_ENOTCONN		128
+#define UHI_ENOTDIR		20
+#define UHI_ENXIO		6
+#define UHI_EOVERFLOW		139
+#define UHI_EPERM		1
+#define UHI_EPIPE		32
+#define UHI_ERANGE		34
+#define UHI_EROFS		30
+#define UHI_ESPIPE		29
+#define UHI_ETIMEDOUT		116
+#define UHI_ETXTBSY		26
+#define UHI_EWOULDBLOCK		11
+#define UHI_EXDEV		18
+
+
+struct uhi_gpctx {
+	unsigned long r[31];
+	unsigned long epc;
+	unsigned long badvaddr;
+	unsigned long hi;
+	unsigned long lo;
+	void *link;
+	uint32_t status;
+	uint32_t cause;
+	uint32_t badinstr;
+	uint32_t badpinstr;
+};
+
+static inline long __uhi_call0(long n)
+{
+	register long r2 __asm__("$2");
+	register long r25 __asm__("$25") = n;
+	register long r3 __asm__("$3");
+
+	__asm__ __volatile__ (
+		".set	push   \n"
+		".set	" MIPS_ISA_LEVEL " \n"
+		"addu $2,$0,%2 \n"
+		"sdbbp " UHI_CALL_CODE "   \n"
+		".set	pop	\n"
+		: "=&r"(r2), "=r"(r3)
+		: "ir"(UHI_CALL_CODE_RAW), "0"(r2), "r"(r25)
+		: "memory");
+
+	return r2 == -1 ? -r3 : r2;
+}
+
+static inline long __uhi_call1(long n, long a)
+{
+	register long r2 __asm__("$2");
+	register long r25 __asm__("$25") = n;
+	register long r4 __asm__("$4") = a;
+	register long r3 __asm__("$3");
+
+	__asm__ __volatile__ (
+		".set	push   \n"
+		".set	" MIPS_ISA_LEVEL " \n"
+		"addu $2,$0,%2 \n"
+		"sdbbp " UHI_CALL_CODE "   \n"
+		".set	pop	\n"
+		: "=&r"(r2), "=r"(r3)
+		: "ir"(UHI_CALL_CODE_RAW), "0"(r2), "r"(r25), "r"(r4)
+		: "memory");
+
+	return r2 == -1 ? -r3 : r2;
+}
+
+static inline long __uhi_call2(long n, long a, long b)
+{
+	register long r2 __asm__("$2");
+	register long r25 __asm__("$25") = n;
+	register long r4 __asm__("$4") = a;
+	register long r5 __asm__("$5") = b;
+	register long r3 __asm__("$3");
+
+	__asm__ __volatile__ (
+		".set	push   \n"
+		".set	" MIPS_ISA_LEVEL " \n"
+		"addu $2,$0,%2 \n"
+		"sdbbp " UHI_CALL_CODE "   \n"
+		".set	pop	\n"
+		: "=&r"(r2), "=r"(r3)
+		: "ir"(UHI_CALL_CODE_RAW), "0"(r2), "r"(r25), "r"(r4), "r"(r5)
+		: "memory");
+
+	return r2 == -1 ? -r3 : r2;
+}
+
+static inline long __uhi_call3(long n, long a, long b, long c)
+{
+	register long r2 __asm__("$2");
+	register long r25 __asm__("$25") = n;
+	register long r4 __asm__("$4") = a;
+	register long r5 __asm__("$5") = b;
+	register long r6 __asm__("$6") = c;
+	register long r3 __asm__("$3");
+
+	__asm__ __volatile__ (
+		".set	push   \n"
+		".set	" MIPS_ISA_LEVEL " \n"
+		"addu $2,$0,%2 \n"
+		"sdbbp " UHI_CALL_CODE "   \n"
+		".set	pop	\n"
+		: "=&r"(r2), "=r"(r3)
+		: "ir"(UHI_CALL_CODE_RAW), "0"(r2), "r"(r25), "r"(r4), "r"(r5), "r"(r6)
+		: "memory");
+
+	return r2 == -1 ? -r3 : r2;
+}
+
+static inline long __uhi_call4(long n, long a, long b, long c, long d)
+{
+	register long r2 __asm__("$2");
+	register long r25 __asm__("$25") = n;
+	register long r4 __asm__("$4") = a;
+	register long r5 __asm__("$5") = b;
+	register long r6 __asm__("$6") = c;
+	register long r7 __asm__("$7") = d;
+	register long r3 __asm__("$3");
+
+	__asm__ __volatile__ (
+		".set	push   \n"
+		".set	" MIPS_ISA_LEVEL " \n"
+		"addu $2,$0,%2 \n"
+		"sdbbp " UHI_CALL_CODE "   \n"
+		".set	pop	\n"
+		: "=&r"(r2), "=r"(r3)
+		: "ir"(UHI_CALL_CODE_RAW), "0"(r2), "r"(r25), "r"(r4), "r"(r5), "r"(r6), "r"(r7)
+		: "memory");
+
+	return r2 == -1 ? -r3 : r2;
+}
+
+static inline int32_t uhi_exit(int32_t code)
+{
+	return __uhi_call1(UHI_NR_exit, code);
+}
+
+static inline int32_t uhi_open(const char *path, int32_t flags, int32_t mode)
+{
+	return __uhi_call3(UHI_NR_open, (long)path, flags, mode);
+}
+
+static inline int32_t uhi_close(int32_t fd)
+{
+	return __uhi_call1(UHI_NR_close, fd);
+}
+
+static inline int32_t uhi_read(int32_t fd, char *buf, long num)
+{
+	return __uhi_call3(UHI_NR_read, fd, (long)buf, num);
+}
+
+static inline long uhi_write(int32_t fd, const char *buf, long num)
+{
+	return __uhi_call3(UHI_NR_write, fd, (long)buf, num);
+}
+
+static inline int32_t uhi_lseek(int32_t fd, long offset, int32_t whence)
+{
+	return __uhi_call3(UHI_NR_lseek, fd, offset, whence);
+}
+
+static inline int32_t uhi_unlink(const char *path)
+{
+	return __uhi_call1(UHI_NR_unlink, (long)path);
+}
+
+static inline int32_t uhi_fstat(int32_t fd, struct uhi_stat *buf)
+{
+	return __uhi_call2(UHI_NR_fstat, fd, (long)buf);
+}
+
+static inline int32_t uhi_argc(void)
+{
+	return __uhi_call0(UHI_NR_argc);
+}
+
+static inline int32_t uhi_argnlen(int32_t n)
+{
+	return __uhi_call1(UHI_NR_argnlen, n);
+}
+
+static inline int32_t uhi_argn(int32_t n, char *buf, int32_t num)
+{
+	return __uhi_call3(UHI_NR_argn, n, (long)buf, num);
+}
+
+static inline int32_t uhi_plog(const char *buf, int32_t num)
+{
+	return __uhi_call2(UHI_NR_plog, (long)buf, num);
+}
+
+static inline void uhi_assert(const char *msg, const char *file, int32_t line)
+{
+	__uhi_call3(UHI_NR_assert, (long)msg, (long)file, line);
+}
+
+static inline int32_t uhi_link(const char *oldpath, const char *newpath)
+{
+	return __uhi_call2(UHI_NR_link, (long)oldpath, (long)newpath);
+}
+
+static inline int32_t uhi_pread(int32_t fd, char *buf, long num, long offset)
+{
+	return __uhi_call4(UHI_NR_pread, fd, (long)buf, num, offset);
+}
+
+static inline int32_t uhi_pwrite(int32_t fd, const char *buf, long num, long offset)
+{
+	return __uhi_call4(UHI_NR_pwrite, fd, (long)buf, num, offset);
+}
+
+static inline void uhi_bootfailure(int reason)
+{
+	__uhi_call1(UHI_NR_bootfailure, reason);
+}
+
+#endif
-- 
2.34.1


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

* [PATCH 2/3] MIPS: zboot: Add UHI semihosting debug print support
  2023-10-27 18:26 [PATCH 0/3] serial, MIPS: Add MIPS UHI semihosting support Jiaxun Yang
                   ` (4 preceding siblings ...)
  2023-10-27 18:26 ` [PATCH 1/3] MIPS: Add header for UHI semihosting defines Jiaxun Yang
@ 2023-10-27 18:26 ` Jiaxun Yang
  2023-10-31 21:49   ` kernel test robot
  2023-10-27 18:26 ` [PATCH 3/3] serial: Add an earlycon driver for MIPS UHI semihosting Jiaxun Yang
  6 siblings, 1 reply; 10+ messages in thread
From: Jiaxun Yang @ 2023-10-27 18:26 UTC (permalink / raw)
  To: linux-mips
  Cc: linux-serial, linux-kernel, tsbogend, gregkh, jirislaby, Jiaxun Yang

Support print debug message via MIPS UHI semihosting Plog
functions.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 arch/mips/Kconfig.debug                | 11 +++++++++++
 arch/mips/boot/compressed/Makefile     |  1 +
 arch/mips/boot/compressed/dbg-uhi.c    | 11 +++++++++++
 arch/mips/boot/compressed/dbg.c        |  4 ++--
 arch/mips/boot/compressed/decompress.c |  4 ++++
 5 files changed, 29 insertions(+), 2 deletions(-)
 create mode 100644 arch/mips/boot/compressed/dbg-uhi.c

diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug
index f4ae7900fcd3..1393bdb33f5c 100644
--- a/arch/mips/Kconfig.debug
+++ b/arch/mips/Kconfig.debug
@@ -98,6 +98,17 @@ config DEBUG_ZBOOT
 	  to reduce the kernel image size and speed up the booting procedure a
 	  little.
 
+config ZBOOT_DBG_UHI
+	bool "Enable UHI debugging"
+	depends on DEBUG_ZBOOT
+	default n
+	help
+	  Enable this option to debug compressed kernel support via UHI.
+	  Logs will be outputed to the host machine via UHI Plog function.
+	  You MUST connect system to a debugger with UHI semihosting support
+	  or use a boot montor implemented UHI exceptions, otherwise the
+	  system will hang.
+
 config ZBOOT_INGENIC_UART
 	int "UART to use for compressed kernel debugging"
 	depends on DEBUG_ZBOOT && MACH_INGENIC_SOC
diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile
index 6cc28173bee8..5667597c3584 100644
--- a/arch/mips/boot/compressed/Makefile
+++ b/arch/mips/boot/compressed/Makefile
@@ -45,6 +45,7 @@ vmlinuzobjs-y := $(obj)/head.o $(obj)/decompress.o $(obj)/string.o $(obj)/bswaps
 
 ifdef CONFIG_DEBUG_ZBOOT
 vmlinuzobjs-$(CONFIG_DEBUG_ZBOOT)		   += $(obj)/dbg.o
+vmlinuzobjs-$(CONFIG_ZBOOT_DBG_UHI)		   += $(obj)/dbg-uhi.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
diff --git a/arch/mips/boot/compressed/dbg-uhi.c b/arch/mips/boot/compressed/dbg-uhi.c
new file mode 100644
index 000000000000..7daa8de717b0
--- /dev/null
+++ b/arch/mips/boot/compressed/dbg-uhi.c
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * zboot debug output for MIPS UHI semihosting
+ */
+
+#include <asm/uhi.h>
+
+void puts(const char *s)
+{
+	uhi_plog(s, 0);
+}
diff --git a/arch/mips/boot/compressed/dbg.c b/arch/mips/boot/compressed/dbg.c
index f6728a8fd1c3..7fa5242e2b7d 100644
--- a/arch/mips/boot/compressed/dbg.c
+++ b/arch/mips/boot/compressed/dbg.c
@@ -4,7 +4,7 @@
  *
  * 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().
+ * need to implement your own putc() or puts().
  */
 #include <linux/compiler.h>
 #include <linux/types.h>
@@ -13,7 +13,7 @@ void __weak putc(char c)
 {
 }
 
-void puts(const char *s)
+void __weak puts(const char *s)
 {
 	char c;
 	while ((c = *s++) != '\0') {
diff --git a/arch/mips/boot/compressed/decompress.c b/arch/mips/boot/compressed/decompress.c
index c5dd415254d3..f4e69dfe2923 100644
--- a/arch/mips/boot/compressed/decompress.c
+++ b/arch/mips/boot/compressed/decompress.c
@@ -17,6 +17,7 @@
 
 #include <asm/addrspace.h>
 #include <asm/unaligned.h>
+#include <asm/uhi.h>
 #include <asm-generic/vmlinux.lds.h>
 
 /*
@@ -46,6 +47,9 @@ void error(char *x)
 	puts(x);
 	puts("\n\n -- System halted");
 
+#ifdef CONFIG_ZBOOT_DBG_UHI
+	uhi_bootfailure(0);
+#endif
 	while (1)
 		;	/* Halt */
 }
-- 
2.34.1


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

* [PATCH 3/3] serial: Add an earlycon driver for MIPS UHI semihosting
  2023-10-27 18:26 [PATCH 0/3] serial, MIPS: Add MIPS UHI semihosting support Jiaxun Yang
                   ` (5 preceding siblings ...)
  2023-10-27 18:26 ` [PATCH 2/3] MIPS: zboot: Add UHI semihosting debug print support Jiaxun Yang
@ 2023-10-27 18:26 ` Jiaxun Yang
  2023-10-27 20:48   ` Jiaxun Yang
  6 siblings, 1 reply; 10+ messages in thread
From: Jiaxun Yang @ 2023-10-27 18:26 UTC (permalink / raw)
  To: linux-mips
  Cc: linux-serial, linux-kernel, tsbogend, gregkh, jirislaby, Jiaxun Yang

UHI is MIPS's implementation of semihosting.
Add an earlycon driver to help with debugging on boot.

This driver is capable for print log using UHI's "Plog" or interact
with KGDB using UHI's stdio function.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 drivers/tty/serial/Kconfig             | 13 ++++
 drivers/tty/serial/Makefile            |  1 +
 drivers/tty/serial/earlycon-mips-uhi.c | 85 ++++++++++++++++++++++++++
 3 files changed, 99 insertions(+)
 create mode 100644 drivers/tty/serial/earlycon-mips-uhi.c

diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index bdc568a4ab66..04c62c6b45cd 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -85,6 +85,19 @@ config SERIAL_EARLYCON_SEMIHOST
 	  This is enabled with "earlycon=smh" on the kernel command line.
 	  The console is enabled when early_param is processed.
 
+config SERIAL_EARLYCON_UHI
+	bool "Early console using MIPS UHI semihosting"
+	depends on MIPS
+	select SERIAL_CORE
+	select SERIAL_CORE_CONSOLE
+	select SERIAL_EARLYCON
+	help
+	  Support for early debug console using UHI semihosting.
+	  This enables the console before standard serial driver is probed.
+	  This is enabled with "earlycon=uhi" or "earlycon=uhi_stdio" on the
+	  kernel command line.
+	  The console is enabled when early_param is processed.
+
 config SERIAL_EARLYCON_RISCV_SBI
 	bool "Early console using RISC-V SBI"
 	depends on RISCV_SBI_V01
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index f6b8c220dcfb..ef5e9c87aea1 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -9,6 +9,7 @@ serial_base-y := serial_core.o serial_base_bus.o serial_ctrl.o serial_port.o
 obj-$(CONFIG_SERIAL_EARLYCON) += earlycon.o
 obj-$(CONFIG_SERIAL_EARLYCON_SEMIHOST) += earlycon-semihost.o
 obj-$(CONFIG_SERIAL_EARLYCON_RISCV_SBI) += earlycon-riscv-sbi.o
+obj-$(CONFIG_SERIAL_EARLYCON_MIPS_UHI) += earlycon-mips-uhi.o
 
 # These Sparc drivers have to appear before others such as 8250
 # which share ttySx minor node space.  Otherwise console device
diff --git a/drivers/tty/serial/earlycon-mips-uhi.c b/drivers/tty/serial/earlycon-mips-uhi.c
new file mode 100644
index 000000000000..002bb2c37064
--- /dev/null
+++ b/drivers/tty/serial/earlycon-mips-uhi.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MIPS UHI semihosting based earlycon
+ *
+ * Copyright (C) 2023 Jiaxun Yang <jiaxun.yang@flygoat.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <asm/uhi.h>
+
+static int stdin_fd = -1;
+static int stdout_fd = -1;
+
+static void uhi_plog_write(struct console *con, const char *s, unsigned int n)
+{
+	uhi_plog(s, 0);
+}
+
+static void uhi_stdout_write(struct console *con, const char *s, unsigned int n)
+{
+	if (stdout_fd < 0)
+		return;
+
+	uhi_write(stdout_fd, s, n);
+}
+
+#ifdef CONFIG_CONSOLE_POLL
+static int uhi_stdin_read(struct console *con, char *s, unsigned int n)
+{
+	if (stdin_fd < 0)
+		return 0;
+
+	return uhi_read(stdin_fd, s, n);
+}
+#endif
+
+static int uhi_stdio_fd_open(struct console *co, char *options)
+{
+	/*
+	 * You have to open both stdin and stdout to get console work
+	 * properly on some old CodeScape debugger.
+	 */
+	stdin_fd = uhi_open("/dev/stdin", UHI_O_RDONLY, 0);
+	stdout_fd = uhi_open("/dev/stdout", UHI_O_WRONLY, 0);
+
+	return (stdin_fd < 0 || stdout_fd < 0) ? -ENODEV : 0;
+}
+
+static int uhi_stdio_fd_close(struct console *co)
+{
+	int ret1 = 0, ret2 = 0;
+
+	if (stdin_fd >= 0)
+		ret1 = uhi_close(stdin_fd);
+	if (stdout_fd >= 0)
+		ret2 = uhi_close(stdout_fd);
+
+	return (ret1 < 0 || ret2 < 0) ? -ENODEV : 0;
+}
+
+static int
+__init early_uhi_setup(struct earlycon_device *device, const char *opt)
+{
+	device->con->write = uhi_plog_write;
+	return 0;
+}
+
+static int
+__init early_uhi_stdio_setup(struct earlycon_device *device, const char *opt)
+{
+
+	device->con->setup = uhi_stdio_fd_open;
+	device->con->exit = uhi_stdio_fd_close;
+	device->con->write = uhi_stdout_write;
+#ifdef CONFIG_CONSOLE_POLL
+	device->con->read = uhi_stdin_read;
+#endif
+	return 0;
+}
+
+EARLYCON_DECLARE(uhi, early_uhi_setup);
+EARLYCON_DECLARE(uhi_stdio, early_uhi_stdio_setup);
-- 
2.34.1


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

* Re: [PATCH 3/3] serial: Add an earlycon driver for MIPS UHI semihosting
  2023-10-27 18:26 ` [PATCH 3/3] serial: Add an earlycon driver for MIPS UHI semihosting Jiaxun Yang
@ 2023-10-27 20:48   ` Jiaxun Yang
  0 siblings, 0 replies; 10+ messages in thread
From: Jiaxun Yang @ 2023-10-27 20:48 UTC (permalink / raw)
  To: linux-mips
  Cc: linux-serial, linux-kernel, Thomas Bogendoerfer,
	Greg Kroah-Hartman, jirislaby



在2023年10月27日十月 下午7:26,Jiaxun Yang写道:
> UHI is MIPS's implementation of semihosting.
> Add an earlycon driver to help with debugging on boot.
>
> This driver is capable for print log using UHI's "Plog" or interact
> with KGDB using UHI's stdio function.
>
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
>  drivers/tty/serial/Kconfig             | 13 ++++
>  drivers/tty/serial/Makefile            |  1 +
>  drivers/tty/serial/earlycon-mips-uhi.c | 85 ++++++++++++++++++++++++++
>  3 files changed, 99 insertions(+)
>  create mode 100644 drivers/tty/serial/earlycon-mips-uhi.c
>
> diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
> index bdc568a4ab66..04c62c6b45cd 100644
> --- a/drivers/tty/serial/Kconfig
> +++ b/drivers/tty/serial/Kconfig
> @@ -85,6 +85,19 @@ config SERIAL_EARLYCON_SEMIHOST
>  	  This is enabled with "earlycon=smh" on the kernel command line.
>  	  The console is enabled when early_param is processed.
> 
> +config SERIAL_EARLYCON_UHI

^ Oops there is a symbol name mismatch, will fix in v2.

Sorry for the noise.

Thanks
- Jiaxun

> +	bool "Early console using MIPS UHI semihosting"
> +	depends on MIPS
> +	select SERIAL_CORE
> +	select SERIAL_CORE_CONSOLE
> +	select SERIAL_EARLYCON
> +	help
> +	  Support for early debug console using UHI semihosting.
> +	  This enables the console before standard serial driver is probed.
> +	  This is enabled with "earlycon=uhi" or "earlycon=uhi_stdio" on the
> +	  kernel command line.
> +	  The console is enabled when early_param is processed.
> +
>  config SERIAL_EARLYCON_RISCV_SBI
>  	bool "Early console using RISC-V SBI"
>  	depends on RISCV_SBI_V01
> diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
> index f6b8c220dcfb..ef5e9c87aea1 100644
> --- a/drivers/tty/serial/Makefile
> +++ b/drivers/tty/serial/Makefile
> @@ -9,6 +9,7 @@ serial_base-y := serial_core.o serial_base_bus.o 
> serial_ctrl.o serial_port.o
>  obj-$(CONFIG_SERIAL_EARLYCON) += earlycon.o
>  obj-$(CONFIG_SERIAL_EARLYCON_SEMIHOST) += earlycon-semihost.o
>  obj-$(CONFIG_SERIAL_EARLYCON_RISCV_SBI) += earlycon-riscv-sbi.o
> +obj-$(CONFIG_SERIAL_EARLYCON_MIPS_UHI) += earlycon-mips-uhi.o
> 
>  # These Sparc drivers have to appear before others such as 8250
>  # which share ttySx minor node space.  Otherwise console device
> diff --git a/drivers/tty/serial/earlycon-mips-uhi.c 
> b/drivers/tty/serial/earlycon-mips-uhi.c
> new file mode 100644
> index 000000000000..002bb2c37064
> --- /dev/null
> +++ b/drivers/tty/serial/earlycon-mips-uhi.c
> @@ -0,0 +1,85 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * MIPS UHI semihosting based earlycon
> + *
> + * Copyright (C) 2023 Jiaxun Yang <jiaxun.yang@flygoat.com>
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/console.h>
> +#include <linux/init.h>
> +#include <linux/serial_core.h>
> +#include <asm/uhi.h>
> +
> +static int stdin_fd = -1;
> +static int stdout_fd = -1;
> +
> +static void uhi_plog_write(struct console *con, const char *s, 
> unsigned int n)
> +{
> +	uhi_plog(s, 0);
> +}
> +
> +static void uhi_stdout_write(struct console *con, const char *s, 
> unsigned int n)
> +{
> +	if (stdout_fd < 0)
> +		return;
> +
> +	uhi_write(stdout_fd, s, n);
> +}
> +
> +#ifdef CONFIG_CONSOLE_POLL
> +static int uhi_stdin_read(struct console *con, char *s, unsigned int n)
> +{
> +	if (stdin_fd < 0)
> +		return 0;
> +
> +	return uhi_read(stdin_fd, s, n);
> +}
> +#endif
> +
> +static int uhi_stdio_fd_open(struct console *co, char *options)
> +{
> +	/*
> +	 * You have to open both stdin and stdout to get console work
> +	 * properly on some old CodeScape debugger.
> +	 */
> +	stdin_fd = uhi_open("/dev/stdin", UHI_O_RDONLY, 0);
> +	stdout_fd = uhi_open("/dev/stdout", UHI_O_WRONLY, 0);
> +
> +	return (stdin_fd < 0 || stdout_fd < 0) ? -ENODEV : 0;
> +}
> +
> +static int uhi_stdio_fd_close(struct console *co)
> +{
> +	int ret1 = 0, ret2 = 0;
> +
> +	if (stdin_fd >= 0)
> +		ret1 = uhi_close(stdin_fd);
> +	if (stdout_fd >= 0)
> +		ret2 = uhi_close(stdout_fd);
> +
> +	return (ret1 < 0 || ret2 < 0) ? -ENODEV : 0;
> +}
> +
> +static int
> +__init early_uhi_setup(struct earlycon_device *device, const char *opt)
> +{
> +	device->con->write = uhi_plog_write;
> +	return 0;
> +}
> +
> +static int
> +__init early_uhi_stdio_setup(struct earlycon_device *device, const 
> char *opt)
> +{
> +
> +	device->con->setup = uhi_stdio_fd_open;
> +	device->con->exit = uhi_stdio_fd_close;
> +	device->con->write = uhi_stdout_write;
> +#ifdef CONFIG_CONSOLE_POLL
> +	device->con->read = uhi_stdin_read;
> +#endif
> +	return 0;
> +}
> +
> +EARLYCON_DECLARE(uhi, early_uhi_setup);
> +EARLYCON_DECLARE(uhi_stdio, early_uhi_stdio_setup);
> -- 
> 2.34.1

-- 
- Jiaxun

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

* Re: [PATCH 2/3] MIPS: zboot: Add UHI semihosting debug print support
  2023-10-27 18:26 ` [PATCH 2/3] MIPS: zboot: Add UHI semihosting debug print support Jiaxun Yang
@ 2023-10-31 21:49   ` kernel test robot
  0 siblings, 0 replies; 10+ messages in thread
From: kernel test robot @ 2023-10-31 21:49 UTC (permalink / raw)
  To: Jiaxun Yang, linux-mips
  Cc: oe-kbuild-all, linux-serial, linux-kernel, tsbogend, gregkh,
	jirislaby, Jiaxun Yang

Hi Jiaxun,

kernel test robot noticed the following build warnings:

[auto build test WARNING on tty/tty-testing]
[also build test WARNING on tty/tty-next tty/tty-linus linus/master v6.6 next-20231030]
[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/Jiaxun-Yang/MIPS-zboot-Add-UHI-semihosting-debug-print-support/20231028-032719
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git tty-testing
patch link:    https://lore.kernel.org/r/20231027182650.281405-7-jiaxun.yang%40flygoat.com
patch subject: [PATCH 2/3] MIPS: zboot: Add UHI semihosting debug print support
config: mips-allmodconfig (https://download.01.org/0day-ci/archive/20231101/202311010521.7YJZiVJm-lkp@intel.com/config)
compiler: mips-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20231101/202311010521.7YJZiVJm-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202311010521.7YJZiVJm-lkp@intel.com/

Note: functions only called from assembly code should be annotated with the asmlinkage attribute
All warnings (new ones prefixed by >>):

>> arch/mips/boot/compressed/dbg-uhi.c:8:6: warning: no previous prototype for 'puts' [-Wmissing-prototypes]
       8 | void puts(const char *s)
         |      ^~~~


vim +/puts +8 arch/mips/boot/compressed/dbg-uhi.c

     7	
   > 8	void puts(const char *s)

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

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

end of thread, other threads:[~2023-10-31 21:49 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-10-27 18:26 [PATCH 0/3] serial, MIPS: Add MIPS UHI semihosting support Jiaxun Yang
2023-10-27 18:26 ` [PATCH 1/3] MIPS: Add header for UHI semihosting defines Jiaxun Yang
2023-10-27 18:26 ` [PATCH 2/3] MIPS: zboot: Add UHI semihosting debug print support Jiaxun Yang
2023-10-27 18:26 ` [PATCH 3/3] serial: Add an earlycon driver for MIPS UHI semihosting Jiaxun Yang
2023-10-27 18:26 ` [PATCH 0/3] serial, MIPS: Add MIPS UHI semihosting support Jiaxun Yang
2023-10-27 18:26 ` [PATCH 1/3] MIPS: Add header for UHI semihosting defines Jiaxun Yang
2023-10-27 18:26 ` [PATCH 2/3] MIPS: zboot: Add UHI semihosting debug print support Jiaxun Yang
2023-10-31 21:49   ` kernel test robot
2023-10-27 18:26 ` [PATCH 3/3] serial: Add an earlycon driver for MIPS UHI semihosting Jiaxun Yang
2023-10-27 20:48   ` Jiaxun Yang

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®