[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 19/23] bsd-user: add shims for sysarch() and sysctl(
From: |
Stacey Son |
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 |
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 <address@hidden>
---
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
- Re: [Qemu-devel] [PATCH 22/23] bsd-user: add more strace formating, (continued)
- [Qemu-devel] [PATCH 20/23] bsd-user: add shims for extended attributes system calls, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 18/23] bsd-user: add shim for the ioctl system call, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 16/23] bsd-user: add shims for stat and file handle related syscalls, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 15/23] bsd-user: add shims for socket related system calls, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 14/23] bsd-user: add shims for process related system calls, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 21/23] bsd-user: add miscellaneous system call shims, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 17/23] bsd-user: add shims for thread related system calls, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 19/23] bsd-user: add shims for sysarch() and sysctl() system calls,
Stacey Son <=
- [Qemu-devel] [PATCH 23/23] bsd-user: add arm cpu support, Stacey Son, 2013/06/24
- Re: [Qemu-devel] [PATCH 00/23] bsd-user: FreeBSD support for mips/mips64 and arm, Peter Maydell, 2013/06/24
- Re: [Qemu-devel] [PATCH 00/23] bsd-user: FreeBSD support for mips/mips64 and arm, Anthony Liguori, 2013/06/24