[PATCH 2/6] firmware: semihosting: add ARMv8-A semihosting support

Ahmad Fatoum a.fatoum at pengutronix.de
Mon Jun 10 23:59:19 PDT 2024


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 at 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




More information about the barebox mailing list