From 7e726bb2244c4cea64bf8f786582875a50f0a94c Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Mon, 27 May 2013 06:15:36 -0500 Subject: [PATCH 10/23] bsd-user: add shims for memory management related syscalls To: Cc: This change adds support for bsd memory management system calls including mmap(2), munmap(2), mprotect(2), msync(2), etc. Also, it adds shared memory management system calls. In addition, cleans up syscall.c a bit and fixes checkpatch.pl warnings and errors. Signed-off-by: Stacey Son --- bsd-user/Makefile.objs | 2 +- bsd-user/bsd-errno.h | 41 +++++ bsd-user/bsd-mem.c | 122 +++++++++++++++ bsd-user/bsd-mem.h | 387 +++++++++++++++++++++++++++++++++++++++++++++++ bsd-user/bsd-mman.h | 121 --------------- bsd-user/mmap.c | 84 +++-------- bsd-user/qemu-bsd.h | 34 ++++ bsd-user/qemu.h | 1 + bsd-user/syscall.c | 185 +++++++++++++---------- bsd-user/syscall_defs.h | 71 +++++++++ 10 files changed, 782 insertions(+), 266 deletions(-) create mode 100644 bsd-user/bsd-errno.h create mode 100644 bsd-user/bsd-mem.c create mode 100644 bsd-user/bsd-mem.h delete mode 100644 bsd-user/bsd-mman.h create mode 100644 bsd-user/qemu-bsd.h diff --git a/bsd-user/Makefile.objs b/bsd-user/Makefile.objs index 5e77f57..d0cea36 100644 --- a/bsd-user/Makefile.objs +++ b/bsd-user/Makefile.objs @@ -1,2 +1,2 @@ obj-y = main.o bsdload.o elfload.o mmap.o signal.o strace.o syscall.o \ - uaccess.o + uaccess.o bsd-mem.o diff --git a/bsd-user/bsd-errno.h b/bsd-user/bsd-errno.h new file mode 100644 index 0000000..721bfc0 --- /dev/null +++ b/bsd-user/bsd-errno.h @@ -0,0 +1,41 @@ +/* + * errno translation + * + * Copyright (c) 2003 - 2008 Fabrice Bellard + * 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 . + */ + +#ifndef __BSD_ERRNO_H_ +#define __BSD_ERRNO_H_ + +static inline abi_long get_errno(abi_long ret) +{ + + if (ret == -1) { + /* XXX need to translate host -> target errnos here */ + return -(errno); + } else { + return ret; + } +} + +static inline int is_error(abi_long ret) +{ + + return (abi_ulong)ret >= (abi_ulong)(-4096); +} + +#endif /* !__BSD_ERRNO_H_ */ diff --git a/bsd-user/bsd-mem.c b/bsd-user/bsd-mem.c new file mode 100644 index 0000000..bfe03aa --- /dev/null +++ b/bsd-user/bsd-mem.c @@ -0,0 +1,122 @@ +/* + * memory management system conversion routines + * + * 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 . + */ + +#include +#include + +#include "qemu.h" +#include "qemu-bsd.h" + +struct bsd_shm_regions bsd_shm_regions[N_BSD_SHM_REGIONS]; + +abi_ulong bsd_target_brk; +abi_ulong bsd_target_original_brk; + +void target_set_brk(abi_ulong new_brk) +{ + + bsd_target_original_brk = bsd_target_brk = HOST_PAGE_ALIGN(new_brk); +} + +abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip, + abi_ulong target_addr) +{ + struct target_ipc_perm *target_ip; + + if (!lock_user_struct(VERIFY_READ, target_ip, target_addr, 1)) { + return -TARGET_EFAULT; + } + __get_user(host_ip->cuid, &target_ip->cuid); + __get_user(host_ip->cgid, &target_ip->cgid); + __get_user(host_ip->uid, &target_ip->uid); + __get_user(host_ip->gid, &target_ip->gid); + __get_user(host_ip->mode, &target_ip->mode); + __get_user(host_ip->seq, &target_ip->seq); + __get_user(host_ip->key, &target_ip->key); + unlock_user_struct(target_ip, target_addr, 0); + + return 0; +} + +abi_long host_to_target_ipc_perm(abi_ulong target_addr, + struct ipc_perm *host_ip) +{ + struct target_ipc_perm *target_ip; + + if (!lock_user_struct(VERIFY_WRITE, target_ip, target_addr, 0)) { + return -TARGET_EFAULT; + } + __put_user(host_ip->cuid, &target_ip->cuid); + __put_user(host_ip->cgid, &target_ip->cgid); + __put_user(host_ip->uid, &target_ip->uid); + __put_user(host_ip->gid, &target_ip->gid); + __put_user(host_ip->mode, &target_ip->mode); + __put_user(host_ip->seq, &target_ip->seq); + __put_user(host_ip->key, &target_ip->key); + unlock_user_struct(target_ip, target_addr, 1); + + return 0; +} + +abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd, + abi_ulong target_addr) +{ + struct target_shmid_ds *target_sd; + + if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) { + return -TARGET_EFAULT; + } + if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr)) { + return -TARGET_EFAULT; + } + __get_user(host_sd->shm_segsz, &target_sd->shm_segsz); + __get_user(host_sd->shm_lpid, &target_sd->shm_lpid); + __get_user(host_sd->shm_cpid, &target_sd->shm_cpid); + __get_user(host_sd->shm_nattch, &target_sd->shm_nattch); + __get_user(host_sd->shm_atime, &target_sd->shm_atime); + __get_user(host_sd->shm_dtime, &target_sd->shm_dtime); + __get_user(host_sd->shm_ctime, &target_sd->shm_ctime); + unlock_user_struct(target_sd, target_addr, 0); + + return 0; +} + +abi_long host_to_target_shmid_ds(abi_ulong target_addr, + struct shmid_ds *host_sd) +{ + struct target_shmid_ds *target_sd; + + if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) { + return -TARGET_EFAULT; + } + if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm))) { + return -TARGET_EFAULT; + } + __put_user(host_sd->shm_segsz, &target_sd->shm_segsz); + __put_user(host_sd->shm_lpid, &target_sd->shm_lpid); + __put_user(host_sd->shm_cpid, &target_sd->shm_cpid); + __put_user(host_sd->shm_nattch, &target_sd->shm_nattch); + __put_user(host_sd->shm_atime, &target_sd->shm_atime); + __put_user(host_sd->shm_dtime, &target_sd->shm_dtime); + __put_user(host_sd->shm_ctime, &target_sd->shm_ctime); + unlock_user_struct(target_sd, target_addr, 1); + + return 0; +} + diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h new file mode 100644 index 0000000..ec44a30 --- /dev/null +++ b/bsd-user/bsd-mem.h @@ -0,0 +1,387 @@ +/* + * memory management 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 . + */ + +/*-- + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _BSD_MMAN_H_ +#define _BSD_MMAN_H_ + +#include +#include +#include +#include +#include + +#include "qemu-bsd.h" + +extern struct bsd_shm_regions bsd_shm_regions[]; +extern abi_ulong bsd_target_brk; +extern abi_ulong bsd_target_original_brk; + +/* mmap(2) */ +static inline abi_long do_bsd_mmap(abi_long arg1, abi_long arg2, abi_long arg3, + abi_long arg4, abi_long arg5, abi_long arg6) +{ + + return get_errno(target_mmap(arg1, arg2, arg3, + target_to_host_bitmask(arg4, mmap_flags_tbl), arg5, arg6)); +} + +/* munmap(2) */ +static inline abi_long do_bsd_munmap(abi_long arg1, abi_long arg2) +{ + + return get_errno(target_munmap(arg1, arg2)); +} + +/* mprotect(2) */ +static inline abi_long do_bsd_mprotect(abi_long arg1, abi_long arg2, + abi_long arg3) +{ + + return get_errno(target_mprotect(arg1, arg2, arg3)); +} + +/* msync(2) */ +static inline abi_long do_bsd_msync(abi_long arg1, abi_long arg2, abi_long arg3) +{ + + return get_errno(msync(g2h(arg1), arg2, arg3)); +} + +/* mlock(2) */ +static inline abi_long do_bsd_mlock(abi_long arg1, abi_long arg2) +{ + + return get_errno(mlock(g2h(arg1), arg2)); +} + +/* munlock(2) */ +static inline abi_long do_bsd_munlock(abi_long arg1, abi_long arg2) +{ + + return get_errno(munlock(g2h(arg1), arg2)); +} + +/* mlockall(2) */ +static inline abi_long do_bsd_mlockall(abi_long arg1) +{ + + return get_errno(mlockall(arg1)); +} + +/* munlockall(2) */ +static inline abi_long do_bsd_munlockall(void) +{ + + return get_errno(munlockall()); +} + +/* madvise(2) */ +static inline abi_long do_bsd_madvise(abi_long arg1, abi_long arg2, + abi_long arg3) +{ + /* + * A straight passthrough may not be safe because qemu sometimes + * turns private file-backed mapping into anonymous mappings. This + * will break MADV_DONTNEED. This is a hint, so ignoring and returing + * success is ok. + */ + return get_errno(0); +} + +/* minherit(2) */ +static inline abi_long do_bsd_minherit(abi_long addr, abi_long len, + abi_long inherit) +{ + + return get_errno(minherit(g2h(addr), len, inherit)); +} + +/* mincore(2) */ +static inline abi_long do_bsd_mincore(abi_ulong target_addr, abi_ulong len, + abi_ulong target_vec) +{ + abi_long ret; + void *p, *a; + + a = lock_user(VERIFY_WRITE, target_addr, len, 0); + if (a == NULL) { + return -TARGET_EFAULT; + } + p = lock_user_string(target_vec); + if (p == NULL) { + unlock_user(a, target_addr, 0); + return -TARGET_EFAULT; + } + ret = get_errno(mincore(a, len, p)); + unlock_user(p, target_vec, ret); + unlock_user(a, target_addr, 0); + + return ret; +} + +/* break() XXX this needs some more work. */ +static inline abi_long do_obreak(abi_ulong new_brk) +{ + abi_ulong brk_page; + abi_long mapped_addr; + int new_alloc_size; + + return -TARGET_EINVAL; + + if (!new_brk) { + return 0; + } + if (new_brk < bsd_target_original_brk) { + return -TARGET_EINVAL; + } + + brk_page = HOST_PAGE_ALIGN(bsd_target_brk); + + /* If the new brk is less than this, set it and we're done... */ + if (new_brk < brk_page) { + bsd_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)) { + bsd_target_brk = new_brk; + } else { + return mapped_addr; + } + + return 0; +} + +/* shm_open(2) */ +static inline abi_long do_bsd_shm_open(abi_ulong arg1, abi_long arg2, + abi_long arg3) +{ + int ret; + void *p; + + p = lock_user_string(arg1); + if (p == NULL) { + return -TARGET_EFAULT; + } + ret = get_errno(shm_open(path(p), + target_to_host_bitmask(arg2, fcntl_flags_tbl), arg3)); + unlock_user(p, arg1, 0); + + return ret; +} + +/* shm_unlink(2) */ +static inline abi_long do_bsd_shm_unlink(abi_ulong arg1) +{ + int ret; + void *p; + + p = lock_user_string(arg1); + if (p == NULL) { + return -TARGET_EFAULT; + } + ret = get_errno(shm_unlink(p)); /* XXX path(p)? */ + unlock_user(p, arg1, 0); + + return ret; +} + +/* shmget(2) */ +static inline abi_long do_bsd_shmget(abi_long arg1, abi_ulong arg2, + abi_long arg3) +{ + + return get_errno(shmget(arg1, arg2, arg3)); +} + +/* shmctl(2) */ +static inline abi_long do_bsd_shmctl(abi_long shmid, abi_long cmd, + abi_ulong buff) +{ + struct shmid_ds dsarg; + abi_long ret = -TARGET_EINVAL; + + cmd &= 0xff; + + switch (cmd) { + case IPC_STAT: + case IPC_SET: + if (target_to_host_shmid_ds(&dsarg, buff)) { + return -TARGET_EFAULT; + } + ret = get_errno(shmctl(shmid, cmd, &dsarg)); + if (host_to_target_shmid_ds(buff, &dsarg)) { + return -TARGET_EFAULT; + } + break; + + case IPC_RMID: + ret = get_errno(shmctl(shmid, cmd, NULL)); + break; + + default: + ret = -TARGET_EINVAL; + break; + } + + return ret; +} + +/* shmat(2) */ +static inline abi_long do_bsd_shmat(int shmid, abi_ulong shmaddr, int shmflg) +{ + abi_ulong raddr; + abi_long ret; + void *host_raddr; + struct shmid_ds shm_info; + int i; + + /* Find out the length of the shared memory segment. */ + ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info)); + if (is_error(ret)) { + /* Can't get the length */ + return ret; + } + + mmap_lock(); + + if (shmaddr) { + host_raddr = shmat(shmid, (void *)g2h(shmaddr), shmflg); + } else { + abi_ulong mmap_start; + + mmap_start = mmap_find_vma(0, shm_info.shm_segsz); + + if (mmap_start == -1) { + errno = ENOMEM; + host_raddr = (void *)-1; + } else { + host_raddr = shmat(shmid, g2h(mmap_start), + shmflg /* | SHM_REMAP */); + } + } + + if (host_raddr == (void *)-1) { + mmap_unlock(); + return get_errno((long)host_raddr); + } + raddr = h2g((unsigned long)host_raddr); + + page_set_flags(raddr, raddr + shm_info.shm_segsz, + PAGE_VALID | PAGE_READ | ((shmflg & SHM_RDONLY) ? 0 : PAGE_WRITE)); + + for (i = 0; i < N_BSD_SHM_REGIONS; i++) { + if (bsd_shm_regions[i].start == 0) { + bsd_shm_regions[i].start = raddr; + bsd_shm_regions[i].size = shm_info.shm_segsz; + break; + } + } + + mmap_unlock(); + return raddr; +} + +/* shmdt(2) */ +static inline abi_long do_bsd_shmdt(abi_ulong shmaddr) +{ + int i; + + for (i = 0; i < N_BSD_SHM_REGIONS; ++i) { + if (bsd_shm_regions[i].start == shmaddr) { + bsd_shm_regions[i].start = 0; + page_set_flags(shmaddr, + shmaddr + bsd_shm_regions[i].size, 0); + break; + } + } + + return get_errno(shmdt(g2h(shmaddr))); +} + + +static inline abi_long do_bsd_vadvise(void) +{ + /* See sys_ovadvise() in vm_unix.c */ + qemu_log("qemu: Unsupported syscall vadvise()\n"); + return -TARGET_ENOSYS; +} + +static inline abi_long do_bsd_sbrk(void) +{ + /* see sys_sbrk() in vm_mmap.c */ + qemu_log("qemu: Unsupported syscall sbrk()\n"); + return -TARGET_ENOSYS; +} + +static inline abi_long do_bsd_sstk(void) +{ + /* see sys_sstk() in vm_mmap.c */ + qemu_log("qemu: Unsupported syscall sstk()\n"); + return -TARGET_ENOSYS; +} + +/* + * undocumented freebsd6_mmap(caddr_t addr, size_t len, int prot, int + * flags, int fd, int pad, off_t pos) system call. + */ +static inline abi_long do_bsd_freebsd6_mmap(abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6, + abi_long arg7) +{ + + qemu_log("qemu: Unsupported syscall freebsd6_mmap()\n"); + return -TARGET_ENOSYS; +} + +#endif /* !_BSD_MMAN_H_ */ diff --git a/bsd-user/bsd-mman.h b/bsd-user/bsd-mman.h deleted file mode 100644 index 2193ce7..0000000 --- a/bsd-user/bsd-mman.h +++ /dev/null @@ -1,121 +0,0 @@ -/*-- - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)mman.h 8.2 (Berkeley) 1/9/95 - * $FreeBSD: src/sys/sys/mman.h,v 1.42 2008/03/28 04:29:27 ps Exp $ - */ - -#define TARGET_FREEBSD_MAP_RESERVED0080 0x0080 /* previously misimplemented MAP_INHERIT */ -#define TARGET_FREEBSD_MAP_RESERVED0100 0x0100 /* previously unimplemented MAP_NOEXTEND */ -#define TARGET_FREEBSD_MAP_STACK 0x0400 /* region grows down, like a stack */ -#define TARGET_FREEBSD_MAP_NOSYNC 0x0800 /* page to but do not sync underlying file */ - -#define TARGET_FREEBSD_MAP_FLAGMASK 0x1ff7 - -/* $NetBSD: mman.h,v 1.42 2008/11/18 22:13:49 ad Exp $ */ - -/*- - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)mman.h 8.2 (Berkeley) 1/9/95 - */ -#define TARGET_NETBSD_MAP_INHERIT 0x0080 /* region is retained after exec */ -#define TARGET_NETBSD_MAP_TRYFIXED 0x0400 /* attempt hint address, even within break */ -#define TARGET_NETBSD_MAP_WIRED 0x0800 /* mlock() mapping when it is established */ - -#define TARGET_NETBSD_MAP_STACK 0x2000 /* allocated from memory, swap space (stack) */ - -#define TARGET_NETBSD_MAP_FLAGMASK 0x3ff7 - -/* $OpenBSD: mman.h,v 1.18 2003/07/21 22:52:19 tedu Exp $ */ -/* $NetBSD: mman.h,v 1.11 1995/03/26 20:24:23 jtc Exp $ */ - -/*- - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)mman.h 8.1 (Berkeley) 6/2/93 - */ - -#define TARGET_OPENBSD_MAP_INHERIT 0x0080 /* region is retained after exec */ -#define TARGET_OPENBSD_MAP_NOEXTEND 0x0100 /* for MAP_FILE, don't change file size */ -#define TARGET_OPENBSD_MAP_TRYFIXED 0x0400 /* attempt hint address, even within heap */ - -#define TARGET_OPENBSD_MAP_FLAGMASK 0x17f7 - -// XXX -#define TARGET_BSD_MAP_FLAGMASK 0x3ff7 diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c index 29e0427..2fbc97c 100644 --- a/bsd-user/mmap.c +++ b/bsd-user/mmap.c @@ -26,13 +26,12 @@ #include "qemu.h" #include "qemu-common.h" -#include "bsd-mman.h" //#define DEBUG_MMAP #if defined(CONFIG_USE_NPTL) -pthread_mutex_t mmap_mutex; -static int __thread mmap_lock_count; +pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER; +static __thread int mmap_lock_count; void mmap_lock(void) { @@ -72,67 +71,7 @@ void mmap_lock(void) void mmap_unlock(void) { } -#endif - -static void *bsd_vmalloc(size_t size) -{ - void *p; - mmap_lock(); - /* Use map and mark the pages as used. */ - p = mmap(NULL, size, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON, -1, 0); - - if (h2g_valid(p)) { - /* Allocated region overlaps guest address space. - This may recurse. */ - abi_ulong addr = h2g(p); - page_set_flags(addr & TARGET_PAGE_MASK, TARGET_PAGE_ALIGN(addr + size), - PAGE_RESERVED); - } - - mmap_unlock(); - return p; -} - -void *g_malloc(size_t size) -{ - char * p; - size += 16; - p = bsd_vmalloc(size); - *(size_t *)p = size; - return p + 16; -} - -/* We use map, which is always zero initialized. */ -void * g_malloc0(size_t size) -{ - return g_malloc(size); -} - -void g_free(void *ptr) -{ - /* FIXME: We should unmark the reserved pages here. However this gets - complicated when one target page spans multiple host pages, so we - don't bother. */ - size_t *p; - p = (size_t *)((char *)ptr - 16); - munmap(p, *p); -} - -void *g_realloc(void *ptr, size_t size) -{ - size_t old_size, copy; - void *new_ptr; - - if (!ptr) - return g_malloc(size); - old_size = *(size_t *)((char *)ptr - 16); - copy = old_size < size ? old_size : size; - new_ptr = g_malloc(size); - memcpy(new_ptr, ptr, copy); - g_free(ptr); - return new_ptr; -} +#endif /* ! CONFIG_USE_NPTL */ /* NOTE: all the constants are the HOST ones, but addresses are target. */ int target_mprotect(abi_ulong start, abi_ulong len, int prot) @@ -275,7 +214,7 @@ unsigned long last_brk; */ /* page_init() marks pages used by the host as reserved to be sure not to use them. */ -static abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size) +abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size) { abi_ulong addr, addr1, addr_start; int prot; @@ -344,6 +283,11 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, case MAP_SHARED: printf("MAP_SHARED "); break; +#ifdef MAP_STACK + case MAP_STACK: + printf("MAP_STACK "); + break; +#endif default: printf("[MAP_FLAGMASK=0x%x] ", flags & TARGET_BSD_MAP_FLAGMASK); break; @@ -352,6 +296,16 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, } #endif +#ifdef MAP_STACK + if (flags & MAP_STACK) { + if ((fd != -1) || ((prot & (PROT_READ | PROT_WRITE)) != + (PROT_READ | PROT_WRITE))) { + errno = EINVAL; + goto fail; + } + } +#endif /* MAP_STACK */ + if (offset & ~TARGET_PAGE_MASK) { errno = EINVAL; goto fail; diff --git a/bsd-user/qemu-bsd.h b/bsd-user/qemu-bsd.h new file mode 100644 index 0000000..0add0b3 --- /dev/null +++ b/bsd-user/qemu-bsd.h @@ -0,0 +1,34 @@ +/* + * BSD conversion extern declarations + * + * 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 . + */ + +#ifndef _QEMU_BSD_H_ +#define _QEMU_BSD_H_ + +/* bsd-mem.c */ +abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip, + abi_ulong target_addr); +abi_long host_to_target_ipc_perm(abi_ulong target_addr, + struct ipc_perm *host_ip); +abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd, + abi_ulong target_addr); +abi_long host_to_target_shmid_ds(abi_ulong target_addr, + struct shmid_ds *host_sd); + + +#endif /* !_QEMU_BSD_H_ */ diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h index 1e2abd5..02a05bb 100644 --- a/bsd-user/qemu.h +++ b/bsd-user/qemu.h @@ -217,6 +217,7 @@ int target_msync(abi_ulong start, abi_ulong len, int flags); extern unsigned long last_brk; void mmap_lock(void); void mmap_unlock(void); +abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size); void cpu_list_lock(void); void cpu_list_unlock(void); #if defined(CONFIG_USE_NPTL) diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c index 02740d5..b64c0b0 100644 --- a/bsd-user/syscall.c +++ b/bsd-user/syscall.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -36,65 +35,12 @@ #include "qemu.h" #include "qemu-common.h" -//#define DEBUG - -static abi_ulong target_brk; -static abi_ulong target_original_brk; - -static inline abi_long get_errno(abi_long ret) -{ - if (ret == -1) - /* XXX need to translate host -> target errnos here */ - return -(errno); - else - return ret; -} - #define target_to_host_bitmask(x, tbl) (x) -static inline int 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)); +#include "bsd-errno.h" +#include "bsd-mem.h" - if (!is_error(mapped_addr)) - target_brk = new_brk; - else - return mapped_addr; - - return 0; -} +/* #define DEBUG */ #if defined(TARGET_I386) static abi_long do_freebsd_sysarch(CPUX86State *env, int op, abi_ulong parms) @@ -278,15 +224,17 @@ static abi_long do_freebsd_sysctl(abi_ulong namep, int32_t namelen, abi_ulong ol * 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) + 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) + 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); @@ -304,13 +252,14 @@ static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr, } static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr, - int count, int copy) + 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); + 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++) { @@ -383,15 +332,95 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1, 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)); + + /* + * Memory management system calls. + */ + case TARGET_FREEBSD_NR_mmap: /* mmap(2) */ + ret = do_bsd_mmap(arg1, arg2, arg3, arg4, arg5, arg6); + break; + + case TARGET_FREEBSD_NR_munmap: /* munmap(2) */ + ret = do_bsd_munmap(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_mprotect: /* mprotect(2) */ + ret = do_bsd_mprotect(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_msync: /* msync(2) */ + ret = do_bsd_msync(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_mlock: /* mlock(2) */ + ret = do_bsd_mlock(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_munlock: /* munlock(2) */ + ret = do_bsd_munlock(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_mlockall: /* mlockall(2) */ + ret = do_bsd_mlockall(arg1); + break; + + case TARGET_FREEBSD_NR_munlockall: /* munlockall(2) */ + ret = do_bsd_munlockall(); + break; + + case TARGET_FREEBSD_NR_madvise: /* madvise(2) */ + ret = do_bsd_madvise(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_minherit: /* minherit(2) */ + ret = do_bsd_minherit(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_mincore: /* mincore(2) */ + ret = do_bsd_mincore(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_shm_open: /* shm_open(2) */ + ret = do_bsd_shm_open(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_shm_unlink: /* shm_unlink(2) */ + ret = do_bsd_shm_unlink(arg1); + break; + + case TARGET_FREEBSD_NR_shmget: /* shmget(2) */ + ret = do_bsd_shmget(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_shmctl: /* shmctl(2) */ + ret = do_bsd_shmctl(arg1, arg2, arg3); break; - case TARGET_FREEBSD_NR_mprotect: - ret = get_errno(target_mprotect(arg1, arg2, arg3)); + + case TARGET_FREEBSD_NR_shmat: /* shmat(2) */ + ret = do_bsd_shmat(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_shmdt: /* shmdt(2) */ + ret = do_bsd_shmdt(arg1); + break; + + case TARGET_FREEBSD_NR_vadvise: + ret = do_bsd_vadvise(); + break; + + case TARGET_FREEBSD_NR_sbrk: + ret = do_bsd_sbrk(); + break; + + case TARGET_FREEBSD_NR_sstk: + ret = do_bsd_sstk(); break; + + case TARGET_FREEBSD_NR_freebsd6_mmap: /* undocumented */ + ret = do_bsd_freebsd6_mmap(arg1, arg2, arg3, arg4, arg5, arg6, arg7); + break; + + case TARGET_FREEBSD_NR_break: ret = do_obreak(arg1); break; @@ -466,15 +495,14 @@ abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long arg1, 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)); + ret = do_bsd_mmap(arg1, arg2, arg3, arg4, arg5, arg6); break; case TARGET_NETBSD_NR_mprotect: - ret = get_errno(target_mprotect(arg1, arg2, arg3)); + ret = do_bsd_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); @@ -538,15 +566,14 @@ abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1, 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)); + ret = do_bsd_mmap(arg1, arg2, arg3, arg4, arg5, arg6); break; case TARGET_OPENBSD_NR_mprotect: - ret = get_errno(target_mprotect(arg1, arg2, arg3)); + ret = do_bsd_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); diff --git a/bsd-user/syscall_defs.h b/bsd-user/syscall_defs.h index a2b0ebe..dea94ef 100644 --- a/bsd-user/syscall_defs.h +++ b/bsd-user/syscall_defs.h @@ -12,4 +12,75 @@ struct target_iovec { abi_long iov_len; /* Number of bytes */ }; +/* + * sys/ipc.h + */ +struct target_ipc_perm { + uint32_t cuid; /* creator user id */ + uint32_t cgid; /* creator group id */ + uint32_t uid; /* user id */ + uint32_t gid; /* group id */ + uint16_t mode; /* r/w permission */ + uint16_t seq; /* sequence # */ + abi_long key; /* user specified msg/sem/shm key */ +}; + +/* + * sys/shm.h + */ +struct target_shmid_ds { + struct target_ipc_perm shm_perm; /* peration permission structure */ + abi_ulong shm_segsz; /* size of segment in bytes */ + int32_t shm_lpid; /* process ID of last shared memory op */ + int32_t shm_cpid; /* process ID of creator */ + int32_t shm_nattch; /* number of current attaches */ + abi_ulong shm_atime; /* time of last shmat() */ + abi_ulong shm_dtime; /* time of last shmdt() */ + abi_ulong shm_ctime; /* time of last change by shmctl() */ +}; + +#define N_BSD_SHM_REGIONS 32 +struct bsd_shm_regions { + abi_long start; + abi_long size; +}; + +/* + * sys/mman.h + */ +#define TARGET_FREEBSD_MAP_RESERVED0080 0x0080 /* previously misimplemented + MAP_INHERIT */ +#define TARGET_FREEBSD_MAP_RESERVED0100 0x0100 /* previously unimplemented + MAP_NOEXTEND */ +#define TARGET_FREEBSD_MAP_STACK 0x0400 /* region grows down, like a + stack */ +#define TARGET_FREEBSD_MAP_NOSYNC 0x0800 /* page to but do not sync + underlying file */ + +#define TARGET_FREEBSD_MAP_FLAGMASK 0x1ff7 + +#define TARGET_NETBSD_MAP_INHERIT 0x0080 /* region is retained after + exec */ +#define TARGET_NETBSD_MAP_TRYFIXED 0x0400 /* attempt hint address, even + within break */ +#define TARGET_NETBSD_MAP_WIRED 0x0800 /* mlock() mapping when it is + established */ + +#define TARGET_NETBSD_MAP_STACK 0x2000 /* allocated from memory, swap + space (stack) */ + +#define TARGET_NETBSD_MAP_FLAGMASK 0x3ff7 + +#define TARGET_OPENBSD_MAP_INHERIT 0x0080 /* region is retained after + exec */ +#define TARGET_OPENBSD_MAP_NOEXTEND 0x0100 /* for MAP_FILE, don't change + file size */ +#define TARGET_OPENBSD_MAP_TRYFIXED 0x0400 /* attempt hint address, + even within heap */ + +#define TARGET_OPENBSD_MAP_FLAGMASK 0x17f7 + +/* XXX */ +#define TARGET_BSD_MAP_FLAGMASK 0x3ff7 + #endif /* ! _SYSCALL_DEFS_H_ */ -- 1.7.8