From 2164cf16a3e6cf3ca249a32892d125ed6cd28b0b Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Sun, 2 Jun 2013 15:11:14 -0500 Subject: [PATCH 19/23] bsd-user: add shims for sysarch() and sysctl() system calls To: Cc: This change adds support for sysarch() and sysctl() system call emulation. sysarch() is both architecture and OS dependent. Therefore this change adds a handler for each architecture. sysctl() has a lot special cases that have to each decoded and handled individually. Signed-off-by: Stacey Son --- bsd-user/Makefile.objs | 3 +- bsd-user/freebsd/os-sys.c | 268 ++++++++++++++++++++++++++++++++ bsd-user/i386/syscall.h | 2 + bsd-user/i386/target_arch_sysarch.h | 69 ++++++++ bsd-user/mips/syscall.h | 12 ++- bsd-user/mips/target_arch_sysarch.h | 50 ++++++ bsd-user/mips64/syscall.h | 11 ++ bsd-user/mips64/target_arch_sysarch.h | 50 ++++++ bsd-user/netbsd/os-sys.c | 46 ++++++ bsd-user/openbsd/os-sys.c | 46 ++++++ bsd-user/qemu.h | 5 + bsd-user/sparc/syscall.h | 7 +- bsd-user/sparc/target_arch_sysarch.h | 43 +++++ bsd-user/sparc64/syscall.h | 7 +- bsd-user/sparc64/target_arch_sysarch.h | 43 +++++ bsd-user/syscall.c | 209 +++---------------------- bsd-user/x86_64/syscall.h | 4 +- bsd-user/x86_64/target_arch_sysarch.h | 67 ++++++++ 18 files changed, 747 insertions(+), 195 deletions(-) create mode 100644 bsd-user/freebsd/os-sys.c create mode 100644 bsd-user/i386/target_arch_sysarch.h create mode 100644 bsd-user/mips/target_arch_sysarch.h create mode 100644 bsd-user/mips64/target_arch_sysarch.h create mode 100644 bsd-user/netbsd/os-sys.c create mode 100644 bsd-user/openbsd/os-sys.c create mode 100644 bsd-user/sparc/target_arch_sysarch.h create mode 100644 bsd-user/sparc64/target_arch_sysarch.h create mode 100644 bsd-user/x86_64/target_arch_sysarch.h diff --git a/bsd-user/Makefile.objs b/bsd-user/Makefile.objs index fbb3e56..e392760 100644 --- a/bsd-user/Makefile.objs +++ b/bsd-user/Makefile.objs @@ -1,4 +1,5 @@ obj-y = main.o bsdload.o elfload.o ioctl.o mmap.o signal.o strace.o syscall.o \ uaccess.o bsd-mem.o bsd-proc.o $(TARGET_OS)/os-time.o \ $(TARGET_OS)/os-proc.o bsd-socket.o $(TARGET_OS)/os-socket.o \ - $(TARGET_OS)/os-stat.o $(TARGET_OS)/os-thread.o + $(TARGET_OS)/os-stat.o $(TARGET_OS)/os-sys.o \ + $(TARGET_OS)/os-thread.o diff --git a/bsd-user/freebsd/os-sys.c b/bsd-user/freebsd/os-sys.c new file mode 100644 index 0000000..86b2826 --- /dev/null +++ b/bsd-user/freebsd/os-sys.c @@ -0,0 +1,268 @@ +/* + * FreeBSD sysctl() and sysarch() system call emulation + * + * Copyright (c) 2013 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include +#include + +#include "qemu.h" + +#include "target_arch_sysarch.h" +#include "target_os_vmparam.h" + +/* + * XXX this uses the undocumented oidfmt interface to find the kind of + * a requested sysctl, see /sys/kern/kern_sysctl.c:sysctl_sysctl_oidfmt() + * (compare to src/sbin/sysctl/sysctl.c) + */ +static int +oidfmt(int *oid, int len, char *fmt, uint32_t *kind) +{ + int qoid[CTL_MAXNAME+2]; + uint8_t buf[BUFSIZ]; + int i; + size_t j; + + qoid[0] = 0; + qoid[1] = 4; + memcpy(qoid + 2, oid, len * sizeof(int)); + + j = sizeof(buf); + i = sysctl(qoid, len + 2, buf, &j, 0, 0); + if (i) { + return i; + } + + if (kind) { + *kind = *(uint32_t *)buf; + } + + if (fmt) { + strcpy(fmt, (char *)(buf + sizeof(uint32_t))); + } + return 0; +} + +/* + * try and convert sysctl return data for the target. + * XXX doesn't handle CTLTYPE_OPAQUE and CTLTYPE_STRUCT. + */ +static int sysctl_oldcvt(void *holdp, size_t holdlen, uint32_t kind) +{ + switch (kind & CTLTYPE) { + case CTLTYPE_INT: + case CTLTYPE_UINT: + *(uint32_t *)holdp = tswap32(*(uint32_t *)holdp); + break; + +#ifdef TARGET_ABI32 + case CTLTYPE_LONG: + case CTLTYPE_ULONG: + *(uint32_t *)holdp = tswap32(*(long *)holdp); + break; +#else + case CTLTYPE_LONG: + *(uint64_t *)holdp = tswap64(*(long *)holdp); + case CTLTYPE_ULONG: + *(uint64_t *)holdp = tswap64(*(unsigned long *)holdp); + break; +#endif +#if !defined(__FreeBSD_version) || __FreeBSD_version < 900031 + case CTLTYPE_QUAD: +#else + case CTLTYPE_U64: + case CTLTYPE_S64: +#endif + *(uint64_t *)holdp = tswap64(*(uint64_t *)holdp); + break; + + case CTLTYPE_STRING: + break; + + default: + /* XXX unhandled */ + return -1; + } + return 0; +} + +/* + * Convert the undocmented name2oid sysctl data for the target. + */ +static inline void sysctl_name2oid(uint32_t *holdp, size_t holdlen) +{ + size_t i; + + for (i = 0; i < holdlen; i++) { + holdp[i] = tswap32(holdp[i]); + } +} + +static inline void sysctl_oidfmt(uint32_t *holdp) +{ + /* byte swap the kind */ + holdp[0] = tswap32(holdp[0]); +} + +abi_long do_freebsd_sysctl(CPUArchState *env, abi_ulong namep, int32_t namelen, + abi_ulong oldp, abi_ulong oldlenp, abi_ulong newp, abi_ulong newlen) +{ + abi_long ret; + void *hnamep, *holdp = NULL, *hnewp = NULL; + size_t holdlen; + abi_ulong oldlen = 0; + int32_t *snamep = g_malloc(sizeof(int32_t) * namelen), *p, *q, i; + uint32_t kind = 0; + TaskState *ts = (TaskState *)env->opaque; + + if (oldlenp) { + if (get_user_ual(oldlen, oldlenp)) { + return -TARGET_EFAULT; + } + } + hnamep = lock_user(VERIFY_READ, namep, namelen, 1); + if (hnamep == NULL) { + return -TARGET_EFAULT; + } + if (newp) { + hnewp = lock_user(VERIFY_READ, newp, newlen, 1); + if (hnewp == NULL) { + return -TARGET_EFAULT; + } + } + if (oldp) { + holdp = lock_user(VERIFY_WRITE, oldp, oldlen, 0); + if (holdp == NULL) { + return -TARGET_EFAULT; + } + } + holdlen = oldlen; + for (p = hnamep, q = snamep, i = 0; i < namelen; p++, i++) { + *q++ = tswap32(*p); + } + oidfmt(snamep, namelen, NULL, &kind); + + /* Handle some arch/emulator dependent sysctl()'s here. */ + switch (snamep[0]) { + case CTL_KERN: + switch (snamep[1]) { + case KERN_USRSTACK: +#if TARGET_USRSTACK != 0 + (*(abi_ulong *)holdp) = tswapal(TARGET_USRSTACK); + holdlen = sizeof(abi_ulong); + ret = 0; +#else + ret = -TARGET_ENOENT; +#endif + goto out; + + case KERN_PS_STRINGS: +#if defined(TARGET_PS_STRINGS) + (*(abi_ulong *)holdp) = tswapal(TARGET_PS_STRINGS); + holdlen = sizeof(abi_ulong); + ret = 0; +#else + ret = -TARGET_ENOENT; +#endif + goto out; + + case KERN_PROC: + switch (snamep[2]) { + case KERN_PROC_PATHNAME: + holdlen = strlen(ts->bprm->fullpath) + 1; + if (holdp) { + if (oldlen < holdlen) { + ret = -TARGET_EINVAL; + goto out; + } + strlcpy(holdp, ts->bprm->fullpath, oldlen); + } + ret = 0; + goto out; + + default: + break; + } + break; + + default: + break; + } + break; + + case CTL_HW: + switch (snamep[1]) { + case HW_MACHINE: + strlcpy(holdp, TARGET_HW_MACHINE, oldlen); + ret = 0; + goto out; + + case HW_MACHINE_ARCH: + strlcpy(holdp, TARGET_HW_MACHINE_ARCH, oldlen); + ret = 0; + goto out; + + default: + break; + } + default: + break; + } + + ret = get_errno(sysctl(snamep, namelen, holdp, &holdlen, hnewp, newlen)); + if (!ret && (holdp != 0 && holdlen != 0)) { + if (0 == snamep[0] && (3 == snamep[1] || 4 == snamep[1])) { + if (3 == snamep[1]) { + /* Handle the undocumented name2oid special case. */ + sysctl_name2oid(holdp, holdlen); + } else { + /* Handle oidfmt */ + sysctl_oidfmt(holdp); + } + } else { + sysctl_oldcvt(holdp, holdlen, kind); + } + } +#ifdef DEBUG + else { + printf("sysctl(mib[0]=%d, mib[1]=%d, mib[3]=%d...) returned %d\n", + snamep[0], snamep[1], snamep[2], (int)ret); + } +#endif + +out: + if (oldlenp) { + put_user_ual(holdlen, oldlenp); + } + unlock_user(hnamep, namep, 0); + unlock_user(holdp, oldp, holdlen); + if (hnewp) { + unlock_user(hnewp, newp, 0); + } + g_free(snamep); + return ret; +} + +/* sysarch() is architecture dependent. */ +abi_long do_freebsd_sysarch(void *cpu_env, abi_long arg1, abi_long arg2) +{ + + return do_freebsd_arch_sysarch(cpu_env, arg1, arg2); +} diff --git a/bsd-user/i386/syscall.h b/bsd-user/i386/syscall.h index 8028fc8..52de302 100644 --- a/bsd-user/i386/syscall.h +++ b/bsd-user/i386/syscall.h @@ -178,5 +178,7 @@ struct target_vm86plus_struct { #define UNAME_MACHINE "i386" +#define TARGET_HW_MACHINE UNAME_MACHINE +#define TARGET_HW_MACHINE_ARCH UNAME_MACHINE #endif /* ! _I386_SYSCALL_H_ */ diff --git a/bsd-user/i386/target_arch_sysarch.h b/bsd-user/i386/target_arch_sysarch.h new file mode 100644 index 0000000..373c838 --- /dev/null +++ b/bsd-user/i386/target_arch_sysarch.h @@ -0,0 +1,69 @@ +/* + * i386 sysarch system call emulation + * + * Copyright (c) 2013 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef __ARCH_SYSARCH_H_ +#define __ARCH_SYSARCH_H_ + +#include "syscall.h" + +static abi_long do_freebsd_arch_sysarch(CPUX86State *env, int op, + abi_ulong parms) +{ + abi_long ret = 0; + abi_ulong val; + int idx; + + switch (op) { + case TARGET_FREEBSD_I386_SET_GSBASE: + case TARGET_FREEBSD_I386_SET_FSBASE: + if (op == TARGET_FREEBSD_I386_SET_GSBASE) { + idx = R_GS; + } else { + idx = R_FS; + } + if (get_user(val, parms, abi_ulong)) { + return -TARGET_EFAULT; + } + cpu_x86_load_seg(env, idx, 0); + env->segs[idx].base = val; + break; + + case TARGET_FREEBSD_I386_GET_GSBASE: + case TARGET_FREEBSD_I386_GET_FSBASE: + if (op == TARGET_FREEBSD_I386_GET_GSBASE) { + idx = R_GS; + } else { + idx = R_FS; + } + val = env->segs[idx].base; + if (put_user(val, parms, abi_ulong)) { + return -TARGET_EFAULT; + } + break; + + /* XXX handle the others... */ + default: + ret = -TARGET_EINVAL; + break; + } + return ret; +} + +#endif /* !__ARCH_SYSARCH_H_ */ + diff --git a/bsd-user/mips/syscall.h b/bsd-user/mips/syscall.h index 149970a..49e2833 100644 --- a/bsd-user/mips/syscall.h +++ b/bsd-user/mips/syscall.h @@ -36,7 +36,17 @@ struct target_pt_regs { abi_ulong cp0_epc; }; - +#if defined(TARGET_WORDS_BIG_ENDIAN) #define UNAME_MACHINE "mips" +#else +#define UNAME_MACHINE "mipsel" +#endif + +#define TARGET_HW_MACHINE "mips" +#define TARGET_HW_MACHINE_ARCH UNAME_MACHINE + +/* sysarch() commands */ +#define TARGET_MIPS_SET_TLS 1 +#define TARGET_MIPS_GET_TLS 2 #endif /* !_MIPS_SYSCALL_H_ */ diff --git a/bsd-user/mips/target_arch_sysarch.h b/bsd-user/mips/target_arch_sysarch.h new file mode 100644 index 0000000..22fa53a --- /dev/null +++ b/bsd-user/mips/target_arch_sysarch.h @@ -0,0 +1,50 @@ +/* + * mips sysarch() system call emulation + * + * Copyright (c) 2013 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef __ARCH_SYSARCH_H_ +#define __ARCH_SYSARCH_H_ + +#include "syscall.h" + +static abi_long do_freebsd_arch_sysarch(CPUMIPSState *env, int op, + abi_ulong parms) +{ + int ret = 0; + + switch (op) { + case TARGET_MIPS_SET_TLS: + cpu_set_tls(env, parms); + break; + + case TARGET_MIPS_GET_TLS: + /* XXX Need a cpu_get_tls() */ + if (put_user(env->tls_value, parms, abi_ulong)) { + ret = -TARGET_EFAULT; + } + break; + + default: + ret = -TARGET_EINVAL; + break; + } + + return ret; +} + +#endif /*!__ARCH_SYSARCH_H_ */ diff --git a/bsd-user/mips64/syscall.h b/bsd-user/mips64/syscall.h index 300ed9b..b068fa1 100644 --- a/bsd-user/mips64/syscall.h +++ b/bsd-user/mips64/syscall.h @@ -37,6 +37,17 @@ struct target_pt_regs { }; +#if defined(TARGET_WORDS_BIG_ENDIAN) #define UNAME_MACHINE "mips64" +#else +#define UNAME_MACHINE "mips64el" +#endif + +#define TARGET_HW_MACHINE "mips" +#define TARGET_HW_MACHINE_ARCH UNAME_MACHINE + +/* sysarch() commands */ +#define TARGET_MIPS_SET_TLS 1 +#define TARGET_MIPS_GET_TLS 2 #endif /* !_MIPS64_SYSCALL_H_ */ diff --git a/bsd-user/mips64/target_arch_sysarch.h b/bsd-user/mips64/target_arch_sysarch.h new file mode 100644 index 0000000..503bc90 --- /dev/null +++ b/bsd-user/mips64/target_arch_sysarch.h @@ -0,0 +1,50 @@ +/* + * mips64 sysarch() system call emulation + * + * Copyright (c) 2013 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef __ARCH_SYSARCH_H_ +#define __ARCH_SYSARCH_H_ + +#include "syscall.h" + +static inline abi_long do_freebsd_arch_sysarch(CPUMIPSState *env, int op, + abi_ulong parms) +{ + int ret = 0; + + switch (op) { + case TARGET_MIPS_SET_TLS: + cpu_set_tls(env, parms); + break; + + case TARGET_MIPS_GET_TLS: + /* XXX Need a cpu_get_tls() */ + if (put_user(env->tls_value, parms, abi_ulong)) { + ret = -TARGET_EFAULT; + } + break; + + default: + ret = -TARGET_EINVAL; + break; + } + + return ret; +} + +#endif /*!__ARCH_SYSARCH_H_ */ diff --git a/bsd-user/netbsd/os-sys.c b/bsd-user/netbsd/os-sys.c new file mode 100644 index 0000000..68ea0e1 --- /dev/null +++ b/bsd-user/netbsd/os-sys.c @@ -0,0 +1,46 @@ +/* + * NetBSD sysctl() and sysarch() system call emulation + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include +#include + +#include "qemu.h" + +#include "target_arch_sysarch.h" +#include "target_os_vmparam.h" + + +/* This must be emulated to support FreeBSD target binaries on NetBSD host. */ + +abi_long do_freebsd_sysctl(CPUArchState *env, abi_ulong namep, int32_t namelen, + abi_ulong oldp, abi_ulong oldlenp, abi_ulong newp, abi_ulong newlen) +{ + + qemu_log("qemu: Unsupported syscall __sysctl()\n"); + return -TARGET_ENOSYS; +} + +/* sysarch() is architecture dependent. */ +abi_long do_freebsd_sysarch(void *cpu_env, abi_long arg1, abi_long arg2) +{ + + qemu_log("qemu: Unsupported syscall sysarch()\n"); + return -TARGET_ENOSYS; +} diff --git a/bsd-user/openbsd/os-sys.c b/bsd-user/openbsd/os-sys.c new file mode 100644 index 0000000..30df472 --- /dev/null +++ b/bsd-user/openbsd/os-sys.c @@ -0,0 +1,46 @@ +/* + * OpenBSD sysctl() and sysarch() system call emulation + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include +#include + +#include "qemu.h" + +#include "target_arch_sysarch.h" +#include "target_os_vmparam.h" + + +/* This must be emulated to support FreeBSD target binaries on NetBSD host. */ + +abi_long do_freebsd_sysctl(CPUArchState *env, abi_ulong namep, int32_t namelen, + abi_ulong oldp, abi_ulong oldlenp, abi_ulong newp, abi_ulong newlen) +{ + + qemu_log("qemu: Unsupported syscall __sysctl()\n"); + return -TARGET_ENOSYS; +} + +/* sysarch() is architecture dependent. */ +abi_long do_freebsd_sysarch(void *cpu_env, abi_long arg1, abi_long arg2) +{ + + qemu_log("qemu: Unsupported syscall sysarch()\n"); + return -TARGET_ENOSYS; +} diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h index ec194d2..2ddf244 100644 --- a/bsd-user/qemu.h +++ b/bsd-user/qemu.h @@ -248,6 +248,11 @@ int is_error(abi_long ret); abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp, abi_ulong guest_envp, int do_fexec); +/* os-sys.c */ +abi_long do_freebsd_sysctl(CPUArchState *env, abi_ulong namep, int32_t namelen, + abi_ulong oldp, abi_ulong oldlenp, abi_ulong newp, abi_ulong newlen); +abi_long do_freebsd_sysarch(void *cpu_env, abi_long arg1, abi_long arg2); + /* os-thread.c */ extern pthread_mutex_t *new_freebsd_thread_lock_ptr; void *new_freebsd_thread_start(void *arg); diff --git a/bsd-user/sparc/syscall.h b/bsd-user/sparc/syscall.h index 804889a..3a5b1e2 100644 --- a/bsd-user/sparc/syscall.h +++ b/bsd-user/sparc/syscall.h @@ -26,6 +26,11 @@ struct target_pt_regs { abi_ulong u_regs[16]; }; -#define UNAME_MACHINE "sun4" +#define UNAME_MACHINE "sun4" +#define TARGET_HW_MACHINE "sparc" +#define TARGET_HW_MACHINE_ARCH "sparc" + +#define TARGET_SPARC_UTRAP_INSTALL 1 +#define TARGET_SPARC_SIGTRAMP_INSTALL 2 #endif /* ! _SPARC_SYSCALL_H_ */ diff --git a/bsd-user/sparc/target_arch_sysarch.h b/bsd-user/sparc/target_arch_sysarch.h new file mode 100644 index 0000000..e523798 --- /dev/null +++ b/bsd-user/sparc/target_arch_sysarch.h @@ -0,0 +1,43 @@ +/* + * SPARC sysarch() system call emulation + * + * Copyright (c) 2013 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef __ARCH_SYSARCH_H_ +#define __ARCH_SYSARCH_H_ + +#include "syscall.h" + +static abi_long do_freebsd_arch_sysarch(void *env, int op, abi_ulong parms) +{ + int ret = 0; + + switch (op) { + case TARGET_SPARC_SIGTRAMP_INSTALL: + /* XXX not currently handled */ + case TARGET_SPARC_UTRAP_INSTALL: + /* XXX not currently handled */ + default: + ret = -TARGET_EINVAL; + break; + } + + return ret; +} + + +#endif /*!__ARCH_SYSARCH_H_ */ diff --git a/bsd-user/sparc64/syscall.h b/bsd-user/sparc64/syscall.h index 9f3b97e..58cc38d 100644 --- a/bsd-user/sparc64/syscall.h +++ b/bsd-user/sparc64/syscall.h @@ -26,6 +26,11 @@ struct target_pt_regs { abi_ulong fprs; }; -#define UNAME_MACHINE "sun4u" +#define UNAME_MACHINE "sun4u" +#define TARGET_HW_MACHINE "sparc" +#define TARGET_HW_MACHINE_ARCH "sparc64" + +#define TARGET_SPARC_UTRAP_INSTALL 1 +#define TARGET_SPARC_SIGTRAMP_INSTALL 2 #endif /* !_SPARC64_SYSCALL_H_ */ diff --git a/bsd-user/sparc64/target_arch_sysarch.h b/bsd-user/sparc64/target_arch_sysarch.h new file mode 100644 index 0000000..c18f699 --- /dev/null +++ b/bsd-user/sparc64/target_arch_sysarch.h @@ -0,0 +1,43 @@ +/* + * SPARC64 sysarch() system call emulation + * + * Copyright (c) 2013 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef __ARCH_SYSARCH_H_ +#define __ARCH_SYSARCH_H_ + +#include "syscall.h" + +static abi_long do_freebsd_arch_sysarch(void *env, int op, abi_ulong parms) +{ + int ret = 0; + + switch (op) { + case TARGET_SPARC_SIGTRAMP_INSTALL: + /* XXX not currently handled */ + case TARGET_SPARC_UTRAP_INSTALL: + /* XXX not currently handled */ + default: + ret = -TARGET_EINVAL; + break; + } + + return ret; +} + + +#endif /*!__ARCH_SYSARCH_H_ */ diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c index 3407894..b976c93 100644 --- a/bsd-user/syscall.c +++ b/bsd-user/syscall.c @@ -77,183 +77,6 @@ int is_error(abi_long ret) return (abi_ulong)ret >= (abi_ulong)(-4096); } -#if defined(TARGET_I386) -static abi_long do_freebsd_sysarch(CPUX86State *env, int op, abi_ulong parms) -{ - abi_long ret = 0; - abi_ulong val; - int idx; - - switch (op) { -#ifdef TARGET_ABI32 - case TARGET_FREEBSD_I386_SET_GSBASE: - case TARGET_FREEBSD_I386_SET_FSBASE: - if (op == TARGET_FREEBSD_I386_SET_GSBASE) -#else - case TARGET_FREEBSD_AMD64_SET_GSBASE: - case TARGET_FREEBSD_AMD64_SET_FSBASE: - if (op == TARGET_FREEBSD_AMD64_SET_GSBASE) -#endif - idx = R_GS; - else - idx = R_FS; - if (get_user(val, parms, abi_ulong)) - return -TARGET_EFAULT; - cpu_x86_load_seg(env, idx, 0); - env->segs[idx].base = val; - break; -#ifdef TARGET_ABI32 - case TARGET_FREEBSD_I386_GET_GSBASE: - case TARGET_FREEBSD_I386_GET_FSBASE: - if (op == TARGET_FREEBSD_I386_GET_GSBASE) -#else - case TARGET_FREEBSD_AMD64_GET_GSBASE: - case TARGET_FREEBSD_AMD64_GET_FSBASE: - if (op == TARGET_FREEBSD_AMD64_GET_GSBASE) -#endif - idx = R_GS; - else - idx = R_FS; - val = env->segs[idx].base; - if (put_user(val, parms, abi_ulong)) - return -TARGET_EFAULT; - break; - /* XXX handle the others... */ - default: - ret = -TARGET_EINVAL; - break; - } - return ret; -} -#endif - -#ifdef TARGET_MIPS -static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms) -{ - - return -TARGET_EINVAL; -} -#endif /* TARGET_MIPS */ - -#ifdef TARGET_SPARC -static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms) -{ - /* XXX handle - * TARGET_FREEBSD_SPARC_UTRAP_INSTALL, - * TARGET_FREEBSD_SPARC_SIGTRAMP_INSTALL - */ - return -TARGET_EINVAL; -} -#endif - -#ifdef __FreeBSD__ -/* - * XXX this uses the undocumented oidfmt interface to find the kind of - * a requested sysctl, see /sys/kern/kern_sysctl.c:sysctl_sysctl_oidfmt() - * (this is mostly copied from src/sbin/sysctl/sysctl.c) - */ -static int -oidfmt(int *oid, int len, char *fmt, uint32_t *kind) -{ - int qoid[CTL_MAXNAME+2]; - uint8_t buf[BUFSIZ]; - int i; - size_t j; - - qoid[0] = 0; - qoid[1] = 4; - memcpy(qoid + 2, oid, len * sizeof(int)); - - j = sizeof(buf); - i = sysctl(qoid, len + 2, buf, &j, 0, 0); - if (i) - return i; - - if (kind) - *kind = *(uint32_t *)buf; - - if (fmt) - strcpy(fmt, (char *)(buf + sizeof(uint32_t))); - return 0; -} - -/* - * try and convert sysctl return data for the target. - * XXX doesn't handle CTLTYPE_OPAQUE and CTLTYPE_STRUCT. - */ -static int sysctl_oldcvt(void *holdp, size_t holdlen, uint32_t kind) -{ - switch (kind & CTLTYPE) { - case CTLTYPE_INT: - case CTLTYPE_UINT: - *(uint32_t *)holdp = tswap32(*(uint32_t *)holdp); - break; -#ifdef TARGET_ABI32 - case CTLTYPE_LONG: - case CTLTYPE_ULONG: - *(uint32_t *)holdp = tswap32(*(long *)holdp); - break; -#else - case CTLTYPE_LONG: - *(uint64_t *)holdp = tswap64(*(long *)holdp); - case CTLTYPE_ULONG: - *(uint64_t *)holdp = tswap64(*(unsigned long *)holdp); - break; -#endif -#ifdef CTLTYPE_U64 - case CTLTYPE_S64: - case CTLTYPE_U64: -#else - case CTLTYPE_QUAD: -#endif - *(uint64_t *)holdp = tswap64(*(uint64_t *)holdp); - break; - case CTLTYPE_STRING: - break; - default: - /* XXX unhandled */ - return -1; - } - return 0; -} - -/* XXX this needs to be emulated on non-FreeBSD hosts... */ -static abi_long do_freebsd_sysctl(abi_ulong namep, int32_t namelen, abi_ulong oldp, - abi_ulong oldlenp, abi_ulong newp, abi_ulong newlen) -{ - abi_long ret; - void *hnamep, *holdp, *hnewp = NULL; - size_t holdlen; - abi_ulong oldlen = 0; - int32_t *snamep = g_malloc(sizeof(int32_t) * namelen), *p, *q, i; - uint32_t kind = 0; - - if (oldlenp) - get_user_ual(oldlen, oldlenp); - if (!(hnamep = lock_user(VERIFY_READ, namep, namelen, 1))) - return -TARGET_EFAULT; - if (newp && !(hnewp = lock_user(VERIFY_READ, newp, newlen, 1))) - return -TARGET_EFAULT; - if (!(holdp = lock_user(VERIFY_WRITE, oldp, oldlen, 0))) - return -TARGET_EFAULT; - holdlen = oldlen; - for (p = hnamep, q = snamep, i = 0; i < namelen; p++, i++) - *q++ = tswap32(*p); - oidfmt(snamep, namelen, NULL, &kind); - /* XXX swap hnewp */ - ret = get_errno(sysctl(snamep, namelen, holdp, &holdlen, hnewp, newlen)); - if (!ret) - sysctl_oldcvt(holdp, holdlen, kind); - put_user_ual(holdlen, oldlenp); - unlock_user(hnamep, namep, 0); - unlock_user(holdp, oldp, holdlen); - if (hnewp) - unlock_user(hnewp, newp, 0); - g_free(snamep); - return ret; -} -#endif - /* FIXME * lock_iovec()/unlock_iovec() have a return code of 0 for success where * other lock functions have a return code of 0 for failure. @@ -1348,24 +1171,30 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_bsd_ioctl(arg1, arg2, arg3); break; - - case TARGET_FREEBSD_NR_break: - ret = do_obreak(arg1); - break; -#ifdef __FreeBSD__ - case TARGET_FREEBSD_NR___sysctl: - ret = do_freebsd_sysctl(arg1, arg2, arg3, arg4, arg5, arg6); + /* + * sys{ctl, arch, call} + */ + case TARGET_FREEBSD_NR___sysctl: /* sysctl(3) */ + ret = do_freebsd_sysctl(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6); break; -#endif - case TARGET_FREEBSD_NR_sysarch: + + case TARGET_FREEBSD_NR_sysarch: /* sysarch(2) */ ret = do_freebsd_sysarch(cpu_env, arg1, arg2); break; - case TARGET_FREEBSD_NR_syscall: - case TARGET_FREEBSD_NR___syscall: - ret = do_freebsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,arg7,arg8,0); + + case TARGET_FREEBSD_NR_syscall: /* syscall(2) */ + case TARGET_FREEBSD_NR___syscall: /* __syscall(2) */ + ret = do_freebsd_syscall(cpu_env, arg1 & 0xffff, arg2, arg3, arg4, + arg5, arg6, arg7, arg8, 0); + break; + + case TARGET_FREEBSD_NR_break: + ret = do_obreak(arg1); break; + default: - ret = get_errno(syscall(num, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)); + ret = get_errno(syscall(num, arg1, arg2, arg3, arg4, arg5, arg6, arg7, + arg8)); break; } diff --git a/bsd-user/x86_64/syscall.h b/bsd-user/x86_64/syscall.h index fbaeacf..4fff6a5 100644 --- a/bsd-user/x86_64/syscall.h +++ b/bsd-user/x86_64/syscall.h @@ -128,7 +128,9 @@ struct target_msqid64_ds { #define TARGET_FREEBSD_AMD64_SET_GSBASE 131 -#define UNAME_MACHINE "x86_64" +#define UNAME_MACHINE "x86_64" +#define TARGET_HW_MACHINE "amd64" +#define TARGET_HW_MACHINE_ARCH "amd64" #define TARGET_ARCH_SET_GS 0x1001 #define TARGET_ARCH_SET_FS 0x1002 diff --git a/bsd-user/x86_64/target_arch_sysarch.h b/bsd-user/x86_64/target_arch_sysarch.h new file mode 100644 index 0000000..52a1d18 --- /dev/null +++ b/bsd-user/x86_64/target_arch_sysarch.h @@ -0,0 +1,67 @@ +/* + * x86_64 sysarch() syscall emulation + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef __ARCH_SYSARCH_H_ +#define __ARCH_SYSARCH_H_ + +#include "syscall.h" + +static abi_long do_freebsd_arch_sysarch(CPUX86State *env, int op, + abi_ulong parms) +{ + abi_long ret = 0; + abi_ulong val; + int idx; + + switch (op) { + case TARGET_FREEBSD_AMD64_SET_GSBASE: + case TARGET_FREEBSD_AMD64_SET_FSBASE: + if (op == TARGET_FREEBSD_AMD64_SET_GSBASE) { + idx = R_GS; + } else { + idx = R_FS; + } + if (get_user(val, parms, abi_ulong)) { + return -TARGET_EFAULT; + } + cpu_x86_load_seg(env, idx, 0); + env->segs[idx].base = val; + break; + + case TARGET_FREEBSD_AMD64_GET_GSBASE: + case TARGET_FREEBSD_AMD64_GET_FSBASE: + if (op == TARGET_FREEBSD_AMD64_GET_GSBASE) { + idx = R_GS; + } else { + idx = R_FS; + } + val = env->segs[idx].base; + if (put_user(val, parms, abi_ulong)) { + return -TARGET_EFAULT; + } + break; + + /* XXX handle the others... */ + default: + ret = -TARGET_EINVAL; + break; + } + return ret; +} + +#endif /*! __ARCH_SYSARCH_H_ */ -- 1.7.8