diff --git a/stand/kboot/Makefile b/stand/kboot/Makefile --- a/stand/kboot/Makefile +++ b/stand/kboot/Makefile @@ -17,7 +17,7 @@ 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 --- a/stand/kboot/arch/powerpc64/host_syscall.S +++ b/stand/kboot/arch/powerpc64/host_syscall.S @@ -1,88 +1,32 @@ -/* - * - * $FreeBSD$ - */ - #include -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 --- /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 --- a/stand/kboot/host_syscall.h +++ b/stand/kboot/host_syscall.h @@ -30,12 +30,14 @@ #include +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 @@ }; 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 --- /dev/null +++ b/stand/kboot/host_syscalls.c @@ -0,0 +1,86 @@ +#include "host_syscall.h" +#include "syscall_nr.h" +#include + +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); +}