aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWarner Losh <imp@FreeBSD.org>2021-12-30 23:07:20 +0000
committerWarner Losh <imp@FreeBSD.org>2023-01-24 21:49:19 +0000
commit6c7ccb922462e77bbcf755310e6bba1666a90d5a (patch)
treec772387a0380fdd1dc56d90d9ec4736f73684a3a
parent4b3f5dd4d87c28b4ef1c2cff521eb8bb0f450e89 (diff)
downloadsrc-6c7ccb922462e77bbcf755310e6bba1666a90d5a.tar.gz
src-6c7ccb922462e77bbcf755310e6bba1666a90d5a.zip
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 (cherry picked from commit 5974cfe1ba47ac756fc0d5e48306730e1115b36c)
-rw-r--r--stand/kboot/Makefile2
-rw-r--r--stand/kboot/arch/powerpc64/host_syscall.S116
-rw-r--r--stand/kboot/arch/powerpc64/syscall_nr.h15
-rw-r--r--stand/kboot/host_syscall.h10
-rw-r--r--stand/kboot/host_syscalls.c86
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);
+}