aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bsd-user/errno_defs.h13
-rw-r--r--bsd-user/freebsd/meson.build3
-rw-r--r--bsd-user/freebsd/os-sys.c27
-rw-r--r--bsd-user/freebsd/strace.list11
-rw-r--r--bsd-user/freebsd/target_os_elf.h12
-rw-r--r--bsd-user/freebsd/target_os_signal.h3
-rw-r--r--bsd-user/freebsd/target_os_user.h100
-rw-r--r--bsd-user/i386/target_arch_cpu.h2
-rw-r--r--bsd-user/i386/target_arch_signal.h2
-rw-r--r--bsd-user/main.c10
-rw-r--r--bsd-user/meson.build7
-rw-r--r--bsd-user/mmap.c144
-rw-r--r--bsd-user/qemu.h25
-rw-r--r--bsd-user/signal.c11
-rw-r--r--bsd-user/syscall.c60
-rw-r--r--bsd-user/x86_64/target_arch_cpu.h2
-rw-r--r--bsd-user/x86_64/target_arch_signal.h2
-rw-r--r--linux-user/meson.build4
-rw-r--r--meson.build12
19 files changed, 187 insertions, 263 deletions
diff --git a/bsd-user/errno_defs.h b/bsd-user/errno_defs.h
index 1efa502a12..832671354f 100644
--- a/bsd-user/errno_defs.h
+++ b/bsd-user/errno_defs.h
@@ -1,6 +1,3 @@
-/* $OpenBSD: errno.h,v 1.20 2007/09/03 14:37:52 millert Exp $ */
-/* $NetBSD: errno.h,v 1.10 1996/01/20 01:33:53 jtc Exp $ */
-
/*
* Copyright (c) 1982, 1986, 1989, 1993
* The Regents of the University of California. All rights reserved.
@@ -37,6 +34,9 @@
* @(#)errno.h 8.5 (Berkeley) 1/21/94
*/
+#ifndef _ERRNO_DEFS_H_
+#define _ERRNO_DEFS_H_
+
#define TARGET_EPERM 1 /* Operation not permitted */
#define TARGET_ENOENT 2 /* No such file or directory */
#define TARGET_ESRCH 3 /* No such process */
@@ -147,3 +147,10 @@
#define TARGET_EIDRM 89 /* Identifier removed */
#define TARGET_ENOMSG 90 /* No message of desired type */
#define TARGET_ELAST 90 /* Must be equal largest errno */
+
+/* Internal errors: */
+#define TARGET_EJUSTRETURN 254 /* Just return without modifing regs */
+#define TARGET_ERESTART 255 /* Restart syscall */
+#define TARGET_ERESTARTSYS TARGET_ERESTART /* Linux compat */
+
+#endif /* ! _ERRNO_DEFS_H_ */
diff --git a/bsd-user/freebsd/meson.build b/bsd-user/freebsd/meson.build
new file mode 100644
index 0000000000..4b69cca7b9
--- /dev/null
+++ b/bsd-user/freebsd/meson.build
@@ -0,0 +1,3 @@
+bsd_user_ss.add(files(
+ 'os-sys.c',
+))
diff --git a/bsd-user/freebsd/os-sys.c b/bsd-user/freebsd/os-sys.c
new file mode 100644
index 0000000000..309e27b9d6
--- /dev/null
+++ b/bsd-user/freebsd/os-sys.c
@@ -0,0 +1,27 @@
+/*
+ * FreeBSD sysctl() and sysarch() system call emulation
+ *
+ * Copyright (c) 2013-15 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 "qemu.h"
+#include "target_arch_sysarch.h"
+
+/* 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/freebsd/strace.list b/bsd-user/freebsd/strace.list
index b01b5f36e8..275d2dbe27 100644
--- a/bsd-user/freebsd/strace.list
+++ b/bsd-user/freebsd/strace.list
@@ -33,10 +33,6 @@
{ TARGET_FREEBSD_NR___syscall, "__syscall", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR___sysctl, "__sysctl", NULL, print_sysctl, NULL },
{ TARGET_FREEBSD_NR__umtx_op, "_umtx_op", "%s(%#x, %d, %d, %#x, %#x)", NULL, NULL },
-#if defined(__FreeBSD_version) && __FreeBSD_version < 1000000
-{ TARGET_FREEBSD_NR__umtx_lock, "__umtx_lock", NULL, NULL, NULL },
-{ TARGET_FREEBSD_NR__umtx_unlock, "__umtx_unlock", NULL, NULL, NULL },
-#endif
{ TARGET_FREEBSD_NR_accept, "accept", "%s(%d,%#x,%#x)", NULL, NULL },
{ TARGET_FREEBSD_NR_accept4, "accept4", "%s(%d,%d,%#x,%#x)", NULL, NULL },
{ TARGET_FREEBSD_NR_access, "access", "%s(\"%s\",%#o)", NULL, NULL },
@@ -49,10 +45,6 @@
{ TARGET_FREEBSD_NR_cap_fcntls_get, "cap_fcntls_get", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_cap_fcntls_limit, "cap_fcntls_limit", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_cap_getmode, "cap_getmode", NULL, NULL, NULL },
-#if defined(__FreeBSD_version) && __FreeBSD_version < 1000000
-{ TARGET_FREEBSD_NR_cap_getrights, "cap_getrights", NULL, NULL, NULL },
-{ TARGET_FREEBSD_NR_cap_new, "cap_new", NULL, NULL, NULL },
-#endif
{ TARGET_FREEBSD_NR_cap_ioctls_get, "cap_ioctls_get", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_cap_ioctls_limit, "cap_ioctls_limit", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_cap_rights_limit, "cap_rights_limit", NULL, NULL, NULL },
@@ -146,9 +138,6 @@
{ TARGET_FREEBSD_NR_freebsd11_kevent, "freebsd11_kevent", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_kevent, "kevent", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_kill, "kill", NULL, NULL, NULL },
-#if defined(__FreeBSD_version) && __FreeBSD_version < 1000000
-{ TARGET_FREEBSD_NR_killpg, "killpg", NULL, NULL, NULL },
-#endif
{ TARGET_FREEBSD_NR_kqueue, "kqueue", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_ktrace, "ktrace", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_lchown, "lchown", NULL, NULL, NULL },
diff --git a/bsd-user/freebsd/target_os_elf.h b/bsd-user/freebsd/target_os_elf.h
index 2d03a883aa..e5ac8e8e50 100644
--- a/bsd-user/freebsd/target_os_elf.h
+++ b/bsd-user/freebsd/target_os_elf.h
@@ -38,10 +38,6 @@
#define ELF_PLATFORM (NULL)
#endif
-#ifndef ELF_HWCAP
-#define ELF_HWCAP 0
-#endif
-
/* XXX Look at the other conflicting AT_* values. */
#define FREEBSD_AT_NCPUS 19
#define FREEBSD_AT_HWCAP 25
@@ -114,12 +110,16 @@ static abi_ulong target_create_elf_tables(abi_ulong p, int argc, int envc,
NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
NEW_AUX_ENT(FREEBSD_AT_NCPUS, (abi_ulong)bsd_get_ncpu());
NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
+ features = ELF_HWCAP;
+ NEW_AUX_ENT(FREEBSD_AT_HWCAP, features);
+#ifdef ELF_HWCAP2
+ features = ELF_HWCAP2;
+ NEW_AUX_ENT(FREEBSD_AT_HWCAP2, features);
+#endif
NEW_AUX_ENT(AT_UID, (abi_ulong)getuid());
NEW_AUX_ENT(AT_EUID, (abi_ulong)geteuid());
NEW_AUX_ENT(AT_GID, (abi_ulong)getgid());
NEW_AUX_ENT(AT_EGID, (abi_ulong)getegid());
- features = ELF_HWCAP;
- NEW_AUX_ENT(FREEBSD_AT_HWCAP, features);
target_auxents = sp; /* Note where the aux entries are in the target */
#ifdef ARCH_DLINFO
/*
diff --git a/bsd-user/freebsd/target_os_signal.h b/bsd-user/freebsd/target_os_signal.h
index 3ed454e086..1a4c5faf19 100644
--- a/bsd-user/freebsd/target_os_signal.h
+++ b/bsd-user/freebsd/target_os_signal.h
@@ -1,6 +1,9 @@
#ifndef _TARGET_OS_SIGNAL_H_
#define _TARGET_OS_SIGNAL_H_
+/* FreeBSD's sys/ucontext.h defines this */
+#define TARGET_MC_GET_CLEAR_RET 0x0001
+
#include "target_os_siginfo.h"
#include "target_arch_signal.h"
diff --git a/bsd-user/freebsd/target_os_user.h b/bsd-user/freebsd/target_os_user.h
index 95b1fa9f99..19892c5071 100644
--- a/bsd-user/freebsd/target_os_user.h
+++ b/bsd-user/freebsd/target_os_user.h
@@ -61,15 +61,7 @@ struct target_sockaddr_storage {
/*
* from sys/user.h
*/
-#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
#define TARGET_KI_NSPARE_INT 2
-#elif defined(__FreeBSD_version) && __FreeBSD_version >= 1100000
-#define TARGET_KI_NSPARE_INT 4
-#elif defined(__FreeBSD_version) && __FreeBSD_version >= 1000000
-#define TARGET_KI_NSPARE_INT 7
-#else
-#define TARGET_KI_NSPARE_INT 9
-#endif /* ! __FreeBSD_version >= 1000000 */
#define TARGET_KI_NSPARE_LONG 12
#define TARGET_KI_NSPARE_PTR 6
@@ -116,11 +108,7 @@ struct target_kinfo_proc {
int32_t ki_tsid; /* Terminal session ID */
int16_t ki_jobc; /* job control counter */
int16_t ki_spare_short1; /* unused (just here for alignment) */
-#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
int32_t ki_tdev__freebsd11; /* controlling tty dev */
-#else
- int32_t ki_tdev; /* controlling tty dev */
-#endif
target_sigset_t ki_siglist; /* Signals arrived but not delivered */
target_sigset_t ki_sigmask; /* Current signal mask */
target_sigset_t ki_sigignore; /* Signals being ignored */
@@ -164,45 +152,24 @@ struct target_kinfo_proc {
int8_t ki_nice; /* Process "nice" value */
char ki_lock; /* Process lock (prevent swap) count */
char ki_rqindex; /* Run queue index */
-#if defined(__FreeBSD_version) && __FreeBSD_version >= 1100000
u_char ki_oncpu_old; /* Which cpu we are on (legacy) */
u_char ki_lastcpu_old; /* Last cpu we were on (legacy) */
-#else
- u_char ki_oncpu; /* Which cpu we are on */
- u_char ki_lastcpu; /* Last cpu we were on */
-#endif /* ! __FreeBSD_version >= 1100000 */
-#if defined(__FreeBSD_version) && __FreeBSD_version >= 900000
char ki_tdname[TARGET_TDNAMLEN + 1]; /* thread name */
-#else
- char ki_ocomm[TARGET_TDNAMLEN + 1]; /* thread name */
-#endif /* ! __FreeBSD_version >= 900000 */
char ki_wmesg[TARGET_WMESGLEN + 1]; /* wchan message */
char ki_login[TARGET_LOGNAMELEN + 1]; /* setlogin name */
char ki_lockname[TARGET_LOCKNAMELEN + 1]; /* lock name */
char ki_comm[TARGET_COMMLEN + 1]; /* command name */
char ki_emul[TARGET_KI_EMULNAMELEN + 1]; /* emulation name */
-#if defined(__FreeBSD_version) && __FreeBSD_version >= 900000
char ki_loginclass[TARGET_LOGINCLASSLEN + 1]; /* login class */
-#endif /* ! __FreeBSD_version >= 900000 */
-#if defined(__FreeBSD_version) && __FreeBSD_version >= 900000
char ki_sparestrings[50]; /* spare string space */
-#else
- char ki_sparestrings[68]; /* spare string space */
-#endif /* ! __FreeBSD_version >= 900000 */
int32_t ki_spareints[TARGET_KI_NSPARE_INT]; /* spare room for growth */
-#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
- uint64_t ki_tdev; /* controlling tty dev */
-#endif
-#if defined(__FreeBSD_version) && __FreeBSD_version >= 1100000
+ uint64_t ki_tdev; /* controlling tty dev */
int32_t ki_oncpu; /* Which cpu we are on */
int32_t ki_lastcpu; /* Last cpu we were on */
int32_t ki_tracer; /* Pid of tracing process */
-#endif /* __FreeBSD_version >= 1100000 */
-#if defined(__FreeBSD_version) && __FreeBSD_version >= 900000
int32_t ki_flag2; /* P2_* flags */
int32_t ki_fibnum; /* Default FIB number */
-#endif /* ! __FreeBSD_version >= 900000 */
uint32_t ki_cr_flags; /* Credential flags */
int32_t ki_jid; /* Process jail ID */
int32_t ki_numthreads; /* XXXKSE number of threads in total */
@@ -234,18 +201,8 @@ struct target_kinfo_file {
int32_t kf_flags; /* Flags. */
int32_t kf_pad0; /* Round to 64 bit alignment. */
int64_t kf_offset; /* Seek location. */
-#if defined(__FreeBSD_version) && __FreeBSD_version < 1200031
- int32_t kf_vnode_type; /* Vnode type. */
- int32_t kf_sock_domain; /* Socket domain. */
- int32_t kf_sock_type; /* Socket type. */
- int32_t kf_sock_protocol; /* Socket protocol. */
- struct target_sockaddr_storage kf_sa_local; /* Socket address. */
- struct target_sockaddr_storage kf_sa_peer; /* Peer address. */
-#endif
-#if defined(__FreeBSD_version) && __FreeBSD_version >= 900000
union {
struct {
-#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
uint32_t kf_spareint;
/* Socket domain. */
int kf_sock_domain0;
@@ -257,7 +214,6 @@ struct target_kinfo_file {
struct sockaddr_storage kf_sa_local;
/* Peer address. */
struct sockaddr_storage kf_sa_peer;
-#endif
/* Address of so_pcb. */
uint64_t kf_sock_pcb;
/* Address of inp_ppcb. */
@@ -272,7 +228,6 @@ struct target_kinfo_file {
uint32_t kf_sock_pad0;
} kf_sock;
struct {
-#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
/* Vnode type. */
int kf_file_type;
/* Space for future use */
@@ -290,16 +245,6 @@ struct target_kinfo_file {
uint32_t kf_file_fsid_freebsd11;
/* File device, FreeBSD 11 compat. */
uint32_t kf_file_rdev_freebsd11;
-#else
- /* Global file id. */
- uint64_t kf_file_fileid;
- /* File size. */
- uint64_t kf_file_size;
- /* Vnode filesystem id. */
- uint32_t kf_file_fsid;
- /* File device. */
- uint32_t kf_file_rdev;
-#endif
/* File mode. */
uint16_t kf_file_mode;
/* Round to 64 bit alignment. */
@@ -307,18 +252,14 @@ struct target_kinfo_file {
uint32_t kf_file_pad1;
} kf_file;
struct {
-#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
uint32_t kf_spareint[4];
uint64_t kf_spareint64[32];
-#endif
uint32_t kf_sem_value;
uint16_t kf_sem_mode;
} kf_sem;
struct {
-#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
uint32_t kf_spareint[4];
uint64_t kf_spareint64[32];
-#endif
uint64_t kf_pipe_addr;
uint64_t kf_pipe_peer;
uint32_t kf_pipe_buffer_cnt;
@@ -326,7 +267,6 @@ struct target_kinfo_file {
uint32_t kf_pipe_pad0[3];
} kf_pipe;
struct {
-#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
uint32_t kf_spareint[4];
uint64_t kf_spareint64[32];
uint32_t kf_pts_dev_freebsd11;
@@ -334,34 +274,18 @@ struct target_kinfo_file {
uint64_t kf_pts_dev;
/* Round to 64 bit alignment. */
uint32_t kf_pts_pad1[4];
-#else
- uint32_t kf_pts_dev;
- /* Round to 64 bit alignment. */
- uint32_t kf_pts_pad0[7];
-#endif
} kf_pts;
struct {
-#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
uint32_t kf_spareint[4];
uint64_t kf_spareint64[32];
-#endif
int32_t kf_pid;
} kf_proc;
} kf_un;
uint16_t kf_status; /* Status flags. */
uint16_t kf_pad1; /* Round to 32 bit alignment. */
int32_t _kf_ispare0; /* Space for more stuff. */
-#if defined(__FreeBSD_version) && __FreeBSD_version >= 1000000
target_cap_rights_t kf_cap_rights; /* Capability rights. */
uint64_t _kf_cap_spare; /* Space for future cap_rights_t. */
-#else /* ! __FreeBSD_version >= 1000000 */
- uint64_t kf_cap_rights;
- int _kf_ispare[4];
-#endif /* ! __FreeBSD_version >= 1000000 */
-
-#else /* ! __FreeBSD_version >= 900000 */
- int _kf_ispare[16];
-#endif /* ! __FreeBSD_version >= 900000 */
/* Truncated before copyout in sysctl */
char kf_path[PATH_MAX]; /* Path to file, if any. */
};
@@ -372,34 +296,19 @@ struct target_kinfo_vmentry {
uint64_t kve_start; /* Starting address. */
uint64_t kve_end; /* Finishing address. */
uint64_t kve_offset; /* Mapping offset in object */
-#if defined(__FreeBSD_version) && __FreeBSD_version >= 900000
uint64_t kve_vn_fileid; /* inode number if vnode */
-#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
uint32_t kve_vn_fsid_freebsd11; /* dev_t of vnode location */
-#else
- uint32_t kve_vn_fsid; /* dev_t of vnode location */
-#endif
-#else /* ! __FreeBSD_version >= 900000 */
- uint64_t kve_fileid; /* inode number if vnode */
- uint32_t kve_fsid; /* dev_t of vnode location */
-#endif /* ! __FreeBSD_version >= 900000 */
int32_t kve_flags; /* Flags on map entry. */
int32_t kve_resident; /* Number of resident pages. */
int32_t kve_private_resident; /* Number of private pages. */
int32_t kve_protection; /* Protection bitmask. */
int32_t kve_ref_count; /* VM obj ref count. */
int32_t kve_shadow_count; /* VM obj shadow count. */
-#if defined(__FreeBSD_version) && __FreeBSD_version >= 900000
int32_t kve_vn_type; /* Vnode type. */
uint64_t kve_vn_size; /* File size. */
-#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
uint32_t kve_vn_rdev_freebsd11; /* Device id if device. */
-#else
- uint32_t kve_vn_rdev; /* Device id if device. */
-#endif
uint16_t kve_vn_mode; /* File mode. */
uint16_t kve_status; /* Status flags. */
-#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
#if (__FreeBSD_version >= 1300501 && __FreeBSD_version < 1400000) || \
__FreeBSD_version >= 1400009
union {
@@ -413,13 +322,6 @@ struct target_kinfo_vmentry {
#endif
uint64_t kve_vn_rdev; /* Device id if device. */
int _kve_ispare[8]; /* Space for more stuff. */
-#else
- int32_t _kve_ispare[12]; /* Space for more stuff. */
-#endif
-#else /* ! __FreeBSD_version >= 900000 */
- int _kve_pad0;
- int32_t _kve_ispare[16]; /* Space for more stuff. */
-#endif /* ! __FreeBSD_version >= 900000 */
/* Truncated before copyout in sysctl */
char kve_path[PATH_MAX]; /* Path to VM obj, if any. */
};
diff --git a/bsd-user/i386/target_arch_cpu.h b/bsd-user/i386/target_arch_cpu.h
index 978e8066af..b28602adbb 100644
--- a/bsd-user/i386/target_arch_cpu.h
+++ b/bsd-user/i386/target_arch_cpu.h
@@ -23,8 +23,6 @@
#define TARGET_DEFAULT_CPU_MODEL "qemu32"
-#define TARGET_CPU_RESET(cpu)
-
static inline void target_cpu_init(CPUX86State *env,
struct target_pt_regs *regs)
{
diff --git a/bsd-user/i386/target_arch_signal.h b/bsd-user/i386/target_arch_signal.h
index 9812c6b034..a90750d602 100644
--- a/bsd-user/i386/target_arch_signal.h
+++ b/bsd-user/i386/target_arch_signal.h
@@ -27,8 +27,6 @@
#define TARGET_MINSIGSTKSZ (512 * 4) /* min sig stack size */
#define TARGET_SIGSTKSZ (MINSIGSTKSZ + 32768) /* recommended size */
-#define TARGET_MC_GET_CLEAR_RET 0x0001
-
struct target_sigcontext {
/* to be added */
};
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 48643eeabc..cb5ea40236 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -195,6 +195,15 @@ static void usage(void)
__thread CPUState *thread_cpu;
+void stop_all_tasks(void)
+{
+ /*
+ * We trust when using NPTL (pthreads) start_exclusive() handles thread
+ * stopping correctly.
+ */
+ start_exclusive();
+}
+
bool qemu_cpu_is_self(CPUState *cpu)
{
return thread_cpu == cpu;
@@ -210,7 +219,6 @@ void init_task_state(TaskState *ts)
{
int i;
- ts->used = 1;
ts->first_free = ts->sigqueue_table;
for (i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++) {
ts->sigqueue_table[i].next = &ts->sigqueue_table[i + 1];
diff --git a/bsd-user/meson.build b/bsd-user/meson.build
index 0369549340..87885d91ed 100644
--- a/bsd-user/meson.build
+++ b/bsd-user/meson.build
@@ -1,3 +1,7 @@
+if not have_bsd_user
+ subdir_done()
+endif
+
bsd_user_ss.add(files(
'bsdload.c',
'elfload.c',
@@ -8,3 +12,6 @@ bsd_user_ss.add(files(
'syscall.c',
'uaccess.c',
))
+
+# Pull in the OS-specific build glue, if any
+subdir(targetos)
diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c
index b40ab9045f..13cb32dba1 100644
--- a/bsd-user/mmap.c
+++ b/bsd-user/mmap.c
@@ -21,8 +21,6 @@
#include "qemu.h"
#include "qemu-common.h"
-//#define DEBUG_MMAP
-
static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER;
static __thread int mmap_lock_count;
@@ -67,14 +65,11 @@ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
abi_ulong end, host_start, host_end, addr;
int prot1, ret;
-#ifdef DEBUG_MMAP
- printf("mprotect: start=0x" TARGET_ABI_FMT_lx
- "len=0x" TARGET_ABI_FMT_lx " prot=%c%c%c\n", start, len,
- prot & PROT_READ ? 'r' : '-',
- prot & PROT_WRITE ? 'w' : '-',
- prot & PROT_EXEC ? 'x' : '-');
-#endif
-
+ qemu_log_mask(CPU_LOG_PAGE, "mprotect: start=0x" TARGET_ABI_FMT_lx
+ " len=0x" TARGET_ABI_FMT_lx " prot=%c%c%c\n", start, len,
+ prot & PROT_READ ? 'r' : '-',
+ prot & PROT_WRITE ? 'w' : '-',
+ prot & PROT_EXEC ? 'x' : '-');
if ((start & ~TARGET_PAGE_MASK) != 0)
return -EINVAL;
len = TARGET_PAGE_ALIGN(len);
@@ -132,7 +127,27 @@ error:
return ret;
}
-/* map an incomplete host page */
+/*
+ * map an incomplete host page
+ *
+ * mmap_frag can be called with a valid fd, if flags doesn't contain one of
+ * MAP_ANON, MAP_STACK, MAP_GUARD. If we need to map a page in those cases, we
+ * pass fd == -1. However, if flags contains MAP_GUARD then MAP_ANON cannot be
+ * added.
+ *
+ * * If fd is valid (not -1) we want to map the pages with MAP_ANON.
+ * * If flags contains MAP_GUARD we don't want to add MAP_ANON because it
+ * will be rejected. See kern_mmap's enforcing of constraints for MAP_GUARD
+ * in sys/vm/vm_mmap.c.
+ * * If flags contains MAP_ANON it doesn't matter if we add it or not.
+ * * If flags contains MAP_STACK, mmap adds MAP_ANON when called so doesn't
+ * matter if we add it or not either. See enforcing of constraints for
+ * MAP_STACK in kern_mmap.
+ *
+ * Don't add MAP_ANON for the flags that use fd == -1 without specifying the
+ * flags directly, with the assumption that future flags that require fd == -1
+ * will also not require MAP_ANON.
+ */
static int mmap_frag(abi_ulong real_start,
abi_ulong start, abi_ulong end,
int prot, int flags, int fd, abi_ulong offset)
@@ -152,9 +167,9 @@ static int mmap_frag(abi_ulong real_start,
}
if (prot1 == 0) {
- /* no page was there, so we allocate one */
+ /* no page was there, so we allocate one. See also above. */
void *p = mmap(host_start, qemu_host_page_size, prot,
- flags | MAP_ANON, -1, 0);
+ flags | ((fd != -1) ? MAP_ANON : 0), -1, 0);
if (p == MAP_FAILED)
return -1;
prot1 = prot;
@@ -162,7 +177,7 @@ static int mmap_frag(abi_ulong real_start,
prot1 &= PAGE_BITS;
prot_new = prot | prot1;
- if (!(flags & MAP_ANON)) {
+ if (fd != -1) {
/* msync() won't work here, so we return an error if write is
possible while it is a shared mapping */
if ((flags & TARGET_BSD_MAP_FLAGMASK) == MAP_SHARED &&
@@ -174,16 +189,20 @@ static int mmap_frag(abi_ulong real_start,
mprotect(host_start, qemu_host_page_size, prot1 | PROT_WRITE);
/* read the corresponding file data */
- pread(fd, g2h_untagged(start), end - start, offset);
+ if (pread(fd, g2h_untagged(start), end - start, offset) == -1) {
+ return -1;
+ }
/* put final protection */
if (prot_new != (prot1 | PROT_WRITE))
mprotect(host_start, qemu_host_page_size, prot_new);
} else {
- /* just update the protection */
if (prot_new != prot1) {
mprotect(host_start, qemu_host_page_size, prot_new);
}
+ if (prot_new & PROT_WRITE) {
+ memset(g2h_untagged(start), 0, end - start);
+ }
}
return 0;
}
@@ -281,14 +300,10 @@ static abi_ulong mmap_find_vma_aligned(abi_ulong start, abi_ulong size,
addr = start;
wrapped = repeat = 0;
prev = 0;
- flags = MAP_ANONYMOUS | MAP_PRIVATE;
-#ifdef MAP_ALIGNED
+ flags = MAP_ANON | MAP_PRIVATE;
if (alignment != 0) {
flags |= MAP_ALIGNED(alignment);
}
-#else
- /* XXX TODO */
-#endif
for (;; prev = ptr) {
/*
@@ -391,57 +406,48 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
abi_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len;
mmap_lock();
-#ifdef DEBUG_MMAP
- {
- printf("mmap: start=0x" TARGET_ABI_FMT_lx
- " len=0x" TARGET_ABI_FMT_lx " prot=%c%c%c flags=",
- start, len,
- prot & PROT_READ ? 'r' : '-',
- prot & PROT_WRITE ? 'w' : '-',
- prot & PROT_EXEC ? 'x' : '-');
+ if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
+ qemu_log("mmap: start=0x" TARGET_ABI_FMT_lx
+ " len=0x" TARGET_ABI_FMT_lx " prot=%c%c%c flags=",
+ start, len,
+ prot & PROT_READ ? 'r' : '-',
+ prot & PROT_WRITE ? 'w' : '-',
+ prot & PROT_EXEC ? 'x' : '-');
if (flags & MAP_ALIGNMENT_MASK) {
- printf("MAP_ALIGNED(%u) ", (flags & MAP_ALIGNMENT_MASK)
- >> MAP_ALIGNMENT_SHIFT);
+ qemu_log("MAP_ALIGNED(%u) ",
+ (flags & MAP_ALIGNMENT_MASK) >> MAP_ALIGNMENT_SHIFT);
}
-#if MAP_GUARD
if (flags & MAP_GUARD) {
- printf("MAP_GUARD ");
+ qemu_log("MAP_GUARD ");
}
-#endif
if (flags & MAP_FIXED) {
- printf("MAP_FIXED ");
+ qemu_log("MAP_FIXED ");
}
- if (flags & MAP_ANONYMOUS) {
- printf("MAP_ANON ");
+ if (flags & MAP_ANON) {
+ qemu_log("MAP_ANON ");
}
-#ifdef MAP_EXCL
if (flags & MAP_EXCL) {
- printf("MAP_EXCL ");
+ qemu_log("MAP_EXCL ");
}
-#endif
if (flags & MAP_PRIVATE) {
- printf("MAP_PRIVATE ");
+ qemu_log("MAP_PRIVATE ");
}
if (flags & MAP_SHARED) {
- printf("MAP_SHARED ");
+ qemu_log("MAP_SHARED ");
}
if (flags & MAP_NOCORE) {
- printf("MAP_NOCORE ");
+ qemu_log("MAP_NOCORE ");
}
-#ifdef MAP_STACK
if (flags & MAP_STACK) {
- printf("MAP_STACK ");
+ qemu_log("MAP_STACK ");
}
-#endif
- printf("fd=%d offset=0x%llx\n", fd, offset);
+ qemu_log("fd=%d offset=0x%lx\n", fd, offset);
}
-#endif
- if ((flags & MAP_ANONYMOUS) && fd != -1) {
+ if ((flags & MAP_ANON) && fd != -1) {
errno = EINVAL;
goto fail;
}
-#ifdef MAP_STACK
if (flags & MAP_STACK) {
if ((fd != -1) || ((prot & (PROT_READ | PROT_WRITE)) !=
(PROT_READ | PROT_WRITE))) {
@@ -449,8 +455,6 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
goto fail;
}
}
-#endif /* MAP_STACK */
-#ifdef MAP_GUARD
if ((flags & MAP_GUARD) && (prot != PROT_NONE || fd != -1 ||
offset != 0 || (flags & (MAP_SHARED | MAP_PRIVATE |
/* MAP_PREFAULT | */ /* MAP_PREFAULT not in mman.h */
@@ -458,18 +462,24 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
errno = EINVAL;
goto fail;
}
-#endif
if (offset & ~TARGET_PAGE_MASK) {
errno = EINVAL;
goto fail;
}
- len = TARGET_PAGE_ALIGN(len);
if (len == 0) {
errno = EINVAL;
goto fail;
}
+
+ /* Check for overflows */
+ len = TARGET_PAGE_ALIGN(len);
+ if (len == 0) {
+ errno = ENOMEM;
+ goto fail;
+ }
+
real_start = start & qemu_host_page_mask;
host_offset = offset & qemu_host_page_mask;
@@ -536,7 +546,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
* qemu_real_host_page_size
*/
p = mmap(g2h_untagged(start), host_len, prot,
- flags | MAP_FIXED | ((fd != -1) ? MAP_ANONYMOUS : 0), -1, 0);
+ flags | MAP_FIXED | ((fd != -1) ? MAP_ANON : 0), -1, 0);
if (p == MAP_FAILED)
goto fail;
/* update start so that it points to the file position at 'offset' */
@@ -564,18 +574,16 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
* It can fail only on 64-bit host with 32-bit target.
* On any other target/host host mmap() handles this error correctly.
*/
-#if TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
- if ((unsigned long)start + len - 1 > (abi_ulong) -1) {
+ if (!guest_range_valid_untagged(start, len)) {
errno = EINVAL;
goto fail;
}
-#endif
/*
* worst case: we cannot map the file because the offset is not
* aligned, so we read it
*/
- if (!(flags & MAP_ANON) &&
+ if (fd != -1 &&
(offset & ~qemu_host_page_mask) != (start & ~qemu_host_page_mask)) {
/*
* msync() won't work here, so we return an error if write is
@@ -591,17 +599,22 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
-1, 0);
if (retaddr == -1)
goto fail;
- pread(fd, g2h_untagged(start), len, offset);
+ if (pread(fd, g2h_untagged(start), len, offset) == -1) {
+ goto fail;
+ }
if (!(prot & PROT_WRITE)) {
ret = target_mprotect(start, len, prot);
- if (ret != 0) {
- start = ret;
- goto the_end;
- }
+ assert(ret == 0);
}
goto the_end;
}
+ /* Reject the mapping if any page within the range is mapped */
+ if ((flags & MAP_EXCL) && page_check_range(start, len, 0) < 0) {
+ errno = EINVAL;
+ goto fail;
+ }
+
/* handle the start of the mapping */
if (start > real_start) {
if (real_end == real_start + qemu_host_page_size) {
@@ -697,8 +710,7 @@ static void mmap_reserve(abi_ulong start, abi_ulong size)
}
if (real_start != real_end) {
mmap(g2h_untagged(real_start), real_end - real_start, PROT_NONE,
- MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE,
- -1, 0);
+ MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
}
}
diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
index 522d6c4031..1b3b974afe 100644
--- a/bsd-user/qemu.h
+++ b/bsd-user/qemu.h
@@ -17,7 +17,6 @@
#ifndef QEMU_H
#define QEMU_H
-
#include "qemu/osdep.h"
#include "cpu.h"
#include "qemu/units.h"
@@ -73,15 +72,15 @@ struct image_info {
#define MAX_SIGQUEUE_SIZE 1024
-struct sigqueue {
- struct sigqueue *next;
+struct qemu_sigqueue {
+ struct qemu_sigqueue *next;
+ target_siginfo_t info;
};
struct emulated_sigtable {
int pending; /* true if signal is pending */
- struct sigqueue *first;
- /* in order to always have memory for the first signal, we put it here */
- struct sigqueue info;
+ struct qemu_sigqueue *first;
+ struct qemu_sigqueue info; /* Put first signal info here */
};
/*
@@ -92,18 +91,18 @@ typedef struct TaskState {
struct TaskState *next;
struct bsd_binprm *bprm;
- int used; /* non zero if used */
struct image_info *info;
struct emulated_sigtable sigtab[TARGET_NSIG];
- struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
- struct sigqueue *first_free; /* first free siginfo queue entry */
+ struct qemu_sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
+ struct qemu_sigqueue *first_free; /* first free siginfo queue entry */
int signal_pending; /* non zero if a signal may be pending */
uint8_t stack[];
} __attribute__((aligned(16))) TaskState;
void init_task_state(TaskState *ts);
+void stop_all_tasks(void);
extern const char *qemu_uname_release;
/*
@@ -209,6 +208,7 @@ void process_pending_signals(CPUArchState *cpu_env);
void signal_init(void);
long do_sigreturn(CPUArchState *env);
long do_rt_sigreturn(CPUArchState *env);
+void queue_signal(CPUArchState *env, int sig, target_siginfo_t *info);
abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp);
/* mmap.c */
@@ -235,6 +235,13 @@ extern unsigned long target_dflssiz;
extern unsigned long target_maxssiz;
extern unsigned long target_sgrowsiz;
+/* syscall.c */
+abi_long get_errno(abi_long ret);
+bool is_error(abi_long ret);
+
+/* os-sys.c */
+abi_long do_freebsd_sysarch(void *cpu_env, abi_long arg1, abi_long arg2);
+
/* user access */
#define VERIFY_READ PAGE_READ
diff --git a/bsd-user/signal.c b/bsd-user/signal.c
index ad6d935569..0c1093deb1 100644
--- a/bsd-user/signal.c
+++ b/bsd-user/signal.c
@@ -16,10 +16,19 @@
* 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/osdep.h"
#include "qemu.h"
+/*
+ * Queue a signal so that it will be send to the virtual CPU as soon as
+ * possible.
+ */
+void queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
+{
+ qemu_log_mask(LOG_UNIMP, "No signal queueing, dropping signal %d\n", sig);
+}
+
void signal_init(void)
{
}
diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
index 372836d44d..d3322760f4 100644
--- a/bsd-user/syscall.c
+++ b/bsd-user/syscall.c
@@ -33,18 +33,18 @@
static abi_ulong target_brk;
static abi_ulong target_original_brk;
-static inline abi_long get_errno(abi_long ret)
+abi_long get_errno(abi_long ret)
{
- if (ret == -1)
+ if (ret == -1) {
/* XXX need to translate host -> target errnos here */
return -(errno);
- else
- return ret;
+ }
+ return ret;
}
#define target_to_host_bitmask(x, tbl) (x)
-static inline int is_error(abi_long ret)
+bool is_error(abi_long ret)
{
return (abi_ulong)ret >= (abi_ulong)(-4096);
}
@@ -88,56 +88,6 @@ static abi_long do_obreak(abi_ulong new_brk)
return 0;
}
-#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 __FreeBSD__
/*
* XXX this uses the undocumented oidfmt interface to find the kind of
diff --git a/bsd-user/x86_64/target_arch_cpu.h b/bsd-user/x86_64/target_arch_cpu.h
index 5f5ee602f9..5172b230f0 100644
--- a/bsd-user/x86_64/target_arch_cpu.h
+++ b/bsd-user/x86_64/target_arch_cpu.h
@@ -23,8 +23,6 @@
#define TARGET_DEFAULT_CPU_MODEL "qemu64"
-#define TARGET_CPU_RESET(cpu)
-
static inline void target_cpu_init(CPUX86State *env,
struct target_pt_regs *regs)
{
diff --git a/bsd-user/x86_64/target_arch_signal.h b/bsd-user/x86_64/target_arch_signal.h
index 4c1ff0e5ba..4bb753b08b 100644
--- a/bsd-user/x86_64/target_arch_signal.h
+++ b/bsd-user/x86_64/target_arch_signal.h
@@ -27,8 +27,6 @@
#define TARGET_MINSIGSTKSZ (512 * 4) /* min sig stack size */
#define TARGET_SIGSTKSZ (MINSIGSTKSZ + 32768) /* recommended size */
-#define TARGET_MC_GET_CLEAR_RET 0x0001
-
struct target_sigcontext {
/* to be added */
};
diff --git a/linux-user/meson.build b/linux-user/meson.build
index 9549f81682..bf62c13e37 100644
--- a/linux-user/meson.build
+++ b/linux-user/meson.build
@@ -1,3 +1,7 @@
+if not have_linux_user
+ subdir_done()
+endif
+
linux_user_ss.add(files(
'elfload.c',
'exit.c',
diff --git a/meson.build b/meson.build
index 6b7487b725..5e7946776d 100644
--- a/meson.build
+++ b/meson.build
@@ -40,12 +40,15 @@ config_host_data = configuration_data()
genh = []
target_dirs = config_host['TARGET_DIRS'].split()
-have_user = false
+have_linux_user = false
+have_bsd_user = false
have_system = false
foreach target : target_dirs
- have_user = have_user or target.endswith('-user')
+ have_linux_user = have_linux_user or target.endswith('linux-user')
+ have_bsd_user = have_bsd_user or target.endswith('bsd-user')
have_system = have_system or target.endswith('-softmmu')
endforeach
+have_user = have_linux_user or have_bsd_user
have_tools = 'CONFIG_TOOLS' in config_host
have_block = have_system or have_tools
@@ -2595,10 +2598,11 @@ subdir('bsd-user')
subdir('linux-user')
subdir('ebpf')
-bsd_user_ss.add(files('gdbstub.c'))
+common_ss.add(libbpf)
+
specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss)
-linux_user_ss.add(files('gdbstub.c', 'thunk.c'))
+linux_user_ss.add(files('thunk.c'))
specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss)
# needed for fuzzing binaries