:p
atchew
Login
The following changes since commit 13356edb87506c148b163b8c7eb0695647d00c2a: Merge tag 'block-pull-request' of https://gitlab.com/stefanha/qemu into staging (2023-01-24 09:45:33 +0000) are available in the Git repository at: https://gitlab.com/laurent_vivier/qemu.git tags/linux-user-for-8.0-pull-request for you to fetch changes up to 3f0744f98b07c6fd2ce9d5840726d0915b2ae7c1: linux-user: Allow sendmsg() without IOV (2023-02-03 22:55:12 +0100) ---------------------------------------------------------------- linux-user branch pull request 20230204 Implement execveat() un-parent OBJECT(cpu) when closing thread Revert fix for glibc >= 2.36 sys/mount.h Fix/update strace move target_flat.h to target subdirs Fix SO_ERROR return code of getsockopt() Fix /proc/cpuinfo output for hppa Add emulation for MADV_WIPEONFORK and MADV_KEEPONFORK in madvise() Implement SOL_ALG encryption support linux-user: Allow sendmsg() without IOV ---------------------------------------------------------------- Daniel P. Berrangé (2): Revert "linux-user: add more compat ioctl definitions" Revert "linux-user: fix compat with glibc >= 2.36 sys/mount.h" Drew DeVault (4): linux-user/strace: Extract print_execve_argv() from print_execve() linux-user/strace: Add output for execveat() syscall linux-user/syscall: Extract do_execve() from do_syscall1() linux-user/syscall: Implement execveat() Helge Deller (11): linux-user: Add missing MAP_HUGETLB and MAP_STACK flags in strace linux-user: Add strace output for clock_getres_time64() and futex_time64() linux-user: Improve strace output of getgroups() and setgroups() linux-user: Fix SO_ERROR return code of getsockopt() linux-user: Fix /proc/cpuinfo output for hppa linux-user: Improve strace output of personality() and sysinfo() linux-user: Add emulation for MADV_WIPEONFORK and MADV_KEEPONFORK in madvise() linux-user: Show 4th argument of rt_sigprocmask() in strace linux-user: Enhance strace output for various syscalls linux-user: Implement SOL_ALG encryption support linux-user: Allow sendmsg() without IOV Letu Ren (1): linux-user: add more netlink protocol constants Mike Frysinger (2): linux-user: fix strace build w/out munlockall linux-user: move target_flat.h to target subdirs Philippe Mathieu-Daudé (1): linux-user/strace: Constify struct flags Richard Henderson (1): linux-user: un-parent OBJECT(cpu) when closing thread linux-user/aarch64/target_flat.h | 1 + linux-user/arm/target_flat.h | 1 + linux-user/{ => generic}/target_flat.h | 0 linux-user/m68k/target_flat.h | 1 + linux-user/microblaze/target_flat.h | 1 + linux-user/mmap.c | 56 +++-- linux-user/sh4/target_flat.h | 1 + linux-user/strace.c | 189 ++++++++++----- linux-user/strace.list | 64 ++--- linux-user/syscall.c | 312 +++++++++++++------------ meson.build | 2 - 11 files changed, 378 insertions(+), 250 deletions(-) create mode 100644 linux-user/aarch64/target_flat.h create mode 100644 linux-user/arm/target_flat.h rename linux-user/{ => generic}/target_flat.h (100%) create mode 100644 linux-user/m68k/target_flat.h create mode 100644 linux-user/microblaze/target_flat.h create mode 100644 linux-user/sh4/target_flat.h -- 2.39.1
From: Philippe Mathieu-Daudé <philmd@linaro.org> print_flags() takes a const pointer. Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <20221104173632.1052-2-philmd@linaro.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/strace.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -XXX,XX +XXX,XX @@ print_syscall_ret_ioctl(CPUArchState *cpu_env, const struct syscallname *name, } #endif -UNUSED static struct flags access_flags[] = { +UNUSED static const struct flags access_flags[] = { FLAG_GENERIC(F_OK), FLAG_GENERIC(R_OK), FLAG_GENERIC(W_OK), @@ -XXX,XX +XXX,XX @@ UNUSED static struct flags access_flags[] = { FLAG_END, }; -UNUSED static struct flags at_file_flags[] = { +UNUSED static const struct flags at_file_flags[] = { #ifdef AT_EACCESS FLAG_GENERIC(AT_EACCESS), #endif @@ -XXX,XX +XXX,XX @@ UNUSED static struct flags at_file_flags[] = { FLAG_END, }; -UNUSED static struct flags unlinkat_flags[] = { +UNUSED static const struct flags unlinkat_flags[] = { #ifdef AT_REMOVEDIR FLAG_GENERIC(AT_REMOVEDIR), #endif FLAG_END, }; -UNUSED static struct flags mode_flags[] = { +UNUSED static const struct flags mode_flags[] = { FLAG_GENERIC(S_IFSOCK), FLAG_GENERIC(S_IFLNK), FLAG_GENERIC(S_IFREG), @@ -XXX,XX +XXX,XX @@ UNUSED static struct flags mode_flags[] = { FLAG_END, }; -UNUSED static struct flags open_access_flags[] = { +UNUSED static const struct flags open_access_flags[] = { FLAG_TARGET(O_RDONLY), FLAG_TARGET(O_WRONLY), FLAG_TARGET(O_RDWR), FLAG_END, }; -UNUSED static struct flags open_flags[] = { +UNUSED static const struct flags open_flags[] = { FLAG_TARGET(O_APPEND), FLAG_TARGET(O_CREAT), FLAG_TARGET(O_DIRECTORY), @@ -XXX,XX +XXX,XX @@ UNUSED static struct flags open_flags[] = { FLAG_END, }; -UNUSED static struct flags mount_flags[] = { +UNUSED static const struct flags mount_flags[] = { #ifdef MS_BIND FLAG_GENERIC(MS_BIND), #endif @@ -XXX,XX +XXX,XX @@ UNUSED static struct flags mount_flags[] = { FLAG_END, }; -UNUSED static struct flags umount2_flags[] = { +UNUSED static const struct flags umount2_flags[] = { #ifdef MNT_FORCE FLAG_GENERIC(MNT_FORCE), #endif @@ -XXX,XX +XXX,XX @@ UNUSED static struct flags umount2_flags[] = { FLAG_END, }; -UNUSED static struct flags mmap_prot_flags[] = { +UNUSED static const struct flags mmap_prot_flags[] = { FLAG_GENERIC(PROT_NONE), FLAG_GENERIC(PROT_EXEC), FLAG_GENERIC(PROT_READ), @@ -XXX,XX +XXX,XX @@ UNUSED static struct flags mmap_prot_flags[] = { FLAG_END, }; -UNUSED static struct flags mmap_flags[] = { +UNUSED static const struct flags mmap_flags[] = { FLAG_TARGET(MAP_SHARED), FLAG_TARGET(MAP_PRIVATE), FLAG_TARGET(MAP_ANONYMOUS), @@ -XXX,XX +XXX,XX @@ UNUSED static struct flags mmap_flags[] = { FLAG_END, }; -UNUSED static struct flags clone_flags[] = { +UNUSED static const struct flags clone_flags[] = { FLAG_GENERIC(CLONE_VM), FLAG_GENERIC(CLONE_FS), FLAG_GENERIC(CLONE_FILES), @@ -XXX,XX +XXX,XX @@ UNUSED static struct flags clone_flags[] = { FLAG_END, }; -UNUSED static struct flags msg_flags[] = { +UNUSED static const struct flags msg_flags[] = { /* send */ FLAG_GENERIC(MSG_CONFIRM), FLAG_GENERIC(MSG_DONTROUTE), @@ -XXX,XX +XXX,XX @@ UNUSED static struct flags msg_flags[] = { FLAG_END, }; -UNUSED static struct flags statx_flags[] = { +UNUSED static const struct flags statx_flags[] = { #ifdef AT_EMPTY_PATH FLAG_GENERIC(AT_EMPTY_PATH), #endif @@ -XXX,XX +XXX,XX @@ UNUSED static struct flags statx_flags[] = { FLAG_END, }; -UNUSED static struct flags statx_mask[] = { +UNUSED static const struct flags statx_mask[] = { /* This must come first, because it includes everything. */ #ifdef STATX_ALL FLAG_GENERIC(STATX_ALL), @@ -XXX,XX +XXX,XX @@ UNUSED static struct flags statx_mask[] = { FLAG_END, }; -UNUSED static struct flags falloc_flags[] = { +UNUSED static const struct flags falloc_flags[] = { FLAG_GENERIC(FALLOC_FL_KEEP_SIZE), FLAG_GENERIC(FALLOC_FL_PUNCH_HOLE), #ifdef FALLOC_FL_NO_HIDE_STALE @@ -XXX,XX +XXX,XX @@ UNUSED static struct flags falloc_flags[] = { #endif }; -UNUSED static struct flags termios_iflags[] = { +UNUSED static const struct flags termios_iflags[] = { FLAG_TARGET(IGNBRK), FLAG_TARGET(BRKINT), FLAG_TARGET(IGNPAR), @@ -XXX,XX +XXX,XX @@ UNUSED static struct flags termios_iflags[] = { FLAG_END, }; -UNUSED static struct flags termios_oflags[] = { +UNUSED static const struct flags termios_oflags[] = { FLAG_TARGET(OPOST), FLAG_TARGET(OLCUC), FLAG_TARGET(ONLCR), @@ -XXX,XX +XXX,XX @@ UNUSED static struct enums termios_cflags_CSIZE[] = { ENUM_END, }; -UNUSED static struct flags termios_cflags[] = { +UNUSED static const struct flags termios_cflags[] = { FLAG_TARGET(CSTOPB), FLAG_TARGET(CREAD), FLAG_TARGET(PARENB), @@ -XXX,XX +XXX,XX @@ UNUSED static struct flags termios_cflags[] = { FLAG_END, }; -UNUSED static struct flags termios_lflags[] = { +UNUSED static const struct flags termios_lflags[] = { FLAG_TARGET(ISIG), FLAG_TARGET(ICANON), FLAG_TARGET(XCASE), @@ -XXX,XX +XXX,XX @@ UNUSED static struct flags termios_lflags[] = { FLAG_END, }; -UNUSED static struct flags mlockall_flags[] = { +UNUSED static const struct flags mlockall_flags[] = { FLAG_TARGET(MCL_CURRENT), FLAG_TARGET(MCL_FUTURE), #ifdef MCL_ONFAULT -- 2.39.1
From: Drew DeVault <sir@cmpwn.com> In order to add print_execveat() which re-use common code from print_execve(), extract print_execve_argv() from it. Signed-off-by: Drew DeVault <sir@cmpwn.com> Message-Id: <20221104081015.706009-1-sir@cmpwn.com> [PMD: Split of bigger patch, filled description, fixed style] Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <20221104173632.1052-3-philmd@linaro.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/strace.c | 71 +++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -XXX,XX +XXX,XX @@ print_semctl(CPUArchState *cpu_env, const struct syscallname *name, } #endif -static void -print_execve(CPUArchState *cpu_env, const struct syscallname *name, - abi_long arg1, abi_long arg2, abi_long arg3, - abi_long arg4, abi_long arg5, abi_long arg6) -{ - abi_ulong arg_ptr_addr; - char *s; - - if (!(s = lock_user_string(arg1))) - return; - qemu_log("%s(\"%s\",{", name->name, s); - unlock_user(s, arg1, 0); - - for (arg_ptr_addr = arg2; ; arg_ptr_addr += sizeof(abi_ulong)) { - abi_ulong *arg_ptr, arg_addr; - - arg_ptr = lock_user(VERIFY_READ, arg_ptr_addr, sizeof(abi_ulong), 1); - if (!arg_ptr) - return; - arg_addr = tswapal(*arg_ptr); - unlock_user(arg_ptr, arg_ptr_addr, 0); - if (!arg_addr) - break; - if ((s = lock_user_string(arg_addr))) { - qemu_log("\"%s\",", s); - unlock_user(s, arg_addr, 0); - } - } - - qemu_log("NULL})"); -} - #ifdef TARGET_NR_ipc static void print_ipc(CPUArchState *cpu_env, const struct syscallname *name, @@ -XXX,XX +XXX,XX @@ print_execv(CPUArchState *cpu_env, const struct syscallname *name, } #endif +static void +print_execve_argv(abi_long argv, int last) +{ + abi_ulong arg_ptr_addr; + char *s; + + qemu_log("{"); + for (arg_ptr_addr = argv; ; arg_ptr_addr += sizeof(abi_ulong)) { + abi_ulong *arg_ptr, arg_addr; + + arg_ptr = lock_user(VERIFY_READ, arg_ptr_addr, sizeof(abi_ulong), 1); + if (!arg_ptr) { + return; + } + arg_addr = tswapal(*arg_ptr); + unlock_user(arg_ptr, arg_ptr_addr, 0); + if (!arg_addr) { + break; + } + s = lock_user_string(arg_addr); + if (s) { + qemu_log("\"%s\",", s); + unlock_user(s, arg_addr, 0); + } + } + qemu_log("NULL}%s", get_comma(last)); +} + +static void +print_execve(CPUArchState *cpu_env, const struct syscallname *name, + abi_long arg1, abi_long arg2, abi_long arg3, + abi_long arg4, abi_long arg5, abi_long arg6) +{ + print_syscall_prologue(name); + print_string(arg1, 0); + print_execve_argv(arg2, 1); + print_syscall_epilogue(name); +} + #if defined(TARGET_NR_faccessat) || defined(TARGET_NR_faccessat2) static void print_faccessat(CPUArchState *cpu_env, const struct syscallname *name, -- 2.39.1
From: Drew DeVault <sir@cmpwn.com> Signed-off-by: Drew DeVault <sir@cmpwn.com> Message-Id: <20221104081015.706009-1-sir@cmpwn.com> Suggested-by: Helge Deller <deller@gmx.de> [PMD: Split of bigger patch] Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <20221104173632.1052-4-philmd@linaro.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/strace.c | 23 +++++++++++++++++++++++ linux-user/strace.list | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -XXX,XX +XXX,XX @@ UNUSED static const struct flags clone_flags[] = { FLAG_END, }; +UNUSED static const struct flags execveat_flags[] = { +#ifdef AT_EMPTY_PATH + FLAG_GENERIC(AT_EMPTY_PATH), +#endif +#ifdef AT_SYMLINK_NOFOLLOW + FLAG_GENERIC(AT_SYMLINK_NOFOLLOW), +#endif + FLAG_END, +}; + UNUSED static const struct flags msg_flags[] = { /* send */ FLAG_GENERIC(MSG_CONFIRM), @@ -XXX,XX +XXX,XX @@ print_execve(CPUArchState *cpu_env, const struct syscallname *name, print_syscall_epilogue(name); } +static void +print_execveat(CPUArchState *cpu_env, const struct syscallname *name, + abi_long arg1, abi_long arg2, abi_long arg3, + abi_long arg4, abi_long arg5, abi_long arg6) +{ + print_syscall_prologue(name); + print_at_dirfd(arg1, 0); + print_string(arg2, 0); + print_execve_argv(arg3, 0); + print_flags(execveat_flags, arg5, 1); + print_syscall_epilogue(name); +} + #if defined(TARGET_NR_faccessat) || defined(TARGET_NR_faccessat2) static void print_faccessat(CPUArchState *cpu_env, const struct syscallname *name, diff --git a/linux-user/strace.list b/linux-user/strace.list index XXXXXXX..XXXXXXX 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -XXX,XX +XXX,XX @@ { TARGET_NR_execve, "execve" , NULL, print_execve, NULL }, #endif #ifdef TARGET_NR_execveat -{ TARGET_NR_execveat, "execveat" , NULL, NULL, NULL }, +{ TARGET_NR_execveat, "execveat" , NULL, print_execveat, NULL }, #endif #ifdef TARGET_NR_exec_with_loader { TARGET_NR_exec_with_loader, "exec_with_loader" , NULL, NULL, NULL }, -- 2.39.1
From: Drew DeVault <sir@cmpwn.com> execve() is a particular case of execveat(). In order to add do_execveat(), first factor do_execve() out. Signed-off-by: Drew DeVault <sir@cmpwn.com> Message-Id: <20221104081015.706009-1-sir@cmpwn.com> [PMD: Split of bigger patch, filled description, fixed style] Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <20221104173632.1052-5-philmd@linaro.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/syscall.c | 211 +++++++++++++++++++++++-------------------- 1 file changed, 114 insertions(+), 97 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -XXX,XX +XXX,XX @@ static int do_openat(CPUArchState *cpu_env, int dirfd, const char *pathname, int return safe_openat(dirfd, path(pathname), flags, mode); } +static int do_execve(CPUArchState *cpu_env, + abi_long pathname, abi_long guest_argp, + abi_long guest_envp) +{ + int ret; + char **argp, **envp; + int argc, envc; + abi_ulong gp; + abi_ulong addr; + char **q; + void *p; + + argc = 0; + + for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) { + if (get_user_ual(addr, gp)) { + return -TARGET_EFAULT; + } + if (!addr) { + break; + } + argc++; + } + envc = 0; + for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) { + if (get_user_ual(addr, gp)) { + return -TARGET_EFAULT; + } + if (!addr) { + break; + } + envc++; + } + + argp = g_new0(char *, argc + 1); + envp = g_new0(char *, envc + 1); + + for (gp = guest_argp, q = argp; gp; gp += sizeof(abi_ulong), q++) { + if (get_user_ual(addr, gp)) { + goto execve_efault; + } + if (!addr) { + break; + } + *q = lock_user_string(addr); + if (!*q) { + goto execve_efault; + } + } + *q = NULL; + + for (gp = guest_envp, q = envp; gp; gp += sizeof(abi_ulong), q++) { + if (get_user_ual(addr, gp)) { + goto execve_efault; + } + if (!addr) { + break; + } + *q = lock_user_string(addr); + if (!*q) { + goto execve_efault; + } + } + *q = NULL; + + /* + * Although execve() is not an interruptible syscall it is + * a special case where we must use the safe_syscall wrapper: + * if we allow a signal to happen before we make the host + * syscall then we will 'lose' it, because at the point of + * execve the process leaves QEMU's control. So we use the + * safe syscall wrapper to ensure that we either take the + * signal as a guest signal, or else it does not happen + * before the execve completes and makes it the other + * program's problem. + */ + p = lock_user_string(pathname); + if (!p) { + goto execve_efault; + } + + if (is_proc_myself(p, "exe")) { + ret = get_errno(safe_execve(exec_path, argp, envp)); + } else { + ret = get_errno(safe_execve(p, argp, envp)); + } + + unlock_user(p, pathname, 0); + + goto execve_end; + +execve_efault: + ret = -TARGET_EFAULT; + +execve_end: + for (gp = guest_argp, q = argp; *q; gp += sizeof(abi_ulong), q++) { + if (get_user_ual(addr, gp) || !addr) { + break; + } + unlock_user(*q, addr, 0); + } + for (gp = guest_envp, q = envp; *q; gp += sizeof(abi_ulong), q++) { + if (get_user_ual(addr, gp) || !addr) { + break; + } + unlock_user(*q, addr, 0); + } + + g_free(argp); + g_free(envp); + return ret; +} + #define TIMER_MAGIC 0x0caf0000 #define TIMER_MAGIC_MASK 0xffff0000 @@ -XXX,XX +XXX,XX @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, return ret; #endif case TARGET_NR_execve: - { - char **argp, **envp; - int argc, envc; - abi_ulong gp; - abi_ulong guest_argp; - abi_ulong guest_envp; - abi_ulong addr; - char **q; - - argc = 0; - guest_argp = arg2; - for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) { - if (get_user_ual(addr, gp)) - return -TARGET_EFAULT; - if (!addr) - break; - argc++; - } - envc = 0; - guest_envp = arg3; - for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) { - if (get_user_ual(addr, gp)) - return -TARGET_EFAULT; - if (!addr) - break; - envc++; - } - - argp = g_new0(char *, argc + 1); - envp = g_new0(char *, envc + 1); - - for (gp = guest_argp, q = argp; gp; - gp += sizeof(abi_ulong), q++) { - if (get_user_ual(addr, gp)) - goto execve_efault; - if (!addr) - break; - if (!(*q = lock_user_string(addr))) - goto execve_efault; - } - *q = NULL; - - for (gp = guest_envp, q = envp; gp; - gp += sizeof(abi_ulong), q++) { - if (get_user_ual(addr, gp)) - goto execve_efault; - if (!addr) - break; - if (!(*q = lock_user_string(addr))) - goto execve_efault; - } - *q = NULL; - - if (!(p = lock_user_string(arg1))) - goto execve_efault; - /* Although execve() is not an interruptible syscall it is - * a special case where we must use the safe_syscall wrapper: - * if we allow a signal to happen before we make the host - * syscall then we will 'lose' it, because at the point of - * execve the process leaves QEMU's control. So we use the - * safe syscall wrapper to ensure that we either take the - * signal as a guest signal, or else it does not happen - * before the execve completes and makes it the other - * program's problem. - */ - if (is_proc_myself(p, "exe")) { - ret = get_errno(safe_execve(exec_path, argp, envp)); - } else { - ret = get_errno(safe_execve(p, argp, envp)); - } - unlock_user(p, arg1, 0); - - goto execve_end; - - execve_efault: - ret = -TARGET_EFAULT; - - execve_end: - for (gp = guest_argp, q = argp; *q; - gp += sizeof(abi_ulong), q++) { - if (get_user_ual(addr, gp) - || !addr) - break; - unlock_user(*q, addr, 0); - } - for (gp = guest_envp, q = envp; *q; - gp += sizeof(abi_ulong), q++) { - if (get_user_ual(addr, gp) - || !addr) - break; - unlock_user(*q, addr, 0); - } - - g_free(argp); - g_free(envp); - } - return ret; + return do_execve(cpu_env, arg1, arg2, arg3); case TARGET_NR_chdir: if (!(p = lock_user_string(arg1))) return -TARGET_EFAULT; -- 2.39.1
From: Drew DeVault <sir@cmpwn.com> References: https://gitlab.com/qemu-project/qemu/-/issues/1007 Signed-off-by: Drew DeVault <sir@cmpwn.com> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <20221104081015.706009-1-sir@cmpwn.com> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-Id: <20221104173632.1052-6-philmd@linaro.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/syscall.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -XXX,XX +XXX,XX @@ safe_syscall4(pid_t, wait4, pid_t, pid, int *, status, int, options, \ #endif safe_syscall5(int, waitid, idtype_t, idtype, id_t, id, siginfo_t *, infop, \ int, options, struct rusage *, rusage) -safe_syscall3(int, execve, const char *, filename, char **, argv, char **, envp) +safe_syscall5(int, execveat, int, dirfd, const char *, filename, + char **, argv, char **, envp, int, flags) #if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \ defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64) safe_syscall6(int, pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds, \ @@ -XXX,XX +XXX,XX @@ static int do_openat(CPUArchState *cpu_env, int dirfd, const char *pathname, int return safe_openat(dirfd, path(pathname), flags, mode); } -static int do_execve(CPUArchState *cpu_env, +static int do_execveat(CPUArchState *cpu_env, int dirfd, abi_long pathname, abi_long guest_argp, - abi_long guest_envp) + abi_long guest_envp, int flags) { int ret; char **argp, **envp; @@ -XXX,XX +XXX,XX @@ static int do_execve(CPUArchState *cpu_env, } if (is_proc_myself(p, "exe")) { - ret = get_errno(safe_execve(exec_path, argp, envp)); + ret = get_errno(safe_execveat(dirfd, exec_path, argp, envp, flags)); } else { - ret = get_errno(safe_execve(p, argp, envp)); + ret = get_errno(safe_execveat(dirfd, p, argp, envp, flags)); } unlock_user(p, pathname, 0); @@ -XXX,XX +XXX,XX @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, unlock_user(p, arg2, 0); return ret; #endif + case TARGET_NR_execveat: + return do_execveat(cpu_env, arg1, arg2, arg3, arg4, arg5); case TARGET_NR_execve: - return do_execve(cpu_env, arg1, arg2, arg3); + return do_execveat(cpu_env, AT_FDCWD, arg1, arg2, arg3, 0); case TARGET_NR_chdir: if (!(p = lock_user_string(arg1))) return -TARGET_EFAULT; -- 2.39.1
From: Helge Deller <deller@gmx.de> Add two missing mmap flags. Signed-off-by: Helge Deller <deller@gmx.de> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <Y5iiED4PpnGAHpyz@p100> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/strace.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linux-user/strace.c b/linux-user/strace.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -XXX,XX +XXX,XX @@ UNUSED static const struct flags mmap_flags[] = { #ifdef TARGET_MAP_UNINITIALIZED FLAG_TARGET(MAP_UNINITIALIZED), #endif + FLAG_TARGET(MAP_HUGETLB), + FLAG_TARGET(MAP_STACK), FLAG_END, }; -- 2.39.1
From: Richard Henderson <richard.henderson@linaro.org> This reinstates commit 52f0c1607671293afcdb2acc2f83e9bccbfa74bb: While forcing the CPU to unrealize by hand does trigger the clean-up code we never fully free resources because refcount never reaches zero. This is because QOM automatically added objects without an explicit parent to /unattached/, incrementing the refcount. Instead of manually triggering unrealization just unparent the object and let the device machinery deal with that for us. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/866 Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <20220811151413.3350684-2-alex.bennee@linaro.org> The original patch tickled a problem in target/arm, and was reverted. But that problem is fixed as of commit 3b07a936d3bf. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20230124201019.3935934-1-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/syscall.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -XXX,XX +XXX,XX @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, if (CPU_NEXT(first_cpu)) { TaskState *ts = cpu->opaque; - object_property_set_bool(OBJECT(cpu), "realized", false, NULL); + if (ts->child_tidptr) { + put_user_u32(0, ts->child_tidptr); + do_sys_futex(g2h(cpu, ts->child_tidptr), + FUTEX_WAKE, INT_MAX, NULL, NULL, 0); + } + + object_unparent(OBJECT(cpu)); object_unref(OBJECT(cpu)); /* * At this point the CPU should be unrealized and removed @@ -XXX,XX +XXX,XX @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, pthread_mutex_unlock(&clone_lock); - if (ts->child_tidptr) { - put_user_u32(0, ts->child_tidptr); - do_sys_futex(g2h(cpu, ts->child_tidptr), - FUTEX_WAKE, INT_MAX, NULL, NULL, 0); - } thread_cpu = NULL; g_free(ts); rcu_unregister_thread(); -- 2.39.1
From: Mike Frysinger <vapier@gentoo.org> Signed-off-by: Mike Frysinger <vapier@gentoo.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-Id: <20230118090144.31155-1-vapier@gentoo.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/strace.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -XXX,XX +XXX,XX @@ UNUSED static const struct flags termios_lflags[] = { FLAG_END, }; -UNUSED static const struct flags mlockall_flags[] = { +#ifdef TARGET_NR_mlockall +static const struct flags mlockall_flags[] = { FLAG_TARGET(MCL_CURRENT), FLAG_TARGET(MCL_FUTURE), #ifdef MCL_ONFAULT @@ -XXX,XX +XXX,XX @@ UNUSED static const struct flags mlockall_flags[] = { #endif FLAG_END, }; +#endif /* IDs of the various system clocks */ #define TARGET_CLOCK_REALTIME 0 -- 2.39.1
From: Letu Ren <fantasquex@gmail.com> Currently, qemu strace only prints four protocol contants. This patch adds others listed in "linux/netlink.h". Signed-off-by: Letu Ren <fantasquex@gmail.com> Message-Id: <20230101141105.12024-1-fantasquex@gmail.com> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/strace.c | 48 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/linux-user/strace.c b/linux-user/strace.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -XXX,XX +XXX,XX @@ print_socket_protocol(int domain, int type, int protocol) case NETLINK_ROUTE: qemu_log("NETLINK_ROUTE"); break; + case NETLINK_UNUSED: + qemu_log("NETLINK_UNUSED"); + break; + case NETLINK_USERSOCK: + qemu_log("NETLINK_USERSOCK"); + break; + case NETLINK_FIREWALL: + qemu_log("NETLINK_FIREWALL"); + break; + case NETLINK_SOCK_DIAG: + qemu_log("NETLINK_SOCK_DIAG"); + break; + case NETLINK_NFLOG: + qemu_log("NETLINK_NFLOG"); + break; + case NETLINK_XFRM: + qemu_log("NETLINK_XFRM"); + break; + case NETLINK_SELINUX: + qemu_log("NETLINK_SELINUX"); + break; + case NETLINK_ISCSI: + qemu_log("NETLINK_ISCSI"); + break; case NETLINK_AUDIT: qemu_log("NETLINK_AUDIT"); break; + case NETLINK_FIB_LOOKUP: + qemu_log("NETLINK_FIB_LOOKUP"); + break; + case NETLINK_CONNECTOR: + qemu_log("NETLINK_CONNECTOR"); + break; case NETLINK_NETFILTER: qemu_log("NETLINK_NETFILTER"); break; + case NETLINK_IP6_FW: + qemu_log("NETLINK_IP6_FW"); + break; + case NETLINK_DNRTMSG: + qemu_log("NETLINK_DNRTMSG"); + break; case NETLINK_KOBJECT_UEVENT: qemu_log("NETLINK_KOBJECT_UEVENT"); break; + case NETLINK_GENERIC: + qemu_log("NETLINK_GENERIC"); + break; + case NETLINK_SCSITRANSPORT: + qemu_log("NETLINK_SCSITRANSPORT"); + break; + case NETLINK_ECRYPTFS: + qemu_log("NETLINK_ECRYPTFS"); + break; case NETLINK_RDMA: qemu_log("NETLINK_RDMA"); break; case NETLINK_CRYPTO: qemu_log("NETLINK_CRYPTO"); break; + case NETLINK_SMC: + qemu_log("NETLINK_SMC"); + break; default: qemu_log("%d", protocol); break; -- 2.39.1
From: Daniel P. Berrangé <berrange@redhat.com> This reverts commit c5495f4ecb0cdaaf2e9dddeb48f1689cdb520ca0. glibc has fixed (in 2.36.9000-40-g774058d729) the problem that caused a clash when both sys/mount.h annd linux/mount.h are included, and backported this to the 2.36 stable release too: https://sourceware.org/glibc/wiki/Release/2.36#Usage_of_.3Clinux.2Fmount.h.3E_and_.3Csys.2Fmount.h.3E It is saner for QEMU to remove the workaround it applied for glibc 2.36 and expect distros to ship the 2.36 maint release with the fix. This avoids needing to add a further workaround to QEMU to deal with the fact that linux/brtfs.h now also pulls in linux/mount.h via linux/fs.h since Linux 6.1 Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-Id: <20230110174901.2580297-2-berrange@redhat.com> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/syscall.c | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -XXX,XX +XXX,XX @@ #define FS_IOC32_SETFLAGS _IOW('f', 2, int) #define FS_IOC32_GETVERSION _IOR('v', 1, int) #define FS_IOC32_SETVERSION _IOW('v', 2, int) - -#define BLKGETSIZE64 _IOR(0x12,114,size_t) -#define BLKDISCARD _IO(0x12,119) -#define BLKIOMIN _IO(0x12,120) -#define BLKIOOPT _IO(0x12,121) -#define BLKALIGNOFF _IO(0x12,122) -#define BLKPBSZGET _IO(0x12,123) -#define BLKDISCARDZEROES _IO(0x12,124) -#define BLKSECDISCARD _IO(0x12,125) -#define BLKROTATIONAL _IO(0x12,126) -#define BLKZEROOUT _IO(0x12,127) - -#define FIBMAP _IO(0x00,1) -#define FIGETBSZ _IO(0x00,2) - -struct file_clone_range { - __s64 src_fd; - __u64 src_offset; - __u64 src_length; - __u64 dest_offset; -}; - -#define FICLONE _IOW(0x94, 9, int) -#define FICLONERANGE _IOW(0x94, 13, struct file_clone_range) - #else #include <linux/fs.h> #endif -- 2.39.1
From: Daniel P. Berrangé <berrange@redhat.com> This reverts commit 3cd3df2a9584e6f753bb62a0028bd67124ab5532. glibc has fixed (in 2.36.9000-40-g774058d729) the problem that caused a clash when both sys/mount.h annd linux/mount.h are included, and backported this to the 2.36 stable release too: https://sourceware.org/glibc/wiki/Release/2.36#Usage_of_.3Clinux.2Fmount.h.3E_and_.3Csys.2Fmount.h.3E It is saner for QEMU to remove the workaround it applied for glibc 2.36 and expect distros to ship the 2.36 maint release with the fix. This avoids needing to add a further workaround to QEMU to deal with the fact that linux/brtfs.h now also pulls in linux/mount.h via linux/fs.h since Linux 6.1 Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-Id: <20230110174901.2580297-3-berrange@redhat.com> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/syscall.c | 18 ------------------ meson.build | 2 -- 2 files changed, 20 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -XXX,XX +XXX,XX @@ #include <linux/soundcard.h> #include <linux/kd.h> #include <linux/mtio.h> - -#ifdef HAVE_SYS_MOUNT_FSCONFIG -/* - * glibc >= 2.36 linux/mount.h conflicts with sys/mount.h, - * which in turn prevents use of linux/fs.h. So we have to - * define the constants ourselves for now. - */ -#define FS_IOC_GETFLAGS _IOR('f', 1, long) -#define FS_IOC_SETFLAGS _IOW('f', 2, long) -#define FS_IOC_GETVERSION _IOR('v', 1, long) -#define FS_IOC_SETVERSION _IOW('v', 2, long) -#define FS_IOC_FIEMAP _IOWR('f', 11, struct fiemap) -#define FS_IOC32_GETFLAGS _IOR('f', 1, int) -#define FS_IOC32_SETFLAGS _IOW('f', 2, int) -#define FS_IOC32_GETVERSION _IOR('v', 1, int) -#define FS_IOC32_SETVERSION _IOW('v', 2, int) -#else #include <linux/fs.h> -#endif #include <linux/fd.h> #if defined(CONFIG_FIEMAP) #include <linux/fiemap.h> diff --git a/meson.build b/meson.build index XXXXXXX..XXXXXXX 100644 --- a/meson.build +++ b/meson.build @@ -XXX,XX +XXX,XX @@ config_host_data.set('HAVE_OPTRESET', cc.has_header_symbol('getopt.h', 'optreset')) config_host_data.set('HAVE_IPPROTO_MPTCP', cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP')) -config_host_data.set('HAVE_SYS_MOUNT_FSCONFIG', - cc.has_header_symbol('sys/mount.h', 'FSCONFIG_SET_FLAG')) # has_member config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID', -- 2.39.1
From: Helge Deller <deller@gmx.de> Add the two syscalls to strace output to avoid "Unknown syscall" message. Signed-off-by: Helge Deller <deller@gmx.de> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <20230115113517.25143-1-deller@gmx.de> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/strace.list | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/linux-user/strace.list b/linux-user/strace.list index XXXXXXX..XXXXXXX 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -XXX,XX +XXX,XX @@ { TARGET_NR_clock_getres, "clock_getres" , NULL, print_clock_getres, print_syscall_ret_clock_getres }, #endif +#ifdef TARGET_NR_clock_getres_time64 +{ TARGET_NR_clock_getres_time64, "clock_getres_time64" , NULL, NULL, NULL }, +#endif #ifdef TARGET_NR_clock_gettime { TARGET_NR_clock_gettime, "clock_gettime" , NULL, print_clock_gettime, print_syscall_ret_clock_gettime }, @@ -XXX,XX +XXX,XX @@ #ifdef TARGET_NR_futex { TARGET_NR_futex, "futex" , NULL, print_futex, NULL }, #endif +#ifdef TARGET_NR_futex_time64 +{ TARGET_NR_futex_time64, "futex_time64" , NULL, NULL, NULL }, +#endif #ifdef TARGET_NR_futimesat { TARGET_NR_futimesat, "futimesat" , NULL, print_futimesat, NULL }, #endif -- 2.39.1
From: Helge Deller <deller@gmx.de> Make the strace look nicer for those syscalls. Signed-off-by: Helge Deller <deller@gmx.de> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <20230115210057.445132-1-deller@gmx.de> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/strace.list | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/linux-user/strace.list b/linux-user/strace.list index XXXXXXX..XXXXXXX 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -XXX,XX +XXX,XX @@ { TARGET_NR_getgid32, "getgid32" , NULL, NULL, NULL }, #endif #ifdef TARGET_NR_getgroups -{ TARGET_NR_getgroups, "getgroups" , NULL, NULL, NULL }, +{ TARGET_NR_getgroups, "getgroups" , "%s(%d,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_getgroups32 -{ TARGET_NR_getgroups32, "getgroups32" , NULL, NULL, NULL }, +{ TARGET_NR_getgroups32, "getgroups32" , "%s(%d,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_gethostname { TARGET_NR_gethostname, "gethostname" , NULL, NULL, NULL }, @@ -XXX,XX +XXX,XX @@ { TARGET_NR_setgid32, "setgid32" , "%s(%u)", NULL, NULL }, #endif #ifdef TARGET_NR_setgroups -{ TARGET_NR_setgroups, "setgroups" , NULL, NULL, NULL }, +{ TARGET_NR_setgroups, "setgroups" , "%s(%d,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_setgroups32 -{ TARGET_NR_setgroups32, "setgroups32" , NULL, NULL, NULL }, +{ TARGET_NR_setgroups32, "setgroups32" , "%s(%d,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_sethae { TARGET_NR_sethae, "sethae" , NULL, NULL, NULL }, -- 2.39.1
From: Mike Frysinger <vapier@gentoo.org> This makes target_flat.h behave like every other target_xxx.h header. It also makes it actually work -- while the current header says adding a header to the target subdir overrides the common one, it doesn't. This is for two reasons: * meson.build adds -Ilinux-user before -Ilinux-user/$arch * the compiler search path for "target_flat.h" looks in the same dir as the source file before searching -I paths. This can be seen with the xtensa port -- the subdir settings aren't used which breaks stack setup. Move it to the generic/ subdir and add include stubs like every other target_xxx.h header is handled. Signed-off-by: Mike Frysinger <vapier@gentoo.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20230129004625.11228-1-vapier@gentoo.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/aarch64/target_flat.h | 1 + linux-user/arm/target_flat.h | 1 + linux-user/{ => generic}/target_flat.h | 0 linux-user/m68k/target_flat.h | 1 + linux-user/microblaze/target_flat.h | 1 + linux-user/sh4/target_flat.h | 1 + 6 files changed, 5 insertions(+) create mode 100644 linux-user/aarch64/target_flat.h create mode 100644 linux-user/arm/target_flat.h rename linux-user/{ => generic}/target_flat.h (100%) create mode 100644 linux-user/m68k/target_flat.h create mode 100644 linux-user/microblaze/target_flat.h create mode 100644 linux-user/sh4/target_flat.h diff --git a/linux-user/aarch64/target_flat.h b/linux-user/aarch64/target_flat.h new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/linux-user/aarch64/target_flat.h @@ -0,0 +1 @@ +#include "../generic/target_flat.h" diff --git a/linux-user/arm/target_flat.h b/linux-user/arm/target_flat.h new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/linux-user/arm/target_flat.h @@ -0,0 +1 @@ +#include "../generic/target_flat.h" diff --git a/linux-user/target_flat.h b/linux-user/generic/target_flat.h similarity index 100% rename from linux-user/target_flat.h rename to linux-user/generic/target_flat.h diff --git a/linux-user/m68k/target_flat.h b/linux-user/m68k/target_flat.h new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/linux-user/m68k/target_flat.h @@ -0,0 +1 @@ +#include "../generic/target_flat.h" diff --git a/linux-user/microblaze/target_flat.h b/linux-user/microblaze/target_flat.h new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/linux-user/microblaze/target_flat.h @@ -0,0 +1 @@ +#include "../generic/target_flat.h" diff --git a/linux-user/sh4/target_flat.h b/linux-user/sh4/target_flat.h new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/linux-user/sh4/target_flat.h @@ -0,0 +1 @@ +#include "../generic/target_flat.h" -- 2.39.1
From: Helge Deller <deller@gmx.de> Add translation for the host error return code of: getsockopt(19, SOL_SOCKET, SO_ERROR, [ECONNREFUSED], [4]) = 0 This fixes the testsuite of the cockpit debian package with a hppa-linux guest on a x86-64 host. Signed-off-by: Helge Deller <deller@gmx.de> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <Y9QzNzXg0hrzHQeo@p100> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/syscall.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -XXX,XX +XXX,XX @@ get_timeout: ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv)); if (ret < 0) return ret; - if (optname == SO_TYPE) { + switch (optname) { + case SO_TYPE: val = host_to_target_sock_type(val); + break; + case SO_ERROR: + val = host_to_target_errno(val); + break; } if (len > lv) len = lv; -- 2.39.1
From: Helge Deller <deller@gmx.de> The hppa architectures provides an own output for the emulated /proc/cpuinfo file. Some userspace applications count (even if that's not the recommended way) the number of lines which start with "processor:" and assume that this number then reflects the number of online CPUs. Since those 3 architectures don't provide any such line, applications may assume "0" CPUs. One such issue can be seen in debian bug report: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1024653 Avoid such issues by adding a "processor:" line for each of the online CPUs. Signed-off-by: Helge Deller <deller@gmx.de> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <Y9QvyRSq1I1k5/JW@p100> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/syscall.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -XXX,XX +XXX,XX @@ static int open_cpuinfo(CPUArchState *cpu_env, int fd) #if defined(TARGET_HPPA) static int open_cpuinfo(CPUArchState *cpu_env, int fd) { - dprintf(fd, "cpu family\t: PA-RISC 1.1e\n"); - dprintf(fd, "cpu\t\t: PA7300LC (PCX-L2)\n"); - dprintf(fd, "capabilities\t: os32\n"); - dprintf(fd, "model\t\t: 9000/778/B160L\n"); - dprintf(fd, "model name\t: Merlin L2 160 QEMU (9000/778/B160L)\n"); + int i, num_cpus; + + num_cpus = sysconf(_SC_NPROCESSORS_ONLN); + for (i = 0; i < num_cpus; i++) { + dprintf(fd, "processor\t: %d\n", i); + dprintf(fd, "cpu family\t: PA-RISC 1.1e\n"); + dprintf(fd, "cpu\t\t: PA7300LC (PCX-L2)\n"); + dprintf(fd, "capabilities\t: os32\n"); + dprintf(fd, "model\t\t: 9000/778/B160L - " + "Merlin L2 160 QEMU (9000/778/B160L)\n\n"); + } return 0; } #endif -- 2.39.1
From: Helge Deller <deller@gmx.de> Make the strace look nicer for those two syscalls. Signed-off-by: Helge Deller <deller@gmx.de> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <Y9QxskymWJjrKQmT@p100> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/strace.list | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/linux-user/strace.list b/linux-user/strace.list index XXXXXXX..XXXXXXX 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -XXX,XX +XXX,XX @@ { TARGET_NR_perfctr, "perfctr" , NULL, NULL, NULL }, #endif #ifdef TARGET_NR_personality -{ TARGET_NR_personality, "personality" , NULL, NULL, NULL }, +{ TARGET_NR_personality, "personality" , "%s(0x"TARGET_ABI_FMT_lx")", NULL, + print_syscall_ret_addr }, #endif #ifdef TARGET_NR_pipe { TARGET_NR_pipe, "pipe" , NULL, NULL, NULL }, @@ -XXX,XX +XXX,XX @@ { TARGET_NR_sysfs, "sysfs" , NULL, NULL, NULL }, #endif #ifdef TARGET_NR_sysinfo -{ TARGET_NR_sysinfo, "sysinfo" , NULL, NULL, NULL }, +{ TARGET_NR_sysinfo, "sysinfo" , "%s(%p)", NULL, NULL }, #endif #ifdef TARGET_NR_sys_kexec_load { TARGET_NR_sys_kexec_load, "sys_kexec_load" , NULL, NULL, NULL }, -- 2.39.1
From: Helge Deller <deller@gmx.de> Both parameters have a different value on the parisc platform, so first translate the target value into a host value for usage in the native madvise() syscall. Those parameters are often used by security sensitive applications (e.g. tor browser, boringssl, ...) which expect the call to return a proper return code on failure, so return -EINVAL if qemu fails to forward the syscall to the host OS. While touching this code, enhance the comments about MADV_DONTNEED. Tested with testcase of tor browser when running hppa-linux guest on x86-64 host. Signed-off-by: Helge Deller <deller@gmx.de> Acked-by: Ilya Leoshkevich <iii@linux.ibm.com> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <Y5iwTaydU7i66K/i@p100> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/mmap.c | 56 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 13 deletions(-) diff --git a/linux-user/mmap.c b/linux-user/mmap.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/mmap.c +++ b/linux-user/mmap.c @@ -XXX,XX +XXX,XX @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size, return new_addr; } -static bool can_passthrough_madv_dontneed(abi_ulong start, abi_ulong end) +static bool can_passthrough_madvise(abi_ulong start, abi_ulong end) { ulong addr; @@ -XXX,XX +XXX,XX @@ abi_long target_madvise(abi_ulong start, abi_ulong len_in, int advice) return -TARGET_EINVAL; } + /* Translate for some architectures which have different MADV_xxx values */ + switch (advice) { + case TARGET_MADV_DONTNEED: /* alpha */ + advice = MADV_DONTNEED; + break; + case TARGET_MADV_WIPEONFORK: /* parisc */ + advice = MADV_WIPEONFORK; + break; + case TARGET_MADV_KEEPONFORK: /* parisc */ + advice = MADV_KEEPONFORK; + break; + /* we do not care about the other MADV_xxx values yet */ + } + /* - * A straight passthrough may not be safe because qemu sometimes turns - * private file-backed mappings into anonymous mappings. + * Most advice values are hints, so ignoring and returning success is ok. + * + * However, some advice values such as MADV_DONTNEED, MADV_WIPEONFORK and + * MADV_KEEPONFORK are not hints and need to be emulated. * - * This is a hint, so ignoring and returning success is ok. + * A straight passthrough for those may not be safe because qemu sometimes + * turns private file-backed mappings into anonymous mappings. + * can_passthrough_madvise() helps to check if a passthrough is possible by + * comparing mappings that are known to have the same semantics in the host + * and the guest. In this case passthrough is safe. * - * This breaks MADV_DONTNEED, completely implementing which is quite - * complicated. However, there is one low-hanging fruit: mappings that are - * known to have the same semantics in the host and the guest. In this case - * passthrough is safe, so do it. + * We pass through MADV_WIPEONFORK and MADV_KEEPONFORK if possible and + * return failure if not. + * + * MADV_DONTNEED is passed through as well, if possible. + * If passthrough isn't possible, we nevertheless (wrongly!) return + * success, which is broken but some userspace programs fail to work + * otherwise. Completely implementing such emulation is quite complicated + * though. */ mmap_lock(); - if (advice == TARGET_MADV_DONTNEED && - can_passthrough_madv_dontneed(start, end)) { - ret = get_errno(madvise(g2h_untagged(start), len, MADV_DONTNEED)); - if (ret == 0) { - page_reset_target_data(start, start + len); + switch (advice) { + case MADV_WIPEONFORK: + case MADV_KEEPONFORK: + ret = -EINVAL; + /* fall through */ + case MADV_DONTNEED: + if (can_passthrough_madvise(start, end)) { + ret = get_errno(madvise(g2h_untagged(start), len, advice)); + if ((advice == MADV_DONTNEED) && (ret == 0)) { + page_reset_target_data(start, start + len); + } } } mmap_unlock(); -- 2.39.1
From: Helge Deller <deller@gmx.de> Add output for the missing 4th parameter (size_t sigsetsize). Signed-off-by: Helge Deller <deller@gmx.de> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <Y9hCxdvdM1o+/iHC@p100> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/strace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -XXX,XX +XXX,XX @@ print_rt_sigprocmask(CPUArchState *cpu_env, const struct syscallname *name, } qemu_log("%s,", how); print_pointer(arg1, 0); - print_pointer(arg2, 1); + print_pointer(arg2, 0); + print_raw_param("%u", arg3, 1); print_syscall_epilogue(name); } #endif -- 2.39.1
From: Helge Deller <deller@gmx.de> Add appropriate strace printf formats for various Linux syscalls. Signed-off-by: Helge Deller <deller@gmx.de> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-Id: <Y5dsfGB1RChGfraW@p100> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/strace.list | 43 ++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/linux-user/strace.list b/linux-user/strace.list index XXXXXXX..XXXXXXX 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -XXX,XX +XXX,XX @@ { TARGET_NR_getpagesize, "getpagesize" , NULL, NULL, NULL }, #endif #ifdef TARGET_NR_getpeername -{ TARGET_NR_getpeername, "getpeername" , NULL, NULL, NULL }, +{ TARGET_NR_getpeername, "getpeername" , "%s(%d,%p,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_getpgid { TARGET_NR_getpgid, "getpgid" , "%s(%u)", NULL, NULL }, @@ -XXX,XX +XXX,XX @@ { TARGET_NR_getrandom, "getrandom", "%s(%p,%u,%u)", NULL, NULL }, #endif #ifdef TARGET_NR_getresgid -{ TARGET_NR_getresgid, "getresgid" , NULL, NULL, NULL }, +{ TARGET_NR_getresgid, "getresgid" , "%s(%p,%p,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_getresgid32 { TARGET_NR_getresgid32, "getresgid32" , NULL, NULL, NULL }, #endif #ifdef TARGET_NR_getresuid -{ TARGET_NR_getresuid, "getresuid" , NULL, NULL, NULL }, +{ TARGET_NR_getresuid, "getresuid" , "%s(%p,%p,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_getresuid32 { TARGET_NR_getresuid32, "getresuid32" , NULL, NULL, NULL }, #endif #ifdef TARGET_NR_getrlimit -{ TARGET_NR_getrlimit, "getrlimit" , NULL, NULL, NULL }, +{ TARGET_NR_getrlimit, "getrlimit" , "%s(%d,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_get_robust_list { TARGET_NR_get_robust_list, "get_robust_list" , NULL, NULL, NULL }, @@ -XXX,XX +XXX,XX @@ { TARGET_NR_getsid, "getsid" , "%s(%d)", NULL, NULL }, #endif #ifdef TARGET_NR_getsockname -{ TARGET_NR_getsockname, "getsockname" , NULL, NULL, NULL }, +{ TARGET_NR_getsockname, "getsockname" , "%s(%d,%p,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_getsockopt -{ TARGET_NR_getsockopt, "getsockopt" , NULL, NULL, NULL }, +{ TARGET_NR_getsockopt, "getsockopt" , "%s(%d,%d,%d,%p,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_get_thread_area #if defined(TARGET_I386) && defined(TARGET_ABI32) @@ -XXX,XX +XXX,XX @@ { TARGET_NR_pivot_root, "pivot_root" , NULL, NULL, NULL }, #endif #ifdef TARGET_NR_poll -{ TARGET_NR_poll, "poll" , NULL, NULL, NULL }, +{ TARGET_NR_poll, "poll" , "%s(%p,%u,%d)", NULL, NULL }, #endif #ifdef TARGET_NR_ppoll -{ TARGET_NR_ppoll, "ppoll" , NULL, NULL, NULL }, +{ TARGET_NR_ppoll, "ppoll" , "%s(%p,%u,%p,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_prctl { TARGET_NR_prctl, "prctl" , NULL, NULL, NULL }, @@ -XXX,XX +XXX,XX @@ { TARGET_NR_reboot, "reboot" , NULL, NULL, NULL }, #endif #ifdef TARGET_NR_recv -{ TARGET_NR_recv, "recv" , NULL, NULL, NULL }, +{ TARGET_NR_recv, "recv" , "%s(%d,%p,%u,%d)", NULL, NULL }, #endif #ifdef TARGET_NR_recvfrom { TARGET_NR_recvfrom, "recvfrom" , NULL, NULL, NULL }, @@ -XXX,XX +XXX,XX @@ { TARGET_NR_rt_sigqueueinfo, "rt_sigqueueinfo" , NULL, print_rt_sigqueueinfo, NULL }, #endif #ifdef TARGET_NR_rt_sigreturn -{ TARGET_NR_rt_sigreturn, "rt_sigreturn" , NULL, NULL, NULL }, +{ TARGET_NR_rt_sigreturn, "rt_sigreturn" , "%s(%p)", NULL, NULL }, #endif #ifdef TARGET_NR_rt_sigsuspend { TARGET_NR_rt_sigsuspend, "rt_sigsuspend" , NULL, NULL, NULL }, @@ -XXX,XX +XXX,XX @@ { TARGET_NR_rt_tgsigqueueinfo, "rt_tgsigqueueinfo" , NULL, print_rt_tgsigqueueinfo, NULL }, #endif #ifdef TARGET_NR_sched_getaffinity -{ TARGET_NR_sched_getaffinity, "sched_getaffinity" , NULL, NULL, NULL }, +{ TARGET_NR_sched_getaffinity, "sched_getaffinity" , "%s(%d,%u,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_sched_get_affinity { TARGET_NR_sched_get_affinity, "sched_get_affinity" , NULL, NULL, NULL }, #endif #ifdef TARGET_NR_sched_getattr -{ TARGET_NR_sched_getattr, "sched_getattr" , NULL, NULL, NULL }, +{ TARGET_NR_sched_getattr, "sched_getattr" , "%s(%d,%p,%u,%u)", NULL, NULL }, +#endif +#ifdef TARGET_NR_sched_setattr +{ TARGET_NR_sched_setattr, "sched_setattr" , "%s(%p,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_sched_getparam -{ TARGET_NR_sched_getparam, "sched_getparam" , NULL, NULL, NULL }, +{ TARGET_NR_sched_getparam, "sched_getparam" , "%s(%d,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_sched_get_priority_max { TARGET_NR_sched_get_priority_max, "sched_get_priority_max" , NULL, NULL, NULL }, @@ -XXX,XX +XXX,XX @@ { TARGET_NR_sched_rr_get_interval, "sched_rr_get_interval" , NULL, NULL, NULL }, #endif #ifdef TARGET_NR_sched_setaffinity -{ TARGET_NR_sched_setaffinity, "sched_setaffinity" , NULL, NULL, NULL }, +{ TARGET_NR_sched_setaffinity, "sched_setaffinity" , "%s(%d,%u,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_sched_setatt { TARGET_NR_sched_setatt, "sched_setatt" , NULL, NULL, NULL }, @@ -XXX,XX +XXX,XX @@ { TARGET_NR_setreuid32, "setreuid32" , "%s(%u,%u)", NULL, NULL }, #endif #ifdef TARGET_NR_setrlimit -{ TARGET_NR_setrlimit, "setrlimit" , NULL, NULL, NULL }, +{ TARGET_NR_setrlimit, "setrlimit" , "%s(%d,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_set_robust_list -{ TARGET_NR_set_robust_list, "set_robust_list" , NULL, NULL, NULL }, +{ TARGET_NR_set_robust_list, "set_robust_list" , "%s(%p,%u)", NULL, NULL }, #endif #ifdef TARGET_NR_setsid { TARGET_NR_setsid, "setsid" , "%s()", NULL, NULL }, #endif #ifdef TARGET_NR_setsockopt -{ TARGET_NR_setsockopt, "setsockopt" , NULL, NULL, NULL }, +{ TARGET_NR_setsockopt, "setsockopt" , "%s(%d,%d,%d,%p,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_set_thread_area { TARGET_NR_set_thread_area, "set_thread_area", "%s(0x"TARGET_ABI_FMT_lx")", NULL, NULL }, #endif #ifdef TARGET_NR_set_tid_address -{ TARGET_NR_set_tid_address, "set_tid_address" , NULL, NULL, NULL }, +{ TARGET_NR_set_tid_address, "set_tid_address" , "%s(%p)", NULL, NULL }, #endif #ifdef TARGET_NR_settimeofday { TARGET_NR_settimeofday, "settimeofday" , NULL, print_settimeofday, NULL }, @@ -XXX,XX +XXX,XX @@ { TARGET_NR_vserver, "vserver" , NULL, NULL, NULL }, #endif #ifdef TARGET_NR_wait4 -{ TARGET_NR_wait4, "wait4" , NULL, NULL, NULL }, +{ TARGET_NR_wait4, "wait4" , "%s(%d,%p,%d,%p)", NULL, NULL }, #endif #ifdef TARGET_NR_waitid { TARGET_NR_waitid, "waitid" , "%s(%#x,%d,%p,%#x)", NULL, NULL }, @@ -XXX,XX +XXX,XX @@ { TARGET_NR_sync_file_range2, "sync_file_range2", NULL, NULL, NULL }, #endif #ifdef TARGET_NR_pipe2 -{ TARGET_NR_pipe2, "pipe2", NULL, NULL, NULL }, +{ TARGET_NR_pipe2, "pipe2", "%s(%p,%d)", NULL, NULL }, #endif #ifdef TARGET_NR_pidfd_open { TARGET_NR_pidfd_open, "pidfd_open", "%s(%d,%u)", NULL, NULL }, -- 2.39.1
From: Helge Deller <deller@gmx.de> Add suport to handle SOL_ALG packets via sendmsg() and recvmsg(). This allows emulated userspace to use encryption functionality. Tested with the debian ell package with hppa guest on x86_64 host. Signed-off-by: Helge Deller <deller@gmx.de> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <20221212173416.90590-1-deller@gmx.de> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/syscall.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -XXX,XX +XXX,XX @@ static inline abi_long target_to_host_cmsg(struct msghdr *msgh, __get_user(cred->pid, &target_cred->pid); __get_user(cred->uid, &target_cred->uid); __get_user(cred->gid, &target_cred->gid); + } else if (cmsg->cmsg_level == SOL_ALG) { + uint32_t *dst = (uint32_t *)data; + + memcpy(dst, target_data, len); + /* fix endianess of first 32-bit word */ + if (len >= sizeof(uint32_t)) { + *dst = tswap32(*dst); + } } else { qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type); -- 2.39.1
From: Helge Deller <deller@gmx.de> Applications do call sendmsg() without any IOV, e.g.: sendmsg(4, {msg_name=NULL, msg_namelen=0, msg_iov=NULL, msg_iovlen=0, msg_control=[{cmsg_len=36, cmsg_level=SOL_ALG, cmsg_type=0x2}], msg_controllen=40, msg_flags=0}, MSG_MORE) = 0 sendmsg(4, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="The quick brown fox jumps over t"..., iov_len=183}], msg_iovlen=1, msg_control=[{cmsg_len=20, cmsg_level=SOL_ALG, cmsg_type=0x3}], msg_controllen=24, msg_flags=0}, 0) = 183 The function do_sendrecvmsg_locked() is used for sndmsg() and recvmsg() and calls lock_iovec() to lock the IOV into memory. For the first sendmsg() above it returns NULL and thus wrongly skips the call the host sendmsg() syscall, which will break the calling application. Fix this issue by: - allowing sendmsg() even with empty IOV - skip recvmsg() if IOV is NULL - skip both if the return code of do_sendrecvmsg_locked() != 0, which indicates some failure like EFAULT on the IOV Tested with the debian "ell" package with hppa guest on x86_64 host. Signed-off-by: Helge Deller <deller@gmx.de> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <20221212173416.90590-2-deller@gmx.de> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/syscall.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -XXX,XX +XXX,XX @@ static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp, target_vec, count, send); if (vec == NULL) { ret = -host_to_target_errno(errno); - goto out2; + /* allow sending packet without any iov, e.g. with MSG_MORE flag */ + if (!send || ret) { + goto out2; + } } msg.msg_iovlen = count; msg.msg_iov = vec; @@ -XXX,XX +XXX,XX @@ static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp, } out: - unlock_iovec(vec, target_vec, count, !send); + if (vec) { + unlock_iovec(vec, target_vec, count, !send); + } out2: return ret; } -- 2.39.1
The following changes since commit 817fd33836e73812df2f1907612b57750fcb9491: Merge tag 'audio-pull-request' of https://gitlab.com/marcandre.lureau/qemu into staging (2023-03-06 14:06:06 +0000) are available in the Git repository at: https://gitlab.com/laurent_vivier/qemu.git tags/linux-user-for-8.0-pull-request for you to fetch changes up to 2732c739d846fc7a1972e984d71a3de0d3eef77b: linux-user: fix bug about incorrect base addresss of gdt on i386 and x86_64 (2023-03-10 20:50:11 +0100) ---------------------------------------------------------------- Pull request linux-user 20230308-v2 Fix gdt on i386/x86_64 Handle traps on sparc Add translation for argument of msync Emulate CLONE_PIDFD flag in clone handle netlink flag NLA_F_NESTED fix sockaddr_in6 endianness Fix brk() to release pages fill out task state in /proc/self/stat add support for xtensa FDPIC Fix unaligned memory access in prlimit64 syscall add target to host netlink conversions fix timerfd read endianness conversion Fix access to /proc/self/exe Add strace for prlimit64() syscall ---------------------------------------------------------------- Andreas Schwab (1): linux-user: fill out task state in /proc/self/stat Helge Deller (6): linux-user: Fix access to /proc/self/exe linux-user: Fix brk() to release pages linux-user: Provide print_raw_param64() for 64-bit values linux-user: Add strace for prlimit64() syscall linux-user: Add translation for argument of msync() linux-user: Emulate CLONE_PIDFD flag in clone() Ilya Leoshkevich (1): linux-user: Fix unaligned memory access in prlimit64 syscall Mathis Marion (4): linux-user: fix timerfd read endianness conversion linux-user: add target to host netlink conversions linux-user: fix sockaddr_in6 endianness linux-user: handle netlink flag NLA_F_NESTED Max Filippov (1): linux-user: add support for xtensa FDPIC Richard Henderson (14): linux-user/sparc: Tidy syscall trap linux-user/sparc: Tidy syscall error return linux-user/sparc: Use TT_TRAP for flush windows linux-user/sparc: Tidy window spill/fill traps linux-user/sparc: Fix sparc64_{get, set}_context traps linux-user/sparc: Handle software breakpoint trap linux-user/sparc: Handle division by zero traps linux-user/sparc: Handle getcc, setcc, getpsr traps linux-user/sparc: Handle priviledged opcode trap linux-user/sparc: Handle privilidged action trap linux-user/sparc: Handle coprocessor disabled trap linux-user/sparc: Handle unimplemented flush trap linux-user/sparc: Handle floating-point exceptions linux-user/sparc: Handle tag overflow traps fanwj@mail.ustc.edu.cn (1): linux-user: fix bug about incorrect base addresss of gdt on i386 and x86_64 include/elf.h | 1 + linux-user/alpha/target_mman.h | 4 + linux-user/elfload.c | 16 ++- linux-user/fd-trans.c | 74 ++++++++++- linux-user/fd-trans.h | 1 + linux-user/generic/target_mman.h | 13 ++ linux-user/generic/target_resource.h | 4 +- linux-user/hppa/target_mman.h | 4 + linux-user/i386/cpu_loop.c | 9 ++ linux-user/main.c | 14 +++ linux-user/sparc/cpu_loop.c | 182 +++++++++++++++++++++------ linux-user/sparc/signal.c | 36 +++--- linux-user/sparc/target_signal.h | 2 +- linux-user/strace.c | 113 ++++++++++++++++- linux-user/strace.list | 5 +- linux-user/syscall.c | 174 +++++++++++++++---------- linux-user/syscall_defs.h | 5 + target/sparc/cpu.h | 3 +- 18 files changed, 520 insertions(+), 140 deletions(-) -- 2.39.2
From: Helge Deller <deller@gmx.de> When accsssing /proc/self/exe from a userspace program, linux-user tries to resolve the name via realpath(), which may fail if the process changed the working directory in the meantime. An example: - a userspace program ist started with ./testprogram - the program runs chdir("/tmp") - then the program calls readlink("/proc/self/exe") - linux-user tries to run realpath("./testprogram") which fails because ./testprogram isn't in /tmp - readlink() will return -ENOENT back to the program Avoid this issue by resolving the full path name of the started process at startup of linux-user and store it in real_exec_path[]. This then simplifies the emulation of readlink() and readlinkat() as well, because they can simply copy the path string to userspace. I noticed this bug because the testsuite of the debian package "pandoc" failed on linux-user while it succeeded on real hardware. The full log is here: https://buildd.debian.org/status/fetch.php?pkg=pandoc&arch=hppa&ver=2.17.1.1-1.1%2Bb1&stamp=1670153210&raw=0 Signed-off-by: Helge Deller <deller@gmx.de> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <20221205113825.20615-1-deller@gmx.de> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/main.c | 6 ++++++ linux-user/syscall.c | 38 ++++++++++++++------------------------ 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/linux-user/main.c b/linux-user/main.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -XXX,XX +XXX,XX @@ #endif char *exec_path; +char real_exec_path[PATH_MAX]; int singlestep; static const char *argv0; @@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp) } } + /* Resolve executable file name to full path name */ + if (realpath(exec_path, real_exec_path)) { + exec_path = real_exec_path; + } + /* * get binfmt_misc flags */ diff --git a/linux-user/syscall.c b/linux-user/syscall.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -XXX,XX +XXX,XX @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, /* Short circuit this for the magic exe check. */ ret = -TARGET_EINVAL; } else if (is_proc_myself((const char *)p, "exe")) { - char real[PATH_MAX], *temp; - temp = realpath(exec_path, real); - /* Return value is # of bytes that we wrote to the buffer. */ - if (temp == NULL) { - ret = get_errno(-1); - } else { - /* Don't worry about sign mismatch as earlier mapping - * logic would have thrown a bad address error. */ - ret = MIN(strlen(real), arg3); - /* We cannot NUL terminate the string. */ - memcpy(p2, real, ret); - } + /* + * Don't worry about sign mismatch as earlier mapping + * logic would have thrown a bad address error. + */ + ret = MIN(strlen(exec_path), arg3); + /* We cannot NUL terminate the string. */ + memcpy(p2, exec_path, ret); } else { ret = get_errno(readlink(path(p), p2, arg3)); } @@ -XXX,XX +XXX,XX @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, /* Short circuit this for the magic exe check. */ ret = -TARGET_EINVAL; } else if (is_proc_myself((const char *)p, "exe")) { - char real[PATH_MAX], *temp; - temp = realpath(exec_path, real); - /* Return value is # of bytes that we wrote to the buffer. */ - if (temp == NULL) { - ret = get_errno(-1); - } else { - /* Don't worry about sign mismatch as earlier mapping - * logic would have thrown a bad address error. */ - ret = MIN(strlen(real), arg4); - /* We cannot NUL terminate the string. */ - memcpy(p2, real, ret); - } + /* + * Don't worry about sign mismatch as earlier mapping + * logic would have thrown a bad address error. + */ + ret = MIN(strlen(exec_path), arg4); + /* We cannot NUL terminate the string. */ + memcpy(p2, exec_path, ret); } else { ret = get_errno(readlinkat(arg1, path(p), p2, arg4)); } -- 2.39.2
From: Mathis Marion <mathis.marion@silabs.com> When reading the expiration count from a timerfd, the endianness of the 64bit value read is the one of the host, just as for eventfds. Signed-off-by: Mathis Marion <mathis.marion@silabs.com> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <20230220085822.626798-2-Mathis.Marion@silabs.com> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/fd-trans.c | 10 +++++++--- linux-user/fd-trans.h | 1 + linux-user/syscall.c | 8 ++++++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/linux-user/fd-trans.c b/linux-user/fd-trans.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/fd-trans.c +++ b/linux-user/fd-trans.c @@ -XXX,XX +XXX,XX @@ TargetFdTrans target_signalfd_trans = { .host_to_target_data = host_to_target_data_signalfd, }; -static abi_long swap_data_eventfd(void *buf, size_t len) +static abi_long swap_data_u64(void *buf, size_t len) { uint64_t *counter = buf; int i; @@ -XXX,XX +XXX,XX @@ static abi_long swap_data_eventfd(void *buf, size_t len) } TargetFdTrans target_eventfd_trans = { - .host_to_target_data = swap_data_eventfd, - .target_to_host_data = swap_data_eventfd, + .host_to_target_data = swap_data_u64, + .target_to_host_data = swap_data_u64, +}; + +TargetFdTrans target_timerfd_trans = { + .host_to_target_data = swap_data_u64, }; #if defined(CONFIG_INOTIFY) && (defined(TARGET_NR_inotify_init) || \ diff --git a/linux-user/fd-trans.h b/linux-user/fd-trans.h index XXXXXXX..XXXXXXX 100644 --- a/linux-user/fd-trans.h +++ b/linux-user/fd-trans.h @@ -XXX,XX +XXX,XX @@ extern TargetFdTrans target_netlink_route_trans; extern TargetFdTrans target_netlink_audit_trans; extern TargetFdTrans target_signalfd_trans; extern TargetFdTrans target_eventfd_trans; +extern TargetFdTrans target_timerfd_trans; #if (defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)) || \ (defined(CONFIG_INOTIFY1) && defined(TARGET_NR_inotify_init1) && \ defined(__NR_inotify_init1)) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -XXX,XX +XXX,XX @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, #if defined(TARGET_NR_timerfd_create) && defined(CONFIG_TIMERFD) case TARGET_NR_timerfd_create: - return get_errno(timerfd_create(arg1, - target_to_host_bitmask(arg2, fcntl_flags_tbl))); + ret = get_errno(timerfd_create(arg1, + target_to_host_bitmask(arg2, fcntl_flags_tbl))); + if (ret >= 0) { + fd_trans_register(ret, &target_timerfd_trans); + } + return ret; #endif #if defined(TARGET_NR_timerfd_gettime) && defined(CONFIG_TIMERFD) -- 2.39.2
From: Mathis Marion <mathis.marion@silabs.com> Added conversions for: - IFLA_MTU - IFLA_TXQLEN - IFLA_AF_SPEC AF_INET6 IFLA_INET6_ADDR_GEN_MODE These relate to the libnl functions rtnl_link_set_mtu, rtnl_link_set_txqlen, and rtnl_link_inet6_set_addr_gen_mode. Signed-off-by: Mathis Marion <mathis.marion@silabs.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <20230220085822.626798-4-Mathis.Marion@silabs.com> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/fd-trans.c | 62 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/linux-user/fd-trans.c b/linux-user/fd-trans.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/fd-trans.c +++ b/linux-user/fd-trans.c @@ -XXX,XX +XXX,XX @@ static inline abi_long host_to_target_nlmsg_route(struct nlmsghdr *nlh, return host_to_target_for_each_nlmsg(nlh, len, host_to_target_data_route); } +static abi_long target_to_host_for_each_nlattr(struct nlattr *nlattr, + size_t len, + abi_long (*target_to_host_nlattr) + (struct nlattr *)) +{ + unsigned short aligned_nla_len; + abi_long ret; + + while (len > sizeof(struct nlattr)) { + if (tswap16(nlattr->nla_len) < sizeof(struct rtattr) || + tswap16(nlattr->nla_len) > len) { + break; + } + nlattr->nla_len = tswap16(nlattr->nla_len); + nlattr->nla_type = tswap16(nlattr->nla_type); + ret = target_to_host_nlattr(nlattr); + if (ret < 0) { + return ret; + } + + aligned_nla_len = NLA_ALIGN(nlattr->nla_len); + if (aligned_nla_len >= len) { + break; + } + len -= aligned_nla_len; + nlattr = (struct nlattr *)(((char *)nlattr) + aligned_nla_len); + } + return 0; +} + +static abi_long target_to_host_data_inet6_nlattr(struct nlattr *nlattr) +{ + switch (nlattr->nla_type) { + /* uint8_t */ + case QEMU_IFLA_INET6_ADDR_GEN_MODE: + break; + default: + qemu_log_mask(LOG_UNIMP, "Unknown target AF_INET6 type: %d\n", + nlattr->nla_type); + } + return 0; +} + static abi_long target_to_host_for_each_rtattr(struct rtattr *rtattr, size_t len, abi_long (*target_to_host_rtattr) @@ -XXX,XX +XXX,XX @@ static abi_long target_to_host_for_each_rtattr(struct rtattr *rtattr, return 0; } +static abi_long target_to_host_data_spec_nlattr(struct nlattr *nlattr) +{ + switch (nlattr->nla_type) { + case AF_INET6: + return target_to_host_for_each_nlattr(NLA_DATA(nlattr), nlattr->nla_len, + target_to_host_data_inet6_nlattr); + default: + qemu_log_mask(LOG_UNIMP, "Unknown target AF_SPEC type: %d\n", + nlattr->nla_type); + break; + } + return 0; +} + static abi_long target_to_host_data_link_rtattr(struct rtattr *rtattr) { uint32_t *u32; switch (rtattr->rta_type) { /* uint32_t */ + case QEMU_IFLA_MTU: + case QEMU_IFLA_TXQLEN: case QEMU_IFLA_EXT_MASK: u32 = RTA_DATA(rtattr); *u32 = tswap32(*u32); break; + case QEMU_IFLA_AF_SPEC: + return target_to_host_for_each_nlattr(RTA_DATA(rtattr), rtattr->rta_len, + target_to_host_data_spec_nlattr); default: qemu_log_mask(LOG_UNIMP, "Unknown target QEMU_IFLA type: %d\n", rtattr->rta_type); -- 2.39.2
From: Ilya Leoshkevich <iii@linux.ibm.com> target_rlimit64 contains uint64_t fields, so it's 8-byte aligned on some hosts, while some guests may align their respective type on a 4-byte boundary. This may lead to an unaligned access, which is an UB. Fix by defining the fields as abi_ullong. This makes the host alignment match that of the guest, and lets the compiler know that it should emit code that can deal with the guest alignment. While at it, also use __get_user() and __put_user() instead of tswap64(). Fixes: 163a05a8398b ("linux-user: Implement prlimit64 syscall") Reported-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <20230224003907.263914-2-iii@linux.ibm.com> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/generic/target_resource.h | 4 ++-- linux-user/syscall.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/linux-user/generic/target_resource.h b/linux-user/generic/target_resource.h index XXXXXXX..XXXXXXX 100644 --- a/linux-user/generic/target_resource.h +++ b/linux-user/generic/target_resource.h @@ -XXX,XX +XXX,XX @@ struct target_rlimit { }; struct target_rlimit64 { - uint64_t rlim_cur; - uint64_t rlim_max; + abi_ullong rlim_cur; + abi_ullong rlim_max; }; #define TARGET_RLIM_INFINITY ((abi_ulong)-1) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -XXX,XX +XXX,XX @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, if (!lock_user_struct(VERIFY_READ, target_rnew, arg3, 1)) { return -TARGET_EFAULT; } - rnew.rlim_cur = tswap64(target_rnew->rlim_cur); - rnew.rlim_max = tswap64(target_rnew->rlim_max); + __get_user(rnew.rlim_cur, &target_rnew->rlim_cur); + __get_user(rnew.rlim_max, &target_rnew->rlim_max); unlock_user_struct(target_rnew, arg3, 0); rnewp = &rnew; } @@ -XXX,XX +XXX,XX @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, if (!lock_user_struct(VERIFY_WRITE, target_rold, arg4, 1)) { return -TARGET_EFAULT; } - target_rold->rlim_cur = tswap64(rold.rlim_cur); - target_rold->rlim_max = tswap64(rold.rlim_max); + __put_user(rold.rlim_cur, &target_rold->rlim_cur); + __put_user(rold.rlim_max, &target_rold->rlim_max); unlock_user_struct(target_rold, arg4, 1); } return ret; -- 2.39.2
From: Max Filippov <jcmvbkbc@gmail.com> Define xtensa-specific info_is_fdpic and fill in FDPIC-specific registers in the xtensa version of init_thread. Signed-off-by: Max Filippov <jcmvbkbc@gmail.com> Message-Id: <20230205061230.544451-1-jcmvbkbc@gmail.com> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- include/elf.h | 1 + linux-user/elfload.c | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/include/elf.h b/include/elf.h index XXXXXXX..XXXXXXX 100644 --- a/include/elf.h +++ b/include/elf.h @@ -XXX,XX +XXX,XX @@ typedef struct elf64_shdr { #define ELFOSABI_MODESTO 11 /* Novell Modesto. */ #define ELFOSABI_OPENBSD 12 /* OpenBSD. */ #define ELFOSABI_ARM_FDPIC 65 /* ARM FDPIC */ +#define ELFOSABI_XTENSA_FDPIC 65 /* Xtensa FDPIC */ #define ELFOSABI_ARM 97 /* ARM */ #define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ diff --git a/linux-user/elfload.c b/linux-user/elfload.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -XXX,XX +XXX,XX @@ static inline void init_thread(struct target_pt_regs *regs, regs->windowstart = 1; regs->areg[1] = infop->start_stack; regs->pc = infop->entry; + if (info_is_fdpic(infop)) { + regs->areg[4] = infop->loadmap_addr; + regs->areg[5] = infop->interpreter_loadmap_addr; + if (infop->interpreter_loadmap_addr) { + regs->areg[6] = infop->interpreter_pt_dynamic_addr; + } else { + regs->areg[6] = infop->pt_dynamic_addr; + } + } } /* See linux kernel: arch/xtensa/include/asm/elf.h. */ @@ -XXX,XX +XXX,XX @@ static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot) } } -#ifdef TARGET_ARM +#if defined(TARGET_ARM) static int elf_is_fdpic(struct elfhdr *exec) { return exec->e_ident[EI_OSABI] == ELFOSABI_ARM_FDPIC; } +#elif defined(TARGET_XTENSA) +static int elf_is_fdpic(struct elfhdr *exec) +{ + return exec->e_ident[EI_OSABI] == ELFOSABI_XTENSA_FDPIC; +} #else /* Default implementation, always false. */ static int elf_is_fdpic(struct elfhdr *exec) -- 2.39.2
From: Andreas Schwab <schwab@suse.de> Some programs want to match an actual task state character. Signed-off-by: Andreas Schwab <schwab@suse.de> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <mvmedq2kxoe.fsf@suse.de> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/syscall.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -XXX,XX +XXX,XX @@ static int open_self_stat(CPUArchState *cpu_env, int fd) gchar *bin = g_strrstr(ts->bprm->argv[0], "/"); bin = bin ? bin + 1 : ts->bprm->argv[0]; g_string_printf(buf, "(%.15s) ", bin); + } else if (i == 2) { + /* task state */ + g_string_assign(buf, "R "); /* we are running right now */ } else if (i == 3) { /* ppid */ g_string_printf(buf, FMT_pid " ", getppid()); -- 2.39.2
From: Helge Deller <deller@gmx.de> The current brk() implementation does not de-allocate pages if a lower address is given compared to earlier brk() calls. But according to the manpage, brk() shall deallocate memory in this case and currently it breaks a real-world application, specifically building the debian gcl package in qemu-user. Fix this issue by reworking the qemu brk() implementation. Tested with the C-code testcase included in qemu commit 4d1de87c750, and by building debian package of gcl in a hppa-linux guest on a x86-64 host. Signed-off-by: Helge Deller <deller@gmx.de> Message-Id: <Y6gId80ek49TK1xB@p100> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/syscall.c | 69 ++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -XXX,XX +XXX,XX @@ static inline int host_to_target_sock_type(int host_type) } static abi_ulong target_brk; -static abi_ulong target_original_brk; static abi_ulong brk_page; void target_set_brk(abi_ulong new_brk) { - target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk); + target_brk = new_brk; brk_page = HOST_PAGE_ALIGN(target_brk); } -//#define DEBUGF_BRK(message, args...) do { fprintf(stderr, (message), ## args); } while (0) -#define DEBUGF_BRK(message, args...) - /* do_brk() must return target values and target errnos. */ -abi_long do_brk(abi_ulong new_brk) +abi_long do_brk(abi_ulong brk_val) { abi_long mapped_addr; abi_ulong new_alloc_size; + abi_ulong new_brk, new_host_brk_page; /* brk pointers are always untagged */ - DEBUGF_BRK("do_brk(" TARGET_ABI_FMT_lx ") -> ", new_brk); - - if (!new_brk) { - DEBUGF_BRK(TARGET_ABI_FMT_lx " (!new_brk)\n", target_brk); + /* return old brk value if brk_val unchanged or zero */ + if (!brk_val || brk_val == target_brk) { return target_brk; } - if (new_brk < target_original_brk) { - DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk < target_original_brk)\n", - target_brk); + + new_brk = TARGET_PAGE_ALIGN(brk_val); + new_host_brk_page = HOST_PAGE_ALIGN(brk_val); + + /* brk_val and old target_brk might be on the same page */ + if (new_brk == TARGET_PAGE_ALIGN(target_brk)) { + if (brk_val > target_brk) { + /* empty remaining bytes in (possibly larger) host page */ + memset(g2h_untagged(target_brk), 0, new_host_brk_page - target_brk); + } + target_brk = brk_val; return target_brk; } - /* If the new brk is less than the highest page reserved to the - * target heap allocation, set it and we're almost done... */ - if (new_brk <= brk_page) { - /* Heap contents are initialized to zero, as for anonymous - * mapped pages. */ - if (new_brk > target_brk) { - memset(g2h_untagged(target_brk), 0, new_brk - target_brk); - } - target_brk = new_brk; - DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk <= brk_page)\n", target_brk); - return target_brk; + /* Release heap if necesary */ + if (new_brk < target_brk) { + /* empty remaining bytes in (possibly larger) host page */ + memset(g2h_untagged(brk_val), 0, new_host_brk_page - brk_val); + + /* free unused host pages and set new brk_page */ + target_munmap(new_host_brk_page, brk_page - new_host_brk_page); + brk_page = new_host_brk_page; + + target_brk = brk_val; + return target_brk; } /* We need to allocate more memory after the brk... Note that @@ -XXX,XX +XXX,XX @@ abi_long do_brk(abi_ulong new_brk) * itself); instead we treat "mapped but at wrong address" as * a failure and unmap again. */ - new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page); - mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size, + new_alloc_size = new_host_brk_page - brk_page; + if (new_alloc_size) { + mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 0, 0)); + } else { + mapped_addr = brk_page; + } if (mapped_addr == brk_page) { /* Heap contents are initialized to zero, as for anonymous @@ -XXX,XX +XXX,XX @@ abi_long do_brk(abi_ulong new_brk) * then shrunken). */ memset(g2h_untagged(target_brk), 0, brk_page - target_brk); - target_brk = new_brk; - brk_page = HOST_PAGE_ALIGN(target_brk); - DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr == brk_page)\n", - target_brk); + target_brk = brk_val; + brk_page = new_host_brk_page; return target_brk; } else if (mapped_addr != -1) { /* Mapped but at wrong address, meaning there wasn't actually @@ -XXX,XX +XXX,XX @@ abi_long do_brk(abi_ulong new_brk) */ target_munmap(mapped_addr, new_alloc_size); mapped_addr = -1; - DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr != -1)\n", target_brk); - } - else { - DEBUGF_BRK(TARGET_ABI_FMT_lx " (otherwise)\n", target_brk); } #if defined(TARGET_ALPHA) -- 2.39.2
From: Helge Deller <deller@gmx.de> Add a new function print_raw_param64() to print 64-bit values in the same way as print_raw_param(). This prevents that qemu_log() is used to work around the problem that print_raw_param() can only print 32-bit values when compiled for 32-bit targets. Additionally convert the existing 64-bit users in print_timespec64(), print_rlimit64() and print_preadwrite64() over to this new function and drop some unneccessary spaces. Suggested-by: Laurent Vivier <laurent@vivier.eu> Signed-off-by: Helge Deller <deller@gmx.de> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <Y9lNbFNyRSUhhrHa@p100> [lvivier: remove print_preadwrite64 and print_rlimit64 part] Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/strace.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -XXX,XX +XXX,XX @@ UNUSED static void print_syscall_epilogue(const struct syscallname *); UNUSED static void print_string(abi_long, int); UNUSED static void print_buf(abi_long addr, abi_long len, int last); UNUSED static void print_raw_param(const char *, abi_long, int); +UNUSED static void print_raw_param64(const char *, long long, int last); UNUSED static void print_timeval(abi_ulong, int); UNUSED static void print_timespec(abi_ulong, int); UNUSED static void print_timespec64(abi_ulong, int); @@ -XXX,XX +XXX,XX @@ print_raw_param(const char *fmt, abi_long param, int last) qemu_log(format, param); } +/* + * Same as print_raw_param() but prints out raw 64-bit parameter. + */ +static void +print_raw_param64(const char *fmt, long long param, int last) +{ + char format[64]; + + (void)snprintf(format, sizeof(format), "%s%s", fmt, get_comma(last)); + qemu_log(format, param); +} + + static void print_pointer(abi_long p, int last) { @@ -XXX,XX +XXX,XX @@ print_timespec64(abi_ulong ts_addr, int last) print_pointer(ts_addr, last); return; } - qemu_log("{tv_sec = %lld" - ",tv_nsec = %lld}%s", - (long long)tswap64(ts->tv_sec), (long long)tswap64(ts->tv_nsec), - get_comma(last)); + print_raw_param64("{tv_sec=%" PRId64, tswap64(ts->tv_sec), 0); + print_raw_param64("tv_nsec=%" PRId64 "}", tswap64(ts->tv_nsec), last); unlock_user(ts, ts_addr, 0); } else { qemu_log("NULL%s", get_comma(last)); -- 2.39.2
From: Helge Deller <deller@gmx.de> Add proper prlimit64() strace output. Signed-off-by: Helge Deller <deller@gmx.de> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <20221222190639.124078-1-deller@gmx.de> [lvivier: use print_raw_param64()] Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/strace.c | 88 ++++++++++++++++++++++++++++++++++++++++++ linux-user/strace.list | 3 +- 2 files changed, 90 insertions(+), 1 deletion(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -XXX,XX +XXX,XX @@ print_futex(CPUArchState *cpu_env, const struct syscallname *name, } #endif +#ifdef TARGET_NR_prlimit64 +static const char *target_ressource_string(abi_ulong r) +{ + #define RET_RES_ENTRY(res) case TARGET_##res: return #res; + switch (r) { + RET_RES_ENTRY(RLIMIT_AS); + RET_RES_ENTRY(RLIMIT_CORE); + RET_RES_ENTRY(RLIMIT_CPU); + RET_RES_ENTRY(RLIMIT_DATA); + RET_RES_ENTRY(RLIMIT_FSIZE); + RET_RES_ENTRY(RLIMIT_LOCKS); + RET_RES_ENTRY(RLIMIT_MEMLOCK); + RET_RES_ENTRY(RLIMIT_MSGQUEUE); + RET_RES_ENTRY(RLIMIT_NICE); + RET_RES_ENTRY(RLIMIT_NOFILE); + RET_RES_ENTRY(RLIMIT_NPROC); + RET_RES_ENTRY(RLIMIT_RSS); + RET_RES_ENTRY(RLIMIT_RTPRIO); +#ifdef RLIMIT_RTTIME + RET_RES_ENTRY(RLIMIT_RTTIME); +#endif + RET_RES_ENTRY(RLIMIT_SIGPENDING); + RET_RES_ENTRY(RLIMIT_STACK); + default: + return NULL; + } + #undef RET_RES_ENTRY +} + +static void +print_rlimit64(abi_ulong rlim_addr, int last) +{ + if (rlim_addr) { + struct target_rlimit64 *rl; + + rl = lock_user(VERIFY_READ, rlim_addr, sizeof(*rl), 1); + if (!rl) { + print_pointer(rlim_addr, last); + return; + } + print_raw_param64("{rlim_cur=%" PRId64, tswap64(rl->rlim_cur), 0); + print_raw_param64("rlim_max=%" PRId64 "}", tswap64(rl->rlim_max), + last); + unlock_user(rl, rlim_addr, 0); + } else { + qemu_log("NULL%s", get_comma(last)); + } +} + +static void +print_prlimit64(CPUArchState *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + const char *rlim_name; + + print_syscall_prologue(name); + print_raw_param("%d", arg0, 0); + rlim_name = target_ressource_string(arg1); + if (rlim_name) { + qemu_log("%s,", rlim_name); + } else { + print_raw_param("%d", arg1, 0); + } + print_rlimit64(arg2, 0); + print_pointer(arg3, 1); + print_syscall_epilogue(name); +} + +static void +print_syscall_ret_prlimit64(CPUArchState *cpu_env, + const struct syscallname *name, + abi_long ret, abi_long arg0, abi_long arg1, + abi_long arg2, abi_long arg3, abi_long arg4, + abi_long arg5) +{ + if (!print_syscall_err(ret)) { + qemu_log(TARGET_ABI_FMT_ld, ret); + if (arg3) { + qemu_log(" ("); + print_rlimit64(arg3, 1); + qemu_log(")"); + } + } + qemu_log("\n"); +} +#endif + #ifdef TARGET_NR_kill static void print_kill(CPUArchState *cpu_env, const struct syscallname *name, diff --git a/linux-user/strace.list b/linux-user/strace.list index XXXXXXX..XXXXXXX 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -XXX,XX +XXX,XX @@ { TARGET_NR_preadv, "preadv" , NULL, NULL, NULL }, #endif #ifdef TARGET_NR_prlimit64 -{ TARGET_NR_prlimit64, "prlimit64" , NULL, NULL, NULL }, +{ TARGET_NR_prlimit64, "prlimit64" , NULL, print_prlimit64, + print_syscall_ret_prlimit64 }, #endif #ifdef TARGET_NR_process_vm_readv { TARGET_NR_process_vm_readv, "process_vm_readv" , NULL, NULL, NULL }, -- 2.39.2
From: Mathis Marion <mathis.marion@silabs.com> The sin6_scope_id field uses the host byte order, so there is a conversion to be made when host and target endianness differ. Signed-off-by: Mathis Marion <mathis.marion@silabs.com> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-Id: <20230307154256.101528-2-Mathis.Marion@silabs.com> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/syscall.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -XXX,XX +XXX,XX @@ static inline abi_long target_to_host_sockaddr(int fd, struct sockaddr *addr, lladdr = (struct target_sockaddr_ll *)addr; lladdr->sll_ifindex = tswap32(lladdr->sll_ifindex); lladdr->sll_hatype = tswap16(lladdr->sll_hatype); + } else if (sa_family == AF_INET6) { + struct sockaddr_in6 *in6addr; + + in6addr = (struct sockaddr_in6 *)addr; + in6addr->sin6_scope_id = tswap32(in6addr->sin6_scope_id); } unlock_user(target_saddr, target_addr, 0); -- 2.39.2
From: Mathis Marion <mathis.marion@silabs.com> Newer kernel versions require this flag to be present contrary to older ones. Depending on the libnl version it is added or not. Typically when using rtnl_link_inet6_set_addr_gen_mode, the netlink packet generated may contain the following attribute: with libnl 3.4 {nla_len=16, nla_type=IFLA_AF_SPEC}, [ {nla_len=12, nla_type=AF_INET6}, [{nla_len=5, nla_type=IFLA_INET6_ADDR_GEN_MODE}, IN6_ADDR_GEN_MODE_NONE] ] with libnl 3.7 {nla_len=16, nla_type=NLA_F_NESTED|IFLA_AF_SPEC}, [ {nla_len=12, nla_type=NLA_F_NESTED|AF_INET6}, [{nla_len=5, nla_type=IFLA_INET6_ADDR_GEN_MODE}, IN6_ADDR_GEN_MODE_NONE]] ] Masking the type is likely needed in other places. Only the above cases are implemented in this patch. Signed-off-by: Mathis Marion <mathis.marion@silabs.com> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <20230307154256.101528-3-Mathis.Marion@silabs.com> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/fd-trans.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux-user/fd-trans.c b/linux-user/fd-trans.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/fd-trans.c +++ b/linux-user/fd-trans.c @@ -XXX,XX +XXX,XX @@ static abi_long target_to_host_for_each_rtattr(struct rtattr *rtattr, static abi_long target_to_host_data_spec_nlattr(struct nlattr *nlattr) { - switch (nlattr->nla_type) { + switch (nlattr->nla_type & NLA_TYPE_MASK) { case AF_INET6: return target_to_host_for_each_nlattr(NLA_DATA(nlattr), nlattr->nla_len, target_to_host_data_inet6_nlattr); @@ -XXX,XX +XXX,XX @@ static abi_long target_to_host_data_link_rtattr(struct rtattr *rtattr) { uint32_t *u32; - switch (rtattr->rta_type) { + switch (rtattr->rta_type & NLA_TYPE_MASK) { /* uint32_t */ case QEMU_IFLA_MTU: case QEMU_IFLA_TXQLEN: -- 2.39.2
From: Helge Deller <deller@gmx.de> msync() uses the flags MS_ASYNC, MS_INVALIDATE and MS_SYNC, which differ between platforms, specifcally on alpha and hppa. Add a target to host translation for those and wire up a nicer strace output. This fixes the testsuite of the macaulay2 debian package with a hppa-linux guest on a x86-64 host. Signed-off-by: Helge Deller <deller@gmx.de> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <Y5rMcts4qe15RaVN@p100> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/alpha/target_mman.h | 4 ++++ linux-user/generic/target_mman.h | 13 +++++++++++++ linux-user/hppa/target_mman.h | 4 ++++ linux-user/strace.list | 2 +- linux-user/syscall.c | 12 +++++++++++- 5 files changed, 33 insertions(+), 2 deletions(-) diff --git a/linux-user/alpha/target_mman.h b/linux-user/alpha/target_mman.h index XXXXXXX..XXXXXXX 100644 --- a/linux-user/alpha/target_mman.h +++ b/linux-user/alpha/target_mman.h @@ -XXX,XX +XXX,XX @@ #define TARGET_MADV_DONTNEED 6 +#define TARGET_MS_ASYNC 1 +#define TARGET_MS_SYNC 2 +#define TARGET_MS_INVALIDATE 4 + #include "../generic/target_mman.h" #endif diff --git a/linux-user/generic/target_mman.h b/linux-user/generic/target_mman.h index XXXXXXX..XXXXXXX 100644 --- a/linux-user/generic/target_mman.h +++ b/linux-user/generic/target_mman.h @@ -XXX,XX +XXX,XX @@ #define TARGET_MADV_DONTNEED_LOCKED 24 #endif + +#ifndef TARGET_MS_ASYNC +#define TARGET_MS_ASYNC 1 +#endif + +#ifndef TARGET_MS_INVALIDATE +#define TARGET_MS_INVALIDATE 2 +#endif + +#ifndef TARGET_MS_SYNC +#define TARGET_MS_SYNC 4 +#endif + #endif diff --git a/linux-user/hppa/target_mman.h b/linux-user/hppa/target_mman.h index XXXXXXX..XXXXXXX 100644 --- a/linux-user/hppa/target_mman.h +++ b/linux-user/hppa/target_mman.h @@ -XXX,XX +XXX,XX @@ #define TARGET_MADV_WIPEONFORK 71 #define TARGET_MADV_KEEPONFORK 72 +#define TARGET_MS_SYNC 1 +#define TARGET_MS_ASYNC 2 +#define TARGET_MS_INVALIDATE 4 + #include "../generic/target_mman.h" #endif diff --git a/linux-user/strace.list b/linux-user/strace.list index XXXXXXX..XXXXXXX 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -XXX,XX +XXX,XX @@ { TARGET_NR_msgsnd, "msgsnd" , NULL, NULL, NULL }, #endif #ifdef TARGET_NR_msync -{ TARGET_NR_msync, "msync" , NULL, NULL, NULL }, +{ TARGET_NR_msync, "msync" , "%s(%p,%u,%d)", NULL, NULL }, #endif #ifdef TARGET_NR_multiplexer { TARGET_NR_multiplexer, "multiplexer" , NULL, NULL, NULL }, diff --git a/linux-user/syscall.c b/linux-user/syscall.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -XXX,XX +XXX,XX @@ #include "qemu/path.h" #include "qemu/memfd.h" #include "qemu/queue.h" +#include "target_mman.h" #include <elf.h> #include <endian.h> #include <grp.h> @@ -XXX,XX +XXX,XX @@ static inline int target_to_host_mlockall_arg(int arg) } #endif +static inline int target_to_host_msync_arg(abi_long arg) +{ + return ((arg & TARGET_MS_ASYNC) ? MS_ASYNC : 0) | + ((arg & TARGET_MS_INVALIDATE) ? MS_INVALIDATE : 0) | + ((arg & TARGET_MS_SYNC) ? MS_SYNC : 0) | + (arg & ~(TARGET_MS_ASYNC | TARGET_MS_INVALIDATE | TARGET_MS_SYNC)); +} + #if (defined(TARGET_NR_stat64) || defined(TARGET_NR_lstat64) || \ defined(TARGET_NR_fstat64) || defined(TARGET_NR_fstatat64) || \ defined(TARGET_NR_newfstatat)) @@ -XXX,XX +XXX,XX @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, /* ??? msync/mlock/munlock are broken for softmmu. */ #ifdef TARGET_NR_msync case TARGET_NR_msync: - return get_errno(msync(g2h(cpu, arg1), arg2, arg3)); + return get_errno(msync(g2h(cpu, arg1), arg2, + target_to_host_msync_arg(arg3))); #endif #ifdef TARGET_NR_mlock case TARGET_NR_mlock: -- 2.39.2
From: Helge Deller <deller@gmx.de> Add emulation for the CLONE_PIDFD flag of the clone() syscall. This flag was added in Linux kernel 5.2. Successfully tested on a x86-64 Linux host with hppa-linux target. Can be verified by running the testsuite of the qcoro debian package, which breaks hard and kills the currently logged-in user without this patch. Signed-off-by: Helge Deller <deller@gmx.de> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <Y4XoJCpvUA1JD7Sj@p100> [lv: define CLONE_PIDFD if it is not] Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/strace.c | 5 +++++ linux-user/syscall.c | 31 ++++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -XXX,XX +XXX,XX @@ UNUSED static const struct flags mmap_flags[] = { FLAG_END, }; +#ifndef CLONE_PIDFD +# define CLONE_PIDFD 0x00001000 +#endif + UNUSED static const struct flags clone_flags[] = { FLAG_GENERIC(CLONE_VM), FLAG_GENERIC(CLONE_FS), FLAG_GENERIC(CLONE_FILES), FLAG_GENERIC(CLONE_SIGHAND), + FLAG_GENERIC(CLONE_PIDFD), FLAG_GENERIC(CLONE_PTRACE), FLAG_GENERIC(CLONE_VFORK), FLAG_GENERIC(CLONE_PARENT), diff --git a/linux-user/syscall.c b/linux-user/syscall.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -XXX,XX +XXX,XX @@ #define CLONE_IGNORED_FLAGS \ (CLONE_DETACHED | CLONE_IO) +#ifndef CLONE_PIDFD +# define CLONE_PIDFD 0x00001000 +#endif + /* Flags for fork which we can implement within QEMU itself */ #define CLONE_OPTIONAL_FORK_FLAGS \ - (CLONE_SETTLS | CLONE_PARENT_SETTID | \ + (CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_PIDFD | \ CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID) /* Flags for thread creation which we can implement within QEMU itself */ @@ -XXX,XX +XXX,XX @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, return -TARGET_EINVAL; } +#if !defined(__NR_pidfd_open) || !defined(TARGET_NR_pidfd_open) + if (flags & CLONE_PIDFD) { + return -TARGET_EINVAL; + } +#endif + + /* Can not allow CLONE_PIDFD with CLONE_PARENT_SETTID */ + if ((flags & CLONE_PIDFD) && (flags & CLONE_PARENT_SETTID)) { + return -TARGET_EINVAL; + } + if (block_signals()) { return -QEMU_ERESTARTSYS; } @@ -XXX,XX +XXX,XX @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, ts->child_tidptr = child_tidptr; } else { cpu_clone_regs_parent(env, flags); + if (flags & CLONE_PIDFD) { + int pid_fd = 0; +#if defined(__NR_pidfd_open) && defined(TARGET_NR_pidfd_open) + int pid_child = ret; + pid_fd = pidfd_open(pid_child, 0); + if (pid_fd >= 0) { + fcntl(pid_fd, F_SETFD, fcntl(pid_fd, F_GETFL) + | FD_CLOEXEC); + } else { + pid_fd = 0; + } +#endif + put_user_u32(pid_fd, parent_tidptr); + } fork_end(0); } g_assert(!cpu_in_exclusive_context(cpu)); -- 2.39.2
From: Richard Henderson <richard.henderson@linaro.org> Use TT_TRAP. For sparc32, 0x88 is the "Slowaris" system call, currently BAD_TRAP in the kernel's ttable_32.S. For sparc64, 0x110 is tl0_linux32, the sparc32 trap, now folded into the TARGET_ABI32 case via TT_TRAP. For sparc64, there does still exist trap 0x111 as tl0_oldlinux64, which was replaced by 0x16d as tl0_linux64 in 1998. Since no one has noticed, don't bother implementing it now. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-Id: <20230216054516.1267305-3-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/sparc/cpu_loop.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/linux-user/sparc/cpu_loop.c b/linux-user/sparc/cpu_loop.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/sparc/cpu_loop.c +++ b/linux-user/sparc/cpu_loop.c @@ -XXX,XX +XXX,XX @@ static void flush_windows(CPUSPARCState *env) #endif } +#ifdef TARGET_ABI32 +#define TARGET_TT_SYSCALL (TT_TRAP + 0x10) /* t_linux */ +#else +#define TARGET_TT_SYSCALL (TT_TRAP + 0x6d) /* tl0_linux64 */ +#endif + void cpu_loop (CPUSPARCState *env) { CPUState *cs = env_cpu(env); @@ -XXX,XX +XXX,XX @@ void cpu_loop (CPUSPARCState *env) } switch (trapnr) { -#ifndef TARGET_SPARC64 - case 0x88: - case 0x90: -#else - case 0x110: - case 0x16d: -#endif + case TARGET_TT_SYSCALL: ret = do_syscall (env, env->gregs[1], env->regwptr[0], env->regwptr[1], env->regwptr[2], env->regwptr[3], -- 2.39.2
From: Richard Henderson <richard.henderson@linaro.org> Reduce ifdefs with #define syscall_cc. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20230216054516.1267305-4-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/sparc/cpu_loop.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/linux-user/sparc/cpu_loop.c b/linux-user/sparc/cpu_loop.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/sparc/cpu_loop.c +++ b/linux-user/sparc/cpu_loop.c @@ -XXX,XX +XXX,XX @@ static void flush_windows(CPUSPARCState *env) #endif } +/* Avoid ifdefs below for the abi32 and abi64 paths. */ #ifdef TARGET_ABI32 #define TARGET_TT_SYSCALL (TT_TRAP + 0x10) /* t_linux */ +#define syscall_cc psr #else #define TARGET_TT_SYSCALL (TT_TRAP + 0x6d) /* tl0_linux64 */ +#define syscall_cc xcc #endif void cpu_loop (CPUSPARCState *env) @@ -XXX,XX +XXX,XX @@ void cpu_loop (CPUSPARCState *env) break; } if ((abi_ulong)ret >= (abi_ulong)(-515)) { -#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) - env->xcc |= PSR_CARRY; -#else - env->psr |= PSR_CARRY; -#endif + env->syscall_cc |= PSR_CARRY; ret = -ret; } else { -#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) - env->xcc &= ~PSR_CARRY; -#else - env->psr &= ~PSR_CARRY; -#endif + env->syscall_cc &= ~PSR_CARRY; } env->regwptr[0] = ret; /* next instruction */ -- 2.39.2
From: Richard Henderson <richard.henderson@linaro.org> The v9 and pre-v9 code can be unified with this macro. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-Id: <20230216054516.1267305-5-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/sparc/cpu_loop.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/linux-user/sparc/cpu_loop.c b/linux-user/sparc/cpu_loop.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/sparc/cpu_loop.c +++ b/linux-user/sparc/cpu_loop.c @@ -XXX,XX +XXX,XX @@ void cpu_loop (CPUSPARCState *env) env->pc = env->npc; env->npc = env->npc + 4; break; - case 0x83: /* flush windows */ -#ifdef TARGET_ABI32 - case 0x103: -#endif + + case TT_TRAP + 0x03: /* flush windows */ flush_windows(env); /* next instruction */ env->pc = env->npc; env->npc = env->npc + 4; break; + #ifndef TARGET_SPARC64 case TT_WIN_OVF: /* window overflow */ save_window(env); -- 2.39.2
From: Richard Henderson <richard.henderson@linaro.org> Add some macros to localize the hw difference between v9 and pre-v9. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-Id: <20230216054516.1267305-6-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/sparc/cpu_loop.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/linux-user/sparc/cpu_loop.c b/linux-user/sparc/cpu_loop.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/sparc/cpu_loop.c +++ b/linux-user/sparc/cpu_loop.c @@ -XXX,XX +XXX,XX @@ static void flush_windows(CPUSPARCState *env) #define syscall_cc xcc #endif +/* Avoid ifdefs below for the v9 and pre-v9 hw traps. */ +#ifdef TARGET_SPARC64 +#define TARGET_TT_SPILL TT_SPILL +#define TARGET_TT_FILL TT_FILL +#else +#define TARGET_TT_SPILL TT_WIN_OVF +#define TARGET_TT_FILL TT_WIN_UNF +#endif + void cpu_loop (CPUSPARCState *env) { CPUState *cs = env_cpu(env); @@ -XXX,XX +XXX,XX @@ void cpu_loop (CPUSPARCState *env) env->npc = env->npc + 4; break; -#ifndef TARGET_SPARC64 - case TT_WIN_OVF: /* window overflow */ - save_window(env); - break; - case TT_WIN_UNF: /* window underflow */ - restore_window(env); - break; -#else - case TT_SPILL: /* window overflow */ + case TARGET_TT_SPILL: /* window overflow */ save_window(env); break; - case TT_FILL: /* window underflow */ + case TARGET_TT_FILL: /* window underflow */ restore_window(env); break; + +#ifdef TARGET_SPARC64 #ifndef TARGET_ABI32 case 0x16e: flush_windows(env); -- 2.39.2
From: Richard Henderson <richard.henderson@linaro.org> These traps are present for sparc64 with ilp32, aka sparc32plus. Enabling them means adjusting the defines over in signal.c, and fixing an incorrect usage of abi_ulong when we really meant the full register, target_ulong. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20230216054516.1267305-7-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/sparc/cpu_loop.c | 21 ++++++++++----------- linux-user/sparc/signal.c | 36 +++++++++++++++++++----------------- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/linux-user/sparc/cpu_loop.c b/linux-user/sparc/cpu_loop.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/sparc/cpu_loop.c +++ b/linux-user/sparc/cpu_loop.c @@ -XXX,XX +XXX,XX @@ void cpu_loop (CPUSPARCState *env) env->npc = env->npc + 4; break; - case TARGET_TT_SPILL: /* window overflow */ - save_window(env); - break; - case TARGET_TT_FILL: /* window underflow */ - restore_window(env); - break; - #ifdef TARGET_SPARC64 -#ifndef TARGET_ABI32 - case 0x16e: + case TT_TRAP + 0x6e: flush_windows(env); sparc64_get_context(env); break; - case 0x16f: + case TT_TRAP + 0x6f: flush_windows(env); sparc64_set_context(env); break; #endif -#endif + + case TARGET_TT_SPILL: /* window overflow */ + save_window(env); + break; + case TARGET_TT_FILL: /* window underflow */ + restore_window(env); + break; + case EXCP_INTERRUPT: /* just indicate that signals should be handled asap */ break; diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/sparc/signal.c +++ b/linux-user/sparc/signal.c @@ -XXX,XX +XXX,XX @@ long do_rt_sigreturn(CPUSPARCState *env) return -QEMU_ESIGRETURN; } -#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) +#ifdef TARGET_ABI32 +void setup_sigtramp(abi_ulong sigtramp_page) +{ + uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 2 * 8, 0); + assert(tramp != NULL); + + default_sigreturn = sigtramp_page; + install_sigtramp(tramp, TARGET_NR_sigreturn); + + default_rt_sigreturn = sigtramp_page + 8; + install_sigtramp(tramp + 2, TARGET_NR_rt_sigreturn); + + unlock_user(tramp, sigtramp_page, 2 * 8); +} +#endif + +#ifdef TARGET_SPARC64 #define SPARC_MC_TSTATE 0 #define SPARC_MC_PC 1 #define SPARC_MC_NPC 2 @@ -XXX,XX +XXX,XX @@ void sparc64_set_context(CPUSPARCState *env) struct target_ucontext *ucp; target_mc_gregset_t *grp; target_mc_fpu_t *fpup; - abi_ulong pc, npc, tstate; + target_ulong pc, npc, tstate; unsigned int i; unsigned char fenab; @@ -XXX,XX +XXX,XX @@ do_sigsegv: unlock_user_struct(ucp, ucp_addr, 1); force_sig(TARGET_SIGSEGV); } -#else -void setup_sigtramp(abi_ulong sigtramp_page) -{ - uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 2 * 8, 0); - assert(tramp != NULL); - - default_sigreturn = sigtramp_page; - install_sigtramp(tramp, TARGET_NR_sigreturn); - - default_rt_sigreturn = sigtramp_page + 8; - install_sigtramp(tramp + 2, TARGET_NR_rt_sigreturn); - - unlock_user(tramp, sigtramp_page, 2 * 8); -} -#endif +#endif /* TARGET_SPARC64 */ -- 2.39.2
From: Richard Henderson <richard.henderson@linaro.org> This is 'ta 1' for both v9 and pre-v9. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20230216054516.1267305-8-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/sparc/cpu_loop.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/linux-user/sparc/cpu_loop.c b/linux-user/sparc/cpu_loop.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/sparc/cpu_loop.c +++ b/linux-user/sparc/cpu_loop.c @@ -XXX,XX +XXX,XX @@ void cpu_loop (CPUSPARCState *env) env->npc = env->npc + 4; break; + case TT_TRAP + 0x01: /* breakpoint */ + case EXCP_DEBUG: + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); + break; + case TT_TRAP + 0x03: /* flush windows */ flush_windows(env); /* next instruction */ @@ -XXX,XX +XXX,XX @@ void cpu_loop (CPUSPARCState *env) case TT_ILL_INSN: force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc); break; - case EXCP_DEBUG: - force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); - break; case EXCP_ATOMIC: cpu_exec_step_atomic(cs); break; -- 2.39.2
From: Richard Henderson <richard.henderson@linaro.org> In addition to the hw trap vector, there is a software trap assigned for older sparc without hw division instructions. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20230216054516.1267305-9-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/sparc/cpu_loop.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/linux-user/sparc/cpu_loop.c b/linux-user/sparc/cpu_loop.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/sparc/cpu_loop.c +++ b/linux-user/sparc/cpu_loop.c @@ -XXX,XX +XXX,XX @@ void cpu_loop (CPUSPARCState *env) force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); break; + case TT_TRAP + 0x02: /* div0 */ + case TT_DIV_ZERO: + force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTDIV, env->pc); + break; + case TT_TRAP + 0x03: /* flush windows */ flush_windows(env); /* next instruction */ -- 2.39.2
From: Richard Henderson <richard.henderson@linaro.org> These are really only meaningful for sparc32, but they're still present for backward compatibility for sparc64. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20230216054516.1267305-10-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/sparc/cpu_loop.c | 62 +++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/linux-user/sparc/cpu_loop.c b/linux-user/sparc/cpu_loop.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/sparc/cpu_loop.c +++ b/linux-user/sparc/cpu_loop.c @@ -XXX,XX +XXX,XX @@ static void flush_windows(CPUSPARCState *env) #endif } +static void next_instruction(CPUSPARCState *env) +{ + env->pc = env->npc; + env->npc = env->npc + 4; +} + +static uint32_t do_getcc(CPUSPARCState *env) +{ +#ifdef TARGET_SPARC64 + return cpu_get_ccr(env) & 0xf; +#else + return extract32(cpu_get_psr(env), 20, 4); +#endif +} + +static void do_setcc(CPUSPARCState *env, uint32_t icc) +{ +#ifdef TARGET_SPARC64 + cpu_put_ccr(env, (cpu_get_ccr(env) & 0xf0) | (icc & 0xf)); +#else + cpu_put_psr(env, deposit32(cpu_get_psr(env), 20, 4, icc)); +#endif +} + +static uint32_t do_getpsr(CPUSPARCState *env) +{ +#ifdef TARGET_SPARC64 + const uint64_t TSTATE_CWP = 0x1f; + const uint64_t TSTATE_ICC = 0xfull << 32; + const uint64_t TSTATE_XCC = 0xfull << 36; + const uint32_t PSR_S = 0x00000080u; + const uint32_t PSR_V8PLUS = 0xff000000u; + uint64_t tstate = sparc64_tstate(env); + + /* See <asm/psrcompat.h>, tstate_to_psr. */ + return ((tstate & TSTATE_CWP) | + PSR_S | + ((tstate & TSTATE_ICC) >> 12) | + ((tstate & TSTATE_XCC) >> 20) | + PSR_V8PLUS); +#else + return (cpu_get_psr(env) & (PSR_ICC | PSR_CWP)) | PSR_S; +#endif +} + /* Avoid ifdefs below for the abi32 and abi64 paths. */ #ifdef TARGET_ABI32 #define TARGET_TT_SYSCALL (TT_TRAP + 0x10) /* t_linux */ @@ -XXX,XX +XXX,XX @@ void cpu_loop (CPUSPARCState *env) case TT_TRAP + 0x03: /* flush windows */ flush_windows(env); - /* next instruction */ - env->pc = env->npc; - env->npc = env->npc + 4; + next_instruction(env); + break; + + case TT_TRAP + 0x20: /* getcc */ + env->gregs[1] = do_getcc(env); + next_instruction(env); + break; + case TT_TRAP + 0x21: /* setcc */ + do_setcc(env, env->gregs[1]); + next_instruction(env); + break; + case TT_TRAP + 0x22: /* getpsr */ + env->gregs[1] = do_getpsr(env); + next_instruction(env); break; #ifdef TARGET_SPARC64 -- 2.39.2
From: Richard Henderson <richard.henderson@linaro.org> For the most part priviledged opcodes are ifdefed out of the user-only sparc translator, which will then incorrectly produce illegal opcode traps. But there are some code paths that properly raise TT_PRIV_INSN, so we must handle it. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20230216054516.1267305-11-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/sparc/cpu_loop.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/linux-user/sparc/cpu_loop.c b/linux-user/sparc/cpu_loop.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/sparc/cpu_loop.c +++ b/linux-user/sparc/cpu_loop.c @@ -XXX,XX +XXX,XX @@ void cpu_loop (CPUSPARCState *env) case TT_ILL_INSN: force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc); break; + case TT_PRIV_INSN: + force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, env->pc); + break; case EXCP_ATOMIC: cpu_exec_step_atomic(cs); break; -- 2.39.2
From: Richard Henderson <richard.henderson@linaro.org> This is raised by using an %asi < 0x80 in user-mode. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20230216054516.1267305-12-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/sparc/cpu_loop.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/linux-user/sparc/cpu_loop.c b/linux-user/sparc/cpu_loop.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/sparc/cpu_loop.c +++ b/linux-user/sparc/cpu_loop.c @@ -XXX,XX +XXX,XX @@ void cpu_loop (CPUSPARCState *env) case TT_PRIV_INSN: force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, env->pc); break; +#ifdef TARGET_SPARC64 + case TT_PRIV_ACT: + /* Note do_privact defers to do_privop. */ + force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, env->pc); + break; +#endif case EXCP_ATOMIC: cpu_exec_step_atomic(cs); break; -- 2.39.2
From: Richard Henderson <richard.henderson@linaro.org> Since qemu does not implement a sparc coprocessor, all such instructions raise this trap. Because of that, we never raise the coprocessor exception trap, which would be vector 0x28. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20230216054516.1267305-13-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/sparc/cpu_loop.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/linux-user/sparc/cpu_loop.c b/linux-user/sparc/cpu_loop.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/sparc/cpu_loop.c +++ b/linux-user/sparc/cpu_loop.c @@ -XXX,XX +XXX,XX @@ void cpu_loop (CPUSPARCState *env) /* Note do_privact defers to do_privop. */ force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, env->pc); break; +#else + case TT_NCP_INSN: + force_sig_fault(TARGET_SIGILL, TARGET_ILL_COPROC, env->pc); + break; #endif case EXCP_ATOMIC: cpu_exec_step_atomic(cs); -- 2.39.2
From: Richard Henderson <richard.henderson@linaro.org> For sparc64, TT_UNIMP_FLUSH == TT_ILL_INSN, so this is already handled. For sparc32, the kernel uses SKIP_TRAP. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20230216054516.1267305-14-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/sparc/cpu_loop.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/linux-user/sparc/cpu_loop.c b/linux-user/sparc/cpu_loop.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/sparc/cpu_loop.c +++ b/linux-user/sparc/cpu_loop.c @@ -XXX,XX +XXX,XX @@ void cpu_loop (CPUSPARCState *env) case TT_NCP_INSN: force_sig_fault(TARGET_SIGILL, TARGET_ILL_COPROC, env->pc); break; + case TT_UNIMP_FLUSH: + next_instruction(env); + break; #endif case EXCP_ATOMIC: cpu_exec_step_atomic(cs); -- 2.39.2
From: Richard Henderson <richard.henderson@linaro.org> Raise SIGFPE for ieee exceptions. The other types, such as FSR_FTT_UNIMPFPOP, should not appear, because we enable normal emulation of missing insns at the start of sparc_cpu_realizefn(). Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20230216054516.1267305-15-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/sparc/cpu_loop.c | 22 ++++++++++++++++++++++ target/sparc/cpu.h | 3 +-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/linux-user/sparc/cpu_loop.c b/linux-user/sparc/cpu_loop.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/sparc/cpu_loop.c +++ b/linux-user/sparc/cpu_loop.c @@ -XXX,XX +XXX,XX @@ void cpu_loop (CPUSPARCState *env) restore_window(env); break; + case TT_FP_EXCP: + { + int code = TARGET_FPE_FLTUNK; + target_ulong fsr = env->fsr; + + if ((fsr & FSR_FTT_MASK) == FSR_FTT_IEEE_EXCP) { + if (fsr & FSR_NVC) { + code = TARGET_FPE_FLTINV; + } else if (fsr & FSR_OFC) { + code = TARGET_FPE_FLTOVF; + } else if (fsr & FSR_UFC) { + code = TARGET_FPE_FLTUND; + } else if (fsr & FSR_DZC) { + code = TARGET_FPE_FLTDIV; + } else if (fsr & FSR_NXC) { + code = TARGET_FPE_FLTRES; + } + } + force_sig_fault(TARGET_SIGFPE, code, env->pc); + } + break; + case EXCP_INTERRUPT: /* just indicate that signals should be handled asap */ break; diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/sparc/cpu.h +++ b/target/sparc/cpu.h @@ -XXX,XX +XXX,XX @@ enum { #define FSR_FTT2 (1ULL << 16) #define FSR_FTT1 (1ULL << 15) #define FSR_FTT0 (1ULL << 14) -//gcc warns about constant overflow for ~FSR_FTT_MASK -//#define FSR_FTT_MASK (FSR_FTT2 | FSR_FTT1 | FSR_FTT0) +#define FSR_FTT_MASK (FSR_FTT2 | FSR_FTT1 | FSR_FTT0) #ifdef TARGET_SPARC64 #define FSR_FTT_NMASK 0xfffffffffffe3fffULL #define FSR_FTT_CEXC_NMASK 0xfffffffffffe3fe0ULL -- 2.39.2
From: Richard Henderson <richard.henderson@linaro.org> This trap is raised by taddcctv and tsubcctv insns. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20230216054516.1267305-16-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/sparc/cpu_loop.c | 3 +++ linux-user/sparc/target_signal.h | 2 +- linux-user/syscall_defs.h | 5 +++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/linux-user/sparc/cpu_loop.c b/linux-user/sparc/cpu_loop.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/sparc/cpu_loop.c +++ b/linux-user/sparc/cpu_loop.c @@ -XXX,XX +XXX,XX @@ void cpu_loop (CPUSPARCState *env) case TT_PRIV_INSN: force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, env->pc); break; + case TT_TOVF: + force_sig_fault(TARGET_SIGEMT, TARGET_EMT_TAGOVF, env->pc); + break; #ifdef TARGET_SPARC64 case TT_PRIV_ACT: /* Note do_privact defers to do_privop. */ diff --git a/linux-user/sparc/target_signal.h b/linux-user/sparc/target_signal.h index XXXXXXX..XXXXXXX 100644 --- a/linux-user/sparc/target_signal.h +++ b/linux-user/sparc/target_signal.h @@ -XXX,XX +XXX,XX @@ #define TARGET_SIGTRAP 5 #define TARGET_SIGABRT 6 #define TARGET_SIGIOT 6 -#define TARGET_SIGSTKFLT 7 /* actually EMT */ +#define TARGET_SIGEMT 7 #define TARGET_SIGFPE 8 #define TARGET_SIGKILL 9 #define TARGET_SIGBUS 10 diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index XXXXXXX..XXXXXXX 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -XXX,XX +XXX,XX @@ typedef struct target_siginfo { #define TARGET_TRAP_HWBKPT (4) /* hardware breakpoint/watchpoint */ #define TARGET_TRAP_UNK (5) /* undiagnosed trap */ +/* + * SIGEMT si_codes + */ +#define TARGET_EMT_TAGOVF 1 /* tag overflow */ + #include "target_resource.h" struct target_pollfd { -- 2.39.2
From: "fanwj@mail.ustc.edu.cn" <fanwj@mail.ustc.edu.cn> On linux user mode, CPUX86State::gdt::base from Different CPUX86State Objects have same value, It is incorrect! Every CPUX86State::gdt::base Must points to independent memory space. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1405 Signed-off-by: fanwenjie <fanwj@mail.ustc.edu.cn> Message-Id: <4172b90.58b08.18631b77860.Coremail.fanwj@mail.ustc.edu.cn> [lv: remove unnecessary casts, split overlong line] Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- linux-user/i386/cpu_loop.c | 9 +++++++++ linux-user/main.c | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/linux-user/i386/cpu_loop.c b/linux-user/i386/cpu_loop.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/i386/cpu_loop.c +++ b/linux-user/i386/cpu_loop.c @@ -XXX,XX +XXX,XX @@ void cpu_loop(CPUX86State *env) } } +static void target_cpu_free(void *obj) +{ + CPUArchState *env = ((CPUState *)obj)->env_ptr; + target_munmap(env->gdt.base, sizeof(uint64_t) * TARGET_GDT_ENTRIES); + g_free(obj); +} + void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) { + CPUState *cpu = env_cpu(env); + OBJECT(cpu)->free = target_cpu_free; env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK; env->hflags |= HF_PE_MASK | HF_CPL_MASK; if (env->features[FEAT_1_EDX] & CPUID_SSE) { diff --git a/linux-user/main.c b/linux-user/main.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -XXX,XX +XXX,XX @@ CPUArchState *cpu_copy(CPUArchState *env) new_cpu->tcg_cflags = cpu->tcg_cflags; memcpy(new_env, env, sizeof(CPUArchState)); +#if defined(TARGET_I386) || defined(TARGET_X86_64) + new_env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES, + PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + memcpy(g2h_untagged(new_env->gdt.base), g2h_untagged(env->gdt.base), + sizeof(uint64_t) * TARGET_GDT_ENTRIES); + OBJECT(new_cpu)->free = OBJECT(cpu)->free; +#endif /* Clone all break/watchpoints. Note: Once we support ptrace with hw-debug register access, make sure -- 2.39.2