diff options
| author | Peter Maydell <peter.maydell@linaro.org> | 2020-07-06 11:40:10 +0100 |
|---|---|---|
| committer | Peter Maydell <peter.maydell@linaro.org> | 2020-07-06 11:40:10 +0100 |
| commit | 7623b5ba017f61de5d7c2bba12c6feb3d55091b1 (patch) | |
| tree | c6f2cd490f2acd9f6592a5bb5fd748a4ba2072a9 /linux-user/syscall.c | |
| parent | eb6490f544388dd24c0d054a96dd304bc7284450 (diff) | |
| parent | 8f902c540eccd72086e8f67d977e30e05659783f (diff) | |
| download | focaccia-qemu-7623b5ba017f61de5d7c2bba12c6feb3d55091b1.tar.gz focaccia-qemu-7623b5ba017f61de5d7c2bba12c6feb3d55091b1.zip | |
Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-5.1-pull-request' into staging
linux-user pull request 2020-07-02 Update linux-user maintainer Improve strace output for some syscalls Display contents of ioctl() parameters Fix sparc64 flushw operation # gpg: Signature made Sat 04 Jul 2020 17:25:21 BST # gpg: using RSA key CD2F75DDC8E3A4DC2E4F5173F30C38BD3F2FBE3C # gpg: issuer "laurent@vivier.eu" # gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [full] # gpg: aka "Laurent Vivier <laurent@vivier.eu>" [full] # gpg: aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [full] # Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F 5173 F30C 38BD 3F2F BE3C * remotes/vivier2/tags/linux-user-for-5.1-pull-request: MAINTAINERS: update linux-user maintainer linux-user: Add strace support for printing arguments of ioctl() linux-user: Add thunk argument types for SIOCGSTAMP and SIOCGSTAMPNS linux-user: Add strace support for printing arguments of fallocate() linux-user: Add strace support for printing arguments of chown()/lchown() linux-user: Add strace support for printing arguments of lseek() linux-user: Add strace support for printing argument of syscalls used for extended attributes linux-user: Add strace support for a group of syscalls linux-user: Extend strace support to enable argument printing after syscall execution linux-user: syscall: ioctls: support DRM_IOCTL_VERSION linux-user/sparc64: Fix the handling of window spill trap target/sparc: Translate flushw opcode Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'linux-user/syscall.c')
| -rw-r--r-- | linux-user/syscall.c | 136 |
1 files changed, 100 insertions, 36 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 97de9fb5c9..82afadcea0 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -112,6 +112,9 @@ #include <linux/if_alg.h> #include <linux/rtc.h> #include <sound/asound.h> +#ifdef HAVE_DRM_H +#include <libdrm/drm.h> +#endif #include "linux_loop.h" #include "uname.h" @@ -4478,24 +4481,6 @@ STRUCT_MAX #undef STRUCT #undef STRUCT_SPECIAL -typedef struct IOCTLEntry IOCTLEntry; - -typedef abi_long do_ioctl_fn(const IOCTLEntry *ie, uint8_t *buf_temp, - int fd, int cmd, abi_long arg); - -struct IOCTLEntry { - int target_cmd; - unsigned int host_cmd; - const char *name; - int access; - do_ioctl_fn *do_ioctl; - const argtype arg_type[5]; -}; - -#define IOC_R 0x0001 -#define IOC_W 0x0002 -#define IOC_RW (IOC_R | IOC_W) - #define MAX_STRUCT_SIZE 4096 #ifdef CONFIG_FIEMAP @@ -5276,7 +5261,102 @@ static abi_long do_ioctl_tiocgptpeer(const IOCTLEntry *ie, uint8_t *buf_temp, } #endif -static IOCTLEntry ioctl_entries[] = { +#ifdef HAVE_DRM_H + +static void unlock_drm_version(struct drm_version *host_ver, + struct target_drm_version *target_ver, + bool copy) +{ + unlock_user(host_ver->name, target_ver->name, + copy ? host_ver->name_len : 0); + unlock_user(host_ver->date, target_ver->date, + copy ? host_ver->date_len : 0); + unlock_user(host_ver->desc, target_ver->desc, + copy ? host_ver->desc_len : 0); +} + +static inline abi_long target_to_host_drmversion(struct drm_version *host_ver, + struct target_drm_version *target_ver) +{ + memset(host_ver, 0, sizeof(*host_ver)); + + __get_user(host_ver->name_len, &target_ver->name_len); + if (host_ver->name_len) { + host_ver->name = lock_user(VERIFY_WRITE, target_ver->name, + target_ver->name_len, 0); + if (!host_ver->name) { + return -EFAULT; + } + } + + __get_user(host_ver->date_len, &target_ver->date_len); + if (host_ver->date_len) { + host_ver->date = lock_user(VERIFY_WRITE, target_ver->date, + target_ver->date_len, 0); + if (!host_ver->date) { + goto err; + } + } + + __get_user(host_ver->desc_len, &target_ver->desc_len); + if (host_ver->desc_len) { + host_ver->desc = lock_user(VERIFY_WRITE, target_ver->desc, + target_ver->desc_len, 0); + if (!host_ver->desc) { + goto err; + } + } + + return 0; +err: + unlock_drm_version(host_ver, target_ver, false); + return -EFAULT; +} + +static inline void host_to_target_drmversion( + struct target_drm_version *target_ver, + struct drm_version *host_ver) +{ + __put_user(host_ver->version_major, &target_ver->version_major); + __put_user(host_ver->version_minor, &target_ver->version_minor); + __put_user(host_ver->version_patchlevel, &target_ver->version_patchlevel); + __put_user(host_ver->name_len, &target_ver->name_len); + __put_user(host_ver->date_len, &target_ver->date_len); + __put_user(host_ver->desc_len, &target_ver->desc_len); + unlock_drm_version(host_ver, target_ver, true); +} + +static abi_long do_ioctl_drm(const IOCTLEntry *ie, uint8_t *buf_temp, + int fd, int cmd, abi_long arg) +{ + struct drm_version *ver; + struct target_drm_version *target_ver; + abi_long ret; + + switch (ie->host_cmd) { + case DRM_IOCTL_VERSION: + if (!lock_user_struct(VERIFY_WRITE, target_ver, arg, 0)) { + return -TARGET_EFAULT; + } + ver = (struct drm_version *)buf_temp; + ret = target_to_host_drmversion(ver, target_ver); + if (!is_error(ret)) { + ret = get_errno(safe_ioctl(fd, ie->host_cmd, ver)); + if (is_error(ret)) { + unlock_drm_version(ver, target_ver, false); + } else { + host_to_target_drmversion(target_ver, ver); + } + } + unlock_user_struct(target_ver, arg, 0); + return ret; + } + return -TARGET_ENOSYS; +} + +#endif + +IOCTLEntry ioctl_entries[] = { #define IOCTL(cmd, access, ...) \ { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } }, #define IOCTL_SPECIAL(cmd, access, dofn, ...) \ @@ -6614,22 +6694,6 @@ void syscall_init(void) } } -#if TARGET_ABI_BITS == 32 -static inline uint64_t target_offset64(uint32_t word0, uint32_t word1) -{ -#ifdef TARGET_WORDS_BIGENDIAN - return ((uint64_t)word0 << 32) | word1; -#else - return ((uint64_t)word1 << 32) | word0; -#endif -} -#else /* TARGET_ABI_BITS == 32 */ -static inline uint64_t target_offset64(uint64_t word0, uint64_t word1) -{ - return word0; -} -#endif /* TARGET_ABI_BITS != 32 */ - #ifdef TARGET_NR_truncate64 static inline abi_long target_truncate64(void *cpu_env, const char *arg1, abi_long arg2, @@ -12467,7 +12531,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, arg5, arg6, arg7, arg8); if (unlikely(qemu_loglevel_mask(LOG_STRACE))) { - print_syscall_ret(num, ret); + print_syscall_ret(num, ret, arg1, arg2, arg3, arg4, arg5, arg6); } record_syscall_return(cpu, num, ret); |