[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 12/18] bsd-user: add support for memory management r
From: |
Stacey Son |
Subject: |
[Qemu-devel] [PATCH 12/18] bsd-user: add support for memory management related system calls |
Date: |
Wed, 16 Oct 2013 09:37:06 -0500 |
This change adds support or stubs for memory management related system calls
including mmap(2), munmap(2), mprotect(2), msync(2), mlock(2), munlock(2),
mlockall(2), munlockall(2), madvise(2), minherit(2), mincore(2), shm_open(2),
shm_unlink(2), shmget(2), shmctl(2), shmat(2), shmdt(2), vadvise(), sbrk(),
sstk(),
and freebsd6_mmap().
Signed-off-by: Stacey Son <address@hidden>
---
bsd-user/Makefile.objs | 2 +-
bsd-user/bsd-mem.c | 122 +++++++++++++++
bsd-user/bsd-mem.h | 393 ++++++++++++++++++++++++++++++++++++++++++++++++
bsd-user/mmap.c | 160 +++++---------------
bsd-user/qemu-bsd.h | 10 ++
bsd-user/qemu.h | 3 +-
bsd-user/syscall.c | 174 +++++++++++++---------
7 files changed, 670 insertions(+), 194 deletions(-)
create mode 100644 bsd-user/bsd-mem.c
create mode 100644 bsd-user/bsd-mem.h
diff --git a/bsd-user/Makefile.objs b/bsd-user/Makefile.objs
index ee70866..1a33a6d 100644
--- a/bsd-user/Makefile.objs
+++ b/bsd-user/Makefile.objs
@@ -1,5 +1,5 @@
obj-y = main.o bsdload.o elfload.o mmap.o signal.o strace.o syscall.o \
- uaccess.o bsd-proc.o \
+ uaccess.o bsd-mem.o bsd-proc.o \
$(HOST_ABI_DIR)/os-proc.o \
$(HOST_ABI_DIR)/os-stat.o \
$(HOST_ABI_DIR)/os-sys.o \
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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+#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..88c01ec
--- /dev/null
+++ b/bsd-user/bsd-mem.h
@@ -0,0 +1,393 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+/*--
+ * 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 <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/mman.h>
+#include <sys/shm.h>
+#include <fcntl.h>
+
+#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(void *cpu_env, abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6, abi_long arg7,
+ abi_long arg8)
+{
+
+ if (regpairs_aligned(cpu_env) != 0) {
+ arg6 = arg7;
+ arg7 = arg8;
+ }
+ return get_errno(target_mmap(arg1, arg2, arg3,
+ target_to_host_bitmask(arg4, mmap_flags_tbl), arg5,
+ target_offset64(arg6, arg7)));
+}
+
+/* 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/mmap.c b/bsd-user/mmap.c
index aae8ea1..f8ef423 100644
--- a/bsd-user/mmap.c
+++ b/bsd-user/mmap.c
@@ -1,4 +1,4 @@
-/*
+/**
* mmap support for qemu
*
* Copyright (c) 2003 - 2008 Fabrice Bellard
@@ -26,44 +26,9 @@
#include "qemu.h"
#include "qemu-common.h"
-#include "bsd-mman.h"
-//#define DEBUG_MMAP
+// #define DEBUG_MMAP
-#if defined(CONFIG_USE_NPTL)
-pthread_mutex_t mmap_mutex;
-static int __thread mmap_lock_count;
-
-void mmap_lock(void)
-{
- if (mmap_lock_count++ == 0) {
- pthread_mutex_lock(&mmap_mutex);
- }
-}
-
-void mmap_unlock(void)
-{
- if (--mmap_lock_count == 0) {
- pthread_mutex_unlock(&mmap_mutex);
- }
-}
-
-/* Grab lock to make sure things are in a consistent state after fork(). */
-void mmap_fork_start(void)
-{
- if (mmap_lock_count)
- abort();
- pthread_mutex_lock(&mmap_mutex);
-}
-
-void mmap_fork_end(int child)
-{
- if (child)
- pthread_mutex_init(&mmap_mutex, NULL);
- else
- pthread_mutex_unlock(&mmap_mutex);
-}
-#else
/* We aren't threadsafe to start with, so no need to worry about locking. */
void mmap_lock(void)
{
@@ -72,67 +37,6 @@ 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;
-}
/* NOTE: all the constants are the HOST ones, but addresses are target. */
int target_mprotect(abi_ulong start, abi_ulong len, int prot)
@@ -164,11 +68,11 @@ int target_mprotect(abi_ulong start, abi_ulong len, int
prot)
if (start > host_start) {
/* handle host page containing start */
prot1 = prot;
- for(addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) {
+ for (addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) {
prot1 |= page_get_flags(addr);
}
if (host_end == host_start + qemu_host_page_size) {
- for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
+ for (addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
prot1 |= page_get_flags(addr);
}
end = host_end;
@@ -180,7 +84,7 @@ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
}
if (end < host_end) {
prot1 = prot;
- for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
+ for (addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
prot1 |= page_get_flags(addr);
}
ret = mprotect(g2h(host_end - qemu_host_page_size),
qemu_host_page_size,
@@ -218,7 +122,7 @@ static int mmap_frag(abi_ulong real_start,
/* get the protection of the target pages outside the mapping */
prot1 = 0;
- for(addr = real_start; addr < real_end; addr++) {
+ for (addr = real_start; addr < real_end; addr++) {
if (addr < start || addr >= end)
prot1 |= page_get_flags(addr);
}
@@ -275,7 +179,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;
@@ -300,9 +204,9 @@ static abi_ulong mmap_find_vma(abi_ulong start, abi_ulong
size)
if (addr == 0)
addr = mmap_next_start;
addr_start = addr;
- for(;;) {
+ for (;;) {
prot = 0;
- for(addr1 = addr; addr1 < (addr + size); addr1 += TARGET_PAGE_SIZE) {
+ for (addr1 = addr; addr1 < (addr + size); addr1 += TARGET_PAGE_SIZE) {
prot |= page_get_flags(addr1);
}
if (prot == 0)
@@ -319,9 +223,10 @@ static abi_ulong mmap_find_vma(abi_ulong start, abi_ulong
size)
/* NOTE: all the constants are the HOST ones */
abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
- int flags, int fd, abi_ulong offset)
+ int flags, int fd, off_t offset)
{
- abi_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len;
+ abi_ulong ret, end, real_start, real_end, retaddr, host_len;
+ off_t host_offset;
unsigned long host_start;
mmap_lock();
@@ -337,21 +242,30 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int
prot,
printf("MAP_FIXED ");
if (flags & MAP_ANON)
printf("MAP_ANON ");
- switch(flags & TARGET_BSD_MAP_FLAGMASK) {
- case MAP_PRIVATE:
- printf("MAP_PRIVATE ");
- break;
- case MAP_SHARED:
- printf("MAP_SHARED ");
- break;
- default:
- printf("[MAP_FLAGMASK=0x%x] ", flags & TARGET_BSD_MAP_FLAGMASK);
- break;
- }
- printf("fd=%d offset=" TARGET_FMT_lx "\n", fd, offset);
+ if (flags & MAP_PRIVATE)
+ printf("MAP_PRIVATE ");
+ if (flags & MAP_SHARED)
+ printf("MAP_SHARED ");
+ if (flags & MAP_NOCORE)
+ printf("MAP_NOCORE ");
+#ifdef MAP_STACK
+ if (flags & MAP_STACK)
+ printf("MAP_STACK ");
+#endif
+ printf("fd=%d offset=0x%llx\n", fd, offset);
}
#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;
@@ -396,7 +310,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int
prot,
end = start + len;
real_end = HOST_PAGE_ALIGN(end);
- for(addr = real_start; addr < real_end; addr += TARGET_PAGE_SIZE) {
+ for (addr = real_start; addr < real_end; addr += TARGET_PAGE_SIZE) {
flg = page_get_flags(addr);
if (flg & PAGE_RESERVED) {
errno = ENXIO;
@@ -508,11 +422,11 @@ int target_munmap(abi_ulong start, abi_ulong len)
if (start > real_start) {
/* handle host page containing start */
prot = 0;
- for(addr = real_start; addr < start; addr += TARGET_PAGE_SIZE) {
+ for (addr = real_start; addr < start; addr += TARGET_PAGE_SIZE) {
prot |= page_get_flags(addr);
}
if (real_end == real_start + qemu_host_page_size) {
- for(addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) {
+ for (addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) {
prot |= page_get_flags(addr);
}
end = real_end;
@@ -522,7 +436,7 @@ int target_munmap(abi_ulong start, abi_ulong len)
}
if (end < real_end) {
prot = 0;
- for(addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) {
+ for (addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) {
prot |= page_get_flags(addr);
}
if (prot != 0)
diff --git a/bsd-user/qemu-bsd.h b/bsd-user/qemu-bsd.h
index 590c36b..f562aad 100644
--- a/bsd-user/qemu-bsd.h
+++ b/bsd-user/qemu-bsd.h
@@ -32,6 +32,16 @@
#include <sys/wait.h>
#include <netinet/in.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);
+
/* bsd-proc.c */
int target_to_host_resource(int code);
rlim_t target_to_host_rlim(abi_ulong target_rlim);
diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
index e668a67..613a89e 100644
--- a/bsd-user/qemu.h
+++ b/bsd-user/qemu.h
@@ -219,7 +219,7 @@ void QEMU_NORETURN force_sig(int target_sig);
/* mmap.c */
int target_mprotect(abi_ulong start, abi_ulong len, int prot);
abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
- int flags, int fd, abi_ulong offset);
+ int flags, int fd, off_t offset);
int target_munmap(abi_ulong start, abi_ulong len);
abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
abi_ulong new_size, unsigned long flags,
@@ -228,6 +228,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 633d638..e3967fa 100644
--- a/bsd-user/syscall.c
+++ b/bsd-user/syscall.c
@@ -17,22 +17,16 @@
* 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 <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
#include <time.h>
-#include <limits.h>
#include <sys/types.h>
-#include <sys/mman.h>
#include <sys/syscall.h>
#include <sys/param.h>
#include <sys/sysctl.h>
-#include <utime.h>
#include "qemu.h"
#include "qemu-common.h"
@@ -42,6 +36,7 @@ static int host_to_target_errno(int err);
/* BSD independent syscall shims */
#include "bsd-file.h"
+#include "bsd-mem.h"
#include "bsd-proc.h"
#include "bsd-signal.h"
@@ -53,19 +48,18 @@ static int host_to_target_errno(int err);
/* #define DEBUG */
-static abi_ulong target_brk;
-static abi_ulong target_original_brk;
-
/*
* errno conversion.
*/
abi_long get_errno(abi_long ret)
{
- if (ret == -1)
+
+ if (ret == -1) {
/* XXX need to translate host -> target errnos here */
return -(errno);
- else
+ } else {
return ret;
+ }
}
static int host_to_target_errno(int err)
@@ -76,46 +70,8 @@ static int host_to_target_errno(int err)
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));
-
- if (!is_error(mapped_addr))
- target_brk = new_brk;
- else
- return mapped_addr;
-
- return 0;
+ return (abi_ulong)ret >= (abi_ulong)(-4096);
}
/* FIXME
@@ -169,6 +125,13 @@ static abi_long unlock_iovec(struct iovec *vec, abi_ulong
target_addr,
return 0;
}
+
+/* stub for arm semihosting support */
+abi_long do_brk(abi_ulong new_brk)
+{
+ return do_obreak(new_brk);
+}
+
/* do_syscall() should always have a single exit point at the end so
that actions, such as logging of syscall results, can be performed.
All errnos that do_syscall() returns must be -TARGET_<errcode>. */
@@ -340,6 +303,7 @@ abi_long do_freebsd_syscall(void *cpu_env, int num,
abi_long arg1,
case TARGET_FREEBSD_NR_getloginclass: /* getloginclass(2) */
ret = do_freebsd_getloginclass(arg1, arg2);
break;
+
#if 0
case TARGET_FREEBSD_NR_pdwait4: /* pdwait4(2) */
ret = do_freebsd_pdwait4(arg1, arg2, arg3, arg4);
@@ -417,6 +381,7 @@ abi_long do_freebsd_syscall(void *cpu_env, int num,
abi_long arg1,
case TARGET_FREEBSD_NR_auditctl: /* auditctl(2) */
ret = do_freebsd_auditctl(arg1);
break;
+
case TARGET_FREEBSD_NR_utrace: /* utrace(2) */
ret = do_bsd_utrace(arg1, arg2);
break;
@@ -434,6 +399,7 @@ abi_long do_freebsd_syscall(void *cpu_env, int num,
abi_long arg1,
break;
+
/*
* File system calls.
*/
@@ -807,20 +773,95 @@ abi_long do_freebsd_syscall(void *cpu_env, int num,
abi_long arg1,
break;
+ /*
+ * Memory management system calls.
+ */
+ case TARGET_FREEBSD_NR_mmap: /* mmap(2) */
+ ret = do_bsd_mmap(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
+ arg8);
+ 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_mmap:
- ret = get_errno(target_mmap(arg1, arg2, arg3,
- target_to_host_bitmask(arg4,
mmap_flags_tbl),
- arg5,
- arg6));
+ case TARGET_FREEBSD_NR_munlock: /* munlock(2) */
+ ret = do_bsd_munlock(arg1, arg2);
break;
- case TARGET_FREEBSD_NR_mprotect:
- ret = get_errno(target_mprotect(arg1, arg2, arg3));
+
+ case TARGET_FREEBSD_NR_mlockall: /* mlockall(2) */
+ ret = do_bsd_mlockall(arg1);
break;
- case TARGET_FREEBSD_NR_break:
- ret = do_obreak(arg1);
+
+ 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_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;
+
+
/*
* time related system calls.
*/
@@ -997,6 +1038,7 @@ abi_long do_freebsd_syscall(void *cpu_env, int num,
abi_long arg1,
arg8));
break;
}
+
#ifdef DEBUG
gemu_log(" = %ld\n", ret);
#endif
@@ -1033,13 +1075,10 @@ abi_long do_netbsd_syscall(void *cpu_env, int num,
abi_long arg1,
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(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6, 0, 0);
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:
@@ -1086,13 +1125,10 @@ abi_long do_openbsd_syscall(void *cpu_env, int num,
abi_long arg1,
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(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6, 0, 0);
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:
--
1.7.8
- [Qemu-devel] [PATCH 02/18] bsd-user: add HOST_ABI_DIR for the various *BSD dependent code., (continued)
- [Qemu-devel] [PATCH 02/18] bsd-user: add HOST_ABI_DIR for the various *BSD dependent code., Stacey Son, 2013/10/16
- [Qemu-devel] [PATCH 06/18] bsd-user: add support for freebsd time related system calls, Stacey Son, 2013/10/16
- [Qemu-devel] [PATCH 05/18] bsd-user: move target arch and host OS dependent code out of syscall.c, Stacey Son, 2013/10/16
- [Qemu-devel] [PATCH 09/18] bsd-user: add support for freebsd process related system calls, Stacey Son, 2013/10/16
- [Qemu-devel] [PATCH 10/18] bsd-user: add support for file system related system calls, Stacey Son, 2013/10/16
- [Qemu-devel] [PATCH 04/18] bsd-user: move target arch and host OS dependent code out of main.c, Stacey Son, 2013/10/16
- [Qemu-devel] [PATCH 11/18] bsd-user: add support for stat, directory, and file control related system calls, Stacey Son, 2013/10/16
- [Qemu-devel] [PATCH 08/18] bsd-user: move target arch and host OS dependent code out of elfload.c, Stacey Son, 2013/10/16
- [Qemu-devel] [PATCH 12/18] bsd-user: add support for memory management related system calls,
Stacey Son <=
- [Qemu-devel] [PATCH 07/18] bsd-user: add support for freebsd signal related system calls, Stacey Son, 2013/10/16
- [Qemu-devel] [PATCH 13/18] bsd-user: add support for socket related system calls, Stacey Son, 2013/10/16
- [Qemu-devel] [PATCH 15/18] bsd-user: add support for the ioctl system call, Stacey Son, 2013/10/16
- [Qemu-devel] [PATCH 14/18] bsd-user: add support for thread related system calls, Stacey Son, 2013/10/16
- [Qemu-devel] [PATCH 17/18] bsd-user: add support for miscellaneous system calls, Stacey Son, 2013/10/16
- [Qemu-devel] [PATCH 16/18] bsd-user: add support for extended attribute and ACL related syscalls, Stacey Son, 2013/10/16
- [Qemu-devel] [PATCH 18/18] bsd-user: add arm, mips and mips64 options to configure target-list, Stacey Son, 2013/10/16