mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 0/6] semihosting: extend support for ARM64, console
@ 2024-06-11  6:59 Ahmad Fatoum
  2024-06-11  6:59 ` [PATCH 1/6] ARM: lib32: semihosting: prepare for more general use Ahmad Fatoum
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Ahmad Fatoum @ 2024-06-11  6:59 UTC (permalink / raw)
  To: barebox

So far, we limited semihosting support to 32-bit ARM, but it's also
usable on ARM64 and even RISC-V.

This series does the first step by making it compile for ARM64 and also
adds DEBUG_LL and console drivers.

Ahmad Fatoum (6):
  ARM: lib32: semihosting: prepare for more general use
  firmware: semihosting: add ARMv8-A semihosting support
  firmware: semihosting: don't return error code from writec/write0
  firmware: semihosting: translate return values in wrappers
  ARM: semihosting: add DEBUG_LL implementation
  serial: add semihosting console

 arch/arm/Kconfig                              |  2 +-
 arch/arm/cpu/Makefile                         |  2 +
 .../semihosting-trap_32.S}                    |  2 +-
 arch/arm/cpu/semihosting-trap_64.S            | 10 ++
 arch/arm/include/asm/debug_ll.h               |  4 +
 arch/arm/include/asm/semihosting.h            | 47 ++++++---
 arch/arm/lib32/Makefile                       |  1 -
 common/Kconfig.debug_ll                       | 13 +++
 drivers/firmware/Kconfig                      |  4 +
 drivers/firmware/Makefile                     |  1 +
 .../lib32 => drivers/firmware}/semihosting.c  | 99 ++++++++++---------
 drivers/serial/Kconfig                        |  8 ++
 drivers/serial/Makefile                       |  1 +
 drivers/serial/serial_semihosting.c           | 44 +++++++++
 fs/Kconfig                                    |  2 +-
 fs/smhfs.c                                    | 37 +++----
 include/asm-generic/semihosting.h             | 23 +++++
 include/debug_ll/semihosting.h                | 15 +++
 18 files changed, 227 insertions(+), 88 deletions(-)
 rename arch/arm/{lib32/semihosting-trap.S => cpu/semihosting-trap_32.S} (84%)
 create mode 100644 arch/arm/cpu/semihosting-trap_64.S
 rename {arch/arm/lib32 => drivers/firmware}/semihosting.c (64%)
 create mode 100644 drivers/serial/serial_semihosting.c
 create mode 100644 include/asm-generic/semihosting.h
 create mode 100644 include/debug_ll/semihosting.h

-- 
2.39.2




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

* [PATCH 1/6] ARM: lib32: semihosting: prepare for more general use
  2024-06-11  6:59 [PATCH 0/6] semihosting: extend support for ARM64, console Ahmad Fatoum
@ 2024-06-11  6:59 ` Ahmad Fatoum
  2024-06-11  6:59 ` [PATCH 2/6] firmware: semihosting: add ARMv8-A semihosting support Ahmad Fatoum
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Ahmad Fatoum @ 2024-06-11  6:59 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

So far, we limited semihosting support to 32-bit ARM, but it's also
usable on ARM64 and even RISC-V. Move the common code to
drivers/firmware, so it can be shared by all architectures.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/arm/Kconfig                              |  1 +
 arch/arm/cpu/Makefile                         |  2 ++
 .../semihosting-trap_32.S}                    |  2 +-
 arch/arm/include/asm/semihosting.h            | 15 +-----------
 arch/arm/lib32/Makefile                       |  1 -
 drivers/firmware/Kconfig                      |  3 +++
 drivers/firmware/Makefile                     |  1 +
 .../lib32 => drivers/firmware}/semihosting.c  |  0
 fs/Kconfig                                    |  2 +-
 include/asm-generic/semihosting.h             | 23 +++++++++++++++++++
 10 files changed, 33 insertions(+), 17 deletions(-)
 rename arch/arm/{lib32/semihosting-trap.S => cpu/semihosting-trap_32.S} (84%)
 rename {arch/arm/lib32 => drivers/firmware}/semihosting.c (100%)
 create mode 100644 include/asm-generic/semihosting.h

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index be18b609c782..26547cd3ba71 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -373,6 +373,7 @@ config ARM_UNWIND
 config ARM_SEMIHOSTING
 	bool "enable ARM semihosting support"
 	depends on !CPU_V8
+	select SEMIHOSTING
 	help
 	  This option enables ARM semihosting support in barebox. ARM
 	  semihosting is a communication discipline that allows code
diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile
index 28161cd7d714..999cc375da1c 100644
--- a/arch/arm/cpu/Makefile
+++ b/arch/arm/cpu/Makefile
@@ -23,6 +23,8 @@ obj-pbl-y += setupc_$(S64_32).o cache_$(S64_32).o
 
 obj-$(CONFIG_ARM_PSCI_CLIENT) += psci-client.o
 
+obj-$(CONFIG_ARM_SEMIHOSTING) += semihosting-trap_$(S64_32).o
+
 #
 # Any variants can be called as start-armxyz.S
 #
diff --git a/arch/arm/lib32/semihosting-trap.S b/arch/arm/cpu/semihosting-trap_32.S
similarity index 84%
rename from arch/arm/lib32/semihosting-trap.S
rename to arch/arm/cpu/semihosting-trap_32.S
index f7960d7cea96..069cdaa1dd38 100644
--- a/arch/arm/lib32/semihosting-trap.S
+++ b/arch/arm/cpu/semihosting-trap_32.S
@@ -2,7 +2,7 @@
 /* SPDX-FileCopyrightText: 2015 Zodiac Inflight Innovations */
 
 /*
- * semihosting-trap.S -- Assembly code needed to make a semihosting call
+ * semihosting-trap_32.S -- Assembly code needed to make a semihosting call
  *
  * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
  */
diff --git a/arch/arm/include/asm/semihosting.h b/arch/arm/include/asm/semihosting.h
index 9e1606c4aeaa..c18aa1a5fef5 100644
--- a/arch/arm/include/asm/semihosting.h
+++ b/arch/arm/include/asm/semihosting.h
@@ -3,19 +3,6 @@
 #ifndef __ASM_ARM_SEMIHOSTING_H
 #define __ASM_ARM_SEMIHOSTING_H
 
-int semihosting_open(const char *fname, int flags);
-int semihosting_close(int fd);
-int semihosting_writec(char c);
-int semihosting_write0(const char *str);
-ssize_t semihosting_write(int fd, const void *buf, size_t count);
-ssize_t semihosting_read(int fd, void *buf, size_t count);
-int semihosting_readc(void);
-int semihosting_isatty(int fd);
-int semihosting_seek(int fd, loff_t pos);
-int semihosting_flen(int fd);
-int semihosting_remove(const char *fname);
-int semihosting_rename(const char *fname1, const char *fname2);
-int semihosting_errno(void);
-int semihosting_system(const char *command);
+#include <asm-generic/semihosting.h>
 
 #endif
diff --git a/arch/arm/lib32/Makefile b/arch/arm/lib32/Makefile
index d54fb7644c39..511a029062e6 100644
--- a/arch/arm/lib32/Makefile
+++ b/arch/arm/lib32/Makefile
@@ -23,7 +23,6 @@ pbl-y	+= runtime-offset.o
 obj-$(CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS)	+= memcpy.o
 obj-$(CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS)	+= memset.o
 obj-$(CONFIG_ARM_UNWIND) += unwind.o
-obj-$(CONFIG_ARM_SEMIHOSTING) += semihosting-trap.o semihosting.o
 obj-$(CONFIG_MODULES) += module.o
 obj-$(CONFIG_ARM_MODULE_PLTS) += module-plts.o
 extra-y += barebox.lds
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 3252b61bc764..89c8bdeda3f0 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -1,6 +1,9 @@
 # SPDX-License-Identifier: GPL-2.0-only
 menu "Firmware Drivers"
 
+config SEMIHOSTING
+	bool
+
 config FIRMWARE_ALTERA_SERIAL
 	bool "Altera SPI programming"
 	depends on OFDEVICE
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 4eabf42fd639..d0ebe663ea55 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_SEMIHOSTING) += semihosting.o
 obj-$(CONFIG_FIRMWARE_ALTERA_SERIAL) += altera_serial.o
 obj-$(CONFIG_FIRMWARE_ALTERA_SOCFPGA) += socfpga.o socfpga_sdr.o
 obj-$(CONFIG_FIRMWARE_ZYNQMP_FPGA) += zynqmp-fpga.o
diff --git a/arch/arm/lib32/semihosting.c b/drivers/firmware/semihosting.c
similarity index 100%
rename from arch/arm/lib32/semihosting.c
rename to drivers/firmware/semihosting.c
diff --git a/fs/Kconfig b/fs/Kconfig
index a3ba84b6aefd..e02cb939a5cf 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -113,7 +113,7 @@ config FS_UIMAGEFS
 	prompt "uImage FS support"
 
 config FS_SMHFS
-	depends on ARM_SEMIHOSTING
+	depends on SEMIHOSTING
 	select FS_LEGACY
 	bool
 	prompt "Semihosting FS support"
diff --git a/include/asm-generic/semihosting.h b/include/asm-generic/semihosting.h
new file mode 100644
index 000000000000..d337c33ff486
--- /dev/null
+++ b/include/asm-generic/semihosting.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __ASM_GENERIC_SEMIHOSTING_H
+#define __ASM_GENERIC_SEMIHOSTING_H
+
+#include <linux/types.h>
+
+int semihosting_open(const char *fname, int flags);
+int semihosting_close(int fd);
+int semihosting_writec(char c);
+int semihosting_write0(const char *str);
+ssize_t semihosting_write(int fd, const void *buf, size_t count);
+ssize_t semihosting_read(int fd, void *buf, size_t count);
+int semihosting_readc(void);
+int semihosting_isatty(int fd);
+int semihosting_seek(int fd, loff_t pos);
+int semihosting_flen(int fd);
+int semihosting_remove(const char *fname);
+int semihosting_rename(const char *fname1, const char *fname2);
+int semihosting_errno(void);
+int semihosting_system(const char *command);
+
+#endif
-- 
2.39.2




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

* [PATCH 2/6] firmware: semihosting: add ARMv8-A semihosting support
  2024-06-11  6:59 [PATCH 0/6] semihosting: extend support for ARM64, console Ahmad Fatoum
  2024-06-11  6:59 ` [PATCH 1/6] ARM: lib32: semihosting: prepare for more general use Ahmad Fatoum
@ 2024-06-11  6:59 ` Ahmad Fatoum
  2024-06-11  6:59 ` [PATCH 3/6] firmware: semihosting: don't return error code from writec/write0 Ahmad Fatoum
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Ahmad Fatoum @ 2024-06-11  6:59 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

The semihosting code was assuming registers and pointers to be 32-bit in
size. To enable usage for ARM64, switch to long-sized types where
appropriate and add a trap implementation for ARMv8.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/arm/Kconfig                   |  1 -
 arch/arm/cpu/semihosting-trap_64.S | 10 ++++++
 drivers/firmware/semihosting.c     | 55 +++++++++++++++---------------
 fs/smhfs.c                         |  4 +--
 include/asm-generic/semihosting.h  |  4 +--
 5 files changed, 41 insertions(+), 33 deletions(-)
 create mode 100644 arch/arm/cpu/semihosting-trap_64.S

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 26547cd3ba71..89125ca576ea 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -372,7 +372,6 @@ config ARM_UNWIND
 
 config ARM_SEMIHOSTING
 	bool "enable ARM semihosting support"
-	depends on !CPU_V8
 	select SEMIHOSTING
 	help
 	  This option enables ARM semihosting support in barebox. ARM
diff --git a/arch/arm/cpu/semihosting-trap_64.S b/arch/arm/cpu/semihosting-trap_64.S
new file mode 100644
index 000000000000..0f52094fc46b
--- /dev/null
+++ b/arch/arm/cpu/semihosting-trap_64.S
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <linux/linkage.h>
+#include <asm/unified.h>
+
+.section .text.semihosting_trap
+ENTRY(semihosting_trap)
+	hlt	#0xf000
+	ret
+ENDPROC(semihosting_trap)
diff --git a/drivers/firmware/semihosting.c b/drivers/firmware/semihosting.c
index 57b412e08ded..a037a95a1077 100644
--- a/drivers/firmware/semihosting.c
+++ b/drivers/firmware/semihosting.c
@@ -41,9 +41,9 @@ enum {
 	SEMIHOSTING_SYS_SYSTEM	= 0x12,
 };
 
-uint32_t semihosting_trap(uint32_t sysnum, void *addr);
+long semihosting_trap(ulong sysnum, void *addr);
 
-static uint32_t semihosting_flags_to_mode(int flags)
+static ulong semihosting_flags_to_mode(int flags)
 {
 	static const int semihosting_open_modeflags[12] = {
 		O_RDONLY,
@@ -72,11 +72,11 @@ static uint32_t semihosting_flags_to_mode(int flags)
 int semihosting_open(const char *fname, int flags)
 {
 	struct __packed {
-		uint32_t fname;
-		uint32_t mode;
-		uint32_t len;
+		ulong fname;
+		ulong mode;
+		ulong len;
 	} open = {
-		.fname = (uint32_t)fname,
+		.fname = virt_to_phys(fname),
 		.len = strlen(fname),
 		.mode = semihosting_flags_to_mode(flags),
 	};
@@ -104,16 +104,16 @@ int semihosting_write0(const char *str)
 EXPORT_SYMBOL(semihosting_write0);
 
 struct __packed semihosting_file_io {
-	uint32_t fd;
-	uint32_t memp;
-	uint32_t len;
+	ulong fd;
+	ulong memp;
+	ulong len;
 };
 
 ssize_t semihosting_write(int fd, const void *buf, size_t count)
 {
 	struct semihosting_file_io write = {
 		.fd = fd,
-		.memp = (uint32_t)buf,
+		.memp = virt_to_phys(buf),
 		.len = count,
 	};
 
@@ -125,7 +125,7 @@ ssize_t semihosting_read(int fd, void *buf, size_t count)
 {
 	struct semihosting_file_io read = {
 		.fd = fd,
-		.memp = (uint32_t)buf,
+		.memp = virt_to_phys(buf),
 		.len = count,
 	};
 
@@ -145,11 +145,11 @@ int semihosting_isatty(int fd)
 }
 EXPORT_SYMBOL(semihosting_isatty);
 
-int semihosting_seek(int fd, loff_t pos)
+off_t semihosting_seek(int fd, off_t pos)
 {
 	struct __packed {
-		uint32_t fd;
-		uint32_t pos;
+		ulong fd;
+		ulong pos;
 	} seek = {
 		.fd = fd,
 		.pos = pos,
@@ -158,8 +158,7 @@ int semihosting_seek(int fd, loff_t pos)
 	return semihosting_trap(SEMIHOSTING_SYS_SEEK, &seek);
 }
 EXPORT_SYMBOL(semihosting_seek);
-
-int semihosting_flen(int fd)
+off_t semihosting_flen(int fd)
 {
 	return semihosting_trap(SEMIHOSTING_SYS_FLEN, &fd);
 }
@@ -168,10 +167,10 @@ EXPORT_SYMBOL(semihosting_flen);
 int semihosting_remove(const char *fname)
 {
 	struct __packed {
-		uint32_t fname;
-		uint32_t fname_length;
+		ulong fname;
+		ulong fname_length;
 	} remove = {
-		.fname = (uint32_t)fname,
+		.fname = virt_to_phys(fname),
 		.fname_length = strlen(fname),
 	};
 
@@ -182,14 +181,14 @@ EXPORT_SYMBOL(semihosting_remove);
 int semihosting_rename(const char *fname1, const char *fname2)
 {
 	struct __packed {
-		uint32_t fname1;
-		uint32_t fname1_length;
-		uint32_t fname2;
-		uint32_t fname2_length;
+		ulong fname1;
+		ulong fname1_length;
+		ulong fname2;
+		ulong fname2_length;
 	} rename = {
-		.fname1 = (uint32_t)fname1,
+		.fname1 = virt_to_phys(fname1),
 		.fname1_length = strlen(fname1),
-		.fname2 = (uint32_t)fname2,
+		.fname2 = virt_to_phys(fname2),
 		.fname2_length = strlen(fname2),
 	};
 
@@ -207,10 +206,10 @@ EXPORT_SYMBOL(semihosting_errno);
 int semihosting_system(const char *command)
 {
 	struct __packed {
-		uint32_t cmd;
-		uint32_t cmd_len;
+		ulong cmd;
+		ulong cmd_len;
 	} system = {
-		.cmd = (uint32_t)command,
+		.cmd = virt_to_phys(command),
 		.cmd_len = strlen(command),
 	};
 
diff --git a/fs/smhfs.c b/fs/smhfs.c
index 5165bf939406..da285b5be52f 100644
--- a/fs/smhfs.c
+++ b/fs/smhfs.c
@@ -26,7 +26,7 @@
 
 static int file_to_fd(const FILE *f)
 {
-	return (int)f->priv;
+	return (int)(uintptr_t)f->priv;
 }
 
 static int smhfs_create(struct device __always_unused *dev,
@@ -72,7 +72,7 @@ static int smhfs_open(struct device __always_unused *dev,
 	if (fd < 0)
 		goto error;
 
-	file->priv = (void *)fd;
+	file->priv = (void *)(uintptr_t)fd;
 	file->size = semihosting_flen(fd);
 	if (file->size < 0)
 		goto error;
diff --git a/include/asm-generic/semihosting.h b/include/asm-generic/semihosting.h
index d337c33ff486..b745f8831977 100644
--- a/include/asm-generic/semihosting.h
+++ b/include/asm-generic/semihosting.h
@@ -13,8 +13,8 @@ ssize_t semihosting_write(int fd, const void *buf, size_t count);
 ssize_t semihosting_read(int fd, void *buf, size_t count);
 int semihosting_readc(void);
 int semihosting_isatty(int fd);
-int semihosting_seek(int fd, loff_t pos);
-int semihosting_flen(int fd);
+off_t semihosting_seek(int fd, off_t pos);
+off_t semihosting_flen(int fd);
 int semihosting_remove(const char *fname);
 int semihosting_rename(const char *fname1, const char *fname2);
 int semihosting_errno(void);
-- 
2.39.2




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

* [PATCH 3/6] firmware: semihosting: don't return error code from writec/write0
  2024-06-11  6:59 [PATCH 0/6] semihosting: extend support for ARM64, console Ahmad Fatoum
  2024-06-11  6:59 ` [PATCH 1/6] ARM: lib32: semihosting: prepare for more general use Ahmad Fatoum
  2024-06-11  6:59 ` [PATCH 2/6] firmware: semihosting: add ARMv8-A semihosting support Ahmad Fatoum
@ 2024-06-11  6:59 ` Ahmad Fatoum
  2024-06-11  6:59 ` [PATCH 4/6] firmware: semihosting: translate return values in wrappers Ahmad Fatoum
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Ahmad Fatoum @ 2024-06-11  6:59 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

As described in the "ARM Compiler toolchain Developing Software
for ARM Processors Version 5.0" document[1], SYS_WRITE0 and SYS_WRITEC
corrupt the R0 register, unlike the other calls that return negative
error codes. Therefore change the return type to void.

[1]: https://developer.arm.com/documentation/dui0471/i/semihosting/sys-write0--0x04-?lang=en

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 drivers/firmware/semihosting.c    | 8 ++++----
 include/asm-generic/semihosting.h | 4 ++--
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/firmware/semihosting.c b/drivers/firmware/semihosting.c
index a037a95a1077..1dfbdf219727 100644
--- a/drivers/firmware/semihosting.c
+++ b/drivers/firmware/semihosting.c
@@ -91,15 +91,15 @@ int semihosting_close(int fd)
 }
 EXPORT_SYMBOL(semihosting_close);
 
-int semihosting_writec(char c)
+void semihosting_writec(char c)
 {
-	return semihosting_trap(SEMIHOSTING_SYS_WRITEC, &c);
+	(void)semihosting_trap(SEMIHOSTING_SYS_WRITEC, &c);
 }
 EXPORT_SYMBOL(semihosting_writec);
 
-int semihosting_write0(const char *str)
+void semihosting_write0(const char *str)
 {
-	return semihosting_trap(SEMIHOSTING_SYS_WRITE0, (void *)str);
+	(void)semihosting_trap(SEMIHOSTING_SYS_WRITE0, (void *)str);
 }
 EXPORT_SYMBOL(semihosting_write0);
 
diff --git a/include/asm-generic/semihosting.h b/include/asm-generic/semihosting.h
index b745f8831977..67031c331b97 100644
--- a/include/asm-generic/semihosting.h
+++ b/include/asm-generic/semihosting.h
@@ -7,8 +7,8 @@
 
 int semihosting_open(const char *fname, int flags);
 int semihosting_close(int fd);
-int semihosting_writec(char c);
-int semihosting_write0(const char *str);
+void semihosting_writec(char c);
+void semihosting_write0(const char *str);
 ssize_t semihosting_write(int fd, const void *buf, size_t count);
 ssize_t semihosting_read(int fd, void *buf, size_t count);
 int semihosting_readc(void);
-- 
2.39.2




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

* [PATCH 4/6] firmware: semihosting: translate return values in wrappers
  2024-06-11  6:59 [PATCH 0/6] semihosting: extend support for ARM64, console Ahmad Fatoum
                   ` (2 preceding siblings ...)
  2024-06-11  6:59 ` [PATCH 3/6] firmware: semihosting: don't return error code from writec/write0 Ahmad Fatoum
@ 2024-06-11  6:59 ` Ahmad Fatoum
  2024-06-11  6:59 ` [PATCH 5/6] ARM: semihosting: add DEBUG_LL implementation Ahmad Fatoum
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Ahmad Fatoum @ 2024-06-11  6:59 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

It's needlessly verbose to expect callers of the semihosting wrappers to
call semihosting_errno() on error, so let's just do that inside the
wrappers so they behave like other functions.

While at it, also have semihosting_read() and semihosting_write() return
the number of bytes sent. The semihosting API returns the number of
bytes that were _not_ sent instead, so a return value of 0 is success.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 drivers/firmware/semihosting.c | 36 ++++++++++++++++++++++------------
 fs/smhfs.c                     | 33 +++++++++----------------------
 2 files changed, 33 insertions(+), 36 deletions(-)

diff --git a/drivers/firmware/semihosting.c b/drivers/firmware/semihosting.c
index 1dfbdf219727..9663959aa49f 100644
--- a/drivers/firmware/semihosting.c
+++ b/drivers/firmware/semihosting.c
@@ -43,6 +43,12 @@ enum {
 
 long semihosting_trap(ulong sysnum, void *addr);
 
+static long semihosting_call(ulong sysnum, void *addr)
+{
+	long ret = semihosting_trap(sysnum, addr);
+	return ret >= 0 ? ret : -semihosting_errno();
+}
+
 static ulong semihosting_flags_to_mode(int flags)
 {
 	static const int semihosting_open_modeflags[12] = {
@@ -81,13 +87,13 @@ int semihosting_open(const char *fname, int flags)
 		.mode = semihosting_flags_to_mode(flags),
 	};
 
-	return semihosting_trap(SEMIHOSTING_SYS_OPEN, &open);
+	return semihosting_call(SEMIHOSTING_SYS_OPEN, &open);
 }
 EXPORT_SYMBOL(semihosting_open);
 
 int semihosting_close(int fd)
 {
-	return semihosting_trap(SEMIHOSTING_SYS_CLOSE, &fd);
+	return semihosting_call(SEMIHOSTING_SYS_CLOSE, &fd);
 }
 EXPORT_SYMBOL(semihosting_close);
 
@@ -111,37 +117,43 @@ struct __packed semihosting_file_io {
 
 ssize_t semihosting_write(int fd, const void *buf, size_t count)
 {
+	ssize_t ret;
 	struct semihosting_file_io write = {
 		.fd = fd,
 		.memp = virt_to_phys(buf),
 		.len = count,
 	};
 
-	return semihosting_trap(SEMIHOSTING_SYS_WRITE, &write);
+	ret = semihosting_call(SEMIHOSTING_SYS_WRITE, &write);
+
+	return ret >= 0 ? count - ret : ret;
 }
 EXPORT_SYMBOL(semihosting_write);
 
 ssize_t semihosting_read(int fd, void *buf, size_t count)
 {
+	ssize_t ret;
 	struct semihosting_file_io read = {
 		.fd = fd,
 		.memp = virt_to_phys(buf),
 		.len = count,
 	};
 
-	return semihosting_trap(SEMIHOSTING_SYS_READ, &read);
+	ret = semihosting_call(SEMIHOSTING_SYS_READ, &read);
+
+	return ret >= 0 ? count - ret : ret;
 }
 EXPORT_SYMBOL(semihosting_read);
 
 int semihosting_readc(void)
 {
-	return semihosting_trap(SEMIHOSTING_SYS_READC, NULL);
+	return semihosting_call(SEMIHOSTING_SYS_READC, NULL);
 }
 EXPORT_SYMBOL(semihosting_readc);
 
 int semihosting_isatty(int fd)
 {
-	return semihosting_trap(SEMIHOSTING_SYS_ISATTY, &fd);
+	return semihosting_call(SEMIHOSTING_SYS_ISATTY, &fd);
 }
 EXPORT_SYMBOL(semihosting_isatty);
 
@@ -155,12 +167,12 @@ off_t semihosting_seek(int fd, off_t pos)
 		.pos = pos,
 	};
 
-	return semihosting_trap(SEMIHOSTING_SYS_SEEK, &seek);
+	return semihosting_call(SEMIHOSTING_SYS_SEEK, &seek);
 }
 EXPORT_SYMBOL(semihosting_seek);
 off_t semihosting_flen(int fd)
 {
-	return semihosting_trap(SEMIHOSTING_SYS_FLEN, &fd);
+	return semihosting_call(SEMIHOSTING_SYS_FLEN, &fd);
 }
 EXPORT_SYMBOL(semihosting_flen);
 
@@ -174,7 +186,7 @@ int semihosting_remove(const char *fname)
 		.fname_length = strlen(fname),
 	};
 
-	return semihosting_trap(SEMIHOSTING_SYS_REMOVE, &remove);
+	return semihosting_call(SEMIHOSTING_SYS_REMOVE, &remove);
 }
 EXPORT_SYMBOL(semihosting_remove);
 
@@ -192,13 +204,13 @@ int semihosting_rename(const char *fname1, const char *fname2)
 		.fname2_length = strlen(fname2),
 	};
 
-	return semihosting_trap(SEMIHOSTING_SYS_RENAME, &rename);
+	return semihosting_call(SEMIHOSTING_SYS_RENAME, &rename);
 }
 EXPORT_SYMBOL(semihosting_rename);
 
 int semihosting_errno(void)
 {
-	return semihosting_trap(SEMIHOSTING_SYS_ERRNO, NULL);
+	return semihosting_call(SEMIHOSTING_SYS_ERRNO, NULL);
 }
 EXPORT_SYMBOL(semihosting_errno);
 
@@ -213,6 +225,6 @@ int semihosting_system(const char *command)
 		.cmd_len = strlen(command),
 	};
 
-	return semihosting_trap(SEMIHOSTING_SYS_SYSTEM, &system);
+	return semihosting_call(SEMIHOSTING_SYS_SYSTEM, &system);
 }
 EXPORT_SYMBOL(semihosting_system);
diff --git a/fs/smhfs.c b/fs/smhfs.c
index da285b5be52f..ce027f203e23 100644
--- a/fs/smhfs.c
+++ b/fs/smhfs.c
@@ -48,10 +48,7 @@ static int smhfs_rm(struct device __always_unused *dev,
 	/* Get rid of leading '/' */
 	pathname = &pathname[1];
 
-	if (semihosting_remove(pathname) != 0)
-		return -semihosting_errno();
-	else
-		return 0;
+	return semihosting_remove(pathname);
 }
 
 static int smhfs_truncate(struct device __always_unused *dev,
@@ -70,52 +67,40 @@ static int smhfs_open(struct device __always_unused *dev,
 
 	fd = semihosting_open(filename, file->flags);
 	if (fd < 0)
-		goto error;
+		return fd;
 
 	file->priv = (void *)(uintptr_t)fd;
 	file->size = semihosting_flen(fd);
 	if (file->size < 0)
-		goto error;
+		return file->size;
 
 	return 0;
-error:
-	return -semihosting_errno();
 }
 
 static int smhfs_close(struct device __always_unused *dev,
 		       FILE *f)
 {
-	if (semihosting_close(file_to_fd(f)))
-		return -semihosting_errno();
-	else
-		return 0;
+	return semihosting_close(file_to_fd(f));
 }
 
 static int smhfs_write(struct device __always_unused *dev,
 		       FILE *f, const void *inbuf, size_t insize)
 {
-	if (semihosting_write(file_to_fd(f), inbuf, insize))
-		return -semihosting_errno();
-	else
-		return insize;
+	long ret = semihosting_write(file_to_fd(f), inbuf, insize);
+	return ret < 0 ? ret : insize;
 }
 
 static int smhfs_read(struct device __always_unused *dev,
 		      FILE *f, void *buf, size_t insize)
 {
-	if (!semihosting_read(file_to_fd(f), buf, insize))
-		return insize;
-	else
-		return -semihosting_errno();
+	long ret = semihosting_read(file_to_fd(f), buf, insize);
+	return ret < 0 ? ret : insize;
 }
 
 static int smhfs_lseek(struct device __always_unused *dev,
 			  FILE *f, loff_t pos)
 {
-	if (semihosting_seek(file_to_fd(f), pos))
-		return -semihosting_errno();
-
-	return 0;
+	return semihosting_seek(file_to_fd(f), pos);
 }
 
 static DIR* smhfs_opendir(struct device __always_unused *dev,
-- 
2.39.2




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

* [PATCH 5/6] ARM: semihosting: add DEBUG_LL implementation
  2024-06-11  6:59 [PATCH 0/6] semihosting: extend support for ARM64, console Ahmad Fatoum
                   ` (3 preceding siblings ...)
  2024-06-11  6:59 ` [PATCH 4/6] firmware: semihosting: translate return values in wrappers Ahmad Fatoum
@ 2024-06-11  6:59 ` Ahmad Fatoum
  2024-06-11  6:59 ` [PATCH 6/6] serial: add semihosting console Ahmad Fatoum
  2024-06-13  7:18 ` [PATCH 0/6] semihosting: extend support for ARM64, console Sascha Hauer
  6 siblings, 0 replies; 8+ messages in thread
From: Ahmad Fatoum @ 2024-06-11  6:59 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

Both OpenOCD and QEMU have a semihosting implementation that provides a
console suitable for low level debugging. Add a DEBUG_LL implementation
that is usable when QEMU is called with

  --semihosting-config chardev=serial0

or following OpenOCD is executed:

  arm semihosting enable

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/arm/include/asm/debug_ll.h    |  4 ++++
 arch/arm/include/asm/semihosting.h | 32 ++++++++++++++++++++++++++++++
 common/Kconfig.debug_ll            | 13 ++++++++++++
 drivers/firmware/Kconfig           |  1 +
 include/debug_ll/semihosting.h     | 15 ++++++++++++++
 5 files changed, 65 insertions(+)
 create mode 100644 include/debug_ll/semihosting.h

diff --git a/arch/arm/include/asm/debug_ll.h b/arch/arm/include/asm/debug_ll.h
index 999f1cb831a8..bac0b2106936 100644
--- a/arch/arm/include/asm/debug_ll.h
+++ b/arch/arm/include/asm/debug_ll.h
@@ -35,6 +35,10 @@
 #include <mach/layerscape/debug_ll.h>
 #endif
 
+#ifdef CONFIG_DEBUG_SEMIHOSTING
+#include <debug_ll/semihosting.h>
+#endif
+
 #ifdef CONFIG_DEBUG_QEMU_ARM64_VIRT
 #define DEBUG_LL_UART_ADDR		0x9000000
 #include <debug_ll/pl011.h>
diff --git a/arch/arm/include/asm/semihosting.h b/arch/arm/include/asm/semihosting.h
index c18aa1a5fef5..2219e858d040 100644
--- a/arch/arm/include/asm/semihosting.h
+++ b/arch/arm/include/asm/semihosting.h
@@ -4,5 +4,37 @@
 #define __ASM_ARM_SEMIHOSTING_H
 
 #include <asm-generic/semihosting.h>
+#include <asm/unified.h>
+
+static inline void semihosting_putc(void *unused, int c)
+{
+	/* We may not be relocated yet here, so we push
+	 * to stack and take address of that
+	 */
+#ifdef CONFIG_CPU_64
+	asm volatile (
+		"stp %0, xzr, [sp, #-16]!\n"
+		"mov x1, sp\n"
+		"mov x0, #0x03\n"
+	 	"hlt #0xf000\n"
+		"add sp, sp, #16\n"
+		: /* No outputs */
+		: "r" ((long)c)
+		: "x0", "x1", "x2", "x3", "x12", "memory"
+	);
+#else
+	asm volatile (
+		"push {%0}\n"
+		"mov r1, sp\n"
+		"mov r0, #0x03\n"
+	 ARM(	"bkpt #0x123456\n")
+	 THUMB(	"bkpt #0xAB\n")
+		"pop {%0}\n"
+		: /* No outputs */
+		: "r" (c)
+		: "r0", "r1", "r2", "r3", "r12", "memory"
+	);
+#endif
+}
 
 #endif
diff --git a/common/Kconfig.debug_ll b/common/Kconfig.debug_ll
index 472048177f8b..3f6f3e7c3bdb 100644
--- a/common/Kconfig.debug_ll
+++ b/common/Kconfig.debug_ll
@@ -337,6 +337,19 @@ config DEBUG_QEMU_ARM64_VIRT
 	bool "QEMU ARM64 Virt PL011 console"
 	depends on ARCH_ARM64_VIRT
 
+config DEBUG_SEMIHOSTING
+	bool "Semihosting console"
+	depends on SEMIHOSTING
+	help
+	  Semihosting enables code to use the I/O facilities on a
+	  host debugger/emulator through a simple supervisor call.
+	  The host debugger or emulator must have semihosting enabled
+	  for the supervisor call to be trapped, otherwise barebox
+	  will crash.
+
+	  Say Y here if you want low-level debugging support
+	  using semihosting writec.
+
 endchoice
 
 config DEBUG_LL_NS16550
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 89c8bdeda3f0..264f7b2a5a65 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -3,6 +3,7 @@ menu "Firmware Drivers"
 
 config SEMIHOSTING
 	bool
+	select HAS_DEBUG_LL
 
 config FIRMWARE_ALTERA_SERIAL
 	bool "Altera SPI programming"
diff --git a/include/debug_ll/semihosting.h b/include/debug_ll/semihosting.h
new file mode 100644
index 000000000000..125d42ee88de
--- /dev/null
+++ b/include/debug_ll/semihosting.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __DEBUG_LL_SEMIHOSTING_H
+#define __DEBUG_LL_SEMIHOSTING_H
+
+#include <asm/semihosting.h>
+#include <linux/stddef.h>
+
+#ifdef CONFIG_DEBUG_SEMIHOSTING
+static inline void PUTC_LL(char c)
+{
+	semihosting_putc(NULL, c);
+}
+#endif
+
+#endif /* __DEBUG_LL_ARM_SEMIHOSTING_H */
-- 
2.39.2




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

* [PATCH 6/6] serial: add semihosting console
  2024-06-11  6:59 [PATCH 0/6] semihosting: extend support for ARM64, console Ahmad Fatoum
                   ` (4 preceding siblings ...)
  2024-06-11  6:59 ` [PATCH 5/6] ARM: semihosting: add DEBUG_LL implementation Ahmad Fatoum
@ 2024-06-11  6:59 ` Ahmad Fatoum
  2024-06-13  7:18 ` [PATCH 0/6] semihosting: extend support for ARM64, console Sascha Hauer
  6 siblings, 0 replies; 8+ messages in thread
From: Ahmad Fatoum @ 2024-06-11  6:59 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

There is no way to implement a proper tstc() with the semihosting
console, so for now, let's add it as output-only console.

Currently, the console is only usable when not running as EFI payload to
avoid duplicate output when it's exposed over regular EFI protocol.

In the future, we could make it opt-in by providing a way to create the
semihosting device from shell.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 drivers/serial/Kconfig              |  8 ++++++
 drivers/serial/Makefile             |  1 +
 drivers/serial/serial_semihosting.c | 44 +++++++++++++++++++++++++++++
 3 files changed, 53 insertions(+)
 create mode 100644 drivers/serial/serial_semihosting.c

diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 60b0e5f1dc1f..20fe26439048 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -151,4 +151,12 @@ config SERIAL_SBI
 	  Select this option if you are building barebox for a RISCV platform
 	  that implements a serial over SBI.
 
+config SERIAL_SEMIHOSTING
+	bool "Semihosting console"
+	depends on SEMIHOSTING
+	help
+	  Select this option if you want barebox to be able to output to
+	  the semihosting console implemented by a debugger or emulator.
+	  This console can not be read from.
+
 endmenu
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 4887e24ee1c1..f4ccb249003a 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -25,3 +25,4 @@ obj-$(CONFIG_VIRTIO_CONSOLE)			+= virtio_console.o
 obj-$(CONFIG_SERIAL_SIFIVE)			+= serial_sifive.o
 obj-$(CONFIG_SERIAL_SBI)			+= serial_sbi.o
 obj-$(CONFIG_SOC_LITEX)				+= serial_litex.o
+obj-$(CONFIG_SERIAL_SEMIHOSTING)		+= serial_semihosting.o
diff --git a/drivers/serial/serial_semihosting.c b/drivers/serial/serial_semihosting.c
new file mode 100644
index 000000000000..d495b07f11ca
--- /dev/null
+++ b/drivers/serial/serial_semihosting.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <console.h>
+#include <asm/semihosting.h>
+#include <efi/efi-mode.h>
+
+static void smh_serial_putc(struct console_device *cdev, char ch)
+{
+	semihosting_writec(ch);
+}
+
+static int smh_serial_probe(struct device *dev)
+{
+	struct console_device *cdev;
+
+	cdev = xzalloc(sizeof(*cdev));
+
+	cdev->dev = dev;
+	cdev->putc = smh_serial_putc;
+
+	return console_register(cdev);
+}
+
+static struct driver serial_semihosting_driver = {
+	.name   = "serial_semihosting",
+	.probe  = smh_serial_probe,
+};
+
+static int __init serial_semihosting_register(void)
+{
+	if (!efi_is_payload()) {
+		struct device *dev;
+		int ret;
+
+		dev = device_alloc("serial_semihosting", 0);
+
+		ret = platform_device_register(dev);
+		if (ret)
+			return ret;
+	}
+
+	return platform_driver_register(&serial_semihosting_driver);
+}
+console_initcall(serial_semihosting_register);
-- 
2.39.2




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

* Re: [PATCH 0/6] semihosting: extend support for ARM64, console
  2024-06-11  6:59 [PATCH 0/6] semihosting: extend support for ARM64, console Ahmad Fatoum
                   ` (5 preceding siblings ...)
  2024-06-11  6:59 ` [PATCH 6/6] serial: add semihosting console Ahmad Fatoum
@ 2024-06-13  7:18 ` Sascha Hauer
  6 siblings, 0 replies; 8+ messages in thread
From: Sascha Hauer @ 2024-06-13  7:18 UTC (permalink / raw)
  To: barebox, Ahmad Fatoum


On Tue, 11 Jun 2024 08:59:17 +0200, Ahmad Fatoum wrote:
> So far, we limited semihosting support to 32-bit ARM, but it's also
> usable on ARM64 and even RISC-V.
> 
> This series does the first step by making it compile for ARM64 and also
> adds DEBUG_LL and console drivers.
> 
> Ahmad Fatoum (6):
>   ARM: lib32: semihosting: prepare for more general use
>   firmware: semihosting: add ARMv8-A semihosting support
>   firmware: semihosting: don't return error code from writec/write0
>   firmware: semihosting: translate return values in wrappers
>   ARM: semihosting: add DEBUG_LL implementation
>   serial: add semihosting console
> 
> [...]

Applied, thanks!

[1/6] ARM: lib32: semihosting: prepare for more general use
      https://git.pengutronix.de/cgit/barebox/commit/?id=b31058d41bb9 (link may not be stable)
[2/6] firmware: semihosting: add ARMv8-A semihosting support
      https://git.pengutronix.de/cgit/barebox/commit/?id=ea71e603e460 (link may not be stable)
[3/6] firmware: semihosting: don't return error code from writec/write0
      https://git.pengutronix.de/cgit/barebox/commit/?id=8f79ab770a4c (link may not be stable)
[4/6] firmware: semihosting: translate return values in wrappers
      https://git.pengutronix.de/cgit/barebox/commit/?id=5f87fad31eef (link may not be stable)
[5/6] ARM: semihosting: add DEBUG_LL implementation
      https://git.pengutronix.de/cgit/barebox/commit/?id=0e87c409e354 (link may not be stable)
[6/6] serial: add semihosting console
      https://git.pengutronix.de/cgit/barebox/commit/?id=1d2df6d26c35 (link may not be stable)

Best regards,
-- 
Sascha Hauer <s.hauer@pengutronix.de>




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

end of thread, other threads:[~2024-06-13  7:19 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-06-11  6:59 [PATCH 0/6] semihosting: extend support for ARM64, console Ahmad Fatoum
2024-06-11  6:59 ` [PATCH 1/6] ARM: lib32: semihosting: prepare for more general use Ahmad Fatoum
2024-06-11  6:59 ` [PATCH 2/6] firmware: semihosting: add ARMv8-A semihosting support Ahmad Fatoum
2024-06-11  6:59 ` [PATCH 3/6] firmware: semihosting: don't return error code from writec/write0 Ahmad Fatoum
2024-06-11  6:59 ` [PATCH 4/6] firmware: semihosting: translate return values in wrappers Ahmad Fatoum
2024-06-11  6:59 ` [PATCH 5/6] ARM: semihosting: add DEBUG_LL implementation Ahmad Fatoum
2024-06-11  6:59 ` [PATCH 6/6] serial: add semihosting console Ahmad Fatoum
2024-06-13  7:18 ` [PATCH 0/6] semihosting: extend support for ARM64, console Sascha Hauer

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