summaryrefslogtreecommitdiffstats
path: root/linux-user/syscall.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux-user/syscall.c')
-rw-r--r--linux-user/syscall.c92
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);