Index: qemu-0.9.0/linux-user/syscall.c =================================================================== --- qemu-0.9.0.orig/linux-user/syscall.c +++ qemu-0.9.0/linux-user/syscall.c @@ -185,6 +185,9 @@ extern int getresgid(gid_t *, gid_t *, g extern int setgroups(int, gid_t *); extern int uselib(const char*); +#include "exec-all.h" +long mmap_lock; + static inline long get_errno(long ret) { if (ret == -1) @@ -227,9 +235,11 @@ long do_brk(target_ulong new_brk) /* We need to allocate more memory after the brk... */ new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1); + spin_lock(&mmap_lock); mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0)); + spin_unlock(&mmap_lock); if (is_error(mapped_addr)) { return mapped_addr; } else { @@ -2133,6 +2133,7 @@ static long do_futex(target_ulong uaddr, struct timespec host_utime; unsigned long val2 = utime; + spin_lock(&mmap_lock); if (utime && (op == FUTEX_WAIT || op == FUTEX_LOCK_PI)) { target_to_host_timespec(&host_utime, utime); val2 = (unsigned long)&host_utime; @@ -2230,6 +2265,7 @@ static long do_futex(target_ulong uaddr, } #endif #endif + spin_unlock(&mmap_lock); return syscall(__NR_futex, g2h(uaddr), op, val, val2, g2h(uaddr2), val3); } @@ -2985,15 +3021,19 @@ long do_syscall(void *cpu_env, int num, v5 = tswapl(v[4]); v6 = tswapl(v[5]); unlock_user(v, arg1, 0); + spin_lock(&mmap_lock); ret = get_errno(target_mmap(v1, v2, v3, target_to_host_bitmask(v4, mmap_flags_tbl), v5, v6)); + spin_unlock(&mmap_lock); } #else + spin_lock(&mmap_lock); ret = get_errno(target_mmap(arg1, arg2, arg3, target_to_host_bitmask(arg4, mmap_flags_tbl), arg5, arg6)); + spin_unlock(&mmap_lock); #endif break; #ifdef TARGET_NR_mmap2 @@ -3003,36 +3043,54 @@ long do_syscall(void *cpu_env, int num, #else #define MMAP_SHIFT TARGET_PAGE_BITS #endif + spin_lock(&mmap_lock); ret = get_errno(target_mmap(arg1, arg2, arg3, target_to_host_bitmask(arg4, mmap_flags_tbl), arg5, arg6 << MMAP_SHIFT)); + spin_unlock(&mmap_lock); break; #endif case TARGET_NR_munmap: + spin_lock(&mmap_lock); ret = get_errno(target_munmap(arg1, arg2)); + spin_unlock(&mmap_lock); break; case TARGET_NR_mprotect: + spin_lock(&mmap_lock); ret = get_errno(target_mprotect(arg1, arg2, arg3)); + spin_unlock(&mmap_lock); break; case TARGET_NR_mremap: + spin_lock(&mmap_lock); ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5)); + spin_unlock(&mmap_lock); break; /* ??? msync/mlock/munlock are broken for softmmu. */ case TARGET_NR_msync: + spin_lock(&mmap_lock); ret = get_errno(msync(g2h(arg1), arg2, arg3)); + spin_unlock(&mmap_lock); break; case TARGET_NR_mlock: + spin_lock(&mmap_lock); ret = get_errno(mlock(g2h(arg1), arg2)); + spin_unlock(&mmap_lock); break; case TARGET_NR_munlock: + spin_lock(&mmap_lock); ret = get_errno(munlock(g2h(arg1), arg2)); + spin_unlock(&mmap_lock); break; case TARGET_NR_mlockall: + spin_lock(&mmap_lock); ret = get_errno(mlockall(arg1)); + spin_unlock(&mmap_lock); break; case TARGET_NR_munlockall: + spin_lock(&mmap_lock); ret = get_errno(munlockall()); + spin_unlock(&mmap_lock); break; case TARGET_NR_truncate: p = lock_user_string(arg1); Index: qemu-0.9.0/exec.c =================================================================== --- qemu-0.9.0.orig/exec.c +++ qemu-0.9.0/exec.c @@ -1676,6 +1684,50 @@ void page_dump(FILE *f) } } +/* dump memory mappings */ +target_ulong page_find_end() +{ + unsigned long start, end; + int i, j, prot, prot1; + void *firsttb; + PageDesc *p; + target_ulong last = 0; + + start = -1; + end = -1; + prot = 0; + for(i = 0; i <= L1_SIZE; i++) { + if (i < L1_SIZE) + p = l1_map[i]; + else + p = NULL; + for(j = 0;j < L2_SIZE; j++) { + if (!p) { + firsttb = NULL; + prot1 = 0; + } + else { + prot1 = p[j].flags; + firsttb = p[j].first_tb; + } + if (prot1 != prot) { + end = (i << (32 - L1_BITS)) | (j << TARGET_PAGE_BITS); + if (start != -1) { + last = end; + } + if (prot1 != 0) + start = end; + else + start = -1; + prot = prot1; + } + if (!p) + break; + } + } + return last; +} + int page_get_flags(target_ulong address) { PageDesc *p; Index: qemu-0.9.0/linux-user/mmap.c =================================================================== --- qemu-0.9.0.orig/linux-user/mmap.c +++ qemu-0.9.0/linux-user/mmap.c @@ -48,8 +48,14 @@ int target_mprotect(target_ulong start, end = start + len; if (end < start) return -EINVAL; - if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) - return -EINVAL; + if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) { +#ifdef DEBUG_MMAP + gemu_log("mprotect: ERROR (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)\n"); +#endif + // dirty hack to get mplayer running (sets PROT_GROWSDOWN) we just ignore advanced flags + prot &= (PROT_READ | PROT_WRITE | PROT_EXEC); +// return -EINVAL; + } if (len == 0) return 0; @@ -205,9 +233,23 @@ long target_mmap(target_ulong start, tar defined(__ia64) || defined(__CYGWIN__) /* tell the kenel to search at the same place as i386 */ if (real_start == 0) { - real_start = last_start; - last_start += HOST_PAGE_ALIGN(len); + target_ulong curend = page_find_end(); + + if(curend > last_start) { +#ifdef DEBUG_MMAP + gemu_log("qemu: set last_start from %p to %p\n", last_start, curend + HOST_PAGE_ALIGN(len)); fflush(stdout); fflush(stderr); +#endif + last_start = curend; +#ifdef DEBUG_MMAP + } else { + gemu_log("qemu: curend(%p) <= last_start(%p)\n", curend, last_start); fflush(stdout); fflush(stderr); +#endif + } + + real_start = last_start; + last_start += HOST_PAGE_ALIGN(len); } + #endif if (0 && qemu_host_page_size != qemu_real_host_page_size) { /* NOTE: this code is only for debugging with '-p' option */