git: 5974cfe1ba47 - main - kboot: move to generic syscall interface

From: Warner Losh <imp_at_FreeBSD.org>
Date: Thu, 30 Dec 2021 23:31:48 UTC
The branch main has been updated by imp:

URL: https://cgit.FreeBSD.org/src/commit/?id=5974cfe1ba47ac756fc0d5e48306730e1115b36c

commit 5974cfe1ba47ac756fc0d5e48306730e1115b36c
Author:     Warner Losh <imp@FreeBSD.org>
AuthorDate: 2021-12-30 23:07:20 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2021-12-30 23:07:20 +0000

    kboot: move to generic syscall interface
    
    Just have the MD code provide syscall and have generic code for the
    rest.
    
    Sponsored by:           Netflix
    Differential Revision:  https://reviews.freebsd.org/D33515
---
 stand/kboot/Makefile                      |   2 +-
 stand/kboot/arch/powerpc64/host_syscall.S | 116 ++++++++----------------------
 stand/kboot/arch/powerpc64/syscall_nr.h   |  15 ++++
 stand/kboot/host_syscall.h                |  10 +--
 stand/kboot/host_syscalls.c               |  86 ++++++++++++++++++++++
 5 files changed, 138 insertions(+), 91 deletions(-)

diff --git a/stand/kboot/Makefile b/stand/kboot/Makefile
index aa5511d915a9..24ab77af66db 100644
--- a/stand/kboot/Makefile
+++ b/stand/kboot/Makefile
@@ -17,7 +17,7 @@ NEWVERSWHAT=	"kboot loader" ${MACHINE_ARCH}
 INSTALLFLAGS=	-b
 
 # Architecture-specific loader code
-SRCS=		vers.c main.c hostcons.c hostdisk.c kbootfdt.c gfx_fb_stub.c
+SRCS=		vers.c main.c host_syscalls.c hostcons.c hostdisk.c kbootfdt.c gfx_fb_stub.c
 
 CFLAGS.gfx_fb_stub.c += -I${SRCTOP}/contrib/pnglite -I${SRCTOP}/sys/teken
 
diff --git a/stand/kboot/arch/powerpc64/host_syscall.S b/stand/kboot/arch/powerpc64/host_syscall.S
index a5556aa1b2dc..729bc6baa082 100644
--- a/stand/kboot/arch/powerpc64/host_syscall.S
+++ b/stand/kboot/arch/powerpc64/host_syscall.S
@@ -1,88 +1,32 @@
-/*
- * 
- * $FreeBSD$
- */
-
 #include <machine/asm.h>
 
-ENTRY(host_read)
-	li %r0, 3 # SYS_read
-	sc
-	bso 1f
-	blr
-1:
-	li %r3, 0
-	blr
-END(host_read)
-
-ENTRY(host_write)
-	li %r0, 4 # SYS_write
-	sc
-	blr
-END(host_write)
-
-ENTRY(host_llseek)
-	li %r0, 140 # SYS_llseek
-	sc
-	blr
-END(host_llseek)
-
-ENTRY(host_open)
-	li %r0, 5 # SYS_open
-	sc
-	bso 1f
-	blr
-1:
-	li %r3, 0
-	blr
-END(host_open)
-
-ENTRY(host_close)
-	li %r0, 6 # SYS_close
-	sc
-	blr
-END(host_close)
-
-ENTRY(host_mmap)
-	li %r0, 90 # SYS_mmap
-	sc
-	blr
-END(host_mmap)
-
-ENTRY(host_uname)
-	li %r0, 122 # SYS_uname
-	sc
-	blr
-END(host_uname)
-
-ENTRY(host_gettimeofday)
-	li %r0, 78 # SYS_gettimeofday
-	sc
-	blr
-END(host_gettimeofday)
-
-ENTRY(host_select)
-	li %r0, 142 # SYS_select
-	sc
-	blr
-END(host_select)
-
-ENTRY(kexec_load)
-	lis	%r6,21	# KEXEC_ARCH_PPC64
-	li	%r0,268 # __NR_kexec_load
-	sc
-	blr
-END(kexec_load)
-
-ENTRY(host_reboot)
-	li %r0,88 # SYS_reboot
-	sc
-	blr
-END(host_reboot)
-
-ENTRY(host_getdents)
-	li %r0,141 # SYS_getdents
-	sc
-	blr
-END(host_getdents)
-
+/*
+ * Emulate the Linux system call interface. The system call number is set in
+ * %r0, and %r3 -> %r8 have the 6 system call arguments. errno is returned
+ * as a negative value, but we use it more as a flag something went wrong
+ * rather than using its value.
+ *
+ * Return value in %r3. If it is positive or < -4096, it's a successful
+ * system call. If it is between -1 and -4095 then it's an failed system
+ * call with -x as the errno. Errors from the kernel are signaled via the
+ * the 'so' bit, but we don't test that here at all. There are at most 6
+ * arguments to system calls in Linux.
+ *
+ * We expose the raw system call result, rather than do the POSIX
+ * converion to -1 and setting errno.
+ *
+ * Note: The code this replaced used bso to set %r3 to 0 for the read and
+ * open system calls for reasons that are still under investigation.
+ */
+ENTRY(host_syscall)
+	mr	%r0, %r3	/* SYS_ number in $r0 */
+	mr	%r3, %r4	/* arg2 -> 1 */
+	mr	%r4, %r5	/* arg3 -> 2 */
+	mr	%r5, %r6	/* arg4 -> 3 */
+	mr	%r6, %r7	/* arg5 -> 4 */
+	mr	%r7, %r8	/* arg6 -> 5 */
+	mr	%r8, %r9	/* arg7 -> 6 */
+	sc
+	blr
+/* Note: We're exposing the raw return value to the caller */	
+END(host_syscall)
diff --git a/stand/kboot/arch/powerpc64/syscall_nr.h b/stand/kboot/arch/powerpc64/syscall_nr.h
new file mode 100644
index 000000000000..2854124153a2
--- /dev/null
+++ b/stand/kboot/arch/powerpc64/syscall_nr.h
@@ -0,0 +1,15 @@
+#define SYS_read		  3
+#define SYS_write		  4
+#define SYS_open		  5
+#define SYS_close		  6
+#define SYS_gettimeofday	 78
+#define SYS_reboot		 88
+#define SYS_mmap		 90
+#define SYS_uname		120
+#define SYS_llseek		140
+#define SYS_getdents		141
+#define SYS_select		142
+#define __NR_kexec_load		268
+
+#define KEXEC_ARCH_PPC64	 21
+#define KEXEC_ARCH		KEXEC_ARCH_PPC64
diff --git a/stand/kboot/host_syscall.h b/stand/kboot/host_syscall.h
index 60b006e5dba4..f6f22a736d53 100644
--- a/stand/kboot/host_syscall.h
+++ b/stand/kboot/host_syscall.h
@@ -30,12 +30,14 @@
 
 #include <stand.h>
 
+long host_syscall(int number, ...);
+
 ssize_t host_read(int fd, void *buf, size_t nbyte);
 ssize_t host_write(int fd, const void *buf, size_t nbyte);
 int host_open(const char *path, int flags, int mode);
 ssize_t host_llseek(int fd, int32_t offset_high, int32_t offset_lo, uint64_t *result, int whence);
 int host_close(int fd);
-void *host_mmap(void *addr, size_t len, int prot, int flags, int fd, int);
+void *host_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off);
 #define host_getmem(size) host_mmap(0, size, 3 /* RW */, 0x22 /* ANON */, -1, 0);
 struct old_utsname {
 	char sysname[65];
@@ -46,14 +48,14 @@ struct old_utsname {
 };
 int host_uname(struct old_utsname *);
 struct host_timeval {
-	int tv_sec;
-	int tv_usec;
+	time_t tv_sec;
+	long tv_usec;
 };
 int host_gettimeofday(struct host_timeval *a, void *b);
 int host_select(int nfds, long *readfds, long *writefds, long *exceptfds,
     struct host_timeval *timeout);
 int kexec_load(uint32_t start, int nsegs, uint32_t segs);
-int host_reboot(int, int, int, uint32_t);
+int host_reboot(int, int, int, uintptr_t);
 int host_getdents(int fd, void *dirp, int count);
 
 #endif
diff --git a/stand/kboot/host_syscalls.c b/stand/kboot/host_syscalls.c
new file mode 100644
index 000000000000..53be0c166374
--- /dev/null
+++ b/stand/kboot/host_syscalls.c
@@ -0,0 +1,86 @@
+#include "host_syscall.h"
+#include "syscall_nr.h"
+#include <stand.h>
+
+ssize_t
+host_read(int fd, void *buf, size_t nbyte)
+{
+	return host_syscall(SYS_read, fd, (uintptr_t)buf, nbyte);
+	/* XXX original overrode errors */
+}
+
+ssize_t
+host_write(int fd, const void *buf, size_t nbyte)
+{
+	return host_syscall(SYS_write, fd, (uintptr_t)buf, nbyte);
+}
+	
+int
+host_open(const char *path, int flags, int mode)
+{
+	return host_syscall(SYS_open, (uintptr_t)path, flags, mode);
+	/* XXX original overrode errors */
+}
+
+ssize_t
+host_llseek(int fd, int32_t offset_high, int32_t offset_lo, uint64_t *result, int whence)
+{
+#ifdef SYS_llseek
+	return host_syscall(SYS_llseek, fd, offset_high, offset_lo, (uintptr_t)result, whence);
+#else
+	int64_t rv = host_syscall(SYS_lseek, fd,
+	    (int64_t)((uint64_t)offset_high << 32 | (uint32_t)offset_lo), whence);
+	if (rv > 0)
+		*result = (uint64_t)rv;
+	return (rv);
+#endif
+}
+
+int
+host_close(int fd)
+{
+	return host_syscall(SYS_close, fd);
+}
+
+void *
+host_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off)
+{
+	return (void *)host_syscall(SYS_mmap, (uintptr_t)addr, len, prot, flags, fd, off);
+}
+
+int
+host_uname(struct old_utsname *uts)
+{
+	return host_syscall(SYS_uname, (uintptr_t)uts);
+}
+
+int
+host_gettimeofday(struct host_timeval *a, void *b)
+{
+	return host_syscall(SYS_gettimeofday, (uintptr_t)a, (uintptr_t)b);
+}
+
+int
+host_select(int nfds, long *readfds, long *writefds, long *exceptfds,
+    struct host_timeval *timeout)
+{
+	return host_syscall(SYS_select, nfds, (uintptr_t)readfds, (uintptr_t)writefds, (uintptr_t)exceptfds, (uintptr_t)timeout, 0);
+}
+
+int
+kexec_load(uint32_t start, int nsegs, uint32_t segs)
+{
+	return host_syscall(__NR_kexec_load, start, nsegs, segs, KEXEC_ARCH << 16);
+}
+
+int
+host_reboot(int magic1, int magic2, int cmd, uintptr_t arg)
+{
+	return host_syscall(SYS_reboot, magic1, magic2, cmd, arg);
+}
+
+int
+host_getdents(int fd, void *dirp, int count)
+{
+	return host_syscall(SYS_getdents, fd, (uintptr_t)dirp, count);
+}