diff --git a/linux-user/main.c b/linux-user/main.c index 52b5a618fe..ea00dd9057 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -78,14 +78,7 @@ int have_guest_base; # endif #endif -/* That said, reserving *too* much vm space via mmap can run into problems - with rlimits, oom due to page table creation, etc. We will still try it, - if directed by the command-line option, but not by default. */ -#if HOST_LONG_BITS == 64 && TARGET_VIRT_ADDR_SPACE_BITS <= 32 -unsigned long reserved_va = MAX_RESERVED_VA; -#else unsigned long reserved_va; -#endif static void usage(int exitcode); @@ -672,6 +665,18 @@ int main(int argc, char **argv, char **envp) /* init tcg before creating CPUs and to get qemu_host_page_size */ tcg_exec_init(0); + /* Reserving *too* much vm space via mmap can run into problems + with rlimits, oom due to page table creation, etc. We will still try it, + if directed by the command-line option, but not by default. */ + if (HOST_LONG_BITS == 64 && + TARGET_VIRT_ADDR_SPACE_BITS <= 32 && + reserved_va == 0) { + /* reserved_va must be aligned with the host page size + * as it is used with mmap() + */ + reserved_va = MAX_RESERVED_VA & qemu_host_page_mask; + } + cpu = cpu_create(cpu_type); env = cpu->env_ptr; cpu_reset(cpu); diff --git a/linux-user/syscall.c b/linux-user/syscall.c index e4b1b7d7da..3df3bdffb2 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -3843,6 +3843,8 @@ static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp, } msg.msg_controllen = 2 * tswapal(msgp->msg_controllen); msg.msg_control = alloca(msg.msg_controllen); + memset(msg.msg_control, 0, msg.msg_controllen); + msg.msg_flags = tswap32(msgp->msg_flags); count = tswapal(msgp->msg_iovlen); @@ -6545,63 +6547,97 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, /* warning : doesn't handle linux specific flags... */ static int target_to_host_fcntl_cmd(int cmd) { + int ret; + switch(cmd) { - case TARGET_F_DUPFD: - case TARGET_F_GETFD: - case TARGET_F_SETFD: - case TARGET_F_GETFL: - case TARGET_F_SETFL: - return cmd; - case TARGET_F_GETLK: - return F_GETLK64; - case TARGET_F_SETLK: - return F_SETLK64; - case TARGET_F_SETLKW: - return F_SETLKW64; - case TARGET_F_GETOWN: - return F_GETOWN; - case TARGET_F_SETOWN: - return F_SETOWN; - case TARGET_F_GETSIG: - return F_GETSIG; - case TARGET_F_SETSIG: - return F_SETSIG; + case TARGET_F_DUPFD: + case TARGET_F_GETFD: + case TARGET_F_SETFD: + case TARGET_F_GETFL: + case TARGET_F_SETFL: + ret = cmd; + break; + case TARGET_F_GETLK: + ret = F_GETLK64; + break; + case TARGET_F_SETLK: + ret = F_SETLK64; + break; + case TARGET_F_SETLKW: + ret = F_SETLKW64; + break; + case TARGET_F_GETOWN: + ret = F_GETOWN; + break; + case TARGET_F_SETOWN: + ret = F_SETOWN; + break; + case TARGET_F_GETSIG: + ret = F_GETSIG; + break; + case TARGET_F_SETSIG: + ret = F_SETSIG; + break; #if TARGET_ABI_BITS == 32 - case TARGET_F_GETLK64: - return F_GETLK64; - case TARGET_F_SETLK64: - return F_SETLK64; - case TARGET_F_SETLKW64: - return F_SETLKW64; + case TARGET_F_GETLK64: + ret = F_GETLK64; + break; + case TARGET_F_SETLK64: + ret = F_SETLK64; + break; + case TARGET_F_SETLKW64: + ret = F_SETLKW64; + break; #endif - case TARGET_F_SETLEASE: - return F_SETLEASE; - case TARGET_F_GETLEASE: - return F_GETLEASE; + case TARGET_F_SETLEASE: + ret = F_SETLEASE; + break; + case TARGET_F_GETLEASE: + ret = F_GETLEASE; + break; #ifdef F_DUPFD_CLOEXEC - case TARGET_F_DUPFD_CLOEXEC: - return F_DUPFD_CLOEXEC; + case TARGET_F_DUPFD_CLOEXEC: + ret = F_DUPFD_CLOEXEC; + break; #endif - case TARGET_F_NOTIFY: - return F_NOTIFY; + case TARGET_F_NOTIFY: + ret = F_NOTIFY; + break; #ifdef F_GETOWN_EX - case TARGET_F_GETOWN_EX: - return F_GETOWN_EX; + case TARGET_F_GETOWN_EX: + ret = F_GETOWN_EX; + break; #endif #ifdef F_SETOWN_EX - case TARGET_F_SETOWN_EX: - return F_SETOWN_EX; + case TARGET_F_SETOWN_EX: + ret = F_SETOWN_EX; + break; #endif #ifdef F_SETPIPE_SZ - case TARGET_F_SETPIPE_SZ: - return F_SETPIPE_SZ; - case TARGET_F_GETPIPE_SZ: - return F_GETPIPE_SZ; + case TARGET_F_SETPIPE_SZ: + ret = F_SETPIPE_SZ; + break; + case TARGET_F_GETPIPE_SZ: + ret = F_GETPIPE_SZ; + break; #endif - default: - return -TARGET_EINVAL; + default: + ret = -TARGET_EINVAL; + break; } - return -TARGET_EINVAL; + +#if defined(__powerpc64__) + /* On PPC64, glibc headers has the F_*LK* defined to 12, 13 and 14 and + * is not supported by kernel. The glibc fcntl call actually adjusts + * them to 5, 6 and 7 before making the syscall(). Since we make the + * syscall directly, adjust to what is supported by the kernel. + */ + if (ret >= F_GETLK64 && ret <= F_SETLKW64) { + ret -= F_GETLK64 - 5; + } +#endif + + return ret; } #define FLOCK_TRANSTBL \ @@ -11730,7 +11766,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, if (ret) { break; } - ret = get_errno(fcntl(arg1, cmd, &fl)); + ret = get_errno(safe_fcntl(arg1, cmd, &fl)); if (ret == 0) { ret = copyto(arg3, &fl); }