qemu-bionic-on-focal-fixes.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From e798b6737a803f5b656e5be93bf4aa8d26df54b0 Mon Sep 17 00:00:00 2001 | |
From: Luqman Aden <me@luqman.ca> | |
Date: Tue, 15 Dec 2020 16:34:07 -0800 | |
Subject: [PATCH] Luqman: Changes to work with newer linux & glibc found on | |
focal. | |
--- | |
linux-user/ioctls.h | 21 ++++- | |
linux-user/syscall.c | 167 +++++++++++++++++++++++++++---------- | |
linux-user/syscall_defs.h | 31 ++++++- | |
linux-user/syscall_types.h | 6 -- | |
4 files changed, 171 insertions(+), 54 deletions(-) | |
diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h | |
index 35cad6f94..512e3f8b4 100644 | |
--- a/linux-user/ioctls.h | |
+++ b/linux-user/ioctls.h | |
@@ -170,8 +170,25 @@ | |
IOCTL(SIOCGRARP, IOC_R, MK_PTR(MK_STRUCT(STRUCT_arpreq))) | |
IOCTL(SIOCGIWNAME, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_char_ifreq))) | |
IOCTL(SIOCGPGRP, IOC_R, MK_PTR(TYPE_INT)) /* pid_t */ | |
- IOCTL(SIOCGSTAMP, IOC_R, MK_PTR(MK_STRUCT(STRUCT_timeval))) | |
- IOCTL(SIOCGSTAMPNS, IOC_R, MK_PTR(MK_STRUCT(STRUCT_timespec))) | |
+ | |
+ /* | |
+ * We can't use IOCTL_SPECIAL() because it will set | |
+ * host_cmd to XXX_OLD and XXX_NEW and these macros | |
+ * are not defined with kernel prior to 5.2. | |
+ * We must set host_cmd to the same value as in target_cmd | |
+ * otherwise the consistency check in syscall_init() | |
+ * will trigger an error. | |
+ * host_cmd is ignored by the do_ioctl_XXX() helpers. | |
+ * FIXME: create a macro to define this kind of entry | |
+ */ | |
+ { TARGET_SIOCGSTAMP_OLD, TARGET_SIOCGSTAMP_OLD, | |
+"SIOCGSTAMP_OLD", IOC_R, do_ioctl_SIOCGSTAMP }, | |
+ { TARGET_SIOCGSTAMPNS_OLD, TARGET_SIOCGSTAMPNS_OLD, | |
+"SIOCGSTAMPNS_OLD", IOC_R, do_ioctl_SIOCGSTAMPNS }, | |
+ { TARGET_SIOCGSTAMP_NEW, TARGET_SIOCGSTAMP_NEW, | |
+"SIOCGSTAMP_NEW", IOC_R, do_ioctl_SIOCGSTAMP }, | |
+ { TARGET_SIOCGSTAMPNS_NEW, TARGET_SIOCGSTAMPNS_NEW, | |
+"SIOCGSTAMPNS_NEW", IOC_R, do_ioctl_SIOCGSTAMPNS }, | |
IOCTL(RNDGETENTCNT, IOC_R, MK_PTR(TYPE_INT)) | |
IOCTL(RNDADDTOENTCNT, IOC_W, MK_PTR(TYPE_INT)) | |
diff --git a/linux-user/syscall.c b/linux-user/syscall.c | |
index 11c9116c4..b4f2322fc 100644 | |
--- a/linux-user/syscall.c | |
+++ b/linux-user/syscall.c | |
@@ -41,6 +41,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base, | |
size_t stack_size, int flags, void *arg, ...); | |
#endif | |
#include <sys/socket.h> | |
+#include <linux/sockios.h> | |
#include <sys/un.h> | |
#include <sys/uio.h> | |
#include <poll.h> | |
@@ -256,15 +257,9 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \ | |
#define TARGET_NR__llseek TARGET_NR_llseek | |
#endif | |
-#ifdef __NR_gettid | |
-_syscall0(int, gettid) | |
-#else | |
-/* This is a replacement for the host gettid() and must return a host | |
- errno. */ | |
-static int gettid(void) { | |
- return -ENOSYS; | |
-} | |
-#endif | |
+#define __NR_sys_gettid __NR_gettid | |
+_syscall0(int, sys_gettid) | |
+ | |
#if defined(TARGET_NR_getdents) && defined(__NR_getdents) | |
_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count); | |
#endif | |
@@ -1345,8 +1340,9 @@ static inline abi_long copy_from_user_timeval(struct timeval *tv, | |
{ | |
struct target_timeval *target_tv; | |
- if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1)) | |
+ if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1)) { | |
return -TARGET_EFAULT; | |
+ } | |
__get_user(tv->tv_sec, &target_tv->tv_sec); | |
__get_user(tv->tv_usec, &target_tv->tv_usec); | |
@@ -1361,8 +1357,9 @@ static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr, | |
{ | |
struct target_timeval *target_tv; | |
- if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0)) | |
+ if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0)) { | |
return -TARGET_EFAULT; | |
+ } | |
__put_user(tv->tv_sec, &target_tv->tv_sec); | |
__put_user(tv->tv_usec, &target_tv->tv_usec); | |
@@ -1372,6 +1369,65 @@ static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr, | |
return 0; | |
} | |
+static inline abi_long copy_to_user_timeval64(abi_ulong target_tv_addr, | |
+ const struct timeval *tv) | |
+{ | |
+ struct target__kernel_sock_timeval *target_tv; | |
+ | |
+ if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0)) { | |
+ return -TARGET_EFAULT; | |
+ } | |
+ | |
+ __put_user(tv->tv_sec, &target_tv->tv_sec); | |
+ __put_user(tv->tv_usec, &target_tv->tv_usec); | |
+ | |
+ unlock_user_struct(target_tv, target_tv_addr, 1); | |
+ | |
+ return 0; | |
+} | |
+ | |
+static inline abi_long target_to_host_timespec(struct timespec *host_ts, | |
+ abi_ulong target_addr) | |
+{ | |
+ struct target_timespec *target_ts; | |
+ | |
+ if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1)) { | |
+ return -TARGET_EFAULT; | |
+ } | |
+ __get_user(host_ts->tv_sec, &target_ts->tv_sec); | |
+ __get_user(host_ts->tv_nsec, &target_ts->tv_nsec); | |
+ unlock_user_struct(target_ts, target_addr, 0); | |
+ return 0; | |
+} | |
+ | |
+static inline abi_long host_to_target_timespec(abi_ulong target_addr, | |
+ struct timespec *host_ts) | |
+{ | |
+ struct target_timespec *target_ts; | |
+ | |
+ if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) { | |
+ return -TARGET_EFAULT; | |
+ } | |
+ __put_user(host_ts->tv_sec, &target_ts->tv_sec); | |
+ __put_user(host_ts->tv_nsec, &target_ts->tv_nsec); | |
+ unlock_user_struct(target_ts, target_addr, 1); | |
+ return 0; | |
+} | |
+ | |
+static inline abi_long host_to_target_timespec64(abi_ulong target_addr, | |
+ struct timespec *host_ts) | |
+{ | |
+ struct target__kernel_timespec *target_ts; | |
+ | |
+ if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) { | |
+ return -TARGET_EFAULT; | |
+ } | |
+ __put_user(host_ts->tv_sec, &target_ts->tv_sec); | |
+ __put_user(host_ts->tv_nsec, &target_ts->tv_nsec); | |
+ unlock_user_struct(target_ts, target_addr, 1); | |
+ return 0; | |
+} | |
+ | |
static inline abi_long copy_from_user_timezone(struct timezone *tz, | |
abi_ulong target_tz_addr) | |
{ | |
@@ -5607,6 +5663,54 @@ static abi_long do_ioctl_kdsigaccept(const IOCTLEntry *ie, uint8_t *buf_temp, | |
return get_errno(safe_ioctl(fd, ie->host_cmd, sig)); | |
} | |
+static abi_long do_ioctl_SIOCGSTAMP(const IOCTLEntry *ie, uint8_t *buf_temp, | |
+ int fd, int cmd, abi_long arg) | |
+{ | |
+ struct timeval tv; | |
+ abi_long ret; | |
+ | |
+ ret = get_errno(safe_ioctl(fd, SIOCGSTAMP, &tv)); | |
+ if (is_error(ret)) { | |
+ return ret; | |
+ } | |
+ | |
+ if (cmd == (int)TARGET_SIOCGSTAMP_OLD) { | |
+ if (copy_to_user_timeval(arg, &tv)) { | |
+ return -TARGET_EFAULT; | |
+ } | |
+ } else { | |
+ if (copy_to_user_timeval64(arg, &tv)) { | |
+ return -TARGET_EFAULT; | |
+ } | |
+ } | |
+ | |
+ return ret; | |
+} | |
+ | |
+static abi_long do_ioctl_SIOCGSTAMPNS(const IOCTLEntry *ie, uint8_t *buf_temp, | |
+ int fd, int cmd, abi_long arg) | |
+{ | |
+ struct timespec ts; | |
+ abi_long ret; | |
+ | |
+ ret = get_errno(safe_ioctl(fd, SIOCGSTAMPNS, &ts)); | |
+ if (is_error(ret)) { | |
+ return ret; | |
+ } | |
+ | |
+ if (cmd == (int)TARGET_SIOCGSTAMPNS_OLD) { | |
+ if (host_to_target_timespec(arg, &ts)) { | |
+ return -TARGET_EFAULT; | |
+ } | |
+ } else{ | |
+ if (host_to_target_timespec64(arg, &ts)) { | |
+ return -TARGET_EFAULT; | |
+ } | |
+ } | |
+ | |
+ return ret; | |
+} | |
+ | |
static IOCTLEntry ioctl_entries[] = { | |
#define IOCTL(cmd, access, ...) \ | |
{ TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } }, | |
@@ -6246,7 +6350,7 @@ static void *clone_func(void *arg) | |
cpu = ENV_GET_CPU(env); | |
thread_cpu = cpu; | |
ts = (TaskState *)cpu->opaque; | |
- info->tid = gettid(); | |
+ info->tid = sys_gettid(); | |
task_settid(ts); | |
if (info->child_tidptr) | |
put_user_u32(info->tid, info->child_tidptr); | |
@@ -6390,9 +6494,9 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, | |
mapping. We can't repeat the spinlock hack used above because | |
the child process gets its own copy of the lock. */ | |
if (flags & CLONE_CHILD_SETTID) | |
- put_user_u32(gettid(), child_tidptr); | |
+ put_user_u32(sys_gettid(), child_tidptr); | |
if (flags & CLONE_PARENT_SETTID) | |
- put_user_u32(gettid(), parent_tidptr); | |
+ put_user_u32(sys_gettid(), parent_tidptr); | |
ts = (TaskState *)cpu->opaque; | |
if (flags & CLONE_SETTLS) | |
cpu_set_tls (env, newtls); | |
@@ -6906,32 +7010,6 @@ static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1, | |
} | |
#endif | |
-static inline abi_long target_to_host_timespec(struct timespec *host_ts, | |
- abi_ulong target_addr) | |
-{ | |
- struct target_timespec *target_ts; | |
- | |
- if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1)) | |
- return -TARGET_EFAULT; | |
- __get_user(host_ts->tv_sec, &target_ts->tv_sec); | |
- __get_user(host_ts->tv_nsec, &target_ts->tv_nsec); | |
- unlock_user_struct(target_ts, target_addr, 0); | |
- return 0; | |
-} | |
- | |
-static inline abi_long host_to_target_timespec(abi_ulong target_addr, | |
- struct timespec *host_ts) | |
-{ | |
- struct target_timespec *target_ts; | |
- | |
- if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) | |
- return -TARGET_EFAULT; | |
- __put_user(host_ts->tv_sec, &target_ts->tv_sec); | |
- __put_user(host_ts->tv_nsec, &target_ts->tv_nsec); | |
- unlock_user_struct(target_ts, target_addr, 1); | |
- return 0; | |
-} | |
- | |
static inline abi_long target_to_host_itimerspec(struct itimerspec *host_itspec, | |
abi_ulong target_addr) | |
{ | |
@@ -8179,10 +8257,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, | |
#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)) | |
goto efault; | |
- ret = get_errno(stime(&host_time)); | |
+ ret = get_errno(clock_settime(CLOCK_REALTIME, &ts)); | |
} | |
break; | |
#endif | |
@@ -11454,7 +11533,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, | |
break; | |
#endif | |
case TARGET_NR_gettid: | |
- ret = get_errno(gettid()); | |
+ ret = get_errno(sys_gettid()); | |
break; | |
#ifdef TARGET_NR_readahead | |
case TARGET_NR_readahead: | |
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h | |
index bec3680b9..45b781995 100644 | |
--- a/linux-user/syscall_defs.h | |
+++ b/linux-user/syscall_defs.h | |
@@ -202,16 +202,34 @@ struct target_ip_mreq_source { | |
uint32_t imr_sourceaddr; | |
}; | |
+#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) | |
+struct target_timeval { | |
+ abi_long tv_sec; | |
+ abi_int tv_usec; | |
+}; | |
+#define target__kernel_sock_timeval target_timeval | |
+#else | |
struct target_timeval { | |
abi_long tv_sec; | |
abi_long tv_usec; | |
}; | |
+struct target__kernel_sock_timeval { | |
+ abi_llong tv_sec; | |
+ abi_llong tv_usec; | |
+}; | |
+#endif | |
+ | |
struct target_timespec { | |
abi_long tv_sec; | |
abi_long tv_nsec; | |
}; | |
+struct target__kernel_timespec { | |
+ abi_llong tv_sec; | |
+ abi_llong tv_nsec; | |
+}; | |
+ | |
struct target_timezone { | |
abi_int tz_minuteswest; | |
abi_int tz_dsttime; | |
@@ -1014,8 +1032,17 @@ struct target_pollfd { | |
#define TARGET_SIOCATMARK 0x8905 | |
#define TARGET_SIOCGPGRP 0x8904 | |
#endif | |
-#define TARGET_SIOCGSTAMP 0x8906 /* Get stamp (timeval) */ | |
-#define TARGET_SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */ | |
+ | |
+#if defined(TARGET_SH4) | |
+#define TARGET_SIOCGSTAMP_OLD TARGET_IOR('s', 100, struct target_timeval) | |
+#define TARGET_SIOCGSTAMPNS_OLD TARGET_IOR('s', 101, struct target_timespec) | |
+#else | |
+#define TARGET_SIOCGSTAMP_OLD 0x8906 | |
+#define TARGET_SIOCGSTAMPNS_OLD 0x8907 | |
+#endif | |
+ | |
+#define TARGET_SIOCGSTAMP_NEW TARGET_IOR(0x89, 0x06, abi_llong[2]) | |
+#define TARGET_SIOCGSTAMPNS_NEW TARGET_IOR(0x89, 0x07, abi_llong[2]) | |
/* Networking ioctls */ | |
#define TARGET_SIOCADDRT 0x890B /* add routing table entry */ | |
diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h | |
index 24631b09b..5fc32e268 100644 | |
--- a/linux-user/syscall_types.h | |
+++ b/linux-user/syscall_types.h | |
@@ -14,12 +14,6 @@ STRUCT(serial_icounter_struct, | |
STRUCT(sockaddr, | |
TYPE_SHORT, MK_ARRAY(TYPE_CHAR, 14)) | |
-STRUCT(timeval, | |
- MK_ARRAY(TYPE_LONG, 2)) | |
- | |
-STRUCT(timespec, | |
- MK_ARRAY(TYPE_LONG, 2)) | |
- | |
STRUCT(rtentry, | |
TYPE_ULONG, MK_STRUCT(STRUCT_sockaddr), MK_STRUCT(STRUCT_sockaddr), MK_STRUCT(STRUCT_sockaddr), | |
TYPE_SHORT, TYPE_SHORT, TYPE_ULONG, TYPE_PTRVOID, TYPE_SHORT, TYPE_PTRVOID, | |
-- | |
2.25.1 | |