summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2022-06-24 08:58:33 -0700
committerRichard Henderson <richard.henderson@linaro.org>2022-06-24 08:58:33 -0700
commit8b5669e40f05ff1a1cb865ccc1bdb079b7bfc92c (patch)
tree94504dd8e326f7d026f9627a08a6936264d0b8d4
parent3a821c52e1a30ecd9a436f2c67cc66b5628c829f (diff)
parent9a7f682c26acae5bc8bfd1f7c774070da54f1625 (diff)
downloadfocaccia-qemu-8b5669e40f05ff1a1cb865ccc1bdb079b7bfc92c.tar.gz
focaccia-qemu-8b5669e40f05ff1a1cb865ccc1bdb079b7bfc92c.zip
Merge tag 'linux-user-for-7.1-pull-request' of https://gitlab.com/laurent_vivier/qemu into staging
linux-user pull request 20220624

# -----BEGIN PGP SIGNATURE-----
#
# iQJGBAABCAAwFiEEzS913cjjpNwuT1Fz8ww4vT8vvjwFAmK1iJISHGxhdXJlbnRA
# dml2aWVyLmV1AAoJEPMMOL0/L748NYIP/R11Ztk4XH8LNDszg/s0y+D3FJm3XAkj
# 5LHaJdRGu9KsCO1zVkZDbhm81LIzY8yEzoQKZhV0vy6A071A2QNp8Pu6JZ4fMt6H
# kIwKclwW7WOiI8Ox+cLW4YYPJvY0tbe9yGoHJnLQjjYOOPeoUQKJ/0wK6sBgnK4y
# R8u2x4AvE5hgFfQvI0HRF1Q1e4y5MQt1WmLIxsGl2yCKzKWA0LrPuLgLROLQPbFj
# R/7fNwQkFW0PGnyyd8MMzRTEV6mdNZ9rQDA8/n2Nqgf7uQQFsOpHfXnhoJPz/CGi
# njhixJXingozKb/mX8OA5/NO0Ps7n7/WgugB36QvaoG9M4+E+9vjOkKTFo0LtfeA
# r75++/gNcJhQrMRU6/jSRx25dlWjfuLmEbUVvvGYtgQJ1hsAs6UwXO9EF5n4ZOr8
# qzgbW0GssvFO8+Ow5HQvWOHENR6ylJSSGc0bvX61ZH+h7cJRbELCiO3wkpyGe8zN
# OjG4tHbAnqKhN52k2uannNnPPqXI4f7GMV91pPXqM5oppY0BNMKRC6+nIS6Ew1D3
# FnNDwYJcDBXRY+Abqdrxfx2BSC35cl7Bfl+OVkXal9tGZTmFB+NOaeFWs9fdHXFA
# QE0Ct3xMut6SfJCNLvHwvBHwYq5yDCV/dngGonqgacn+F/epkbdY9sdlsYeRbud2
# h1tremHRgq9e
# =6mTR
# -----END PGP SIGNATURE-----
# gpg: Signature made Fri 24 Jun 2022 02:49:06 AM PDT
# gpg:                using RSA key CD2F75DDC8E3A4DC2E4F5173F30C38BD3F2FBE3C
# gpg:                issuer "laurent@vivier.eu"
# gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [undefined]
# gpg:                 aka "Laurent Vivier <laurent@vivier.eu>" [undefined]
# gpg:                 aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [undefined]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F  5173 F30C 38BD 3F2F BE3C

* tag 'linux-user-for-7.1-pull-request' of https://gitlab.com/laurent_vivier/qemu:
  linux-user: Adjust child_tidptr on set_tid_address() syscall
  linux-user: Add partial support for MADV_DONTNEED
  linux-user/x86_64: Fix ELF_PLATFORM

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
-rw-r--r--linux-user/elfload.c30
-rw-r--r--linux-user/mmap.c64
-rw-r--r--linux-user/syscall.c20
-rw-r--r--linux-user/user-internals.h1
-rw-r--r--linux-user/user-mmap.h1
5 files changed, 92 insertions, 24 deletions
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index f7eae357f4..163fc8a1ee 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -130,19 +130,6 @@ typedef abi_int         target_pid_t;
 
 #ifdef TARGET_I386
 
-#define ELF_PLATFORM get_elf_platform()
-
-static const char *get_elf_platform(void)
-{
-    static char elf_platform[] = "i386";
-    int family = object_property_get_int(OBJECT(thread_cpu), "family", NULL);
-    if (family > 6)
-        family = 6;
-    if (family >= 3)
-        elf_platform[1] = '0' + family;
-    return elf_platform;
-}
-
 #define ELF_HWCAP get_elf_hwcap()
 
 static uint32_t get_elf_hwcap(void)
@@ -158,6 +145,8 @@ static uint32_t get_elf_hwcap(void)
 #define ELF_CLASS      ELFCLASS64
 #define ELF_ARCH       EM_X86_64
 
+#define ELF_PLATFORM   "x86_64"
+
 static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
 {
     regs->rax = 0;
@@ -221,6 +210,21 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *en
 #define ELF_CLASS       ELFCLASS32
 #define ELF_ARCH        EM_386
 
+#define ELF_PLATFORM get_elf_platform()
+
+static const char *get_elf_platform(void)
+{
+    static char elf_platform[] = "i386";
+    int family = object_property_get_int(OBJECT(thread_cpu), "family", NULL);
+    if (family > 6) {
+        family = 6;
+    }
+    if (family >= 3) {
+        elf_platform[1] = '0' + family;
+    }
+    return elf_platform;
+}
+
 static inline void init_thread(struct target_pt_regs *regs,
                                struct image_info *infop)
 {
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 48e1373796..4e7a6be6ee 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -835,3 +835,67 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
     mmap_unlock();
     return new_addr;
 }
+
+static bool can_passthrough_madv_dontneed(abi_ulong start, abi_ulong end)
+{
+    ulong addr;
+
+    if ((start | end) & ~qemu_host_page_mask) {
+        return false;
+    }
+
+    for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
+        if (!(page_get_flags(addr) & PAGE_ANON)) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+abi_long target_madvise(abi_ulong start, abi_ulong len_in, int advice)
+{
+    abi_ulong len, end;
+    int ret = 0;
+
+    if (start & ~TARGET_PAGE_MASK) {
+        return -TARGET_EINVAL;
+    }
+    len = TARGET_PAGE_ALIGN(len_in);
+
+    if (len_in && !len) {
+        return -TARGET_EINVAL;
+    }
+
+    end = start + len;
+    if (end < start) {
+        return -TARGET_EINVAL;
+    }
+
+    if (end == start) {
+        return 0;
+    }
+
+    if (!guest_range_valid_untagged(start, len)) {
+        return -TARGET_EINVAL;
+    }
+
+    /*
+     * A straight passthrough may not be safe because qemu sometimes turns
+     * private file-backed mappings into anonymous mappings.
+     *
+     * This is a hint, so ignoring and returning success is ok.
+     *
+     * This breaks MADV_DONTNEED, completely implementing which is quite
+     * complicated. However, there is one low-hanging fruit: host-page-aligned
+     * anonymous mappings. In this case passthrough is safe, so do it.
+     */
+    mmap_lock();
+    if ((advice & MADV_DONTNEED) &&
+        can_passthrough_madv_dontneed(start, end)) {
+        ret = get_errno(madvise(g2h_untagged(start), len, MADV_DONTNEED));
+    }
+    mmap_unlock();
+
+    return ret;
+}
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index f55cdebee5..669add74c1 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -320,9 +320,6 @@ _syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
 #ifdef __NR_exit_group
 _syscall1(int,exit_group,int,error_code)
 #endif
-#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
-_syscall1(int,set_tid_address,int *,tidptr)
-#endif
 #if defined(__NR_futex)
 _syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
           const struct timespec *,timeout,int *,uaddr2,int,val3)
@@ -538,7 +535,7 @@ static inline int target_to_host_errno(int target_errno)
     }
 }
 
-static inline abi_long get_errno(abi_long ret)
+abi_long get_errno(abi_long ret)
 {
     if (ret == -1)
         return -host_to_target_errno(errno);
@@ -11807,11 +11804,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
 
 #ifdef TARGET_NR_madvise
     case TARGET_NR_madvise:
-        /* A straight passthrough may not be safe because qemu sometimes
-           turns private file-backed mappings into anonymous mappings.
-           This will break MADV_DONTNEED.
-           This is a hint, so ignoring and returning success is ok.  */
-        return 0;
+        return target_madvise(arg1, arg2, arg3);
 #endif
 #ifdef TARGET_NR_fcntl64
     case TARGET_NR_fcntl64:
@@ -12200,9 +12193,14 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
     }
 #endif
 
-#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
+#if defined(TARGET_NR_set_tid_address)
     case TARGET_NR_set_tid_address:
-        return get_errno(set_tid_address((int *)g2h(cpu, arg1)));
+    {
+        TaskState *ts = cpu->opaque;
+        ts->child_tidptr = arg1;
+        /* do not call host set_tid_address() syscall, instead return tid() */
+        return get_errno(sys_gettid());
+    }
 #endif
 
     case TARGET_NR_tkill:
diff --git a/linux-user/user-internals.h b/linux-user/user-internals.h
index 6175ce53db..0280e76add 100644
--- a/linux-user/user-internals.h
+++ b/linux-user/user-internals.h
@@ -65,6 +65,7 @@ abi_long do_syscall(CPUArchState *cpu_env, int num, abi_long arg1,
                     abi_long arg8);
 extern __thread CPUState *thread_cpu;
 G_NORETURN void cpu_loop(CPUArchState *env);
+abi_long get_errno(abi_long ret);
 const char *target_strerror(int err);
 int get_osversion(void);
 void init_qemu_uname_release(void);
diff --git a/linux-user/user-mmap.h b/linux-user/user-mmap.h
index d1dec99c02..480ce1c114 100644
--- a/linux-user/user-mmap.h
+++ b/linux-user/user-mmap.h
@@ -25,6 +25,7 @@ int target_munmap(abi_ulong start, abi_ulong len);
 abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
                        abi_ulong new_size, unsigned long flags,
                        abi_ulong new_addr);
+abi_long target_madvise(abi_ulong start, abi_ulong len_in, int advice);
 extern unsigned long last_brk;
 extern abi_ulong mmap_next_start;
 abi_ulong mmap_find_vma(abi_ulong, abi_ulong, abi_ulong);