* [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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).