All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/3] Add riscv semihosting support in u-boot
@ 2022-09-19 11:49 Kautuk Consul
  2022-09-19 11:49 ` [PATCH v4 1/3] lib: Add common semihosting library Kautuk Consul
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Kautuk Consul @ 2022-09-19 11:49 UTC (permalink / raw)
  To: Rayagonda Kokatanur, Sean Anderson, Rick Chen, Leo, Simon Glass,
	Heinrich Schuchardt, Ilias Apalodimas, Alexandru Gagniuc,
	Philippe Reynes, Rasmus Villemoes, Stefan Roese, Loic Poulain,
	Bin Meng
  Cc: u-boot, Kautuk Consul

Semihosting is a mechanism that enables code running on
a target to communicate and use the Input/Output
facilities on a host computer that is running a debugger.
This patchset adds support for semihosting in u-boot
for RISCV64 targets.

CHANGES since v2 and v3:
-	v2: Move the arch/arm/Kconfig common *SEMIHOSTING* config
	options from arch/arm/Kconfig to lib/Kconfig.
-	v2: Improve the *SEMIHOSTING_FALLBACK config options in
	lib/Kconfig to depend on RISCV or ARM64.
-	v2: Remove the arch/riscv/include/asm/semhosting.h file.
-	v2: Improve the arch/riscv/lib/semihosting.c by removing the
	jump statement and moving the .align 4 to before the 2
	.option directives.
-	v3: Additionally check for the RISCV config option in the "depends"
	of the SPL_SEMIHOSTING_FALLBACK config option in lib/Kconfig.

Compilation and test commands for SPL and S-mode configurations
=================================================================

U-Boot S-mode on QEMU virt
----------------------------
// Compilation of S-mode u-boot
ARCH=riscv
CROSS_COMPILE=riscv64-unknown-linux-gnu-
make qemu-riscv64_smode_defconfig
make
// Run riscv 64-bit u-boot with opensbi on qemu
qemu-system-riscv64 -M virt -m 256M -display none -serial stdio -bios\
opensbi/build/platform/generic/firmware/fw_jump.bin -kernel\
u-boot/u-boot.bin

U-Boot SPL on QEMU virt
------------------------
// Compilation of u-boot-spl
ARCH=riscv
CROSS_COMPILE=riscv64-unknown-linux-gnu-
make qemu-riscv64_spl_defconfig
make OPENSBI=opensbi/build/platform/generic/firmware/fw_dynamic.bin
// Run 64-bit u-boot-spl in qemu
qemu-system-riscv64 -M virt -m 256M -display none -serial stdio -bios\
u-boot/spl/u-boot-spl.bin -device\
loader,file=u-boot/u-boot.itb,addr=0x80200000

Kautuk Consul (3):
  lib: Add common semihosting library
  arch/riscv: add semihosting support for RISC-V
  board: qemu-riscv: enable semihosting

 arch/arm/Kconfig                     |  46 -------
 arch/arm/lib/semihosting.c           | 181 +-------------------------
 arch/riscv/include/asm/spl.h         |   1 +
 arch/riscv/lib/Makefile              |   2 +
 arch/riscv/lib/interrupts.c          |  11 ++
 arch/riscv/lib/semihosting.c         |  24 ++++
 configs/qemu-riscv32_defconfig       |   4 +
 configs/qemu-riscv32_smode_defconfig |   4 +
 configs/qemu-riscv32_spl_defconfig   |   7 +
 configs/qemu-riscv64_defconfig       |   4 +
 configs/qemu-riscv64_smode_defconfig |   4 +
 configs/qemu-riscv64_spl_defconfig   |   7 +
 include/semihosting.h                |  11 ++
 lib/Kconfig                          |  46 +++++++
 lib/Makefile                         |   2 +
 lib/semihosting.c                    | 186 +++++++++++++++++++++++++++
 16 files changed, 314 insertions(+), 226 deletions(-)
 create mode 100644 arch/riscv/lib/semihosting.c
 create mode 100644 lib/semihosting.c

-- 
2.34.1


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

* [PATCH v4 1/3] lib: Add common semihosting library
  2022-09-19 11:49 [PATCH v4 0/3] Add riscv semihosting support in u-boot Kautuk Consul
@ 2022-09-19 11:49 ` Kautuk Consul
  2022-09-22  9:02   ` Leo Liang
  2022-09-22 17:00   ` Sean Anderson
  2022-09-19 11:49 ` [PATCH v4 2/3] arch/riscv: add semihosting support for RISC-V Kautuk Consul
  2022-09-19 11:49 ` [PATCH v4 3/3] board: qemu-riscv: enable semihosting Kautuk Consul
  2 siblings, 2 replies; 11+ messages in thread
From: Kautuk Consul @ 2022-09-19 11:49 UTC (permalink / raw)
  To: Rayagonda Kokatanur, Sean Anderson, Rick Chen, Leo, Simon Glass,
	Heinrich Schuchardt, Ilias Apalodimas, Alexandru Gagniuc,
	Philippe Reynes, Rasmus Villemoes, Stefan Roese, Loic Poulain,
	Bin Meng
  Cc: u-boot, Kautuk Consul

We factor out the arch-independent parts of the ARM semihosting
implementation as a common library so that it can be shared
with RISC-V.

Signed-off-by: Kautuk Consul <kconsul@ventanamicro.com>
---
 arch/arm/Kconfig           |  46 ---------
 arch/arm/lib/semihosting.c | 181 +-----------------------------------
 include/semihosting.h      |  11 +++
 lib/Kconfig                |  46 +++++++++
 lib/Makefile               |   2 +
 lib/semihosting.c          | 186 +++++++++++++++++++++++++++++++++++++
 6 files changed, 246 insertions(+), 226 deletions(-)
 create mode 100644 lib/semihosting.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 82cd456f51..ee6a9fadd9 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -413,52 +413,6 @@ config ARM_SMCCC
 	  This should be enabled if U-Boot needs to communicate with system
 	  firmware (for example, PSCI) according to SMCCC.
 
-config SEMIHOSTING
-	bool "Support ARM semihosting"
-	help
-	  Semihosting is a method for a target to communicate with a host
-	  debugger. It uses special instructions which the debugger will trap
-	  on and interpret. This allows U-Boot to read/write files, print to
-	  the console, and execute arbitrary commands on the host system.
-
-	  Enabling this option will add support for reading and writing files
-	  on the host system. If you don't have a debugger attached then trying
-	  to do this will likely cause U-Boot to hang. Say 'n' if you are unsure.
-
-config SEMIHOSTING_FALLBACK
-	bool "Recover gracefully when semihosting fails"
-	depends on SEMIHOSTING && ARM64
-	default y
-	help
-	  Normally, if U-Boot makes a semihosting call and no debugger is
-	  attached, then it will panic due to a synchronous abort
-	  exception. This config adds an exception handler which will allow
-	  U-Boot to recover. Say 'y' if unsure.
-
-config SPL_SEMIHOSTING
-	bool "Support ARM semihosting in SPL"
-	depends on SPL
-	help
-	  Semihosting is a method for a target to communicate with a host
-	  debugger. It uses special instructions which the debugger will trap
-	  on and interpret. This allows U-Boot to read/write files, print to
-	  the console, and execute arbitrary commands on the host system.
-
-	  Enabling this option will add support for reading and writing files
-	  on the host system. If you don't have a debugger attached then trying
-	  to do this will likely cause U-Boot to hang. Say 'n' if you are unsure.
-
-config SPL_SEMIHOSTING_FALLBACK
-	bool "Recover gracefully when semihosting fails in SPL"
-	depends on SPL_SEMIHOSTING && ARM64
-	select ARMV8_SPL_EXCEPTION_VECTORS
-	default y
-	help
-	  Normally, if U-Boot makes a semihosting call and no debugger is
-	  attached, then it will panic due to a synchronous abort
-	  exception. This config adds an exception handler which will allow
-	  U-Boot to recover. Say 'y' if unsure.
-
 config SYS_THUMB_BUILD
 	bool "Build U-Boot using the Thumb instruction set"
 	depends on !ARM64
diff --git a/arch/arm/lib/semihosting.c b/arch/arm/lib/semihosting.c
index 01d652a6b8..11e7b85ee6 100644
--- a/arch/arm/lib/semihosting.c
+++ b/arch/arm/lib/semihosting.c
@@ -10,25 +10,11 @@
  * available in silicon now, fastmodel usage makes less sense for them.
  */
 #include <common.h>
-#include <log.h>
-#include <semihosting.h>
-
-#define SYSOPEN		0x01
-#define SYSCLOSE	0x02
-#define SYSWRITEC	0x03
-#define SYSWRITE0	0x04
-#define SYSWRITE	0x05
-#define SYSREAD		0x06
-#define SYSREADC	0x07
-#define SYSISERROR	0x08
-#define SYSSEEK		0x0A
-#define SYSFLEN		0x0C
-#define SYSERRNO	0x13
 
 /*
  * Call the handler
  */
-static noinline long smh_trap(unsigned int sysnum, void *addr)
+long smh_trap(unsigned int sysnum, void *addr)
 {
 	register long result asm("r0");
 #if defined(CONFIG_ARM64)
@@ -41,168 +27,3 @@ static noinline long smh_trap(unsigned int sysnum, void *addr)
 #endif
 	return result;
 }
-
-#if CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK)
-static bool _semihosting_enabled = true;
-static bool try_semihosting = true;
-
-bool semihosting_enabled(void)
-{
-	if (try_semihosting) {
-		smh_trap(SYSERRNO, NULL);
-		try_semihosting = false;
-	}
-
-	return _semihosting_enabled;
-}
-
-void disable_semihosting(void)
-{
-	_semihosting_enabled = false;
-}
-#endif
-
-/**
- * smh_errno() - Read the host's errno
- *
- * This gets the value of the host's errno and negates it. The host's errno may
- * or may not be set, so only call this function if a previous semihosting call
- * has failed.
- *
- * Return: a negative error value
- */
-static int smh_errno(void)
-{
-	long ret = smh_trap(SYSERRNO, NULL);
-
-	if (ret > 0 && ret < INT_MAX)
-		return -ret;
-	return -EIO;
-}
-
-long smh_open(const char *fname, enum smh_open_mode mode)
-{
-	long fd;
-	struct smh_open_s {
-		const char *fname;
-		unsigned long mode;
-		size_t len;
-	} open;
-
-	debug("%s: file \'%s\', mode \'%u\'\n", __func__, fname, mode);
-
-	open.fname = fname;
-	open.len = strlen(fname);
-	open.mode = mode;
-
-	/* Open the file on the host */
-	fd = smh_trap(SYSOPEN, &open);
-	if (fd == -1)
-		return smh_errno();
-	return fd;
-}
-
-/**
- * struct smg_rdwr_s - Arguments for read and write
- * @fd: A file descriptor returned from smh_open()
- * @memp: Pointer to a buffer of memory of at least @len bytes
- * @len: The number of bytes to read or write
- */
-struct smh_rdwr_s {
-	long fd;
-	void *memp;
-	size_t len;
-};
-
-long smh_read(long fd, void *memp, size_t len)
-{
-	long ret;
-	struct smh_rdwr_s read;
-
-	debug("%s: fd %ld, memp %p, len %zu\n", __func__, fd, memp, len);
-
-	read.fd = fd;
-	read.memp = memp;
-	read.len = len;
-
-	ret = smh_trap(SYSREAD, &read);
-	if (ret < 0)
-		return smh_errno();
-	return len - ret;
-}
-
-long smh_write(long fd, const void *memp, size_t len, ulong *written)
-{
-	long ret;
-	struct smh_rdwr_s write;
-
-	debug("%s: fd %ld, memp %p, len %zu\n", __func__, fd, memp, len);
-
-	write.fd = fd;
-	write.memp = (void *)memp;
-	write.len = len;
-
-	ret = smh_trap(SYSWRITE, &write);
-	*written = len - ret;
-	if (ret)
-		return smh_errno();
-	return 0;
-}
-
-long smh_close(long fd)
-{
-	long ret;
-
-	debug("%s: fd %ld\n", __func__, fd);
-
-	ret = smh_trap(SYSCLOSE, &fd);
-	if (ret == -1)
-		return smh_errno();
-	return 0;
-}
-
-long smh_flen(long fd)
-{
-	long ret;
-
-	debug("%s: fd %ld\n", __func__, fd);
-
-	ret = smh_trap(SYSFLEN, &fd);
-	if (ret == -1)
-		return smh_errno();
-	return ret;
-}
-
-long smh_seek(long fd, long pos)
-{
-	long ret;
-	struct smh_seek_s {
-		long fd;
-		long pos;
-	} seek;
-
-	debug("%s: fd %ld pos %ld\n", __func__, fd, pos);
-
-	seek.fd = fd;
-	seek.pos = pos;
-
-	ret = smh_trap(SYSSEEK, &seek);
-	if (ret)
-		return smh_errno();
-	return 0;
-}
-
-int smh_getc(void)
-{
-	return smh_trap(SYSREADC, NULL);
-}
-
-void smh_putc(char ch)
-{
-	smh_trap(SYSWRITEC, &ch);
-}
-
-void smh_puts(const char *s)
-{
-	smh_trap(SYSWRITE0, (char *)s);
-}
diff --git a/include/semihosting.h b/include/semihosting.h
index f1f73464e4..4e844cbad8 100644
--- a/include/semihosting.h
+++ b/include/semihosting.h
@@ -17,6 +17,17 @@
 #define SMH_T32_SVC 0xDFAB
 #define SMH_T32_HLT 0xBABC
 
+/**
+ * smh_trap() - ARCH-specific semihosting call.
+ *
+ * Semihosting library/driver can use this function to do the
+ * actual semihosting calls.
+ *
+ * Return: Error code defined by semihosting spec.
+ */
+
+long smh_trap(unsigned int sysnum, void *addr);
+
 #if CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK)
 /**
  * semihosting_enabled() - Determine whether semihosting is supported
diff --git a/lib/Kconfig b/lib/Kconfig
index 6121c80dc8..97920e7552 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -71,6 +71,52 @@ config HAVE_PRIVATE_LIBGCC
 config LIB_UUID
 	bool
 
+config SEMIHOSTING
+	bool "Support semihosting"
+	help
+	  Semihosting is a method for a target to communicate with a host
+	  debugger. It uses special instructions which the debugger will trap
+	  on and interpret. This allows U-Boot to read/write files, print to
+	  the console, and execute arbitrary commands on the host system.
+
+	  Enabling this option will add support for reading and writing files
+	  on the host system. If you don't have a debugger attached then trying
+	  to do this will likely cause U-Boot to hang. Say 'n' if you are unsure.
+
+config SEMIHOSTING_FALLBACK
+	bool "Recover gracefully when semihosting fails"
+	depends on SEMIHOSTING && ARM64
+	default y
+	help
+	  Normally, if U-Boot makes a semihosting call and no debugger is
+	  attached, then it will panic due to a synchronous abort
+	  exception. This config adds an exception handler which will allow
+	  U-Boot to recover. Say 'y' if unsure.
+
+config SPL_SEMIHOSTING
+	bool "Support semihosting in SPL"
+	depends on SPL
+	help
+	  Semihosting is a method for a target to communicate with a host
+	  debugger. It uses special instructions which the debugger will trap
+	  on and interpret. This allows U-Boot to read/write files, print to
+	  the console, and execute arbitrary commands on the host system.
+
+	  Enabling this option will add support for reading and writing files
+	  on the host system. If you don't have a debugger attached then trying
+	  to do this will likely cause U-Boot to hang. Say 'n' if you are unsure.
+
+config SPL_SEMIHOSTING_FALLBACK
+	bool "Recover gracefully when semihosting fails in SPL"
+	depends on SPL_SEMIHOSTING && ARM64
+	select ARMV8_SPL_EXCEPTION_VECTORS
+	default y
+	help
+	  Normally, if U-Boot makes a semihosting call and no debugger is
+	  attached, then it will panic due to a synchronous abort
+	  exception. This config adds an exception handler which will allow
+	  U-Boot to recover. Say 'y' if unsure.
+
 config PRINTF
 	bool
 	default y
diff --git a/lib/Makefile b/lib/Makefile
index e3deb15287..134c4319cd 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -145,6 +145,8 @@ obj-y += date.o
 obj-y += rtc-lib.o
 obj-$(CONFIG_LIB_ELF) += elf.o
 
+obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o
+
 #
 # Build a fast OID lookup registry from include/linux/oid_registry.h
 #
diff --git a/lib/semihosting.c b/lib/semihosting.c
new file mode 100644
index 0000000000..831774e356
--- /dev/null
+++ b/lib/semihosting.c
@@ -0,0 +1,186 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022 Sean Anderson <sean.anderson@seco.com>
+ * Copyright 2014 Broadcom Corporation
+ */
+
+#include <common.h>
+#include <log.h>
+#include <semihosting.h>
+
+#define SYSOPEN		0x01
+#define SYSCLOSE	0x02
+#define SYSWRITEC	0x03
+#define SYSWRITE0	0x04
+#define SYSWRITE	0x05
+#define SYSREAD		0x06
+#define SYSREADC	0x07
+#define SYSISERROR	0x08
+#define SYSSEEK		0x0A
+#define SYSFLEN		0x0C
+#define SYSERRNO	0x13
+
+#if CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK)
+static bool _semihosting_enabled = true;
+static bool try_semihosting = true;
+
+bool semihosting_enabled(void)
+{
+	if (try_semihosting) {
+		smh_trap(SYSERRNO, NULL);
+		try_semihosting = false;
+	}
+
+	return _semihosting_enabled;
+}
+
+void disable_semihosting(void)
+{
+	_semihosting_enabled = false;
+}
+#endif
+
+/**
+ * smh_errno() - Read the host's errno
+ *
+ * This gets the value of the host's errno and negates it. The host's errno may
+ * or may not be set, so only call this function if a previous semihosting call
+ * has failed.
+ *
+ * Return: a negative error value
+ */
+static int smh_errno(void)
+{
+	long ret = smh_trap(SYSERRNO, NULL);
+
+	if (ret > 0 && ret < INT_MAX)
+		return -ret;
+	return -EIO;
+}
+
+long smh_open(const char *fname, enum smh_open_mode mode)
+{
+	long fd;
+	struct smh_open_s {
+		const char *fname;
+		unsigned long mode;
+		size_t len;
+	} open;
+
+	debug("%s: file \'%s\', mode \'%u\'\n", __func__, fname, mode);
+
+	open.fname = fname;
+	open.len = strlen(fname);
+	open.mode = mode;
+
+	/* Open the file on the host */
+	fd = smh_trap(SYSOPEN, &open);
+	if (fd == -1)
+		return smh_errno();
+	return fd;
+}
+
+/**
+ * struct smg_rdwr_s - Arguments for read and write
+ * @fd: A file descriptor returned from smh_open()
+ * @memp: Pointer to a buffer of memory of at least @len bytes
+ * @len: The number of bytes to read or write
+ */
+struct smh_rdwr_s {
+	long fd;
+	void *memp;
+	size_t len;
+};
+
+long smh_read(long fd, void *memp, size_t len)
+{
+	long ret;
+	struct smh_rdwr_s read;
+
+	debug("%s: fd %ld, memp %p, len %zu\n", __func__, fd, memp, len);
+
+	read.fd = fd;
+	read.memp = memp;
+	read.len = len;
+
+	ret = smh_trap(SYSREAD, &read);
+	if (ret < 0)
+		return smh_errno();
+	return len - ret;
+}
+
+long smh_write(long fd, const void *memp, size_t len, ulong *written)
+{
+	long ret;
+	struct smh_rdwr_s write;
+
+	debug("%s: fd %ld, memp %p, len %zu\n", __func__, fd, memp, len);
+
+	write.fd = fd;
+	write.memp = (void *)memp;
+	write.len = len;
+
+	ret = smh_trap(SYSWRITE, &write);
+	*written = len - ret;
+	if (ret)
+		return smh_errno();
+	return 0;
+}
+
+long smh_close(long fd)
+{
+	long ret;
+
+	debug("%s: fd %ld\n", __func__, fd);
+
+	ret = smh_trap(SYSCLOSE, &fd);
+	if (ret == -1)
+		return smh_errno();
+	return 0;
+}
+
+long smh_flen(long fd)
+{
+	long ret;
+
+	debug("%s: fd %ld\n", __func__, fd);
+
+	ret = smh_trap(SYSFLEN, &fd);
+	if (ret == -1)
+		return smh_errno();
+	return ret;
+}
+
+long smh_seek(long fd, long pos)
+{
+	long ret;
+	struct smh_seek_s {
+		long fd;
+		long pos;
+	} seek;
+
+	debug("%s: fd %ld pos %ld\n", __func__, fd, pos);
+
+	seek.fd = fd;
+	seek.pos = pos;
+
+	ret = smh_trap(SYSSEEK, &seek);
+	if (ret)
+		return smh_errno();
+	return 0;
+}
+
+int smh_getc(void)
+{
+	return smh_trap(SYSREADC, NULL);
+}
+
+void smh_putc(char ch)
+{
+	smh_trap(SYSWRITEC, &ch);
+}
+
+void smh_puts(const char *s)
+{
+	smh_trap(SYSWRITE0, (char *)s);
+}
-- 
2.34.1


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

* [PATCH v4 2/3] arch/riscv: add semihosting support for RISC-V
  2022-09-19 11:49 [PATCH v4 0/3] Add riscv semihosting support in u-boot Kautuk Consul
  2022-09-19 11:49 ` [PATCH v4 1/3] lib: Add common semihosting library Kautuk Consul
@ 2022-09-19 11:49 ` Kautuk Consul
  2022-09-22  9:03   ` Leo Liang
  2022-09-22 17:05   ` Sean Anderson
  2022-09-19 11:49 ` [PATCH v4 3/3] board: qemu-riscv: enable semihosting Kautuk Consul
  2 siblings, 2 replies; 11+ messages in thread
From: Kautuk Consul @ 2022-09-19 11:49 UTC (permalink / raw)
  To: Rayagonda Kokatanur, Sean Anderson, Rick Chen, Leo, Simon Glass,
	Heinrich Schuchardt, Ilias Apalodimas, Alexandru Gagniuc,
	Philippe Reynes, Rasmus Villemoes, Stefan Roese, Loic Poulain,
	Bin Meng
  Cc: u-boot, Kautuk Consul, Anup Patel

We add RISC-V semihosting based serial console for JTAG based early
debugging.

The RISC-V semihosting specification is available at:
https://github.com/riscv/riscv-semihosting-spec/blob/main/riscv-semihosting-spec.adoc

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Signed-off-by: Kautuk Consul <kconsul@ventanamicro.com>
---
 arch/riscv/include/asm/spl.h |  1 +
 arch/riscv/lib/Makefile      |  2 ++
 arch/riscv/lib/interrupts.c  | 11 +++++++++++
 arch/riscv/lib/semihosting.c | 24 ++++++++++++++++++++++++
 lib/Kconfig                  |  6 +++---
 5 files changed, 41 insertions(+), 3 deletions(-)
 create mode 100644 arch/riscv/lib/semihosting.c

diff --git a/arch/riscv/include/asm/spl.h b/arch/riscv/include/asm/spl.h
index e8a94fcb1f..2898a770ee 100644
--- a/arch/riscv/include/asm/spl.h
+++ b/arch/riscv/include/asm/spl.h
@@ -25,6 +25,7 @@ enum {
 	BOOT_DEVICE_DFU,
 	BOOT_DEVICE_XIP,
 	BOOT_DEVICE_BOOTROM,
+	BOOT_DEVICE_SMH,
 	BOOT_DEVICE_NONE
 };
 
diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile
index 06020fcc2a..64e29804c1 100644
--- a/arch/riscv/lib/Makefile
+++ b/arch/riscv/lib/Makefile
@@ -42,3 +42,5 @@ extra-$(CONFIG_EFI) += $(EFI_CRT0) $(EFI_RELOC)
 obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_MEMSET) += memset.o
 obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_MEMMOVE) += memmove.o
 obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_MEMCPY) += memcpy.o
+
+obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o
diff --git a/arch/riscv/lib/interrupts.c b/arch/riscv/lib/interrupts.c
index 100be2e966..bd7cd772b8 100644
--- a/arch/riscv/lib/interrupts.c
+++ b/arch/riscv/lib/interrupts.c
@@ -17,6 +17,7 @@
 #include <asm/ptrace.h>
 #include <asm/system.h>
 #include <asm/encoding.h>
+#include <semihosting.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -149,6 +150,16 @@ ulong handle_trap(ulong cause, ulong epc, ulong tval, struct pt_regs *regs)
 	/* An UEFI application may have changed gd. Restore U-Boot's gd. */
 	efi_restore_gd();
 
+	if (cause == CAUSE_BREAKPOINT &&
+	    CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK)) {
+		/* For semihosting fallback we simply skip the ebreak
+		 * instruction.
+		 */
+		disable_semihosting();
+		epc += 4;
+		return epc;
+	}
+
 	is_irq = (cause & MCAUSE_INT);
 	irq = (cause & ~MCAUSE_INT);
 
diff --git a/arch/riscv/lib/semihosting.c b/arch/riscv/lib/semihosting.c
new file mode 100644
index 0000000000..d6593b02a6
--- /dev/null
+++ b/arch/riscv/lib/semihosting.c
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022 Ventana Micro Systems Inc.
+ */
+
+#include <common.h>
+
+long smh_trap(int sysnum, void *addr)
+{
+	register int ret asm ("a0") = sysnum;
+	register void *param0 asm ("a1") = addr;
+
+	asm volatile (".align 4\n"
+		".option push\n"
+		".option norvc\n"
+
+		"slli zero, zero, 0x1f\n"
+		"ebreak\n"
+		"srai zero, zero, 7\n"
+		".option pop\n"
+		: "+r" (ret) : "r" (param0) : "memory");
+
+	return ret;
+}
diff --git a/lib/Kconfig b/lib/Kconfig
index 97920e7552..eed3a231d9 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -85,7 +85,7 @@ config SEMIHOSTING
 
 config SEMIHOSTING_FALLBACK
 	bool "Recover gracefully when semihosting fails"
-	depends on SEMIHOSTING && ARM64
+	depends on SEMIHOSTING && (ARM64 || RISCV)
 	default y
 	help
 	  Normally, if U-Boot makes a semihosting call and no debugger is
@@ -108,8 +108,8 @@ config SPL_SEMIHOSTING
 
 config SPL_SEMIHOSTING_FALLBACK
 	bool "Recover gracefully when semihosting fails in SPL"
-	depends on SPL_SEMIHOSTING && ARM64
-	select ARMV8_SPL_EXCEPTION_VECTORS
+	depends on SPL_SEMIHOSTING && (ARM64 || RISCV)
+	select ARMV8_SPL_EXCEPTION_VECTORS if ARM64
 	default y
 	help
 	  Normally, if U-Boot makes a semihosting call and no debugger is
-- 
2.34.1


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

* [PATCH v4 3/3] board: qemu-riscv: enable semihosting
  2022-09-19 11:49 [PATCH v4 0/3] Add riscv semihosting support in u-boot Kautuk Consul
  2022-09-19 11:49 ` [PATCH v4 1/3] lib: Add common semihosting library Kautuk Consul
  2022-09-19 11:49 ` [PATCH v4 2/3] arch/riscv: add semihosting support for RISC-V Kautuk Consul
@ 2022-09-19 11:49 ` Kautuk Consul
  2022-09-22  9:03   ` Leo Liang
  2 siblings, 1 reply; 11+ messages in thread
From: Kautuk Consul @ 2022-09-19 11:49 UTC (permalink / raw)
  To: Rayagonda Kokatanur, Sean Anderson, Rick Chen, Leo, Simon Glass,
	Heinrich Schuchardt, Ilias Apalodimas, Alexandru Gagniuc,
	Philippe Reynes, Rasmus Villemoes, Stefan Roese, Loic Poulain,
	Bin Meng
  Cc: u-boot, Kautuk Consul

To enable semihosting we also need to enable the following
configs in defconfigs:
CONFIG_SEMIHOSTING
CONFIG_SPL_SEMIHOSTING
CONFIG_SEMIHOSTING_SERIAL
CONFIG_SERIAL_PROBE_ALL
CONFIG_SPL_FS_EXT4
CONFIG_SPL_FS_FAT

Signed-off-by: Kautuk Consul <kconsul@ventanamicro.com>
---
 configs/qemu-riscv32_defconfig       | 4 ++++
 configs/qemu-riscv32_smode_defconfig | 4 ++++
 configs/qemu-riscv32_spl_defconfig   | 7 +++++++
 configs/qemu-riscv64_defconfig       | 4 ++++
 configs/qemu-riscv64_smode_defconfig | 4 ++++
 configs/qemu-riscv64_spl_defconfig   | 7 +++++++
 6 files changed, 30 insertions(+)

diff --git a/configs/qemu-riscv32_defconfig b/configs/qemu-riscv32_defconfig
index 9634d7f77f..4961652548 100644
--- a/configs/qemu-riscv32_defconfig
+++ b/configs/qemu-riscv32_defconfig
@@ -1,4 +1,5 @@
 CONFIG_RISCV=y
+CONFIG_SEMIHOSTING=y
 CONFIG_SYS_MALLOC_LEN=0x800000
 CONFIG_NR_DRAM_BANKS=1
 CONFIG_ENV_SIZE=0x20000
@@ -20,3 +21,6 @@ CONFIG_CMD_NVEDIT_EFI=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_DM_MTD=y
 CONFIG_SYS_MAX_FLASH_BANKS=2
+# CONFIG_SERIAL_PUTS is not set
+CONFIG_SERIAL_PROBE_ALL=y
+CONFIG_SEMIHOSTING_SERIAL=y
diff --git a/configs/qemu-riscv32_smode_defconfig b/configs/qemu-riscv32_smode_defconfig
index 1c5a0617aa..91e4ffebc2 100644
--- a/configs/qemu-riscv32_smode_defconfig
+++ b/configs/qemu-riscv32_smode_defconfig
@@ -1,4 +1,5 @@
 CONFIG_RISCV=y
+CONFIG_SEMIHOSTING=y
 CONFIG_SYS_MALLOC_LEN=0x800000
 CONFIG_NR_DRAM_BANKS=1
 CONFIG_ENV_SIZE=0x20000
@@ -21,4 +22,7 @@ CONFIG_CMD_NVEDIT_EFI=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_DM_MTD=y
 CONFIG_SYS_MAX_FLASH_BANKS=2
+# CONFIG_SERIAL_PUTS is not set
+CONFIG_SERIAL_PROBE_ALL=y
+CONFIG_SEMIHOSTING_SERIAL=y
 CONFIG_SYSRESET_SBI=y
diff --git a/configs/qemu-riscv32_spl_defconfig b/configs/qemu-riscv32_spl_defconfig
index 2421c9a371..5fd28fc58c 100644
--- a/configs/qemu-riscv32_spl_defconfig
+++ b/configs/qemu-riscv32_spl_defconfig
@@ -1,9 +1,12 @@
 CONFIG_RISCV=y
+CONFIG_SEMIHOSTING=y
+CONFIG_SPL_SEMIHOSTING=y
 CONFIG_SYS_MALLOC_LEN=0x800000
 CONFIG_NR_DRAM_BANKS=1
 CONFIG_ENV_SIZE=0x20000
 CONFIG_DEFAULT_DEVICE_TREE="qemu-virt32"
 CONFIG_SPL=y
+CONFIG_SPL_FS_FAT=y
 CONFIG_SYS_LOAD_ADDR=0x80200000
 CONFIG_TARGET_QEMU_VIRT=y
 CONFIG_RISCV_SMODE=y
@@ -18,6 +21,7 @@ CONFIG_DISPLAY_BOARDINFO=y
 CONFIG_SPL_MAX_SIZE=0x100000
 CONFIG_SPL_BSS_START_ADDR=0x84000000
 CONFIG_SYS_SPL_MALLOC=y
+CONFIG_SPL_FS_EXT4=y
 CONFIG_SYS_CBSIZE=256
 CONFIG_SYS_PBSIZE=276
 CONFIG_SYS_BOOTM_LEN=0x4000000
@@ -25,5 +29,8 @@ CONFIG_SYS_BOOTM_LEN=0x4000000
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_DM_MTD=y
 CONFIG_SYS_MAX_FLASH_BANKS=2
+# CONFIG_SERIAL_PUTS is not set
+CONFIG_SERIAL_PROBE_ALL=y
+CONFIG_SEMIHOSTING_SERIAL=y
 CONFIG_SYSRESET_SBI=y
 # CONFIG_BINMAN_FDT is not set
diff --git a/configs/qemu-riscv64_defconfig b/configs/qemu-riscv64_defconfig
index d5eae95c80..87478f4481 100644
--- a/configs/qemu-riscv64_defconfig
+++ b/configs/qemu-riscv64_defconfig
@@ -1,4 +1,5 @@
 CONFIG_RISCV=y
+CONFIG_SEMIHOSTING=y
 CONFIG_SYS_MALLOC_LEN=0x800000
 CONFIG_NR_DRAM_BANKS=1
 CONFIG_ENV_SIZE=0x20000
@@ -21,3 +22,6 @@ CONFIG_CMD_NVEDIT_EFI=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_DM_MTD=y
 CONFIG_SYS_MAX_FLASH_BANKS=2
+# CONFIG_SERIAL_PUTS is not set
+CONFIG_SERIAL_PROBE_ALL=y
+CONFIG_SEMIHOSTING_SERIAL=y
diff --git a/configs/qemu-riscv64_smode_defconfig b/configs/qemu-riscv64_smode_defconfig
index 2861d07f97..5e9d6af3be 100644
--- a/configs/qemu-riscv64_smode_defconfig
+++ b/configs/qemu-riscv64_smode_defconfig
@@ -1,4 +1,5 @@
 CONFIG_RISCV=y
+CONFIG_SEMIHOSTING=y
 CONFIG_SYS_MALLOC_LEN=0x800000
 CONFIG_NR_DRAM_BANKS=1
 CONFIG_ENV_SIZE=0x20000
@@ -24,4 +25,7 @@ CONFIG_CMD_NVEDIT_EFI=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_DM_MTD=y
 CONFIG_SYS_MAX_FLASH_BANKS=2
+# CONFIG_SERIAL_PUTS is not set
+CONFIG_SERIAL_PROBE_ALL=y
+CONFIG_SEMIHOSTING_SERIAL=y
 CONFIG_SYSRESET_SBI=y
diff --git a/configs/qemu-riscv64_spl_defconfig b/configs/qemu-riscv64_spl_defconfig
index 1ecfa27ce2..e5d817b783 100644
--- a/configs/qemu-riscv64_spl_defconfig
+++ b/configs/qemu-riscv64_spl_defconfig
@@ -1,9 +1,12 @@
 CONFIG_RISCV=y
+CONFIG_SEMIHOSTING=y
+CONFIG_SPL_SEMIHOSTING=y
 CONFIG_SYS_MALLOC_LEN=0x800000
 CONFIG_NR_DRAM_BANKS=1
 CONFIG_ENV_SIZE=0x20000
 CONFIG_DEFAULT_DEVICE_TREE="qemu-virt64"
 CONFIG_SPL=y
+CONFIG_SPL_FS_FAT=y
 CONFIG_SYS_LOAD_ADDR=0x80200000
 CONFIG_TARGET_QEMU_VIRT=y
 CONFIG_ARCH_RV64I=y
@@ -18,6 +21,7 @@ CONFIG_DISPLAY_BOARDINFO=y
 CONFIG_SPL_MAX_SIZE=0x100000
 CONFIG_SPL_BSS_START_ADDR=0x84000000
 CONFIG_SYS_SPL_MALLOC=y
+CONFIG_SPL_FS_EXT4=y
 CONFIG_SYS_CBSIZE=256
 CONFIG_SYS_PBSIZE=276
 CONFIG_SYS_BOOTM_LEN=0x4000000
@@ -25,5 +29,8 @@ CONFIG_SYS_BOOTM_LEN=0x4000000
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_DM_MTD=y
 CONFIG_SYS_MAX_FLASH_BANKS=2
+# CONFIG_SERIAL_PUTS is not set
+CONFIG_SERIAL_PROBE_ALL=y
+CONFIG_SEMIHOSTING_SERIAL=y
 CONFIG_SYSRESET_SBI=y
 # CONFIG_BINMAN_FDT is not set
-- 
2.34.1


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

* Re: [PATCH v4 1/3] lib: Add common semihosting library
  2022-09-19 11:49 ` [PATCH v4 1/3] lib: Add common semihosting library Kautuk Consul
@ 2022-09-22  9:02   ` Leo Liang
  2022-09-22 17:00   ` Sean Anderson
  1 sibling, 0 replies; 11+ messages in thread
From: Leo Liang @ 2022-09-22  9:02 UTC (permalink / raw)
  To: Kautuk Consul
  Cc: Rayagonda Kokatanur, Sean Anderson, Rick Chen, Simon Glass,
	Heinrich Schuchardt, Ilias Apalodimas, Alexandru Gagniuc,
	Philippe Reynes, Rasmus Villemoes, Stefan Roese, Loic Poulain,
	Bin Meng, u-boot

On Mon, Sep 19, 2022 at 05:19:06PM +0530, Kautuk Consul wrote:
> We factor out the arch-independent parts of the ARM semihosting
> implementation as a common library so that it can be shared
> with RISC-V.
> 
> Signed-off-by: Kautuk Consul <kconsul@ventanamicro.com>
> ---
>  arch/arm/Kconfig           |  46 ---------
>  arch/arm/lib/semihosting.c | 181 +-----------------------------------
>  include/semihosting.h      |  11 +++
>  lib/Kconfig                |  46 +++++++++
>  lib/Makefile               |   2 +
>  lib/semihosting.c          | 186 +++++++++++++++++++++++++++++++++++++
>  6 files changed, 246 insertions(+), 226 deletions(-)
>  create mode 100644 lib/semihosting.c
Reviewed-by: Leo Yu-Chi Liang <ycliang@andestech.com>

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

* Re: [PATCH v4 2/3] arch/riscv: add semihosting support for RISC-V
  2022-09-19 11:49 ` [PATCH v4 2/3] arch/riscv: add semihosting support for RISC-V Kautuk Consul
@ 2022-09-22  9:03   ` Leo Liang
  2022-09-22 17:05   ` Sean Anderson
  1 sibling, 0 replies; 11+ messages in thread
From: Leo Liang @ 2022-09-22  9:03 UTC (permalink / raw)
  To: Kautuk Consul
  Cc: Rayagonda Kokatanur, Sean Anderson, Rick Chen, Simon Glass,
	Heinrich Schuchardt, Ilias Apalodimas, Alexandru Gagniuc,
	Philippe Reynes, Rasmus Villemoes, Stefan Roese, Loic Poulain,
	Bin Meng, u-boot, Anup Patel

On Mon, Sep 19, 2022 at 05:19:07PM +0530, Kautuk Consul wrote:
> We add RISC-V semihosting based serial console for JTAG based early
> debugging.
> 
> The RISC-V semihosting specification is available at:
> https://github.com/riscv/riscv-semihosting-spec/blob/main/riscv-semihosting-spec.adoc
> 
> Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> Signed-off-by: Kautuk Consul <kconsul@ventanamicro.com>
> ---
>  arch/riscv/include/asm/spl.h |  1 +
>  arch/riscv/lib/Makefile      |  2 ++
>  arch/riscv/lib/interrupts.c  | 11 +++++++++++
>  arch/riscv/lib/semihosting.c | 24 ++++++++++++++++++++++++
>  lib/Kconfig                  |  6 +++---
>  5 files changed, 41 insertions(+), 3 deletions(-)
>  create mode 100644 arch/riscv/lib/semihosting.c

Reviewed-by: Leo Yu-Chi Liang <ycliang@andestech.com>

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

* Re: [PATCH v4 3/3] board: qemu-riscv: enable semihosting
  2022-09-19 11:49 ` [PATCH v4 3/3] board: qemu-riscv: enable semihosting Kautuk Consul
@ 2022-09-22  9:03   ` Leo Liang
  0 siblings, 0 replies; 11+ messages in thread
From: Leo Liang @ 2022-09-22  9:03 UTC (permalink / raw)
  To: Kautuk Consul
  Cc: Rayagonda Kokatanur, Sean Anderson, Rick Chen, Simon Glass,
	Heinrich Schuchardt, Ilias Apalodimas, Alexandru Gagniuc,
	Philippe Reynes, Rasmus Villemoes, Stefan Roese, Loic Poulain,
	Bin Meng, u-boot

On Mon, Sep 19, 2022 at 05:19:08PM +0530, Kautuk Consul wrote:
> To enable semihosting we also need to enable the following
> configs in defconfigs:
> CONFIG_SEMIHOSTING
> CONFIG_SPL_SEMIHOSTING
> CONFIG_SEMIHOSTING_SERIAL
> CONFIG_SERIAL_PROBE_ALL
> CONFIG_SPL_FS_EXT4
> CONFIG_SPL_FS_FAT
> 
> Signed-off-by: Kautuk Consul <kconsul@ventanamicro.com>
> ---
>  configs/qemu-riscv32_defconfig       | 4 ++++
>  configs/qemu-riscv32_smode_defconfig | 4 ++++
>  configs/qemu-riscv32_spl_defconfig   | 7 +++++++
>  configs/qemu-riscv64_defconfig       | 4 ++++
>  configs/qemu-riscv64_smode_defconfig | 4 ++++
>  configs/qemu-riscv64_spl_defconfig   | 7 +++++++
>  6 files changed, 30 insertions(+)

Reviewed-by: Leo Yu-Chi Liang <ycliang@andestech.com>

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

* Re: [PATCH v4 1/3] lib: Add common semihosting library
  2022-09-19 11:49 ` [PATCH v4 1/3] lib: Add common semihosting library Kautuk Consul
  2022-09-22  9:02   ` Leo Liang
@ 2022-09-22 17:00   ` Sean Anderson
  2022-09-23  4:39     ` Kautuk Consul
  1 sibling, 1 reply; 11+ messages in thread
From: Sean Anderson @ 2022-09-22 17:00 UTC (permalink / raw)
  To: Kautuk Consul, Rayagonda Kokatanur, Rick Chen, Leo, Simon Glass,
	Heinrich Schuchardt, Ilias Apalodimas, Alexandru Gagniuc,
	Philippe Reynes, Rasmus Villemoes, Stefan Roese, Loic Poulain,
	Bin Meng
  Cc: u-boot



On 9/19/22 7:49 AM, Kautuk Consul wrote:
> We factor out the arch-independent parts of the ARM semihosting
> implementation as a common library so that it can be shared
> with RISC-V.
> 
> Signed-off-by: Kautuk Consul <kconsul@ventanamicro.com>
> ---
>  arch/arm/Kconfig           |  46 ---------
>  arch/arm/lib/semihosting.c | 181 +-----------------------------------
>  include/semihosting.h      |  11 +++
>  lib/Kconfig                |  46 +++++++++
>  lib/Makefile               |   2 +
>  lib/semihosting.c          | 186 +++++++++++++++++++++++++++++++++++++
>  6 files changed, 246 insertions(+), 226 deletions(-)
>  create mode 100644 lib/semihosting.c
> 
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 82cd456f51..ee6a9fadd9 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -413,52 +413,6 @@ config ARM_SMCCC
>  	  This should be enabled if U-Boot needs to communicate with system
>  	  firmware (for example, PSCI) according to SMCCC.
>  
> -config SEMIHOSTING
> -	bool "Support ARM semihosting"
> -	help
> -	  Semihosting is a method for a target to communicate with a host
> -	  debugger. It uses special instructions which the debugger will trap
> -	  on and interpret. This allows U-Boot to read/write files, print to
> -	  the console, and execute arbitrary commands on the host system.
> -
> -	  Enabling this option will add support for reading and writing files
> -	  on the host system. If you don't have a debugger attached then trying
> -	  to do this will likely cause U-Boot to hang. Say 'n' if you are unsure.
> -
> -config SEMIHOSTING_FALLBACK
> -	bool "Recover gracefully when semihosting fails"
> -	depends on SEMIHOSTING && ARM64
> -	default y
> -	help
> -	  Normally, if U-Boot makes a semihosting call and no debugger is
> -	  attached, then it will panic due to a synchronous abort
> -	  exception. This config adds an exception handler which will allow
> -	  U-Boot to recover. Say 'y' if unsure.
> -
> -config SPL_SEMIHOSTING
> -	bool "Support ARM semihosting in SPL"
> -	depends on SPL
> -	help
> -	  Semihosting is a method for a target to communicate with a host
> -	  debugger. It uses special instructions which the debugger will trap
> -	  on and interpret. This allows U-Boot to read/write files, print to
> -	  the console, and execute arbitrary commands on the host system.
> -
> -	  Enabling this option will add support for reading and writing files
> -	  on the host system. If you don't have a debugger attached then trying
> -	  to do this will likely cause U-Boot to hang. Say 'n' if you are unsure.
> -
> -config SPL_SEMIHOSTING_FALLBACK
> -	bool "Recover gracefully when semihosting fails in SPL"
> -	depends on SPL_SEMIHOSTING && ARM64
> -	select ARMV8_SPL_EXCEPTION_VECTORS
> -	default y
> -	help
> -	  Normally, if U-Boot makes a semihosting call and no debugger is
> -	  attached, then it will panic due to a synchronous abort
> -	  exception. This config adds an exception handler which will allow
> -	  U-Boot to recover. Say 'y' if unsure.
> -
>  config SYS_THUMB_BUILD
>  	bool "Build U-Boot using the Thumb instruction set"
>  	depends on !ARM64
> diff --git a/arch/arm/lib/semihosting.c b/arch/arm/lib/semihosting.c
> index 01d652a6b8..11e7b85ee6 100644
> --- a/arch/arm/lib/semihosting.c
> +++ b/arch/arm/lib/semihosting.c
> @@ -10,25 +10,11 @@
>   * available in silicon now, fastmodel usage makes less sense for them.
>   */
>  #include <common.h>
> -#include <log.h>
> -#include <semihosting.h>
> -
> -#define SYSOPEN		0x01
> -#define SYSCLOSE	0x02
> -#define SYSWRITEC	0x03
> -#define SYSWRITE0	0x04
> -#define SYSWRITE	0x05
> -#define SYSREAD		0x06
> -#define SYSREADC	0x07
> -#define SYSISERROR	0x08
> -#define SYSSEEK		0x0A
> -#define SYSFLEN		0x0C
> -#define SYSERRNO	0x13
>  
>  /*
>   * Call the handler
>   */
> -static noinline long smh_trap(unsigned int sysnum, void *addr)
> +long smh_trap(unsigned int sysnum, void *addr)
>  {
>  	register long result asm("r0");
>  #if defined(CONFIG_ARM64)
> @@ -41,168 +27,3 @@ static noinline long smh_trap(unsigned int sysnum, void *addr)
>  #endif
>  	return result;
>  }
> -
> -#if CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK)
> -static bool _semihosting_enabled = true;
> -static bool try_semihosting = true;
> -
> -bool semihosting_enabled(void)
> -{
> -	if (try_semihosting) {
> -		smh_trap(SYSERRNO, NULL);
> -		try_semihosting = false;
> -	}
> -
> -	return _semihosting_enabled;
> -}
> -
> -void disable_semihosting(void)
> -{
> -	_semihosting_enabled = false;
> -}
> -#endif
> -
> -/**
> - * smh_errno() - Read the host's errno
> - *
> - * This gets the value of the host's errno and negates it. The host's errno may
> - * or may not be set, so only call this function if a previous semihosting call
> - * has failed.
> - *
> - * Return: a negative error value
> - */
> -static int smh_errno(void)
> -{
> -	long ret = smh_trap(SYSERRNO, NULL);
> -
> -	if (ret > 0 && ret < INT_MAX)
> -		return -ret;
> -	return -EIO;
> -}
> -
> -long smh_open(const char *fname, enum smh_open_mode mode)
> -{
> -	long fd;
> -	struct smh_open_s {
> -		const char *fname;
> -		unsigned long mode;
> -		size_t len;
> -	} open;
> -
> -	debug("%s: file \'%s\', mode \'%u\'\n", __func__, fname, mode);
> -
> -	open.fname = fname;
> -	open.len = strlen(fname);
> -	open.mode = mode;
> -
> -	/* Open the file on the host */
> -	fd = smh_trap(SYSOPEN, &open);
> -	if (fd == -1)
> -		return smh_errno();
> -	return fd;
> -}
> -
> -/**
> - * struct smg_rdwr_s - Arguments for read and write
> - * @fd: A file descriptor returned from smh_open()
> - * @memp: Pointer to a buffer of memory of at least @len bytes
> - * @len: The number of bytes to read or write
> - */
> -struct smh_rdwr_s {
> -	long fd;
> -	void *memp;
> -	size_t len;
> -};
> -
> -long smh_read(long fd, void *memp, size_t len)
> -{
> -	long ret;
> -	struct smh_rdwr_s read;
> -
> -	debug("%s: fd %ld, memp %p, len %zu\n", __func__, fd, memp, len);
> -
> -	read.fd = fd;
> -	read.memp = memp;
> -	read.len = len;
> -
> -	ret = smh_trap(SYSREAD, &read);
> -	if (ret < 0)
> -		return smh_errno();
> -	return len - ret;
> -}
> -
> -long smh_write(long fd, const void *memp, size_t len, ulong *written)
> -{
> -	long ret;
> -	struct smh_rdwr_s write;
> -
> -	debug("%s: fd %ld, memp %p, len %zu\n", __func__, fd, memp, len);
> -
> -	write.fd = fd;
> -	write.memp = (void *)memp;
> -	write.len = len;
> -
> -	ret = smh_trap(SYSWRITE, &write);
> -	*written = len - ret;
> -	if (ret)
> -		return smh_errno();
> -	return 0;
> -}
> -
> -long smh_close(long fd)
> -{
> -	long ret;
> -
> -	debug("%s: fd %ld\n", __func__, fd);
> -
> -	ret = smh_trap(SYSCLOSE, &fd);
> -	if (ret == -1)
> -		return smh_errno();
> -	return 0;
> -}
> -
> -long smh_flen(long fd)
> -{
> -	long ret;
> -
> -	debug("%s: fd %ld\n", __func__, fd);
> -
> -	ret = smh_trap(SYSFLEN, &fd);
> -	if (ret == -1)
> -		return smh_errno();
> -	return ret;
> -}
> -
> -long smh_seek(long fd, long pos)
> -{
> -	long ret;
> -	struct smh_seek_s {
> -		long fd;
> -		long pos;
> -	} seek;
> -
> -	debug("%s: fd %ld pos %ld\n", __func__, fd, pos);
> -
> -	seek.fd = fd;
> -	seek.pos = pos;
> -
> -	ret = smh_trap(SYSSEEK, &seek);
> -	if (ret)
> -		return smh_errno();
> -	return 0;
> -}
> -
> -int smh_getc(void)
> -{
> -	return smh_trap(SYSREADC, NULL);
> -}
> -
> -void smh_putc(char ch)
> -{
> -	smh_trap(SYSWRITEC, &ch);
> -}
> -
> -void smh_puts(const char *s)
> -{
> -	smh_trap(SYSWRITE0, (char *)s);
> -}
> diff --git a/include/semihosting.h b/include/semihosting.h
> index f1f73464e4..4e844cbad8 100644
> --- a/include/semihosting.h
> +++ b/include/semihosting.h
> @@ -17,6 +17,17 @@
>  #define SMH_T32_SVC 0xDFAB
>  #define SMH_T32_HLT 0xBABC
>  
> +/**
> + * smh_trap() - ARCH-specific semihosting call.
> + *
> + * Semihosting library/driver can use this function to do the
> + * actual semihosting calls.
> + *
> + * Return: Error code defined by semihosting spec.
> + */
> +
> +long smh_trap(unsigned int sysnum, void *addr);
> +
>  #if CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK)
>  /**
>   * semihosting_enabled() - Determine whether semihosting is supported
> diff --git a/lib/Kconfig b/lib/Kconfig
> index 6121c80dc8..97920e7552 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -71,6 +71,52 @@ config HAVE_PRIVATE_LIBGCC
>  config LIB_UUID
>  	bool
>  
> +config SEMIHOSTING
> +	bool "Support semihosting"

Should probably depend on ARM (and in the next patch RISCV).

> +	help
> +	  Semihosting is a method for a target to communicate with a host
> +	  debugger. It uses special instructions which the debugger will trap
> +	  on and interpret. This allows U-Boot to read/write files, print to
> +	  the console, and execute arbitrary commands on the host system.
> +
> +	  Enabling this option will add support for reading and writing files
> +	  on the host system. If you don't have a debugger attached then trying
> +	  to do this will likely cause U-Boot to hang. Say 'n' if you are unsure.
> +
> +config SEMIHOSTING_FALLBACK
> +	bool "Recover gracefully when semihosting fails"
> +	depends on SEMIHOSTING && ARM64
> +	default y
> +	help
> +	  Normally, if U-Boot makes a semihosting call and no debugger is
> +	  attached, then it will panic due to a synchronous abort
> +	  exception. This config adds an exception handler which will allow
> +	  U-Boot to recover. Say 'y' if unsure.
> +
> +config SPL_SEMIHOSTING
> +	bool "Support semihosting in SPL"
> +	depends on SPL

ditto

> +	help
> +	  Semihosting is a method for a target to communicate with a host
> +	  debugger. It uses special instructions which the debugger will trap
> +	  on and interpret. This allows U-Boot to read/write files, print to
> +	  the console, and execute arbitrary commands on the host system.
> +
> +	  Enabling this option will add support for reading and writing files
> +	  on the host system. If you don't have a debugger attached then trying
> +	  to do this will likely cause U-Boot to hang. Say 'n' if you are unsure.
> +
> +config SPL_SEMIHOSTING_FALLBACK
> +	bool "Recover gracefully when semihosting fails in SPL"
> +	depends on SPL_SEMIHOSTING && ARM64
> +	select ARMV8_SPL_EXCEPTION_VECTORS
> +	default y
> +	help
> +	  Normally, if U-Boot makes a semihosting call and no debugger is
> +	  attached, then it will panic due to a synchronous abort
> +	  exception. This config adds an exception handler which will allow
> +	  U-Boot to recover. Say 'y' if unsure.
> +
>  config PRINTF
>  	bool
>  	default y
> diff --git a/lib/Makefile b/lib/Makefile
> index e3deb15287..134c4319cd 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -145,6 +145,8 @@ obj-y += date.o
>  obj-y += rtc-lib.o
>  obj-$(CONFIG_LIB_ELF) += elf.o
>  
> +obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o
> +
>  #
>  # Build a fast OID lookup registry from include/linux/oid_registry.h
>  #
> diff --git a/lib/semihosting.c b/lib/semihosting.c
> new file mode 100644
> index 0000000000..831774e356
> --- /dev/null
> +++ b/lib/semihosting.c
> @@ -0,0 +1,186 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2022 Sean Anderson <sean.anderson@seco.com>
> + * Copyright 2014 Broadcom Corporation
> + */
> +
> +#include <common.h>
> +#include <log.h>
> +#include <semihosting.h>
> +
> +#define SYSOPEN		0x01
> +#define SYSCLOSE	0x02
> +#define SYSWRITEC	0x03
> +#define SYSWRITE0	0x04
> +#define SYSWRITE	0x05
> +#define SYSREAD		0x06
> +#define SYSREADC	0x07
> +#define SYSISERROR	0x08
> +#define SYSSEEK		0x0A
> +#define SYSFLEN		0x0C
> +#define SYSERRNO	0x13
> +
> +#if CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK)
> +static bool _semihosting_enabled = true;
> +static bool try_semihosting = true;
> +
> +bool semihosting_enabled(void)
> +{
> +	if (try_semihosting) {
> +		smh_trap(SYSERRNO, NULL);
> +		try_semihosting = false;
> +	}
> +
> +	return _semihosting_enabled;
> +}
> +
> +void disable_semihosting(void)
> +{
> +	_semihosting_enabled = false;
> +}
> +#endif
> +
> +/**
> + * smh_errno() - Read the host's errno
> + *
> + * This gets the value of the host's errno and negates it. The host's errno may
> + * or may not be set, so only call this function if a previous semihosting call
> + * has failed.
> + *
> + * Return: a negative error value
> + */
> +static int smh_errno(void)
> +{
> +	long ret = smh_trap(SYSERRNO, NULL);
> +
> +	if (ret > 0 && ret < INT_MAX)
> +		return -ret;
> +	return -EIO;
> +}
> +
> +long smh_open(const char *fname, enum smh_open_mode mode)
> +{
> +	long fd;
> +	struct smh_open_s {
> +		const char *fname;
> +		unsigned long mode;
> +		size_t len;
> +	} open;
> +
> +	debug("%s: file \'%s\', mode \'%u\'\n", __func__, fname, mode);
> +
> +	open.fname = fname;
> +	open.len = strlen(fname);
> +	open.mode = mode;
> +
> +	/* Open the file on the host */
> +	fd = smh_trap(SYSOPEN, &open);
> +	if (fd == -1)
> +		return smh_errno();
> +	return fd;
> +}
> +
> +/**
> + * struct smg_rdwr_s - Arguments for read and write
> + * @fd: A file descriptor returned from smh_open()
> + * @memp: Pointer to a buffer of memory of at least @len bytes
> + * @len: The number of bytes to read or write
> + */
> +struct smh_rdwr_s {
> +	long fd;
> +	void *memp;
> +	size_t len;
> +};
> +
> +long smh_read(long fd, void *memp, size_t len)
> +{
> +	long ret;
> +	struct smh_rdwr_s read;
> +
> +	debug("%s: fd %ld, memp %p, len %zu\n", __func__, fd, memp, len);
> +
> +	read.fd = fd;
> +	read.memp = memp;
> +	read.len = len;
> +
> +	ret = smh_trap(SYSREAD, &read);
> +	if (ret < 0)
> +		return smh_errno();
> +	return len - ret;
> +}
> +
> +long smh_write(long fd, const void *memp, size_t len, ulong *written)
> +{
> +	long ret;
> +	struct smh_rdwr_s write;
> +
> +	debug("%s: fd %ld, memp %p, len %zu\n", __func__, fd, memp, len);
> +
> +	write.fd = fd;
> +	write.memp = (void *)memp;
> +	write.len = len;
> +
> +	ret = smh_trap(SYSWRITE, &write);
> +	*written = len - ret;
> +	if (ret)
> +		return smh_errno();
> +	return 0;
> +}
> +
> +long smh_close(long fd)
> +{
> +	long ret;
> +
> +	debug("%s: fd %ld\n", __func__, fd);
> +
> +	ret = smh_trap(SYSCLOSE, &fd);
> +	if (ret == -1)
> +		return smh_errno();
> +	return 0;
> +}
> +
> +long smh_flen(long fd)
> +{
> +	long ret;
> +
> +	debug("%s: fd %ld\n", __func__, fd);
> +
> +	ret = smh_trap(SYSFLEN, &fd);
> +	if (ret == -1)
> +		return smh_errno();
> +	return ret;
> +}
> +
> +long smh_seek(long fd, long pos)
> +{
> +	long ret;
> +	struct smh_seek_s {
> +		long fd;
> +		long pos;
> +	} seek;
> +
> +	debug("%s: fd %ld pos %ld\n", __func__, fd, pos);
> +
> +	seek.fd = fd;
> +	seek.pos = pos;
> +
> +	ret = smh_trap(SYSSEEK, &seek);
> +	if (ret)
> +		return smh_errno();
> +	return 0;
> +}
> +
> +int smh_getc(void)
> +{
> +	return smh_trap(SYSREADC, NULL);
> +}
> +
> +void smh_putc(char ch)
> +{
> +	smh_trap(SYSWRITEC, &ch);
> +}
> +
> +void smh_puts(const char *s)
> +{
> +	smh_trap(SYSWRITE0, (char *)s);
> +}
> 

Other than that,

Reviewed-by: Sean Anderson <sean.anderson@seco.com>

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

* Re: [PATCH v4 2/3] arch/riscv: add semihosting support for RISC-V
  2022-09-19 11:49 ` [PATCH v4 2/3] arch/riscv: add semihosting support for RISC-V Kautuk Consul
  2022-09-22  9:03   ` Leo Liang
@ 2022-09-22 17:05   ` Sean Anderson
  2022-09-23  4:57     ` Kautuk Consul
  1 sibling, 1 reply; 11+ messages in thread
From: Sean Anderson @ 2022-09-22 17:05 UTC (permalink / raw)
  To: Kautuk Consul, Rayagonda Kokatanur, Rick Chen, Leo, Simon Glass,
	Heinrich Schuchardt, Ilias Apalodimas, Alexandru Gagniuc,
	Philippe Reynes, Rasmus Villemoes, Stefan Roese, Loic Poulain,
	Bin Meng
  Cc: u-boot, Anup Patel



On 9/19/22 7:49 AM, Kautuk Consul wrote:
> We add RISC-V semihosting based serial console for JTAG based early
> debugging.
> 
> The RISC-V semihosting specification is available at:
> https://github.com/riscv/riscv-semihosting-spec/blob/main/riscv-semihosting-spec.adoc
> 
> Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> Signed-off-by: Kautuk Consul <kconsul@ventanamicro.com>
> ---
>  arch/riscv/include/asm/spl.h |  1 +
>  arch/riscv/lib/Makefile      |  2 ++
>  arch/riscv/lib/interrupts.c  | 11 +++++++++++
>  arch/riscv/lib/semihosting.c | 24 ++++++++++++++++++++++++
>  lib/Kconfig                  |  6 +++---
>  5 files changed, 41 insertions(+), 3 deletions(-)
>  create mode 100644 arch/riscv/lib/semihosting.c
> 
> diff --git a/arch/riscv/include/asm/spl.h b/arch/riscv/include/asm/spl.h
> index e8a94fcb1f..2898a770ee 100644
> --- a/arch/riscv/include/asm/spl.h
> +++ b/arch/riscv/include/asm/spl.h
> @@ -25,6 +25,7 @@ enum {
>  	BOOT_DEVICE_DFU,
>  	BOOT_DEVICE_XIP,
>  	BOOT_DEVICE_BOOTROM,
> +	BOOT_DEVICE_SMH,
>  	BOOT_DEVICE_NONE
>  };
>  
> diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile
> index 06020fcc2a..64e29804c1 100644
> --- a/arch/riscv/lib/Makefile
> +++ b/arch/riscv/lib/Makefile
> @@ -42,3 +42,5 @@ extra-$(CONFIG_EFI) += $(EFI_CRT0) $(EFI_RELOC)
>  obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_MEMSET) += memset.o
>  obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_MEMMOVE) += memmove.o
>  obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_MEMCPY) += memcpy.o
> +
> +obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o
> diff --git a/arch/riscv/lib/interrupts.c b/arch/riscv/lib/interrupts.c
> index 100be2e966..bd7cd772b8 100644
> --- a/arch/riscv/lib/interrupts.c
> +++ b/arch/riscv/lib/interrupts.c
> @@ -17,6 +17,7 @@
>  #include <asm/ptrace.h>
>  #include <asm/system.h>
>  #include <asm/encoding.h>
> +#include <semihosting.h>
>  
>  DECLARE_GLOBAL_DATA_PTR;
>  
> @@ -149,6 +150,16 @@ ulong handle_trap(ulong cause, ulong epc, ulong tval, struct pt_regs *regs)
>  	/* An UEFI application may have changed gd. Restore U-Boot's gd. */
>  	efi_restore_gd();
>  
> +	if (cause == CAUSE_BREAKPOINT &&
> +	    CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK)) {

Hm, shouldn't we check to see if this is actually a semihosting
breakpoint? This involves reading the prior and posterior
instructions, which might be a bit too much. Alternatively, we
could only take this trap if semihosting_enabled(), which would
limit any suppression of spurious breakpoints to one instruction.

> +		/* For semihosting fallback we simply skip the ebreak
> +		 * instruction.
> +		 */
> +		disable_semihosting();
> +		epc += 4;
> +		return epc;
> +	}
> +
>  	is_irq = (cause & MCAUSE_INT);
>  	irq = (cause & ~MCAUSE_INT);
>  
> diff --git a/arch/riscv/lib/semihosting.c b/arch/riscv/lib/semihosting.c
> new file mode 100644
> index 0000000000..d6593b02a6
> --- /dev/null
> +++ b/arch/riscv/lib/semihosting.c
> @@ -0,0 +1,24 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2022 Ventana Micro Systems Inc.
> + */
> +
> +#include <common.h>
> +
> +long smh_trap(int sysnum, void *addr)
> +{
> +	register int ret asm ("a0") = sysnum;
> +	register void *param0 asm ("a1") = addr;
> +
> +	asm volatile (".align 4\n"
> +		".option push\n"
> +		".option norvc\n"
> +
> +		"slli zero, zero, 0x1f\n"
> +		"ebreak\n"
> +		"srai zero, zero, 7\n"
> +		".option pop\n"
> +		: "+r" (ret) : "r" (param0) : "memory");
> +
> +	return ret;
> +}
> diff --git a/lib/Kconfig b/lib/Kconfig
> index 97920e7552..eed3a231d9 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -85,7 +85,7 @@ config SEMIHOSTING
>  
>  config SEMIHOSTING_FALLBACK
>  	bool "Recover gracefully when semihosting fails"
> -	depends on SEMIHOSTING && ARM64
> +	depends on SEMIHOSTING && (ARM64 || RISCV)
>  	default y
>  	help
>  	  Normally, if U-Boot makes a semihosting call and no debugger is
> @@ -108,8 +108,8 @@ config SPL_SEMIHOSTING
>  
>  config SPL_SEMIHOSTING_FALLBACK
>  	bool "Recover gracefully when semihosting fails in SPL"
> -	depends on SPL_SEMIHOSTING && ARM64
> -	select ARMV8_SPL_EXCEPTION_VECTORS
> +	depends on SPL_SEMIHOSTING && (ARM64 || RISCV)
> +	select ARMV8_SPL_EXCEPTION_VECTORS if ARM64
>  	default y
>  	help
>  	  Normally, if U-Boot makes a semihosting call and no debugger is
> 

The rest looks fine.

--Sean

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

* Re: [PATCH v4 1/3] lib: Add common semihosting library
  2022-09-22 17:00   ` Sean Anderson
@ 2022-09-23  4:39     ` Kautuk Consul
  0 siblings, 0 replies; 11+ messages in thread
From: Kautuk Consul @ 2022-09-23  4:39 UTC (permalink / raw)
  To: Sean Anderson
  Cc: Rayagonda Kokatanur, Rick Chen, Leo, Simon Glass,
	Heinrich Schuchardt, Ilias Apalodimas, Alexandru Gagniuc,
	Philippe Reynes, Rasmus Villemoes, Stefan Roese, Loic Poulain,
	Bin Meng, u-boot

Hi Sean,

On Thu, Sep 22, 2022 at 10:30 PM Sean Anderson <sean.anderson@seco.com> wrote:
>
>
>
> On 9/19/22 7:49 AM, Kautuk Consul wrote:
> > We factor out the arch-independent parts of the ARM semihosting
> > implementation as a common library so that it can be shared
> > with RISC-V.
> >
> > Signed-off-by: Kautuk Consul <kconsul@ventanamicro.com>
> > ---
> >  arch/arm/Kconfig           |  46 ---------
> >  arch/arm/lib/semihosting.c | 181 +-----------------------------------
> >  include/semihosting.h      |  11 +++
> >  lib/Kconfig                |  46 +++++++++
> >  lib/Makefile               |   2 +
> >  lib/semihosting.c          | 186 +++++++++++++++++++++++++++++++++++++
> >  6 files changed, 246 insertions(+), 226 deletions(-)
> >  create mode 100644 lib/semihosting.c
> >
> > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> > index 82cd456f51..ee6a9fadd9 100644
> > --- a/arch/arm/Kconfig
> > +++ b/arch/arm/Kconfig
> > @@ -413,52 +413,6 @@ config ARM_SMCCC
> >         This should be enabled if U-Boot needs to communicate with system
> >         firmware (for example, PSCI) according to SMCCC.
> >
> > -config SEMIHOSTING
> > -     bool "Support ARM semihosting"
> > -     help
> > -       Semihosting is a method for a target to communicate with a host
> > -       debugger. It uses special instructions which the debugger will trap
> > -       on and interpret. This allows U-Boot to read/write files, print to
> > -       the console, and execute arbitrary commands on the host system.
> > -
> > -       Enabling this option will add support for reading and writing files
> > -       on the host system. If you don't have a debugger attached then trying
> > -       to do this will likely cause U-Boot to hang. Say 'n' if you are unsure.
> > -
> > -config SEMIHOSTING_FALLBACK
> > -     bool "Recover gracefully when semihosting fails"
> > -     depends on SEMIHOSTING && ARM64
> > -     default y
> > -     help
> > -       Normally, if U-Boot makes a semihosting call and no debugger is
> > -       attached, then it will panic due to a synchronous abort
> > -       exception. This config adds an exception handler which will allow
> > -       U-Boot to recover. Say 'y' if unsure.
> > -
> > -config SPL_SEMIHOSTING
> > -     bool "Support ARM semihosting in SPL"
> > -     depends on SPL
> > -     help
> > -       Semihosting is a method for a target to communicate with a host
> > -       debugger. It uses special instructions which the debugger will trap
> > -       on and interpret. This allows U-Boot to read/write files, print to
> > -       the console, and execute arbitrary commands on the host system.
> > -
> > -       Enabling this option will add support for reading and writing files
> > -       on the host system. If you don't have a debugger attached then trying
> > -       to do this will likely cause U-Boot to hang. Say 'n' if you are unsure.
> > -
> > -config SPL_SEMIHOSTING_FALLBACK
> > -     bool "Recover gracefully when semihosting fails in SPL"
> > -     depends on SPL_SEMIHOSTING && ARM64
> > -     select ARMV8_SPL_EXCEPTION_VECTORS
> > -     default y
> > -     help
> > -       Normally, if U-Boot makes a semihosting call and no debugger is
> > -       attached, then it will panic due to a synchronous abort
> > -       exception. This config adds an exception handler which will allow
> > -       U-Boot to recover. Say 'y' if unsure.
> > -
> >  config SYS_THUMB_BUILD
> >       bool "Build U-Boot using the Thumb instruction set"
> >       depends on !ARM64
> > diff --git a/arch/arm/lib/semihosting.c b/arch/arm/lib/semihosting.c
> > index 01d652a6b8..11e7b85ee6 100644
> > --- a/arch/arm/lib/semihosting.c
> > +++ b/arch/arm/lib/semihosting.c
> > @@ -10,25 +10,11 @@
> >   * available in silicon now, fastmodel usage makes less sense for them.
> >   */
> >  #include <common.h>
> > -#include <log.h>
> > -#include <semihosting.h>
> > -
> > -#define SYSOPEN              0x01
> > -#define SYSCLOSE     0x02
> > -#define SYSWRITEC    0x03
> > -#define SYSWRITE0    0x04
> > -#define SYSWRITE     0x05
> > -#define SYSREAD              0x06
> > -#define SYSREADC     0x07
> > -#define SYSISERROR   0x08
> > -#define SYSSEEK              0x0A
> > -#define SYSFLEN              0x0C
> > -#define SYSERRNO     0x13
> >
> >  /*
> >   * Call the handler
> >   */
> > -static noinline long smh_trap(unsigned int sysnum, void *addr)
> > +long smh_trap(unsigned int sysnum, void *addr)
> >  {
> >       register long result asm("r0");
> >  #if defined(CONFIG_ARM64)
> > @@ -41,168 +27,3 @@ static noinline long smh_trap(unsigned int sysnum, void *addr)
> >  #endif
> >       return result;
> >  }
> > -
> > -#if CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK)
> > -static bool _semihosting_enabled = true;
> > -static bool try_semihosting = true;
> > -
> > -bool semihosting_enabled(void)
> > -{
> > -     if (try_semihosting) {
> > -             smh_trap(SYSERRNO, NULL);
> > -             try_semihosting = false;
> > -     }
> > -
> > -     return _semihosting_enabled;
> > -}
> > -
> > -void disable_semihosting(void)
> > -{
> > -     _semihosting_enabled = false;
> > -}
> > -#endif
> > -
> > -/**
> > - * smh_errno() - Read the host's errno
> > - *
> > - * This gets the value of the host's errno and negates it. The host's errno may
> > - * or may not be set, so only call this function if a previous semihosting call
> > - * has failed.
> > - *
> > - * Return: a negative error value
> > - */
> > -static int smh_errno(void)
> > -{
> > -     long ret = smh_trap(SYSERRNO, NULL);
> > -
> > -     if (ret > 0 && ret < INT_MAX)
> > -             return -ret;
> > -     return -EIO;
> > -}
> > -
> > -long smh_open(const char *fname, enum smh_open_mode mode)
> > -{
> > -     long fd;
> > -     struct smh_open_s {
> > -             const char *fname;
> > -             unsigned long mode;
> > -             size_t len;
> > -     } open;
> > -
> > -     debug("%s: file \'%s\', mode \'%u\'\n", __func__, fname, mode);
> > -
> > -     open.fname = fname;
> > -     open.len = strlen(fname);
> > -     open.mode = mode;
> > -
> > -     /* Open the file on the host */
> > -     fd = smh_trap(SYSOPEN, &open);
> > -     if (fd == -1)
> > -             return smh_errno();
> > -     return fd;
> > -}
> > -
> > -/**
> > - * struct smg_rdwr_s - Arguments for read and write
> > - * @fd: A file descriptor returned from smh_open()
> > - * @memp: Pointer to a buffer of memory of at least @len bytes
> > - * @len: The number of bytes to read or write
> > - */
> > -struct smh_rdwr_s {
> > -     long fd;
> > -     void *memp;
> > -     size_t len;
> > -};
> > -
> > -long smh_read(long fd, void *memp, size_t len)
> > -{
> > -     long ret;
> > -     struct smh_rdwr_s read;
> > -
> > -     debug("%s: fd %ld, memp %p, len %zu\n", __func__, fd, memp, len);
> > -
> > -     read.fd = fd;
> > -     read.memp = memp;
> > -     read.len = len;
> > -
> > -     ret = smh_trap(SYSREAD, &read);
> > -     if (ret < 0)
> > -             return smh_errno();
> > -     return len - ret;
> > -}
> > -
> > -long smh_write(long fd, const void *memp, size_t len, ulong *written)
> > -{
> > -     long ret;
> > -     struct smh_rdwr_s write;
> > -
> > -     debug("%s: fd %ld, memp %p, len %zu\n", __func__, fd, memp, len);
> > -
> > -     write.fd = fd;
> > -     write.memp = (void *)memp;
> > -     write.len = len;
> > -
> > -     ret = smh_trap(SYSWRITE, &write);
> > -     *written = len - ret;
> > -     if (ret)
> > -             return smh_errno();
> > -     return 0;
> > -}
> > -
> > -long smh_close(long fd)
> > -{
> > -     long ret;
> > -
> > -     debug("%s: fd %ld\n", __func__, fd);
> > -
> > -     ret = smh_trap(SYSCLOSE, &fd);
> > -     if (ret == -1)
> > -             return smh_errno();
> > -     return 0;
> > -}
> > -
> > -long smh_flen(long fd)
> > -{
> > -     long ret;
> > -
> > -     debug("%s: fd %ld\n", __func__, fd);
> > -
> > -     ret = smh_trap(SYSFLEN, &fd);
> > -     if (ret == -1)
> > -             return smh_errno();
> > -     return ret;
> > -}
> > -
> > -long smh_seek(long fd, long pos)
> > -{
> > -     long ret;
> > -     struct smh_seek_s {
> > -             long fd;
> > -             long pos;
> > -     } seek;
> > -
> > -     debug("%s: fd %ld pos %ld\n", __func__, fd, pos);
> > -
> > -     seek.fd = fd;
> > -     seek.pos = pos;
> > -
> > -     ret = smh_trap(SYSSEEK, &seek);
> > -     if (ret)
> > -             return smh_errno();
> > -     return 0;
> > -}
> > -
> > -int smh_getc(void)
> > -{
> > -     return smh_trap(SYSREADC, NULL);
> > -}
> > -
> > -void smh_putc(char ch)
> > -{
> > -     smh_trap(SYSWRITEC, &ch);
> > -}
> > -
> > -void smh_puts(const char *s)
> > -{
> > -     smh_trap(SYSWRITE0, (char *)s);
> > -}
> > diff --git a/include/semihosting.h b/include/semihosting.h
> > index f1f73464e4..4e844cbad8 100644
> > --- a/include/semihosting.h
> > +++ b/include/semihosting.h
> > @@ -17,6 +17,17 @@
> >  #define SMH_T32_SVC 0xDFAB
> >  #define SMH_T32_HLT 0xBABC
> >
> > +/**
> > + * smh_trap() - ARCH-specific semihosting call.
> > + *
> > + * Semihosting library/driver can use this function to do the
> > + * actual semihosting calls.
> > + *
> > + * Return: Error code defined by semihosting spec.
> > + */
> > +
> > +long smh_trap(unsigned int sysnum, void *addr);
> > +
> >  #if CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK)
> >  /**
> >   * semihosting_enabled() - Determine whether semihosting is supported
> > diff --git a/lib/Kconfig b/lib/Kconfig
> > index 6121c80dc8..97920e7552 100644
> > --- a/lib/Kconfig
> > +++ b/lib/Kconfig
> > @@ -71,6 +71,52 @@ config HAVE_PRIVATE_LIBGCC
> >  config LIB_UUID
> >       bool
> >
> > +config SEMIHOSTING
> > +     bool "Support semihosting"
>
> Should probably depend on ARM (and in the next patch RISCV).

I did think of this. The fallback part appears to be arch-dependent.
But can we make the main SEMIHOSTING options as arch-independent
as that was the way they were before ?
>
> > +     help
> > +       Semihosting is a method for a target to communicate with a host
> > +       debugger. It uses special instructions which the debugger will trap
> > +       on and interpret. This allows U-Boot to read/write files, print to
> > +       the console, and execute arbitrary commands on the host system.
> > +
> > +       Enabling this option will add support for reading and writing files
> > +       on the host system. If you don't have a debugger attached then trying
> > +       to do this will likely cause U-Boot to hang. Say 'n' if you are unsure.
> > +
> > +config SEMIHOSTING_FALLBACK
> > +     bool "Recover gracefully when semihosting fails"
> > +     depends on SEMIHOSTING && ARM64
> > +     default y
> > +     help
> > +       Normally, if U-Boot makes a semihosting call and no debugger is
> > +       attached, then it will panic due to a synchronous abort
> > +       exception. This config adds an exception handler which will allow
> > +       U-Boot to recover. Say 'y' if unsure.
> > +
> > +config SPL_SEMIHOSTING
> > +     bool "Support semihosting in SPL"
> > +     depends on SPL
>
> ditto
>
> > +     help
> > +       Semihosting is a method for a target to communicate with a host
> > +       debugger. It uses special instructions which the debugger will trap
> > +       on and interpret. This allows U-Boot to read/write files, print to
> > +       the console, and execute arbitrary commands on the host system.
> > +
> > +       Enabling this option will add support for reading and writing files
> > +       on the host system. If you don't have a debugger attached then trying
> > +       to do this will likely cause U-Boot to hang. Say 'n' if you are unsure.
> > +
> > +config SPL_SEMIHOSTING_FALLBACK
> > +     bool "Recover gracefully when semihosting fails in SPL"
> > +     depends on SPL_SEMIHOSTING && ARM64
> > +     select ARMV8_SPL_EXCEPTION_VECTORS
> > +     default y
> > +     help
> > +       Normally, if U-Boot makes a semihosting call and no debugger is
> > +       attached, then it will panic due to a synchronous abort
> > +       exception. This config adds an exception handler which will allow
> > +       U-Boot to recover. Say 'y' if unsure.
> > +
> >  config PRINTF
> >       bool
> >       default y
> > diff --git a/lib/Makefile b/lib/Makefile
> > index e3deb15287..134c4319cd 100644
> > --- a/lib/Makefile
> > +++ b/lib/Makefile
> > @@ -145,6 +145,8 @@ obj-y += date.o
> >  obj-y += rtc-lib.o
> >  obj-$(CONFIG_LIB_ELF) += elf.o
> >
> > +obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o
> > +
> >  #
> >  # Build a fast OID lookup registry from include/linux/oid_registry.h
> >  #
> > diff --git a/lib/semihosting.c b/lib/semihosting.c
> > new file mode 100644
> > index 0000000000..831774e356
> > --- /dev/null
> > +++ b/lib/semihosting.c
> > @@ -0,0 +1,186 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Copyright (C) 2022 Sean Anderson <sean.anderson@seco.com>
> > + * Copyright 2014 Broadcom Corporation
> > + */
> > +
> > +#include <common.h>
> > +#include <log.h>
> > +#include <semihosting.h>
> > +
> > +#define SYSOPEN              0x01
> > +#define SYSCLOSE     0x02
> > +#define SYSWRITEC    0x03
> > +#define SYSWRITE0    0x04
> > +#define SYSWRITE     0x05
> > +#define SYSREAD              0x06
> > +#define SYSREADC     0x07
> > +#define SYSISERROR   0x08
> > +#define SYSSEEK              0x0A
> > +#define SYSFLEN              0x0C
> > +#define SYSERRNO     0x13
> > +
> > +#if CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK)
> > +static bool _semihosting_enabled = true;
> > +static bool try_semihosting = true;
> > +
> > +bool semihosting_enabled(void)
> > +{
> > +     if (try_semihosting) {
> > +             smh_trap(SYSERRNO, NULL);
> > +             try_semihosting = false;
> > +     }
> > +
> > +     return _semihosting_enabled;
> > +}
> > +
> > +void disable_semihosting(void)
> > +{
> > +     _semihosting_enabled = false;
> > +}
> > +#endif
> > +
> > +/**
> > + * smh_errno() - Read the host's errno
> > + *
> > + * This gets the value of the host's errno and negates it. The host's errno may
> > + * or may not be set, so only call this function if a previous semihosting call
> > + * has failed.
> > + *
> > + * Return: a negative error value
> > + */
> > +static int smh_errno(void)
> > +{
> > +     long ret = smh_trap(SYSERRNO, NULL);
> > +
> > +     if (ret > 0 && ret < INT_MAX)
> > +             return -ret;
> > +     return -EIO;
> > +}
> > +
> > +long smh_open(const char *fname, enum smh_open_mode mode)
> > +{
> > +     long fd;
> > +     struct smh_open_s {
> > +             const char *fname;
> > +             unsigned long mode;
> > +             size_t len;
> > +     } open;
> > +
> > +     debug("%s: file \'%s\', mode \'%u\'\n", __func__, fname, mode);
> > +
> > +     open.fname = fname;
> > +     open.len = strlen(fname);
> > +     open.mode = mode;
> > +
> > +     /* Open the file on the host */
> > +     fd = smh_trap(SYSOPEN, &open);
> > +     if (fd == -1)
> > +             return smh_errno();
> > +     return fd;
> > +}
> > +
> > +/**
> > + * struct smg_rdwr_s - Arguments for read and write
> > + * @fd: A file descriptor returned from smh_open()
> > + * @memp: Pointer to a buffer of memory of at least @len bytes
> > + * @len: The number of bytes to read or write
> > + */
> > +struct smh_rdwr_s {
> > +     long fd;
> > +     void *memp;
> > +     size_t len;
> > +};
> > +
> > +long smh_read(long fd, void *memp, size_t len)
> > +{
> > +     long ret;
> > +     struct smh_rdwr_s read;
> > +
> > +     debug("%s: fd %ld, memp %p, len %zu\n", __func__, fd, memp, len);
> > +
> > +     read.fd = fd;
> > +     read.memp = memp;
> > +     read.len = len;
> > +
> > +     ret = smh_trap(SYSREAD, &read);
> > +     if (ret < 0)
> > +             return smh_errno();
> > +     return len - ret;
> > +}
> > +
> > +long smh_write(long fd, const void *memp, size_t len, ulong *written)
> > +{
> > +     long ret;
> > +     struct smh_rdwr_s write;
> > +
> > +     debug("%s: fd %ld, memp %p, len %zu\n", __func__, fd, memp, len);
> > +
> > +     write.fd = fd;
> > +     write.memp = (void *)memp;
> > +     write.len = len;
> > +
> > +     ret = smh_trap(SYSWRITE, &write);
> > +     *written = len - ret;
> > +     if (ret)
> > +             return smh_errno();
> > +     return 0;
> > +}
> > +
> > +long smh_close(long fd)
> > +{
> > +     long ret;
> > +
> > +     debug("%s: fd %ld\n", __func__, fd);
> > +
> > +     ret = smh_trap(SYSCLOSE, &fd);
> > +     if (ret == -1)
> > +             return smh_errno();
> > +     return 0;
> > +}
> > +
> > +long smh_flen(long fd)
> > +{
> > +     long ret;
> > +
> > +     debug("%s: fd %ld\n", __func__, fd);
> > +
> > +     ret = smh_trap(SYSFLEN, &fd);
> > +     if (ret == -1)
> > +             return smh_errno();
> > +     return ret;
> > +}
> > +
> > +long smh_seek(long fd, long pos)
> > +{
> > +     long ret;
> > +     struct smh_seek_s {
> > +             long fd;
> > +             long pos;
> > +     } seek;
> > +
> > +     debug("%s: fd %ld pos %ld\n", __func__, fd, pos);
> > +
> > +     seek.fd = fd;
> > +     seek.pos = pos;
> > +
> > +     ret = smh_trap(SYSSEEK, &seek);
> > +     if (ret)
> > +             return smh_errno();
> > +     return 0;
> > +}
> > +
> > +int smh_getc(void)
> > +{
> > +     return smh_trap(SYSREADC, NULL);
> > +}
> > +
> > +void smh_putc(char ch)
> > +{
> > +     smh_trap(SYSWRITEC, &ch);
> > +}
> > +
> > +void smh_puts(const char *s)
> > +{
> > +     smh_trap(SYSWRITE0, (char *)s);
> > +}
> >
>
> Other than that,
>
> Reviewed-by: Sean Anderson <sean.anderson@seco.com>

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

* Re: [PATCH v4 2/3] arch/riscv: add semihosting support for RISC-V
  2022-09-22 17:05   ` Sean Anderson
@ 2022-09-23  4:57     ` Kautuk Consul
  0 siblings, 0 replies; 11+ messages in thread
From: Kautuk Consul @ 2022-09-23  4:57 UTC (permalink / raw)
  To: Sean Anderson
  Cc: Rayagonda Kokatanur, Rick Chen, Leo, Simon Glass,
	Heinrich Schuchardt, Ilias Apalodimas, Alexandru Gagniuc,
	Philippe Reynes, Rasmus Villemoes, Stefan Roese, Loic Poulain,
	Bin Meng, u-boot, Anup Patel

Hi Sean,

On Thu, Sep 22, 2022 at 10:35 PM Sean Anderson <sean.anderson@seco.com> wrote:
>
>
>
> On 9/19/22 7:49 AM, Kautuk Consul wrote:
> > We add RISC-V semihosting based serial console for JTAG based early
> > debugging.
> >
> > The RISC-V semihosting specification is available at:
> > https://github.com/riscv/riscv-semihosting-spec/blob/main/riscv-semihosting-spec.adoc
> >
> > Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> > Signed-off-by: Kautuk Consul <kconsul@ventanamicro.com>
> > ---
> >  arch/riscv/include/asm/spl.h |  1 +
> >  arch/riscv/lib/Makefile      |  2 ++
> >  arch/riscv/lib/interrupts.c  | 11 +++++++++++
> >  arch/riscv/lib/semihosting.c | 24 ++++++++++++++++++++++++
> >  lib/Kconfig                  |  6 +++---
> >  5 files changed, 41 insertions(+), 3 deletions(-)
> >  create mode 100644 arch/riscv/lib/semihosting.c
> >
> > diff --git a/arch/riscv/include/asm/spl.h b/arch/riscv/include/asm/spl.h
> > index e8a94fcb1f..2898a770ee 100644
> > --- a/arch/riscv/include/asm/spl.h
> > +++ b/arch/riscv/include/asm/spl.h
> > @@ -25,6 +25,7 @@ enum {
> >       BOOT_DEVICE_DFU,
> >       BOOT_DEVICE_XIP,
> >       BOOT_DEVICE_BOOTROM,
> > +     BOOT_DEVICE_SMH,
> >       BOOT_DEVICE_NONE
> >  };
> >
> > diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile
> > index 06020fcc2a..64e29804c1 100644
> > --- a/arch/riscv/lib/Makefile
> > +++ b/arch/riscv/lib/Makefile
> > @@ -42,3 +42,5 @@ extra-$(CONFIG_EFI) += $(EFI_CRT0) $(EFI_RELOC)
> >  obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_MEMSET) += memset.o
> >  obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_MEMMOVE) += memmove.o
> >  obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_MEMCPY) += memcpy.o
> > +
> > +obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o
> > diff --git a/arch/riscv/lib/interrupts.c b/arch/riscv/lib/interrupts.c
> > index 100be2e966..bd7cd772b8 100644
> > --- a/arch/riscv/lib/interrupts.c
> > +++ b/arch/riscv/lib/interrupts.c
> > @@ -17,6 +17,7 @@
> >  #include <asm/ptrace.h>
> >  #include <asm/system.h>
> >  #include <asm/encoding.h>
> > +#include <semihosting.h>
> >
> >  DECLARE_GLOBAL_DATA_PTR;
> >
> > @@ -149,6 +150,16 @@ ulong handle_trap(ulong cause, ulong epc, ulong tval, struct pt_regs *regs)
> >       /* An UEFI application may have changed gd. Restore U-Boot's gd. */
> >       efi_restore_gd();
> >
> > +     if (cause == CAUSE_BREAKPOINT &&
> > +         CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK)) {
>
> Hm, shouldn't we check to see if this is actually a semihosting
> breakpoint? This involves reading the prior and posterior
> instructions, which might be a bit too much. Alternatively, we
> could only take this trap if semihosting_enabled(), which would
> limit any suppression of spurious breakpoints to one instruction.
>

Agreed. Will read the prior and posterior instructions in v5 and send this out.
Thanks.

> > +             /* For semihosting fallback we simply skip the ebreak
> > +              * instruction.
> > +              */
> > +             disable_semihosting();
> > +             epc += 4;
> > +             return epc;
> > +     }
> > +
> >       is_irq = (cause & MCAUSE_INT);
> >       irq = (cause & ~MCAUSE_INT);
> >
> > diff --git a/arch/riscv/lib/semihosting.c b/arch/riscv/lib/semihosting.c
> > new file mode 100644
> > index 0000000000..d6593b02a6
> > --- /dev/null
> > +++ b/arch/riscv/lib/semihosting.c
> > @@ -0,0 +1,24 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Copyright (C) 2022 Ventana Micro Systems Inc.
> > + */
> > +
> > +#include <common.h>
> > +
> > +long smh_trap(int sysnum, void *addr)
> > +{
> > +     register int ret asm ("a0") = sysnum;
> > +     register void *param0 asm ("a1") = addr;
> > +
> > +     asm volatile (".align 4\n"
> > +             ".option push\n"
> > +             ".option norvc\n"
> > +
> > +             "slli zero, zero, 0x1f\n"
> > +             "ebreak\n"
> > +             "srai zero, zero, 7\n"
> > +             ".option pop\n"
> > +             : "+r" (ret) : "r" (param0) : "memory");
> > +
> > +     return ret;
> > +}
> > diff --git a/lib/Kconfig b/lib/Kconfig
> > index 97920e7552..eed3a231d9 100644
> > --- a/lib/Kconfig
> > +++ b/lib/Kconfig
> > @@ -85,7 +85,7 @@ config SEMIHOSTING
> >
> >  config SEMIHOSTING_FALLBACK
> >       bool "Recover gracefully when semihosting fails"
> > -     depends on SEMIHOSTING && ARM64
> > +     depends on SEMIHOSTING && (ARM64 || RISCV)
> >       default y
> >       help
> >         Normally, if U-Boot makes a semihosting call and no debugger is
> > @@ -108,8 +108,8 @@ config SPL_SEMIHOSTING
> >
> >  config SPL_SEMIHOSTING_FALLBACK
> >       bool "Recover gracefully when semihosting fails in SPL"
> > -     depends on SPL_SEMIHOSTING && ARM64
> > -     select ARMV8_SPL_EXCEPTION_VECTORS
> > +     depends on SPL_SEMIHOSTING && (ARM64 || RISCV)
> > +     select ARMV8_SPL_EXCEPTION_VECTORS if ARM64
> >       default y
> >       help
> >         Normally, if U-Boot makes a semihosting call and no debugger is
> >
>
> The rest looks fine.
>
> --Sean

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

end of thread, other threads:[~2022-09-23  4:57 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-19 11:49 [PATCH v4 0/3] Add riscv semihosting support in u-boot Kautuk Consul
2022-09-19 11:49 ` [PATCH v4 1/3] lib: Add common semihosting library Kautuk Consul
2022-09-22  9:02   ` Leo Liang
2022-09-22 17:00   ` Sean Anderson
2022-09-23  4:39     ` Kautuk Consul
2022-09-19 11:49 ` [PATCH v4 2/3] arch/riscv: add semihosting support for RISC-V Kautuk Consul
2022-09-22  9:03   ` Leo Liang
2022-09-22 17:05   ` Sean Anderson
2022-09-23  4:57     ` Kautuk Consul
2022-09-19 11:49 ` [PATCH v4 3/3] board: qemu-riscv: enable semihosting Kautuk Consul
2022-09-22  9:03   ` Leo Liang

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