diff options
Diffstat (limited to 'linux-user/syscall.c')
-rw-r--r-- | linux-user/syscall.c | 92 |
1 files changed, 71 insertions, 21 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c index c930577686..8d27d10807 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -111,6 +111,7 @@ #include <linux/netlink.h> #include <linux/if_alg.h> #include <linux/rtc.h> +#include <sound/asound.h> #include "linux_loop.h" #include "uname.h" @@ -334,6 +335,9 @@ _syscall5(int, kcmp, pid_t, pid1, pid_t, pid2, int, type, _syscall5(int, sys_statx, int, dirfd, const char *, pathname, int, flags, unsigned int, mask, struct target_statx *, statxbuf) #endif +#if defined(TARGET_NR_membarrier) && defined(__NR_membarrier) +_syscall2(int, membarrier, int, cmd, int, flags) +#endif static bitmask_transtbl fcntl_flags_tbl[] = { { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, }, @@ -1560,7 +1564,11 @@ static inline abi_long target_to_host_cmsg(struct msghdr *msgh, * something more intelligent than "twice the size of the * target buffer we're reading from". */ - gemu_log("Host cmsg overflow\n"); + qemu_log_mask(LOG_UNIMP, + ("Unsupported ancillary data %d/%d: " + "unhandled msg size\n"), + tswap32(target_cmsg->cmsg_level), + tswap32(target_cmsg->cmsg_type)); break; } @@ -1590,8 +1598,8 @@ static inline abi_long target_to_host_cmsg(struct msghdr *msgh, __get_user(cred->uid, &target_cred->uid); __get_user(cred->gid, &target_cred->gid); } else { - gemu_log("Unsupported ancillary data: %d/%d\n", - cmsg->cmsg_level, cmsg->cmsg_type); + qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n", + cmsg->cmsg_level, cmsg->cmsg_type); memcpy(data, target_data, len); } @@ -1812,8 +1820,8 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh, default: unimplemented: - gemu_log("Unsupported ancillary data: %d/%d\n", - cmsg->cmsg_level, cmsg->cmsg_type); + qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n", + cmsg->cmsg_level, cmsg->cmsg_type); memcpy(target_data, data, MIN(len, tgt_len)); if (tgt_len > len) { memset(target_data + len, 0, tgt_len - len); @@ -2288,7 +2296,8 @@ set_timeout: #endif /* SOL_NETLINK */ default: unimplemented: - gemu_log("Unsupported setsockopt level=%d optname=%d\n", level, optname); + qemu_log_mask(LOG_UNIMP, "Unsupported setsockopt level=%d optname=%d\n", + level, optname); ret = -TARGET_ENOPROTOOPT; } return ret; @@ -2307,10 +2316,42 @@ static abi_long do_getsockopt(int sockfd, int level, int optname, level = SOL_SOCKET; switch (optname) { /* These don't just return a single integer */ - case TARGET_SO_RCVTIMEO: - case TARGET_SO_SNDTIMEO: case TARGET_SO_PEERNAME: goto unimplemented; + case TARGET_SO_RCVTIMEO: { + struct timeval tv; + socklen_t tvlen; + + optname = SO_RCVTIMEO; + +get_timeout: + if (get_user_u32(len, optlen)) { + return -TARGET_EFAULT; + } + if (len < 0) { + return -TARGET_EINVAL; + } + + tvlen = sizeof(tv); + ret = get_errno(getsockopt(sockfd, level, optname, + &tv, &tvlen)); + if (ret < 0) { + return ret; + } + if (len > sizeof(struct target_timeval)) { + len = sizeof(struct target_timeval); + } + if (copy_to_user_timeval(optval_addr, &tv)) { + return -TARGET_EFAULT; + } + if (put_user_u32(len, optlen)) { + return -TARGET_EFAULT; + } + break; + } + case TARGET_SO_SNDTIMEO: + optname = SO_SNDTIMEO; + goto get_timeout; case TARGET_SO_PEERCRED: { struct ucred cr; socklen_t crlen; @@ -2663,8 +2704,9 @@ static abi_long do_getsockopt(int sockfd, int level, int optname, #endif /* SOL_NETLINK */ default: unimplemented: - gemu_log("getsockopt level=%d optname=%d not yet supported\n", - level, optname); + qemu_log_mask(LOG_UNIMP, + "getsockopt level=%d optname=%d not yet supported\n", + level, optname); ret = -TARGET_EOPNOTSUPP; break; } @@ -3419,7 +3461,7 @@ static abi_long do_socketcall(int num, abi_ulong vptr) case TARGET_SYS_SENDMMSG: /* sockfd, msgvec, vlen, flags */ return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 1); default: - gemu_log("Unsupported socketcall: %d\n", num); + qemu_log_mask(LOG_UNIMP, "Unsupported socketcall: %d\n", num); return -TARGET_EINVAL; } } @@ -4330,7 +4372,8 @@ static abi_long do_ipc(CPUArchState *cpu_env, ret = do_shmctl(first, second, ptr); break; default: - gemu_log("Unsupported ipc call: %d (version %d)\n", call, version); + qemu_log_mask(LOG_UNIMP, "Unsupported ipc call: %d (version %d)\n", + call, version); ret = -TARGET_ENOSYS; break; } @@ -5178,7 +5221,8 @@ static abi_long do_ioctl(int fd, int cmd, abi_long arg) ie = ioctl_entries; for(;;) { if (ie->target_cmd == 0) { - gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd); + qemu_log_mask( + LOG_UNIMP, "Unsupported ioctl: cmd=0x%04lx\n", (long)cmd); return -TARGET_ENOSYS; } if (ie->target_cmd == cmd) @@ -5246,8 +5290,9 @@ static abi_long do_ioctl(int fd, int cmd, abi_long arg) } break; default: - gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n", - (long)cmd, arg_type[0]); + qemu_log_mask(LOG_UNIMP, + "Unsupported ioctl type: cmd=0x%04lx type=%d\n", + (long)cmd, arg_type[0]); ret = -TARGET_ENOSYS; break; } @@ -12090,6 +12135,10 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, unlock_user(p, arg1, 0); return ret; #endif +#if defined TARGET_NR_membarrier && defined __NR_membarrier + case TARGET_NR_membarrier: + return get_errno(membarrier(arg1, arg2)); +#endif default: qemu_log_mask(LOG_UNIMP, "Unsupported syscall: %d\n", num); @@ -12123,14 +12172,15 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, record_syscall_start(cpu, num, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); - if (unlikely(do_strace)) { + if (unlikely(qemu_loglevel_mask(LOG_STRACE))) { print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6); - ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4, - arg5, arg6, arg7, arg8); + } + + ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4, + arg5, arg6, arg7, arg8); + + if (unlikely(qemu_loglevel_mask(LOG_STRACE))) { print_syscall_ret(num, ret); - } else { - ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4, - arg5, arg6, arg7, arg8); } record_syscall_return(cpu, num, ret); |