summaryrefslogtreecommitdiffstats
path: root/bsd-user
diff options
context:
space:
mode:
Diffstat (limited to 'bsd-user')
-rw-r--r--bsd-user/arm/target.h21
-rw-r--r--bsd-user/arm/target_arch_cpu.h139
-rw-r--r--bsd-user/arm/target_arch_thread.h4
-rw-r--r--bsd-user/bsd-file.h30
-rw-r--r--bsd-user/freebsd/meson.build1
-rw-r--r--bsd-user/freebsd/os-syscall.c92
-rw-r--r--bsd-user/i386/target.h21
-rw-r--r--bsd-user/i386/target_arch_cpu.h84
-rw-r--r--bsd-user/main.c14
-rw-r--r--bsd-user/meson.build1
-rw-r--r--bsd-user/qemu.h24
-rw-r--r--bsd-user/syscall.c516
-rw-r--r--bsd-user/syscall_defs.h47
-rw-r--r--bsd-user/x86_64/target.h21
-rw-r--r--bsd-user/x86_64/target_arch_cpu.h85
-rw-r--r--bsd-user/x86_64/target_arch_thread.h4
16 files changed, 362 insertions, 742 deletions
diff --git a/bsd-user/arm/target.h b/bsd-user/arm/target.h
new file mode 100644
index 0000000000..419c039b68
--- /dev/null
+++ b/bsd-user/arm/target.h
@@ -0,0 +1,21 @@
+/*
+ * Intel general target stuff that's common to all i386 details
+ *
+ * Copyright (c) 2022 M. Warner Losh <imp@bsdimp.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef TARGET_H
+#define TARGET_H
+
+/*
+ * arm EABI 'lumps' the registers for 64-bit args.
+ */
+static inline bool regpairs_aligned(void *cpu_env)
+{
+ return true;
+}
+
+#endif /* ! TARGET_H */
+
diff --git a/bsd-user/arm/target_arch_cpu.h b/bsd-user/arm/target_arch_cpu.h
index b087db48fa..afb7814a8d 100644
--- a/bsd-user/arm/target_arch_cpu.h
+++ b/bsd-user/arm/target_arch_cpu.h
@@ -40,7 +40,6 @@ static inline void target_cpu_init(CPUARMState *env,
static inline void target_cpu_loop(CPUARMState *env)
{
int trapnr, si_signo, si_code;
- unsigned int n;
CPUState *cs = env_cpu(env);
for (;;) {
@@ -66,82 +65,76 @@ static inline void target_cpu_loop(CPUARMState *env)
break;
case EXCP_SWI:
{
- n = env->regs[7];
- if (bsd_type == target_freebsd) {
- int ret;
- abi_ulong params = get_sp_from_cpustate(env);
- int32_t syscall_nr = n;
- int32_t arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
+ int ret;
+ abi_ulong params = get_sp_from_cpustate(env);
+ int32_t syscall_nr = env->regs[7];
+ int32_t arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
- /* See arm/arm/syscall.c cpu_fetch_syscall_args() */
- if (syscall_nr == TARGET_FREEBSD_NR_syscall) {
- syscall_nr = env->regs[0];
- arg1 = env->regs[1];
- arg2 = env->regs[2];
- arg3 = env->regs[3];
- get_user_s32(arg4, params);
- params += sizeof(int32_t);
- get_user_s32(arg5, params);
- params += sizeof(int32_t);
- get_user_s32(arg6, params);
- params += sizeof(int32_t);
- get_user_s32(arg7, params);
- arg8 = 0;
- } else if (syscall_nr == TARGET_FREEBSD_NR___syscall) {
- syscall_nr = env->regs[0];
- arg1 = env->regs[2];
- arg2 = env->regs[3];
- get_user_s32(arg3, params);
- params += sizeof(int32_t);
- get_user_s32(arg4, params);
- params += sizeof(int32_t);
- get_user_s32(arg5, params);
- params += sizeof(int32_t);
- get_user_s32(arg6, params);
- arg7 = 0;
- arg8 = 0;
- } else {
- arg1 = env->regs[0];
- arg2 = env->regs[1];
- arg3 = env->regs[2];
- arg4 = env->regs[3];
- get_user_s32(arg5, params);
- params += sizeof(int32_t);
- get_user_s32(arg6, params);
- params += sizeof(int32_t);
- get_user_s32(arg7, params);
- params += sizeof(int32_t);
- get_user_s32(arg8, params);
- }
- ret = do_freebsd_syscall(env, syscall_nr, arg1, arg2, arg3,
- arg4, arg5, arg6, arg7, arg8);
+ /* See arm/arm/syscall.c cpu_fetch_syscall_args() */
+ if (syscall_nr == TARGET_FREEBSD_NR_syscall) {
+ syscall_nr = env->regs[0];
+ arg1 = env->regs[1];
+ arg2 = env->regs[2];
+ arg3 = env->regs[3];
+ get_user_s32(arg4, params);
+ params += sizeof(int32_t);
+ get_user_s32(arg5, params);
+ params += sizeof(int32_t);
+ get_user_s32(arg6, params);
+ params += sizeof(int32_t);
+ get_user_s32(arg7, params);
+ arg8 = 0;
+ } else if (syscall_nr == TARGET_FREEBSD_NR___syscall) {
+ syscall_nr = env->regs[0];
+ arg1 = env->regs[2];
+ arg2 = env->regs[3];
+ get_user_s32(arg3, params);
+ params += sizeof(int32_t);
+ get_user_s32(arg4, params);
+ params += sizeof(int32_t);
+ get_user_s32(arg5, params);
+ params += sizeof(int32_t);
+ get_user_s32(arg6, params);
+ arg7 = 0;
+ arg8 = 0;
+ } else {
+ arg1 = env->regs[0];
+ arg2 = env->regs[1];
+ arg3 = env->regs[2];
+ arg4 = env->regs[3];
+ get_user_s32(arg5, params);
+ params += sizeof(int32_t);
+ get_user_s32(arg6, params);
+ params += sizeof(int32_t);
+ get_user_s32(arg7, params);
+ params += sizeof(int32_t);
+ get_user_s32(arg8, params);
+ }
+ ret = do_freebsd_syscall(env, syscall_nr, arg1, arg2, arg3,
+ arg4, arg5, arg6, arg7, arg8);
+ /*
+ * Compare to arm/arm/vm_machdep.c
+ * cpu_set_syscall_retval()
+ */
+ if (-TARGET_EJUSTRETURN == ret) {
/*
- * Compare to arm/arm/vm_machdep.c
- * cpu_set_syscall_retval()
+ * Returning from a successful sigreturn syscall.
+ * Avoid clobbering register state.
*/
- if (-TARGET_EJUSTRETURN == ret) {
- /*
- * Returning from a successful sigreturn syscall.
- * Avoid clobbering register state.
- */
- break;
- }
- if (-TARGET_ERESTART == ret) {
- env->regs[15] -= env->thumb ? 2 : 4;
- break;
- }
- if ((unsigned int)ret >= (unsigned int)(-515)) {
- ret = -ret;
- cpsr_write(env, CPSR_C, CPSR_C, CPSRWriteByInstr);
- env->regs[0] = ret;
- } else {
- cpsr_write(env, 0, CPSR_C, CPSRWriteByInstr);
- env->regs[0] = ret; /* XXX need to handle lseek()? */
- /* env->regs[1] = 0; */
- }
+ break;
+ }
+ if (-TARGET_ERESTART == ret) {
+ env->regs[15] -= env->thumb ? 2 : 4;
+ break;
+ }
+ if ((unsigned int)ret >= (unsigned int)(-515)) {
+ ret = -ret;
+ cpsr_write(env, CPSR_C, CPSR_C, CPSRWriteByInstr);
+ env->regs[0] = ret;
} else {
- fprintf(stderr, "qemu: bsd_type (= %d) syscall "
- "not supported\n", bsd_type);
+ cpsr_write(env, 0, CPSR_C, CPSRWriteByInstr);
+ env->regs[0] = ret; /* XXX need to handle lseek()? */
+ /* env->regs[1] = 0; */
}
}
break;
diff --git a/bsd-user/arm/target_arch_thread.h b/bsd-user/arm/target_arch_thread.h
index 11c7f76583..fcafca2408 100644
--- a/bsd-user/arm/target_arch_thread.h
+++ b/bsd-user/arm/target_arch_thread.h
@@ -62,9 +62,7 @@ static inline void target_thread_init(struct target_pt_regs *regs,
}
regs->ARM_pc = infop->entry & 0xfffffffe;
regs->ARM_sp = stack;
- if (bsd_type == target_freebsd) {
- regs->ARM_lr = infop->entry & 0xfffffffe;
- }
+ regs->ARM_lr = infop->entry & 0xfffffffe;
/*
* FreeBSD kernel passes the ps_strings pointer in r0. This is used by some
* programs to set status messages that we see in ps. bsd-user doesn't
diff --git a/bsd-user/bsd-file.h b/bsd-user/bsd-file.h
new file mode 100644
index 0000000000..f0c3f347ec
--- /dev/null
+++ b/bsd-user/bsd-file.h
@@ -0,0 +1,30 @@
+/*
+ * file related system call shims and definitions
+ *
+ * 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 BSD_FILE_H_
+#define BSD_FILE_H_
+
+#include "qemu/path.h"
+
+extern struct iovec *lock_iovec(int type, abi_ulong target_addr, int count,
+ int copy);
+extern void unlock_iovec(struct iovec *vec, abi_ulong target_addr, int count,
+ int copy);
+
+#endif /* !BSD_FILE_H_ */
diff --git a/bsd-user/freebsd/meson.build b/bsd-user/freebsd/meson.build
index 4b69cca7b9..f87c788e84 100644
--- a/bsd-user/freebsd/meson.build
+++ b/bsd-user/freebsd/meson.build
@@ -1,3 +1,4 @@
bsd_user_ss.add(files(
'os-sys.c',
+ 'os-syscall.c',
))
diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c
new file mode 100644
index 0000000000..a17ff9f6ec
--- /dev/null
+++ b/bsd-user/freebsd/os-syscall.c
@@ -0,0 +1,92 @@
+/*
+ * BSD syscalls
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ * Copyright (c) 2013-2014 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/>.
+ */
+
+/*
+ * We need the FreeBSD "legacy" definitions. Rust needs the FreeBSD 11 system
+ * calls since it doesn't use libc at all, so we have to emulate that despite
+ * FreeBSD 11 being EOL'd.
+ */
+#define _WANT_FREEBSD11_STAT
+#define _WANT_FREEBSD11_STATFS
+#define _WANT_FREEBSD11_DIRENT
+#define _WANT_KERNEL_ERRNO
+#define _WANT_SEMUN
+#include "qemu/osdep.h"
+#include "qemu/cutils.h"
+#include "qemu/path.h"
+#include <sys/syscall.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <utime.h>
+
+#include "qemu.h"
+#include "qemu-common.h"
+#include "signal-common.h"
+#include "user/syscall-trace.h"
+
+#include "bsd-file.h"
+
+void target_set_brk(abi_ulong new_brk)
+{
+}
+
+/*
+ * errno conversion.
+ */
+abi_long get_errno(abi_long ret)
+{
+ if (ret == -1) {
+ return -host_to_target_errno(errno);
+ } else {
+ return ret;
+ }
+}
+
+int host_to_target_errno(int err)
+{
+ /*
+ * All the BSDs have the property that the error numbers are uniform across
+ * all architectures for a given BSD, though they may vary between different
+ * BSDs.
+ */
+ return err;
+}
+
+bool is_error(abi_long ret)
+{
+ return (abi_ulong)ret >= (abi_ulong)(-4096);
+}
+
+/*
+ * do_syscall() should always have a single exit point at the end so that
+ * actions, such as logging of syscall results, can be performed. All errnos
+ * that do_syscall() returns must be -TARGET_<errcode>.
+ */
+abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
+ abi_long arg2, abi_long arg3, abi_long arg4,
+ abi_long arg5, abi_long arg6, abi_long arg7,
+ abi_long arg8)
+{
+ return 0;
+}
+
+void syscall_init(void)
+{
+}
diff --git a/bsd-user/i386/target.h b/bsd-user/i386/target.h
new file mode 100644
index 0000000000..9b9df047a3
--- /dev/null
+++ b/bsd-user/i386/target.h
@@ -0,0 +1,21 @@
+/*
+ * Intel general target stuff that's common to all i386 details
+ *
+ * Copyright (c) 2022 M. Warner Losh <imp@bsdimp.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef TARGET_ARCH_H
+#define TARGET_ARCH_H
+
+/*
+ * i386 doesn't 'lump' the registers for 64-bit args.
+ */
+static inline bool regpairs_aligned(void *cpu_env)
+{
+ return false;
+}
+
+#endif /* ! TARGET_ARCH_H */
+
diff --git a/bsd-user/i386/target_arch_cpu.h b/bsd-user/i386/target_arch_cpu.h
index 3cbf69d8af..9da22202d4 100644
--- a/bsd-user/i386/target_arch_cpu.h
+++ b/bsd-user/i386/target_arch_cpu.h
@@ -116,55 +116,45 @@ static inline void target_cpu_loop(CPUX86State *env)
process_queued_cpu_work(cs);
switch (trapnr) {
- case 0x80:
+ case 0x80: {
/* syscall from int $0x80 */
- if (bsd_type == target_freebsd) {
- abi_ulong params = (abi_ulong) env->regs[R_ESP] +
- sizeof(int32_t);
- int32_t syscall_nr = env->regs[R_EAX];
- int32_t arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
-
- if (syscall_nr == TARGET_FREEBSD_NR_syscall) {
- get_user_s32(syscall_nr, params);
- params += sizeof(int32_t);
- } else if (syscall_nr == TARGET_FREEBSD_NR___syscall) {
- get_user_s32(syscall_nr, params);
- params += sizeof(int64_t);
- }
- get_user_s32(arg1, params);
- params += sizeof(int32_t);
- get_user_s32(arg2, params);
- params += sizeof(int32_t);
- get_user_s32(arg3, params);
- params += sizeof(int32_t);
- get_user_s32(arg4, params);
- params += sizeof(int32_t);
- get_user_s32(arg5, params);
- params += sizeof(int32_t);
- get_user_s32(arg6, params);
- params += sizeof(int32_t);
- get_user_s32(arg7, params);
+ abi_ulong params = (abi_ulong) env->regs[R_ESP] +
+ sizeof(int32_t);
+ int32_t syscall_nr = env->regs[R_EAX];
+ int32_t arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
+
+ if (syscall_nr == TARGET_FREEBSD_NR_syscall) {
+ get_user_s32(syscall_nr, params);
params += sizeof(int32_t);
- get_user_s32(arg8, params);
- env->regs[R_EAX] = do_freebsd_syscall(env,
- syscall_nr,
- arg1,
- arg2,
- arg3,
- arg4,
- arg5,
- arg6,
- arg7,
- arg8);
- } else { /* if (bsd_type == target_openbsd) */
- env->regs[R_EAX] = do_openbsd_syscall(env,
- env->regs[R_EAX],
- env->regs[R_EBX],
- env->regs[R_ECX],
- env->regs[R_EDX],
- env->regs[R_ESI],
- env->regs[R_EDI],
- env->regs[R_EBP]);
+ } else if (syscall_nr == TARGET_FREEBSD_NR___syscall) {
+ get_user_s32(syscall_nr, params);
+ params += sizeof(int64_t);
+ }
+ get_user_s32(arg1, params);
+ params += sizeof(int32_t);
+ get_user_s32(arg2, params);
+ params += sizeof(int32_t);
+ get_user_s32(arg3, params);
+ params += sizeof(int32_t);
+ get_user_s32(arg4, params);
+ params += sizeof(int32_t);
+ get_user_s32(arg5, params);
+ params += sizeof(int32_t);
+ get_user_s32(arg6, params);
+ params += sizeof(int32_t);
+ get_user_s32(arg7, params);
+ params += sizeof(int32_t);
+ get_user_s32(arg8, params);
+ env->regs[R_EAX] = do_freebsd_syscall(env,
+ syscall_nr,
+ arg1,
+ arg2,
+ arg3,
+ arg4,
+ arg5,
+ arg6,
+ arg7,
+ arg8);
}
if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
env->regs[R_EAX] = -env->regs[R_EAX];
diff --git a/bsd-user/main.c b/bsd-user/main.c
index f1d58e905e..88d347d05e 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -96,7 +96,6 @@ unsigned long reserved_va;
static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
const char *qemu_uname_release;
-enum BSDType bsd_type;
char qemu_proc_pathname[PATH_MAX]; /* full path to exeutable */
unsigned long target_maxtsiz = TARGET_MAXTSIZ; /* max text size */
@@ -164,7 +163,6 @@ static void usage(void)
"-E var=value sets/modifies targets environment variable(s)\n"
"-U var unsets targets environment variable(s)\n"
"-B address set guest_base address to address\n"
- "-bsd type select emulated BSD type FreeBSD/NetBSD/OpenBSD (default)\n"
"\n"
"Debug options:\n"
"-d item1[,...] enable logging of specified items\n"
@@ -285,7 +283,6 @@ int main(int argc, char **argv)
const char *gdbstub = NULL;
char **target_environ, **wrk;
envlist_t *envlist = NULL;
- bsd_type = HOST_DEFAULT_BSD_TYPE;
char *argv0 = NULL;
adjust_ssize();
@@ -392,17 +389,6 @@ int main(int argc, char **argv)
have_guest_base = true;
} else if (!strcmp(r, "drop-ld-preload")) {
(void) envlist_unsetenv(envlist, "LD_PRELOAD");
- } else if (!strcmp(r, "bsd")) {
- if (!strcasecmp(argv[optind], "freebsd")) {
- bsd_type = target_freebsd;
- } else if (!strcasecmp(argv[optind], "netbsd")) {
- bsd_type = target_netbsd;
- } else if (!strcasecmp(argv[optind], "openbsd")) {
- bsd_type = target_openbsd;
- } else {
- usage();
- }
- optind++;
} else if (!strcmp(r, "seed")) {
seed_optarg = optarg;
} else if (!strcmp(r, "singlestep")) {
diff --git a/bsd-user/meson.build b/bsd-user/meson.build
index 8380fa44c2..5243122fc5 100644
--- a/bsd-user/meson.build
+++ b/bsd-user/meson.build
@@ -13,7 +13,6 @@ bsd_user_ss.add(files(
'mmap.c',
'signal.c',
'strace.c',
- 'syscall.c',
'uaccess.c',
))
diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
index 02921ac8b3..af272c2a80 100644
--- a/bsd-user/qemu.h
+++ b/bsd-user/qemu.h
@@ -29,19 +29,13 @@
extern char **environ;
-enum BSDType {
- target_freebsd,
- target_netbsd,
- target_openbsd,
-};
-extern enum BSDType bsd_type;
-
#include "exec/user/thunk.h"
#include "target_arch.h"
#include "syscall_defs.h"
#include "target_syscall.h"
#include "target_os_vmparam.h"
#include "target_os_signal.h"
+#include "target.h"
#include "exec/gdbstub.h"
/*
@@ -253,9 +247,10 @@ extern unsigned long target_dflssiz;
extern unsigned long target_maxssiz;
extern unsigned long target_sgrowsiz;
-/* syscall.c */
+/* os-syscall.c */
abi_long get_errno(abi_long ret);
bool is_error(abi_long ret);
+int host_to_target_errno(int err);
/* os-sys.c */
abi_long do_freebsd_sysarch(void *cpu_env, abi_long arg1, abi_long arg2);
@@ -467,6 +462,19 @@ static inline void *lock_user_string(abi_ulong guest_addr)
#define unlock_user_struct(host_ptr, guest_addr, copy) \
unlock_user(host_ptr, guest_addr, (copy) ? sizeof(*host_ptr) : 0)
+static inline uint64_t target_arg64(uint32_t word0, uint32_t word1)
+{
+#if TARGET_ABI_BITS == 32
+#ifdef TARGET_WORDS_BIGENDIAN
+ return ((uint64_t)word0 << 32) | word1;
+#else
+ return ((uint64_t)word1 << 32) | word0;
+#endif
+#else /* TARGET_ABI_BITS != 32 */
+ return word0;
+#endif /* TARGET_ABI_BITS != 32 */
+}
+
#include <pthread.h>
#include "user/safe-syscall.h"
diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
deleted file mode 100644
index d3322760f4..0000000000
--- a/bsd-user/syscall.c
+++ /dev/null
@@ -1,516 +0,0 @@
-/*
- * BSD syscalls
- *
- * Copyright (c) 2003 - 2008 Fabrice Bellard
- *
- * 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 "qemu/osdep.h"
-#include "qemu/cutils.h"
-#include "qemu/path.h"
-#include <sys/syscall.h>
-#include <sys/param.h>
-#include <sys/sysctl.h>
-#include <utime.h>
-
-#include "qemu.h"
-#include "qemu-common.h"
-#include "user/syscall-trace.h"
-
-//#define DEBUG
-
-static abi_ulong target_brk;
-static abi_ulong target_original_brk;
-
-abi_long get_errno(abi_long ret)
-{
- if (ret == -1) {
- /* XXX need to translate host -> target errnos here */
- return -(errno);
- }
- return ret;
-}
-
-#define target_to_host_bitmask(x, tbl) (x)
-
-bool is_error(abi_long ret)
-{
- return (abi_ulong)ret >= (abi_ulong)(-4096);
-}
-
-void target_set_brk(abi_ulong new_brk)
-{
- target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
-}
-
-/* do_obreak() must return target errnos. */
-static abi_long do_obreak(abi_ulong new_brk)
-{
- abi_ulong brk_page;
- abi_long mapped_addr;
- int new_alloc_size;
-
- if (!new_brk)
- return 0;
- if (new_brk < target_original_brk)
- return -TARGET_EINVAL;
-
- brk_page = HOST_PAGE_ALIGN(target_brk);
-
- /* If the new brk is less than this, set it and we're done... */
- if (new_brk < brk_page) {
- target_brk = new_brk;
- return 0;
- }
-
- /* We need to allocate more memory after the brk... */
- new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
- mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
- PROT_READ|PROT_WRITE,
- MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0));
-
- if (!is_error(mapped_addr))
- target_brk = new_brk;
- else
- return mapped_addr;
-
- return 0;
-}
-
-#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);
- break;
- 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.
- */
-static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
- int count, int copy)
-{
- struct target_iovec *target_vec;
- abi_ulong base;
- int i;
-
- target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
- if (!target_vec)
- return -TARGET_EFAULT;
- for (i = 0;i < count; i++) {
- base = tswapl(target_vec[i].iov_base);
- vec[i].iov_len = tswapl(target_vec[i].iov_len);
- if (vec[i].iov_len != 0) {
- vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
- /* Don't check lock_user return value. We must call writev even
- if a element has invalid base address. */
- } else {
- /* zero length pointer is ignored */
- vec[i].iov_base = NULL;
- }
- }
- unlock_user (target_vec, target_addr, 0);
- return 0;
-}
-
-static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
- int count, int copy)
-{
- struct target_iovec *target_vec;
- abi_ulong base;
- int i;
-
- target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
- if (!target_vec)
- return -TARGET_EFAULT;
- for (i = 0;i < count; i++) {
- if (target_vec[i].iov_base) {
- base = tswapl(target_vec[i].iov_base);
- unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
- }
- }
- unlock_user (target_vec, target_addr, 0);
-
- return 0;
-}
-
-/* do_syscall() should always have a single exit point at the end so
- that actions, such as logging of syscall results, can be performed.
- All errnos that do_syscall() returns must be -TARGET_<errcode>. */
-abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
- abi_long arg2, abi_long arg3, abi_long arg4,
- abi_long arg5, abi_long arg6, abi_long arg7,
- abi_long arg8)
-{
- CPUState *cpu = env_cpu(cpu_env);
- abi_long ret;
- void *p;
-
-#ifdef DEBUG
- gemu_log("freebsd syscall %d\n", num);
-#endif
- record_syscall_start(cpu, num, arg1, arg2, arg3, arg4, arg5, arg6, 0, 0);
-
- if (do_strace)
- print_freebsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
-
- switch (num) {
- case TARGET_FREEBSD_NR_exit:
-#ifdef CONFIG_GPROF
- _mcleanup();
-#endif
- gdb_exit(arg1);
- qemu_plugin_user_exit();
- /* XXX: should free thread stack and CPU env */
- _exit(arg1);
- ret = 0; /* avoid warning */
- break;
- case TARGET_FREEBSD_NR_read:
- if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
- goto efault;
- ret = get_errno(read(arg1, p, arg3));
- unlock_user(p, arg2, ret);
- break;
- case TARGET_FREEBSD_NR_write:
- if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
- goto efault;
- ret = get_errno(write(arg1, p, arg3));
- unlock_user(p, arg2, 0);
- break;
- case TARGET_FREEBSD_NR_writev:
- {
- int count = arg3;
- struct iovec *vec;
-
- vec = alloca(count * sizeof(struct iovec));
- if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
- goto efault;
- ret = get_errno(writev(arg1, vec, count));
- unlock_iovec(vec, arg2, count, 0);
- }
- break;
- case TARGET_FREEBSD_NR_open:
- if (!(p = lock_user_string(arg1)))
- goto efault;
- ret = get_errno(open(path(p),
- target_to_host_bitmask(arg2, fcntl_flags_tbl),
- arg3));
- unlock_user(p, arg1, 0);
- break;
- case TARGET_FREEBSD_NR_mmap:
- ret = get_errno(target_mmap(arg1, arg2, arg3,
- target_to_host_bitmask(arg4, mmap_flags_tbl),
- arg5,
- arg6));
- break;
- case TARGET_FREEBSD_NR_mprotect:
- ret = get_errno(target_mprotect(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);
- break;
-#endif
- case TARGET_FREEBSD_NR_sysarch:
- 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);
- break;
- default:
- ret = get_errno(syscall(num, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8));
- break;
- }
- fail:
-#ifdef DEBUG
- gemu_log(" = %ld\n", ret);
-#endif
- if (do_strace)
- print_freebsd_syscall_ret(num, ret);
-
- record_syscall_return(cpu, num, ret);
- return ret;
- efault:
- ret = -TARGET_EFAULT;
- goto fail;
-}
-
-abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long arg1,
- abi_long arg2, abi_long arg3, abi_long arg4,
- abi_long arg5, abi_long arg6)
-{
- CPUState *cpu = env_cpu(cpu_env);
- abi_long ret;
- void *p;
-
-#ifdef DEBUG
- gemu_log("netbsd syscall %d\n", num);
-#endif
-
- record_syscall_start(cpu, num, arg1, arg2, arg3, arg4, arg5, arg6, 0, 0);
-
- if (do_strace)
- print_netbsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
-
- switch (num) {
- case TARGET_NETBSD_NR_exit:
-#ifdef CONFIG_GPROF
- _mcleanup();
-#endif
- gdb_exit(arg1);
- qemu_plugin_user_exit();
- /* XXX: should free thread stack and CPU env */
- _exit(arg1);
- ret = 0; /* avoid warning */
- break;
- case TARGET_NETBSD_NR_read:
- if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
- goto efault;
- ret = get_errno(read(arg1, p, arg3));
- unlock_user(p, arg2, ret);
- break;
- case TARGET_NETBSD_NR_write:
- if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
- goto efault;
- ret = get_errno(write(arg1, p, arg3));
- unlock_user(p, arg2, 0);
- break;
- case TARGET_NETBSD_NR_open:
- if (!(p = lock_user_string(arg1)))
- goto efault;
- ret = get_errno(open(path(p),
- target_to_host_bitmask(arg2, fcntl_flags_tbl),
- arg3));
- unlock_user(p, arg1, 0);
- break;
- case TARGET_NETBSD_NR_mmap:
- ret = get_errno(target_mmap(arg1, arg2, arg3,
- target_to_host_bitmask(arg4, mmap_flags_tbl),
- arg5,
- arg6));
- break;
- case TARGET_NETBSD_NR_mprotect:
- ret = get_errno(target_mprotect(arg1, arg2, arg3));
- break;
- case TARGET_NETBSD_NR_syscall:
- case TARGET_NETBSD_NR___syscall:
- ret = do_netbsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
- break;
- default:
- ret = syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
- break;
- }
- fail:
-#ifdef DEBUG
- gemu_log(" = %ld\n", ret);
-#endif
- if (do_strace)
- print_netbsd_syscall_ret(num, ret);
-
- record_syscall_return(cpu, num, ret);
- return ret;
- efault:
- ret = -TARGET_EFAULT;
- goto fail;
-}
-
-abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1,
- abi_long arg2, abi_long arg3, abi_long arg4,
- abi_long arg5, abi_long arg6)
-{
- CPUState *cpu = env_cpu(cpu_env);
- abi_long ret;
- void *p;
-
-#ifdef DEBUG
- gemu_log("openbsd syscall %d\n", num);
-#endif
-
- record_syscall_start(cpu, num, arg1, arg2, arg3, arg4, arg5, arg6, 0, 0);
-
- if (do_strace)
- print_openbsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
-
- switch (num) {
- case TARGET_OPENBSD_NR_exit:
-#ifdef CONFIG_GPROF
- _mcleanup();
-#endif
- gdb_exit(arg1);
- qemu_plugin_user_exit();
- /* XXX: should free thread stack and CPU env */
- _exit(arg1);
- ret = 0; /* avoid warning */
- break;
- case TARGET_OPENBSD_NR_read:
- if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
- goto efault;
- ret = get_errno(read(arg1, p, arg3));
- unlock_user(p, arg2, ret);
- break;
- case TARGET_OPENBSD_NR_write:
- if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
- goto efault;
- ret = get_errno(write(arg1, p, arg3));
- unlock_user(p, arg2, 0);
- break;
- case TARGET_OPENBSD_NR_open:
- if (!(p = lock_user_string(arg1)))
- goto efault;
- ret = get_errno(open(path(p),
- target_to_host_bitmask(arg2, fcntl_flags_tbl),
- arg3));
- unlock_user(p, arg1, 0);
- break;
- case TARGET_OPENBSD_NR_mmap:
- ret = get_errno(target_mmap(arg1, arg2, arg3,
- target_to_host_bitmask(arg4, mmap_flags_tbl),
- arg5,
- arg6));
- break;
- case TARGET_OPENBSD_NR_mprotect:
- ret = get_errno(target_mprotect(arg1, arg2, arg3));
- break;
- case TARGET_OPENBSD_NR_syscall:
- case TARGET_OPENBSD_NR___syscall:
- ret = do_openbsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
- break;
- default:
- ret = syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
- break;
- }
- fail:
-#ifdef DEBUG
- gemu_log(" = %ld\n", ret);
-#endif
- if (do_strace)
- print_openbsd_syscall_ret(num, ret);
-
- record_syscall_return(cpu, num, ret);
- return ret;
- efault:
- ret = -TARGET_EFAULT;
- goto fail;
-}
-
-void syscall_init(void)
-{
-}
diff --git a/bsd-user/syscall_defs.h b/bsd-user/syscall_defs.h
index 62b472b990..c3bf14f38f 100644
--- a/bsd-user/syscall_defs.h
+++ b/bsd-user/syscall_defs.h
@@ -179,4 +179,51 @@ struct target_freebsd__wrusage {
struct target_freebsd_rusage wru_children;
};
+#define safe_syscall0(type, name) \
+type safe_##name(void) \
+{ \
+ return safe_syscall(SYS_##name); \
+}
+
+#define safe_syscall1(type, name, type1, arg1) \
+type safe_##name(type1 arg1) \
+{ \
+ return safe_syscall(SYS_##name, arg1); \
+}
+
+#define safe_syscall2(type, name, type1, arg1, type2, arg2) \
+type safe_##name(type1 arg1, type2 arg2) \
+{ \
+ return safe_syscall(SYS_##name, arg1, arg2); \
+}
+
+#define safe_syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
+type safe_##name(type1 arg1, type2 arg2, type3 arg3) \
+{ \
+ return safe_syscall(SYS_##name, arg1, arg2, arg3); \
+}
+
+#define safe_syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4) \
+type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
+{ \
+ return safe_syscall(SYS_##name, arg1, arg2, arg3, arg4); \
+}
+
+#define safe_syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4, type5, arg5) \
+type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
+ type5 arg5) \
+{ \
+ return safe_syscall(SYS_##name, arg1, arg2, arg3, arg4, arg5); \
+}
+
+#define safe_syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4, type5, arg5, type6, arg6) \
+type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
+ type5 arg5, type6 arg6) \
+{ \
+ return safe_syscall(SYS_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
+}
+
#endif /* ! _SYSCALL_DEFS_H_ */
diff --git a/bsd-user/x86_64/target.h b/bsd-user/x86_64/target.h
new file mode 100644
index 0000000000..8956631db1
--- /dev/null
+++ b/bsd-user/x86_64/target.h
@@ -0,0 +1,21 @@
+/*
+ * Intel general target stuff that's common to all x86_64 details
+ *
+ * Copyright (c) 2022 M. Warner Losh <imp@bsdimp.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef TARGET_H
+#define TARGET_H
+
+/*
+ * x86 doesn't 'lump' the registers for 64-bit args, all args are 64 bits.
+ */
+static inline bool regpairs_aligned(void *cpu_env)
+{
+ return false;
+}
+
+#endif /* ! TARGET_H */
+
diff --git a/bsd-user/x86_64/target_arch_cpu.h b/bsd-user/x86_64/target_arch_cpu.h
index 0a9c0f0894..5be2f02416 100644
--- a/bsd-user/x86_64/target_arch_cpu.h
+++ b/bsd-user/x86_64/target_arch_cpu.h
@@ -124,85 +124,16 @@ static inline void target_cpu_loop(CPUX86State *env)
process_queued_cpu_work(cs);
switch (trapnr) {
- case 0x80:
- /* syscall from int $0x80 */
- if (bsd_type == target_freebsd) {
- abi_ulong params = (abi_ulong) env->regs[R_ESP] +
- sizeof(int32_t);
- int32_t syscall_nr = env->regs[R_EAX];
- int32_t arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
-
- if (syscall_nr == TARGET_FREEBSD_NR_syscall) {
- get_user_s32(syscall_nr, params);
- params += sizeof(int32_t);
- } else if (syscall_nr == TARGET_FREEBSD_NR___syscall) {
- get_user_s32(syscall_nr, params);
- params += sizeof(int64_t);
- }
- get_user_s32(arg1, params);
- params += sizeof(int32_t);
- get_user_s32(arg2, params);
- params += sizeof(int32_t);
- get_user_s32(arg3, params);
- params += sizeof(int32_t);
- get_user_s32(arg4, params);
- params += sizeof(int32_t);
- get_user_s32(arg5, params);
- params += sizeof(int32_t);
- get_user_s32(arg6, params);
- params += sizeof(int32_t);
- get_user_s32(arg7, params);
- params += sizeof(int32_t);
- get_user_s32(arg8, params);
- env->regs[R_EAX] = do_freebsd_syscall(env,
- syscall_nr,
- arg1,
- arg2,
- arg3,
- arg4,
- arg5,
- arg6,
- arg7,
- arg8);
- } else { /* if (bsd_type == target_openbsd) */
- env->regs[R_EAX] = do_openbsd_syscall(env,
- env->regs[R_EAX],
- env->regs[R_EBX],
- env->regs[R_ECX],
- env->regs[R_EDX],
- env->regs[R_ESI],
- env->regs[R_EDI],
- env->regs[R_EBP]);
- }
- if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
- env->regs[R_EAX] = -env->regs[R_EAX];
- env->eflags |= CC_C;
- } else {
- env->eflags &= ~CC_C;
- }
- break;
-
case EXCP_SYSCALL:
/* syscall from syscall instruction */
- if (bsd_type == target_freebsd) {
- env->regs[R_EAX] = do_freebsd_syscall(env,
- env->regs[R_EAX],
- env->regs[R_EDI],
- env->regs[R_ESI],
- env->regs[R_EDX],
- env->regs[R_ECX],
- env->regs[8],
- env->regs[9], 0, 0);
- } else { /* if (bsd_type == target_openbsd) */
- env->regs[R_EAX] = do_openbsd_syscall(env,
- env->regs[R_EAX],
- env->regs[R_EDI],
- env->regs[R_ESI],
- env->regs[R_EDX],
- env->regs[10],
- env->regs[8],
- env->regs[9]);
- }
+ env->regs[R_EAX] = do_freebsd_syscall(env,
+ env->regs[R_EAX],
+ env->regs[R_EDI],
+ env->regs[R_ESI],
+ env->regs[R_EDX],
+ env->regs[R_ECX],
+ env->regs[8],
+ env->regs[9], 0, 0);
env->eip = env->exception_next_eip;
if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
env->regs[R_EAX] = -env->regs[R_EAX];
diff --git a/bsd-user/x86_64/target_arch_thread.h b/bsd-user/x86_64/target_arch_thread.h
index d105e43fd3..b745d7ffeb 100644
--- a/bsd-user/x86_64/target_arch_thread.h
+++ b/bsd-user/x86_64/target_arch_thread.h
@@ -32,9 +32,7 @@ static inline void target_thread_init(struct target_pt_regs *regs,
regs->rax = 0;
regs->rsp = infop->start_stack;
regs->rip = infop->entry;
- if (bsd_type == target_freebsd) {
- regs->rdi = infop->start_stack;
- }
+ regs->rdi = infop->start_stack;
}
#endif /* !_TARGET_ARCH_THREAD_H_ */