#include "qemu.h"
#include "qemu/guest-random.h"
+#include "user/syscall-trace.h"
#include "qapi/error.h"
#include "fd-trans.h"
return -TARGET_EFAULT;
ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
break;
+#ifdef SOL_NETLINK
+ case SOL_NETLINK:
+ switch (optname) {
+ case NETLINK_PKTINFO:
+ case NETLINK_ADD_MEMBERSHIP:
+ case NETLINK_DROP_MEMBERSHIP:
+ case NETLINK_BROADCAST_ERROR:
+ case NETLINK_NO_ENOBUFS:
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
+ case NETLINK_LISTEN_ALL_NSID:
+ case NETLINK_CAP_ACK:
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+ case NETLINK_EXT_ACK:
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
+ case NETLINK_GET_STRICT_CHK:
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
+ break;
+ default:
+ goto unimplemented;
+ }
+ val = 0;
+ if (optlen < sizeof(uint32_t)) {
+ return -TARGET_EINVAL;
+ }
+ if (get_user_u32(val, optval_addr)) {
+ return -TARGET_EFAULT;
+ }
+ ret = get_errno(setsockopt(sockfd, SOL_NETLINK, optname, &val,
+ sizeof(val)));
+ break;
+#endif /* SOL_NETLINK */
default:
unimplemented:
gemu_log("Unsupported setsockopt level=%d optname=%d\n", level, optname);
break;
}
break;
+#ifdef SOL_NETLINK
+ case SOL_NETLINK:
+ switch (optname) {
+ case NETLINK_PKTINFO:
+ case NETLINK_BROADCAST_ERROR:
+ case NETLINK_NO_ENOBUFS:
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
+ case NETLINK_LISTEN_ALL_NSID:
+ case NETLINK_CAP_ACK:
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+ case NETLINK_EXT_ACK:
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
+ case NETLINK_GET_STRICT_CHK:
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
+ if (get_user_u32(len, optlen)) {
+ return -TARGET_EFAULT;
+ }
+ if (len != sizeof(val)) {
+ return -TARGET_EINVAL;
+ }
+ lv = len;
+ ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
+ if (ret < 0) {
+ return ret;
+ }
+ if (put_user_u32(lv, optlen)
+ || put_user_u32(val, optval_addr)) {
+ return -TARGET_EFAULT;
+ }
+ break;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
+ case NETLINK_LIST_MEMBERSHIPS:
+ {
+ uint32_t *results;
+ int i;
+ if (get_user_u32(len, optlen)) {
+ return -TARGET_EFAULT;
+ }
+ if (len < 0) {
+ return -TARGET_EINVAL;
+ }
+ results = lock_user(VERIFY_WRITE, optval_addr, len, 1);
+ if (!results) {
+ return -TARGET_EFAULT;
+ }
+ lv = len;
+ ret = get_errno(getsockopt(sockfd, level, optname, results, &lv));
+ if (ret < 0) {
+ unlock_user(results, optval_addr, 0);
+ return ret;
+ }
+ /* swap host endianess to target endianess. */
+ for (i = 0; i < (len / sizeof(uint32_t)); i++) {
+ results[i] = tswap32(results[i]);
+ }
+ if (put_user_u32(lv, optlen)) {
+ return -TARGET_EFAULT;
+ }
+ unlock_user(results, optval_addr, 0);
+ break;
+ }
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) */
+ default:
+ goto unimplemented;
+ }
+ break;
+#endif /* SOL_NETLINK */
default:
unimplemented:
gemu_log("getsockopt level=%d optname=%d not yet supported\n",
/* we create a new CPU instance. */
new_env = cpu_copy(env);
/* Init regs that differ from the parent. */
- cpu_clone_regs(new_env, newsp);
+ cpu_clone_regs_child(new_env, newsp, flags);
+ cpu_clone_regs_parent(env, flags);
new_cpu = env_cpu(new_env);
new_cpu->opaque = ts;
ts->bprm = parent_ts->bprm;
ret = fork();
if (ret == 0) {
/* Child Process. */
- cpu_clone_regs(env, newsp);
+ cpu_clone_regs_child(env, newsp, flags);
fork_end(1);
/* There is a race condition here. The parent process could
theoretically read the TID in the child process before the child
if (flags & CLONE_CHILD_CLEARTID)
ts->child_tidptr = child_tidptr;
} else {
+ cpu_clone_regs_parent(env, flags);
fork_end(0);
}
}
__put_user(host_stx->stx_attributes_mask, &target_stx->stx_attributes_mask);
__put_user(host_stx->stx_atime.tv_sec, &target_stx->stx_atime.tv_sec);
__put_user(host_stx->stx_atime.tv_nsec, &target_stx->stx_atime.tv_nsec);
- __put_user(host_stx->stx_btime.tv_sec, &target_stx->stx_atime.tv_sec);
- __put_user(host_stx->stx_btime.tv_nsec, &target_stx->stx_atime.tv_nsec);
- __put_user(host_stx->stx_ctime.tv_sec, &target_stx->stx_atime.tv_sec);
- __put_user(host_stx->stx_ctime.tv_nsec, &target_stx->stx_atime.tv_nsec);
- __put_user(host_stx->stx_mtime.tv_sec, &target_stx->stx_atime.tv_sec);
- __put_user(host_stx->stx_mtime.tv_nsec, &target_stx->stx_atime.tv_nsec);
+ __put_user(host_stx->stx_btime.tv_sec, &target_stx->stx_btime.tv_sec);
+ __put_user(host_stx->stx_btime.tv_nsec, &target_stx->stx_btime.tv_nsec);
+ __put_user(host_stx->stx_ctime.tv_sec, &target_stx->stx_ctime.tv_sec);
+ __put_user(host_stx->stx_ctime.tv_nsec, &target_stx->stx_ctime.tv_nsec);
+ __put_user(host_stx->stx_mtime.tv_sec, &target_stx->stx_mtime.tv_sec);
+ __put_user(host_stx->stx_mtime.tv_nsec, &target_stx->stx_mtime.tv_nsec);
__put_user(host_stx->stx_rdev_major, &target_stx->stx_rdev_major);
__put_user(host_stx->stx_rdev_minor, &target_stx->stx_rdev_minor);
__put_user(host_stx->stx_dev_major, &target_stx->stx_dev_major);
#ifdef TARGET_NR_stime /* not on alpha */
case TARGET_NR_stime:
{
- time_t host_time;
- if (get_user_sal(host_time, arg1))
+ struct timespec ts;
+ ts.tv_nsec = 0;
+ if (get_user_sal(ts.tv_sec, arg1)) {
return -TARGET_EFAULT;
- return get_errno(stime(&host_time));
+ }
+ return get_errno(clock_settime(CLOCK_REALTIME, &ts));
}
#endif
#ifdef TARGET_NR_alarm /* not on alpha */
aarch64_sve_narrow_vq(env, vq);
}
env->vfp.zcr_el[1] = vq - 1;
+ arm_rebuild_hflags(env);
ret = vq * 16;
}
return ret;
}
#endif
- trace_guest_user_syscall(cpu, num, arg1, arg2, arg3, arg4,
- arg5, arg6, arg7, arg8);
+ record_syscall_start(cpu, num, arg1,
+ arg2, arg3, arg4, arg5, arg6, arg7, arg8);
if (unlikely(do_strace)) {
print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
arg5, arg6, arg7, arg8);
}
- trace_guest_user_syscall_ret(cpu, num, ret);
+ record_syscall_return(cpu, num, ret);
return ret;
}