From: Stacey Son <sson@FreeBSD.org>
To: qemu-devel@nongnu.org
Cc: Stacey Son <sson@FreeBSD.org>
Subject: [Qemu-devel] [PATCH 19/23] bsd-user: add shims for sysarch() and sysctl() system calls
Date: Sun, 23 Jun 2013 21:03:51 -0500 [thread overview]
Message-ID: <1372039435-41921-20-git-send-email-sson@FreeBSD.org> (raw)
In-Reply-To: <1372039435-41921-1-git-send-email-sson@FreeBSD.org>
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 <sson@FreeBSD.org>
---
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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <string.h>
+
+#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 <http://www.gnu.org/licenses/>.
+ */
+
+#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 <http://www.gnu.org/licenses/>.
+ */
+
+#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 <http://www.gnu.org/licenses/>.
+ */
+
+#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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <string.h>
+
+#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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <string.h>
+
+#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 <http://www.gnu.org/licenses/>.
+ */
+
+#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 <http://www.gnu.org/licenses/>.
+ */
+
+#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 <http://www.gnu.org/licenses/>.
+ */
+
+#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
next prev parent reply other threads:[~2013-06-24 17:03 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-06-24 2:03 [Qemu-devel] [PATCH 00/23] bsd-user: FreeBSD support for mips/mips64 and arm Stacey Son
2013-06-24 2:03 ` [Qemu-devel] [PATCH 01/23] bsd-user: initial code clean up Stacey Son
2013-06-24 2:03 ` [Qemu-devel] [PATCH 02/23] bsd-user: add initial support for mips/mips64 Stacey Son
2013-06-24 17:15 ` Peter Maydell
2013-06-24 20:09 ` Stacey Son
2013-06-24 2:03 ` [Qemu-devel] [PATCH 03/23] bsd-user: additional seperation of OS and architecture dependent code Stacey Son
2013-06-24 17:20 ` Peter Maydell
2013-06-24 17:24 ` Peter Maydell
2013-06-24 20:15 ` Stacey Son
2013-06-24 2:03 ` [Qemu-devel] [PATCH 04/23] bsd-user: add bsd signal emulation Stacey Son
2013-06-24 2:03 ` [Qemu-devel] [PATCH 05/23] bsd-user: add bsd_binprm to TaskState for core dumping emulation Stacey Son
2013-06-24 2:03 ` [Qemu-devel] [PATCH 06/23] bsd-user: fix thread initialization and ELF addresses for mips/mips64 Stacey Son
2013-06-24 2:03 ` [Qemu-devel] [PATCH 07/23] bsd-user: find target executable in path when absolute path not given Stacey Son
2013-06-24 2:03 ` [Qemu-devel] [PATCH 08/23] bsd-user: initialize stack with signal trampolin code and canary Stacey Son
2013-06-24 2:03 ` [Qemu-devel] [PATCH 09/23] bsd-user: refresh FreeBSD's system call numbers Stacey Son
2013-06-24 2:03 ` [Qemu-devel] [PATCH 10/23] bsd-user: add shims for memory management related syscalls Stacey Son
2013-06-24 17:26 ` Peter Maydell
2013-06-24 2:03 ` [Qemu-devel] [PATCH 11/23] bsd-user: add shims for file related system calls Stacey Son
2013-06-24 2:03 ` [Qemu-devel] [PATCH 12/23] bsd-user: add shims for time " Stacey Son
2013-06-24 2:03 ` [Qemu-devel] [PATCH 13/23] bsd-user: add shims for signal " Stacey Son
2013-06-24 2:03 ` [Qemu-devel] [PATCH 14/23] bsd-user: add shims for process " Stacey Son
2013-06-24 2:03 ` [Qemu-devel] [PATCH 15/23] bsd-user: add shims for socket " Stacey Son
2013-06-24 2:03 ` [Qemu-devel] [PATCH 16/23] bsd-user: add shims for stat and file handle related syscalls Stacey Son
2013-06-24 2:03 ` [Qemu-devel] [PATCH 17/23] bsd-user: add shims for thread related system calls Stacey Son
2013-06-24 17:37 ` Peter Maydell
2013-06-24 20:23 ` Stacey Son
2013-06-24 2:03 ` [Qemu-devel] [PATCH 18/23] bsd-user: add shim for the ioctl system call Stacey Son
2013-06-24 2:03 ` Stacey Son [this message]
2013-06-24 2:03 ` [Qemu-devel] [PATCH 20/23] bsd-user: add shims for extended attributes system calls Stacey Son
2013-06-24 2:03 ` [Qemu-devel] [PATCH 21/23] bsd-user: add miscellaneous system call shims Stacey Son
2013-06-24 2:03 ` [Qemu-devel] [PATCH 22/23] bsd-user: add more strace formating Stacey Son
2013-06-24 17:41 ` Peter Maydell
2013-06-24 20:55 ` Stacey Son
2013-06-24 2:03 ` [Qemu-devel] [PATCH 23/23] bsd-user: add arm cpu support Stacey Son
2013-06-24 17:18 ` Peter Maydell
2013-06-24 17:49 ` [Qemu-devel] [PATCH 00/23] bsd-user: FreeBSD support for mips/mips64 and arm Peter Maydell
2013-06-24 19:18 ` Stacey Son
2013-06-24 17:55 ` Anthony Liguori
2013-06-24 19:29 ` Stacey Son
2013-06-24 20:07 ` Anthony Liguori
2013-06-24 20:40 ` Stacey Son
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1372039435-41921-20-git-send-email-sson@FreeBSD.org \
--to=sson@freebsd.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).