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 . + */ + +#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 . */ -#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