qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v6 00/19] linux-user: Implement VDSOs
@ 2023-09-30  2:15 Richard Henderson
  2023-09-30  2:15 ` [PATCH v6 01/19] linux-user: Introduce imgsrc_read, imgsrc_read_alloc Richard Henderson
                   ` (18 more replies)
  0 siblings, 19 replies; 37+ messages in thread
From: Richard Henderson @ 2023-09-30  2:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.bennee, laurent

Becase b4 eats a binaries:
  https://gitlab.com/rth7680/qemu/-/tree/lu-vdso

Changes for v6:
  * Revert build-vdso.sh and meson rules.
  * Add update-linux-vdso makefile rule.  Since this is run manually,
    we no longer have a problem with docker images failing to update
    and causing the normal build to fail.

Changes for v5:
  * Integrated cross-compile, via new build-vdso.sh and meson rules.
    However, keep the binaries in the tree for hosts which do not
    have all of the cross-compile machinery.
  * Update our loongarch64 docker image to avoid a binutils bug.

r~


Richard Henderson (19):
  linux-user: Introduce imgsrc_read, imgsrc_read_alloc
  linux-user: Tidy loader_exec
  linux-user: Do not clobber bprm_buf swapping ehdr
  linux-user: Use ImageSource in load_elf_image
  linux-user: Use ImageSource in load_symbols
  linux-user: Replace bprm->fd with bprm->src.fd
  linux-user: Load vdso image if available
  linux-user: Add gen-vdso tool
  linux-user/i386: Add vdso
  linux-user/x86_64: Add vdso
  linux-user/aarch64: Add vdso
  linux-user/arm: Add vdso
  linux-user/hppa: Add vdso
  linux-user/riscv: Add vdso
  linux-user/loongarch64: Add vdso
  linux-user/ppc: Add vdso
  linux-user/s390x: Rename __SIGNAL_FRAMESIZE to STACK_FRAME_OVERHEAD
  linux-user/s390x: Add vdso
  build: Add update-linux-vdso makefile rule

 Makefile                                |  10 +
 linux-user/arm/vdso-asmoffset.h         |   3 +
 linux-user/hppa/vdso-asmoffset.h        |  12 +
 linux-user/i386/vdso-asmoffset.h        |   6 +
 linux-user/loader.h                     |  60 +++-
 linux-user/loongarch64/vdso-asmoffset.h |   8 +
 linux-user/ppc/vdso-asmoffset.h         |  20 ++
 linux-user/riscv/vdso-asmoffset.h       |   9 +
 linux-user/s390x/vdso-asmoffset.h       |   2 +
 linux-user/arm/signal.c                 |  55 ++--
 linux-user/elfload.c                    | 358 +++++++++++++++---------
 linux-user/flatload.c                   |   8 +-
 linux-user/gen-vdso.c                   | 223 +++++++++++++++
 linux-user/hppa/signal.c                |  24 +-
 linux-user/i386/signal.c                |  11 +
 linux-user/linuxload.c                  | 137 +++++++--
 linux-user/loongarch64/signal.c         |  17 +-
 linux-user/ppc/signal.c                 |  31 +-
 linux-user/riscv/signal.c               |   8 +
 linux-user/s390x/signal.c               |   7 +-
 linux-user/gen-vdso-elfn.c.inc          | 314 +++++++++++++++++++++
 linux-user/aarch64/Makefile.vdso        |  15 +
 linux-user/aarch64/meson.build          |  11 +
 linux-user/aarch64/vdso-be.so           | Bin 0 -> 3216 bytes
 linux-user/aarch64/vdso-le.so           | Bin 0 -> 3216 bytes
 linux-user/aarch64/vdso.S               |  71 +++++
 linux-user/aarch64/vdso.ld              |  72 +++++
 linux-user/arm/Makefile.vdso            |  17 ++
 linux-user/arm/meson.build              |  12 +
 linux-user/arm/vdso-be.so               | Bin 0 -> 2648 bytes
 linux-user/arm/vdso-le.so               | Bin 0 -> 2648 bytes
 linux-user/arm/vdso.S                   | 174 ++++++++++++
 linux-user/arm/vdso.ld                  |  67 +++++
 linux-user/hppa/Makefile.vdso           |  11 +
 linux-user/hppa/meson.build             |   5 +
 linux-user/hppa/vdso.S                  | 165 +++++++++++
 linux-user/hppa/vdso.ld                 |  77 +++++
 linux-user/hppa/vdso.so                 | Bin 0 -> 2104 bytes
 linux-user/i386/Makefile.vdso           |  11 +
 linux-user/i386/meson.build             |   7 +
 linux-user/i386/vdso.S                  | 143 ++++++++++
 linux-user/i386/vdso.ld                 |  76 +++++
 linux-user/i386/vdso.so                 | Bin 0 -> 2672 bytes
 linux-user/loongarch64/Makefile.vdso    |  11 +
 linux-user/loongarch64/meson.build      |   4 +
 linux-user/loongarch64/vdso.S           | 130 +++++++++
 linux-user/loongarch64/vdso.ld          |  73 +++++
 linux-user/loongarch64/vdso.so          | Bin 0 -> 3560 bytes
 linux-user/meson.build                  |   9 +-
 linux-user/ppc/Makefile.vdso            |  20 ++
 linux-user/ppc/meson.build              |  12 +
 linux-user/ppc/vdso-32.ld               |  70 +++++
 linux-user/ppc/vdso-32.so               | Bin 0 -> 3020 bytes
 linux-user/ppc/vdso-64.ld               |  68 +++++
 linux-user/ppc/vdso-64.so               | Bin 0 -> 3896 bytes
 linux-user/ppc/vdso-64le.so             | Bin 0 -> 3896 bytes
 linux-user/ppc/vdso.S                   | 239 ++++++++++++++++
 linux-user/riscv/Makefile.vdso          |  15 +
 linux-user/riscv/meson.build            |   7 +
 linux-user/riscv/vdso-32.so             | Bin 0 -> 2888 bytes
 linux-user/riscv/vdso-64.so             | Bin 0 -> 3840 bytes
 linux-user/riscv/vdso.S                 | 186 ++++++++++++
 linux-user/riscv/vdso.ld                |  74 +++++
 linux-user/s390x/Makefile.vdso          |  11 +
 linux-user/s390x/meson.build            |   6 +
 linux-user/s390x/vdso.S                 |  61 ++++
 linux-user/s390x/vdso.ld                |  69 +++++
 linux-user/s390x/vdso.so                | Bin 0 -> 3464 bytes
 linux-user/x86_64/Makefile.vdso         |  11 +
 linux-user/x86_64/meson.build           |   4 +
 linux-user/x86_64/vdso.S                |  78 ++++++
 linux-user/x86_64/vdso.ld               |  73 +++++
 linux-user/x86_64/vdso.so               | Bin 0 -> 2968 bytes
 73 files changed, 3274 insertions(+), 214 deletions(-)
 create mode 100644 linux-user/arm/vdso-asmoffset.h
 create mode 100644 linux-user/hppa/vdso-asmoffset.h
 create mode 100644 linux-user/i386/vdso-asmoffset.h
 create mode 100644 linux-user/loongarch64/vdso-asmoffset.h
 create mode 100644 linux-user/ppc/vdso-asmoffset.h
 create mode 100644 linux-user/riscv/vdso-asmoffset.h
 create mode 100644 linux-user/s390x/vdso-asmoffset.h
 create mode 100644 linux-user/gen-vdso.c
 create mode 100644 linux-user/gen-vdso-elfn.c.inc
 create mode 100644 linux-user/aarch64/Makefile.vdso
 create mode 100644 linux-user/aarch64/meson.build
 create mode 100755 linux-user/aarch64/vdso-be.so
 create mode 100755 linux-user/aarch64/vdso-le.so
 create mode 100644 linux-user/aarch64/vdso.S
 create mode 100644 linux-user/aarch64/vdso.ld
 create mode 100644 linux-user/arm/Makefile.vdso
 create mode 100755 linux-user/arm/vdso-be.so
 create mode 100755 linux-user/arm/vdso-le.so
 create mode 100644 linux-user/arm/vdso.S
 create mode 100644 linux-user/arm/vdso.ld
 create mode 100644 linux-user/hppa/Makefile.vdso
 create mode 100644 linux-user/hppa/vdso.S
 create mode 100644 linux-user/hppa/vdso.ld
 create mode 100755 linux-user/hppa/vdso.so
 create mode 100644 linux-user/i386/Makefile.vdso
 create mode 100644 linux-user/i386/vdso.S
 create mode 100644 linux-user/i386/vdso.ld
 create mode 100755 linux-user/i386/vdso.so
 create mode 100644 linux-user/loongarch64/Makefile.vdso
 create mode 100644 linux-user/loongarch64/meson.build
 create mode 100644 linux-user/loongarch64/vdso.S
 create mode 100644 linux-user/loongarch64/vdso.ld
 create mode 100755 linux-user/loongarch64/vdso.so
 create mode 100644 linux-user/ppc/Makefile.vdso
 create mode 100644 linux-user/ppc/vdso-32.ld
 create mode 100755 linux-user/ppc/vdso-32.so
 create mode 100644 linux-user/ppc/vdso-64.ld
 create mode 100755 linux-user/ppc/vdso-64.so
 create mode 100755 linux-user/ppc/vdso-64le.so
 create mode 100644 linux-user/ppc/vdso.S
 create mode 100644 linux-user/riscv/Makefile.vdso
 create mode 100644 linux-user/riscv/meson.build
 create mode 100755 linux-user/riscv/vdso-32.so
 create mode 100755 linux-user/riscv/vdso-64.so
 create mode 100644 linux-user/riscv/vdso.S
 create mode 100644 linux-user/riscv/vdso.ld
 create mode 100644 linux-user/s390x/Makefile.vdso
 create mode 100644 linux-user/s390x/vdso.S
 create mode 100644 linux-user/s390x/vdso.ld
 create mode 100755 linux-user/s390x/vdso.so
 create mode 100644 linux-user/x86_64/Makefile.vdso
 create mode 100644 linux-user/x86_64/vdso.S
 create mode 100644 linux-user/x86_64/vdso.ld
 create mode 100755 linux-user/x86_64/vdso.so

-- 
2.34.1



^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH v6 01/19] linux-user: Introduce imgsrc_read, imgsrc_read_alloc
  2023-09-30  2:15 [PATCH v6 00/19] linux-user: Implement VDSOs Richard Henderson
@ 2023-09-30  2:15 ` Richard Henderson
  2023-09-30  2:15 ` [PATCH v6 02/19] linux-user: Tidy loader_exec Richard Henderson
                   ` (17 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Richard Henderson @ 2023-09-30  2:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.bennee, laurent, Philippe Mathieu-Daudé

Introduced and initialized, but not yet really used.
These will tidy the current tests vs BPRM_BUF_SIZE.

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/loader.h    | 61 +++++++++++++++++++++++-----
 linux-user/linuxload.c | 90 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 142 insertions(+), 9 deletions(-)

diff --git a/linux-user/loader.h b/linux-user/loader.h
index 324e5c872a..da6591fff0 100644
--- a/linux-user/loader.h
+++ b/linux-user/loader.h
@@ -18,6 +18,48 @@
 #ifndef LINUX_USER_LOADER_H
 #define LINUX_USER_LOADER_H
 
+typedef struct {
+    const void *cache;
+    unsigned int cache_size;
+    int fd;
+} ImageSource;
+
+/**
+ * imgsrc_read: Read from ImageSource
+ * @dst: destination for read
+ * @offset: offset within file for read
+ * @len: size of the read
+ * @img: ImageSource to read from
+ * @errp: Error details.
+ *
+ * Read into @dst, using the cache when possible.
+ */
+bool imgsrc_read(void *dst, off_t offset, size_t len,
+                 const ImageSource *img, Error **errp);
+
+/**
+ * imgsrc_read_alloc: Read from ImageSource
+ * @offset: offset within file for read
+ * @size: size of the read
+ * @img: ImageSource to read from
+ * @errp: Error details.
+ *
+ * Read into newly allocated memory, using the cache when possible.
+ */
+void *imgsrc_read_alloc(off_t offset, size_t len,
+                        const ImageSource *img, Error **errp);
+
+/**
+ * imgsrc_mmap: Map from ImageSource
+ *
+ * If @src has a file descriptor, pass on to target_mmap.  Otherwise,
+ * this is "mapping" from a host buffer, which resolves to memcpy.
+ * Therefore, flags must be MAP_PRIVATE | MAP_FIXED; the argument is
+ * retained for clarity.
+ */
+abi_long imgsrc_mmap(abi_ulong start, abi_ulong len, int prot,
+                     int flags, const ImageSource *src, abi_ulong offset);
+
 /*
  * Read a good amount of data initially, to hopefully get all the
  * program headers loaded.
@@ -29,15 +71,16 @@
  * used when loading binaries.
  */
 struct linux_binprm {
-        char buf[BPRM_BUF_SIZE] __attribute__((aligned));
-        abi_ulong p;
-        int fd;
-        int e_uid, e_gid;
-        int argc, envc;
-        char **argv;
-        char **envp;
-        char *filename;        /* Name of binary */
-        int (*core_dump)(int, const CPUArchState *); /* coredump routine */
+    char buf[BPRM_BUF_SIZE] __attribute__((aligned));
+    ImageSource src;
+    abi_ulong p;
+    int fd;
+    int e_uid, e_gid;
+    int argc, envc;
+    char **argv;
+    char **envp;
+    char *filename;        /* Name of binary */
+    int (*core_dump)(int, const CPUArchState *); /* coredump routine */
 };
 
 void do_init_thread(struct target_pt_regs *regs, struct image_info *infop);
diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c
index 745cce70ab..3536dd8104 100644
--- a/linux-user/linuxload.c
+++ b/linux-user/linuxload.c
@@ -3,7 +3,9 @@
 #include "qemu/osdep.h"
 #include "qemu.h"
 #include "user-internals.h"
+#include "user-mmap.h"
 #include "loader.h"
+#include "qapi/error.h"
 
 #define NGROUPS 32
 
@@ -76,6 +78,10 @@ static int prepare_binprm(struct linux_binprm *bprm)
         /* Make sure the rest of the loader won't read garbage.  */
         memset(bprm->buf + retval, 0, BPRM_BUF_SIZE - retval);
     }
+
+    bprm->src.cache = bprm->buf;
+    bprm->src.cache_size = retval;
+
     return retval;
 }
 
@@ -139,6 +145,7 @@ int loader_exec(int fdexec, const char *filename, char **argv, char **envp,
     int retval;
 
     bprm->fd = fdexec;
+    bprm->src.fd = fdexec;
     bprm->filename = (char *)filename;
     bprm->argc = count(argv);
     bprm->argv = argv;
@@ -173,3 +180,86 @@ int loader_exec(int fdexec, const char *filename, char **argv, char **envp,
 
     return retval;
 }
+
+bool imgsrc_read(void *dst, off_t offset, size_t len,
+                 const ImageSource *img, Error **errp)
+{
+    ssize_t ret;
+
+    if (offset + len <= img->cache_size) {
+        memcpy(dst, img->cache + offset, len);
+        return true;
+    }
+
+    if (img->fd < 0) {
+        error_setg(errp, "read past end of buffer");
+        return false;
+    }
+
+    ret = pread(img->fd, dst, len, offset);
+    if (ret == len) {
+        return true;
+    }
+    if (ret < 0) {
+        error_setg_errno(errp, errno, "Error reading file header");
+    } else {
+        error_setg(errp, "Incomplete read of file header");
+    }
+    return false;
+}
+
+void *imgsrc_read_alloc(off_t offset, size_t len,
+                        const ImageSource *img, Error **errp)
+{
+    void *alloc = g_malloc(len);
+    bool ok = imgsrc_read(alloc, offset, len, img, errp);
+
+    if (!ok) {
+        g_free(alloc);
+        alloc = NULL;
+    }
+    return alloc;
+}
+
+abi_long imgsrc_mmap(abi_ulong start, abi_ulong len, int prot,
+                     int flags, const ImageSource *src, abi_ulong offset)
+{
+    const int prot_write = PROT_READ | PROT_WRITE;
+    abi_long ret;
+    void *haddr;
+
+    assert(flags == (MAP_PRIVATE | MAP_FIXED));
+
+    if (src->fd >= 0) {
+        return target_mmap(start, len, prot, flags, src->fd, offset);
+    }
+
+    /*
+     * This case is for the vdso; we don't expect bad images.
+     * The mmap may extend beyond the end of the image, especially
+     * to the end of the page.  Zero fill.
+     */
+    assert(offset < src->cache_size);
+
+    ret = target_mmap(start, len, prot_write, flags | MAP_ANON, -1, 0);
+    if (ret == -1) {
+        return ret;
+    }
+
+    haddr = lock_user(VERIFY_WRITE, start, len, 0);
+    assert(haddr != NULL);
+    if (offset + len <= src->cache_size) {
+        memcpy(haddr, src->cache + offset, len);
+    } else {
+        size_t rest = src->cache_size - offset;
+        memcpy(haddr, src->cache + offset, rest);
+        memset(haddr + rest, 0, len - rest);
+    }
+    unlock_user(haddr, start, len);
+
+    if (prot != prot_write) {
+        target_mprotect(start, len, prot);
+    }
+
+    return ret;
+}
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH v6 02/19] linux-user: Tidy loader_exec
  2023-09-30  2:15 [PATCH v6 00/19] linux-user: Implement VDSOs Richard Henderson
  2023-09-30  2:15 ` [PATCH v6 01/19] linux-user: Introduce imgsrc_read, imgsrc_read_alloc Richard Henderson
@ 2023-09-30  2:15 ` Richard Henderson
  2023-09-30  2:15 ` [PATCH v6 03/19] linux-user: Do not clobber bprm_buf swapping ehdr Richard Henderson
                   ` (16 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Richard Henderson @ 2023-09-30  2:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.bennee, laurent, Philippe Mathieu-Daudé

Reorg the if cases to reduce indentation.
Test for 4 bytes in the file before checking the signatures.

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/linuxload.c | 42 +++++++++++++++++++++---------------------
 1 file changed, 21 insertions(+), 21 deletions(-)

diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c
index 3536dd8104..5b7e9ab983 100644
--- a/linux-user/linuxload.c
+++ b/linux-user/linuxload.c
@@ -154,31 +154,31 @@ int loader_exec(int fdexec, const char *filename, char **argv, char **envp,
 
     retval = prepare_binprm(bprm);
 
-    if (retval >= 0) {
-        if (bprm->buf[0] == 0x7f
-                && bprm->buf[1] == 'E'
-                && bprm->buf[2] == 'L'
-                && bprm->buf[3] == 'F') {
-            retval = load_elf_binary(bprm, infop);
-#if defined(TARGET_HAS_BFLT)
-        } else if (bprm->buf[0] == 'b'
-                && bprm->buf[1] == 'F'
-                && bprm->buf[2] == 'L'
-                && bprm->buf[3] == 'T') {
-            retval = load_flt_binary(bprm, infop);
-#endif
-        } else {
-            return -ENOEXEC;
-        }
+    if (retval < 4) {
+        return -ENOEXEC;
     }
-
-    if (retval >= 0) {
-        /* success.  Initialize important registers */
-        do_init_thread(regs, infop);
+    if (bprm->buf[0] == 0x7f
+        && bprm->buf[1] == 'E'
+        && bprm->buf[2] == 'L'
+        && bprm->buf[3] == 'F') {
+        retval = load_elf_binary(bprm, infop);
+#if defined(TARGET_HAS_BFLT)
+    } else if (bprm->buf[0] == 'b'
+               && bprm->buf[1] == 'F'
+               && bprm->buf[2] == 'L'
+               && bprm->buf[3] == 'T') {
+        retval = load_flt_binary(bprm, infop);
+#endif
+    } else {
+        return -ENOEXEC;
+    }
+    if (retval < 0) {
         return retval;
     }
 
-    return retval;
+    /* Success.  Initialize important registers. */
+    do_init_thread(regs, infop);
+    return 0;
 }
 
 bool imgsrc_read(void *dst, off_t offset, size_t len,
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH v6 03/19] linux-user: Do not clobber bprm_buf swapping ehdr
  2023-09-30  2:15 [PATCH v6 00/19] linux-user: Implement VDSOs Richard Henderson
  2023-09-30  2:15 ` [PATCH v6 01/19] linux-user: Introduce imgsrc_read, imgsrc_read_alloc Richard Henderson
  2023-09-30  2:15 ` [PATCH v6 02/19] linux-user: Tidy loader_exec Richard Henderson
@ 2023-09-30  2:15 ` Richard Henderson
  2023-09-30  2:15 ` [PATCH v6 04/19] linux-user: Use ImageSource in load_elf_image Richard Henderson
                   ` (15 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Richard Henderson @ 2023-09-30  2:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.bennee, laurent, Philippe Mathieu-Daudé

Rearrange the allocation of storage for ehdr between load_elf_image
and load_elf_binary.  The same set of copies are done, but we don't
modify bprm_buf, which will be important later.

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/elfload.c | 25 ++++++++++++++-----------
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index db75cd4b33..e5c014611c 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -3164,16 +3164,17 @@ static bool parse_elf_properties(int image_fd,
    On return: INFO values will be filled in, as necessary or available.  */
 
 static void load_elf_image(const char *image_name, int image_fd,
-                           struct image_info *info, char **pinterp_name,
+                           struct image_info *info, struct elfhdr *ehdr,
+                           char **pinterp_name,
                            char bprm_buf[BPRM_BUF_SIZE])
 {
-    struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
     struct elf_phdr *phdr;
     abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
     int i, retval, prot_exec;
     Error *err = NULL;
 
     /* First of all, some simple consistency checks */
+    memcpy(ehdr, bprm_buf, sizeof(*ehdr));
     if (!elf_check_ident(ehdr)) {
         error_setg(&err, "Invalid ELF image for this architecture");
         goto exit_errmsg;
@@ -3488,6 +3489,7 @@ static void load_elf_image(const char *image_name, int image_fd,
 static void load_elf_interp(const char *filename, struct image_info *info,
                             char bprm_buf[BPRM_BUF_SIZE])
 {
+    struct elfhdr ehdr;
     int fd, retval;
     Error *err = NULL;
 
@@ -3509,7 +3511,7 @@ static void load_elf_interp(const char *filename, struct image_info *info,
         memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
     }
 
-    load_elf_image(filename, fd, info, NULL, bprm_buf);
+    load_elf_image(filename, fd, info, &ehdr, NULL, bprm_buf);
 }
 
 static int symfind(const void *s0, const void *s1)
@@ -3702,8 +3704,14 @@ uint32_t get_elf_eflags(int fd)
 
 int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
 {
+    /*
+     * We need a copy of the elf header for passing to create_elf_tables.
+     * We will have overwritten the original when we re-use bprm->buf
+     * while loading the interpreter.  Allocate the storage for this now
+     * and let elf_load_image do any swapping that may be required.
+     */
+    struct elfhdr ehdr;
     struct image_info interp_info;
-    struct elfhdr elf_ex;
     char *elf_interpreter = NULL;
     char *scratch;
 
@@ -3713,12 +3721,7 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
 #endif
 
     load_elf_image(bprm->filename, bprm->fd, info,
-                   &elf_interpreter, bprm->buf);
-
-    /* ??? We need a copy of the elf header for passing to create_elf_tables.
-       If we do nothing, we'll have overwritten this when we re-use bprm->buf
-       when we load the interpreter.  */
-    elf_ex = *(struct elfhdr *)bprm->buf;
+                   &ehdr, &elf_interpreter, bprm->buf);
 
     /* Do this so that we can load the interpreter, if need be.  We will
        change some of these later */
@@ -3805,7 +3808,7 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
         target_mprotect(tramp_page, TARGET_PAGE_SIZE, PROT_READ | PROT_EXEC);
     }
 
-    bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &elf_ex,
+    bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &ehdr,
                                 info, (elf_interpreter ? &interp_info : NULL));
     info->start_stack = bprm->p;
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH v6 04/19] linux-user: Use ImageSource in load_elf_image
  2023-09-30  2:15 [PATCH v6 00/19] linux-user: Implement VDSOs Richard Henderson
                   ` (2 preceding siblings ...)
  2023-09-30  2:15 ` [PATCH v6 03/19] linux-user: Do not clobber bprm_buf swapping ehdr Richard Henderson
@ 2023-09-30  2:15 ` Richard Henderson
  2023-10-02 13:22   ` Philippe Mathieu-Daudé
  2023-09-30  2:15 ` [PATCH v6 05/19] linux-user: Use ImageSource in load_symbols Richard Henderson
                   ` (14 subsequent siblings)
  18 siblings, 1 reply; 37+ messages in thread
From: Richard Henderson @ 2023-09-30  2:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.bennee, laurent

Change parse_elf_properties as well, as the bprm_buf argument
ties the two functions closely.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/elfload.c | 128 +++++++++++++++++--------------------------
 1 file changed, 49 insertions(+), 79 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index e5c014611c..d6f1b8d2b1 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -3067,10 +3067,9 @@ static bool parse_elf_property(const uint32_t *data, int *off, int datasz,
 }
 
 /* Process NT_GNU_PROPERTY_TYPE_0. */
-static bool parse_elf_properties(int image_fd,
+static bool parse_elf_properties(const ImageSource *src,
                                  struct image_info *info,
                                  const struct elf_phdr *phdr,
-                                 char bprm_buf[BPRM_BUF_SIZE],
                                  Error **errp)
 {
     union {
@@ -3098,14 +3097,8 @@ static bool parse_elf_properties(int image_fd,
         return false;
     }
 
-    if (phdr->p_offset + n <= BPRM_BUF_SIZE) {
-        memcpy(&note, bprm_buf + phdr->p_offset, n);
-    } else {
-        ssize_t len = pread(image_fd, &note, n, phdr->p_offset);
-        if (len != n) {
-            error_setg_errno(errp, errno, "Error reading file header");
-            return false;
-        }
+    if (!imgsrc_read(&note, phdr->p_offset, n, src, errp)) {
+        return false;
     }
 
     /*
@@ -3151,30 +3144,34 @@ static bool parse_elf_properties(int image_fd,
     }
 }
 
-/* Load an ELF image into the address space.
+/**
+ * load_elf_image: Load an ELF image into the address space.
+ * @image_name: the filename of the image, to use in error messages.
+ * @src: the ImageSource from which to read.
+ * @info: info collected from the loaded image.
+ * @ehdr: the ELF header, not yet bswapped.
+ * @pinterp_name: record any PT_INTERP string found.
+ *
+ * On return: @info values will be filled in, as necessary or available.
+ */
 
-   IMAGE_NAME is the filename of the image, to use in error messages.
-   IMAGE_FD is the open file descriptor for the image.
-
-   BPRM_BUF is a copy of the beginning of the file; this of course
-   contains the elf file header at offset 0.  It is assumed that this
-   buffer is sufficiently aligned to present no problems to the host
-   in accessing data at aligned offsets within the buffer.
-
-   On return: INFO values will be filled in, as necessary or available.  */
-
-static void load_elf_image(const char *image_name, int image_fd,
+static void load_elf_image(const char *image_name, const ImageSource *src,
                            struct image_info *info, struct elfhdr *ehdr,
-                           char **pinterp_name,
-                           char bprm_buf[BPRM_BUF_SIZE])
+                           char **pinterp_name)
 {
-    struct elf_phdr *phdr;
+    g_autofree struct elf_phdr *phdr = NULL;
     abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
-    int i, retval, prot_exec;
+    int i, prot_exec;
     Error *err = NULL;
 
-    /* First of all, some simple consistency checks */
-    memcpy(ehdr, bprm_buf, sizeof(*ehdr));
+    /*
+     * First of all, some simple consistency checks.
+     * Note that we rely on the bswapped ehdr staying in bprm_buf,
+     * for later use by load_elf_binary and create_elf_tables.
+     */
+    if (!imgsrc_read(ehdr, 0, sizeof(*ehdr), src, &err)) {
+        goto exit_errmsg;
+    }
     if (!elf_check_ident(ehdr)) {
         error_setg(&err, "Invalid ELF image for this architecture");
         goto exit_errmsg;
@@ -3185,15 +3182,11 @@ static void load_elf_image(const char *image_name, int image_fd,
         goto exit_errmsg;
     }
 
-    i = ehdr->e_phnum * sizeof(struct elf_phdr);
-    if (ehdr->e_phoff + i <= BPRM_BUF_SIZE) {
-        phdr = (struct elf_phdr *)(bprm_buf + ehdr->e_phoff);
-    } else {
-        phdr = (struct elf_phdr *) alloca(i);
-        retval = pread(image_fd, phdr, i, ehdr->e_phoff);
-        if (retval != i) {
-            goto exit_read;
-        }
+    phdr = imgsrc_read_alloc(ehdr->e_phoff,
+                             ehdr->e_phnum * sizeof(struct elf_phdr),
+                             src, &err);
+    if (phdr == NULL) {
+        goto exit_errmsg;
     }
     bswap_phdr(phdr, ehdr->e_phnum);
 
@@ -3230,17 +3223,10 @@ static void load_elf_image(const char *image_name, int image_fd,
                 goto exit_errmsg;
             }
 
-            interp_name = g_malloc(eppnt->p_filesz);
-
-            if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
-                memcpy(interp_name, bprm_buf + eppnt->p_offset,
-                       eppnt->p_filesz);
-            } else {
-                retval = pread(image_fd, interp_name, eppnt->p_filesz,
-                               eppnt->p_offset);
-                if (retval != eppnt->p_filesz) {
-                    goto exit_read;
-                }
+            interp_name = imgsrc_read_alloc(eppnt->p_offset, eppnt->p_filesz,
+                                            src, &err);
+            if (interp_name == NULL) {
+                goto exit_errmsg;
             }
             if (interp_name[eppnt->p_filesz - 1] != 0) {
                 error_setg(&err, "Invalid PT_INTERP entry");
@@ -3248,7 +3234,7 @@ static void load_elf_image(const char *image_name, int image_fd,
             }
             *pinterp_name = g_steal_pointer(&interp_name);
         } else if (eppnt->p_type == PT_GNU_PROPERTY) {
-            if (!parse_elf_properties(image_fd, info, eppnt, bprm_buf, &err)) {
+            if (!parse_elf_properties(src, info, eppnt, &err)) {
                 goto exit_errmsg;
             }
         } else if (eppnt->p_type == PT_GNU_STACK) {
@@ -3401,9 +3387,9 @@ static void load_elf_image(const char *image_name, int image_fd,
              * but no backing file segment.
              */
             if (eppnt->p_filesz != 0) {
-                error = target_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po,
+                error = imgsrc_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po,
                                     elf_prot, MAP_PRIVATE | MAP_FIXED,
-                                    image_fd, eppnt->p_offset - vaddr_po);
+                                    src, eppnt->p_offset - vaddr_po);
                 if (error == -1) {
                     goto exit_mmap;
                 }
@@ -3435,20 +3421,11 @@ static void load_elf_image(const char *image_name, int image_fd,
 #ifdef TARGET_MIPS
         } else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
             Mips_elf_abiflags_v0 abiflags;
-            if (eppnt->p_filesz < sizeof(Mips_elf_abiflags_v0)) {
-                error_setg(&err, "Invalid PT_MIPS_ABIFLAGS entry");
+
+            if (!imgsrc_read(&abiflags, eppnt->p_offset, sizeof(abiflags),
+                             src, &err)) {
                 goto exit_errmsg;
             }
-            if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
-                memcpy(&abiflags, bprm_buf + eppnt->p_offset,
-                       sizeof(Mips_elf_abiflags_v0));
-            } else {
-                retval = pread(image_fd, &abiflags, sizeof(Mips_elf_abiflags_v0),
-                               eppnt->p_offset);
-                if (retval != sizeof(Mips_elf_abiflags_v0)) {
-                    goto exit_read;
-                }
-            }
             bswap_mips_abiflags(&abiflags);
             info->fp_abi = abiflags.fp_abi;
 #endif
@@ -3461,23 +3438,16 @@ static void load_elf_image(const char *image_name, int image_fd,
     }
 
     if (qemu_log_enabled()) {
-        load_symbols(ehdr, image_fd, load_bias);
+        load_symbols(ehdr, src->fd, load_bias);
     }
 
-    debuginfo_report_elf(image_name, image_fd, load_bias);
+    debuginfo_report_elf(image_name, src->fd, load_bias);
 
     mmap_unlock();
 
-    close(image_fd);
+    close(src->fd);
     return;
 
- exit_read:
-    if (retval >= 0) {
-        error_setg(&err, "Incomplete read of file header");
-    } else {
-        error_setg_errno(&err, errno, "Error reading file header");
-    }
-    goto exit_errmsg;
  exit_mmap:
     error_setg_errno(&err, errno, "Error mapping file");
     goto exit_errmsg;
@@ -3490,6 +3460,7 @@ static void load_elf_interp(const char *filename, struct image_info *info,
                             char bprm_buf[BPRM_BUF_SIZE])
 {
     struct elfhdr ehdr;
+    ImageSource src;
     int fd, retval;
     Error *err = NULL;
 
@@ -3507,11 +3478,11 @@ static void load_elf_interp(const char *filename, struct image_info *info,
         exit(-1);
     }
 
-    if (retval < BPRM_BUF_SIZE) {
-        memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
-    }
+    src.fd = fd;
+    src.cache = bprm_buf;
+    src.cache_size = retval;
 
-    load_elf_image(filename, fd, info, &ehdr, NULL, bprm_buf);
+    load_elf_image(filename, &src, info, &ehdr, NULL);
 }
 
 static int symfind(const void *s0, const void *s1)
@@ -3720,8 +3691,7 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
     interp_info.fp_abi = MIPS_ABI_FP_UNKNOWN;
 #endif
 
-    load_elf_image(bprm->filename, bprm->fd, info,
-                   &ehdr, &elf_interpreter, bprm->buf);
+    load_elf_image(bprm->filename, &bprm->src, info, &ehdr, &elf_interpreter);
 
     /* Do this so that we can load the interpreter, if need be.  We will
        change some of these later */
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH v6 05/19] linux-user: Use ImageSource in load_symbols
  2023-09-30  2:15 [PATCH v6 00/19] linux-user: Implement VDSOs Richard Henderson
                   ` (3 preceding siblings ...)
  2023-09-30  2:15 ` [PATCH v6 04/19] linux-user: Use ImageSource in load_elf_image Richard Henderson
@ 2023-09-30  2:15 ` Richard Henderson
  2023-09-30  2:15 ` [PATCH v6 06/19] linux-user: Replace bprm->fd with bprm->src.fd Richard Henderson
                   ` (13 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Richard Henderson @ 2023-09-30  2:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.bennee, laurent, Philippe Mathieu-Daudé

Aside from the section headers, we're unlikely to hit the
ImageSource cache on guest executables.  But the interface
for imgsrc_read_* is better.

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/elfload.c | 87 ++++++++++++++++++++++++--------------------
 1 file changed, 48 insertions(+), 39 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index d6f1b8d2b1..ed276edb3c 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -2193,7 +2193,8 @@ static inline void bswap_mips_abiflags(Mips_elf_abiflags_v0 *abiflags) { }
 #ifdef USE_ELF_CORE_DUMP
 static int elf_core_dump(int, const CPUArchState *);
 #endif /* USE_ELF_CORE_DUMP */
-static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias);
+static void load_symbols(struct elfhdr *hdr, const ImageSource *src,
+                         abi_ulong load_bias);
 
 /* Verify the portions of EHDR within E_IDENT for the target.
    This can be performed before bswapping the entire header.  */
@@ -3438,7 +3439,7 @@ static void load_elf_image(const char *image_name, const ImageSource *src,
     }
 
     if (qemu_log_enabled()) {
-        load_symbols(ehdr, src->fd, load_bias);
+        load_symbols(ehdr, src, load_bias);
     }
 
     debuginfo_report_elf(image_name, src->fd, load_bias);
@@ -3529,19 +3530,20 @@ static int symcmp(const void *s0, const void *s1)
 }
 
 /* Best attempt to load symbols from this ELF object. */
-static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
+static void load_symbols(struct elfhdr *hdr, const ImageSource *src,
+                         abi_ulong load_bias)
 {
     int i, shnum, nsyms, sym_idx = 0, str_idx = 0;
-    uint64_t segsz;
-    struct elf_shdr *shdr;
+    g_autofree struct elf_shdr *shdr = NULL;
     char *strings = NULL;
-    struct syminfo *s = NULL;
-    struct elf_sym *new_syms, *syms = NULL;
+    struct elf_sym *syms = NULL;
+    struct elf_sym *new_syms;
+    uint64_t segsz;
 
     shnum = hdr->e_shnum;
-    i = shnum * sizeof(struct elf_shdr);
-    shdr = (struct elf_shdr *)alloca(i);
-    if (pread(fd, shdr, i, hdr->e_shoff) != i) {
+    shdr = imgsrc_read_alloc(hdr->e_shoff, shnum * sizeof(struct elf_shdr),
+                             src, NULL);
+    if (shdr == NULL) {
         return;
     }
 
@@ -3559,31 +3561,33 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
 
  found:
     /* Now know where the strtab and symtab are.  Snarf them.  */
-    s = g_try_new(struct syminfo, 1);
-    if (!s) {
-        goto give_up;
-    }
 
     segsz = shdr[str_idx].sh_size;
-    s->disas_strtab = strings = g_try_malloc(segsz);
-    if (!strings ||
-        pread(fd, strings, segsz, shdr[str_idx].sh_offset) != segsz) {
+    strings = g_try_malloc(segsz);
+    if (!strings) {
+        goto give_up;
+    }
+    if (!imgsrc_read(strings, shdr[str_idx].sh_offset, segsz, src, NULL)) {
         goto give_up;
     }
 
     segsz = shdr[sym_idx].sh_size;
-    syms = g_try_malloc(segsz);
-    if (!syms || pread(fd, syms, segsz, shdr[sym_idx].sh_offset) != segsz) {
-        goto give_up;
-    }
-
     if (segsz / sizeof(struct elf_sym) > INT_MAX) {
-        /* Implausibly large symbol table: give up rather than ploughing
-         * on with the number of symbols calculation overflowing
+        /*
+         * Implausibly large symbol table: give up rather than ploughing
+         * on with the number of symbols calculation overflowing.
          */
         goto give_up;
     }
     nsyms = segsz / sizeof(struct elf_sym);
+    syms = g_try_malloc(segsz);
+    if (!syms) {
+        goto give_up;
+    }
+    if (!imgsrc_read(syms, shdr[sym_idx].sh_offset, segsz, src, NULL)) {
+        goto give_up;
+    }
+
     for (i = 0; i < nsyms; ) {
         bswap_sym(syms + i);
         /* Throw away entries which we do not need.  */
@@ -3608,10 +3612,12 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
         goto give_up;
     }
 
-    /* Attempt to free the storage associated with the local symbols
-       that we threw away.  Whether or not this has any effect on the
-       memory allocation depends on the malloc implementation and how
-       many symbols we managed to discard.  */
+    /*
+     * Attempt to free the storage associated with the local symbols
+     * that we threw away.  Whether or not this has any effect on the
+     * memory allocation depends on the malloc implementation and how
+     * many symbols we managed to discard.
+     */
     new_syms = g_try_renew(struct elf_sym, syms, nsyms);
     if (new_syms == NULL) {
         goto give_up;
@@ -3620,20 +3626,23 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
 
     qsort(syms, nsyms, sizeof(*syms), symcmp);
 
-    s->disas_num_syms = nsyms;
-#if ELF_CLASS == ELFCLASS32
-    s->disas_symtab.elf32 = syms;
-#else
-    s->disas_symtab.elf64 = syms;
-#endif
-    s->lookup_symbol = lookup_symbolxx;
-    s->next = syminfos;
-    syminfos = s;
+    {
+        struct syminfo *s = g_new(struct syminfo, 1);
 
+        s->disas_strtab = strings;
+        s->disas_num_syms = nsyms;
+#if ELF_CLASS == ELFCLASS32
+        s->disas_symtab.elf32 = syms;
+#else
+        s->disas_symtab.elf64 = syms;
+#endif
+        s->lookup_symbol = lookup_symbolxx;
+        s->next = syminfos;
+        syminfos = s;
+    }
     return;
 
-give_up:
-    g_free(s);
+ give_up:
     g_free(strings);
     g_free(syms);
 }
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH v6 06/19] linux-user: Replace bprm->fd with bprm->src.fd
  2023-09-30  2:15 [PATCH v6 00/19] linux-user: Implement VDSOs Richard Henderson
                   ` (4 preceding siblings ...)
  2023-09-30  2:15 ` [PATCH v6 05/19] linux-user: Use ImageSource in load_symbols Richard Henderson
@ 2023-09-30  2:15 ` Richard Henderson
  2023-09-30  2:15 ` [PATCH v6 07/19] linux-user: Load vdso image if available Richard Henderson
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Richard Henderson @ 2023-09-30  2:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.bennee, laurent, Philippe Mathieu-Daudé

There are only a couple of uses of bprm->fd remaining.
Migrate to the other field.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/loader.h    | 1 -
 linux-user/flatload.c  | 8 ++++----
 linux-user/linuxload.c | 5 ++---
 3 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/linux-user/loader.h b/linux-user/loader.h
index da6591fff0..a0834290e7 100644
--- a/linux-user/loader.h
+++ b/linux-user/loader.h
@@ -74,7 +74,6 @@ struct linux_binprm {
     char buf[BPRM_BUF_SIZE] __attribute__((aligned));
     ImageSource src;
     abi_ulong p;
-    int fd;
     int e_uid, e_gid;
     int argc, envc;
     char **argv;
diff --git a/linux-user/flatload.c b/linux-user/flatload.c
index 4331a11bf0..0811f32aaf 100644
--- a/linux-user/flatload.c
+++ b/linux-user/flatload.c
@@ -463,7 +463,7 @@ static int load_flat_file(struct linux_binprm * bprm,
         DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n");
 
         textpos = target_mmap(0, text_len, PROT_READ|PROT_EXEC,
-                              MAP_PRIVATE, bprm->fd, 0);
+                              MAP_PRIVATE, bprm->src.fd, 0);
         if (textpos == -1) {
             fprintf(stderr, "Unable to mmap process text\n");
             return -1;
@@ -490,7 +490,7 @@ static int load_flat_file(struct linux_binprm * bprm,
         } else
 #endif
         {
-            result = target_pread(bprm->fd, datapos,
+            result = target_pread(bprm->src.fd, datapos,
                                   data_len + (relocs * sizeof(abi_ulong)),
                                   fpos);
         }
@@ -540,10 +540,10 @@ static int load_flat_file(struct linux_binprm * bprm,
         else
 #endif
         {
-            result = target_pread(bprm->fd, textpos,
+            result = target_pread(bprm->src.fd, textpos,
                                   text_len, 0);
             if (result >= 0) {
-                result = target_pread(bprm->fd, datapos,
+                result = target_pread(bprm->src.fd, datapos,
                     data_len + (relocs * sizeof(abi_ulong)),
                     ntohl(hdr->data_start));
             }
diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c
index 5b7e9ab983..4a794f8cea 100644
--- a/linux-user/linuxload.c
+++ b/linux-user/linuxload.c
@@ -39,7 +39,7 @@ static int prepare_binprm(struct linux_binprm *bprm)
     int mode;
     int retval;
 
-    if (fstat(bprm->fd, &st) < 0) {
+    if (fstat(bprm->src.fd, &st) < 0) {
         return -errno;
     }
 
@@ -69,7 +69,7 @@ static int prepare_binprm(struct linux_binprm *bprm)
         bprm->e_gid = st.st_gid;
     }
 
-    retval = read(bprm->fd, bprm->buf, BPRM_BUF_SIZE);
+    retval = read(bprm->src.fd, bprm->buf, BPRM_BUF_SIZE);
     if (retval < 0) {
         perror("prepare_binprm");
         exit(-1);
@@ -144,7 +144,6 @@ int loader_exec(int fdexec, const char *filename, char **argv, char **envp,
 {
     int retval;
 
-    bprm->fd = fdexec;
     bprm->src.fd = fdexec;
     bprm->filename = (char *)filename;
     bprm->argc = count(argv);
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH v6 07/19] linux-user: Load vdso image if available
  2023-09-30  2:15 [PATCH v6 00/19] linux-user: Implement VDSOs Richard Henderson
                   ` (5 preceding siblings ...)
  2023-09-30  2:15 ` [PATCH v6 06/19] linux-user: Replace bprm->fd with bprm->src.fd Richard Henderson
@ 2023-09-30  2:15 ` Richard Henderson
  2023-10-03 12:47   ` Philippe Mathieu-Daudé
  2023-09-30  2:15 ` [PATCH v6 08/19] linux-user: Add gen-vdso tool Richard Henderson
                   ` (11 subsequent siblings)
  18 siblings, 1 reply; 37+ messages in thread
From: Richard Henderson @ 2023-09-30  2:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.bennee, laurent

The vdso image will be pre-processed into a C data array, with
a simple list of relocations to perform, and identifying the
location of signal trampolines.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/elfload.c | 90 +++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 81 insertions(+), 9 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index ed276edb3c..9c97d14b7e 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -33,6 +33,19 @@
 #undef ELF_ARCH
 #endif
 
+#ifndef TARGET_ARCH_HAS_SIGTRAMP_PAGE
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 0
+#endif
+
+typedef struct {
+    const uint8_t *image;
+    const uint32_t *relocs;
+    unsigned image_size;
+    unsigned reloc_count;
+    unsigned sigreturn_ofs;
+    unsigned rt_sigreturn_ofs;
+} VdsoImageInfo;
+
 #define ELF_OSABI   ELFOSABI_SYSV
 
 /* from personality.h */
@@ -2436,7 +2449,8 @@ static abi_ulong loader_build_fdpic_loadmap(struct image_info *info, abi_ulong s
 static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
                                    struct elfhdr *exec,
                                    struct image_info *info,
-                                   struct image_info *interp_info)
+                                   struct image_info *interp_info,
+                                   struct image_info *vdso_info)
 {
     abi_ulong sp;
     abi_ulong u_argc, u_argv, u_envp, u_auxv;
@@ -2524,10 +2538,15 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
     }
 
     size = (DLINFO_ITEMS + 1) * 2;
-    if (k_base_platform)
+    if (k_base_platform) {
         size += 2;
-    if (k_platform)
+    }
+    if (k_platform) {
         size += 2;
+    }
+    if (vdso_info) {
+        size += 2;
+    }
 #ifdef DLINFO_ARCH_ITEMS
     size += DLINFO_ARCH_ITEMS * 2;
 #endif
@@ -2609,6 +2628,9 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
     if (u_platform) {
         NEW_AUX_ENT(AT_PLATFORM, u_platform);
     }
+    if (vdso_info) {
+        NEW_AUX_ENT(AT_SYSINFO_EHDR, vdso_info->load_addr);
+    }
     NEW_AUX_ENT (AT_NULL, 0);
 #undef NEW_AUX_ENT
 
@@ -3486,6 +3508,52 @@ static void load_elf_interp(const char *filename, struct image_info *info,
     load_elf_image(filename, &src, info, &ehdr, NULL);
 }
 
+#ifdef VDSO_HEADER
+#include VDSO_HEADER
+#define  vdso_image_info()  &vdso_image_info
+#else
+#define  vdso_image_info()  NULL
+#endif
+
+static void load_elf_vdso(struct image_info *info, const VdsoImageInfo *vdso)
+{
+    ImageSource src;
+    struct elfhdr ehdr;
+    abi_ulong load_bias, load_addr;
+
+    src.fd = -1;
+    src.cache = vdso->image;
+    src.cache_size = vdso->image_size;
+
+    load_elf_image("<internal-vdso>", &src, info, &ehdr, NULL);
+    load_addr = info->load_addr;
+    load_bias = info->load_bias;
+
+    /*
+     * We need to relocate the VDSO image.  The one built into the kernel
+     * is built for a fixed address.  The one built for QEMU is not, since
+     * that requires close control of the guest address space.
+     * We pre-processed the image to locate all of the addresses that need
+     * to be updated.
+     */
+    for (unsigned i = 0, n = vdso->reloc_count; i < n; i++) {
+        abi_ulong *addr = g2h_untagged(load_addr + vdso->relocs[i]);
+        *addr = tswapal(tswapal(*addr) + load_bias);
+    }
+
+    /* Install signal trampolines, if present. */
+    if (vdso->sigreturn_ofs) {
+        default_sigreturn = load_addr + vdso->sigreturn_ofs;
+    }
+    if (vdso->rt_sigreturn_ofs) {
+        default_rt_sigreturn = load_addr + vdso->rt_sigreturn_ofs;
+    }
+
+    /* Remove write from VDSO segment. */
+    target_mprotect(info->start_data, info->end_data - info->start_data,
+                    PROT_READ | PROT_EXEC);
+}
+
 static int symfind(const void *s0, const void *s1)
 {
     struct elf_sym *sym = (struct elf_sym *)s1;
@@ -3691,7 +3759,7 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
      * and let elf_load_image do any swapping that may be required.
      */
     struct elfhdr ehdr;
-    struct image_info interp_info;
+    struct image_info interp_info, vdso_info;
     char *elf_interpreter = NULL;
     char *scratch;
 
@@ -3772,10 +3840,13 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
     }
 
     /*
-     * TODO: load a vdso, which would also contain the signal trampolines.
-     * Otherwise, allocate a private page to hold them.
+     * Load a vdso if available, which will amongst other things contain the
+     * signal trampolines.  Otherwise, allocate a separate page for them.
      */
-    if (TARGET_ARCH_HAS_SIGTRAMP_PAGE) {
+    const VdsoImageInfo *vdso = vdso_image_info();
+    if (vdso) {
+        load_elf_vdso(&vdso_info, vdso);
+    } else if (TARGET_ARCH_HAS_SIGTRAMP_PAGE) {
         abi_long tramp_page = target_mmap(0, TARGET_PAGE_SIZE,
                                           PROT_READ | PROT_WRITE,
                                           MAP_PRIVATE | MAP_ANON, -1, 0);
@@ -3787,8 +3858,9 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
         target_mprotect(tramp_page, TARGET_PAGE_SIZE, PROT_READ | PROT_EXEC);
     }
 
-    bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &ehdr,
-                                info, (elf_interpreter ? &interp_info : NULL));
+    bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &ehdr, info,
+                                elf_interpreter ? &interp_info : NULL,
+                                vdso ? &vdso_info : NULL);
     info->start_stack = bprm->p;
 
     /* If we have an interpreter, set that as the program's entry point.
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH v6 08/19] linux-user: Add gen-vdso tool
  2023-09-30  2:15 [PATCH v6 00/19] linux-user: Implement VDSOs Richard Henderson
                   ` (6 preceding siblings ...)
  2023-09-30  2:15 ` [PATCH v6 07/19] linux-user: Load vdso image if available Richard Henderson
@ 2023-09-30  2:15 ` Richard Henderson
  2023-10-03 13:00   ` Philippe Mathieu-Daudé
  2023-09-30  2:15 ` [PATCH v6 09/19] linux-user/i386: Add vdso Richard Henderson
                   ` (10 subsequent siblings)
  18 siblings, 1 reply; 37+ messages in thread
From: Richard Henderson @ 2023-09-30  2:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.bennee, laurent

This tool will be used for post-processing the linked vdso image,
turning it into something that is easy to include into elfload.c.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/gen-vdso.c          | 223 ++++++++++++++++++++++++
 linux-user/gen-vdso-elfn.c.inc | 307 +++++++++++++++++++++++++++++++++
 linux-user/meson.build         |   6 +-
 3 files changed, 535 insertions(+), 1 deletion(-)
 create mode 100644 linux-user/gen-vdso.c
 create mode 100644 linux-user/gen-vdso-elfn.c.inc

diff --git a/linux-user/gen-vdso.c b/linux-user/gen-vdso.c
new file mode 100644
index 0000000000..a6c61d2f6e
--- /dev/null
+++ b/linux-user/gen-vdso.c
@@ -0,0 +1,223 @@
+/*
+ * Post-process a vdso elf image for inclusion into qemu.
+ *
+ * Copyright 2023 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <endian.h>
+#include <unistd.h>
+#include "elf.h"
+
+
+#define bswap_(p)  _Generic(*(p), \
+                            uint16_t: __builtin_bswap16,       \
+                            uint32_t: __builtin_bswap32,       \
+                            uint64_t: __builtin_bswap64,       \
+                            int16_t: __builtin_bswap16,        \
+                            int32_t: __builtin_bswap32,        \
+                            int64_t: __builtin_bswap64)
+#define bswaps(p) (*(p) = bswap_(p)(*(p)))
+
+static void output_reloc(FILE *outf, void *buf, void *loc)
+{
+    fprintf(outf, "    0x%08lx,\n", (unsigned long)(loc - buf));
+}
+
+static const char *sigreturn_sym;
+static const char *rt_sigreturn_sym;
+
+static unsigned sigreturn_addr;
+static unsigned rt_sigreturn_addr;
+
+#define N 32
+#define elfN(x)  elf32_##x
+#define ElfN(x)  Elf32_##x
+#include "gen-vdso-elfn.c.inc"
+#undef N
+#undef elfN
+#undef ElfN
+
+#define N 64
+#define elfN(x)  elf64_##x
+#define ElfN(x)  Elf64_##x
+#include "gen-vdso-elfn.c.inc"
+#undef N
+#undef elfN
+#undef ElfN
+
+
+int main(int argc, char **argv)
+{
+    FILE *inf, *outf;
+    long total_len;
+    const char *prefix = "vdso";
+    const char *inf_name;
+    const char *outf_name = NULL;
+    unsigned char *buf;
+    bool need_bswap;
+
+    while (1) {
+        int opt = getopt(argc, argv, "o:p:r:s:");
+        if (opt < 0) {
+            break;
+        }
+        switch (opt) {
+        case 'o':
+            outf_name = optarg;
+            break;
+        case 'p':
+            prefix = optarg;
+            break;
+        case 'r':
+            rt_sigreturn_sym = optarg;
+            break;
+        case 's':
+            sigreturn_sym = optarg;
+            break;
+        default:
+        usage:
+            fprintf(stderr, "usage: [-p prefix] [-r rt-sigreturn-name] "
+                    "[-s sigreturn-name] -o output-file input-file\n");
+            return EXIT_FAILURE;
+        }
+    }
+
+    if (optind >= argc || outf_name == NULL) {
+        goto usage;
+    }
+    inf_name = argv[optind];
+
+    /*
+     * Open the input and output files.
+     */
+    inf = fopen(inf_name, "rb");
+    if (inf == NULL) {
+        goto perror_inf;
+    }
+    outf = fopen(outf_name, "w");
+    if (outf == NULL) {
+        goto perror_outf;
+    }
+
+    /*
+     * Read the input file into a buffer.
+     * We expect the vdso to be small, on the order of one page,
+     * therefore we do not expect a partial read.
+     */
+    fseek(inf, 0, SEEK_END);
+    total_len = ftell(inf);
+    fseek(inf, 0, SEEK_SET);
+
+    buf = malloc(total_len);
+    if (buf == NULL) {
+        goto perror_inf;
+    }
+
+    errno = 0;
+    if (fread(buf, 1, total_len, inf) != total_len) {
+        if (errno) {
+            goto perror_inf;
+        }
+        fprintf(stderr, "%s: incomplete read\n", inf_name);
+        return EXIT_FAILURE;
+    }
+    fclose(inf);
+
+    /*
+     * Write out the vdso image now, before we make local changes.
+     */
+
+    fprintf(outf,
+            "/* Automatically generated from linux-user/gen-vdso.c. */\n"
+            "\n"
+            "static const uint8_t %s_image[] = {",
+            prefix);
+    for (long i = 0; i < total_len; ++i) {
+        if (i % 12 == 0) {
+            fputs("\n   ", outf);
+        }
+        fprintf(outf, " 0x%02x,", buf[i]);
+    }
+    fprintf(outf, "\n};\n\n");
+
+    /*
+     * Identify which elf flavor we're processing.
+     * The first 16 bytes of the file are e_ident.
+     */
+
+    if (buf[EI_MAG0] != ELFMAG0 || buf[EI_MAG1] != ELFMAG1 ||
+        buf[EI_MAG2] != ELFMAG2 || buf[EI_MAG3] != ELFMAG3) {
+        fprintf(stderr, "%s: not an elf file\n", inf_name);
+        return EXIT_FAILURE;
+    }
+    switch (buf[EI_DATA]) {
+    case ELFDATA2LSB:
+        need_bswap = BYTE_ORDER != LITTLE_ENDIAN;
+        break;
+    case ELFDATA2MSB:
+        need_bswap = BYTE_ORDER != BIG_ENDIAN;
+        break;
+    default:
+        fprintf(stderr, "%s: invalid elf EI_DATA (%u)\n",
+                inf_name, buf[EI_DATA]);
+        return EXIT_FAILURE;
+    }
+
+    /*
+     * We need to relocate the VDSO image.  The one built into the kernel
+     * is built for a fixed address.  The one we built for QEMU is not,
+     * since that requires close control of the guest address space.
+     *
+     * Output relocation addresses as we go.
+     */
+
+    fprintf(outf, "static const unsigned %s_relocs[] = {\n", prefix);
+
+    switch (buf[EI_CLASS]) {
+    case ELFCLASS32:
+        elf32_process(outf, buf, need_bswap);
+        break;
+    case ELFCLASS64:
+        elf64_process(outf, buf, need_bswap);
+        break;
+    default:
+        fprintf(stderr, "%s: invalid elf EI_CLASS (%u)\n",
+                inf_name, buf[EI_CLASS]);
+        return EXIT_FAILURE;
+    }
+
+    fprintf(outf, "};\n\n");   /* end vdso_relocs. */
+
+    fprintf(outf, "static const VdsoImageInfo %s_image_info = {\n", prefix);
+    fprintf(outf, "    .image = %s_image,\n", prefix);
+    fprintf(outf, "    .relocs = %s_relocs,\n", prefix);
+    fprintf(outf, "    .image_size = sizeof(%s_image),\n", prefix);
+    fprintf(outf, "    .reloc_count = ARRAY_SIZE(%s_relocs),\n", prefix);
+    fprintf(outf, "    .sigreturn_ofs = 0x%x,\n", sigreturn_addr);
+    fprintf(outf, "    .rt_sigreturn_ofs = 0x%x,\n", rt_sigreturn_addr);
+    fprintf(outf, "};\n");
+
+    /*
+     * Everything should have gone well.
+     */
+    if (fclose(outf)) {
+        goto perror_outf;
+    }
+    return EXIT_SUCCESS;
+
+ perror_inf:
+    perror(inf_name);
+    return EXIT_FAILURE;
+
+ perror_outf:
+    perror(outf_name);
+    return EXIT_FAILURE;
+}
diff --git a/linux-user/gen-vdso-elfn.c.inc b/linux-user/gen-vdso-elfn.c.inc
new file mode 100644
index 0000000000..7034c36d5e
--- /dev/null
+++ b/linux-user/gen-vdso-elfn.c.inc
@@ -0,0 +1,307 @@
+/*
+ * Post-process a vdso elf image for inclusion into qemu.
+ * Elf size specialization.
+ *
+ * Copyright 2023 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+static void elfN(bswap_ehdr)(ElfN(Ehdr) *ehdr)
+{
+    bswaps(&ehdr->e_type);            /* Object file type */
+    bswaps(&ehdr->e_machine);         /* Architecture */
+    bswaps(&ehdr->e_version);         /* Object file version */
+    bswaps(&ehdr->e_entry);           /* Entry point virtual address */
+    bswaps(&ehdr->e_phoff);           /* Program header table file offset */
+    bswaps(&ehdr->e_shoff);           /* Section header table file offset */
+    bswaps(&ehdr->e_flags);           /* Processor-specific flags */
+    bswaps(&ehdr->e_ehsize);          /* ELF header size in bytes */
+    bswaps(&ehdr->e_phentsize);       /* Program header table entry size */
+    bswaps(&ehdr->e_phnum);           /* Program header table entry count */
+    bswaps(&ehdr->e_shentsize);       /* Section header table entry size */
+    bswaps(&ehdr->e_shnum);           /* Section header table entry count */
+    bswaps(&ehdr->e_shstrndx);        /* Section header string table index */
+}
+
+static void elfN(bswap_phdr)(ElfN(Phdr) *phdr)
+{
+    bswaps(&phdr->p_type);            /* Segment type */
+    bswaps(&phdr->p_flags);           /* Segment flags */
+    bswaps(&phdr->p_offset);          /* Segment file offset */
+    bswaps(&phdr->p_vaddr);           /* Segment virtual address */
+    bswaps(&phdr->p_paddr);           /* Segment physical address */
+    bswaps(&phdr->p_filesz);          /* Segment size in file */
+    bswaps(&phdr->p_memsz);           /* Segment size in memory */
+    bswaps(&phdr->p_align);           /* Segment alignment */
+}
+
+static void elfN(bswap_shdr)(ElfN(Shdr) *shdr)
+{
+    bswaps(&shdr->sh_name);
+    bswaps(&shdr->sh_type);
+    bswaps(&shdr->sh_flags);
+    bswaps(&shdr->sh_addr);
+    bswaps(&shdr->sh_offset);
+    bswaps(&shdr->sh_size);
+    bswaps(&shdr->sh_link);
+    bswaps(&shdr->sh_info);
+    bswaps(&shdr->sh_addralign);
+    bswaps(&shdr->sh_entsize);
+}
+
+static void elfN(bswap_sym)(ElfN(Sym) *sym)
+{
+    bswaps(&sym->st_name);
+    bswaps(&sym->st_value);
+    bswaps(&sym->st_size);
+    bswaps(&sym->st_shndx);
+}
+
+static void elfN(bswap_dyn)(ElfN(Dyn) *dyn)
+{
+    bswaps(&dyn->d_tag);              /* Dynamic type tag */
+    bswaps(&dyn->d_un.d_ptr);         /* Dynamic ptr or val, in union */
+}
+
+static void elfN(search_symtab)(ElfN(Shdr) *shdr, unsigned sym_idx,
+                                void *buf, bool need_bswap)
+{
+    unsigned str_idx = shdr[sym_idx].sh_link;
+    ElfN(Sym) *sym = buf + shdr[sym_idx].sh_offset;
+    unsigned sym_n = shdr[sym_idx].sh_size / sizeof(*sym);
+    const char *str = buf + shdr[str_idx].sh_offset;
+
+    for (unsigned i = 0; i < sym_n; ++i) {
+        const char *name;
+
+        if (need_bswap) {
+            elfN(bswap_sym)(sym + i);
+        }
+        name = str + sym[i].st_name;
+
+        if (sigreturn_sym && strcmp(sigreturn_sym, name) == 0) {
+            sigreturn_addr = sym[i].st_value;
+        }
+        if (rt_sigreturn_sym && strcmp(rt_sigreturn_sym, name) == 0) {
+            rt_sigreturn_addr = sym[i].st_value;
+        }
+    }
+}
+
+static void elfN(process)(FILE *outf, void *buf, bool need_bswap)
+{
+    ElfN(Ehdr) *ehdr = buf;
+    ElfN(Phdr) *phdr;
+    ElfN(Shdr) *shdr;
+    unsigned phnum, shnum;
+    unsigned dynamic_ofs = 0;
+    unsigned dynamic_addr = 0;
+    unsigned symtab_idx = 0;
+    unsigned dynsym_idx = 0;
+    unsigned first_segsz = 0;
+    int errors = 0;
+
+    if (need_bswap) {
+        elfN(bswap_ehdr)(ehdr);
+    }
+
+    phnum = ehdr->e_phnum;
+    phdr = buf + ehdr->e_phoff;
+    if (need_bswap) {
+        for (unsigned i = 0; i < phnum; ++i) {
+            elfN(bswap_phdr)(phdr + i);
+        }
+    }
+
+    shnum = ehdr->e_shnum;
+    shdr = buf + ehdr->e_shoff;
+    if (need_bswap) {
+        for (unsigned i = 0; i < shnum; ++i) {
+            elfN(bswap_shdr)(shdr + i);
+        }
+    }
+    for (unsigned i = 0; i < shnum; ++i) {
+        switch (shdr[i].sh_type) {
+        case SHT_SYMTAB:
+            symtab_idx = i;
+            break;
+        case SHT_DYNSYM:
+            dynsym_idx = i;
+            break;
+        }
+    }
+
+    /*
+     * Validate the VDSO is created as we expect: that PT_PHDR,
+     * PT_DYNAMIC, and PT_NOTE located in a writable data segment.
+     * PHDR and DYNAMIC require relocation, and NOTE will get the
+     * linux version number.
+     */
+    for (unsigned i = 0; i < phnum; ++i) {
+        if (phdr[i].p_type != PT_LOAD) {
+            continue;
+        }
+        if (first_segsz != 0) {
+            fprintf(stderr, "Multiple LOAD segments\n");
+            errors++;
+        }
+        if (phdr[i].p_offset != 0) {
+            fprintf(stderr, "LOAD segment does not cover EHDR\n");
+            errors++;
+        }
+        if (phdr[i].p_vaddr != 0) {
+            fprintf(stderr, "LOAD segment not loaded at address 0\n");
+            errors++;
+        }
+        first_segsz = phdr[i].p_filesz;
+        if (first_segsz < ehdr->e_phoff + phnum * sizeof(*phdr)) {
+            fprintf(stderr, "LOAD segment does not cover PHDRs\n");
+            errors++;
+        }
+        if ((phdr[i].p_flags & (PF_R | PF_W)) != (PF_R | PF_W)) {
+            fprintf(stderr, "LOAD segment is not read-write\n");
+            errors++;
+        }
+    }
+    for (unsigned i = 0; i < phnum; ++i) {
+        const char *which;
+
+        switch (phdr[i].p_type) {
+        case PT_PHDR:
+            which = "PT_PHDR";
+            break;
+        case PT_NOTE:
+            which = "PT_NOTE";
+            break;
+        case PT_DYNAMIC:
+            dynamic_ofs = phdr[i].p_offset;
+            dynamic_addr = phdr[i].p_vaddr;
+            which = "PT_DYNAMIC";
+            break;
+        default:
+            continue;
+        }
+        if (first_segsz < phdr[i].p_vaddr + phdr[i].p_filesz) {
+            fprintf(stderr, "LOAD segment does not cover %s\n", which);
+            errors++;
+        }
+    }
+    if (errors) {
+        exit(EXIT_FAILURE);
+    }
+
+    /* Relocate the program headers. */
+    for (unsigned i = 0; i < phnum; ++i) {
+        output_reloc(outf, buf, &phdr[i].p_vaddr);
+        output_reloc(outf, buf, &phdr[i].p_paddr);
+    }
+
+    /* Relocate the DYNAMIC entries. */
+    if (dynamic_addr) {
+        ElfN(Dyn) *dyn = buf + dynamic_ofs;
+        __typeof(dyn->d_tag) tag;
+
+        do {
+
+            if (need_bswap) {
+                elfN(bswap_dyn)(dyn);
+            }
+            tag = dyn->d_tag;
+
+            switch (tag) {
+            case DT_HASH:
+            case DT_SYMTAB:
+            case DT_STRTAB:
+            case DT_VERDEF:
+            case DT_VERSYM:
+            case DT_PLTGOT:
+            case DT_ADDRRNGLO ... DT_ADDRRNGHI:
+                /* These entries store an address in the entry. */
+                output_reloc(outf, buf, &dyn->d_un.d_val);
+                break;
+
+            case DT_NULL:
+            case DT_STRSZ:
+            case DT_SONAME:
+            case DT_DEBUG:
+            case DT_FLAGS:
+            case DT_FLAGS_1:
+            case DT_SYMBOLIC:
+            case DT_BIND_NOW:
+            case DT_VERDEFNUM:
+            case DT_VALRNGLO ... DT_VALRNGHI:
+                /* These entries store an integer in the entry. */
+                break;
+
+            case DT_SYMENT:
+                if (dyn->d_un.d_val != sizeof(ElfN(Sym))) {
+                    fprintf(stderr, "VDSO has incorrect dynamic symbol size\n");
+                    errors++;
+                }
+                break;
+
+            case DT_REL:
+            case DT_RELSZ:
+            case DT_RELA:
+            case DT_RELASZ:
+                /*
+                 * These entries indicate that the VDSO was built incorrectly.
+                 * It should not have any real relocations.
+                 * ??? The RISC-V toolchain will emit these even when there
+                 * are no relocations.  Validate zeros.
+                 */
+                if (dyn->d_un.d_val != 0) {
+                    fprintf(stderr, "VDSO has dynamic relocations\n");
+                    errors++;
+                }
+                break;
+            case DT_RELENT:
+            case DT_RELAENT:
+            case DT_TEXTREL:
+                /* These entries store an integer in the entry. */
+                /* Should not be required; see above. */
+                break;
+
+            case DT_NEEDED:
+            case DT_VERNEED:
+            case DT_PLTREL:
+            case DT_JMPREL:
+            case DT_RPATH:
+            case DT_RUNPATH:
+                fprintf(stderr, "VDSO has external dependencies\n");
+                errors++;
+                break;
+
+            default:
+                /* This is probably something target specific. */
+                fprintf(stderr, "VDSO has unknown DYNAMIC entry (%lx)\n",
+                        (unsigned long)tag);
+                errors++;
+                break;
+            }
+            dyn++;
+        } while (tag != DT_NULL);
+        if (errors) {
+            exit(EXIT_FAILURE);
+        }
+    }
+
+    /* Relocate the dynamic symbol table. */
+    if (dynsym_idx) {
+        ElfN(Sym) *sym = buf + shdr[dynsym_idx].sh_offset;
+        unsigned sym_n = shdr[dynsym_idx].sh_size / sizeof(*sym);
+
+        for (unsigned i = 0; i < sym_n; ++i) {
+            output_reloc(outf, buf, &sym[i].st_value);
+        }
+    }
+
+    /* Search both dynsym and symtab for the signal return symbols. */
+    if (dynsym_idx) {
+        elfN(search_symtab)(shdr, dynsym_idx, buf, need_bswap);
+    }
+    if (symtab_idx) {
+        elfN(search_symtab)(shdr, symtab_idx, buf, need_bswap);
+    }
+}
diff --git a/linux-user/meson.build b/linux-user/meson.build
index 7171dc60be..e4cb70ed2d 100644
--- a/linux-user/meson.build
+++ b/linux-user/meson.build
@@ -28,9 +28,13 @@ linux_user_ss.add(when: 'TARGET_HAS_BFLT', if_true: files('flatload.c'))
 linux_user_ss.add(when: 'TARGET_I386', if_true: files('vm86.c'))
 linux_user_ss.add(when: 'CONFIG_ARM_COMPATIBLE_SEMIHOSTING', if_true: files('semihost.c'))
 
-
 syscall_nr_generators = {}
 
+gen_vdso_exe = executable('gen-vdso', 'gen-vdso.c',
+                          native: true, build_by_default: false)
+gen_vdso = generator(gen_vdso_exe, output: '@BASENAME@.c.inc',
+                     arguments: ['-o', '@OUTPUT@', '@EXTRA_ARGS@', '@INPUT@'])
+
 subdir('alpha')
 subdir('arm')
 subdir('hppa')
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH v6 09/19] linux-user/i386: Add vdso
  2023-09-30  2:15 [PATCH v6 00/19] linux-user: Implement VDSOs Richard Henderson
                   ` (7 preceding siblings ...)
  2023-09-30  2:15 ` [PATCH v6 08/19] linux-user: Add gen-vdso tool Richard Henderson
@ 2023-09-30  2:15 ` Richard Henderson
  2023-10-05 16:42   ` Philippe Mathieu-Daudé
  2023-09-30  2:15 ` [PATCH v6 10/19] linux-user/x86_64: " Richard Henderson
                   ` (9 subsequent siblings)
  18 siblings, 1 reply; 37+ messages in thread
From: Richard Henderson @ 2023-09-30  2:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.bennee, laurent

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1267
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/i386/vdso-asmoffset.h |   6 ++
 linux-user/elfload.c             |  19 +++-
 linux-user/i386/signal.c         |  11 +++
 linux-user/i386/Makefile.vdso    |  11 +++
 linux-user/i386/meson.build      |   7 ++
 linux-user/i386/vdso.S           | 143 +++++++++++++++++++++++++++++++
 linux-user/i386/vdso.ld          |  76 ++++++++++++++++
 linux-user/i386/vdso.so          | Bin 0 -> 2672 bytes
 8 files changed, 271 insertions(+), 2 deletions(-)
 create mode 100644 linux-user/i386/vdso-asmoffset.h
 create mode 100644 linux-user/i386/Makefile.vdso
 create mode 100644 linux-user/i386/vdso.S
 create mode 100644 linux-user/i386/vdso.ld
 create mode 100755 linux-user/i386/vdso.so

diff --git a/linux-user/i386/vdso-asmoffset.h b/linux-user/i386/vdso-asmoffset.h
new file mode 100644
index 0000000000..4e5ee0dd49
--- /dev/null
+++ b/linux-user/i386/vdso-asmoffset.h
@@ -0,0 +1,6 @@
+/*
+ * offsetof(struct sigframe, sc.eip)
+ * offsetof(struct rt_sigframe, uc.tuc_mcontext.eip)
+ */
+#define SIGFRAME_SIGCONTEXT_eip      64
+#define RT_SIGFRAME_SIGCONTEXT_eip  220
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 9c97d14b7e..314ae7cacf 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -305,12 +305,27 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *en
     (*regs)[15] = tswapreg(env->regs[R_ESP]);
     (*regs)[16] = tswapreg(env->segs[R_SS].selector & 0xffff);
 }
-#endif
+
+/*
+ * i386 is the only target which supplies AT_SYSINFO for the vdso.
+ * All others only supply AT_SYSINFO_EHDR.
+ */
+#define DLINFO_ARCH_ITEMS (vdso_info != NULL)
+#define ARCH_DLINFO                                     \
+    do {                                                \
+        if (vdso_info) {                                \
+            NEW_AUX_ENT(AT_SYSINFO, vdso_info->entry);  \
+        }                                               \
+    } while (0)
+
+#define VDSO_HEADER "vdso.c.inc"
+
+#endif /* TARGET_X86_64 */
 
 #define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE       4096
 
-#endif
+#endif /* TARGET_I386 */
 
 #ifdef TARGET_ARM
 
diff --git a/linux-user/i386/signal.c b/linux-user/i386/signal.c
index 60fa07d6f9..bc5d45302e 100644
--- a/linux-user/i386/signal.c
+++ b/linux-user/i386/signal.c
@@ -214,6 +214,17 @@ struct rt_sigframe {
 };
 #define TARGET_RT_SIGFRAME_FXSAVE_OFFSET (                                 \
     offsetof(struct rt_sigframe, fpstate) + TARGET_FPSTATE_FXSAVE_OFFSET)
+
+/*
+ * Verify that vdso-asmoffset.h constants match.
+ */
+#include "i386/vdso-asmoffset.h"
+
+QEMU_BUILD_BUG_ON(offsetof(struct sigframe, sc.eip)
+                  != SIGFRAME_SIGCONTEXT_eip);
+QEMU_BUILD_BUG_ON(offsetof(struct rt_sigframe, uc.tuc_mcontext.eip)
+                  != RT_SIGFRAME_SIGCONTEXT_eip);
+
 #else
 
 struct rt_sigframe {
diff --git a/linux-user/i386/Makefile.vdso b/linux-user/i386/Makefile.vdso
new file mode 100644
index 0000000000..95bc616f6d
--- /dev/null
+++ b/linux-user/i386/Makefile.vdso
@@ -0,0 +1,11 @@
+include $(BUILD_DIR)/tests/tcg/i386-linux-user/config-target.mak
+
+SUBDIR = $(SRC_PATH)/linux-user/i386
+VPATH += $(SUBDIR)
+
+all: $(SUBDIR)/vdso.so
+
+$(SUBDIR)/vdso.so: vdso.S vdso.ld vdso-asmoffset.h
+	$(CC) -o $@ -m32 -nostdlib -shared -Wl,-h,linux-gate.so.1 \
+	  -Wl,--build-id=sha1 -Wl,--hash-style=both \
+	  -Wl,-T,$(SUBDIR)/vdso.ld $<
diff --git a/linux-user/i386/meson.build b/linux-user/i386/meson.build
index ee523019a5..d42fc6cbc9 100644
--- a/linux-user/i386/meson.build
+++ b/linux-user/i386/meson.build
@@ -3,3 +3,10 @@ syscall_nr_generators += {
                     arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ],
                     output: '@BASENAME@_nr.h')
 }
+
+vdso_inc = gen_vdso.process('vdso.so', extra_args: [
+                                '-s', '__kernel_sigreturn',
+                                '-r', '__kernel_rt_sigreturn'
+                            ])
+
+linux_user_ss.add(when: 'TARGET_I386', if_true: vdso_inc)
diff --git a/linux-user/i386/vdso.S b/linux-user/i386/vdso.S
new file mode 100644
index 0000000000..e7a1f333a1
--- /dev/null
+++ b/linux-user/i386/vdso.S
@@ -0,0 +1,143 @@
+/*
+ * i386 linux replacement vdso.
+ *
+ * Copyright 2023 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <asm/unistd.h>
+#include "vdso-asmoffset.h"
+
+.macro endf name
+	.globl	\name
+	.type	\name, @function
+	.size	\name, . - \name
+.endm
+
+.macro vdso_syscall1 name, nr
+\name:
+	.cfi_startproc
+	mov	%ebx, %edx
+	.cfi_register %ebx, %edx
+	mov	4(%esp), %ebx
+	mov	$\nr, %eax
+	int	$0x80
+	mov	%edx, %ebx
+	ret
+	.cfi_endproc
+endf	\name
+.endm
+
+.macro vdso_syscall2 name, nr
+\name:
+	.cfi_startproc
+	mov	%ebx, %edx
+	.cfi_register %ebx, %edx
+	mov	4(%esp), %ebx
+	mov	8(%esp), %ecx
+	mov	$\nr, %eax
+	int	$0x80
+	mov	%edx, %ebx
+	ret
+	.cfi_endproc
+endf	\name
+.endm
+
+.macro vdso_syscall3 name, nr
+\name:
+	.cfi_startproc
+	push	%ebx
+	.cfi_adjust_cfa_offset 4
+	.cfi_rel_offset %ebx, 0
+	mov	8(%esp), %ebx
+	mov	12(%esp), %ecx
+	mov	16(%esp), %edx
+	mov	$\nr, %eax
+	int	$0x80
+	pop	%ebx
+	.cfi_adjust_cfa_offset -4
+	.cfi_restore %ebx
+	ret
+	.cfi_endproc
+endf	\name
+.endm
+
+__kernel_vsyscall:
+	.cfi_startproc
+	int	$0x80
+	ret
+	.cfi_endproc
+endf	__kernel_vsyscall
+
+vdso_syscall2 __vdso_clock_gettime, __NR_clock_gettime
+vdso_syscall2 __vdso_clock_gettime64, __NR_clock_gettime64
+vdso_syscall2 __vdso_clock_getres, __NR_clock_getres
+vdso_syscall2 __vdso_gettimeofday, __NR_gettimeofday
+vdso_syscall1 __vdso_time, __NR_time
+vdso_syscall3 __vdso_getcpu, __NR_gettimeofday
+
+/*
+ * Signal return handlers.
+ */
+
+	.cfi_startproc simple
+	.cfi_signal_frame
+
+/*
+ * For convenience, put the cfa just above eip in sigcontext, and count
+ * offsets backward from there.  Re-compute the cfa in the two contexts
+ * we have for signal unwinding.  This is far simpler than the
+ * DW_CFA_expression form that the kernel uses, and is equally correct.
+ */
+
+	.cfi_def_cfa	%esp, SIGFRAME_SIGCONTEXT_eip + 4
+
+	.cfi_offset	%eip, -4
+			/* err, -8 */
+			/* trapno, -12 */
+	.cfi_offset	%eax, -16
+	.cfi_offset	%ecx, -20
+	.cfi_offset	%edx, -24
+	.cfi_offset	%ebx, -28
+	.cfi_offset	%esp, -32
+	.cfi_offset	%ebp, -36
+	.cfi_offset	%esi, -40
+	.cfi_offset	%edi, -44
+
+/*
+ * While this frame is marked as a signal frame, that only applies to how
+ * the return address is handled for the outer frame.  The return address
+ * that arrived here, from the inner frame, is not marked as a signal frame
+ * and so the unwinder still tries to subtract 1 to examine the presumed
+ * call insn.  Thus we must extend the unwind info to a nop before the start.
+ */
+	nop
+
+__kernel_sigreturn:
+	popl	%eax	/* pop sig */
+	.cfi_adjust_cfa_offset -4
+	movl	$__NR_sigreturn, %eax
+	int	$0x80
+endf	__kernel_sigreturn
+
+	.cfi_def_cfa_offset RT_SIGFRAME_SIGCONTEXT_eip + 4
+	nop
+
+__kernel_rt_sigreturn:
+	movl	$__NR_rt_sigreturn, %eax
+	int	$0x80
+endf	__kernel_rt_sigreturn
+
+	.cfi_endproc
+
+/*
+ * TODO: Add elf notes.  E.g.
+ *
+ * #include <linux/elfnote.h>
+ * ELFNOTE_START(Linux, 0, "a")
+ *   .long LINUX_VERSION_CODE
+ * ELFNOTE_END
+ *
+ * but what version number would we set for QEMU?
+ */
diff --git a/linux-user/i386/vdso.ld b/linux-user/i386/vdso.ld
new file mode 100644
index 0000000000..326b7a8f98
--- /dev/null
+++ b/linux-user/i386/vdso.ld
@@ -0,0 +1,76 @@
+/*
+ * Linker script for linux i386 replacement vdso.
+ *
+ * Copyright 2023 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+ENTRY(__kernel_vsyscall)
+
+VERSION {
+        LINUX_2.6 {
+        global:
+                __vdso_clock_gettime;
+                __vdso_gettimeofday;
+                __vdso_time;
+                __vdso_clock_getres;
+                __vdso_clock_gettime64;
+                __vdso_getcpu;
+        };
+
+        LINUX_2.5 {
+        global:
+                __kernel_vsyscall;
+                __kernel_sigreturn;
+                __kernel_rt_sigreturn;
+        local: *;
+        };
+}
+
+PHDRS {
+        phdr            PT_PHDR         FLAGS(4) PHDRS;
+        load            PT_LOAD         FLAGS(7) FILEHDR PHDRS; /* FLAGS=RWX */
+        dynamic         PT_DYNAMIC      FLAGS(4);
+        eh_frame_hdr    PT_GNU_EH_FRAME;
+        note            PT_NOTE         FLAGS(4);
+}
+
+SECTIONS {
+        . = SIZEOF_HEADERS;
+
+        /*
+         * The following, including the FILEHDRS and PHDRS, are modified
+         * when we relocate the binary.  We want them to be initially
+         * writable for the relocation; we'll force them read-only after.
+         */
+        .note           : { *(.note*) }         :load :note
+        .dynamic        : { *(.dynamic) }       :load :dynamic
+        .dynsym         : { *(.dynsym) }        :load
+        .data           : {
+                /*
+                 * There ought not be any real read-write data.
+                 * But since we manipulated the segment layout,
+                 * we have to put these sections somewhere.
+                 */
+                *(.data*)
+                *(.sdata*)
+                *(.got.plt) *(.got)
+                *(.gnu.linkonce.d.*)
+                *(.bss*)
+                *(.dynbss*)
+                *(.gnu.linkonce.b.*)
+        }
+
+        .rodata         : { *(.rodata*) }
+        .hash           : { *(.hash) }
+        .gnu.hash       : { *(.gnu.hash) }
+        .dynstr         : { *(.dynstr) }
+        .gnu.version    : { *(.gnu.version) }
+        .gnu.version_d  : { *(.gnu.version_d) }
+        .gnu.version_r  : { *(.gnu.version_r) }
+        .eh_frame_hdr   : { *(.eh_frame_hdr) }  :load :eh_frame_hdr
+        .eh_frame       : { *(.eh_frame) }      :load
+
+        .text           : { *(.text*) }         :load   =0x90909090
+}
diff --git a/linux-user/i386/vdso.so b/linux-user/i386/vdso.so
new file mode 100755
index 0000000000000000000000000000000000000000..bdece5dfcf8da036d013262d4e37208350283cfa
GIT binary patch
literal 2672
zcmbtWU1%It6u#5lG_z^4ZB?X_C>9o5sxCF8QBlyONt?nZ)?|y73e)ZGba%;SR(597
zjTXE8QIiHtY6YPbDhO>6s(mPS(FX(Z2Q`g?1xp_^KInr_=|f8&)b;yj=5}w=eGok1
z%XiMX=brmB_ny0ldSlx(O%qZAA|PnR8-(ZpuhYGj4)L&P5F5p65f&@qVw=PV(21ar
zS~fT!zaSUUNMnr<D?qmul%W%{|IXi?lnz58hBiXBldmd>Kqu7p`(Ouv?E|~S#J4vR
z?eBj&+ji~rg~eZ!zf~VSJr_pXM}D8DFrl0ORPzVHn5LKmbB!e|qzOC^tO77~@mIB)
zzl6kpgPDI3e2U8d6uIY2bq_`x0-wZWxDMLSfe$J6M%crOeHivUY<@1rr@`l7bI!EC
z1WQ>fZdBic@iW@_P1t@f_$4LZXEGSfcpH2f?e~Kj&v`Zj+$T!NBlkb|jQhnHeiL+a
z&lJb<kCS@_*v@tHJTOn=lluBDy{$|iW0~jDvC(tlyVi??Q=2p0KUP})m@B{A^3Fp?
z#y5Ta$e&ZC6Ayg2)jAG+!^M53FpOcdV3|2%)E={wiChkz(UhGxlDT|x*hrg>lO18$
z-OkRAyW9oSmOj5{et#-4CVgruv?pIJqQxKI&ZY~dQ!H3DSHUrA-dxrymL5+h95ZU?
zqfdy~j)7gfjrM5g9c>HN9>C7<kIZ}NS==-4@5JK#YMzfafM=QF?WZPg6+aHhHu){t
z#@l_<Z)3bX7g}rJnLgP3J~0HQz%PJH;3Rk&d;okNJPDowp8;P3e*#_ve+BLUI4(td
zZBS?jb*;5I7#xS6XOVMV0Ql`GjNJ_U;OnA06ySNFpY!>?j(;zF-_-GQuCsOgock95
z$CvrnLFHO513c5BE36+~5f2BEAVM30`47nj^o(oe;NgZND~~oF)87oe)%5l%caD!C
zZUR`#4&CABw}%(BE9KdV>yxiUf|Id`UI}64SIQGVslJnSd`)$H14yd$t+Ysc2<dgC
zZ=Q@t)>OQ(J+srhD+k<&>B<F{@o$-65V!Wyt>HxRj<L>q5)uze70i3T0nE36-;4MD
zX|P(C`eCbeVGnF6>~F$Q>&)x0)jBo>TdiYfVXJlMbJ%KKV=Y$enlO4^9_Z@du@yHB
zwchCMGqw$O_4gWmJ%e{HQ)lfOF0TyrZnl4$<)z$G>%HU>FE1lXy;xFj>Xa70cGRgB
zZe?<tMbsV}aT5E$PQl}h)U3Q?ifC%gN{nQau7X$*O<ToiCShkhk5lkGqh`U*=B*`$
zkrGieW9%;^Moc4<LZq}r)G<pAcKN?aE5cZ-d1tTskoO0sTmQ-H0oHh)quV~pVEQOL
zf~-B80KOf}$M=_*fzCLdUB>YqcLID@7{~XU=z-4s6vh$lz%9JdjN|)G?1a8N?pfc*
zIKKY`&zcmDP2m_-KOf(Hg0)2EV}IgBfWHx_^Y;P~hc5SkbEE79n459x?;V(~$T$m@
zjElobxDGGOT`N`AK*n(#-do~0bSZKjGMDr(AZ`H$D-74d^xS8@>$IiJAn|o+fMq_`
OKQ-<Y4#gXF;{FA}h_Ctp

literal 0
HcmV?d00001

-- 
2.34.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH v6 10/19] linux-user/x86_64: Add vdso
  2023-09-30  2:15 [PATCH v6 00/19] linux-user: Implement VDSOs Richard Henderson
                   ` (8 preceding siblings ...)
  2023-09-30  2:15 ` [PATCH v6 09/19] linux-user/i386: Add vdso Richard Henderson
@ 2023-09-30  2:15 ` Richard Henderson
  2023-10-05 16:44   ` Philippe Mathieu-Daudé
  2023-09-30  2:15 ` [PATCH v6 11/19] linux-user/aarch64: " Richard Henderson
                   ` (8 subsequent siblings)
  18 siblings, 1 reply; 37+ messages in thread
From: Richard Henderson @ 2023-09-30  2:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.bennee, laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/elfload.c            |   4 +-
 linux-user/x86_64/Makefile.vdso |  11 +++++
 linux-user/x86_64/meson.build   |   4 ++
 linux-user/x86_64/vdso.S        |  78 ++++++++++++++++++++++++++++++++
 linux-user/x86_64/vdso.ld       |  73 ++++++++++++++++++++++++++++++
 linux-user/x86_64/vdso.so       | Bin 0 -> 2968 bytes
 6 files changed, 168 insertions(+), 2 deletions(-)
 create mode 100644 linux-user/x86_64/Makefile.vdso
 create mode 100644 linux-user/x86_64/vdso.S
 create mode 100644 linux-user/x86_64/vdso.ld
 create mode 100755 linux-user/x86_64/vdso.so

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 314ae7cacf..1e1fdce656 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -318,10 +318,10 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *en
         }                                               \
     } while (0)
 
-#define VDSO_HEADER "vdso.c.inc"
-
 #endif /* TARGET_X86_64 */
 
+#define VDSO_HEADER "vdso.c.inc"
+
 #define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE       4096
 
diff --git a/linux-user/x86_64/Makefile.vdso b/linux-user/x86_64/Makefile.vdso
new file mode 100644
index 0000000000..26552b66db
--- /dev/null
+++ b/linux-user/x86_64/Makefile.vdso
@@ -0,0 +1,11 @@
+include $(BUILD_DIR)/tests/tcg/x86_64-linux-user/config-target.mak
+
+SUBDIR = $(SRC_PATH)/linux-user/x86_64
+VPATH += $(SUBDIR)
+
+all: $(SUBDIR)/vdso.so
+
+$(SUBDIR)/vdso.so: vdso.S vdso.ld
+	$(CC) -o $@ -nostdlib -shared -Wl,-h,linux-vdso.so.1 \
+	  -Wl,--build-id=sha1 -Wl,--hash-style=both \
+	  -Wl,-T,$(SUBDIR)/vdso.ld $<
diff --git a/linux-user/x86_64/meson.build b/linux-user/x86_64/meson.build
index 203af9a60c..8c60da7a60 100644
--- a/linux-user/x86_64/meson.build
+++ b/linux-user/x86_64/meson.build
@@ -3,3 +3,7 @@ syscall_nr_generators += {
                       arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ],
                       output: '@BASENAME@_nr.h')
 }
+
+vdso_inc = gen_vdso.process('vdso.so')
+
+linux_user_ss.add(when: 'TARGET_X86_64', if_true: vdso_inc)
diff --git a/linux-user/x86_64/vdso.S b/linux-user/x86_64/vdso.S
new file mode 100644
index 0000000000..47d16c00ab
--- /dev/null
+++ b/linux-user/x86_64/vdso.S
@@ -0,0 +1,78 @@
+/*
+ * x86-64 linux replacement vdso.
+ *
+ * Copyright 2023 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <asm/unistd.h>
+
+.macro endf name
+	.globl	\name
+	.type	\name, @function
+	.size	\name, . - \name
+.endm
+
+.macro weakalias name
+\name	= __vdso_\name
+	.weak	\name
+.endm
+
+.macro vdso_syscall name, nr
+__vdso_\name:
+	mov	$\nr, %eax
+	syscall
+	ret
+endf	__vdso_\name
+weakalias \name
+.endm
+
+	.cfi_startproc
+
+vdso_syscall clock_gettime, __NR_clock_gettime
+vdso_syscall clock_getres, __NR_clock_getres
+vdso_syscall gettimeofday, __NR_gettimeofday
+vdso_syscall time, __NR_time
+
+__vdso_getcpu:
+	/*
+         * There is no syscall number for this allocated on x64.
+	 * We can handle this several ways:
+         *
+	 * (1) Invent a syscall number for use within qemu.
+         *     It should be easy enough to pick a number that
+         *     is well out of the way of the kernel numbers.
+         *
+         * (2) Force the emulated cpu to support the rdtscp insn,
+	 *     and initialize the TSC_AUX value the appropriate value.
+         *
+	 * (3) Pretend that we're always running on cpu 0.
+         *
+	 * This last is the one that's implemented here, with the
+	 * tiny bit of extra code to support rdtscp in place.
+         */
+	xor	%ecx, %ecx		/* rdtscp w/ tsc_aux = 0 */
+
+	/* if (cpu != NULL) *cpu = (ecx & 0xfff); */
+	test	%rdi, %rdi
+	jz	1f
+	mov	%ecx, %eax
+	and	$0xfff, %eax
+	mov	%eax, (%rdi)
+
+	/* if (node != NULL) *node = (ecx >> 12); */
+1:	test	%rsi, %rsi
+	jz	2f
+	shr	$12, %ecx
+	mov	%ecx, (%rsi)
+
+2:	xor	%eax, %eax
+	ret
+endf	__vdso_getcpu
+
+weakalias getcpu
+
+	.cfi_endproc
+
+/* TODO: Add elf note for LINUX_VERSION_CODE */
diff --git a/linux-user/x86_64/vdso.ld b/linux-user/x86_64/vdso.ld
new file mode 100644
index 0000000000..ca6001cc3c
--- /dev/null
+++ b/linux-user/x86_64/vdso.ld
@@ -0,0 +1,73 @@
+/*
+ * Linker script for linux x86-64 replacement vdso.
+ *
+ * Copyright 2023 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+VERSION {
+        LINUX_2.6 {
+        global:
+                clock_gettime;
+                __vdso_clock_gettime;
+                gettimeofday;
+                __vdso_gettimeofday;
+                getcpu;
+                __vdso_getcpu;
+                time;
+                __vdso_time;
+                clock_getres;
+                __vdso_clock_getres;
+
+        local: *;
+        };
+}
+
+
+PHDRS {
+        phdr            PT_PHDR         FLAGS(4) PHDRS;
+        load            PT_LOAD         FLAGS(7) FILEHDR PHDRS; /* FLAGS=RWX */
+        dynamic         PT_DYNAMIC      FLAGS(4);
+        eh_frame_hdr    PT_GNU_EH_FRAME;
+        note            PT_NOTE         FLAGS(4);
+}
+
+SECTIONS {
+        . = SIZEOF_HEADERS;
+
+        /*
+         * The following, including the FILEHDRS and PHDRS, are modified
+         * when we relocate the binary.  We want them to be initially
+         * writable for the relocation; we'll force them read-only after.
+         */
+        .note           : { *(.note*) }         :load :note
+        .dynamic        : { *(.dynamic) }       :load :dynamic
+        .dynsym         : { *(.dynsym) }        :load
+        .data           : {
+                /*
+                 * There ought not be any real read-write data.
+                 * But since we manipulated the segment layout,
+                 * we have to put these sections somewhere.
+                 */
+                *(.data*)
+                *(.sdata*)
+                *(.got.plt) *(.got)
+                *(.gnu.linkonce.d.*)
+                *(.bss*)
+                *(.dynbss*)
+                *(.gnu.linkonce.b.*)
+        }
+
+        .rodata         : { *(.rodata*) }
+        .hash           : { *(.hash) }
+        .gnu.hash       : { *(.gnu.hash) }
+        .dynstr         : { *(.dynstr) }
+        .gnu.version    : { *(.gnu.version) }
+        .gnu.version_d  : { *(.gnu.version_d) }
+        .gnu.version_r  : { *(.gnu.version_r) }
+        .eh_frame_hdr   : { *(.eh_frame_hdr) }  :load :eh_frame_hdr
+        .eh_frame       : { *(.eh_frame) }      :load
+
+        .text           : { *(.text*) }         :load   =0x90909090
+}
diff --git a/linux-user/x86_64/vdso.so b/linux-user/x86_64/vdso.so
new file mode 100755
index 0000000000000000000000000000000000000000..c873d6ea580b393825506d2ffbddcf9827d89e14
GIT binary patch
literal 2968
zcmcgtO=w(I6uvKUOl$t7l}J=nY6?Lgol-PVEvcEL6HP)om@-1c>vZO|6VjQnGcRQ#
zQlk(xE{v3}x(Eh$E+iYFJ0pdXxDr=E=&lLvMs(4vwBz~aoiCl-j=CuHBzL}hzkANP
z=iPhmJs%H_3^h28p){If=E2CAex2B8q6WA=6OrF`(`KF&`Uz?MI&EW@IwS5;J<v5S
zm3;u8M8ZDNbcEvu0jxKter?<dUgx>q_-2rSodh0=h5M8yR&|8~q9xUzjR(|@2weye
zz8a;S7@IIXlUIKD#o1b1+rN5odUE>L=z;rh$dv40C`m=ye*;62d-p2^;2j+^>^@b*
z{zK-lF(OZeV2X;(id~9-RYHGjYX7&6)!h7{<L?-V+C6T-xxH+fO-w(S=h!R!)55=J
z@z1ONh{Zpn`Zga`ecR75)jw_d8B~3nM_M2rJI<`|o#xMqz%F@5M$pfwf5Z(rDGlFi
z^EmbvX*g$?a37>=_DaLK@yv17h==zIwme4kF^2|U3rG4QL%vz2K73uCxOLI|+`aN!
z$F-%z;-Tzk@6K<ve)YnqSIbKuJ^SrI{>$E*Jv}RD{ao_%it)TlnNq<^Unr!fz4Lw$
zOy&HC$f92&rz(YWnba(~S{s>9e=uV%Oyy_Fufeq||4}nCJT{T^4!f^Qd<}K~WJ1Kz
zzvUl)Z^gZPP8#nNzOg~(w`aa@<o(9^K%DNzqu`(ulXgfNgnG`03FDMIobHyUJzt9w
zo+0?gnY<+pa{adav`21S-&8!KxE^A3Jw9Iv_AacwQfZf+Z;H=v2a%udwk)(oS8s^Q
ze+lApB>FjYY9u^!IW^5APGzK1@7^HK>gD4>;p^R}arI;0o1?04=jpKWw!W)=?0Yt=
zynUbER^IkMss3a7y}So_=McZ`$9S>#$BvH<4@j=b`|AzHy`jYM(LpaBOVlKlW^ujb
z)P%J2ye6gV=6*G&ja!<{1*x-wK{3QEd-+1(8#gnXPvxf4)sE;I_k4cF&8AA(kO_(*
zbIC83rV9C8121D-KkJ<<rgFZQ&4?yP#tr;(AUpEt(k(9Vj<7ELTixSId}la*Nji9E
z@a{mEzeGvus<3|XJhjXlyz_X^xc;1Wh%eUIqf2|%IlLE07230&5^>idjF0yGj>9sy
zEwzyLtiMFu4~T6avc|lrbF^o@CbB+LUq6S#>RVK)S)cWo$nWI(T!)Byg4)h8>pihg
zSHk{7hu^QXIU^m!MEjk0M(-crN9uFmIL=%4U1~>sm5Pe?`en6ee(>HC`S#L{y??u6
vr;^|o8ppUAv<ink<oeuK)I;vAba!M!1G>D!gdKbRPND1BpVH#|fA;?X5$6$T

literal 0
HcmV?d00001

-- 
2.34.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH v6 11/19] linux-user/aarch64: Add vdso
  2023-09-30  2:15 [PATCH v6 00/19] linux-user: Implement VDSOs Richard Henderson
                   ` (9 preceding siblings ...)
  2023-09-30  2:15 ` [PATCH v6 10/19] linux-user/x86_64: " Richard Henderson
@ 2023-09-30  2:15 ` Richard Henderson
  2023-10-05 16:47   ` Philippe Mathieu-Daudé
  2023-09-30  2:15 ` [PATCH v6 12/19] linux-user/arm: " Richard Henderson
                   ` (7 subsequent siblings)
  18 siblings, 1 reply; 37+ messages in thread
From: Richard Henderson @ 2023-09-30  2:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.bennee, laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/elfload.c             |   6 +++
 linux-user/aarch64/Makefile.vdso |  15 +++++++
 linux-user/aarch64/meson.build   |  11 +++++
 linux-user/aarch64/vdso-be.so    | Bin 0 -> 3216 bytes
 linux-user/aarch64/vdso-le.so    | Bin 0 -> 3216 bytes
 linux-user/aarch64/vdso.S        |  71 ++++++++++++++++++++++++++++++
 linux-user/aarch64/vdso.ld       |  72 +++++++++++++++++++++++++++++++
 linux-user/meson.build           |   1 +
 8 files changed, 176 insertions(+)
 create mode 100644 linux-user/aarch64/Makefile.vdso
 create mode 100644 linux-user/aarch64/meson.build
 create mode 100755 linux-user/aarch64/vdso-be.so
 create mode 100755 linux-user/aarch64/vdso-le.so
 create mode 100644 linux-user/aarch64/vdso.S
 create mode 100644 linux-user/aarch64/vdso.ld

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 1e1fdce656..693ebc94bd 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -944,6 +944,12 @@ const char *elf_hwcap2_str(uint32_t bit)
 
 #undef GET_FEATURE_ID
 
+#if TARGET_BIG_ENDIAN
+# define VDSO_HEADER  "vdso-be.c.inc"
+#else
+# define VDSO_HEADER  "vdso-le.c.inc"
+#endif
+
 #endif /* not TARGET_AARCH64 */
 #endif /* TARGET_ARM */
 
diff --git a/linux-user/aarch64/Makefile.vdso b/linux-user/aarch64/Makefile.vdso
new file mode 100644
index 0000000000..599958116b
--- /dev/null
+++ b/linux-user/aarch64/Makefile.vdso
@@ -0,0 +1,15 @@
+include $(BUILD_DIR)/tests/tcg/aarch64-linux-user/config-target.mak
+
+SUBDIR = $(SRC_PATH)/linux-user/aarch64
+VPATH += $(SUBDIR)
+
+all: $(SUBDIR)/vdso-be.so $(SUBDIR)/vdso-le.so
+
+LDFLAGS = -nostdlib -shared -Wl,-h,linux-vdso.so.1 -Wl,--build-id=sha1 \
+	  -Wl,--hash-style=both -Wl,-T,$(SUBDIR)/vdso.ld
+
+$(SUBDIR)/vdso-be.so: vdso.S vdso.ld
+	$(CC) -o $@ $(LDFLAGS) -mbig-endian $<
+
+$(SUBDIR)/vdso-le.so: vdso.S vdso.ld
+	$(CC) -o $@ $(LDFLAGS) -mlittle-endian $<
diff --git a/linux-user/aarch64/meson.build b/linux-user/aarch64/meson.build
new file mode 100644
index 0000000000..248c578d15
--- /dev/null
+++ b/linux-user/aarch64/meson.build
@@ -0,0 +1,11 @@
+# TARGET_BIG_ENDIAN is defined to 'n' for little-endian; which means it
+# is always true as far as source_set.apply() is concerned.  Always build
+# both header files and include the right one via #if.
+
+vdso_be_inc = gen_vdso.process('vdso-be.so',
+                               extra_args: ['-r', '__kernel_rt_sigreturn'])
+
+vdso_le_inc = gen_vdso.process('vdso-le.so',
+                               extra_args: ['-r', '__kernel_rt_sigreturn'])
+
+linux_user_ss.add(when: 'TARGET_AARCH64', if_true: [vdso_be_inc, vdso_le_inc])
diff --git a/linux-user/aarch64/vdso-be.so b/linux-user/aarch64/vdso-be.so
new file mode 100755
index 0000000000000000000000000000000000000000..6084f3d1a701316004894fcdd739c4e1e0463b68
GIT binary patch
literal 3216
zcmc&$O>A355T57v+64N8Q&ABq6>X&mRj7RmMS`Gmu!EhX$W24qs-c&yv0q~6$41XD
z#X$mc;KBh>)D!9f7jbE&o<UsN14xy6s{mC(f)i3Dq>3KO1&W#3omsDqjgUAn$-Zyr
zo0*+`yF2UmUcNA$N_k+#hcB@25ZaP4_Th`HO~N+FKpLJveLJ?m*pV~RgWjm21z{L<
z$}wd4LC@e<V_`J2N+HMjyq2;54GrCSjp1_g^L!^RXc~uJgeN&rkn%{wuD59Hy$Csu
z6QuW}xHPtHGjnI)CU#JW^L5YkDUVO~&u;(z;i>e4`!_DFeDmp#mw&i^<zSxu2zGP-
z93zc`;?p}pz5VAyLe#f3U`~Vnm#otsp`=<G03K(2i*W~|-luxI{fE(m3?b@|j1IK+
zq|3fcF#mr*xCdaTNgUke3DA1y9R42jv>z)Y(0;(W3!dXI>qX-{<?y#SfcSq9uZ2e1
zUtVwB=e^KjQdiCy);`2j+up*`@G|ff>*VL(Jr;fPar2{J(&x^9ec+i^?x(BSN1)Vd
z6xX6PwHzf$bv>#tm5ZAlwzO6+t%|J=9Y>808z-t!U5=w<Bd)<(wYJeba-rO)hxq>-
z6pqiGSyV^E7sBUX!r9;<vVWv`=5N>i8&^=H^Slq6Ij8hSDe#8W?GM<704wzH#{6Rl
z<WF81Y=^Ot=r#7<UVxzav^TbMzi@OmX}>3kP~-l0hxTsW!QgLi`s#bF@9x%T9lbJQ
zY!o|4aN}q$C{o`>LtdYI<XeWZJeo*sU1<$TsZTvuP2vN2smpoc2$ARWV(V9%ksmUC
zwvL6T^NbSoj{g|*8H47D<8ZypeP?;D``}`aztok~1DU;`fBleezjdSEhJND^CwV`|
zzLf#v@9}KjuJs?oz<%!)cKrQWJ2>781M2@Zr_SAbWZB{G@i?^Z?>M}yPa6444u6aN
z(@-i+W?!6HJsZ|xybR+_P`TIVvL}weg5`%7zsk?5>4ofxyqe7|fSM_soXQr|$?54+
z`P1rjcB+t9-4$r--d6bFQntST=8k}{vALcU-#|=agB9u3>PZA)d9zkrua<NNeG!XE
z5yIu#Mp!8}Duz#D!(52sMzvn+QdAkjsG^qQ;(DYiW%Lvc!X#=YylDRs=v;8!*t%Ub
zW7@jT_2i&^6*-6<_x?sz&YeZ_l^oQUcsd8qVw2xfzBf`W<WK~G>W$*LZfyK0az`B=
zOP9o-=tekTbo-S2gfC;0-yF_wz7ueqd5$=Y$YX0p;sews@%Q~V_LKN6qx+07iF&_y
za+`8&63=yF?=kuAAb%2B2kO6y`P<Y%;dr^{1oge*=4U_cf428~1@Fm>9?hbjKdryS
z$@`Pr5;mES<ZqGz$6>VJiH5fKy;kWM_r}wHqu6`)kkRea&Hpa463^!_;Pn&K^S8m+
zp?wpfSa~nu80C99^(GSZO}Up1l7AF+`VDc{mR$&j&a-ljQ9$NP`UtiG@xy#y!}}7*
HXyg9^8}}&g

literal 0
HcmV?d00001

diff --git a/linux-user/aarch64/vdso-le.so b/linux-user/aarch64/vdso-le.so
new file mode 100755
index 0000000000000000000000000000000000000000..947d534ec1899740edbd6921da6bc6e70e2ecd09
GIT binary patch
literal 3216
zcmcguL2MgU5FKYzk|v=|N~=Z+qD6{Og<utmRJD|Y9c(v2Zd%etExr7@_Qp0%>~_6L
z9VDO!E}RJB#LXZsa7BWO3q5c^;)VcKz2t<11S;tPP82h<JI`MKYy}b$WB;B1-^~2^
z`~S@Be=AqW52R8Aa_9@{jfm1J*c^t2V8>|}KgVe=J;LxHx3r3FKB<#|V;X^n)Fz2-
z%cM-;q^lZWOhj#+*XG^Ds~rB${uGqOuBG$Zd_T*Cz*Q~uCH;#!pUtzO6%jc6iOo2-
zUEEGBEQ!`_!5rx^Nnd=)Smd95v^A8^_@B?;{q2QA>mys0rC%Ro5$%x&)1`=ocG5ko
z6aD^Iry=8;Iu?IIw{$G$Bh;3SV;YGV-B3QNd{X(JooK$aERgAej@6vDbv&c;NbCQ9
zy6kcvjnN%lhwQabmYd)|D~|JcjqwS(-w~ZS$+3$5Eo+{GihpC_aoczwaVXo4J(oVt
zLv%HS2r(>}=m;)N?7pOQiiV@`7Cn)F;GMkl%e$@jzP@~EJllTi@Po`JTV%{t&#!wc
zrs4%bZPjZmmx~)cw6xMFU4<+G_Pu5g^#jwaReUd4^Xs%ytFN`5T`xBqF8`mS!u-P0
zMRU|W=01Od7sIQ^Pev*IefZVAM<t#g=Z097cN$>%JKvfi<dvL*P-@CKDVXS_xjn;8
z2<Mo3eUS!RPo$>C4uzP+=NPvcQDQRF&JRZp-29I1zrXF6AH(sU{_$LFT%Cwyk#+LZ
z;ng6&;~EaXMOzkXk;A9cMq<Qd4rl3%9GpcCM+5RUE^_$fk-z=;P&beJ@nK5JKZkY`
z^0r@pq+9p;@lo2;`0mGh`2bvAe=s3`<V@rg?S0!D;ydSw^hfFA1iwl1?+a(Y-?8_9
zDx81kdr4hL@jB<M{m(L<l>e_Vo>WIFiraPM4aMzx@xJ0a>P4w^{aUtsrS3Lpx=hn8
zGTB!bGN<QX;`HOfZ*p@cznD3lGjrKRGN%e>W-|qICZ9i-J8#ZsW(zsfpMl-H?`HVJ
zQ@N}AZ)ya&&5hNdc!hc3N4$z&y%BiimN)9f)mka+urBjrP$aifUvsO)W;MbCKSI_$
zzgcV4`v#^=u2(h7esR?^)iP^hL~h`<0^Y;_N)i`xuRvNNF2N-Z;)L%5uqU}Abr|7;
zxC7_l3JG@?*rRSe%~JWM!awQ*_-14tu2H6fJ-)w38511-QAfZJvn)=q2Y-=;^38#N
z)EjWrS<DYRq~me6{e!>put!}27rBsaAE89EDuX@lA>g=oKwq~LLwcEeotS^rIq;}{
z^!&pQ_yx9?I}66Bhu~O0Vg&Dx1uSz%)&%>9-4mgYeZyE{IBt*n3VsBN%5DE|sy*%y
zs59VLKc=z$$9+Rb__iuu(-)I_<pFN+KPgH~ySd?PLqH#wHQ+yugWR{zZ-TKT`w?~Y
I_CMJF4X7R_od5s;

literal 0
HcmV?d00001

diff --git a/linux-user/aarch64/vdso.S b/linux-user/aarch64/vdso.S
new file mode 100644
index 0000000000..34d3a9ebd2
--- /dev/null
+++ b/linux-user/aarch64/vdso.S
@@ -0,0 +1,71 @@
+/*
+ * aarch64 linux replacement vdso.
+ *
+ * Copyright 2023 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <asm/unistd.h>
+
+/* ??? These are in include/elf.h, which is not ready for inclusion in asm. */
+#define NT_GNU_PROPERTY_TYPE_0  5
+#define GNU_PROPERTY_AARCH64_FEATURE_1_AND      0xc0000000
+#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI      (1U << 0)
+#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC      (1U << 1)
+
+#define GNU_PROPERTY_AARCH64_FEATURE_1_DEFAULT \
+    (GNU_PROPERTY_AARCH64_FEATURE_1_BTI | GNU_PROPERTY_AARCH64_FEATURE_1_PAC)
+
+	.section .note.gnu.property
+	.align	3
+	.long	2f - 1f
+	.long	6f - 3f
+	.long	NT_GNU_PROPERTY_TYPE_0
+1:	.string	"GNU"
+2:	.align	3
+3:	.long	GNU_PROPERTY_AARCH64_FEATURE_1_AND
+	.long	5f - 4f
+4:	.long	GNU_PROPERTY_AARCH64_FEATURE_1_DEFAULT
+5:	.align	3
+6:
+
+	.text
+
+.macro endf name
+	.globl	\name
+	.type	\name, @function
+	.size	\name, . - \name
+.endm
+
+.macro vdso_syscall name, nr
+\name:
+	bti	c
+	mov	x8, #\nr
+	svc	#0
+	ret
+endf	\name
+.endm
+
+	.cfi_startproc
+
+vdso_syscall __kernel_gettimeofday, __NR_gettimeofday
+vdso_syscall __kernel_clock_gettime, __NR_clock_gettime
+vdso_syscall __kernel_clock_getres, __NR_clock_getres
+
+	.cfi_endproc
+
+
+/*
+ * TODO: The kernel makes a big deal of turning off the .cfi directives,
+ * because they cause libgcc to crash, but that's because they're wrong.
+ *
+ * For now, elide the unwind info for __kernel_rt_sigreturn and rely on
+ * the libgcc fallback routine as we have always done.  This requires
+ * that the code sequence used be exact.
+ */
+__kernel_rt_sigreturn:
+	/* No BTI C insn here -- we arrive via RET. */
+	mov	x8, #__NR_rt_sigreturn
+	svc	#0
+endf	__kernel_rt_sigreturn
diff --git a/linux-user/aarch64/vdso.ld b/linux-user/aarch64/vdso.ld
new file mode 100644
index 0000000000..4c12f33352
--- /dev/null
+++ b/linux-user/aarch64/vdso.ld
@@ -0,0 +1,72 @@
+/*
+ * Linker script for linux aarch64 replacement vdso.
+ *
+ * Copyright 2021 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+VERSION {
+        LINUX_2.6.39 {
+        global:
+                __kernel_rt_sigreturn;
+                __kernel_gettimeofday;
+                __kernel_clock_gettime;
+                __kernel_clock_getres;
+
+        local: *;
+        };
+}
+
+
+PHDRS {
+        phdr            PT_PHDR         FLAGS(4) PHDRS;
+        load            PT_LOAD         FLAGS(7) FILEHDR PHDRS;
+        dynamic         PT_DYNAMIC      FLAGS(4);
+        eh_frame_hdr    PT_GNU_EH_FRAME;
+        note            PT_NOTE         FLAGS(4);
+}
+
+SECTIONS {
+        /*
+         * We can't prelink to any address without knowing something about
+         * the virtual memory space of the host, since that leaks over into
+         * the available memory space of the guest.
+         */
+        . = SIZEOF_HEADERS;
+
+        /*
+         * The following, including the FILEHDRS and PHDRS, are modified
+         * when we relocate the binary.  We want them to be initially
+         * writable for the relocation; we'll force them read-only after.
+         */
+        .note           : { *(.note*) }         :load :note
+        .dynamic        : { *(.dynamic) }       :load :dynamic
+        .dynsym         : { *(.dynsym) }        :load
+        /*
+         * There ought not be any real read-write data.
+         * But since we manipulated the segment layout,
+         * we have to put these sections somewhere.
+         */
+        .data           : {
+                *(.data*)
+                *(.sdata*)
+                *(.got.plt) *(.got)
+                *(.gnu.linkonce.d.*)
+                *(.bss*)
+                *(.dynbss*)
+                *(.gnu.linkonce.b.*)
+        }
+
+        .rodata         : { *(.rodata*) }
+        .hash           : { *(.hash) }
+        .gnu.hash       : { *(.gnu.hash) }
+        .dynstr         : { *(.dynstr) }
+        .gnu.version    : { *(.gnu.version) }
+        .gnu.version_d  : { *(.gnu.version_d) }
+        .gnu.version_r  : { *(.gnu.version_r) }
+        .eh_frame_hdr   : { *(.eh_frame_hdr) }  :load :eh_frame_hdr
+        .eh_frame       : { *(.eh_frame) }      :load
+
+        .text           : { *(.text*) }         :load   =0xd503201f
+}
diff --git a/linux-user/meson.build b/linux-user/meson.build
index e4cb70ed2d..dd24389052 100644
--- a/linux-user/meson.build
+++ b/linux-user/meson.build
@@ -35,6 +35,7 @@ gen_vdso_exe = executable('gen-vdso', 'gen-vdso.c',
 gen_vdso = generator(gen_vdso_exe, output: '@BASENAME@.c.inc',
                      arguments: ['-o', '@OUTPUT@', '@EXTRA_ARGS@', '@INPUT@'])
 
+subdir('aarch64')
 subdir('alpha')
 subdir('arm')
 subdir('hppa')
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH v6 12/19] linux-user/arm: Add vdso
  2023-09-30  2:15 [PATCH v6 00/19] linux-user: Implement VDSOs Richard Henderson
                   ` (10 preceding siblings ...)
  2023-09-30  2:15 ` [PATCH v6 11/19] linux-user/aarch64: " Richard Henderson
@ 2023-09-30  2:15 ` Richard Henderson
  2023-09-30  2:15 ` [PATCH v6 13/19] linux-user/hppa: " Richard Henderson
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Richard Henderson @ 2023-09-30  2:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.bennee, laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/arm/vdso-asmoffset.h |   3 +
 linux-user/arm/signal.c         |  55 ++++++----
 linux-user/elfload.c            |   3 +-
 linux-user/arm/Makefile.vdso    |  17 ++++
 linux-user/arm/meson.build      |  12 +++
 linux-user/arm/vdso-be.so       | Bin 0 -> 2648 bytes
 linux-user/arm/vdso-le.so       | Bin 0 -> 2648 bytes
 linux-user/arm/vdso.S           | 174 ++++++++++++++++++++++++++++++++
 linux-user/arm/vdso.ld          |  67 ++++++++++++
 9 files changed, 310 insertions(+), 21 deletions(-)
 create mode 100644 linux-user/arm/vdso-asmoffset.h
 create mode 100644 linux-user/arm/Makefile.vdso
 create mode 100755 linux-user/arm/vdso-be.so
 create mode 100755 linux-user/arm/vdso-le.so
 create mode 100644 linux-user/arm/vdso.S
 create mode 100644 linux-user/arm/vdso.ld

diff --git a/linux-user/arm/vdso-asmoffset.h b/linux-user/arm/vdso-asmoffset.h
new file mode 100644
index 0000000000..252a95c46e
--- /dev/null
+++ b/linux-user/arm/vdso-asmoffset.h
@@ -0,0 +1,3 @@
+/* offsetof(struct sigframe, retcode[3]) */
+#define SIGFRAME_RC3_OFFSET     756
+#define RT_SIGFRAME_RC3_OFFSET  884
diff --git a/linux-user/arm/signal.c b/linux-user/arm/signal.c
index cf99fd7b8a..e19b514f17 100644
--- a/linux-user/arm/signal.c
+++ b/linux-user/arm/signal.c
@@ -21,6 +21,7 @@
 #include "user-internals.h"
 #include "signal-common.h"
 #include "linux-user/trace.h"
+#include "vdso-asmoffset.h"
 
 struct target_sigcontext {
     abi_ulong trap_no;
@@ -102,6 +103,11 @@ struct rt_sigframe
     struct sigframe sig;
 };
 
+QEMU_BUILD_BUG_ON(offsetof(struct sigframe, retcode[3])
+                  != SIGFRAME_RC3_OFFSET);
+QEMU_BUILD_BUG_ON(offsetof(struct rt_sigframe, sig.retcode[3])
+                  != RT_SIGFRAME_RC3_OFFSET);
+
 static abi_ptr sigreturn_fdpic_tramp;
 
 /*
@@ -160,6 +166,9 @@ get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
     return (sp - framesize) & ~7;
 }
 
+static void write_arm_sigreturn(uint32_t *rc, int syscall);
+static void write_arm_fdpic_sigreturn(uint32_t *rc, int ofs);
+
 static int
 setup_return(CPUARMState *env, struct target_sigaction *ka, int usig,
              struct sigframe *frame, abi_ulong sp_addr)
@@ -167,9 +176,9 @@ setup_return(CPUARMState *env, struct target_sigaction *ka, int usig,
     abi_ulong handler = 0;
     abi_ulong handler_fdpic_GOT = 0;
     abi_ulong retcode;
-    int thumb, retcode_idx;
-    int is_fdpic = info_is_fdpic(((TaskState *)thread_cpu->opaque)->info);
-    bool copy_retcode;
+    bool is_fdpic = info_is_fdpic(((TaskState *)thread_cpu->opaque)->info);
+    bool is_rt = ka->sa_flags & TARGET_SA_SIGINFO;
+    bool thumb;
 
     if (is_fdpic) {
         /* In FDPIC mode, ka->_sa_handler points to a function
@@ -184,9 +193,7 @@ setup_return(CPUARMState *env, struct target_sigaction *ka, int usig,
     } else {
         handler = ka->_sa_handler;
     }
-
     thumb = handler & 1;
-    retcode_idx = thumb + (ka->sa_flags & TARGET_SA_SIGINFO ? 2 : 0);
 
     uint32_t cpsr = cpsr_read(env);
 
@@ -202,24 +209,32 @@ setup_return(CPUARMState *env, struct target_sigaction *ka, int usig,
         cpsr &= ~CPSR_E;
     }
 
-    if (ka->sa_flags & TARGET_SA_RESTORER) {
-        if (is_fdpic) {
-            __put_user((abi_ulong)ka->sa_restorer, &frame->retcode[3]);
-            retcode = (sigreturn_fdpic_tramp +
-                       retcode_idx * RETCODE_BYTES + thumb);
-            copy_retcode = true;
-        } else {
-            retcode = ka->sa_restorer;
-            copy_retcode = false;
-        }
+    /* Our vdso default_sigreturn label is a table of entry points. */
+    retcode = default_sigreturn + (is_fdpic * 2 + is_rt) * 8;
+
+    /*
+     * Put the sigreturn code on the stack no matter which return
+     * mechanism we use in order to remain ABI compliant.
+     * Because this is about ABI, always use the A32 instructions,
+     * despite the fact that our actual vdso trampoline is T16.
+     */
+    if (is_fdpic) {
+        write_arm_fdpic_sigreturn(frame->retcode,
+                                  is_rt ? RT_SIGFRAME_RC3_OFFSET
+                                        : SIGFRAME_RC3_OFFSET);
     } else {
-        retcode = default_sigreturn + retcode_idx * RETCODE_BYTES + thumb;
-        copy_retcode = true;
+        write_arm_sigreturn(frame->retcode,
+                            is_rt ? TARGET_NR_rt_sigreturn
+                                  : TARGET_NR_sigreturn);
     }
 
-    /* Copy the code to the stack slot for ABI compatibility. */
-    if (copy_retcode) {
-        memcpy(frame->retcode, g2h_untagged(retcode & ~1), RETCODE_BYTES);
+    if (ka->sa_flags & TARGET_SA_RESTORER) {
+        if (is_fdpic) {
+            /* Place the function descriptor in slot 3. */
+            __put_user((abi_ulong)ka->sa_restorer, &frame->retcode[3]);
+        } else {
+            retcode = ka->sa_restorer;
+        }
     }
 
     env->regs[0] = usig;
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 693ebc94bd..a65401f8d5 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -944,13 +944,14 @@ const char *elf_hwcap2_str(uint32_t bit)
 
 #undef GET_FEATURE_ID
 
+#endif /* not TARGET_AARCH64 */
+
 #if TARGET_BIG_ENDIAN
 # define VDSO_HEADER  "vdso-be.c.inc"
 #else
 # define VDSO_HEADER  "vdso-le.c.inc"
 #endif
 
-#endif /* not TARGET_AARCH64 */
 #endif /* TARGET_ARM */
 
 #ifdef TARGET_SPARC
diff --git a/linux-user/arm/Makefile.vdso b/linux-user/arm/Makefile.vdso
new file mode 100644
index 0000000000..2d098a5748
--- /dev/null
+++ b/linux-user/arm/Makefile.vdso
@@ -0,0 +1,17 @@
+include $(BUILD_DIR)/tests/tcg/arm-linux-user/config-target.mak
+
+SUBDIR = $(SRC_PATH)/linux-user/arm
+VPATH += $(SUBDIR)
+
+all: $(SUBDIR)/vdso-be.so $(SUBDIR)/vdso-le.so
+
+# Adding -use-blx disables unneeded interworking without actually using blx.
+LDFLAGS = -nostdlib -shared -Wl,-use-blx \
+	  -Wl,-h,linux-vdso.so.1 -Wl,--build-id=sha1 \
+	  -Wl,--hash-style=both -Wl,-T,$(SUBDIR)/vdso.ld
+
+$(SUBDIR)/vdso-be.so: vdso.S vdso.ld vdso-asmoffset.h
+	$(CC) -o $@ $(LDFLAGS) -mbig-endian $<
+
+$(SUBDIR)/vdso-le.so: vdso.S vdso.ld vdso-asmoffset.h
+	$(CC) -o $@ $(LDFLAGS) -mlittle-endian $<
diff --git a/linux-user/arm/meson.build b/linux-user/arm/meson.build
index 5a93c925cf..c4bb9af5b8 100644
--- a/linux-user/arm/meson.build
+++ b/linux-user/arm/meson.build
@@ -5,3 +5,15 @@ syscall_nr_generators += {
                    arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ],
                    output: '@BASENAME@_nr.h')
 }
+
+# TARGET_BIG_ENDIAN is defined to 'n' for little-endian; which means it
+# is always true as far as source_set.apply() is concerned.  Always build
+# both header files and include the right one via #if.
+
+vdso_be_inc = gen_vdso.process('vdso-be.so',
+                               extra_args: ['-s', 'sigreturn_codes'])
+
+vdso_le_inc = gen_vdso.process('vdso-le.so',
+                               extra_args: ['-s', 'sigreturn_codes'])
+
+linux_user_ss.add(when: 'TARGET_ARM', if_true: [vdso_be_inc, vdso_le_inc])
diff --git a/linux-user/arm/vdso-be.so b/linux-user/arm/vdso-be.so
new file mode 100755
index 0000000000000000000000000000000000000000..69cafbb956e283e2975bac59a10491c0cbafca57
GIT binary patch
literal 2648
zcmbtVO>A355T57%q>ketR9ezQ5D`VCwMu1`A`rrf?W8D4OPYuR5-*PZ5?ds8WWR(2
z@#8{h3oY#>2P%XJf@`Y?wNft?xqwg)z@Y~Y{2jstAq3+00GRLFx0^a47sMproBd{H
zci-Ec8NZkr$XY&2*2OP(V{8mbk?=~e?h{E$mjvPKkU0Dy0KRoBV@w1z%zRKvVA+F&
z^~zXK{%ArSV?xa@xZfTX@xgB(Y4`}`*ZKyuK{v)kv;S6bf8WrkT>1HI=J#C}-v0DM
z`Ko86^ZqyN_qyPV0iyusSZkHW-@jr%ep?Va4UKQK=Am1G3a|}`R~n5!;a`RR3)~0&
zBh+P#|F5L*D%>Y>i%1lDAGibEs`+;CC!09VIPho_XRMMAY5ar%&)0|_1Kt@mh37=U
zx2hZAeHdX3?~e!ucLq!h=LA<euS;?N`Qf&!pY@h|-`#oFM|;kQZO;{I6+1sw$v<sR
zI<8xqcD6JgO#aJUb!x_@XI3T(xdoXjm1pPoaoq&|@0EeWL!-y-1Brup3mo|RpN03t
zU)v8KyaPM$d>6obHD6}=FU|f2Mju6;lhx^e0ON;&FanQ51J*e74D=NAY3MoVW#|{6
zanIHg5CLf03mfxAtY?SC_gu{CjJA<-pB(_tzg1GP$SL1Bo+a)3f$z4k_rvzZ7WOgN
zJ^><4>m<Rs=P_*B&P~Va@e}PY#a?b(jJ~q%Wb3Jx(~(!huZ7M8&jw!ipYxsP<`C}x
zAaD}cE`70Yw7m=bV_*@8N<0>P{+D1V6mJPr-x*-qNEh%uz;lUsF(DljGBI$8)UPyl
zNA8oa>(@A1S|7FO(a>)CR<q{s8E}p-YJKg^==BTPc;A;=r?BR2IVU$>!Yzxm1(PEZ
z^0nw!=Z+iX1{o6A_<0B9K5Cff`2=T<L#)sF1kv?it!d7jhp2u)zd8i)G_Bys8H!i;
z;K&KZSNQ~Qp@!e=&mIEt^Ze;&FM$M(@(CWLHUiE>GT(rgQ}v7(FCIR|w_~Q7kFj14
zBZ!Vi+wgjT<<0Me=LBqBI1J9e$GjiLe7}dxdFc2N*p%pg@)YJb_opg2YsvH{<kg1$
z^cMKd{*=!@G1Iq@Ehj3{?Min+?DXS9slmg&QY%eX9e1``w)2&O>IP`qcBbFX4yOh)
zc7J+U?7o2`J*ffvNH%*cGh&aVdImCfQ%ledXhQ?p+?1Lc&4xy`MNd-wOA@t(X*V|x
z?N&WqG^29GbtF+(DCee2c{M;Rbk5C5VzNA&DCTNK&+b+|%bZiKl`7>8#4bp}DcTd&
z+_YmC3y3sK60S4vN+LBpn8>+qwKP8K;%NSp;J#I!GWS^*L^ohW=e*nj1M?ecr}Bk4
zTL*NGBb~hb-UH1%!+NYERZC;wjAO1cj{Wd}=2(yQrE07>zZplc7FcIoZ_R`31?PKE
zOxz*-#<G7Sj`gT&G6}vpu1DJ#m-e83w_#Rd>gf@z*MNm_mp!O@FzdlipFC!M<3U$F
z$RXJIz4Y__C=&qJ=6X0gRrA<?T}+${i;iO-Ags;j!b$wCVI1y+^{#5()H(e;W6I*p
z%`*TEEaR~QFv2w`dQXoa?kY?xVCWzC9e@Ggn(SHT3@{88@pvCFV%F<`p(!qWJNS|b
If>v?=0AXBj6aWAK

literal 0
HcmV?d00001

diff --git a/linux-user/arm/vdso-le.so b/linux-user/arm/vdso-le.so
new file mode 100755
index 0000000000000000000000000000000000000000..ad05a1251875ac0c76685e1f9190a7307a8444d1
GIT binary patch
literal 2648
zcmbtWU1%It6h5<)-6ZYqW>ciL#)n9wmD&!qgeWwKo1aZ8NgB5ajR>7=b|=}zWT)&-
zVj@~ojcv8s`j8h9Aw_&tf++N*n7)V<5g#h}py-1lh)4@s`cPfJ@6OyfN%J6hHs74{
zoqO(`JNMpmZeH#k$QXtpT1<IZG;4=*wH}X%MBAlRqG)TDl*Hg-o5l)kqAq~$52|DZ
z4Frc0j2^-Bb_k2G3EhAAXRmM@K^i@1BXm3U^$^-%6XEuIz)hfUXjI-lT>i52o2xxn
z_w4-TgA;d}AB-ETNwkdyeSX4(|NOh=rtr=vd_B<o#(DU+LA$_qAO+m1)!a3-{{;;t
zH=sYE@joSv{w_YC0eXkT<p8t;&i9k=gnl-}xyDb2xC5@GS#H+2zFN2r{2powx+&qe
za-8t=8ABhz_GsPiC~fv3muoGn*^38@-Cti$?0&zye16~O4~cEh6{@bCpLX-l*;9_^
zm1dkRogM9Wxhqap`+}bCWFfa8)1~t4`~i+@;qOryI5IRkW*@RTIEl#m&%jLiyY$)b
z3GVs*0QZ&Rf14q<W<N67M$zkJw3vsV1m~F?L*N+n1oTPhY3Os%bI>c$r=V{@FGDxb
z2kZxU9w^2OS&6)uG+N>b;d^!gTz~GJq>~M2BNq(%4+6geoBjRpeYb^w9KNpro(Vlp
zJ8cNwc?>UY;!DRDQ>U9=Nxqs`iodq~%(k<Q=NewGe<OB2`exl*=7q>bOjXUR6Z#Cm
zvm|}VAL(xez5tehI3THH^rb(du~@3Ho_bGROvU_$rfERUMa9H|n3#%TSIXk2wY?3G
z$q$QHXf3Z>je#|^mu+hq{d*pq_J@JK@^1XvJDF79_km8|i$QZvZlWYc0%o**L}HOf
zPW>*q9(YW(^Zp*tWd<jl`RsE)6TV&Nenzkk`0eVX3+sW;nLU18@VQ^fbl#i(s>s@U
ze4~nI{qp10j!S2dfTpS@BEvx<n*PfB!FZaI2)@8~)ghm`H#(j>)kLlnIvCH7X0G0>
z?Euj=zyNOnKaKabLPya55w-{O<B5C%T(1Y?N5HkPo}2&)*QW}2xIXb*h3nIM;Nkit
z`Mh_$BQrW|xzgrITS4reXNJ;)N4lk2nyNV7Y^7}H-GZtHDB5;!zn#gZ2Yc=Qo~+n?
z14p~k1NPBO=2-8DJ(BJk=(R&7At*o_3drW76e=_u3e^@hN!2g0stYq-ZUWk?_`0aA
zvg<iw6&A|5nNnUEh=tC1IkBe7vsN)zE&6`1;(O+tO10#cHxRoZmQ%DRE4dlRE*21}
znOL4P?}?Sp4q7?StCS{YJuJ<C7w)%zb^m);wuQO}M^7GrPu~qZFT^6?pK!nKGw1gK
zyaRb;m`B7oY{tP<_XF$Up@8#f@;ni$u7FecUV^oVS;q00cf@|!`bg`z$Kksb+_lU{
zf;Dh+Tvy=Zc)Y&}-rHI*yppHztOesSe+kY{j|ZyebR1gW@oR7roQqyl&W|z)aBTJq
z|GxsNM8|nxI*xUKi0etAO~;)I;<zWwcLms5^qsQ=2ZlJQ{VRywr3thiTE9~_T}Iq0
noU9+b2SC+5#)_ra0Hzc%fsbhfqQ`3n569hy1zFZX&^qoPLfUOq

literal 0
HcmV?d00001

diff --git a/linux-user/arm/vdso.S b/linux-user/arm/vdso.S
new file mode 100644
index 0000000000..b3bb6491dc
--- /dev/null
+++ b/linux-user/arm/vdso.S
@@ -0,0 +1,174 @@
+/*
+ * arm linux replacement vdso.
+ *
+ * Copyright 2023 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <asm/unistd.h>
+#include "vdso-asmoffset.h"
+
+/*
+ * All supported cpus have T16 instructions: at least arm4t.
+ *
+ * We support user-user with m-profile cpus as an extension, because it
+ * is useful for testing gcc, which requires we avoid A32 instructions.
+ */
+	.thumb
+	.arch	armv4t
+	.eabi_attribute Tag_FP_arch, 0
+	.eabi_attribute Tag_ARM_ISA_use, 0
+
+	.text
+
+.macro	raw_syscall n
+	.ifne \n < 0x100
+	mov	r7, #\n
+	.elseif \n < 0x1ff
+	mov	r7, #0xff
+	add	r7, #(\n - 0xff)
+	.else
+	.err
+	.endif
+	swi	#0
+.endm
+
+.macro	fdpic_thunk ofs
+	ldr	r3, [sp, #\ofs]
+	ldmia	r2, {r2, r3}
+	mov	r9, r3
+	bx	r2
+.endm
+
+.macro	endf name
+	.globl	\name
+	.type	\name, %function
+	.size	\name, . - \name
+.endm
+
+/*
+ * We must save/restore r7 for the EABI syscall number.
+ * While we're doing that, we might as well save LR to get a free return,
+ * and a branch that is interworking back to ARMv5.
+ */
+
+.macro SYSCALL name, nr
+\name:
+	.cfi_startproc
+	push	{r7, lr}
+	.cfi_adjust_cfa_offset 8
+	.cfi_offset r7, -8
+	.cfi_offset lr, -4
+	raw_syscall \nr
+	pop	{r7, pc}
+	.cfi_endproc
+endf \name
+.endm
+
+SYSCALL	__vdso_clock_gettime, __NR_clock_gettime
+SYSCALL __vdso_clock_gettime64, __NR_clock_gettime64
+SYSCALL __vdso_clock_getres, __NR_clock_getres
+SYSCALL __vdso_gettimeofday, __NR_gettimeofday
+
+
+/*
+ * We, like the real kernel, use a table of sigreturn trampolines.
+ * Unlike the real kernel, we do not attempt to pack this into as
+ * few bytes as possible -- simply use 8 bytes per slot.
+ *
+ * Within each slot, use the exact same code sequence as the kernel,
+ * lest we trip up someone doing code inspection.
+ */
+
+.macro	slot n
+	.balign	8
+	.org	sigreturn_codes + 8 * \n
+.endm
+
+.macro cfi_fdpic_r9 ofs
+	/*
+	 * fd = *(r13 + ofs)
+         * r9 = *(fd + 4)
+	 *
+	 * DW_CFA_expression r9, length (7),
+	 *   DW_OP_breg13, ofs, DW_OP_deref,
+	 *   DW_OP_plus_uconst, 4, DW_OP_deref
+         */
+	.cfi_escape 0x10, 9, 7, 0x7d, (\ofs & 0x7f) + 0x80, (\ofs >> 7), 0x06, 0x23, 4, 0x06
+.endm
+
+.macro cfi_fdpic_pc ofs
+	/*
+	 * fd = *(r13 + ofs)
+         * pc = *fd
+	 *
+	 * DW_CFA_expression lr (14), length (5),
+	 *   DW_OP_breg13, ofs, DW_OP_deref, DW_OP_deref
+         */
+	.cfi_escape 0x10, 14, 5, 0x7d, (\ofs & 0x7f) + 0x80, (\ofs >> 7), 0x06, 0x06
+.endm
+
+/*
+ * Start the unwind info at least one instruction before the signal
+ * trampoline, because the unwinder will assume we are returning
+ * after a call site.
+ */
+	.cfi_startproc simple
+	.cfi_signal_frame
+	.cfi_return_column 15
+
+	.cfi_def_cfa	sp, 32 + 64
+	.cfi_offset	r0, -16 * 4
+	.cfi_offset	r1, -15 * 4
+	.cfi_offset	r2, -14 * 4
+	.cfi_offset	r3, -13 * 4
+	.cfi_offset	r4, -12 * 4
+	.cfi_offset	r5, -11 * 4
+	.cfi_offset	r6, -10 * 4
+	.cfi_offset	r7, -9 * 4
+	.cfi_offset	r8, -8 * 4
+	.cfi_offset	r9, -7 * 4
+	.cfi_offset	r10, -6 * 4
+	.cfi_offset	r11, -5 * 4
+	.cfi_offset	r12, -4 * 4
+	.cfi_offset	r13, -3 * 4
+	.cfi_offset	r14, -2 * 4
+	.cfi_offset	r15, -1 * 4
+
+	nop
+
+	.balign	16
+sigreturn_codes:
+	/* [EO]ABI sigreturn */
+	slot	0
+	raw_syscall __NR_sigreturn
+
+	.cfi_def_cfa_offset 160 + 64
+
+	/* [EO]ABI rt_sigreturn */
+	slot	1
+	raw_syscall __NR_rt_sigreturn
+
+	.cfi_endproc
+
+	/* FDPIC sigreturn */
+	.cfi_startproc
+	cfi_fdpic_pc SIGFRAME_RC3_OFFSET
+	cfi_fdpic_r9 SIGFRAME_RC3_OFFSET
+
+	slot	2
+	fdpic_thunk SIGFRAME_RC3_OFFSET
+	.cfi_endproc
+
+	/* FDPIC rt_sigreturn */
+	.cfi_startproc
+	cfi_fdpic_pc RT_SIGFRAME_RC3_OFFSET
+	cfi_fdpic_r9 RT_SIGFRAME_RC3_OFFSET
+
+	slot	3
+	fdpic_thunk RT_SIGFRAME_RC3_OFFSET
+	.cfi_endproc
+
+	.balign	16
+endf sigreturn_codes
diff --git a/linux-user/arm/vdso.ld b/linux-user/arm/vdso.ld
new file mode 100644
index 0000000000..3b00adf27a
--- /dev/null
+++ b/linux-user/arm/vdso.ld
@@ -0,0 +1,67 @@
+/*
+ * Linker script for linux arm replacement vdso.
+ *
+ * Copyright 2023 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+VERSION {
+        LINUX_2.6 {
+        global:
+                __vdso_clock_gettime;
+                __vdso_gettimeofday;
+                __vdso_clock_getres;
+                __vdso_clock_gettime64;
+
+        local: *;
+        };
+}
+
+
+PHDRS {
+        phdr            PT_PHDR         FLAGS(4) PHDRS;
+        load            PT_LOAD         FLAGS(7) FILEHDR PHDRS; /* FLAGS=RWX */
+        dynamic         PT_DYNAMIC      FLAGS(4);
+        eh_frame_hdr    PT_GNU_EH_FRAME;
+        note            PT_NOTE         FLAGS(4);
+}
+
+SECTIONS {
+        . = SIZEOF_HEADERS;
+
+        /*
+         * The following, including the FILEHDRS and PHDRS, are modified
+         * when we relocate the binary.  We want them to be initially
+         * writable for the relocation; we'll force them read-only after.
+         */
+        .note           : { *(.note*) }         :load :note
+        .dynamic        : { *(.dynamic) }       :load :dynamic
+        .dynsym         : { *(.dynsym) }        :load
+        /*
+         * There ought not be any real read-write data.
+         * But since we manipulated the segment layout,
+         * we have to put these sections somewhere.
+         */
+        .data           : {
+                *(.data*)
+                *(.sdata*)
+                *(.got.plt) *(.got)
+                *(.gnu.linkonce.d.*)
+                *(.bss*)
+                *(.dynbss*)
+                *(.gnu.linkonce.b.*)
+        }
+
+        .rodata         : { *(.rodata*) }
+        .hash           : { *(.hash) }
+        .gnu.hash       : { *(.gnu.hash) }
+        .dynstr         : { *(.dynstr) }
+        .gnu.version    : { *(.gnu.version) }
+        .gnu.version_d  : { *(.gnu.version_d) }
+        .gnu.version_r  : { *(.gnu.version_r) }
+        .eh_frame_hdr   : { *(.eh_frame_hdr) }  :load :eh_frame_hdr
+        .eh_frame       : { *(.eh_frame) }      :load
+
+        .text           : { *(.text*) }         :load
+}
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH v6 13/19] linux-user/hppa: Add vdso
  2023-09-30  2:15 [PATCH v6 00/19] linux-user: Implement VDSOs Richard Henderson
                   ` (11 preceding siblings ...)
  2023-09-30  2:15 ` [PATCH v6 12/19] linux-user/arm: " Richard Henderson
@ 2023-09-30  2:15 ` Richard Henderson
  2023-10-05 16:16   ` Philippe Mathieu-Daudé
  2023-09-30  2:15 ` [PATCH v6 14/19] linux-user/riscv: " Richard Henderson
                   ` (5 subsequent siblings)
  18 siblings, 1 reply; 37+ messages in thread
From: Richard Henderson @ 2023-09-30  2:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.bennee, laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/hppa/vdso-asmoffset.h |  12 +++
 linux-user/elfload.c             |   2 +
 linux-user/hppa/signal.c         |  24 +++--
 linux-user/hppa/Makefile.vdso    |  11 +++
 linux-user/hppa/meson.build      |   5 +
 linux-user/hppa/vdso.S           | 165 +++++++++++++++++++++++++++++++
 linux-user/hppa/vdso.ld          |  77 +++++++++++++++
 linux-user/hppa/vdso.so          | Bin 0 -> 2104 bytes
 8 files changed, 286 insertions(+), 10 deletions(-)
 create mode 100644 linux-user/hppa/vdso-asmoffset.h
 create mode 100644 linux-user/hppa/Makefile.vdso
 create mode 100644 linux-user/hppa/vdso.S
 create mode 100644 linux-user/hppa/vdso.ld
 create mode 100755 linux-user/hppa/vdso.so

diff --git a/linux-user/hppa/vdso-asmoffset.h b/linux-user/hppa/vdso-asmoffset.h
new file mode 100644
index 0000000000..c8b40c0332
--- /dev/null
+++ b/linux-user/hppa/vdso-asmoffset.h
@@ -0,0 +1,12 @@
+#define sizeof_rt_sigframe              584
+#define offsetof_sigcontext             160
+#define offsetof_sigcontext_gr          0x4
+#define offsetof_sigcontext_fr          0x88
+#define offsetof_sigcontext_iaoq        0x190
+#define offsetof_sigcontext_sar         0x198
+
+/* arch/parisc/include/asm/rt_sigframe.h */
+#define SIGFRAME                        64
+#define FUNCTIONCALLFRAME               48
+#define PARISC_RT_SIGFRAME_SIZE32 \
+    (((sizeof_rt_sigframe) + FUNCTIONCALLFRAME + SIGFRAME) & -SIGFRAME)
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index a65401f8d5..ccf8a1dc78 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1921,6 +1921,8 @@ static inline void init_thread(struct target_pt_regs *regs,
 #define STACK_GROWS_DOWN 0
 #define STACK_ALIGNMENT  64
 
+#define VDSO_HEADER "vdso.c.inc"
+
 static inline void init_thread(struct target_pt_regs *regs,
                                struct image_info *infop)
 {
diff --git a/linux-user/hppa/signal.c b/linux-user/hppa/signal.c
index bda6e54655..741dac79b6 100644
--- a/linux-user/hppa/signal.c
+++ b/linux-user/hppa/signal.c
@@ -21,6 +21,7 @@
 #include "user-internals.h"
 #include "signal-common.h"
 #include "linux-user/trace.h"
+#include "vdso-asmoffset.h"
 
 struct target_sigcontext {
     abi_ulong sc_flags;
@@ -47,6 +48,19 @@ struct target_rt_sigframe {
     /* hidden location of upper halves of pa2.0 64-bit gregs */
 };
 
+QEMU_BUILD_BUG_ON(sizeof(struct target_rt_sigframe) != sizeof_rt_sigframe);
+QEMU_BUILD_BUG_ON(offsetof(struct target_rt_sigframe, uc.tuc_mcontext)
+                  != offsetof_sigcontext);
+QEMU_BUILD_BUG_ON(offsetof(struct target_sigcontext, sc_gr)
+                  != offsetof_sigcontext_gr);
+QEMU_BUILD_BUG_ON(offsetof(struct target_sigcontext, sc_fr)
+                  != offsetof_sigcontext_fr);
+QEMU_BUILD_BUG_ON(offsetof(struct target_sigcontext, sc_iaoq)
+                  != offsetof_sigcontext_iaoq);
+QEMU_BUILD_BUG_ON(offsetof(struct target_sigcontext, sc_sar)
+                  != offsetof_sigcontext_sar);
+
+
 static void setup_sigcontext(struct target_sigcontext *sc, CPUArchState *env)
 {
     int i;
@@ -91,16 +105,6 @@ static void restore_sigcontext(CPUArchState *env, struct target_sigcontext *sc)
     __get_user(env->cr[CR_SAR], &sc->sc_sar);
 }
 
-#if TARGET_ABI_BITS == 32
-#define SIGFRAME                64
-#define FUNCTIONCALLFRAME       48
-#else
-#define SIGFRAME                128
-#define FUNCTIONCALLFRAME       96
-#endif
-#define PARISC_RT_SIGFRAME_SIZE32 \
-    ((sizeof(struct target_rt_sigframe) + FUNCTIONCALLFRAME + SIGFRAME) & -SIGFRAME)
-
 void setup_rt_frame(int sig, struct target_sigaction *ka,
                     target_siginfo_t *info,
                     target_sigset_t *set, CPUArchState *env)
diff --git a/linux-user/hppa/Makefile.vdso b/linux-user/hppa/Makefile.vdso
new file mode 100644
index 0000000000..f4537ae716
--- /dev/null
+++ b/linux-user/hppa/Makefile.vdso
@@ -0,0 +1,11 @@
+include $(BUILD_DIR)/tests/tcg/hppa-linux-user/config-target.mak
+
+SUBDIR = $(SRC_PATH)/linux-user/hppa
+VPATH += $(SUBDIR)
+
+all: $(SUBDIR)/vdso.so
+
+$(SUBDIR)/vdso.so: vdso.S vdso.ld vdso-asmoffset.h
+	$(CC) -o $@ -nostdlib -shared -Wl,-h,linux-vdso32.so.1 \
+	  -Wl,--build-id=sha1 -Wl,--hash-style=both \
+	  -Wl,-T,$(SUBDIR)/vdso.ld $<
diff --git a/linux-user/hppa/meson.build b/linux-user/hppa/meson.build
index 4709508a09..aa2d9a87a6 100644
--- a/linux-user/hppa/meson.build
+++ b/linux-user/hppa/meson.build
@@ -3,3 +3,8 @@ syscall_nr_generators += {
                     arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ],
                     output: '@BASENAME@_nr.h')
 }
+
+vdso_inc = gen_vdso.process('vdso.so',
+                            extra_args: [ '-r', '__kernel_sigtramp_rt' ])
+
+linux_user_ss.add(when: 'TARGET_HPPA', if_true: vdso_inc)
diff --git a/linux-user/hppa/vdso.S b/linux-user/hppa/vdso.S
new file mode 100644
index 0000000000..5be14d2f70
--- /dev/null
+++ b/linux-user/hppa/vdso.S
@@ -0,0 +1,165 @@
+/*
+ * hppa linux kernel vdso replacement.
+ *
+ * Copyright 2023 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <asm/unistd.h>
+#include "vdso-asmoffset.h"
+
+	.text
+
+
+/*
+ * arch/parisc/kernel/vdso32/sigtramp.S:
+ * Gdb expects the trampoline is on the stack and the pc is offset from
+ * a 64-byte boundary by 0, 4 or 5 instructions. Since the vdso trampoline
+ * is not on the stack, we need a new variant with different offsets and
+ * data to tell gdb where to find the signal context on the stack.
+ *
+ * Here we put the offset to the context data at the start of the trampoline
+ * region and offset the first trampoline by 2 instructions. Please do
+ * not change the trampoline as the code in gdb depends on the following
+ * instruction sequence exactly.
+ */
+
+/* arch/parisc/kernel/asm-offsets.c */
+#define SIGFRAME_CONTEXT_REGS32 \
+    (offsetof_sigcontext - PARISC_RT_SIGFRAME_SIZE32)
+
+        .align	64
+        .word	SIGFRAME_CONTEXT_REGS32
+
+/*
+ * All that said, we can provide a proper unwind record, which means that
+ * GDB should not actually need the offset magic.
+ *
+ * The return address that arrived here, from the inner frame, is
+ * not marked as a signal frame and so the unwinder still tries to
+ * subtract 1 to examine the presumed call insn.  Thus we must
+ * extend the unwind info to a nop before the start.
+ */
+
+	.cfi_startproc simple
+	.cfi_signal_frame
+
+	/* Compare pa32_fallback_frame_state from libgcc. */
+
+	/*
+	 * Place the CFA at the start of sigcontext for convenience.
+	 * The previous CFA will be restored from the saved stack pointer.
+	 */
+	.cfi_def_cfa	30, -PARISC_RT_SIGFRAME_SIZE32 + offsetof_sigcontext
+
+	/* Record save offset of general registers. */
+	.cfi_offset	1, offsetof_sigcontext_gr + 1 * 4
+	.cfi_offset	2, offsetof_sigcontext_gr + 2 * 4
+	.cfi_offset	3, offsetof_sigcontext_gr + 3 * 4
+	.cfi_offset	4, offsetof_sigcontext_gr + 4 * 4
+	.cfi_offset	5, offsetof_sigcontext_gr + 5 * 4
+	.cfi_offset	6, offsetof_sigcontext_gr + 6 * 4
+	.cfi_offset	7, offsetof_sigcontext_gr + 7 * 4
+	.cfi_offset	8, offsetof_sigcontext_gr + 8 * 4
+	.cfi_offset	9, offsetof_sigcontext_gr + 9 * 4
+	.cfi_offset	10, offsetof_sigcontext_gr + 10 * 4
+	.cfi_offset	11, offsetof_sigcontext_gr + 11 * 4
+	.cfi_offset	12, offsetof_sigcontext_gr + 12 * 4
+	.cfi_offset	13, offsetof_sigcontext_gr + 13 * 4
+	.cfi_offset	14, offsetof_sigcontext_gr + 14 * 4
+	.cfi_offset	15, offsetof_sigcontext_gr + 15 * 4
+	.cfi_offset	16, offsetof_sigcontext_gr + 16 * 4
+	.cfi_offset	17, offsetof_sigcontext_gr + 17 * 4
+	.cfi_offset	18, offsetof_sigcontext_gr + 18 * 4
+	.cfi_offset	19, offsetof_sigcontext_gr + 19 * 4
+	.cfi_offset	20, offsetof_sigcontext_gr + 20 * 4
+	.cfi_offset	21, offsetof_sigcontext_gr + 21 * 4
+	.cfi_offset	22, offsetof_sigcontext_gr + 22 * 4
+	.cfi_offset	23, offsetof_sigcontext_gr + 23 * 4
+	.cfi_offset	24, offsetof_sigcontext_gr + 24 * 4
+	.cfi_offset	25, offsetof_sigcontext_gr + 25 * 4
+	.cfi_offset	26, offsetof_sigcontext_gr + 26 * 4
+	.cfi_offset	27, offsetof_sigcontext_gr + 27 * 4
+	.cfi_offset	28, offsetof_sigcontext_gr + 28 * 4
+	.cfi_offset	29, offsetof_sigcontext_gr + 29 * 4
+	.cfi_offset	30, offsetof_sigcontext_gr + 30 * 4
+	.cfi_offset	31, offsetof_sigcontext_gr + 31 * 4
+
+	/* Record save offset of fp registers, left and right halves. */
+	.cfi_offset	32, offsetof_sigcontext_fr + 4 * 8
+	.cfi_offset	33, offsetof_sigcontext_fr + 4 * 8 + 4
+	.cfi_offset	34, offsetof_sigcontext_fr + 5 * 8
+	.cfi_offset	35, offsetof_sigcontext_fr + 5 * 8 + 4
+	.cfi_offset	36, offsetof_sigcontext_fr + 6 * 8
+	.cfi_offset	37, offsetof_sigcontext_fr + 6 * 8 + 4
+	.cfi_offset	38, offsetof_sigcontext_fr + 7 * 8
+	.cfi_offset	39, offsetof_sigcontext_fr + 7 * 8 + 4
+	.cfi_offset	40, offsetof_sigcontext_fr + 8 * 8
+	.cfi_offset	41, offsetof_sigcontext_fr + 8 * 8 + 4
+	.cfi_offset	42, offsetof_sigcontext_fr + 9 * 8
+	.cfi_offset	43, offsetof_sigcontext_fr + 9 * 8 + 4
+	.cfi_offset	44, offsetof_sigcontext_fr + 10 * 8
+	.cfi_offset	45, offsetof_sigcontext_fr + 10 * 8 + 4
+	.cfi_offset	46, offsetof_sigcontext_fr + 11 * 8
+	.cfi_offset	47, offsetof_sigcontext_fr + 11 * 8 + 4
+	.cfi_offset	48, offsetof_sigcontext_fr + 12 * 8
+	.cfi_offset	49, offsetof_sigcontext_fr + 12 * 8 + 4
+	.cfi_offset	50, offsetof_sigcontext_fr + 13 * 8
+	.cfi_offset	51, offsetof_sigcontext_fr + 13 * 8 + 4
+	.cfi_offset	52, offsetof_sigcontext_fr + 14 * 8
+	.cfi_offset	53, offsetof_sigcontext_fr + 14 * 8 + 4
+	.cfi_offset	54, offsetof_sigcontext_fr + 15 * 8
+	.cfi_offset	55, offsetof_sigcontext_fr + 15 * 8 + 4
+	.cfi_offset	56, offsetof_sigcontext_fr + 16 * 8
+	.cfi_offset	57, offsetof_sigcontext_fr + 16 * 8 + 4
+	.cfi_offset	58, offsetof_sigcontext_fr + 17 * 8
+	.cfi_offset	59, offsetof_sigcontext_fr + 17 * 8 + 4
+	.cfi_offset	60, offsetof_sigcontext_fr + 18 * 8
+	.cfi_offset	61, offsetof_sigcontext_fr + 18 * 8 + 4
+	.cfi_offset	62, offsetof_sigcontext_fr + 19 * 8
+	.cfi_offset	63, offsetof_sigcontext_fr + 19 * 8 + 4
+	.cfi_offset	64, offsetof_sigcontext_fr + 20 * 8
+	.cfi_offset	65, offsetof_sigcontext_fr + 20 * 8 + 4
+	.cfi_offset	66, offsetof_sigcontext_fr + 21 * 8
+	.cfi_offset	67, offsetof_sigcontext_fr + 21 * 8 + 4
+	.cfi_offset	68, offsetof_sigcontext_fr + 22 * 8
+	.cfi_offset	69, offsetof_sigcontext_fr + 22 * 8 + 4
+	.cfi_offset	70, offsetof_sigcontext_fr + 23 * 8
+	.cfi_offset	71, offsetof_sigcontext_fr + 23 * 8 + 4
+	.cfi_offset	72, offsetof_sigcontext_fr + 24 * 8
+	.cfi_offset	73, offsetof_sigcontext_fr + 24 * 8 + 4
+	.cfi_offset	74, offsetof_sigcontext_fr + 25 * 8
+	.cfi_offset	75, offsetof_sigcontext_fr + 25 * 8 + 4
+	.cfi_offset	76, offsetof_sigcontext_fr + 26 * 8
+	.cfi_offset	77, offsetof_sigcontext_fr + 26 * 8 + 4
+	.cfi_offset	78, offsetof_sigcontext_fr + 27 * 8
+	.cfi_offset	79, offsetof_sigcontext_fr + 27 * 8 + 4
+	.cfi_offset	80, offsetof_sigcontext_fr + 28 * 8
+	.cfi_offset	81, offsetof_sigcontext_fr + 28 * 8 + 4
+	.cfi_offset	82, offsetof_sigcontext_fr + 29 * 8
+	.cfi_offset	83, offsetof_sigcontext_fr + 29 * 8 + 4
+	.cfi_offset	84, offsetof_sigcontext_fr + 30 * 8
+	.cfi_offset	85, offsetof_sigcontext_fr + 30 * 8 + 4
+	.cfi_offset	86, offsetof_sigcontext_fr + 31 * 8
+	.cfi_offset	87, offsetof_sigcontext_fr + 31 * 8 + 4
+
+	/* Record save offset of %sar */
+	.cfi_offset	88, offsetof_sigcontext_sar
+
+	/* Record save offset of return address, iaoq[0]. */
+	.cfi_return_column 89
+	.cfi_offset	89, offsetof_sigcontext_iaoq
+
+	nop
+
+__kernel_sigtramp_rt:
+	ldi	0, %r25
+	ldi	__NR_rt_sigreturn, %r20
+	be,l	0x100(%sr2, %r0), %sr0, %r31
+	nop
+
+	.cfi_endproc
+	.size	__kernel_sigtramp_rt, . - __kernel_sigtramp_rt
+	.type	__kernel_sigtramp_rt, @function
+	.globl	__kernel_sigtramp_rt
diff --git a/linux-user/hppa/vdso.ld b/linux-user/hppa/vdso.ld
new file mode 100644
index 0000000000..b17ad974f3
--- /dev/null
+++ b/linux-user/hppa/vdso.ld
@@ -0,0 +1,77 @@
+/*
+ * Linker script for linux hppa vdso.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+VERSION {
+        /*
+         * The kernel's vdso32.lds.S attempts to export
+         *     __kernel_sigtramp_rt32
+         *     __kernel_restart_syscall32
+         * except that those symbols don't exist.  The actual symbols are
+         *     __kernel_sigtramp_rt
+         *     __kernel_restart_syscall
+         * which means that nothing is exported at all.
+         * QEMU handles syscall restart internally, so we don't
+         * need to implement __kernel_restart_syscall at all.
+         */
+        LINUX_5.18 {
+        local: *;
+        };
+}
+
+
+PHDRS {
+        phdr            PT_PHDR         FLAGS(4) PHDRS;
+        load            PT_LOAD         FLAGS(7) FILEHDR PHDRS;
+        dynamic         PT_DYNAMIC      FLAGS(4);
+        note            PT_NOTE         FLAGS(4);
+        eh_frame_hdr    PT_GNU_EH_FRAME;
+}
+
+SECTIONS {
+        . = SIZEOF_HEADERS;
+
+        /* The following, including the FILEHDRS and PHDRS, are modified
+           when we relocate the binary.  We want them to be initially
+           writable for the relocation; we'll force them read-only after.  */
+        .note           : { *(.note*) }         :load :note
+        .dynamic        : { *(.dynamic) }       :load :dynamic
+        .dynsym         : { *(.dynsym) }        :load
+        .data           : {
+                /* There ought not be any real read-write data.
+                   But since we manipulated the segment layout,
+                   we have to put these sections somewhere.  */
+                *(.data*)
+                *(.sdata*)
+                *(.got.plt) *(.got)
+                *(.gnu.linkonce.d.*)
+                *(.bss*)
+                *(.dynbss*)
+                *(.gnu.linkonce.b.*)
+        }
+
+        .rodata         : { *(.rodata) }
+        .hash           : { *(.hash) }
+        .gnu.hash       : { *(.gnu.hash) }
+        .dynstr         : { *(.dynstr) }
+        .gnu.version    : { *(.gnu.version) }
+        .gnu.version_d  : { *(.gnu.version_d) }
+        .gnu.version_r  : { *(.gnu.version_r) }
+        .eh_frame_hdr   : { *(.eh_frame_hdr) }  :load :eh_frame_hdr
+        .eh_frame       : { *(.eh_frame) }      :load
+
+        .text           : { *(.text*) }         :load
+}
diff --git a/linux-user/hppa/vdso.so b/linux-user/hppa/vdso.so
new file mode 100755
index 0000000000000000000000000000000000000000..e1ddd70c37e9eb6871c21d538dcce0a1e736a918
GIT binary patch
literal 2104
zcmbtVTXR!Y6kaFkhEgcBP%l`hafWdil!Lv1RY03GNz;<1rD<u4mqRou?Lbo}Ntxn<
z6hy2j;=SIj_j<pgs8u`u1|EIrgN{DxgO1|}@%#2U8(N>7>6(0JUG~~*U)EYXM<Vg4
z<+J=^$S<oPTAtb<qRxu=Dx^UIqGY2~=<y{O$Jj+oK_*H(nE6mi{#h5YR1g5<1OA$a
z3CM(*PkwG5Hb5ryc)IX&Cqgt{f>dFQ(BmGb?r%x-$mIFC+3xTU<+0?(1N%-~JGte|
zwo#0&1h`Mkv8G3g7ybaBfv&)R1jiYzaqu#r23QVo^SCSe7yscgz|X_x1OE;7zacM{
z)|dd5Qv4k<?}@~{^4{j(t<h=2zNONP7f%I_%E6)R=-B2%>HJ82ot+=CYbD;A=;?E|
z+O@bm6U{<ItNi3nuEjfB2e@mvD_Uj0oF4PWz(nuQs`hV(%=>_s6$j@&=K!(p?Mg~X
zNxxOSx@O|YQQtBD{UyiM14~XUeXw+5*+XR~mp{DXk@8b3A6<32;<3udS3j}l$*QL=
zd;0Qcu9&>?*|pDI^?daU>t0;{Qq9X(zY>_*^y+o5UH|&#H|#gJymiCdwbOO))W6&C
z-q!cGeQ@K4jUV0g@y(xX|8&P^J3qhW%&lKEeHlC(`l|Ws@Hdf}=(jE3#lCM<O>HW;
zONHX9xm|@5D$=2%ovLNGigl^hq-yI{yLwc7k81B#i9XfQuR8at-M6W(+g0)o)qSVx
zanzoDsyC(j22_8Vr_*Qt6`W`0eJzTL#S4K_@ijH9MKe`ddw-H+LR}U|=Qy2(>V?rY
z1fBH)(sj*o{IovBFBJ9<$eQLCI%^7~`+_?Ao;v%3I{KO9);;u6S9h0zzRc5gxj|<y
zfqc9>&Sy_i8rNTu72w>n-mm4>KjyI4HF5rW`17r(z$)~w!;~p-Ow|1nqfFBM<AnPY
z!S>c>aU8q_P9)|;yMpZzCl>C4=|Coz%^Y;{L;DN4)bKq{t{_fJydxBhI~~zzGScmI
z2Sf3Qv!HS8{Ndq3>MpVKg`CR=jg%cJWW-J%&ZdTk?$!c)!Bd5l*!#1i_FyVM=-LZ8
z*K#P6%MXoY7bs3z?98AufIVfL!8AOLCUzk+R&dYvKfl%RW1g54)&;QvFy!T2u7QF1
zMOrSt&AewX$GSF{-%SAXhIp(aT}uJz^keQAkM9EVqIJY$eh5<^kS@K|J0P>p7;oBz
z?knzt#CSv_-q=6E={Ms-0?_~K7xHZML!Ihc<@;@jdnC0XUJ;yrc(-*8a~%^8c8*D}
zdE;G`CSg6AJLMeG0KnLAF#k;p-Us8y>={4wf$jxe@351M-+hqjhn)DwT}TsjLrtFG
t#WH69ET#p-{eR>C0pl?r>_u}nn&<FI0)`le#5wc)R6X?L9Pmi{{R?cl2WkKS

literal 0
HcmV?d00001

-- 
2.34.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH v6 14/19] linux-user/riscv: Add vdso
  2023-09-30  2:15 [PATCH v6 00/19] linux-user: Implement VDSOs Richard Henderson
                   ` (12 preceding siblings ...)
  2023-09-30  2:15 ` [PATCH v6 13/19] linux-user/hppa: " Richard Henderson
@ 2023-09-30  2:15 ` Richard Henderson
  2023-10-05 16:24   ` Philippe Mathieu-Daudé
  2023-09-30  2:15 ` [PATCH v6 15/19] linux-user/loongarch64: " Richard Henderson
                   ` (4 subsequent siblings)
  18 siblings, 1 reply; 37+ messages in thread
From: Richard Henderson @ 2023-09-30  2:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.bennee, laurent, Alistair Francis

Acked-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/riscv/vdso-asmoffset.h |   9 ++
 linux-user/elfload.c              |   2 +
 linux-user/riscv/signal.c         |   8 ++
 linux-user/meson.build            |   1 +
 linux-user/riscv/Makefile.vdso    |  15 +++
 linux-user/riscv/meson.build      |   7 ++
 linux-user/riscv/vdso-32.so       | Bin 0 -> 2888 bytes
 linux-user/riscv/vdso-64.so       | Bin 0 -> 3840 bytes
 linux-user/riscv/vdso.S           | 186 ++++++++++++++++++++++++++++++
 linux-user/riscv/vdso.ld          |  74 ++++++++++++
 10 files changed, 302 insertions(+)
 create mode 100644 linux-user/riscv/vdso-asmoffset.h
 create mode 100644 linux-user/riscv/Makefile.vdso
 create mode 100644 linux-user/riscv/meson.build
 create mode 100755 linux-user/riscv/vdso-32.so
 create mode 100755 linux-user/riscv/vdso-64.so
 create mode 100644 linux-user/riscv/vdso.S
 create mode 100644 linux-user/riscv/vdso.ld

diff --git a/linux-user/riscv/vdso-asmoffset.h b/linux-user/riscv/vdso-asmoffset.h
new file mode 100644
index 0000000000..123902ef61
--- /dev/null
+++ b/linux-user/riscv/vdso-asmoffset.h
@@ -0,0 +1,9 @@
+#ifdef TARGET_ABI32
+# define sizeof_rt_sigframe     0x2b0
+# define offsetof_uc_mcontext   0x120
+# define offsetof_freg0         0x80
+#else
+# define sizeof_rt_sigframe     0x340
+# define offsetof_uc_mcontext   0x130
+# define offsetof_freg0         0x100
+#endif
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index ccf8a1dc78..ff6951950b 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1884,8 +1884,10 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
 
 #ifdef TARGET_RISCV32
 #define ELF_CLASS ELFCLASS32
+#define VDSO_HEADER "vdso-32.c.inc"
 #else
 #define ELF_CLASS ELFCLASS64
+#define VDSO_HEADER "vdso-64.c.inc"
 #endif
 
 #define ELF_HWCAP get_elf_hwcap()
diff --git a/linux-user/riscv/signal.c b/linux-user/riscv/signal.c
index f989f7f51f..941eadce87 100644
--- a/linux-user/riscv/signal.c
+++ b/linux-user/riscv/signal.c
@@ -21,6 +21,7 @@
 #include "user-internals.h"
 #include "signal-common.h"
 #include "linux-user/trace.h"
+#include "vdso-asmoffset.h"
 
 /* Signal handler invocation must be transparent for the code being
    interrupted. Complete CPU (hart) state is saved on entry and restored
@@ -37,6 +38,8 @@ struct target_sigcontext {
     uint32_t fcsr;
 }; /* cf. riscv-linux:arch/riscv/include/uapi/asm/ptrace.h */
 
+QEMU_BUILD_BUG_ON(offsetof(struct target_sigcontext, fpr) != offsetof_freg0);
+
 struct target_ucontext {
     abi_ulong uc_flags;
     abi_ptr uc_link;
@@ -51,6 +54,11 @@ struct target_rt_sigframe {
     struct target_ucontext uc;
 };
 
+QEMU_BUILD_BUG_ON(sizeof(struct target_rt_sigframe)
+                  != sizeof_rt_sigframe);
+QEMU_BUILD_BUG_ON(offsetof(struct target_rt_sigframe, uc.uc_mcontext)
+                  != offsetof_uc_mcontext);
+
 static abi_ulong get_sigframe(struct target_sigaction *ka,
                               CPURISCVState *regs, size_t framesize)
 {
diff --git a/linux-user/meson.build b/linux-user/meson.build
index dd24389052..3ff3bc5bbc 100644
--- a/linux-user/meson.build
+++ b/linux-user/meson.build
@@ -45,6 +45,7 @@ subdir('microblaze')
 subdir('mips64')
 subdir('mips')
 subdir('ppc')
+subdir('riscv')
 subdir('s390x')
 subdir('sh4')
 subdir('sparc')
diff --git a/linux-user/riscv/Makefile.vdso b/linux-user/riscv/Makefile.vdso
new file mode 100644
index 0000000000..2c257dbfda
--- /dev/null
+++ b/linux-user/riscv/Makefile.vdso
@@ -0,0 +1,15 @@
+include $(BUILD_DIR)/tests/tcg/riscv64-linux-user/config-target.mak
+
+SUBDIR = $(SRC_PATH)/linux-user/riscv
+VPATH += $(SUBDIR)
+
+all: $(SUBDIR)/vdso-32.so $(SUBDIR)/vdso-64.so
+
+LDFLAGS = -nostdlib -shared -fpic -Wl,-h,linux-vdso.so.1 -Wl,--build-id=sha1 \
+	  -Wl,--hash-style=both -Wl,-T,$(SUBDIR)/vdso.ld
+
+$(SUBDIR)/vdso-32.so: vdso.S vdso.ld vdso-asmoffset.h
+	$(CC) -o $@ $(LDFLAGS) -mabi=ilp32d -march=rv32g $<
+
+$(SUBDIR)/vdso-64.so: vdso.S vdso.ld vdso-asmoffset.h
+	$(CC) -o $@ $(LDFLAGS) -mabi=lp64d -march=rv64g $<
diff --git a/linux-user/riscv/meson.build b/linux-user/riscv/meson.build
new file mode 100644
index 0000000000..beb989a7ca
--- /dev/null
+++ b/linux-user/riscv/meson.build
@@ -0,0 +1,7 @@
+vdso_32_inc = gen_vdso.process('vdso-32.so',
+                               extra_args: ['-r', '__vdso_rt_sigreturn'])
+vdso_64_inc = gen_vdso.process('vdso-64.so',
+                               extra_args: ['-r', '__vdso_rt_sigreturn'])
+
+linux_user_ss.add(when: 'TARGET_RISCV32', if_true: vdso_32_inc)
+linux_user_ss.add(when: 'TARGET_RISCV64', if_true: vdso_64_inc)
diff --git a/linux-user/riscv/vdso-32.so b/linux-user/riscv/vdso-32.so
new file mode 100755
index 0000000000000000000000000000000000000000..274b92c23dca9b44da32cb0c293f879c03a5f8ae
GIT binary patch
literal 2888
zcmb_eU2Icj7=BMnu}qj912f!W2AjB$*>rUfg3GdY>-e#3%V3I1JnPzSZDj4zo-VKu
z2M!Sx1sxzF>HtMl)Cnk}C?uMg=#7b2-fO%u#vk-Tk@-C5oUfeeF1+yFp1$AvbKdiP
z=X<~BoY6?MUDGsC;+9`US&eW`ctvJGH%hh4mO3dDA2jXjxQsEuJi;w9RPVvSmR4Ic
z#@edB?H1+|H_+h|aY0oeN#QVTLe=m3&PW`_O%!SoBUGIFiUTvn7a)!jvbv*3>NlT0
zbjEx2%E52H9Q~v7+%M-BUm7h%%m7%c4HNq9+EjKsG?#S|n$KVob1Z@02iyo?>ed>d
z@z_k6gWtKp)v2j$FK+l3G}reNbd(eLAEbo^A#Ti;&-N51y$O0g?z{}zi%D}nw0A)(
zDU+Y4dSTQ$;tLsc*io1j4!aq)&tY?qxD2k7ntRA+;}oQu!a4AHQaEMiQxm*KE1T00
z5}%JY^UQwuqH=P>zCfz#z}~5o7X}wEI?<YGTKM^q+b8>yqU*znd{!Sw8b*3Bne9)+
zwkcnHOE&(Hiu}u&OXigi7srPR%Ie=z$fxvlJQhzC%jXO|pB~61jY2LXThf`r);oAx
zKmHpey0)WdliuiWSdIxpT+{y8>(<|~OFzzI&s72JD+>3@h2O&H_a%%`)c$Cd?z^gC
z^BMV&xDq-A-37e|`YQbZ#XZt3+ICH=oaYkOsQ|tL*aOm4TAe^MGdBRRRy8!`fTei-
z1{7$~D(AW;J)V}t&b~)_#~$3Z`O*7#Z+h&WJsThIexmEij=j;R);+yuU;F;HXTs06
zj5i->I=Jf4%I8)bZhSs?B=Ca&X#I=JUaEU}=|tPH@bQ)t&95}Qy6WW0*H)Zrd_DL^
z;7$MO`nQ(7UH8t?$=Y|9oT)y0>$$4;Zh61r{LLRMxG?`i-$$hv=YCxBiTBcMbFN1*
zH$DrV9ZGz+M`|X3;~pv3v}-kW$E4h&$+$PLD3AEq5>4DSAsMULDPy;38gg85pT|}1
z>H0HX<wmYZdFhVkvtNJeu9@gToq`PPkmB{@-d?lLxOYbh>oK44a*W5llV18lVf^IM
z`S`GC+z(G~_|9NDIMkpI28RNAjHCYGP*6|sXCxiZ=jb0v_a`&)Boes+GsqR&=QcaS
z;yt?D=E<;l#<JNBA}u^15T17m`HA8-*-3;vW!ctABwty!d7?z|j@xFbUaKsw=P9;$
z)ygNkf$xfOvYf>))b8T$(4sxhUV&xL0>5zo$VZl_-Lx#mZ^DoqLeXHecLO$I&<?^T
z&s$O=5e(G&8Gk^9pvh<b&`!P@f$ikOr(rw!i+$$gze(6mzWfZflMf{xU)~<>TCvWb
zmD;VMx82tfTEDhc^sesC)<|1VcSHvz+#OmS(Km*|(TEOa!8=BetkK)ML+c~@nznAy
zS4TU;p{U;3-o7ESQ6)O4#3r_x*k~rQo6cd=_{y$Sq(cYu6@4U65r2N$pb_hXHgc9u
zsZl0tB*mZDmWd6f<K_Ul&@m$>{((%vpNi#Emfy%(p5bIJpU!5c8G1te$&}uoiw!3A
zR05gG62Fn$YKY%FT>hA0<kEcw10?;Qr4pI!Zniql6HyB&Q7yO_4xS3Ol=J(-IvLh`
zhwmxAH`(p1$M-z3A7gb7*7E`EPqr`Xu`daAFSyJx?IwV2&3Zhq1UW>tHggF2ez(67
zc#eq{`2Lv}wtWbj-y=NZ{0>pVIZ@UDQ+7R`dtyF(svfT=?giAhNiTu~=i*#1OyT)r
zZC>O2{(@<WTDt*D<&i&#AM6||mG`in$35XWC3Z2v7L`XIN(?DKzZYAT0j<`n?x{jU
q$h!<Dd4}IMtjB#*-zylJ62L;gQ3kZCSB5d}Ta-CyjzdN3dfwmbtESli

literal 0
HcmV?d00001

diff --git a/linux-user/riscv/vdso-64.so b/linux-user/riscv/vdso-64.so
new file mode 100755
index 0000000000000000000000000000000000000000..792b3ea1ee7b262c27b2c02bf6d397ddb8f85cc6
GIT binary patch
literal 3840
zcmc&%Yiv|S6h600=~`NBOEJYZO)*uGl+CuOq>+Z)ZM$vJrQIwLF`8VK-EDVc_mSPZ
zO=*Z!t#1UhfQYC?6vbzKpx}%CFiK2}{M7#%(HNsK`op00oO{n%?oK!Q!yle@?l*HD
zGjq?(e0O$_KhR&MX&~Z)U*U2KKxe~zrCnKqphFid#b+(lAOhGr+pgPChzoLOf^N3E
z05TLeMje!pUPUK!BCJqs&ZhJyh*Pwr44*XK8SY3$FY5(mp22U;D8;puTiq<eR$C2%
z<V!+G<pB4qqWBAvF9~5i7R(O}3~hsTKb-m_f9Z6^r{7;|_`Yf0@MW|A3pBxUdZ3s#
zSaDQ6Pk|`E{k4#`D%>$oA9QX@+AmUKP<VM^zukmoj17!x&Lux=hAR~ROAGe+7kRut
zxy{4D&)mMicIoH;Ko@3jp7SQ-)3Vh;6?Af<s@SlW^@FUJJWQj$7JgY^w*u_I8ub%Z
z{8zGGSM&kaZ&&miSszsNvX5!{v<8H<R_ul~TV(xdzLIiU3-TwV_oW!EW>u}OftPgT
zXRZ6^jdNS}d*e+9_b!|~n_Ru>L~p8l<!48)pW7J&!x)d|(#B}aG!w~KdL$a&CA!F1
zI&!C27Ado_oait(lF3VJWGtVH8;M9b5-)V0HH}<iG#fMX*%XW=Qu&E>G^_{z+aa)N
zXxnz9)6;$<P8g-E=+D+^_=fa%{M=8~biSIf$l0NHFGE{?&v%t%Bcb&q(HdPFS`jHv
z_2}4**n${D)G3e(3eya@CPSd@*0jdzGD}D2=K>blKjhbj<vf-aEF?#4px7-KtZR)`
zW%EnR^=a+yDea!!_fAZk_hs%Mdm#Q`^r0OO-|@)yy;~m*?hEW6Jka-;{&@FH*TK$1
z-otHAtU1#9WXsW}ry7pcKV9=o)wAx|zT-X5=_fWm-~GZ(C%ax;|5E3vj+ec!cwTLL
zZSCu8-neeA_04PEYI(c)ou<=QzuWNMRcGqY*1ccz!SWBQKC1lKeUA16&36_{7Z!Pk
z8TWz89JWWN0A}1Z6;z*bw=hmwwiUSH$iBj|&AG|P*MpC2A{QA4jruFkj<4@bbY$9%
zWJktpgsC>tk?Am^^q5RUa#_+(CPreZNDLjl81xU~!o?7tb-KB5b>*BC>s=uHSFB&m
z2V{3ad4XSx{V`K=s2m0to*uoV-VLRA&xI#g_|nl0j$2vy?iA~n!Jr&$hr#9GEr%NW
zsdhH4I&I%2C3wqT>&yJ-3@qh;B|2!>kD6!N|D?|-gw$bmxcI&N>_1Nj&LOvBy%fKW
zpq}_u<;zLdtNgu>^(v1ZW4+4LbF5eS{u9=#{0)&vd#JxZ8S<o|bpnjO+lG9bH}!%M
z3=Q}C`?iJr2GZ3nz5&0n)z=g78_0V2oj3f0Mt{h+*>4Q?g}@jH4EOi~#&CcC7XMap
zbkH1=ZYicLMa0GYTEwN?Q-P`-tX$9$u>*K=yOL&jC!(3PF)p=K+KhoGx+@h<CL&e^
zeG$WE7(An?yeA&c#cjQrwKe0hY%Y;b6*Y_~cw%v5BpXh~jCd41r3D@{HerItA`eg4
zG_#4Fc@sY%|5+Nb2l~d*_l`vPLy)-NDe7@vjYitqvR!5W3wrtcV0}l?PworEt0Z)v
zpu3igFMK5U6*-~E93`I46$zaq8bZdGb0aAJ<VzxLLHeE%g~<4Fe-tF1CXxOnPVzwZ
z-|;Rd@dX}a2c3dZ)OcG9(8D%~7rqpf`>6PHI;9CWV{O4PzVNDG9ec|7GLGP_Xs5fW
zw1s~K<^9$C%LIsjXigHZ{!aL}{X=&UXT0#a;Eys8qvT)IcX7PXtMHwm%wPOv-K0H@
z70gXW+Jf@?saF(?YW|&bce>8;gl0K0^nIW^ugt%Jo#oEzjHP;ze^7j_7}W7=(JpK2
QbiILp&>VIuv98Ad4S{NxYXATM

literal 0
HcmV?d00001

diff --git a/linux-user/riscv/vdso.S b/linux-user/riscv/vdso.S
new file mode 100644
index 0000000000..70a4f710db
--- /dev/null
+++ b/linux-user/riscv/vdso.S
@@ -0,0 +1,186 @@
+/*
+ * RISC-V linux replacement vdso.
+ *
+ * Copyright 2021 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <asm/unistd.h>
+#include <asm/errno.h>
+
+#if __riscv_xlen == 32
+# define TARGET_ABI32
+#endif
+#include "vdso-asmoffset.h"
+
+	.text
+
+.macro endf name
+	.globl	\name
+	.type	\name, @function
+	.size	\name, . - \name
+.endm
+
+.macro raw_syscall nr
+	li	a7, \nr
+	ecall
+.endm
+
+.macro vdso_syscall name, nr
+\name:
+	raw_syscall \nr
+endf	\name
+.endm
+
+__vdso_gettimeofday:
+	.cfi_startproc
+#ifdef __NR_gettimeofday
+	raw_syscall __NR_gettimeofday
+	ret
+#else
+	/* No gettimeofday, fall back to clock_gettime64. */
+	beq	a1, zero, 1f
+	sw	zero, 0(a1)	/* tz->tz_minuteswest = 0 */
+	sw	zero, 4(a1)	/* tz->tz_dsttime = 0 */
+1:	addi	sp, sp, -32
+	.cfi_adjust_cfa_offset 32
+	sw	a0, 16(sp)	/* save tv */
+	mv	a0, sp
+	raw_syscall __NR_clock_gettime64
+	lw	t0, 0(sp)	/* timespec.tv_sec.low */
+	lw	t1, 4(sp)	/* timespec.tv_sec.high */
+	lw	t2, 8(sp)	/* timespec.tv_nsec.low */
+	lw	a1, 16(sp)	/* restore tv */
+	addi	sp, sp, 32
+	.cfi_adjust_cfa_offset -32
+	bne	a0, zero, 9f	/* syscall error? */
+	li	a0, -EOVERFLOW
+	bne	t1, zero, 9f	/* y2038? */
+	li	a0, 0
+	li	t3, 1000
+	divu	t2, t2, t3	/* nsec -> usec */
+	sw	t0, 0(a1)	/* tz->tv_sec */
+	sw	t2, 4(a1)	/* tz->tv_usec */
+9:	ret
+#endif
+	.cfi_endproc
+endf __vdso_gettimeofday
+
+	.cfi_startproc
+
+#ifdef __NR_clock_gettime
+vdso_syscall __vdso_clock_gettime, __NR_clock_gettime
+#else
+vdso_syscall __vdso_clock_gettime, __NR_clock_gettime64
+#endif
+
+#ifdef __NR_clock_getres
+vdso_syscall __vdso_clock_getres, __NR_clock_getres
+#else
+vdso_syscall __vdso_clock_getres, __NR_clock_getres_time64
+#endif
+
+vdso_syscall __vdso_getcpu, __NR_getcpu
+
+__vdso_flush_icache:
+	/* qemu does not need to flush the icache */
+	li	a0, 0
+	ret
+endf __vdso_flush_icache
+
+	.cfi_endproc
+
+/*
+ * Start the unwind info at least one instruction before the signal
+ * trampoline, because the unwinder will assume we are returning
+ * after a call site.
+ */
+
+	.cfi_startproc simple
+	.cfi_signal_frame
+
+#define sizeof_reg	(__riscv_xlen / 4)
+#define sizeof_freg	8
+#define B_GR	(offsetof_uc_mcontext - sizeof_rt_sigframe)
+#define B_FR	(offsetof_uc_mcontext - sizeof_rt_sigframe + offsetof_freg0)
+
+	.cfi_def_cfa	2, sizeof_rt_sigframe
+
+	/* Return address */
+	.cfi_return_column 64
+	.cfi_offset	64, B_GR + 0			/* pc */
+
+	/* Integer registers */
+	.cfi_offset	1, B_GR + 1 * sizeof_reg	/* r1 (ra) */
+	.cfi_offset	2, B_GR + 2 * sizeof_reg	/* r2 (sp) */
+	.cfi_offset	3, B_GR + 3 * sizeof_reg
+	.cfi_offset	4, B_GR + 4 * sizeof_reg
+	.cfi_offset	5, B_GR + 5 * sizeof_reg
+	.cfi_offset	6, B_GR + 6 * sizeof_reg
+	.cfi_offset	7, B_GR + 7 * sizeof_reg
+	.cfi_offset	8, B_GR + 8 * sizeof_reg
+	.cfi_offset	9, B_GR + 9 * sizeof_reg
+	.cfi_offset	10, B_GR + 10 * sizeof_reg
+	.cfi_offset	11, B_GR + 11 * sizeof_reg
+	.cfi_offset	12, B_GR + 12 * sizeof_reg
+	.cfi_offset	13, B_GR + 13 * sizeof_reg
+	.cfi_offset	14, B_GR + 14 * sizeof_reg
+	.cfi_offset	15, B_GR + 15 * sizeof_reg
+	.cfi_offset	16, B_GR + 16 * sizeof_reg
+	.cfi_offset	17, B_GR + 17 * sizeof_reg
+	.cfi_offset	18, B_GR + 18 * sizeof_reg
+	.cfi_offset	19, B_GR + 19 * sizeof_reg
+	.cfi_offset	20, B_GR + 20 * sizeof_reg
+	.cfi_offset	21, B_GR + 21 * sizeof_reg
+	.cfi_offset	22, B_GR + 22 * sizeof_reg
+	.cfi_offset	23, B_GR + 23 * sizeof_reg
+	.cfi_offset	24, B_GR + 24 * sizeof_reg
+	.cfi_offset	25, B_GR + 25 * sizeof_reg
+	.cfi_offset	26, B_GR + 26 * sizeof_reg
+	.cfi_offset	27, B_GR + 27 * sizeof_reg
+	.cfi_offset	28, B_GR + 28 * sizeof_reg
+	.cfi_offset	29, B_GR + 29 * sizeof_reg
+	.cfi_offset	30, B_GR + 30 * sizeof_reg
+	.cfi_offset	31, B_GR + 31 * sizeof_reg	/* r31 */
+
+	.cfi_offset	32, B_FR + 0			/* f0 */
+	.cfi_offset	33, B_FR + 1 * sizeof_freg	/* f1 */
+	.cfi_offset	34, B_FR + 2 * sizeof_freg
+	.cfi_offset	35, B_FR + 3 * sizeof_freg
+	.cfi_offset	36, B_FR + 4 * sizeof_freg
+	.cfi_offset	37, B_FR + 5 * sizeof_freg
+	.cfi_offset	38, B_FR + 6 * sizeof_freg
+	.cfi_offset	39, B_FR + 7 * sizeof_freg
+	.cfi_offset	40, B_FR + 8 * sizeof_freg
+	.cfi_offset	41, B_FR + 9 * sizeof_freg
+	.cfi_offset	42, B_FR + 10 * sizeof_freg
+	.cfi_offset	43, B_FR + 11 * sizeof_freg
+	.cfi_offset	44, B_FR + 12 * sizeof_freg
+	.cfi_offset	45, B_FR + 13 * sizeof_freg
+	.cfi_offset	46, B_FR + 14 * sizeof_freg
+	.cfi_offset	47, B_FR + 15 * sizeof_freg
+	.cfi_offset	48, B_FR + 16 * sizeof_freg
+	.cfi_offset	49, B_FR + 17 * sizeof_freg
+	.cfi_offset	50, B_FR + 18 * sizeof_freg
+	.cfi_offset	51, B_FR + 19 * sizeof_freg
+	.cfi_offset	52, B_FR + 20 * sizeof_freg
+	.cfi_offset	53, B_FR + 21 * sizeof_freg
+	.cfi_offset	54, B_FR + 22 * sizeof_freg
+	.cfi_offset	55, B_FR + 23 * sizeof_freg
+	.cfi_offset	56, B_FR + 24 * sizeof_freg
+	.cfi_offset	57, B_FR + 25 * sizeof_freg
+	.cfi_offset	58, B_FR + 26 * sizeof_freg
+	.cfi_offset	59, B_FR + 27 * sizeof_freg
+	.cfi_offset	60, B_FR + 28 * sizeof_freg
+	.cfi_offset	61, B_FR + 29 * sizeof_freg
+	.cfi_offset	62, B_FR + 30 * sizeof_freg
+	.cfi_offset	63, B_FR + 31 * sizeof_freg	/* f31 */
+
+	nop
+
+__vdso_rt_sigreturn:
+	raw_syscall __NR_rt_sigreturn
+endf __vdso_rt_sigreturn
+
+	.cfi_endproc
diff --git a/linux-user/riscv/vdso.ld b/linux-user/riscv/vdso.ld
new file mode 100644
index 0000000000..aabe2b0ab3
--- /dev/null
+++ b/linux-user/riscv/vdso.ld
@@ -0,0 +1,74 @@
+/*
+ * Linker script for linux riscv replacement vdso.
+ *
+ * Copyright 2021 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+VERSION {
+        LINUX_4.15 {
+        global:
+                __vdso_rt_sigreturn;
+                __vdso_gettimeofday;
+                __vdso_clock_gettime;
+                __vdso_clock_getres;
+                __vdso_getcpu;
+                __vdso_flush_icache;
+
+        local: *;
+        };
+}
+
+
+PHDRS {
+        phdr            PT_PHDR         FLAGS(4) PHDRS;
+        load            PT_LOAD         FLAGS(7) FILEHDR PHDRS;
+        dynamic         PT_DYNAMIC      FLAGS(4);
+        eh_frame_hdr    PT_GNU_EH_FRAME;
+        note            PT_NOTE         FLAGS(4);
+}
+
+SECTIONS {
+        /*
+         * We can't prelink to any address without knowing something about
+         * the virtual memory space of the host, since that leaks over into
+         * the available memory space of the guest.
+         */
+        . = SIZEOF_HEADERS;
+
+        /*
+         * The following, including the FILEHDRS and PHDRS, are modified
+         * when we relocate the binary.  We want them to be initially
+         * writable for the relocation; we'll force them read-only after.
+         */
+        .note           : { *(.note*) }         :load :note
+        .dynamic        : { *(.dynamic) }       :load :dynamic
+        .dynsym         : { *(.dynsym) }        :load
+        /*
+         * There ought not be any real read-write data.
+         * But since we manipulated the segment layout,
+         * we have to put these sections somewhere.
+         */
+        .data           : {
+                *(.data*)
+                *(.sdata*)
+                *(.got.plt) *(.got)
+                *(.gnu.linkonce.d.*)
+                *(.bss*)
+                *(.dynbss*)
+                *(.gnu.linkonce.b.*)
+        }
+
+        .rodata         : { *(.rodata*) }
+        .hash           : { *(.hash) }
+        .gnu.hash       : { *(.gnu.hash) }
+        .dynstr         : { *(.dynstr) }
+        .gnu.version    : { *(.gnu.version) }
+        .gnu.version_d  : { *(.gnu.version_d) }
+        .gnu.version_r  : { *(.gnu.version_r) }
+        .eh_frame_hdr   : { *(.eh_frame_hdr) }  :load :eh_frame_hdr
+        .eh_frame       : { *(.eh_frame) }      :load
+
+        .text           : { *(.text*) }         :load   =0xd503201f
+}
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH v6 15/19] linux-user/loongarch64: Add vdso
  2023-09-30  2:15 [PATCH v6 00/19] linux-user: Implement VDSOs Richard Henderson
                   ` (13 preceding siblings ...)
  2023-09-30  2:15 ` [PATCH v6 14/19] linux-user/riscv: " Richard Henderson
@ 2023-09-30  2:15 ` Richard Henderson
  2023-10-05 16:18   ` Philippe Mathieu-Daudé
  2023-09-30  2:15 ` [PATCH v6 16/19] linux-user/ppc: " Richard Henderson
                   ` (3 subsequent siblings)
  18 siblings, 1 reply; 37+ messages in thread
From: Richard Henderson @ 2023-09-30  2:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.bennee, laurent, Song Gao

Requires a relatively recent binutils version in order to avoid
spurious R_LARCH_NONE relocations.  The presence of these relocs
are diagnosed by our gen-vdso tool.

Tested-by: Song Gao <gaosong@loongson.cn>
Reviewed-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/loongarch64/vdso-asmoffset.h |   8 ++
 linux-user/elfload.c                    |   2 +
 linux-user/loongarch64/signal.c         |  17 +++-
 linux-user/loongarch64/Makefile.vdso    |  11 ++
 linux-user/loongarch64/meson.build      |   4 +
 linux-user/loongarch64/vdso.S           | 130 ++++++++++++++++++++++++
 linux-user/loongarch64/vdso.ld          |  73 +++++++++++++
 linux-user/loongarch64/vdso.so          | Bin 0 -> 3560 bytes
 linux-user/meson.build                  |   1 +
 9 files changed, 245 insertions(+), 1 deletion(-)
 create mode 100644 linux-user/loongarch64/vdso-asmoffset.h
 create mode 100644 linux-user/loongarch64/Makefile.vdso
 create mode 100644 linux-user/loongarch64/meson.build
 create mode 100644 linux-user/loongarch64/vdso.S
 create mode 100644 linux-user/loongarch64/vdso.ld
 create mode 100755 linux-user/loongarch64/vdso.so

diff --git a/linux-user/loongarch64/vdso-asmoffset.h b/linux-user/loongarch64/vdso-asmoffset.h
new file mode 100644
index 0000000000..60d113822f
--- /dev/null
+++ b/linux-user/loongarch64/vdso-asmoffset.h
@@ -0,0 +1,8 @@
+#define sizeof_rt_sigframe         0x240
+#define sizeof_sigcontext          0x110
+#define sizeof_sctx_info           0x10
+
+#define offsetof_sigcontext        0x130
+#define offsetof_sigcontext_pc     0
+#define offsetof_sigcontext_gr     8
+#define offsetof_fpucontext_fr     0
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index ff6951950b..f41a57ebd5 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1197,6 +1197,8 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUPPCState *en
 
 #define elf_check_arch(x) ((x) == EM_LOONGARCH)
 
+#define VDSO_HEADER "vdso.c.inc"
+
 static inline void init_thread(struct target_pt_regs *regs,
                                struct image_info *infop)
 {
diff --git a/linux-user/loongarch64/signal.c b/linux-user/loongarch64/signal.c
index 39572c1190..afcee641a6 100644
--- a/linux-user/loongarch64/signal.c
+++ b/linux-user/loongarch64/signal.c
@@ -10,9 +10,9 @@
 #include "user-internals.h"
 #include "signal-common.h"
 #include "linux-user/trace.h"
-
 #include "target/loongarch/internals.h"
 #include "target/loongarch/vec.h"
+#include "vdso-asmoffset.h"
 
 /* FP context was used */
 #define SC_USED_FP              (1 << 0)
@@ -24,6 +24,11 @@ struct target_sigcontext {
     uint64_t sc_extcontext[0]   QEMU_ALIGNED(16);
 };
 
+QEMU_BUILD_BUG_ON(sizeof(struct target_sigcontext) != sizeof_sigcontext);
+QEMU_BUILD_BUG_ON(offsetof(struct target_sigcontext, sc_pc)
+                  != offsetof_sigcontext_pc);
+QEMU_BUILD_BUG_ON(offsetof(struct target_sigcontext, sc_regs)
+                  != offsetof_sigcontext_gr);
 
 #define FPU_CTX_MAGIC           0x46505501
 #define FPU_CTX_ALIGN           8
@@ -33,6 +38,9 @@ struct target_fpu_context {
     uint32_t fcsr;
 } QEMU_ALIGNED(FPU_CTX_ALIGN);
 
+QEMU_BUILD_BUG_ON(offsetof(struct target_fpu_context, regs)
+                  != offsetof_fpucontext_fr);
+
 #define CONTEXT_INFO_ALIGN      16
 struct target_sctx_info {
     uint32_t magic;
@@ -40,6 +48,8 @@ struct target_sctx_info {
     uint64_t padding;
 } QEMU_ALIGNED(CONTEXT_INFO_ALIGN);
 
+QEMU_BUILD_BUG_ON(sizeof(struct target_sctx_info) != sizeof_sctx_info);
+
 struct target_ucontext {
     abi_ulong tuc_flags;
     abi_ptr tuc_link;
@@ -54,6 +64,11 @@ struct target_rt_sigframe {
     struct target_ucontext       rs_uc;
 };
 
+QEMU_BUILD_BUG_ON(sizeof(struct target_rt_sigframe)
+                  != sizeof_rt_sigframe);
+QEMU_BUILD_BUG_ON(offsetof(struct target_rt_sigframe, rs_uc.tuc_mcontext)
+                  != offsetof_sigcontext);
+
 /*
  * These two structures are not present in guest memory, are private
  * to the signal implementation, but are largely copied from the
diff --git a/linux-user/loongarch64/Makefile.vdso b/linux-user/loongarch64/Makefile.vdso
new file mode 100644
index 0000000000..369de13344
--- /dev/null
+++ b/linux-user/loongarch64/Makefile.vdso
@@ -0,0 +1,11 @@
+include $(BUILD_DIR)/tests/tcg/loongarch64-linux-user/config-target.mak
+
+SUBDIR = $(SRC_PATH)/linux-user/loongarch64
+VPATH += $(SUBDIR)
+
+all: $(SUBDIR)/vdso.so
+
+$(SUBDIR)/vdso.so: vdso.S vdso.ld vdso-asmoffset.h
+	$(CC) -o $@ -nostdlib -shared -fpic -Wl,-h,linux-vdso.so.1 \
+	  -Wl,--build-id=sha1 -Wl,--hash-style=both \
+	  -Wl,--no-warn-rwx-segments -Wl,-T,$(SUBDIR)/vdso.ld $<
diff --git a/linux-user/loongarch64/meson.build b/linux-user/loongarch64/meson.build
new file mode 100644
index 0000000000..17896535f0
--- /dev/null
+++ b/linux-user/loongarch64/meson.build
@@ -0,0 +1,4 @@
+vdso_inc = gen_vdso.process('vdso.so',
+                            extra_args: ['-r', '__vdso_rt_sigreturn'])
+
+linux_user_ss.add(when: 'TARGET_LOONGARCH64', if_true: vdso_inc)
diff --git a/linux-user/loongarch64/vdso.S b/linux-user/loongarch64/vdso.S
new file mode 100644
index 0000000000..780a5fda12
--- /dev/null
+++ b/linux-user/loongarch64/vdso.S
@@ -0,0 +1,130 @@
+/*
+ * Loongarch64 linux replacement vdso.
+ *
+ * Copyright 2023 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <asm/unistd.h>
+#include <asm/errno.h>
+#include "vdso-asmoffset.h"
+
+
+	.text
+
+.macro endf name
+	.globl	\name
+	.type	\name, @function
+	.size	\name, . - \name
+.endm
+
+.macro vdso_syscall name, nr
+\name:
+	li.w	$a7, \nr
+	syscall	0
+	jr	$ra
+endf	\name
+.endm
+
+	.cfi_startproc
+
+vdso_syscall __vdso_gettimeofday, __NR_gettimeofday
+vdso_syscall __vdso_clock_gettime, __NR_clock_gettime
+vdso_syscall __vdso_clock_getres, __NR_clock_getres
+vdso_syscall __vdso_getcpu, __NR_getcpu
+
+	.cfi_endproc
+
+/*
+ * Start the unwind info at least one instruction before the signal
+ * trampoline, because the unwinder will assume we are returning
+ * after a call site.
+ */
+
+	.cfi_startproc simple
+	.cfi_signal_frame
+
+#define B_GR	offsetof_sigcontext_gr
+#define B_FR	sizeof_sigcontext + sizeof_sctx_info + offsetof_fpucontext_fr
+
+	.cfi_def_cfa	2, offsetof_sigcontext
+
+	/* Return address */
+	.cfi_return_column 64
+	.cfi_offset	64, offsetof_sigcontext_pc	/* pc */
+
+	/* Integer registers */
+	.cfi_offset	1, B_GR + 1 * 8
+	.cfi_offset	2, B_GR + 2 * 8
+	.cfi_offset	3, B_GR + 3 * 8
+	.cfi_offset	4, B_GR + 4 * 8
+	.cfi_offset	5, B_GR + 5 * 8
+	.cfi_offset	6, B_GR + 6 * 8
+	.cfi_offset	7, B_GR + 7 * 8
+	.cfi_offset	8, B_GR + 8 * 8
+	.cfi_offset	9, B_GR + 9 * 8
+	.cfi_offset	10, B_GR + 10 * 8
+	.cfi_offset	11, B_GR + 11 * 8
+	.cfi_offset	12, B_GR + 12 * 8
+	.cfi_offset	13, B_GR + 13 * 8
+	.cfi_offset	14, B_GR + 14 * 8
+	.cfi_offset	15, B_GR + 15 * 8
+	.cfi_offset	16, B_GR + 16 * 8
+	.cfi_offset	17, B_GR + 17 * 8
+	.cfi_offset	18, B_GR + 18 * 8
+	.cfi_offset	19, B_GR + 19 * 8
+	.cfi_offset	20, B_GR + 20 * 8
+	.cfi_offset	21, B_GR + 21 * 8
+	.cfi_offset	22, B_GR + 22 * 8
+	.cfi_offset	23, B_GR + 23 * 8
+	.cfi_offset	24, B_GR + 24 * 8
+	.cfi_offset	25, B_GR + 25 * 8
+	.cfi_offset	26, B_GR + 26 * 8
+	.cfi_offset	27, B_GR + 27 * 8
+	.cfi_offset	28, B_GR + 28 * 8
+	.cfi_offset	29, B_GR + 29 * 8
+	.cfi_offset	30, B_GR + 30 * 8
+	.cfi_offset	31, B_GR + 31 * 8
+
+	/* Floating point registers */
+	.cfi_offset	32, B_FR + 0
+	.cfi_offset	33, B_FR + 1 * 8
+	.cfi_offset	34, B_FR + 2 * 8
+	.cfi_offset	35, B_FR + 3 * 8
+	.cfi_offset	36, B_FR + 4 * 8
+	.cfi_offset	37, B_FR + 5 * 8
+	.cfi_offset	38, B_FR + 6 * 8
+	.cfi_offset	39, B_FR + 7 * 8
+	.cfi_offset	40, B_FR + 8 * 8
+	.cfi_offset	41, B_FR + 9 * 8
+	.cfi_offset	42, B_FR + 10 * 8
+	.cfi_offset	43, B_FR + 11 * 8
+	.cfi_offset	44, B_FR + 12 * 8
+	.cfi_offset	45, B_FR + 13 * 8
+	.cfi_offset	46, B_FR + 14 * 8
+	.cfi_offset	47, B_FR + 15 * 8
+	.cfi_offset	48, B_FR + 16 * 8
+	.cfi_offset	49, B_FR + 17 * 8
+	.cfi_offset	50, B_FR + 18 * 8
+	.cfi_offset	51, B_FR + 19 * 8
+	.cfi_offset	52, B_FR + 20 * 8
+	.cfi_offset	53, B_FR + 21 * 8
+	.cfi_offset	54, B_FR + 22 * 8
+	.cfi_offset	55, B_FR + 23 * 8
+	.cfi_offset	56, B_FR + 24 * 8
+	.cfi_offset	57, B_FR + 25 * 8
+	.cfi_offset	58, B_FR + 26 * 8
+	.cfi_offset	59, B_FR + 27 * 8
+	.cfi_offset	60, B_FR + 28 * 8
+	.cfi_offset	61, B_FR + 29 * 8
+	.cfi_offset	62, B_FR + 30 * 8
+	.cfi_offset	63, B_FR + 31 * 8
+
+	nop
+
+__vdso_rt_sigreturn:
+	li.w	$a7, __NR_rt_sigreturn
+	syscall	0
+	.cfi_endproc
+endf __vdso_rt_sigreturn
diff --git a/linux-user/loongarch64/vdso.ld b/linux-user/loongarch64/vdso.ld
new file mode 100644
index 0000000000..682446ed0c
--- /dev/null
+++ b/linux-user/loongarch64/vdso.ld
@@ -0,0 +1,73 @@
+/*
+ * Linker script for linux loongarch64 replacement vdso.
+ *
+ * Copyright 2023 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+VERSION {
+        LINUX_5.10 {
+        global:
+                __vdso_getcpu;
+                __vdso_clock_getres;
+                __vdso_clock_gettime;
+                __vdso_gettimeofday;
+                __vdso_rt_sigreturn;
+
+        local: *;
+        };
+}
+
+
+PHDRS {
+        phdr            PT_PHDR         FLAGS(4) PHDRS;
+        load            PT_LOAD         FLAGS(7) FILEHDR PHDRS;
+        dynamic         PT_DYNAMIC      FLAGS(4);
+        eh_frame_hdr    PT_GNU_EH_FRAME;
+        note            PT_NOTE         FLAGS(4);
+}
+
+SECTIONS {
+        /*
+         * We can't prelink to any address without knowing something about
+         * the virtual memory space of the host, since that leaks over into
+         * the available memory space of the guest.
+         */
+        . = SIZEOF_HEADERS;
+
+        /*
+         * The following, including the FILEHDRS and PHDRS, are modified
+         * when we relocate the binary.  We want them to be initially
+         * writable for the relocation; we'll force them read-only after.
+         */
+        .note           : { *(.note*) }         :load :note
+        .dynamic        : { *(.dynamic) }       :load :dynamic
+        .dynsym         : { *(.dynsym) }        :load
+        /*
+         * There ought not be any real read-write data.
+         * But since we manipulated the segment layout,
+         * we have to put these sections somewhere.
+         */
+        .data           : {
+                *(.data*)
+                *(.sdata*)
+                *(.got.plt) *(.got)
+                *(.gnu.linkonce.d.*)
+                *(.bss*)
+                *(.dynbss*)
+                *(.gnu.linkonce.b.*)
+        }
+
+        .rodata         : { *(.rodata*) }
+        .hash           : { *(.hash) }
+        .gnu.hash       : { *(.gnu.hash) }
+        .dynstr         : { *(.dynstr) }
+        .gnu.version    : { *(.gnu.version) }
+        .gnu.version_d  : { *(.gnu.version_d) }
+        .gnu.version_r  : { *(.gnu.version_r) }
+        .eh_frame_hdr   : { *(.eh_frame_hdr) }  :load :eh_frame_hdr
+        .eh_frame       : { *(.eh_frame) }      :load
+
+        .text           : { *(.text*) }         :load   =0xd503201f
+}
diff --git a/linux-user/loongarch64/vdso.so b/linux-user/loongarch64/vdso.so
new file mode 100755
index 0000000000000000000000000000000000000000..bfaa26f2bfe1aaa01d9a349b8b030ef6323e1f8e
GIT binary patch
literal 3560
zcmc&%|4$r66ra5<U&=wttF2NG6%=bN^n^+++FFk<$Cr9ga)46PxE$QUp>Rj;76P?0
z*pkLHYK<{!)EKHwLri1P7+ZfbCjMajKaBm!V50tDu=w8YyuH2cp)oP>9lM{I&%8Hp
zXLj~8gA7MHeVQiNbm6WE5mF5|x7&qwgpg<vMR>0iJ4G?pw^^Ls9<srSt5RJvma2B5
zOH{cKEK$d3jNG9QIm)-B`t@R?;u$$#|Bq&z;@0U_0IO|UFe*1I7nO%qzh10Uag6S`
z-Poq%)zvp7qV*T`vX?&yG++NVu{3(B=kn+08z^)K-Oxs?yFE54u2LY{Z?`tngf~^a
zh$?7xDv_Edu|^YvR%U~ENugh1l|t{F^Zcl0p<c6K|BX#M{|%MzPgPgx#JZ}l@W8pF
z{{eM;TPtdw-05}U7nMA5t_EF{iw>SZ#nWrv<>Jc~e?al4l|S<l#m_6A=W~zZ`#t{0
z6`%C*GsuJZWfLLKczx5b=-tvV=pA|ABT|-8xBLw5S3>brr}2@GURkPzG*L^O6Z1o0
zZQxR4^6J;qwR=BlPwiV9O)S*Bz9|f2E}l&r6A9CtoKB?2<FN(i#-`F^FLKLmWG0bi
z4ui*LX1SIzjqKz^CSlHIQetW{H9LQhQUvj@Nkn@3hK7y9!KOxhIAuPO`w^w7-{o(9
zuAuLXzS|MJ$Y_i{yw6<vsf^mlXnx7GfPR#GY5fkOV>9A1Vu*s!Ds2$jnW)gtYFeN|
zw>bJ9NW=J%e$Dv}pkqi2l>63vMIiy&S@4|!eIB;WL6Hf?87P^7(iCi;g0dIDpM>&p
zsEEUkQP?>GmCpm5hF#CW9mBBu8Q3!jcShl^eyHk$y%D(k1O&RFx)bi{fP35Ez7W*h
zkWl-Tg!{jg@W2-m>eeJY_?d)#*Cagjsf7Kj5+1%P;lLFM^&d-USdnn>BMHF|B|P%J
zgvR$IG`%C?(AyFoeM>^~n-UJcA>pytBpkUYq2*Nxk6)1R#Il5==Oi3klJMlMML52(
z2v7a7XwT0Ej{O*3{0;c8oWtc+FKUE{_`iE4SN`5rUdj33Z0r68yRN3OAn5oGS#RAA
zxJNnqpU>-#4(9V)=|YjCv-$qTj^5_;C64aq^QEGY{^|IovTo-4mpS`TKL77@N<+O^
zQtOucA&szjr7z6aS%us49#Q^Y-RwoakPgNa@6|8bq{!c^gXb0R)y;Pm@72d^$QRN<
zVRW48Ywhi67e;^dWP7+{C>l0UD4uTZ3LAs1ZIQ5n+JZZ+5$-lRqpiJRqq`$2jIPMZ
zw$_Mova@p_JeYIbQqTTIrj!agisuqHha-K=)30E5VcLw1ieT2v*qG!}Ds3i2FustA
zO;3(l1@uLXnK2QZNX-V5v24=j&5X^=B{JE`bSkf6#6>WXG{!Tr>4cGtqbJuy&`ivm
zIHCW61+Wj=b9mq9?~>78U%5oIuehxiE7rcFNM5&$d|u;yjrTCtW7>b|EW`Qvyu-Mz
z`lWcv&GCGWIfNX2Dkx5t@p@-uf7R^7Gf#R)doSnb^BE(xlX3qX$MevFZNKALiR1Y^
z$GBCz)hXWERNoxW=RZb1@3Fr}7Q_i`*mUJ*y<+5jlAoXRFg}a%boS#q>l!1CkBrv{
zkKbm67{>xV6UTec;nnP@kmrqQTE^~pKF={Wdj{;yk6V`&&$7tpK1QB@&gbbaFE{%T
t^8Y9M)xhXH4|s8YUVn6E<GID6W2?&Xy2IE7Z+_~tP`sfI?92ZU{}&)DVfp|7

literal 0
HcmV?d00001

diff --git a/linux-user/meson.build b/linux-user/meson.build
index 3ff3bc5bbc..bc41e8c3bc 100644
--- a/linux-user/meson.build
+++ b/linux-user/meson.build
@@ -40,6 +40,7 @@ subdir('alpha')
 subdir('arm')
 subdir('hppa')
 subdir('i386')
+subdir('loongarch64')
 subdir('m68k')
 subdir('microblaze')
 subdir('mips64')
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH v6 16/19] linux-user/ppc: Add vdso
  2023-09-30  2:15 [PATCH v6 00/19] linux-user: Implement VDSOs Richard Henderson
                   ` (14 preceding siblings ...)
  2023-09-30  2:15 ` [PATCH v6 15/19] linux-user/loongarch64: " Richard Henderson
@ 2023-09-30  2:15 ` Richard Henderson
  2023-10-05 16:35   ` Philippe Mathieu-Daudé
  2023-09-30  2:15 ` [PATCH v6 17/19] linux-user/s390x: Rename __SIGNAL_FRAMESIZE to STACK_FRAME_OVERHEAD Richard Henderson
                   ` (2 subsequent siblings)
  18 siblings, 1 reply; 37+ messages in thread
From: Richard Henderson @ 2023-09-30  2:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.bennee, laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/ppc/vdso-asmoffset.h |  20 +++
 linux-user/elfload.c            |   8 ++
 linux-user/ppc/signal.c         |  31 +++--
 linux-user/gen-vdso-elfn.c.inc  |   7 +
 linux-user/ppc/Makefile.vdso    |  20 +++
 linux-user/ppc/meson.build      |  12 ++
 linux-user/ppc/vdso-32.ld       |  70 ++++++++++
 linux-user/ppc/vdso-32.so       | Bin 0 -> 3020 bytes
 linux-user/ppc/vdso-64.ld       |  68 +++++++++
 linux-user/ppc/vdso-64.so       | Bin 0 -> 3896 bytes
 linux-user/ppc/vdso-64le.so     | Bin 0 -> 3896 bytes
 linux-user/ppc/vdso.S           | 239 ++++++++++++++++++++++++++++++++
 12 files changed, 467 insertions(+), 8 deletions(-)
 create mode 100644 linux-user/ppc/vdso-asmoffset.h
 create mode 100644 linux-user/ppc/Makefile.vdso
 create mode 100644 linux-user/ppc/vdso-32.ld
 create mode 100755 linux-user/ppc/vdso-32.so
 create mode 100644 linux-user/ppc/vdso-64.ld
 create mode 100755 linux-user/ppc/vdso-64.so
 create mode 100755 linux-user/ppc/vdso-64le.so
 create mode 100644 linux-user/ppc/vdso.S

diff --git a/linux-user/ppc/vdso-asmoffset.h b/linux-user/ppc/vdso-asmoffset.h
new file mode 100644
index 0000000000..6844c8c81c
--- /dev/null
+++ b/linux-user/ppc/vdso-asmoffset.h
@@ -0,0 +1,20 @@
+/*
+ * Size of dummy stack frame allocated when calling signal handler.
+ * See arch/powerpc/include/asm/ptrace.h.
+ */
+#ifdef TARGET_ABI32
+# define SIGNAL_FRAMESIZE                   64
+#else
+# define SIGNAL_FRAMESIZE                   128
+#endif
+
+#ifdef TARGET_ABI32
+# define offsetof_sigframe_mcontext         0x20
+# define offsetof_rt_sigframe_mcontext      0x140
+# define offsetof_mcontext_fregs            0xc0
+# define offsetof_mcontext_vregs            0x1d0
+#else
+# define offsetof_rt_sigframe_mcontext      0xe8
+# define offsetof_mcontext_fregs            0x180
+# define offsetof_mcontext_vregs_ptr        0x288
+#endif
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index f41a57ebd5..4a2d21a1f9 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1187,6 +1187,14 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUPPCState *en
 #define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE       4096
 
+#ifndef TARGET_PPC64
+# define VDSO_HEADER  "vdso-32.c.inc"
+#elif TARGET_BIG_ENDIAN
+# define VDSO_HEADER  "vdso-64.c.inc"
+#else
+# define VDSO_HEADER  "vdso-64le.c.inc"
+#endif
+
 #endif
 
 #ifdef TARGET_LOONGARCH64
diff --git a/linux-user/ppc/signal.c b/linux-user/ppc/signal.c
index a616f20efb..7e7302823b 100644
--- a/linux-user/ppc/signal.c
+++ b/linux-user/ppc/signal.c
@@ -21,14 +21,7 @@
 #include "user-internals.h"
 #include "signal-common.h"
 #include "linux-user/trace.h"
-
-/* Size of dummy stack frame allocated when calling signal handler.
-   See arch/powerpc/include/asm/ptrace.h.  */
-#if defined(TARGET_PPC64)
-#define SIGNAL_FRAMESIZE 128
-#else
-#define SIGNAL_FRAMESIZE 64
-#endif
+#include "vdso-asmoffset.h"
 
 /* See arch/powerpc/include/asm/ucontext.h.  Only used for 32-bit PPC;
    on 64-bit PPC, sigcontext and mcontext are one and the same.  */
@@ -73,6 +66,16 @@ struct target_mcontext {
 #endif
 };
 
+QEMU_BUILD_BUG_ON(offsetof(struct target_mcontext, mc_fregs)
+                  != offsetof_mcontext_fregs);
+#if defined(TARGET_PPC64)
+QEMU_BUILD_BUG_ON(offsetof(struct target_mcontext, v_regs)
+                  != offsetof_mcontext_vregs_ptr);
+#else
+QEMU_BUILD_BUG_ON(offsetof(struct target_mcontext, mc_vregs)
+                  != offsetof_mcontext_vregs);
+#endif
+
 /* See arch/powerpc/include/asm/sigcontext.h.  */
 struct target_sigcontext {
     target_ulong _unused[4];
@@ -161,6 +164,7 @@ struct target_ucontext {
 #endif
 };
 
+#if !defined(TARGET_PPC64)
 /* See arch/powerpc/kernel/signal_32.c.  */
 struct target_sigframe {
     struct target_sigcontext sctx;
@@ -168,6 +172,10 @@ struct target_sigframe {
     int32_t abigap[56];
 };
 
+QEMU_BUILD_BUG_ON(offsetof(struct target_sigframe, mctx)
+                  != offsetof_sigframe_mcontext);
+#endif
+
 #if defined(TARGET_PPC64)
 
 #define TARGET_TRAMP_SIZE 6
@@ -184,6 +192,10 @@ struct target_rt_sigframe {
     char abigap[288];
 } __attribute__((aligned(16)));
 
+QEMU_BUILD_BUG_ON(offsetof(struct target_rt_sigframe,
+                           uc.tuc_sigcontext.mcontext)
+                  != offsetof_rt_sigframe_mcontext);
+
 #else
 
 struct target_rt_sigframe {
@@ -192,6 +204,9 @@ struct target_rt_sigframe {
     int32_t abigap[56];
 };
 
+QEMU_BUILD_BUG_ON(offsetof(struct target_rt_sigframe, uc.tuc_mcontext)
+                  != offsetof_rt_sigframe_mcontext);
+
 #endif
 
 #if defined(TARGET_PPC64)
diff --git a/linux-user/gen-vdso-elfn.c.inc b/linux-user/gen-vdso-elfn.c.inc
index 7034c36d5e..95856eb839 100644
--- a/linux-user/gen-vdso-elfn.c.inc
+++ b/linux-user/gen-vdso-elfn.c.inc
@@ -273,7 +273,14 @@ static void elfN(process)(FILE *outf, void *buf, bool need_bswap)
                 errors++;
                 break;
 
+            case PT_LOPROC + 3:
+                if (ehdr->e_machine == EM_PPC64) {
+                    break;  /* DT_PPC64_OPT: integer bitmask */
+                }
+                goto do_default;
+
             default:
+            do_default:
                 /* This is probably something target specific. */
                 fprintf(stderr, "VDSO has unknown DYNAMIC entry (%lx)\n",
                         (unsigned long)tag);
diff --git a/linux-user/ppc/Makefile.vdso b/linux-user/ppc/Makefile.vdso
new file mode 100644
index 0000000000..3ca3c6b83e
--- /dev/null
+++ b/linux-user/ppc/Makefile.vdso
@@ -0,0 +1,20 @@
+include $(BUILD_DIR)/tests/tcg/ppc64-linux-user/config-target.mak
+
+SUBDIR = $(SRC_PATH)/linux-user/ppc
+VPATH += $(SUBDIR)
+
+all: $(SUBDIR)/vdso-32.so $(SUBDIR)/vdso-64.so $(SUBDIR)/vdso-64le.so
+
+LDFLAGS32 = -nostdlib -shared -Wl,-T,$(SUBDIR)/vdso-32.ld \
+            -Wl,-h,linux-vdso32.so.1 -Wl,--hash-style=both -Wl,--build-id=sha1
+LDFLAGS64 = -nostdlib -shared -Wl,-T,$(SUBDIR)/vdso-64.ld \
+            -Wl,-h,linux-vdso64.so.1 -Wl,--hash-style=both -Wl,--build-id=sha1
+
+$(SUBDIR)/vdso-32.so: vdso.S vdso-32.ld vdso-asmoffset.h
+	$(CC) -o $@ $(LDFLAGS32) -m32 $<
+
+$(SUBDIR)/vdso-64.so: vdso.S vdso-64.ld vdso-asmoffset.h
+	$(CC) -o $@ $(LDFLAGS64) -mbig-endian $<
+
+$(SUBDIR)/vdso-64le.so: vdso.S vdso-64.ld vdso-asmoffset.h
+	$(CC) -o $@ $(LDFLAGS64) -mlittle-endian $<
diff --git a/linux-user/ppc/meson.build b/linux-user/ppc/meson.build
index 19fead7bc8..80cacae396 100644
--- a/linux-user/ppc/meson.build
+++ b/linux-user/ppc/meson.build
@@ -3,3 +3,15 @@ syscall_nr_generators += {
                    arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ],
                    output: '@BASENAME@_nr.h')
 }
+
+vdso_32_inc = gen_vdso.process('vdso-32.so', extra_args: [
+                                   '-s', '__kernel_sigtramp32',
+                                   '-r', '__kernel_sigtramp_rt32'
+                               ])
+linux_user_ss.add(when: 'TARGET_PPC', if_true: vdso_32_inc)
+
+vdso_64_inc = gen_vdso.process('vdso-64.so',
+                               extra_args: ['-r', '__kernel_sigtramp_rt64'])
+vdso_64le_inc = gen_vdso.process('vdso-64le.so',
+                                 extra_args: ['-r', '__kernel_sigtramp_rt64'])
+linux_user_ss.add(when: 'TARGET_PPC64', if_true: [vdso_64_inc, vdso_64le_inc])
diff --git a/linux-user/ppc/vdso-32.ld b/linux-user/ppc/vdso-32.ld
new file mode 100644
index 0000000000..6962696540
--- /dev/null
+++ b/linux-user/ppc/vdso-32.ld
@@ -0,0 +1,70 @@
+/*
+ * Linker script for linux powerpc64 replacement vdso.
+ *
+ * Copyright 2023 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+VERSION {
+        LINUX_2.6.15 {
+        global:
+                __kernel_gettimeofday;
+                __kernel_clock_gettime;
+                __kernel_clock_gettime64;
+                __kernel_clock_getres;
+                __kernel_time;
+                __kernel_sync_dicache;
+                __kernel_sigtramp32;
+                __kernel_sigtramp_rt32;
+                __kernel_getcpu;
+        local: *;
+        };
+}
+
+PHDRS {
+        phdr            PT_PHDR         FLAGS(4) PHDRS;
+        load            PT_LOAD         FLAGS(7) FILEHDR PHDRS; /* FLAGS=RWX */
+        dynamic         PT_DYNAMIC      FLAGS(4);
+        eh_frame_hdr    PT_GNU_EH_FRAME;
+        note            PT_NOTE         FLAGS(4);
+}
+
+SECTIONS {
+        . = SIZEOF_HEADERS;
+
+        /*
+         * The following, including the FILEHDRS and PHDRS, are modified
+         * when we relocate the binary.  We want them to be initially
+         * writable for the relocation; we'll force them read-only after.
+         */
+        .note           : { *(.note*) }         :load :note
+        .dynamic        : { *(.dynamic) }       :load :dynamic
+        .dynsym         : { *(.dynsym) }        :load
+        .data           : {
+                /*
+                 * There ought not be any real read-write data.
+                 * But since we manipulated the segment layout,
+                 * we have to put these sections somewhere.
+                 */
+                *(.data*)
+                *(.sdata*)
+                *(.got.plt) *(.got)
+                *(.gnu.linkonce.d.*)
+                *(.bss*)
+                *(.dynbss*)
+                *(.gnu.linkonce.b.*)
+        }
+
+        .rodata         : { *(.rodata*) }
+        .hash           : { *(.hash) }
+        .gnu.hash       : { *(.gnu.hash) }
+        .dynstr         : { *(.dynstr) }
+        .gnu.version    : { *(.gnu.version) }
+        .gnu.version_d  : { *(.gnu.version_d) }
+        .gnu.version_r  : { *(.gnu.version_r) }
+        .eh_frame_hdr   : { *(.eh_frame_hdr) }  :load :eh_frame_hdr
+        .eh_frame       : { *(.eh_frame) }      :load
+
+        .text           : { *(.text*) }         :load
+}
diff --git a/linux-user/ppc/vdso-32.so b/linux-user/ppc/vdso-32.so
new file mode 100755
index 0000000000000000000000000000000000000000..b19baafb0d38e15b4a24def5c44a6d684714be45
GIT binary patch
literal 3020
zcmbtWeQXp}5P#e27f_&s6{-a-h*%I#XbYl%a{b~XN2zU*57F)Q?%F%r-of3qv<2Um
z1QRhNq7Vb7G1Z^}LI}~u5YuQA2$G0I6M`g?$RC*a2Z<OJNd)U}-tD{FYGX7`J3I56
znK%3P?abU-)!rH-!w@NQi2~@_P%gwcukw|PVv!|EM822|oDGIA#RJfpGi}!E0hzMr
zCt2j!nKNL#<KRB%%xZlg@qL{TuA6BV)8S**`B`3e@NDSJPCq|~YgO$AvFGf0kL&f&
zyz@uCzSg_H@|!C=N(SMZ1RhGR$taJG{PC+0842Jl$YDr4qtOjH9{eqM0ysZ9GIAGb
z2O;kPXF%Qp?uY(=$&FiIN0PiLV8}PHg+j<&8#ltwXQus^perIV@)MLQ_;F?_|1qrR
zGtujtf%$y&`dz^Jz?pV_ytAwe4*xXZ%MQ%<*5rc1=fT7}pAi%19|z85U=!B@*9*=S
z?;mFd<~3|*J$r8Bfmwl!+_Sb#<+!>mczErej|%2|`C~)=mL~agwClu?S594u8bd8b
zfqm~5&l#xt?zrckFwM4LED~%tTZ4&2xFZ;C3HW-_R)2fc-==+Im}9|s+KLqZ?VV}N
z`O;`qswL%VN4zKEHv?h6&mVGx$HT3On6G2I8B3IvI)ZI8Z0+GlXZM1xKs;Jj>W)X<
zi-dPg?S@Tese6fg(PEqipU>a__~g{z#Mf5vdoKWUZ*VQ^Q#EqTFWv`YACsyTqsX-k
zI@c7=-M9w15NZkZbI`dKgwb0sGIx87qCC~YY(u<p6w=Fn=)2Xmx4r>^l^odTqROT|
zL54*cl3XuS=5ET`McKWS(?hx4G;Sx2@1hBvl$W51ahepP$vY^2J5iLTMCiT_Drl$s
z+i2=Gnii(Q5IxXJ54KQIkfsM{hMyj4riXpx*-ABAsJM=1*3v95J+hW&uck+9XigP9
zRzW2zY3`>M%^R}l@lPz8f5xH(A6w)ewCITsEn0ZmqD7}HDm`gY*$Iovk6E<%1B;d%
zwdl$BELu8X(NphO^mM;P%igwV`C*Gzyk*fdhb(&bO^ep;x2X12i`MV8sIJeV=k7|X
zzay#P7fFq`ByG4U>G>ZdZM-3A({)LkuSwc+RniNWC2jpm(u)@*y>vm6c}`N(uq5A*
zq~<e{{DYDLrzHhXN@_VKsr9I&(14_Hzoc!4CAA%r)P6ux$9_qXeNvr2zf)r`)UDt`
zQJH5nL0Kw9Z53W-ZJ#KHe%qn{mevh-S{D=3x^YnJyxz`tl5MuWlXcu?EaDl#4Xp|W
z>Kz-~@oI*$AOB2TZwh3x1TN<*oID>uY6dgrnZbCNufRMzSnF5U)QoWr+L-4Kh<`U!
zygidL)hxn#dtRv-$NBOQ#(P%#g~I#An&kSVE@r^2_6tAnw+yVvp1CWrZN8tLsdd2D
z9k>OLF&kLV;9g+PqvH=E{(=J^ho5^+&*aa53mxmPAfETD*WUo<^G{;4YICh;-I_{F
z8~pB>)vL{#de6FQb9Gg{FjslkS9rYU`kI=C>PEBCQ{k;PM-Lq5C>=EiQ<HDhwA2I6
zIo(o`JUX2-a_s5+pC;!&Ok*M3@t%%^uNg8COUjVeBGE)pxC1>AUq{%l6vRUM5<cN>
zjdZ$0zIZ5UPsEazu3#)4jz&fSGa%f-klBKn9yCJ%L~115iC}jEZ{gol5kmEEA-_Ln
zt`kjMBTO^F+y^Mv)b~;!bh{T+O>%wD19N?&hPmHV&z-j8xW+jj*HtN)G4gR;tJ>y1
z(8O`f%fZ}_$jAMudUPc)?}JIlEyefGZD5YW38>!n0{=Cx!nSeTaFW$G70ilwPfTl(
zZv+x?+~=y-rvmGIu(MBW)Zbrl4JMgKVCqbHe@y5<^}L)9eX4qUy7DA1Iu3i+aXc@W
zjo~rkcm(ra@lLpJRqqBIar!w}@;+_i?_Xm8fWJ9af7_C0mVP#<ITvyH9jr;`BN!ZU
Nxt{~?)j^Od?oZyq_3Z!v

literal 0
HcmV?d00001

diff --git a/linux-user/ppc/vdso-64.ld b/linux-user/ppc/vdso-64.ld
new file mode 100644
index 0000000000..a55c65ed54
--- /dev/null
+++ b/linux-user/ppc/vdso-64.ld
@@ -0,0 +1,68 @@
+/*
+ * Linker script for linux powerpc64 replacement vdso.
+ *
+ * Copyright 2023 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+VERSION {
+        LINUX_2.6.15 {
+        global:
+                __kernel_gettimeofday;
+                __kernel_clock_gettime;
+                __kernel_clock_getres;
+                __kernel_sync_dicache;
+                __kernel_sigtramp_rt64;
+                __kernel_getcpu;
+                __kernel_time;
+        local: *;
+        };
+}
+
+PHDRS {
+        phdr            PT_PHDR         FLAGS(4) PHDRS;
+        load            PT_LOAD         FLAGS(7) FILEHDR PHDRS; /* FLAGS=RWX */
+        dynamic         PT_DYNAMIC      FLAGS(4);
+        eh_frame_hdr    PT_GNU_EH_FRAME;
+        note            PT_NOTE         FLAGS(4);
+}
+
+SECTIONS {
+        . = SIZEOF_HEADERS;
+
+        /*
+         * The following, including the FILEHDRS and PHDRS, are modified
+         * when we relocate the binary.  We want them to be initially
+         * writable for the relocation; we'll force them read-only after.
+         */
+        .note           : { *(.note*) }         :load :note
+        .dynamic        : { *(.dynamic) }       :load :dynamic
+        .dynsym         : { *(.dynsym) }        :load
+        .data           : {
+                /*
+                 * There ought not be any real read-write data.
+                 * But since we manipulated the segment layout,
+                 * we have to put these sections somewhere.
+                 */
+                *(.data*)
+                *(.sdata*)
+                *(.got.plt) *(.got)
+                *(.gnu.linkonce.d.*)
+                *(.bss*)
+                *(.dynbss*)
+                *(.gnu.linkonce.b.*)
+        }
+
+        .rodata         : { *(.rodata*) }
+        .hash           : { *(.hash) }
+        .gnu.hash       : { *(.gnu.hash) }
+        .dynstr         : { *(.dynstr) }
+        .gnu.version    : { *(.gnu.version) }
+        .gnu.version_d  : { *(.gnu.version_d) }
+        .gnu.version_r  : { *(.gnu.version_r) }
+        .eh_frame_hdr   : { *(.eh_frame_hdr) }  :load :eh_frame_hdr
+        .eh_frame       : { *(.eh_frame) }      :load
+
+        .text           : { *(.text*) }         :load
+}
diff --git a/linux-user/ppc/vdso-64.so b/linux-user/ppc/vdso-64.so
new file mode 100755
index 0000000000000000000000000000000000000000..913c831b3819fc09912b9b31f7fbe9ee311ae12f
GIT binary patch
literal 3896
zcmc&%U2GIp6uvXF?G`9-4}zctEm9FtR=`p#KiZ|+@?%?S0V#-Xx4YZ!(ssA*ZflFk
zEC~;qnApU`81<o$n4mGH3Ml?k-$;l_A9*mbFC-+ASfip3Vm)Why|dG`O-y|7wlm*%
zzH`sLGxzVz+6_&OrfCSbSYjD+kKlOf*uS7wS+$}>)CnmTqg{%ZkNv1|DMDif%Nj))
z+SG@i^||i;3HB)Dr!rAf{TX@o{{yAc6^gQ0?s{t>&Ub_T#VA&??jrT0FQi60`-@Rj
zsW^=~W-02{u9k!1`mJ|PoV_YnU0i;>+kW%g%Rg34j;I)dMT)<!km9je{d7-H|MeRo
z+UFQ?^qpeeR5r~47E`x5pKbAx!UYPQdB8?3Wjm0bp8k_<-xwj<x7ijn)?`ny?R#74
z{|5x55aryl|6TO}WFPS87d-kI5Ys;^+Y2F2eLbGkPNzp7R{=B+hDSfGbgDn((XS}I
z3~{+fAMw;jdWuXM`*}pL(D+ge71GtbI=0g{GMZc3C*-FcKv!v}C<~T^D$gpLe5Kd6
z#ot={-B0`Fk&ctUqz6B!h`oBIa_wkn@2T@cKfE8jEyCfRcqSF^4R^<Lxny5F-4%-r
z7u0BPI@+Usv&flvwxD7Y(f)ygP3;w|>~Ja?jwPd!Xu_)|yK|XHUw=50tEm>f$<)Bm
zhQU}iT~i&%rURQq)1H=t?cvRVn!u(l_(C{3Gyh04_|H7HgXWg@7wuWzH#9P)F#O@G
z?<pUGI72t1!rF#F>mSG5r1i5A@q6@CBgZL2cDzmahJr>#IW^>HSl^5xuOk7=O}b&d
z{aCS{D&8=mz9TQdu)#bD*2~~K0VOX%>2dH6L)j3_dlBXj!h!)P&%wehEXu&*7eMv{
zq+v-4?&yQ1y|AnY?mPy|ldvKIcXh+vT~HB+l`&Wqg?l>T-UtMbLgNvrY=zbP;Jy}E
z(+pKjaQ{=Vb}u}z2iEO|2Y12xMtG<J9uC2VdI;=<M}n}i4mMr3Ve>aOJo>c_)nD1L
z<x3lCzOdo3&uyr^WW(d1*|7Cf8@64vVfzIecAU52iBD{J@?)D`R2cN`zaowzmJ8YJ
zU-L>y>6*NdEzCxQ+{bKG$W~@!LO#uGT*x+N6GHB1HYwx*W>Z2QWR^GNGt5Q|d5GDl
zA={aa8S*f*aYG(qHetwTnN1q<D6=U;KF2I?%IBGlm@>?4)RY~}#!MMuHg3vJW)r52
zGMhAIjM<ba<IM7w>|!=z$!=z&mP{}kvt*LlxFwG<o3LaLvq?+#GMlnwAG5qqrkK6v
z!-1_8q9ue2ttBrik>B$0-wWIb6u4NZImL8v8y}K}bk2f@gtM>_+P#%fS8+OzvKMvy
zr{d-n$3oHP5Md=4mF1paoVT<O>#O|a<}b&Ey2}4<9@Dxy6KCcdtgp^Z&QqTDRld{t
zoIO}y<-HR1ysl2?Hx~bCM(1we;LJ7-)b?!cubLyjtoNM%=T!UD-&T+A&0nn^T|W=i
z@ABy5svUZd6CVAF(rLWj@aQx0phq83^~*&#bhsthyr&+|Z2Ue6H|!2KwgsCT!n;Fl
zGtXgf(wK4LyXm4hFU*o!{!Kn`JDQnF+-@9M1hT_@xkx8sF2k76ES1j1MIbhuiu5I;
z4#B#Jkz7Osx>EyzL?oMFJ(po+FrLXK)2SIoI3@z|M7RqxRXm)CVNGp`KrTL%Q$zTl
zp#odb-@kg@seS40&#IzcX#RCsjYRD$y-)T2brGlD?StafzH)NgdbIU-q3U1nbB*Gf
zidW}`8@~ee&3I`Yw;C0F9%yvyv%AngJ;!#uN|ZzOug?vQbTsOBb8716r*Wvo@6uaE
z@#olf&zTU~>e(ERjwfTM$EW*u@;inobibdSV7%$~C3`RSKdl@pUY}PQ#S-*;`&adx
zbLLR-cQziYW89ub=lyAo=s555ccHGINB4h2#Vd4w$FS_4+m1;KxhP(rlN!yu4pit}
ze<wZhY8~qHRHJArir4*-OkBTLQ8oVr3+6gR`fWtNGpXqJr}am<z&p0&S7qKGid@o)
TLT~?o+8puo)jWvPbH)D+{oljD

literal 0
HcmV?d00001

diff --git a/linux-user/ppc/vdso-64le.so b/linux-user/ppc/vdso-64le.so
new file mode 100755
index 0000000000000000000000000000000000000000..258a03b807c4eca23547d978c16d1ad5ebd08bc5
GIT binary patch
literal 3896
zcmcgvU2GIp6uvXl(gKCvgCJ-@i&R9Eg<`3dAMMg@`LQjvfc%I~x4YZ!(ssA*ZflFk
zEC~;qkl2J5V|XYgCTNVQf{Oq3!NkOv^pOV>`(nZa2_*`eAl7sC-m^P9tkJ~8vza;H
z{q8yU%)K-BoV!kQYl~?Zg2fU`M7||NqwZ*!&lbcrh*G>uQ7PsiU4mDm?)K_sdN9`I
z+K%Wljf<%%-N{<$r!vu);$`%>UM)4xn&Wl+oDP%U6}lDC%M~qHYqM-D!Uy%ZUR|U8
zSiAieW1ofBj`scH*7la@tux=QtI3pvuGN0C{_N=+7s+)Y-B4avDjSdBAUUGk_;WTv
z`n+zJQUm3xZqxdcjM2iN%u`CduQk86Wx9=SgBoVlAG2!w3H{)=bz2W7W_0^ao|xPD
zf5bkFB}IietG|m19ebbVFM9ZM$b+~(tIcvMpzY6l?7KBTsd=6*y>^Ow%40vG`R_E(
z-`P^lk9q9HN$fzO*ETncgrGHMKjQh_Qa8n?*z|sBDC(y+b8l4#O8w=co7&Vzc5g(s
zT;6-_ht(&#4$F6k6Th5$EnF2CUtK+N;pFby{&#*7w%r#=#v}c9ZzP?L4MY+>;oxYV
z4fQ8NecV@sPDWCB7KaE84&~c4UcQwYjfd=TEEEhy-E6EkoeT~P+R1c%o#>Cnhep;7
zhf|6AI$tW`s}-%g+V>x{H~Q**wVQB0rsszg&R_kmZ#!zz{-XWLdxzG-#QwLxx67!H
z<eXB%sIs=u9-uWpi?<D^e?(n}PLgeob&8S^zfo0TWI3`AqfMjkznZt(i-t{Pc*TUK
zu8aV~0rLb{uRzIhD18~`9D}k^C?A2jFTuQFm_Gy+X;_egg-NJ<5#%610v5&Lt^ruw
z4@>&s?xV0Y2Fs#wPcPit162`N9)=YmxUU=T4}$*)v>b-&4p_Md9%zSEZBWw+4?Yd6
zcf&)wV9ic=cn7R)fk&F*(EzM#0^fF6?}rVIQ2Vt58^3bku`eB{`@(@upF2?hnFEi1
z>OjLK2cG!Efz2N~u;n8MwqA5#+XV-n{Lq1?K5%I6xHi9{9!H(sZ?dgy)vKj*R%L{2
zS7=PgJqnEr*`d&ckk2SIDP*TYQ$p@lXj;g93e5<)U!ja4pH*ngkOveRH{?NuCJcE<
zp-Dp?R%ptQ&nYx*$Ri5P81i|AGNyb%p)ph13XPkxOQ8u<1{In#Ww%08rVJ@GZOX7h
zGp39vl(A%wLSvTfRcPFjQH3Tf8B=J|l1CMqvSgn^)0XU4XvUHQ3S~-UT%psn&)bD)
zz|SmDEi&ylUHCT__8EDb1umX^aEPw=G>7<a#lpS8^~-H!;jYNwJNAl&nT6|$yU)Vx
z6s4r&5eqXI*DZIKh1rSgS0P`Pt7C<HxhPg|EX<r-rwZ-o<?4DNKVOu%ldA5tT=|^s
zY5GQybx`&6&hb~EeX;to7I~@{-ukjx^WOT^p?Pn8>CwEm9v#=bx9*(Le6c!6&vQpT
zvIB?O{cXFNFlXcW#BSbcw{-g3n(du|&cZzGE*b?HKUXfib)iUU`8V|-7pSn5<iccW
z;Y*DUq=Vh4(@CYHjN*xOMEJs^@!&u#lm%#uI+zX$UvGTK7Y(MOiccpMGaN~#Vu^S`
z!ww5yBx?6yrHa_mFj{g;_|lP)G_Lf2mns~B>N@WGtnj{MU88wclqcM>5*t+Wc^mTn
zWzFYbeGJK+Gq~2#cS>hNj?ep?^=0fMA%EH%d`_X7NU{+x;yFI&1J-O$wj|tUy%jmy
znjD|=2I~fLLgDe*kJo|vZ{pdM{W-s|4rIOW^w+f5uE%D7K2Nje^E2DiT-~x88?&zX
zoUd3f(#HJ!9EbG*?5DFfw>ht|=K1qC!t>{6p!`73#Qxs@HT*w@?Rnj}O<%FwpYtT^
z3=gawy#6P&KYfEFoWEGNDmr)fuAe)0&Ikej-&>>OFGQ{qFP=Yte{_cCwMCed-}T}8
WQjSr;8y}D^=0BklzBu&{{(k}Ee8OG;

literal 0
HcmV?d00001

diff --git a/linux-user/ppc/vdso.S b/linux-user/ppc/vdso.S
new file mode 100644
index 0000000000..689010db13
--- /dev/null
+++ b/linux-user/ppc/vdso.S
@@ -0,0 +1,239 @@
+/*
+ * PowerPC linux replacement vdso.
+ *
+ * Copyright 2023 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <asm/unistd.h>
+#include <asm/errno.h>
+
+#ifndef _ARCH_PPC64
+# define TARGET_ABI32
+#endif
+#include "vdso-asmoffset.h"
+
+
+	.text
+
+.macro endf name
+	.globl	\name
+	.size	\name, .-\name
+	/* For PPC64, functions have special linkage; we export pointers. */
+#ifndef _ARCH_PPC64
+	.type	\name, @function
+#endif
+.endm
+
+.macro raw_syscall nr
+	addi	0, 0, \nr
+	sc
+.endm
+
+.macro vdso_syscall name, nr
+\name:
+	raw_syscall \nr
+	blr
+endf	\name
+.endm
+
+	.cfi_startproc
+
+vdso_syscall __kernel_gettimeofday, __NR_gettimeofday
+vdso_syscall __kernel_clock_gettime, __NR_clock_gettime
+vdso_syscall __kernel_clock_getres, __NR_clock_getres
+vdso_syscall __kernel_getcpu, __NR_getcpu
+vdso_syscall __kernel_time, __NR_time
+
+#ifdef __NR_clock_gettime64
+vdso_syscall __kernel_clock_gettime64, __NR_clock_gettime64
+#endif
+
+__kernel_sync_dicache:
+	/* qemu does not need to flush caches */
+	blr
+endf	__kernel_sync_dicache
+
+	.cfi_endproc
+
+/*
+ * TODO: __kernel_get_tbfreq
+ * This is probably a constant for QEMU.
+ */
+
+/*
+ * Start the unwind info at least one instruction before the signal
+ * trampoline, because the unwinder will assume we are returning
+ * after a call site.
+ */
+
+	.cfi_startproc simple
+	.cfi_signal_frame
+
+#ifdef _ARCH_PPC64
+# define __kernel_sigtramp_rt  __kernel_sigtramp_rt64
+# define sizeof_reg	8
+#else
+# define __kernel_sigtramp_rt  __kernel_sigtramp_rt32
+# define sizeof_reg	4
+#endif
+#define sizeof_freg	8
+#define sizeof_vreg	16
+
+	.cfi_def_cfa	1, SIGNAL_FRAMESIZE + offsetof_rt_sigframe_mcontext
+
+	/* Return address */
+	.cfi_return_column 67
+	.cfi_offset	67, 32 * sizeof_reg		/* nip */
+
+	/* Integer registers */
+	.cfi_offset	0, 0 * sizeof_reg
+	.cfi_offset	1, 1 * sizeof_reg
+	.cfi_offset	2, 2 * sizeof_reg
+	.cfi_offset	3, 3 * sizeof_reg
+	.cfi_offset	4, 4 * sizeof_reg
+	.cfi_offset	5, 5 * sizeof_reg
+	.cfi_offset	6, 6 * sizeof_reg
+	.cfi_offset	7, 7 * sizeof_reg
+	.cfi_offset	8, 8 * sizeof_reg
+	.cfi_offset	9, 9 * sizeof_reg
+	.cfi_offset	10, 10 * sizeof_reg
+	.cfi_offset	11, 11 * sizeof_reg
+	.cfi_offset	12, 12 * sizeof_reg
+	.cfi_offset	13, 13 * sizeof_reg
+	.cfi_offset	14, 14 * sizeof_reg
+	.cfi_offset	15, 15 * sizeof_reg
+	.cfi_offset	16, 16 * sizeof_reg
+	.cfi_offset	17, 17 * sizeof_reg
+	.cfi_offset	18, 18 * sizeof_reg
+	.cfi_offset	19, 19 * sizeof_reg
+	.cfi_offset	20, 20 * sizeof_reg
+	.cfi_offset	21, 21 * sizeof_reg
+	.cfi_offset	22, 22 * sizeof_reg
+	.cfi_offset	23, 23 * sizeof_reg
+	.cfi_offset	24, 24 * sizeof_reg
+	.cfi_offset	25, 25 * sizeof_reg
+	.cfi_offset	26, 26 * sizeof_reg
+	.cfi_offset	27, 27 * sizeof_reg
+	.cfi_offset	28, 28 * sizeof_reg
+	.cfi_offset	29, 29 * sizeof_reg
+	.cfi_offset	30, 30 * sizeof_reg
+	.cfi_offset	31, 31 * sizeof_reg
+	.cfi_offset	65, 36 * sizeof_reg		/* lr */
+	.cfi_offset	70, 38 * sizeof_reg		/* ccr */
+
+	/* Floating point registers */
+	.cfi_offset	32, offsetof_mcontext_fregs
+	.cfi_offset	33, offsetof_mcontext_fregs + 1 * sizeof_freg
+	.cfi_offset	34, offsetof_mcontext_fregs + 2 * sizeof_freg
+	.cfi_offset	35, offsetof_mcontext_fregs + 3 * sizeof_freg
+	.cfi_offset	36, offsetof_mcontext_fregs + 4 * sizeof_freg
+	.cfi_offset	37, offsetof_mcontext_fregs + 5 * sizeof_freg
+	.cfi_offset	38, offsetof_mcontext_fregs + 6 * sizeof_freg
+	.cfi_offset	39, offsetof_mcontext_fregs + 7 * sizeof_freg
+	.cfi_offset	40, offsetof_mcontext_fregs + 8 * sizeof_freg
+	.cfi_offset	41, offsetof_mcontext_fregs + 9 * sizeof_freg
+	.cfi_offset	42, offsetof_mcontext_fregs + 10 * sizeof_freg
+	.cfi_offset	43, offsetof_mcontext_fregs + 11 * sizeof_freg
+	.cfi_offset	44, offsetof_mcontext_fregs + 12 * sizeof_freg
+	.cfi_offset	45, offsetof_mcontext_fregs + 13 * sizeof_freg
+	.cfi_offset	46, offsetof_mcontext_fregs + 14 * sizeof_freg
+	.cfi_offset	47, offsetof_mcontext_fregs + 15 * sizeof_freg
+	.cfi_offset	48, offsetof_mcontext_fregs + 16 * sizeof_freg
+	.cfi_offset	49, offsetof_mcontext_fregs + 17 * sizeof_freg
+	.cfi_offset	50, offsetof_mcontext_fregs + 18 * sizeof_freg
+	.cfi_offset	51, offsetof_mcontext_fregs + 19 * sizeof_freg
+	.cfi_offset	52, offsetof_mcontext_fregs + 20 * sizeof_freg
+	.cfi_offset	53, offsetof_mcontext_fregs + 21 * sizeof_freg
+	.cfi_offset	54, offsetof_mcontext_fregs + 22 * sizeof_freg
+	.cfi_offset	55, offsetof_mcontext_fregs + 23 * sizeof_freg
+	.cfi_offset	56, offsetof_mcontext_fregs + 24 * sizeof_freg
+	.cfi_offset	57, offsetof_mcontext_fregs + 25 * sizeof_freg
+	.cfi_offset	58, offsetof_mcontext_fregs + 26 * sizeof_freg
+	.cfi_offset	59, offsetof_mcontext_fregs + 27 * sizeof_freg
+	.cfi_offset	60, offsetof_mcontext_fregs + 28 * sizeof_freg
+	.cfi_offset	61, offsetof_mcontext_fregs + 29 * sizeof_freg
+	.cfi_offset	62, offsetof_mcontext_fregs + 30 * sizeof_freg
+	.cfi_offset	63, offsetof_mcontext_fregs + 31 * sizeof_freg
+
+	/*
+	 * Unlike the kernel, unconditionally represent the Altivec/VSX regs.
+	 * The space within the stack frame is always available, and most of
+	 * our supported processors have them enabled.  The only complication
+	 * for PPC64 is the misalignment, so that we have to use indirection.
+	 */
+.macro	save_vreg_ofs reg, ofs
+#ifdef _ARCH_PPC64
+	/*
+	 * vreg = *(cfa + offsetof(v_regs)) + ofs
+         *
+         * The CFA is input to the expression on the stack, so:
+	 * DW_CFA_expression reg, length (7),
+         *   DW_OP_plus_uconst (0x23), vreg_ptr, DW_OP_deref (0x06),
+	 *   DW_OP_plus_uconst (0x23), ofs
+	 */
+	.cfi_escape 0x10, 77 + \reg, 7, 0x23, (offsetof_mcontext_vregs_ptr & 0x7f) + 0x80, offsetof_mcontext_vregs_ptr >> 7, 0x06, 0x23, (\ofs & 0x7f) | 0x80, \ofs >> 7
+#else
+	.cfi_offset 77 + \reg, offsetof_mcontext_vregs + \ofs
+#endif
+.endm
+
+.macro	save_vreg reg
+	save_vreg_ofs \reg, (\reg * sizeof_vreg)
+.endm
+
+	save_vreg   0
+	save_vreg   1
+	save_vreg   2
+	save_vreg   3
+	save_vreg   4
+	save_vreg   5
+	save_vreg   6
+	save_vreg   7
+	save_vreg   8
+	save_vreg   9
+	save_vreg  10
+	save_vreg  11
+	save_vreg  12
+	save_vreg  13
+	save_vreg  14
+	save_vreg  15
+	save_vreg  16
+	save_vreg  17
+	save_vreg  18
+	save_vreg  19
+	save_vreg  20
+	save_vreg  21
+	save_vreg  22
+	save_vreg  23
+	save_vreg  24
+	save_vreg  25
+	save_vreg  26
+	save_vreg  27
+	save_vreg  28
+	save_vreg  29
+	save_vreg  30
+	save_vreg  31
+	save_vreg  32
+	save_vreg_ofs 33, (32 * sizeof_vreg + 12)
+
+	nop
+
+__kernel_sigtramp_rt:
+	raw_syscall __NR_rt_sigreturn
+endf	__kernel_sigtramp_rt
+
+#ifndef _ARCH_PPC64
+	/*
+	 * The non-rt sigreturn has the same layout at a different offset.
+	 * Move the CFA and leave all othe other descriptions the same.
+	 */
+	.cfi_def_cfa	1, SIGNAL_FRAMESIZE + offsetof_sigframe_mcontext
+	nop
+__kernel_sigtramp32:
+	raw_syscall __NR_sigreturn
+endf	__kernel_sigtramp32
+#endif
+
+	.cfi_endproc
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH v6 17/19] linux-user/s390x: Rename __SIGNAL_FRAMESIZE to STACK_FRAME_OVERHEAD
  2023-09-30  2:15 [PATCH v6 00/19] linux-user: Implement VDSOs Richard Henderson
                   ` (15 preceding siblings ...)
  2023-09-30  2:15 ` [PATCH v6 16/19] linux-user/ppc: " Richard Henderson
@ 2023-09-30  2:15 ` Richard Henderson
  2023-09-30  2:15 ` [PATCH v6 18/19] linux-user/s390x: Add vdso Richard Henderson
  2023-09-30  2:15 ` [PATCH v6 19/19] build: Add update-linux-vdso makefile rule Richard Henderson
  18 siblings, 0 replies; 37+ messages in thread
From: Richard Henderson @ 2023-09-30  2:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.bennee, laurent, Philippe Mathieu-Daudé

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/s390x/signal.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/linux-user/s390x/signal.c b/linux-user/s390x/signal.c
index f72165576f..0f8b8e04bf 100644
--- a/linux-user/s390x/signal.c
+++ b/linux-user/s390x/signal.c
@@ -26,7 +26,8 @@
 #define __NUM_FPRS 16
 #define __NUM_ACRS 16
 
-#define __SIGNAL_FRAMESIZE      160 /* FIXME: 31-bit mode -> 96 */
+/* Minimum stack frame size */
+#define STACK_FRAME_OVERHEAD    160
 
 #define _SIGCONTEXT_NSIG        64
 #define _SIGCONTEXT_NSIG_BPW    64 /* FIXME: 31-bit mode -> 32 */
@@ -63,7 +64,7 @@ typedef struct {
 } target_sigcontext;
 
 typedef struct {
-    uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
+    uint8_t callee_used_stack[STACK_FRAME_OVERHEAD];
     target_sigcontext sc;
     target_sigregs sregs;
     int signo;
@@ -83,7 +84,7 @@ struct target_ucontext {
 };
 
 typedef struct {
-    uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
+    uint8_t callee_used_stack[STACK_FRAME_OVERHEAD];
     /*
      * This field is no longer initialized by the kernel, but it's still a part
      * of the ABI.
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH v6 18/19] linux-user/s390x: Add vdso
  2023-09-30  2:15 [PATCH v6 00/19] linux-user: Implement VDSOs Richard Henderson
                   ` (16 preceding siblings ...)
  2023-09-30  2:15 ` [PATCH v6 17/19] linux-user/s390x: Rename __SIGNAL_FRAMESIZE to STACK_FRAME_OVERHEAD Richard Henderson
@ 2023-09-30  2:15 ` Richard Henderson
  2023-10-03 13:07   ` Philippe Mathieu-Daudé
  2023-09-30  2:15 ` [PATCH v6 19/19] build: Add update-linux-vdso makefile rule Richard Henderson
  18 siblings, 1 reply; 37+ messages in thread
From: Richard Henderson @ 2023-09-30  2:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.bennee, laurent

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/s390x/vdso-asmoffset.h |   2 +
 linux-user/elfload.c              |   2 +
 linux-user/s390x/signal.c         |   4 +-
 linux-user/s390x/Makefile.vdso    |  11 +++++
 linux-user/s390x/meson.build      |   6 +++
 linux-user/s390x/vdso.S           |  61 ++++++++++++++++++++++++++
 linux-user/s390x/vdso.ld          |  69 ++++++++++++++++++++++++++++++
 linux-user/s390x/vdso.so          | Bin 0 -> 3464 bytes
 8 files changed, 152 insertions(+), 3 deletions(-)
 create mode 100644 linux-user/s390x/vdso-asmoffset.h
 create mode 100644 linux-user/s390x/Makefile.vdso
 create mode 100644 linux-user/s390x/vdso.S
 create mode 100644 linux-user/s390x/vdso.ld
 create mode 100755 linux-user/s390x/vdso.so

diff --git a/linux-user/s390x/vdso-asmoffset.h b/linux-user/s390x/vdso-asmoffset.h
new file mode 100644
index 0000000000..27a062d6c1
--- /dev/null
+++ b/linux-user/s390x/vdso-asmoffset.h
@@ -0,0 +1,2 @@
+/* Minimum stack frame size */
+#define STACK_FRAME_OVERHEAD    160
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 4a2d21a1f9..7450f9eab0 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1886,6 +1886,8 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
 #define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE 4096
 
+#define VDSO_HEADER "vdso.c.inc"
+
 #endif /* TARGET_S390X */
 
 #ifdef TARGET_RISCV
diff --git a/linux-user/s390x/signal.c b/linux-user/s390x/signal.c
index 0f8b8e04bf..b40f738a70 100644
--- a/linux-user/s390x/signal.c
+++ b/linux-user/s390x/signal.c
@@ -21,14 +21,12 @@
 #include "user-internals.h"
 #include "signal-common.h"
 #include "linux-user/trace.h"
+#include "vdso-asmoffset.h"
 
 #define __NUM_GPRS 16
 #define __NUM_FPRS 16
 #define __NUM_ACRS 16
 
-/* Minimum stack frame size */
-#define STACK_FRAME_OVERHEAD    160
-
 #define _SIGCONTEXT_NSIG        64
 #define _SIGCONTEXT_NSIG_BPW    64 /* FIXME: 31-bit mode -> 32 */
 #define _SIGCONTEXT_NSIG_WORDS  (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
diff --git a/linux-user/s390x/Makefile.vdso b/linux-user/s390x/Makefile.vdso
new file mode 100644
index 0000000000..e82bf9e29f
--- /dev/null
+++ b/linux-user/s390x/Makefile.vdso
@@ -0,0 +1,11 @@
+include $(BUILD_DIR)/tests/tcg/s390x-linux-user/config-target.mak
+
+SUBDIR = $(SRC_PATH)/linux-user/s390x
+VPATH += $(SUBDIR)
+
+all: $(SUBDIR)/vdso.so
+
+$(SUBDIR)/vdso.so: vdso.S vdso.ld vdso-asmoffset.h
+	$(CC) -o $@ -nostdlib -shared -Wl,-h,linux-vdso64.so.1 \
+	  -Wl,--build-id=sha1 -Wl,--hash-style=both \
+	  -Wl,-T,$(SUBDIR)/vdso.ld $<
diff --git a/linux-user/s390x/meson.build b/linux-user/s390x/meson.build
index 0781ccea1d..a7a25ed9ce 100644
--- a/linux-user/s390x/meson.build
+++ b/linux-user/s390x/meson.build
@@ -3,3 +3,9 @@ syscall_nr_generators += {
                      arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ],
                      output: '@BASENAME@_nr.h')
 }
+
+vdso_inc = gen_vdso.process('vdso.so', extra_args: [
+                                '-s', '__kernel_sigreturn',
+                                '-r', '__kernel_rt_sigreturn'
+                            ])
+linux_user_ss.add(when: 'TARGET_S390X', if_true: vdso_inc)
diff --git a/linux-user/s390x/vdso.S b/linux-user/s390x/vdso.S
new file mode 100644
index 0000000000..3332492477
--- /dev/null
+++ b/linux-user/s390x/vdso.S
@@ -0,0 +1,61 @@
+/*
+ * s390x linux replacement vdso.
+ *
+ * Copyright 2023 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <asm/unistd.h>
+#include "vdso-asmoffset.h"
+
+.macro endf name
+	.globl	\name
+	.type	\name, @function
+	.size	\name, . - \name
+.endm
+
+.macro raw_syscall n
+        .ifne	\n < 0x100
+	svc	\n
+	.else
+	lghi	%r1, \n
+	svc	0
+        .endif
+.endm
+
+.macro vdso_syscall name, nr
+\name:
+	.cfi_startproc
+	aghi	%r15, -(STACK_FRAME_OVERHEAD + 16)
+	.cfi_adjust_cfa_offset STACK_FRAME_OVERHEAD + 16
+	stg	%r14, STACK_FRAME_OVERHEAD(%r15)
+	.cfi_rel_offset %r14, STACK_FRAME_OVERHEAD
+	raw_syscall \nr
+	lg	%r14, STACK_FRAME_OVERHEAD(%r15)
+	aghi	%r15, STACK_FRAME_OVERHEAD + 16
+	.cfi_restore %r14
+	.cfi_adjust_cfa_offset -(STACK_FRAME_OVERHEAD + 16)
+	br	%r14
+	.cfi_endproc
+endf	\name
+.endm
+
+vdso_syscall __kernel_gettimeofday, __NR_gettimeofday
+vdso_syscall __kernel_clock_gettime, __NR_clock_gettime
+vdso_syscall __kernel_clock_getres, __NR_clock_getres
+vdso_syscall __kernel_getcpu, __NR_getcpu
+
+/*
+ * TODO unwind info, though we're ok without it.
+ * The kernel supplies bogus empty unwind info, and it is likely ignored
+ * by all users.  Without it we get the fallback signal frame handling.
+ */
+
+__kernel_sigreturn:
+	raw_syscall __NR_sigreturn
+endf	__kernel_sigreturn
+
+__kernel_rt_sigreturn:
+	raw_syscall __NR_rt_sigreturn
+endf	__kernel_rt_sigreturn
diff --git a/linux-user/s390x/vdso.ld b/linux-user/s390x/vdso.ld
new file mode 100644
index 0000000000..2a30ff382a
--- /dev/null
+++ b/linux-user/s390x/vdso.ld
@@ -0,0 +1,69 @@
+/*
+ * Linker script for linux x86-64 replacement vdso.
+ *
+ * Copyright 2023 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+VERSION {
+        LINUX_2.6.29 {
+        global:
+                __kernel_gettimeofday;
+                __kernel_clock_gettime;
+                __kernel_clock_getres;
+                __kernel_getcpu;
+                __kernel_restart_syscall;
+                __kernel_rt_sigreturn;
+                __kernel_sigreturn;
+        local: *;
+        };
+}
+
+
+PHDRS {
+        phdr            PT_PHDR         FLAGS(4) PHDRS;
+        load            PT_LOAD         FLAGS(7) FILEHDR PHDRS; /* FLAGS=RWX */
+        dynamic         PT_DYNAMIC      FLAGS(4);
+        eh_frame_hdr    PT_GNU_EH_FRAME;
+        note            PT_NOTE         FLAGS(4);
+}
+
+SECTIONS {
+        . = SIZEOF_HEADERS;
+
+        /*
+         * The following, including the FILEHDRS and PHDRS, are modified
+         * when we relocate the binary.  We want them to be initially
+         * writable for the relocation; we'll force them read-only after.
+         */
+        .note           : { *(.note*) }         :load :note
+        .dynamic        : { *(.dynamic) }       :load :dynamic
+        .dynsym         : { *(.dynsym) }        :load
+        .data           : {
+                /*
+                 * There ought not be any real read-write data.
+                 * But since we manipulated the segment layout,
+                 * we have to put these sections somewhere.
+                 */
+                *(.data*)
+                *(.sdata*)
+                *(.got.plt) *(.got)
+                *(.gnu.linkonce.d.*)
+                *(.bss*)
+                *(.dynbss*)
+                *(.gnu.linkonce.b.*)
+        }
+
+        .rodata         : { *(.rodata*) }
+        .hash           : { *(.hash) }
+        .gnu.hash       : { *(.gnu.hash) }
+        .dynstr         : { *(.dynstr) }
+        .gnu.version    : { *(.gnu.version) }
+        .gnu.version_d  : { *(.gnu.version_d) }
+        .gnu.version_r  : { *(.gnu.version_r) }
+        .eh_frame_hdr   : { *(.eh_frame_hdr) }  :load :eh_frame_hdr
+        .eh_frame       : { *(.eh_frame) }      :load
+
+        .text           : { *(.text*) }         :load
+}
diff --git a/linux-user/s390x/vdso.so b/linux-user/s390x/vdso.so
new file mode 100755
index 0000000000000000000000000000000000000000..64130f6f335269b03291653d006225b365be9cd9
GIT binary patch
literal 3464
zcmcguUuaup6hAlrn#R#}B6HHJ6^h8v3s#wtDI{HzWs-HJcB~u1U2JZX*fw`0w>2I9
z>4SqkSsXs>VMq|PDvEm&1Rwf1RK!O?(CHKhzDz`4)-9g%edpXip_vbYU-<6tJHK<z
zcW%!8&bjyXe5nwL7~qX4?8S9}P@0U^51wZ!4ROf8FziM-fitG{$m!98#y(98LK0<)
zF`)T=*Tk6C2o94N!O8KAbs})9bp<|Z(f=FCiu>y{lI$0|t_^w-9%V;CvX_ZVV@~UP
z5ysh1P<-w|K6-fSIDGtl`ke<)|Mc0}bJcWb@yj2!fBy7s_8}PJ^{b5Jk0Yw$Io;cT
zvAm@bv#$o5>1TjUWL@)+V!Xt77o&O(PPe<Q<=ACHly9+~a!c|JEyu*4)&DD)cLVIw
z5#zsb<Wa;~pHGlXgYG*Q;1!7%(pLlg1FRr>!{_5F56Dq|HugaG54H=!y#f0xtl;=^
z{(|Oe9c6~jI}MdzM5-AY|8oAd5niPp<$=q-bPi}udYXw&GFgmg;C+@!7ys^{eeuHj
z*T4PgtbX)Xd*k=9hda69Q>Wkk@x$ybu&hP9*|3+as_nY<W!qV(l-GQAe#x0%6x|MV
z({A}JZZUsm#g|+4YSVUCnhl?7x|Yu_)f+4A$5tyX=fIO@%P}8^(vhj-bJm1;z?^s*
zZyoa${1Id5U*x4{=^0Ud(KFC>Lm7yGF<^c5IqMK$gD%EM^dJJ&HRX_=UlHe3oHd-=
zIM1UMJ^v4I(xAP;I6DJId&n5swY$R)f#T6@<J<?ip>HFFH}{sl84Bv3LERZ;$NK58
z{sq)6-9i5f>gc{kWq<MCyxE<;cJ)RF##2)YW1BbO^1yAM-@MO=rJ%1aeh1xCVO{Fw
z)F*fkeFq*cPKoqGZHhdf^Ke}tPv;Sb*Qb<(B%kYOMiG2Lp8K5cgQ7#8>nFM;93k>t
zPf{jYi+obAVwW^}{2=pE|4KxA?w|60@a(yd##JBHtcojrD!7kfczq<42ikk5{qOhf
zLwR_@?>o{q)cHH)^P&ED(&rPwe&_gnsNbFI)9)_$_Mtxep3ldxa1KVn%AK6b9zAjh
zOC8^LR=#KzX0k`~RxvjN*5T5z$!y6wRwz85pS5PQlcl`n_k`ZI;q{zQa|v~hox4`3
zdw3>(zwsz90(Cq9v$eMDmS044n;L7fYB;V9W@W8WUarrp1==E(-7=Wf#)?@hw`!Vq
zo0?g*o2|Oj2nkjNOuJ?+G|S7jRjZ(-NMO2l+m)mAUvLDS<$WUcH>WrB>T|p&K(J6A
zLY*8iECCvFZapMYV$hoF3cmya_T!ZA42~~#E(lv_L;l=1Jb$XEi2%>>r49tu`x(u=
zA@PZzo*QQk$Cth#sCp{ztt`c#Fpb|mfA{!rX*tRW8I*VOC$q_bj^j&u1tHXb&|dOD
z{?B3jE-i3~KihkKi}D<d&vwfGMDKSTwpH#&f{;dk%D?!@|3?ZIaLWBi{OhE^eHgv(
zV@-Q~TZwdtd;FzO3c^KkWDLfCE#RNfdg)Vw>YW<g!b>ds%Kr-5;5sp;iO3^}^sP;K
oq#^O?{L#B0m|N2GNEUhVg)ofre@WbfvycCv+~*tYC*b-21AbI{0ssI2

literal 0
HcmV?d00001

-- 
2.34.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH v6 19/19] build: Add update-linux-vdso makefile rule
  2023-09-30  2:15 [PATCH v6 00/19] linux-user: Implement VDSOs Richard Henderson
                   ` (17 preceding siblings ...)
  2023-09-30  2:15 ` [PATCH v6 18/19] linux-user/s390x: Add vdso Richard Henderson
@ 2023-09-30  2:15 ` Richard Henderson
  2023-10-03 13:02   ` Philippe Mathieu-Daudé
  18 siblings, 1 reply; 37+ messages in thread
From: Richard Henderson @ 2023-09-30  2:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: alex.bennee, laurent

This is not ideal, since it requires all cross-compilers
to be present rather than a simple subset.  But since it
is only run manually, should be good enough for now.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 Makefile | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/Makefile b/Makefile
index bfc4b2c8e9..676a4a54f4 100644
--- a/Makefile
+++ b/Makefile
@@ -283,6 +283,13 @@ include $(SRC_PATH)/tests/vm/Makefile.include
 print-help-run = printf "  %-30s - %s\\n" "$1" "$2"
 print-help = @$(call print-help-run,$1,$2)
 
+.PHONY: update-linux-vdso
+update-linux-vdso:
+	@for m in $(SRC_PATH)/linux-user/*/Makefile.vdso; do \
+	  $(MAKE) $(SUBDIR_MAKEFLAGS) -C $$(dirname $$m) -f Makefile.vdso \
+		SRC_PATH=$(SRC_PATH) BUILD_DIR=$(BUILD_DIR); \
+	done
+
 .PHONY: help
 help:
 	@echo  'Generic targets:'
@@ -303,6 +310,9 @@ endif
 	$(call print-help,distclean,Remove all generated files)
 	$(call print-help,dist,Build a distributable tarball)
 	@echo  ''
+	@echo  'Linux-user targets:'
+	$(call print-help,update-linux-vdso,Build linux-user vdso images)
+	@echo  ''
 	@echo  'Test targets:'
 	$(call print-help,check,Run all tests (check-help for details))
 	$(call print-help,bench,Run all benchmarks)
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [PATCH v6 04/19] linux-user: Use ImageSource in load_elf_image
  2023-09-30  2:15 ` [PATCH v6 04/19] linux-user: Use ImageSource in load_elf_image Richard Henderson
@ 2023-10-02 13:22   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 37+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-10-02 13:22 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: alex.bennee, laurent

On 30/9/23 04:15, Richard Henderson wrote:
> Change parse_elf_properties as well, as the bprm_buf argument
> ties the two functions closely.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   linux-user/elfload.c | 128 +++++++++++++++++--------------------------
>   1 file changed, 49 insertions(+), 79 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH v6 07/19] linux-user: Load vdso image if available
  2023-09-30  2:15 ` [PATCH v6 07/19] linux-user: Load vdso image if available Richard Henderson
@ 2023-10-03 12:47   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 37+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-10-03 12:47 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: alex.bennee, laurent

On 30/9/23 04:15, Richard Henderson wrote:
> The vdso image will be pre-processed into a C data array, with
> a simple list of relocations to perform, and identifying the
> location of signal trampolines.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   linux-user/elfload.c | 90 +++++++++++++++++++++++++++++++++++++++-----
>   1 file changed, 81 insertions(+), 9 deletions(-)


> @@ -3691,7 +3759,7 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
>        * and let elf_load_image do any swapping that may be required.
>        */
>       struct elfhdr ehdr;
> -    struct image_info interp_info;
> +    struct image_info interp_info, vdso_info;
>       char *elf_interpreter = NULL;
>       char *scratch;
>   
> @@ -3772,10 +3840,13 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
>       }
>   
>       /*
> -     * TODO: load a vdso, which would also contain the signal trampolines.
> -     * Otherwise, allocate a private page to hold them.
> +     * Load a vdso if available, which will amongst other things contain the
> +     * signal trampolines.  Otherwise, allocate a separate page for them.
>        */
> -    if (TARGET_ARCH_HAS_SIGTRAMP_PAGE) {
> +    const VdsoImageInfo *vdso = vdso_image_info();

Declare in prologue? Otherwise,

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>

> +    if (vdso) {
> +        load_elf_vdso(&vdso_info, vdso);
> +    } else if (TARGET_ARCH_HAS_SIGTRAMP_PAGE) {
>           abi_long tramp_page = target_mmap(0, TARGET_PAGE_SIZE,
>                                             PROT_READ | PROT_WRITE,
>                                             MAP_PRIVATE | MAP_ANON, -1, 0);



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH v6 08/19] linux-user: Add gen-vdso tool
  2023-09-30  2:15 ` [PATCH v6 08/19] linux-user: Add gen-vdso tool Richard Henderson
@ 2023-10-03 13:00   ` Philippe Mathieu-Daudé
  2023-10-03 23:05     ` Richard Henderson
  0 siblings, 1 reply; 37+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-10-03 13:00 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: alex.bennee, laurent

On 30/9/23 04:15, Richard Henderson wrote:
> This tool will be used for post-processing the linked vdso image,
> turning it into something that is easy to include into elfload.c.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   linux-user/gen-vdso.c          | 223 ++++++++++++++++++++++++
>   linux-user/gen-vdso-elfn.c.inc | 307 +++++++++++++++++++++++++++++++++
>   linux-user/meson.build         |   6 +-
>   3 files changed, 535 insertions(+), 1 deletion(-)
>   create mode 100644 linux-user/gen-vdso.c
>   create mode 100644 linux-user/gen-vdso-elfn.c.inc


> +static void output_reloc(FILE *outf, void *buf, void *loc)
> +{
> +    fprintf(outf, "    0x%08lx,\n", (unsigned long)(loc - buf));

uintptr_t? Otherwise nice!

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>

> +}




^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH v6 19/19] build: Add update-linux-vdso makefile rule
  2023-09-30  2:15 ` [PATCH v6 19/19] build: Add update-linux-vdso makefile rule Richard Henderson
@ 2023-10-03 13:02   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 37+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-10-03 13:02 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: alex.bennee, laurent

On 30/9/23 04:15, Richard Henderson wrote:
> This is not ideal, since it requires all cross-compilers
> to be present rather than a simple subset.  But since it
> is only run manually, should be good enough for now.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   Makefile | 10 ++++++++++
>   1 file changed, 10 insertions(+)


> @@ -303,6 +310,9 @@ endif
>   	$(call print-help,distclean,Remove all generated files)
>   	$(call print-help,dist,Build a distributable tarball)
>   	@echo  ''
> +	@echo  'Linux-user targets:'
> +	$(call print-help,update-linux-vdso,Build linux-user vdso images)

Maybe amend '(require all cross-compilers to be present)'? Otherwise,

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>

> +	@echo  ''
>   	@echo  'Test targets:'
>   	$(call print-help,check,Run all tests (check-help for details))
>   	$(call print-help,bench,Run all benchmarks)



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH v6 18/19] linux-user/s390x: Add vdso
  2023-09-30  2:15 ` [PATCH v6 18/19] linux-user/s390x: Add vdso Richard Henderson
@ 2023-10-03 13:07   ` Philippe Mathieu-Daudé
  2023-10-03 23:01     ` Richard Henderson
  0 siblings, 1 reply; 37+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-10-03 13:07 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: alex.bennee, laurent

Hi Richard,

On 30/9/23 04:15, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   linux-user/s390x/vdso-asmoffset.h |   2 +
>   linux-user/elfload.c              |   2 +
>   linux-user/s390x/signal.c         |   4 +-
>   linux-user/s390x/Makefile.vdso    |  11 +++++
>   linux-user/s390x/meson.build      |   6 +++
>   linux-user/s390x/vdso.S           |  61 ++++++++++++++++++++++++++
>   linux-user/s390x/vdso.ld          |  69 ++++++++++++++++++++++++++++++
>   linux-user/s390x/vdso.so          | Bin 0 -> 3464 bytes
>   8 files changed, 152 insertions(+), 3 deletions(-)
>   create mode 100644 linux-user/s390x/vdso-asmoffset.h
>   create mode 100644 linux-user/s390x/Makefile.vdso
>   create mode 100644 linux-user/s390x/vdso.S
>   create mode 100644 linux-user/s390x/vdso.ld
>   create mode 100755 linux-user/s390x/vdso.so


> diff --git a/linux-user/s390x/Makefile.vdso b/linux-user/s390x/Makefile.vdso
> new file mode 100644
> index 0000000000..e82bf9e29f
> --- /dev/null
> +++ b/linux-user/s390x/Makefile.vdso
> @@ -0,0 +1,11 @@
> +include $(BUILD_DIR)/tests/tcg/s390x-linux-user/config-target.mak
> +
> +SUBDIR = $(SRC_PATH)/linux-user/s390x
> +VPATH += $(SUBDIR)
> +
> +all: $(SUBDIR)/vdso.so
> +
> +$(SUBDIR)/vdso.so: vdso.S vdso.ld vdso-asmoffset.h
> +	$(CC) -o $@ -nostdlib -shared -Wl,-h,linux-vdso64.so.1 \
> +	  -Wl,--build-id=sha1 -Wl,--hash-style=both \
> +	  -Wl,-T,$(SUBDIR)/vdso.ld $<
> diff --git a/linux-user/s390x/meson.build b/linux-user/s390x/meson.build
> index 0781ccea1d..a7a25ed9ce 100644
> --- a/linux-user/s390x/meson.build
> +++ b/linux-user/s390x/meson.build
> @@ -3,3 +3,9 @@ syscall_nr_generators += {
>                        arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ],
>                        output: '@BASENAME@_nr.h')
>   }
> +
> +vdso_inc = gen_vdso.process('vdso.so', extra_args: [
> +                                '-s', '__kernel_sigreturn',
> +                                '-r', '__kernel_rt_sigreturn'
> +                            ])
> +linux_user_ss.add(when: 'TARGET_S390X', if_true: vdso_inc)
> diff --git a/linux-user/s390x/vdso.S b/linux-user/s390x/vdso.S
> new file mode 100644
> index 0000000000..3332492477
> --- /dev/null
> +++ b/linux-user/s390x/vdso.S
> @@ -0,0 +1,61 @@
> +/*
> + * s390x linux replacement vdso.
> + *
> + * Copyright 2023 Linaro, Ltd.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#include <asm/unistd.h>
> +#include "vdso-asmoffset.h"
> +
> +.macro endf name
> +	.globl	\name
> +	.type	\name, @function
> +	.size	\name, . - \name
> +.endm
> +
> +.macro raw_syscall n
> +        .ifne	\n < 0x100
> +	svc	\n
> +	.else
> +	lghi	%r1, \n
> +	svc	0
> +        .endif
> +.endm
> +
> +.macro vdso_syscall name, nr
> +\name:
> +	.cfi_startproc
> +	aghi	%r15, -(STACK_FRAME_OVERHEAD + 16)
> +	.cfi_adjust_cfa_offset STACK_FRAME_OVERHEAD + 16
> +	stg	%r14, STACK_FRAME_OVERHEAD(%r15)
> +	.cfi_rel_offset %r14, STACK_FRAME_OVERHEAD
> +	raw_syscall \nr
> +	lg	%r14, STACK_FRAME_OVERHEAD(%r15)
> +	aghi	%r15, STACK_FRAME_OVERHEAD + 16
> +	.cfi_restore %r14
> +	.cfi_adjust_cfa_offset -(STACK_FRAME_OVERHEAD + 16)
> +	br	%r14
> +	.cfi_endproc
> +endf	\name
> +.endm
> +
> +vdso_syscall __kernel_gettimeofday, __NR_gettimeofday
> +vdso_syscall __kernel_clock_gettime, __NR_clock_gettime
> +vdso_syscall __kernel_clock_getres, __NR_clock_getres
> +vdso_syscall __kernel_getcpu, __NR_getcpu
> +
> +/*
> + * TODO unwind info, though we're ok without it.
> + * The kernel supplies bogus empty unwind info, and it is likely ignored
> + * by all users.  Without it we get the fallback signal frame handling.
> + */
> +
> +__kernel_sigreturn:
> +	raw_syscall __NR_sigreturn
> +endf	__kernel_sigreturn
> +
> +__kernel_rt_sigreturn:
> +	raw_syscall __NR_rt_sigreturn
> +endf	__kernel_rt_sigreturn
> diff --git a/linux-user/s390x/vdso.ld b/linux-user/s390x/vdso.ld
> new file mode 100644
> index 0000000000..2a30ff382a
> --- /dev/null
> +++ b/linux-user/s390x/vdso.ld
> @@ -0,0 +1,69 @@
> +/*
> + * Linker script for linux x86-64 replacement vdso.
> + *
> + * Copyright 2023 Linaro, Ltd.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +VERSION {
> +        LINUX_2.6.29 {
> +        global:
> +                __kernel_gettimeofday;
> +                __kernel_clock_gettime;
> +                __kernel_clock_getres;
> +                __kernel_getcpu;
> +                __kernel_restart_syscall;

Where is __kernel_restart_syscall defined?

> +                __kernel_rt_sigreturn;
> +                __kernel_sigreturn;
> +        local: *;
> +        };
> +}



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH v6 18/19] linux-user/s390x: Add vdso
  2023-10-03 13:07   ` Philippe Mathieu-Daudé
@ 2023-10-03 23:01     ` Richard Henderson
  2023-10-05 16:14       ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 37+ messages in thread
From: Richard Henderson @ 2023-10-03 23:01 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, qemu-devel; +Cc: alex.bennee, laurent

On 10/3/23 06:07, Philippe Mathieu-Daudé wrote:
>> +++ b/linux-user/s390x/vdso.ld
>> @@ -0,0 +1,69 @@
>> +/*
>> + * Linker script for linux x86-64 replacement vdso.
>> + *
>> + * Copyright 2023 Linaro, Ltd.
>> + *
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + */
>> +
>> +VERSION {
>> +        LINUX_2.6.29 {
>> +        global:
>> +                __kernel_gettimeofday;
>> +                __kernel_clock_gettime;
>> +                __kernel_clock_getres;
>> +                __kernel_getcpu;
>> +                __kernel_restart_syscall;
> 
> Where is __kernel_restart_syscall defined?

It isn't, and I guess isn't needed for qemu (we have QEMU_ERESTARTSYS).
I'm not sure why it's an exported symbol for the s390x vdso for the kernel, even if they 
do require some user-space code.

Anyway, I'll remove the symbol here.


r~


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH v6 08/19] linux-user: Add gen-vdso tool
  2023-10-03 13:00   ` Philippe Mathieu-Daudé
@ 2023-10-03 23:05     ` Richard Henderson
  2023-10-05 16:25       ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 37+ messages in thread
From: Richard Henderson @ 2023-10-03 23:05 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, qemu-devel; +Cc: alex.bennee, laurent

On 10/3/23 06:00, Philippe Mathieu-Daudé wrote:
> On 30/9/23 04:15, Richard Henderson wrote:
>> This tool will be used for post-processing the linked vdso image,
>> turning it into something that is easy to include into elfload.c.
>>
>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
>> ---
>>   linux-user/gen-vdso.c          | 223 ++++++++++++++++++++++++
>>   linux-user/gen-vdso-elfn.c.inc | 307 +++++++++++++++++++++++++++++++++
>>   linux-user/meson.build         |   6 +-
>>   3 files changed, 535 insertions(+), 1 deletion(-)
>>   create mode 100644 linux-user/gen-vdso.c
>>   create mode 100644 linux-user/gen-vdso-elfn.c.inc
> 
> 
>> +static void output_reloc(FILE *outf, void *buf, void *loc)
>> +{
>> +    fprintf(outf, "    0x%08lx,\n", (unsigned long)(loc - buf));
> 
> uintptr_t? Otherwise nice!

uintptr_t would require more complex printf.

Actually, I should just use %tx for the ptrdiff_t one gets from pointer subtraction.


r~


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH v6 18/19] linux-user/s390x: Add vdso
  2023-10-03 23:01     ` Richard Henderson
@ 2023-10-05 16:14       ` Philippe Mathieu-Daudé
  2023-10-06  7:30         ` Thomas Huth
  0 siblings, 1 reply; 37+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-10-05 16:14 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: alex.bennee, laurent, David Hildenbrand, Thomas Huth

On 4/10/23 01:01, Richard Henderson wrote:
> On 10/3/23 06:07, Philippe Mathieu-Daudé wrote:
>>> +++ b/linux-user/s390x/vdso.ld
>>> @@ -0,0 +1,69 @@
>>> +/*
>>> + * Linker script for linux x86-64 replacement vdso.
>>> + *
>>> + * Copyright 2023 Linaro, Ltd.
>>> + *
>>> + * SPDX-License-Identifier: GPL-2.0-or-later
>>> + */
>>> +
>>> +VERSION {
>>> +        LINUX_2.6.29 {
>>> +        global:
>>> +                __kernel_gettimeofday;
>>> +                __kernel_clock_gettime;
>>> +                __kernel_clock_getres;
>>> +                __kernel_getcpu;
>>> +                __kernel_restart_syscall;
>>
>> Where is __kernel_restart_syscall defined?
> 
> It isn't, and I guess isn't needed for qemu (we have QEMU_ERESTARTSYS).
> I'm not sure why it's an exported symbol for the s390x vdso for the 
> kernel, even if they do require some user-space code.
> 
> Anyway, I'll remove the symbol here.

OK.

I dare to give:

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>

But still I'm Cc'ing David / Thomas who better know s390x :)


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH v6 13/19] linux-user/hppa: Add vdso
  2023-09-30  2:15 ` [PATCH v6 13/19] linux-user/hppa: " Richard Henderson
@ 2023-10-05 16:16   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 37+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-10-05 16:16 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: alex.bennee, laurent, Helge Deller

On 30/9/23 04:15, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   linux-user/hppa/vdso-asmoffset.h |  12 +++
>   linux-user/elfload.c             |   2 +
>   linux-user/hppa/signal.c         |  24 +++--
>   linux-user/hppa/Makefile.vdso    |  11 +++
>   linux-user/hppa/meson.build      |   5 +
>   linux-user/hppa/vdso.S           | 165 +++++++++++++++++++++++++++++++
>   linux-user/hppa/vdso.ld          |  77 +++++++++++++++
>   linux-user/hppa/vdso.so          | Bin 0 -> 2104 bytes
>   8 files changed, 286 insertions(+), 10 deletions(-)
>   create mode 100644 linux-user/hppa/vdso-asmoffset.h
>   create mode 100644 linux-user/hppa/Makefile.vdso
>   create mode 100644 linux-user/hppa/vdso.S
>   create mode 100644 linux-user/hppa/vdso.ld
>   create mode 100755 linux-user/hppa/vdso.so

The overall LGTM, so:

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>

Cc'ing Helge who have better knowledge of HPPA.

> diff --git a/linux-user/hppa/vdso-asmoffset.h b/linux-user/hppa/vdso-asmoffset.h
> new file mode 100644
> index 0000000000..c8b40c0332
> --- /dev/null
> +++ b/linux-user/hppa/vdso-asmoffset.h
> @@ -0,0 +1,12 @@
> +#define sizeof_rt_sigframe              584
> +#define offsetof_sigcontext             160
> +#define offsetof_sigcontext_gr          0x4
> +#define offsetof_sigcontext_fr          0x88
> +#define offsetof_sigcontext_iaoq        0x190
> +#define offsetof_sigcontext_sar         0x198
> +
> +/* arch/parisc/include/asm/rt_sigframe.h */
> +#define SIGFRAME                        64
> +#define FUNCTIONCALLFRAME               48
> +#define PARISC_RT_SIGFRAME_SIZE32 \
> +    (((sizeof_rt_sigframe) + FUNCTIONCALLFRAME + SIGFRAME) & -SIGFRAME)
> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
> index a65401f8d5..ccf8a1dc78 100644
> --- a/linux-user/elfload.c
> +++ b/linux-user/elfload.c
> @@ -1921,6 +1921,8 @@ static inline void init_thread(struct target_pt_regs *regs,
>   #define STACK_GROWS_DOWN 0
>   #define STACK_ALIGNMENT  64
>   
> +#define VDSO_HEADER "vdso.c.inc"
> +
>   static inline void init_thread(struct target_pt_regs *regs,
>                                  struct image_info *infop)
>   {
> diff --git a/linux-user/hppa/signal.c b/linux-user/hppa/signal.c
> index bda6e54655..741dac79b6 100644
> --- a/linux-user/hppa/signal.c
> +++ b/linux-user/hppa/signal.c
> @@ -21,6 +21,7 @@
>   #include "user-internals.h"
>   #include "signal-common.h"
>   #include "linux-user/trace.h"
> +#include "vdso-asmoffset.h"
>   
>   struct target_sigcontext {
>       abi_ulong sc_flags;
> @@ -47,6 +48,19 @@ struct target_rt_sigframe {
>       /* hidden location of upper halves of pa2.0 64-bit gregs */
>   };
>   
> +QEMU_BUILD_BUG_ON(sizeof(struct target_rt_sigframe) != sizeof_rt_sigframe);
> +QEMU_BUILD_BUG_ON(offsetof(struct target_rt_sigframe, uc.tuc_mcontext)
> +                  != offsetof_sigcontext);
> +QEMU_BUILD_BUG_ON(offsetof(struct target_sigcontext, sc_gr)
> +                  != offsetof_sigcontext_gr);
> +QEMU_BUILD_BUG_ON(offsetof(struct target_sigcontext, sc_fr)
> +                  != offsetof_sigcontext_fr);
> +QEMU_BUILD_BUG_ON(offsetof(struct target_sigcontext, sc_iaoq)
> +                  != offsetof_sigcontext_iaoq);
> +QEMU_BUILD_BUG_ON(offsetof(struct target_sigcontext, sc_sar)
> +                  != offsetof_sigcontext_sar);
> +
> +
>   static void setup_sigcontext(struct target_sigcontext *sc, CPUArchState *env)
>   {
>       int i;
> @@ -91,16 +105,6 @@ static void restore_sigcontext(CPUArchState *env, struct target_sigcontext *sc)
>       __get_user(env->cr[CR_SAR], &sc->sc_sar);
>   }
>   
> -#if TARGET_ABI_BITS == 32
> -#define SIGFRAME                64
> -#define FUNCTIONCALLFRAME       48
> -#else
> -#define SIGFRAME                128
> -#define FUNCTIONCALLFRAME       96
> -#endif
> -#define PARISC_RT_SIGFRAME_SIZE32 \
> -    ((sizeof(struct target_rt_sigframe) + FUNCTIONCALLFRAME + SIGFRAME) & -SIGFRAME)
> -
>   void setup_rt_frame(int sig, struct target_sigaction *ka,
>                       target_siginfo_t *info,
>                       target_sigset_t *set, CPUArchState *env)
> diff --git a/linux-user/hppa/Makefile.vdso b/linux-user/hppa/Makefile.vdso
> new file mode 100644
> index 0000000000..f4537ae716
> --- /dev/null
> +++ b/linux-user/hppa/Makefile.vdso
> @@ -0,0 +1,11 @@
> +include $(BUILD_DIR)/tests/tcg/hppa-linux-user/config-target.mak
> +
> +SUBDIR = $(SRC_PATH)/linux-user/hppa
> +VPATH += $(SUBDIR)
> +
> +all: $(SUBDIR)/vdso.so
> +
> +$(SUBDIR)/vdso.so: vdso.S vdso.ld vdso-asmoffset.h
> +	$(CC) -o $@ -nostdlib -shared -Wl,-h,linux-vdso32.so.1 \
> +	  -Wl,--build-id=sha1 -Wl,--hash-style=both \
> +	  -Wl,-T,$(SUBDIR)/vdso.ld $<
> diff --git a/linux-user/hppa/meson.build b/linux-user/hppa/meson.build
> index 4709508a09..aa2d9a87a6 100644
> --- a/linux-user/hppa/meson.build
> +++ b/linux-user/hppa/meson.build
> @@ -3,3 +3,8 @@ syscall_nr_generators += {
>                       arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ],
>                       output: '@BASENAME@_nr.h')
>   }
> +
> +vdso_inc = gen_vdso.process('vdso.so',
> +                            extra_args: [ '-r', '__kernel_sigtramp_rt' ])
> +
> +linux_user_ss.add(when: 'TARGET_HPPA', if_true: vdso_inc)
> diff --git a/linux-user/hppa/vdso.S b/linux-user/hppa/vdso.S
> new file mode 100644
> index 0000000000..5be14d2f70
> --- /dev/null
> +++ b/linux-user/hppa/vdso.S
> @@ -0,0 +1,165 @@
> +/*
> + * hppa linux kernel vdso replacement.
> + *
> + * Copyright 2023 Linaro, Ltd.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#include <asm/unistd.h>
> +#include "vdso-asmoffset.h"
> +
> +	.text
> +
> +
> +/*
> + * arch/parisc/kernel/vdso32/sigtramp.S:
> + * Gdb expects the trampoline is on the stack and the pc is offset from
> + * a 64-byte boundary by 0, 4 or 5 instructions. Since the vdso trampoline
> + * is not on the stack, we need a new variant with different offsets and
> + * data to tell gdb where to find the signal context on the stack.
> + *
> + * Here we put the offset to the context data at the start of the trampoline
> + * region and offset the first trampoline by 2 instructions. Please do
> + * not change the trampoline as the code in gdb depends on the following
> + * instruction sequence exactly.
> + */
> +
> +/* arch/parisc/kernel/asm-offsets.c */
> +#define SIGFRAME_CONTEXT_REGS32 \
> +    (offsetof_sigcontext - PARISC_RT_SIGFRAME_SIZE32)
> +
> +        .align	64
> +        .word	SIGFRAME_CONTEXT_REGS32
> +
> +/*
> + * All that said, we can provide a proper unwind record, which means that
> + * GDB should not actually need the offset magic.
> + *
> + * The return address that arrived here, from the inner frame, is
> + * not marked as a signal frame and so the unwinder still tries to
> + * subtract 1 to examine the presumed call insn.  Thus we must
> + * extend the unwind info to a nop before the start.
> + */
> +
> +	.cfi_startproc simple
> +	.cfi_signal_frame
> +
> +	/* Compare pa32_fallback_frame_state from libgcc. */
> +
> +	/*
> +	 * Place the CFA at the start of sigcontext for convenience.
> +	 * The previous CFA will be restored from the saved stack pointer.
> +	 */
> +	.cfi_def_cfa	30, -PARISC_RT_SIGFRAME_SIZE32 + offsetof_sigcontext
> +
> +	/* Record save offset of general registers. */
> +	.cfi_offset	1, offsetof_sigcontext_gr + 1 * 4
> +	.cfi_offset	2, offsetof_sigcontext_gr + 2 * 4
> +	.cfi_offset	3, offsetof_sigcontext_gr + 3 * 4
> +	.cfi_offset	4, offsetof_sigcontext_gr + 4 * 4
> +	.cfi_offset	5, offsetof_sigcontext_gr + 5 * 4
> +	.cfi_offset	6, offsetof_sigcontext_gr + 6 * 4
> +	.cfi_offset	7, offsetof_sigcontext_gr + 7 * 4
> +	.cfi_offset	8, offsetof_sigcontext_gr + 8 * 4
> +	.cfi_offset	9, offsetof_sigcontext_gr + 9 * 4
> +	.cfi_offset	10, offsetof_sigcontext_gr + 10 * 4
> +	.cfi_offset	11, offsetof_sigcontext_gr + 11 * 4
> +	.cfi_offset	12, offsetof_sigcontext_gr + 12 * 4
> +	.cfi_offset	13, offsetof_sigcontext_gr + 13 * 4
> +	.cfi_offset	14, offsetof_sigcontext_gr + 14 * 4
> +	.cfi_offset	15, offsetof_sigcontext_gr + 15 * 4
> +	.cfi_offset	16, offsetof_sigcontext_gr + 16 * 4
> +	.cfi_offset	17, offsetof_sigcontext_gr + 17 * 4
> +	.cfi_offset	18, offsetof_sigcontext_gr + 18 * 4
> +	.cfi_offset	19, offsetof_sigcontext_gr + 19 * 4
> +	.cfi_offset	20, offsetof_sigcontext_gr + 20 * 4
> +	.cfi_offset	21, offsetof_sigcontext_gr + 21 * 4
> +	.cfi_offset	22, offsetof_sigcontext_gr + 22 * 4
> +	.cfi_offset	23, offsetof_sigcontext_gr + 23 * 4
> +	.cfi_offset	24, offsetof_sigcontext_gr + 24 * 4
> +	.cfi_offset	25, offsetof_sigcontext_gr + 25 * 4
> +	.cfi_offset	26, offsetof_sigcontext_gr + 26 * 4
> +	.cfi_offset	27, offsetof_sigcontext_gr + 27 * 4
> +	.cfi_offset	28, offsetof_sigcontext_gr + 28 * 4
> +	.cfi_offset	29, offsetof_sigcontext_gr + 29 * 4
> +	.cfi_offset	30, offsetof_sigcontext_gr + 30 * 4
> +	.cfi_offset	31, offsetof_sigcontext_gr + 31 * 4
> +
> +	/* Record save offset of fp registers, left and right halves. */
> +	.cfi_offset	32, offsetof_sigcontext_fr + 4 * 8
> +	.cfi_offset	33, offsetof_sigcontext_fr + 4 * 8 + 4
> +	.cfi_offset	34, offsetof_sigcontext_fr + 5 * 8
> +	.cfi_offset	35, offsetof_sigcontext_fr + 5 * 8 + 4
> +	.cfi_offset	36, offsetof_sigcontext_fr + 6 * 8
> +	.cfi_offset	37, offsetof_sigcontext_fr + 6 * 8 + 4
> +	.cfi_offset	38, offsetof_sigcontext_fr + 7 * 8
> +	.cfi_offset	39, offsetof_sigcontext_fr + 7 * 8 + 4
> +	.cfi_offset	40, offsetof_sigcontext_fr + 8 * 8
> +	.cfi_offset	41, offsetof_sigcontext_fr + 8 * 8 + 4
> +	.cfi_offset	42, offsetof_sigcontext_fr + 9 * 8
> +	.cfi_offset	43, offsetof_sigcontext_fr + 9 * 8 + 4
> +	.cfi_offset	44, offsetof_sigcontext_fr + 10 * 8
> +	.cfi_offset	45, offsetof_sigcontext_fr + 10 * 8 + 4
> +	.cfi_offset	46, offsetof_sigcontext_fr + 11 * 8
> +	.cfi_offset	47, offsetof_sigcontext_fr + 11 * 8 + 4
> +	.cfi_offset	48, offsetof_sigcontext_fr + 12 * 8
> +	.cfi_offset	49, offsetof_sigcontext_fr + 12 * 8 + 4
> +	.cfi_offset	50, offsetof_sigcontext_fr + 13 * 8
> +	.cfi_offset	51, offsetof_sigcontext_fr + 13 * 8 + 4
> +	.cfi_offset	52, offsetof_sigcontext_fr + 14 * 8
> +	.cfi_offset	53, offsetof_sigcontext_fr + 14 * 8 + 4
> +	.cfi_offset	54, offsetof_sigcontext_fr + 15 * 8
> +	.cfi_offset	55, offsetof_sigcontext_fr + 15 * 8 + 4
> +	.cfi_offset	56, offsetof_sigcontext_fr + 16 * 8
> +	.cfi_offset	57, offsetof_sigcontext_fr + 16 * 8 + 4
> +	.cfi_offset	58, offsetof_sigcontext_fr + 17 * 8
> +	.cfi_offset	59, offsetof_sigcontext_fr + 17 * 8 + 4
> +	.cfi_offset	60, offsetof_sigcontext_fr + 18 * 8
> +	.cfi_offset	61, offsetof_sigcontext_fr + 18 * 8 + 4
> +	.cfi_offset	62, offsetof_sigcontext_fr + 19 * 8
> +	.cfi_offset	63, offsetof_sigcontext_fr + 19 * 8 + 4
> +	.cfi_offset	64, offsetof_sigcontext_fr + 20 * 8
> +	.cfi_offset	65, offsetof_sigcontext_fr + 20 * 8 + 4
> +	.cfi_offset	66, offsetof_sigcontext_fr + 21 * 8
> +	.cfi_offset	67, offsetof_sigcontext_fr + 21 * 8 + 4
> +	.cfi_offset	68, offsetof_sigcontext_fr + 22 * 8
> +	.cfi_offset	69, offsetof_sigcontext_fr + 22 * 8 + 4
> +	.cfi_offset	70, offsetof_sigcontext_fr + 23 * 8
> +	.cfi_offset	71, offsetof_sigcontext_fr + 23 * 8 + 4
> +	.cfi_offset	72, offsetof_sigcontext_fr + 24 * 8
> +	.cfi_offset	73, offsetof_sigcontext_fr + 24 * 8 + 4
> +	.cfi_offset	74, offsetof_sigcontext_fr + 25 * 8
> +	.cfi_offset	75, offsetof_sigcontext_fr + 25 * 8 + 4
> +	.cfi_offset	76, offsetof_sigcontext_fr + 26 * 8
> +	.cfi_offset	77, offsetof_sigcontext_fr + 26 * 8 + 4
> +	.cfi_offset	78, offsetof_sigcontext_fr + 27 * 8
> +	.cfi_offset	79, offsetof_sigcontext_fr + 27 * 8 + 4
> +	.cfi_offset	80, offsetof_sigcontext_fr + 28 * 8
> +	.cfi_offset	81, offsetof_sigcontext_fr + 28 * 8 + 4
> +	.cfi_offset	82, offsetof_sigcontext_fr + 29 * 8
> +	.cfi_offset	83, offsetof_sigcontext_fr + 29 * 8 + 4
> +	.cfi_offset	84, offsetof_sigcontext_fr + 30 * 8
> +	.cfi_offset	85, offsetof_sigcontext_fr + 30 * 8 + 4
> +	.cfi_offset	86, offsetof_sigcontext_fr + 31 * 8
> +	.cfi_offset	87, offsetof_sigcontext_fr + 31 * 8 + 4
> +
> +	/* Record save offset of %sar */
> +	.cfi_offset	88, offsetof_sigcontext_sar
> +
> +	/* Record save offset of return address, iaoq[0]. */
> +	.cfi_return_column 89
> +	.cfi_offset	89, offsetof_sigcontext_iaoq
> +
> +	nop
> +
> +__kernel_sigtramp_rt:
> +	ldi	0, %r25
> +	ldi	__NR_rt_sigreturn, %r20
> +	be,l	0x100(%sr2, %r0), %sr0, %r31
> +	nop
> +
> +	.cfi_endproc
> +	.size	__kernel_sigtramp_rt, . - __kernel_sigtramp_rt
> +	.type	__kernel_sigtramp_rt, @function
> +	.globl	__kernel_sigtramp_rt
> diff --git a/linux-user/hppa/vdso.ld b/linux-user/hppa/vdso.ld
> new file mode 100644
> index 0000000000..b17ad974f3
> --- /dev/null
> +++ b/linux-user/hppa/vdso.ld
> @@ -0,0 +1,77 @@
> +/*
> + * Linker script for linux hppa vdso.
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +VERSION {
> +        /*
> +         * The kernel's vdso32.lds.S attempts to export
> +         *     __kernel_sigtramp_rt32
> +         *     __kernel_restart_syscall32
> +         * except that those symbols don't exist.  The actual symbols are
> +         *     __kernel_sigtramp_rt
> +         *     __kernel_restart_syscall
> +         * which means that nothing is exported at all.
> +         * QEMU handles syscall restart internally, so we don't
> +         * need to implement __kernel_restart_syscall at all.
> +         */
> +        LINUX_5.18 {
> +        local: *;
> +        };
> +}
> +
> +
> +PHDRS {
> +        phdr            PT_PHDR         FLAGS(4) PHDRS;
> +        load            PT_LOAD         FLAGS(7) FILEHDR PHDRS;
> +        dynamic         PT_DYNAMIC      FLAGS(4);
> +        note            PT_NOTE         FLAGS(4);
> +        eh_frame_hdr    PT_GNU_EH_FRAME;
> +}
> +
> +SECTIONS {
> +        . = SIZEOF_HEADERS;
> +
> +        /* The following, including the FILEHDRS and PHDRS, are modified
> +           when we relocate the binary.  We want them to be initially
> +           writable for the relocation; we'll force them read-only after.  */
> +        .note           : { *(.note*) }         :load :note
> +        .dynamic        : { *(.dynamic) }       :load :dynamic
> +        .dynsym         : { *(.dynsym) }        :load
> +        .data           : {
> +                /* There ought not be any real read-write data.
> +                   But since we manipulated the segment layout,
> +                   we have to put these sections somewhere.  */
> +                *(.data*)
> +                *(.sdata*)
> +                *(.got.plt) *(.got)
> +                *(.gnu.linkonce.d.*)
> +                *(.bss*)
> +                *(.dynbss*)
> +                *(.gnu.linkonce.b.*)
> +        }
> +
> +        .rodata         : { *(.rodata) }
> +        .hash           : { *(.hash) }
> +        .gnu.hash       : { *(.gnu.hash) }
> +        .dynstr         : { *(.dynstr) }
> +        .gnu.version    : { *(.gnu.version) }
> +        .gnu.version_d  : { *(.gnu.version_d) }
> +        .gnu.version_r  : { *(.gnu.version_r) }
> +        .eh_frame_hdr   : { *(.eh_frame_hdr) }  :load :eh_frame_hdr
> +        .eh_frame       : { *(.eh_frame) }      :load
> +
> +        .text           : { *(.text*) }         :load
> +}



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH v6 15/19] linux-user/loongarch64: Add vdso
  2023-09-30  2:15 ` [PATCH v6 15/19] linux-user/loongarch64: " Richard Henderson
@ 2023-10-05 16:18   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 37+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-10-05 16:18 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: alex.bennee, laurent, Song Gao

On 30/9/23 04:15, Richard Henderson wrote:
> Requires a relatively recent binutils version in order to avoid
> spurious R_LARCH_NONE relocations.  The presence of these relocs
> are diagnosed by our gen-vdso tool.
> 
> Tested-by: Song Gao <gaosong@loongson.cn>
> Reviewed-by: Song Gao <gaosong@loongson.cn>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   linux-user/loongarch64/vdso-asmoffset.h |   8 ++
>   linux-user/elfload.c                    |   2 +
>   linux-user/loongarch64/signal.c         |  17 +++-
>   linux-user/loongarch64/Makefile.vdso    |  11 ++
>   linux-user/loongarch64/meson.build      |   4 +
>   linux-user/loongarch64/vdso.S           | 130 ++++++++++++++++++++++++
>   linux-user/loongarch64/vdso.ld          |  73 +++++++++++++
>   linux-user/loongarch64/vdso.so          | Bin 0 -> 3560 bytes
>   linux-user/meson.build                  |   1 +
>   9 files changed, 245 insertions(+), 1 deletion(-)
>   create mode 100644 linux-user/loongarch64/vdso-asmoffset.h
>   create mode 100644 linux-user/loongarch64/Makefile.vdso
>   create mode 100644 linux-user/loongarch64/meson.build
>   create mode 100644 linux-user/loongarch64/vdso.S
>   create mode 100644 linux-user/loongarch64/vdso.ld
>   create mode 100755 linux-user/loongarch64/vdso.so

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH v6 14/19] linux-user/riscv: Add vdso
  2023-09-30  2:15 ` [PATCH v6 14/19] linux-user/riscv: " Richard Henderson
@ 2023-10-05 16:24   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 37+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-10-05 16:24 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: alex.bennee, laurent, Alistair Francis

On 30/9/23 04:15, Richard Henderson wrote:
> Acked-by: Alistair Francis <alistair.francis@wdc.com>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   linux-user/riscv/vdso-asmoffset.h |   9 ++
>   linux-user/elfload.c              |   2 +
>   linux-user/riscv/signal.c         |   8 ++
>   linux-user/meson.build            |   1 +
>   linux-user/riscv/Makefile.vdso    |  15 +++
>   linux-user/riscv/meson.build      |   7 ++
>   linux-user/riscv/vdso-32.so       | Bin 0 -> 2888 bytes
>   linux-user/riscv/vdso-64.so       | Bin 0 -> 3840 bytes
>   linux-user/riscv/vdso.S           | 186 ++++++++++++++++++++++++++++++
>   linux-user/riscv/vdso.ld          |  74 ++++++++++++
>   10 files changed, 302 insertions(+)
>   create mode 100644 linux-user/riscv/vdso-asmoffset.h
>   create mode 100644 linux-user/riscv/Makefile.vdso
>   create mode 100644 linux-user/riscv/meson.build
>   create mode 100755 linux-user/riscv/vdso-32.so
>   create mode 100755 linux-user/riscv/vdso-64.so
>   create mode 100644 linux-user/riscv/vdso.S
>   create mode 100644 linux-user/riscv/vdso.ld

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>

> diff --git a/linux-user/meson.build b/linux-user/meson.build
> index dd24389052..3ff3bc5bbc 100644
> --- a/linux-user/meson.build
> +++ b/linux-user/meson.build
> @@ -45,6 +45,7 @@ subdir('microblaze')
>   subdir('mips64')
>   subdir('mips')
>   subdir('ppc')
> +subdir('riscv')
>   subdir('s390x')
>   subdir('sh4')
>   subdir('sparc')

We should cover these directories in MAINTAINERS, likely in
the "$arch TCG CPUs" sections.


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH v6 08/19] linux-user: Add gen-vdso tool
  2023-10-03 23:05     ` Richard Henderson
@ 2023-10-05 16:25       ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 37+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-10-05 16:25 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: alex.bennee, laurent

On 4/10/23 01:05, Richard Henderson wrote:
> On 10/3/23 06:00, Philippe Mathieu-Daudé wrote:
>> On 30/9/23 04:15, Richard Henderson wrote:
>>> This tool will be used for post-processing the linked vdso image,
>>> turning it into something that is easy to include into elfload.c.
>>>
>>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
>>> ---
>>>   linux-user/gen-vdso.c          | 223 ++++++++++++++++++++++++
>>>   linux-user/gen-vdso-elfn.c.inc | 307 +++++++++++++++++++++++++++++++++
>>>   linux-user/meson.build         |   6 +-
>>>   3 files changed, 535 insertions(+), 1 deletion(-)
>>>   create mode 100644 linux-user/gen-vdso.c
>>>   create mode 100644 linux-user/gen-vdso-elfn.c.inc
>>
>>
>>> +static void output_reloc(FILE *outf, void *buf, void *loc)
>>> +{
>>> +    fprintf(outf, "    0x%08lx,\n", (unsigned long)(loc - buf));
>>
>> uintptr_t? Otherwise nice!
> 
> uintptr_t would require more complex printf.
> 
> Actually, I should just use %tx for the ptrdiff_t one gets from pointer 
> subtraction.

Right, this is the type I was thinking of.



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH v6 16/19] linux-user/ppc: Add vdso
  2023-09-30  2:15 ` [PATCH v6 16/19] linux-user/ppc: " Richard Henderson
@ 2023-10-05 16:35   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 37+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-10-05 16:35 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: alex.bennee, laurent, Cédric Le Goater,
	Daniel Henrique Barboza, Nicholas Piggin

On 30/9/23 04:15, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   linux-user/ppc/vdso-asmoffset.h |  20 +++
>   linux-user/elfload.c            |   8 ++
>   linux-user/ppc/signal.c         |  31 +++--
>   linux-user/gen-vdso-elfn.c.inc  |   7 +
>   linux-user/ppc/Makefile.vdso    |  20 +++
>   linux-user/ppc/meson.build      |  12 ++
>   linux-user/ppc/vdso-32.ld       |  70 ++++++++++
>   linux-user/ppc/vdso-32.so       | Bin 0 -> 3020 bytes
>   linux-user/ppc/vdso-64.ld       |  68 +++++++++
>   linux-user/ppc/vdso-64.so       | Bin 0 -> 3896 bytes
>   linux-user/ppc/vdso-64le.so     | Bin 0 -> 3896 bytes
>   linux-user/ppc/vdso.S           | 239 ++++++++++++++++++++++++++++++++
>   12 files changed, 467 insertions(+), 8 deletions(-)
>   create mode 100644 linux-user/ppc/vdso-asmoffset.h
>   create mode 100644 linux-user/ppc/Makefile.vdso
>   create mode 100644 linux-user/ppc/vdso-32.ld
>   create mode 100755 linux-user/ppc/vdso-32.so
>   create mode 100644 linux-user/ppc/vdso-64.ld
>   create mode 100755 linux-user/ppc/vdso-64.so
>   create mode 100755 linux-user/ppc/vdso-64le.so
>   create mode 100644 linux-user/ppc/vdso.S

Scratching my head for the CFA/CFI lines, so Cc'ing Nicholas, Daniel
and Cédric.

Do you mind adding a quick comment for the DT_PPC64_OPT change in
the description?

LGTM. To the best of my PPC knowledge,
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>

> diff --git a/linux-user/ppc/vdso-asmoffset.h b/linux-user/ppc/vdso-asmoffset.h
> new file mode 100644
> index 0000000000..6844c8c81c
> --- /dev/null
> +++ b/linux-user/ppc/vdso-asmoffset.h
> @@ -0,0 +1,20 @@
> +/*
> + * Size of dummy stack frame allocated when calling signal handler.
> + * See arch/powerpc/include/asm/ptrace.h.
> + */
> +#ifdef TARGET_ABI32
> +# define SIGNAL_FRAMESIZE                   64
> +#else
> +# define SIGNAL_FRAMESIZE                   128
> +#endif
> +
> +#ifdef TARGET_ABI32
> +# define offsetof_sigframe_mcontext         0x20
> +# define offsetof_rt_sigframe_mcontext      0x140
> +# define offsetof_mcontext_fregs            0xc0
> +# define offsetof_mcontext_vregs            0x1d0
> +#else
> +# define offsetof_rt_sigframe_mcontext      0xe8
> +# define offsetof_mcontext_fregs            0x180
> +# define offsetof_mcontext_vregs_ptr        0x288
> +#endif
> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
> index f41a57ebd5..4a2d21a1f9 100644
> --- a/linux-user/elfload.c
> +++ b/linux-user/elfload.c
> @@ -1187,6 +1187,14 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUPPCState *en
>   #define USE_ELF_CORE_DUMP
>   #define ELF_EXEC_PAGESIZE       4096
>   
> +#ifndef TARGET_PPC64
> +# define VDSO_HEADER  "vdso-32.c.inc"
> +#elif TARGET_BIG_ENDIAN
> +# define VDSO_HEADER  "vdso-64.c.inc"
> +#else
> +# define VDSO_HEADER  "vdso-64le.c.inc"
> +#endif
> +
>   #endif
>   
>   #ifdef TARGET_LOONGARCH64
> diff --git a/linux-user/ppc/signal.c b/linux-user/ppc/signal.c
> index a616f20efb..7e7302823b 100644
> --- a/linux-user/ppc/signal.c
> +++ b/linux-user/ppc/signal.c
> @@ -21,14 +21,7 @@
>   #include "user-internals.h"
>   #include "signal-common.h"
>   #include "linux-user/trace.h"
> -
> -/* Size of dummy stack frame allocated when calling signal handler.
> -   See arch/powerpc/include/asm/ptrace.h.  */
> -#if defined(TARGET_PPC64)
> -#define SIGNAL_FRAMESIZE 128
> -#else
> -#define SIGNAL_FRAMESIZE 64
> -#endif
> +#include "vdso-asmoffset.h"
>   
>   /* See arch/powerpc/include/asm/ucontext.h.  Only used for 32-bit PPC;
>      on 64-bit PPC, sigcontext and mcontext are one and the same.  */
> @@ -73,6 +66,16 @@ struct target_mcontext {
>   #endif
>   };
>   
> +QEMU_BUILD_BUG_ON(offsetof(struct target_mcontext, mc_fregs)
> +                  != offsetof_mcontext_fregs);
> +#if defined(TARGET_PPC64)
> +QEMU_BUILD_BUG_ON(offsetof(struct target_mcontext, v_regs)
> +                  != offsetof_mcontext_vregs_ptr);
> +#else
> +QEMU_BUILD_BUG_ON(offsetof(struct target_mcontext, mc_vregs)
> +                  != offsetof_mcontext_vregs);
> +#endif
> +
>   /* See arch/powerpc/include/asm/sigcontext.h.  */
>   struct target_sigcontext {
>       target_ulong _unused[4];
> @@ -161,6 +164,7 @@ struct target_ucontext {
>   #endif
>   };
>   
> +#if !defined(TARGET_PPC64)
>   /* See arch/powerpc/kernel/signal_32.c.  */
>   struct target_sigframe {
>       struct target_sigcontext sctx;
> @@ -168,6 +172,10 @@ struct target_sigframe {
>       int32_t abigap[56];
>   };
>   
> +QEMU_BUILD_BUG_ON(offsetof(struct target_sigframe, mctx)
> +                  != offsetof_sigframe_mcontext);
> +#endif
> +
>   #if defined(TARGET_PPC64)
>   
>   #define TARGET_TRAMP_SIZE 6
> @@ -184,6 +192,10 @@ struct target_rt_sigframe {
>       char abigap[288];
>   } __attribute__((aligned(16)));
>   
> +QEMU_BUILD_BUG_ON(offsetof(struct target_rt_sigframe,
> +                           uc.tuc_sigcontext.mcontext)
> +                  != offsetof_rt_sigframe_mcontext);
> +
>   #else
>   
>   struct target_rt_sigframe {
> @@ -192,6 +204,9 @@ struct target_rt_sigframe {
>       int32_t abigap[56];
>   };
>   
> +QEMU_BUILD_BUG_ON(offsetof(struct target_rt_sigframe, uc.tuc_mcontext)
> +                  != offsetof_rt_sigframe_mcontext);
> +
>   #endif
>   
>   #if defined(TARGET_PPC64)
> diff --git a/linux-user/gen-vdso-elfn.c.inc b/linux-user/gen-vdso-elfn.c.inc
> index 7034c36d5e..95856eb839 100644
> --- a/linux-user/gen-vdso-elfn.c.inc
> +++ b/linux-user/gen-vdso-elfn.c.inc
> @@ -273,7 +273,14 @@ static void elfN(process)(FILE *outf, void *buf, bool need_bswap)
>                   errors++;
>                   break;
>   
> +            case PT_LOPROC + 3:
> +                if (ehdr->e_machine == EM_PPC64) {
> +                    break;  /* DT_PPC64_OPT: integer bitmask */
> +                }
> +                goto do_default;
> +
>               default:
> +            do_default:
>                   /* This is probably something target specific. */
>                   fprintf(stderr, "VDSO has unknown DYNAMIC entry (%lx)\n",
>                           (unsigned long)tag);
> diff --git a/linux-user/ppc/Makefile.vdso b/linux-user/ppc/Makefile.vdso
> new file mode 100644
> index 0000000000..3ca3c6b83e
> --- /dev/null
> +++ b/linux-user/ppc/Makefile.vdso
> @@ -0,0 +1,20 @@
> +include $(BUILD_DIR)/tests/tcg/ppc64-linux-user/config-target.mak
> +
> +SUBDIR = $(SRC_PATH)/linux-user/ppc
> +VPATH += $(SUBDIR)
> +
> +all: $(SUBDIR)/vdso-32.so $(SUBDIR)/vdso-64.so $(SUBDIR)/vdso-64le.so
> +
> +LDFLAGS32 = -nostdlib -shared -Wl,-T,$(SUBDIR)/vdso-32.ld \
> +            -Wl,-h,linux-vdso32.so.1 -Wl,--hash-style=both -Wl,--build-id=sha1
> +LDFLAGS64 = -nostdlib -shared -Wl,-T,$(SUBDIR)/vdso-64.ld \
> +            -Wl,-h,linux-vdso64.so.1 -Wl,--hash-style=both -Wl,--build-id=sha1
> +
> +$(SUBDIR)/vdso-32.so: vdso.S vdso-32.ld vdso-asmoffset.h
> +	$(CC) -o $@ $(LDFLAGS32) -m32 $<
> +
> +$(SUBDIR)/vdso-64.so: vdso.S vdso-64.ld vdso-asmoffset.h
> +	$(CC) -o $@ $(LDFLAGS64) -mbig-endian $<
> +
> +$(SUBDIR)/vdso-64le.so: vdso.S vdso-64.ld vdso-asmoffset.h
> +	$(CC) -o $@ $(LDFLAGS64) -mlittle-endian $<
> diff --git a/linux-user/ppc/meson.build b/linux-user/ppc/meson.build
> index 19fead7bc8..80cacae396 100644
> --- a/linux-user/ppc/meson.build
> +++ b/linux-user/ppc/meson.build
> @@ -3,3 +3,15 @@ syscall_nr_generators += {
>                      arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ],
>                      output: '@BASENAME@_nr.h')
>   }
> +
> +vdso_32_inc = gen_vdso.process('vdso-32.so', extra_args: [
> +                                   '-s', '__kernel_sigtramp32',
> +                                   '-r', '__kernel_sigtramp_rt32'
> +                               ])
> +linux_user_ss.add(when: 'TARGET_PPC', if_true: vdso_32_inc)
> +
> +vdso_64_inc = gen_vdso.process('vdso-64.so',
> +                               extra_args: ['-r', '__kernel_sigtramp_rt64'])
> +vdso_64le_inc = gen_vdso.process('vdso-64le.so',
> +                                 extra_args: ['-r', '__kernel_sigtramp_rt64'])
> +linux_user_ss.add(when: 'TARGET_PPC64', if_true: [vdso_64_inc, vdso_64le_inc])
> diff --git a/linux-user/ppc/vdso-32.ld b/linux-user/ppc/vdso-32.ld
> new file mode 100644
> index 0000000000..6962696540
> --- /dev/null
> +++ b/linux-user/ppc/vdso-32.ld
> @@ -0,0 +1,70 @@
> +/*
> + * Linker script for linux powerpc64 replacement vdso.
> + *
> + * Copyright 2023 Linaro, Ltd.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +VERSION {
> +        LINUX_2.6.15 {
> +        global:
> +                __kernel_gettimeofday;
> +                __kernel_clock_gettime;
> +                __kernel_clock_gettime64;
> +                __kernel_clock_getres;
> +                __kernel_time;
> +                __kernel_sync_dicache;
> +                __kernel_sigtramp32;
> +                __kernel_sigtramp_rt32;
> +                __kernel_getcpu;
> +        local: *;
> +        };
> +}
> +
> +PHDRS {
> +        phdr            PT_PHDR         FLAGS(4) PHDRS;
> +        load            PT_LOAD         FLAGS(7) FILEHDR PHDRS; /* FLAGS=RWX */
> +        dynamic         PT_DYNAMIC      FLAGS(4);
> +        eh_frame_hdr    PT_GNU_EH_FRAME;
> +        note            PT_NOTE         FLAGS(4);
> +}
> +
> +SECTIONS {
> +        . = SIZEOF_HEADERS;
> +
> +        /*
> +         * The following, including the FILEHDRS and PHDRS, are modified
> +         * when we relocate the binary.  We want them to be initially
> +         * writable for the relocation; we'll force them read-only after.
> +         */
> +        .note           : { *(.note*) }         :load :note
> +        .dynamic        : { *(.dynamic) }       :load :dynamic
> +        .dynsym         : { *(.dynsym) }        :load
> +        .data           : {
> +                /*
> +                 * There ought not be any real read-write data.
> +                 * But since we manipulated the segment layout,
> +                 * we have to put these sections somewhere.
> +                 */
> +                *(.data*)
> +                *(.sdata*)
> +                *(.got.plt) *(.got)
> +                *(.gnu.linkonce.d.*)
> +                *(.bss*)
> +                *(.dynbss*)
> +                *(.gnu.linkonce.b.*)
> +        }
> +
> +        .rodata         : { *(.rodata*) }
> +        .hash           : { *(.hash) }
> +        .gnu.hash       : { *(.gnu.hash) }
> +        .dynstr         : { *(.dynstr) }
> +        .gnu.version    : { *(.gnu.version) }
> +        .gnu.version_d  : { *(.gnu.version_d) }
> +        .gnu.version_r  : { *(.gnu.version_r) }
> +        .eh_frame_hdr   : { *(.eh_frame_hdr) }  :load :eh_frame_hdr
> +        .eh_frame       : { *(.eh_frame) }      :load
> +
> +        .text           : { *(.text*) }         :load
> +}
> diff --git a/linux-user/ppc/vdso-32.so b/linux-user/ppc/vdso-32.so
> new file mode 100755
> index 0000000000000000000000000000000000000000..b19baafb0d38e15b4a24def5c44a6d684714be45
> GIT binary patch
> literal 3020
> zcmbtWeQXp}5P#e27f_&s6{-a-h*%I#XbYl%a{b~XN2zU*57F)Q?%F%r-of3qv<2Um
> z1QRhNq7Vb7G1Z^}LI}~u5YuQA2$G0I6M`g?$RC*a2Z<OJNd)U}-tD{FYGX7`J3I56
> znK%3P?abU-)!rH-!w@NQi2~@_P%gwcukw|PVv!|EM822|oDGIA#RJfpGi}!E0hzMr
> zCt2j!nKNL#<KRB%%xZlg@qL{TuA6BV)8S**`B`3e@NDSJPCq|~YgO$AvFGf0kL&f&
> zyz@uCzSg_H@|!C=N(SMZ1RhGR$taJG{PC+0842Jl$YDr4qtOjH9{eqM0ysZ9GIAGb
> z2O;kPXF%Qp?uY(=$&FiIN0PiLV8}PHg+j<&8#ltwXQus^perIV@)MLQ_;F?_|1qrR
> zGtujtf%$y&`dz^Jz?pV_ytAwe4*xXZ%MQ%<*5rc1=fT7}pAi%19|z85U=!B@*9*=S
> z?;mFd<~3|*J$r8Bfmwl!+_Sb#<+!>mczErej|%2|`C~)=mL~agwClu?S594u8bd8b
> zfqm~5&l#xt?zrckFwM4LED~%tTZ4&2xFZ;C3HW-_R)2fc-==+Im}9|s+KLqZ?VV}N
> z`O;`qswL%VN4zKEHv?h6&mVGx$HT3On6G2I8B3IvI)ZI8Z0+GlXZM1xKs;Jj>W)X<
> zi-dPg?S@Tese6fg(PEqipU>a__~g{z#Mf5vdoKWUZ*VQ^Q#EqTFWv`YACsyTqsX-k
> zI@c7=-M9w15NZkZbI`dKgwb0sGIx87qCC~YY(u<p6w=Fn=)2Xmx4r>^l^odTqROT|
> zL54*cl3XuS=5ET`McKWS(?hx4G;Sx2@1hBvl$W51ahepP$vY^2J5iLTMCiT_Drl$s
> z+i2=Gnii(Q5IxXJ54KQIkfsM{hMyj4riXpx*-ABAsJM=1*3v95J+hW&uck+9XigP9
> zRzW2zY3`>M%^R}l@lPz8f5xH(A6w)ewCITsEn0ZmqD7}HDm`gY*$Iovk6E<%1B;d%
> zwdl$BELu8X(NphO^mM;P%igwV`C*Gzyk*fdhb(&bO^ep;x2X12i`MV8sIJeV=k7|X
> zzay#P7fFq`ByG4U>G>ZdZM-3A({)LkuSwc+RniNWC2jpm(u)@*y>vm6c}`N(uq5A*
> zq~<e{{DYDLrzHhXN@_VKsr9I&(14_Hzoc!4CAA%r)P6ux$9_qXeNvr2zf)r`)UDt`
> zQJH5nL0Kw9Z53W-ZJ#KHe%qn{mevh-S{D=3x^YnJyxz`tl5MuWlXcu?EaDl#4Xp|W
> z>Kz-~@oI*$AOB2TZwh3x1TN<*oID>uY6dgrnZbCNufRMzSnF5U)QoWr+L-4Kh<`U!
> zygidL)hxn#dtRv-$NBOQ#(P%#g~I#An&kSVE@r^2_6tAnw+yVvp1CWrZN8tLsdd2D
> z9k>OLF&kLV;9g+PqvH=E{(=J^ho5^+&*aa53mxmPAfETD*WUo<^G{;4YICh;-I_{F
> z8~pB>)vL{#de6FQb9Gg{FjslkS9rYU`kI=C>PEBCQ{k;PM-Lq5C>=EiQ<HDhwA2I6
> zIo(o`JUX2-a_s5+pC;!&Ok*M3@t%%^uNg8COUjVeBGE)pxC1>AUq{%l6vRUM5<cN>
> zjdZ$0zIZ5UPsEazu3#)4jz&fSGa%f-klBKn9yCJ%L~115iC}jEZ{gol5kmEEA-_Ln
> zt`kjMBTO^F+y^Mv)b~;!bh{T+O>%wD19N?&hPmHV&z-j8xW+jj*HtN)G4gR;tJ>y1
> z(8O`f%fZ}_$jAMudUPc)?}JIlEyefGZD5YW38>!n0{=Cx!nSeTaFW$G70ilwPfTl(
> zZv+x?+~=y-rvmGIu(MBW)Zbrl4JMgKVCqbHe@y5<^}L)9eX4qUy7DA1Iu3i+aXc@W
> zjo~rkcm(ra@lLpJRqqBIar!w}@;+_i?_Xm8fWJ9af7_C0mVP#<ITvyH9jr;`BN!ZU
> Nxt{~?)j^Od?oZyq_3Z!v
> 
> literal 0
> HcmV?d00001
> 
> diff --git a/linux-user/ppc/vdso-64.ld b/linux-user/ppc/vdso-64.ld
> new file mode 100644
> index 0000000000..a55c65ed54
> --- /dev/null
> +++ b/linux-user/ppc/vdso-64.ld
> @@ -0,0 +1,68 @@
> +/*
> + * Linker script for linux powerpc64 replacement vdso.
> + *
> + * Copyright 2023 Linaro, Ltd.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +VERSION {
> +        LINUX_2.6.15 {
> +        global:
> +                __kernel_gettimeofday;
> +                __kernel_clock_gettime;
> +                __kernel_clock_getres;
> +                __kernel_sync_dicache;
> +                __kernel_sigtramp_rt64;
> +                __kernel_getcpu;
> +                __kernel_time;
> +        local: *;
> +        };
> +}
> +
> +PHDRS {
> +        phdr            PT_PHDR         FLAGS(4) PHDRS;
> +        load            PT_LOAD         FLAGS(7) FILEHDR PHDRS; /* FLAGS=RWX */
> +        dynamic         PT_DYNAMIC      FLAGS(4);
> +        eh_frame_hdr    PT_GNU_EH_FRAME;
> +        note            PT_NOTE         FLAGS(4);
> +}
> +
> +SECTIONS {
> +        . = SIZEOF_HEADERS;
> +
> +        /*
> +         * The following, including the FILEHDRS and PHDRS, are modified
> +         * when we relocate the binary.  We want them to be initially
> +         * writable for the relocation; we'll force them read-only after.
> +         */
> +        .note           : { *(.note*) }         :load :note
> +        .dynamic        : { *(.dynamic) }       :load :dynamic
> +        .dynsym         : { *(.dynsym) }        :load
> +        .data           : {
> +                /*
> +                 * There ought not be any real read-write data.
> +                 * But since we manipulated the segment layout,
> +                 * we have to put these sections somewhere.
> +                 */
> +                *(.data*)
> +                *(.sdata*)
> +                *(.got.plt) *(.got)
> +                *(.gnu.linkonce.d.*)
> +                *(.bss*)
> +                *(.dynbss*)
> +                *(.gnu.linkonce.b.*)
> +        }
> +
> +        .rodata         : { *(.rodata*) }
> +        .hash           : { *(.hash) }
> +        .gnu.hash       : { *(.gnu.hash) }
> +        .dynstr         : { *(.dynstr) }
> +        .gnu.version    : { *(.gnu.version) }
> +        .gnu.version_d  : { *(.gnu.version_d) }
> +        .gnu.version_r  : { *(.gnu.version_r) }
> +        .eh_frame_hdr   : { *(.eh_frame_hdr) }  :load :eh_frame_hdr
> +        .eh_frame       : { *(.eh_frame) }      :load
> +
> +        .text           : { *(.text*) }         :load
> +}
> diff --git a/linux-user/ppc/vdso-64.so b/linux-user/ppc/vdso-64.so
> new file mode 100755
> index 0000000000000000000000000000000000000000..913c831b3819fc09912b9b31f7fbe9ee311ae12f
> GIT binary patch
> literal 3896
> zcmc&%U2GIp6uvXF?G`9-4}zctEm9FtR=`p#KiZ|+@?%?S0V#-Xx4YZ!(ssA*ZflFk
> zEC~;qnApU`81<o$n4mGH3Ml?k-$;l_A9*mbFC-+ASfip3Vm)Why|dG`O-y|7wlm*%
> zzH`sLGxzVz+6_&OrfCSbSYjD+kKlOf*uS7wS+$}>)CnmTqg{%ZkNv1|DMDif%Nj))
> z+SG@i^||i;3HB)Dr!rAf{TX@o{{yAc6^gQ0?s{t>&Ub_T#VA&??jrT0FQi60`-@Rj
> zsW^=~W-02{u9k!1`mJ|PoV_YnU0i;>+kW%g%Rg34j;I)dMT)<!km9je{d7-H|MeRo
> z+UFQ?^qpeeR5r~47E`x5pKbAx!UYPQdB8?3Wjm0bp8k_<-xwj<x7ijn)?`ny?R#74
> z{|5x55aryl|6TO}WFPS87d-kI5Ys;^+Y2F2eLbGkPNzp7R{=B+hDSfGbgDn((XS}I
> z3~{+fAMw;jdWuXM`*}pL(D+ge71GtbI=0g{GMZc3C*-FcKv!v}C<~T^D$gpLe5Kd6
> z#ot={-B0`Fk&ctUqz6B!h`oBIa_wkn@2T@cKfE8jEyCfRcqSF^4R^<Lxny5F-4%-r
> z7u0BPI@+Usv&flvwxD7Y(f)ygP3;w|>~Ja?jwPd!Xu_)|yK|XHUw=50tEm>f$<)Bm
> zhQU}iT~i&%rURQq)1H=t?cvRVn!u(l_(C{3Gyh04_|H7HgXWg@7wuWzH#9P)F#O@G
> z?<pUGI72t1!rF#F>mSG5r1i5A@q6@CBgZL2cDzmahJr>#IW^>HSl^5xuOk7=O}b&d
> z{aCS{D&8=mz9TQdu)#bD*2~~K0VOX%>2dH6L)j3_dlBXj!h!)P&%wehEXu&*7eMv{
> zq+v-4?&yQ1y|AnY?mPy|ldvKIcXh+vT~HB+l`&Wqg?l>T-UtMbLgNvrY=zbP;Jy}E
> z(+pKjaQ{=Vb}u}z2iEO|2Y12xMtG<J9uC2VdI;=<M}n}i4mMr3Ve>aOJo>c_)nD1L
> z<x3lCzOdo3&uyr^WW(d1*|7Cf8@64vVfzIecAU52iBD{J@?)D`R2cN`zaowzmJ8YJ
> zU-L>y>6*NdEzCxQ+{bKG$W~@!LO#uGT*x+N6GHB1HYwx*W>Z2QWR^GNGt5Q|d5GDl
> zA={aa8S*f*aYG(qHetwTnN1q<D6=U;KF2I?%IBGlm@>?4)RY~}#!MMuHg3vJW)r52
> zGMhAIjM<ba<IM7w>|!=z$!=z&mP{}kvt*LlxFwG<o3LaLvq?+#GMlnwAG5qqrkK6v
> z!-1_8q9ue2ttBrik>B$0-wWIb6u4NZImL8v8y}K}bk2f@gtM>_+P#%fS8+OzvKMvy
> zr{d-n$3oHP5Md=4mF1paoVT<O>#O|a<}b&Ey2}4<9@Dxy6KCcdtgp^Z&QqTDRld{t
> zoIO}y<-HR1ysl2?Hx~bCM(1we;LJ7-)b?!cubLyjtoNM%=T!UD-&T+A&0nn^T|W=i
> z@ABy5svUZd6CVAF(rLWj@aQx0phq83^~*&#bhsthyr&+|Z2Ue6H|!2KwgsCT!n;Fl
> zGtXgf(wK4LyXm4hFU*o!{!Kn`JDQnF+-@9M1hT_@xkx8sF2k76ES1j1MIbhuiu5I;
> z4#B#Jkz7Osx>EyzL?oMFJ(po+FrLXK)2SIoI3@z|M7RqxRXm)CVNGp`KrTL%Q$zTl
> zp#odb-@kg@seS40&#IzcX#RCsjYRD$y-)T2brGlD?StafzH)NgdbIU-q3U1nbB*Gf
> zidW}`8@~ee&3I`Yw;C0F9%yvyv%AngJ;!#uN|ZzOug?vQbTsOBb8716r*Wvo@6uaE
> z@#olf&zTU~>e(ERjwfTM$EW*u@;inobibdSV7%$~C3`RSKdl@pUY}PQ#S-*;`&adx
> zbLLR-cQziYW89ub=lyAo=s555ccHGINB4h2#Vd4w$FS_4+m1;KxhP(rlN!yu4pit}
> ze<wZhY8~qHRHJArir4*-OkBTLQ8oVr3+6gR`fWtNGpXqJr}am<z&p0&S7qKGid@o)
> TLT~?o+8puo)jWvPbH)D+{oljD
> 
> literal 0
> HcmV?d00001
> 
> diff --git a/linux-user/ppc/vdso-64le.so b/linux-user/ppc/vdso-64le.so
> new file mode 100755
> index 0000000000000000000000000000000000000000..258a03b807c4eca23547d978c16d1ad5ebd08bc5
> GIT binary patch
> literal 3896
> zcmcgvU2GIp6uvXl(gKCvgCJ-@i&R9Eg<`3dAMMg@`LQjvfc%I~x4YZ!(ssA*ZflFk
> zEC~;qkl2J5V|XYgCTNVQf{Oq3!NkOv^pOV>`(nZa2_*`eAl7sC-m^P9tkJ~8vza;H
> z{q8yU%)K-BoV!kQYl~?Zg2fU`M7||NqwZ*!&lbcrh*G>uQ7PsiU4mDm?)K_sdN9`I
> z+K%Wljf<%%-N{<$r!vu);$`%>UM)4xn&Wl+oDP%U6}lDC%M~qHYqM-D!Uy%ZUR|U8
> zSiAieW1ofBj`scH*7la@tux=QtI3pvuGN0C{_N=+7s+)Y-B4avDjSdBAUUGk_;WTv
> z`n+zJQUm3xZqxdcjM2iN%u`CduQk86Wx9=SgBoVlAG2!w3H{)=bz2W7W_0^ao|xPD
> zf5bkFB}IietG|m19ebbVFM9ZM$b+~(tIcvMpzY6l?7KBTsd=6*y>^Ow%40vG`R_E(
> z-`P^lk9q9HN$fzO*ETncgrGHMKjQh_Qa8n?*z|sBDC(y+b8l4#O8w=co7&Vzc5g(s
> zT;6-_ht(&#4$F6k6Th5$EnF2CUtK+N;pFby{&#*7w%r#=#v}c9ZzP?L4MY+>;oxYV
> z4fQ8NecV@sPDWCB7KaE84&~c4UcQwYjfd=TEEEhy-E6EkoeT~P+R1c%o#>Cnhep;7
> zhf|6AI$tW`s}-%g+V>x{H~Q**wVQB0rsszg&R_kmZ#!zz{-XWLdxzG-#QwLxx67!H
> z<eXB%sIs=u9-uWpi?<D^e?(n}PLgeob&8S^zfo0TWI3`AqfMjkznZt(i-t{Pc*TUK
> zu8aV~0rLb{uRzIhD18~`9D}k^C?A2jFTuQFm_Gy+X;_egg-NJ<5#%610v5&Lt^ruw
> z4@>&s?xV0Y2Fs#wPcPit162`N9)=YmxUU=T4}$*)v>b-&4p_Md9%zSEZBWw+4?Yd6
> zcf&)wV9ic=cn7R)fk&F*(EzM#0^fF6?}rVIQ2Vt58^3bku`eB{`@(@upF2?hnFEi1
> z>OjLK2cG!Efz2N~u;n8MwqA5#+XV-n{Lq1?K5%I6xHi9{9!H(sZ?dgy)vKj*R%L{2
> zS7=PgJqnEr*`d&ckk2SIDP*TYQ$p@lXj;g93e5<)U!ja4pH*ngkOveRH{?NuCJcE<
> zp-Dp?R%ptQ&nYx*$Ri5P81i|AGNyb%p)ph13XPkxOQ8u<1{In#Ww%08rVJ@GZOX7h
> zGp39vl(A%wLSvTfRcPFjQH3Tf8B=J|l1CMqvSgn^)0XU4XvUHQ3S~-UT%psn&)bD)
> zz|SmDEi&ylUHCT__8EDb1umX^aEPw=G>7<a#lpS8^~-H!;jYNwJNAl&nT6|$yU)Vx
> z6s4r&5eqXI*DZIKh1rSgS0P`Pt7C<HxhPg|EX<r-rwZ-o<?4DNKVOu%ldA5tT=|^s
> zY5GQybx`&6&hb~EeX;to7I~@{-ukjx^WOT^p?Pn8>CwEm9v#=bx9*(Le6c!6&vQpT
> zvIB?O{cXFNFlXcW#BSbcw{-g3n(du|&cZzGE*b?HKUXfib)iUU`8V|-7pSn5<iccW
> z;Y*DUq=Vh4(@CYHjN*xOMEJs^@!&u#lm%#uI+zX$UvGTK7Y(MOiccpMGaN~#Vu^S`
> z!ww5yBx?6yrHa_mFj{g;_|lP)G_Lf2mns~B>N@WGtnj{MU88wclqcM>5*t+Wc^mTn
> zWzFYbeGJK+Gq~2#cS>hNj?ep?^=0fMA%EH%d`_X7NU{+x;yFI&1J-O$wj|tUy%jmy
> znjD|=2I~fLLgDe*kJo|vZ{pdM{W-s|4rIOW^w+f5uE%D7K2Nje^E2DiT-~x88?&zX
> zoUd3f(#HJ!9EbG*?5DFfw>ht|=K1qC!t>{6p!`73#Qxs@HT*w@?Rnj}O<%FwpYtT^
> z3=gawy#6P&KYfEFoWEGNDmr)fuAe)0&Ikej-&>>OFGQ{qFP=Yte{_cCwMCed-}T}8
> WQjSr;8y}D^=0BklzBu&{{(k}Ee8OG;
> 
> literal 0
> HcmV?d00001
> 
> diff --git a/linux-user/ppc/vdso.S b/linux-user/ppc/vdso.S
> new file mode 100644
> index 0000000000..689010db13
> --- /dev/null
> +++ b/linux-user/ppc/vdso.S
> @@ -0,0 +1,239 @@
> +/*
> + * PowerPC linux replacement vdso.
> + *
> + * Copyright 2023 Linaro, Ltd.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#include <asm/unistd.h>
> +#include <asm/errno.h>
> +
> +#ifndef _ARCH_PPC64
> +# define TARGET_ABI32
> +#endif
> +#include "vdso-asmoffset.h"
> +
> +
> +	.text
> +
> +.macro endf name
> +	.globl	\name
> +	.size	\name, .-\name
> +	/* For PPC64, functions have special linkage; we export pointers. */
> +#ifndef _ARCH_PPC64
> +	.type	\name, @function
> +#endif
> +.endm
> +
> +.macro raw_syscall nr
> +	addi	0, 0, \nr
> +	sc
> +.endm
> +
> +.macro vdso_syscall name, nr
> +\name:
> +	raw_syscall \nr
> +	blr
> +endf	\name
> +.endm
> +
> +	.cfi_startproc
> +
> +vdso_syscall __kernel_gettimeofday, __NR_gettimeofday
> +vdso_syscall __kernel_clock_gettime, __NR_clock_gettime
> +vdso_syscall __kernel_clock_getres, __NR_clock_getres
> +vdso_syscall __kernel_getcpu, __NR_getcpu
> +vdso_syscall __kernel_time, __NR_time
> +
> +#ifdef __NR_clock_gettime64
> +vdso_syscall __kernel_clock_gettime64, __NR_clock_gettime64
> +#endif
> +
> +__kernel_sync_dicache:
> +	/* qemu does not need to flush caches */
> +	blr
> +endf	__kernel_sync_dicache
> +
> +	.cfi_endproc
> +
> +/*
> + * TODO: __kernel_get_tbfreq
> + * This is probably a constant for QEMU.
> + */
> +
> +/*
> + * Start the unwind info at least one instruction before the signal
> + * trampoline, because the unwinder will assume we are returning
> + * after a call site.
> + */
> +
> +	.cfi_startproc simple
> +	.cfi_signal_frame
> +
> +#ifdef _ARCH_PPC64
> +# define __kernel_sigtramp_rt  __kernel_sigtramp_rt64
> +# define sizeof_reg	8
> +#else
> +# define __kernel_sigtramp_rt  __kernel_sigtramp_rt32
> +# define sizeof_reg	4
> +#endif
> +#define sizeof_freg	8
> +#define sizeof_vreg	16
> +
> +	.cfi_def_cfa	1, SIGNAL_FRAMESIZE + offsetof_rt_sigframe_mcontext
> +
> +	/* Return address */
> +	.cfi_return_column 67
> +	.cfi_offset	67, 32 * sizeof_reg		/* nip */
> +
> +	/* Integer registers */
> +	.cfi_offset	0, 0 * sizeof_reg
> +	.cfi_offset	1, 1 * sizeof_reg
> +	.cfi_offset	2, 2 * sizeof_reg
> +	.cfi_offset	3, 3 * sizeof_reg
> +	.cfi_offset	4, 4 * sizeof_reg
> +	.cfi_offset	5, 5 * sizeof_reg
> +	.cfi_offset	6, 6 * sizeof_reg
> +	.cfi_offset	7, 7 * sizeof_reg
> +	.cfi_offset	8, 8 * sizeof_reg
> +	.cfi_offset	9, 9 * sizeof_reg
> +	.cfi_offset	10, 10 * sizeof_reg
> +	.cfi_offset	11, 11 * sizeof_reg
> +	.cfi_offset	12, 12 * sizeof_reg
> +	.cfi_offset	13, 13 * sizeof_reg
> +	.cfi_offset	14, 14 * sizeof_reg
> +	.cfi_offset	15, 15 * sizeof_reg
> +	.cfi_offset	16, 16 * sizeof_reg
> +	.cfi_offset	17, 17 * sizeof_reg
> +	.cfi_offset	18, 18 * sizeof_reg
> +	.cfi_offset	19, 19 * sizeof_reg
> +	.cfi_offset	20, 20 * sizeof_reg
> +	.cfi_offset	21, 21 * sizeof_reg
> +	.cfi_offset	22, 22 * sizeof_reg
> +	.cfi_offset	23, 23 * sizeof_reg
> +	.cfi_offset	24, 24 * sizeof_reg
> +	.cfi_offset	25, 25 * sizeof_reg
> +	.cfi_offset	26, 26 * sizeof_reg
> +	.cfi_offset	27, 27 * sizeof_reg
> +	.cfi_offset	28, 28 * sizeof_reg
> +	.cfi_offset	29, 29 * sizeof_reg
> +	.cfi_offset	30, 30 * sizeof_reg
> +	.cfi_offset	31, 31 * sizeof_reg
> +	.cfi_offset	65, 36 * sizeof_reg		/* lr */
> +	.cfi_offset	70, 38 * sizeof_reg		/* ccr */
> +
> +	/* Floating point registers */
> +	.cfi_offset	32, offsetof_mcontext_fregs
> +	.cfi_offset	33, offsetof_mcontext_fregs + 1 * sizeof_freg
> +	.cfi_offset	34, offsetof_mcontext_fregs + 2 * sizeof_freg
> +	.cfi_offset	35, offsetof_mcontext_fregs + 3 * sizeof_freg
> +	.cfi_offset	36, offsetof_mcontext_fregs + 4 * sizeof_freg
> +	.cfi_offset	37, offsetof_mcontext_fregs + 5 * sizeof_freg
> +	.cfi_offset	38, offsetof_mcontext_fregs + 6 * sizeof_freg
> +	.cfi_offset	39, offsetof_mcontext_fregs + 7 * sizeof_freg
> +	.cfi_offset	40, offsetof_mcontext_fregs + 8 * sizeof_freg
> +	.cfi_offset	41, offsetof_mcontext_fregs + 9 * sizeof_freg
> +	.cfi_offset	42, offsetof_mcontext_fregs + 10 * sizeof_freg
> +	.cfi_offset	43, offsetof_mcontext_fregs + 11 * sizeof_freg
> +	.cfi_offset	44, offsetof_mcontext_fregs + 12 * sizeof_freg
> +	.cfi_offset	45, offsetof_mcontext_fregs + 13 * sizeof_freg
> +	.cfi_offset	46, offsetof_mcontext_fregs + 14 * sizeof_freg
> +	.cfi_offset	47, offsetof_mcontext_fregs + 15 * sizeof_freg
> +	.cfi_offset	48, offsetof_mcontext_fregs + 16 * sizeof_freg
> +	.cfi_offset	49, offsetof_mcontext_fregs + 17 * sizeof_freg
> +	.cfi_offset	50, offsetof_mcontext_fregs + 18 * sizeof_freg
> +	.cfi_offset	51, offsetof_mcontext_fregs + 19 * sizeof_freg
> +	.cfi_offset	52, offsetof_mcontext_fregs + 20 * sizeof_freg
> +	.cfi_offset	53, offsetof_mcontext_fregs + 21 * sizeof_freg
> +	.cfi_offset	54, offsetof_mcontext_fregs + 22 * sizeof_freg
> +	.cfi_offset	55, offsetof_mcontext_fregs + 23 * sizeof_freg
> +	.cfi_offset	56, offsetof_mcontext_fregs + 24 * sizeof_freg
> +	.cfi_offset	57, offsetof_mcontext_fregs + 25 * sizeof_freg
> +	.cfi_offset	58, offsetof_mcontext_fregs + 26 * sizeof_freg
> +	.cfi_offset	59, offsetof_mcontext_fregs + 27 * sizeof_freg
> +	.cfi_offset	60, offsetof_mcontext_fregs + 28 * sizeof_freg
> +	.cfi_offset	61, offsetof_mcontext_fregs + 29 * sizeof_freg
> +	.cfi_offset	62, offsetof_mcontext_fregs + 30 * sizeof_freg
> +	.cfi_offset	63, offsetof_mcontext_fregs + 31 * sizeof_freg
> +
> +	/*
> +	 * Unlike the kernel, unconditionally represent the Altivec/VSX regs.
> +	 * The space within the stack frame is always available, and most of
> +	 * our supported processors have them enabled.  The only complication
> +	 * for PPC64 is the misalignment, so that we have to use indirection.
> +	 */
> +.macro	save_vreg_ofs reg, ofs
> +#ifdef _ARCH_PPC64
> +	/*
> +	 * vreg = *(cfa + offsetof(v_regs)) + ofs
> +         *
> +         * The CFA is input to the expression on the stack, so:
> +	 * DW_CFA_expression reg, length (7),
> +         *   DW_OP_plus_uconst (0x23), vreg_ptr, DW_OP_deref (0x06),
> +	 *   DW_OP_plus_uconst (0x23), ofs
> +	 */
> +	.cfi_escape 0x10, 77 + \reg, 7, 0x23, (offsetof_mcontext_vregs_ptr & 0x7f) + 0x80, offsetof_mcontext_vregs_ptr >> 7, 0x06, 0x23, (\ofs & 0x7f) | 0x80, \ofs >> 7
> +#else
> +	.cfi_offset 77 + \reg, offsetof_mcontext_vregs + \ofs
> +#endif
> +.endm
> +
> +.macro	save_vreg reg
> +	save_vreg_ofs \reg, (\reg * sizeof_vreg)
> +.endm
> +
> +	save_vreg   0
> +	save_vreg   1
> +	save_vreg   2
> +	save_vreg   3
> +	save_vreg   4
> +	save_vreg   5
> +	save_vreg   6
> +	save_vreg   7
> +	save_vreg   8
> +	save_vreg   9
> +	save_vreg  10
> +	save_vreg  11
> +	save_vreg  12
> +	save_vreg  13
> +	save_vreg  14
> +	save_vreg  15
> +	save_vreg  16
> +	save_vreg  17
> +	save_vreg  18
> +	save_vreg  19
> +	save_vreg  20
> +	save_vreg  21
> +	save_vreg  22
> +	save_vreg  23
> +	save_vreg  24
> +	save_vreg  25
> +	save_vreg  26
> +	save_vreg  27
> +	save_vreg  28
> +	save_vreg  29
> +	save_vreg  30
> +	save_vreg  31
> +	save_vreg  32
> +	save_vreg_ofs 33, (32 * sizeof_vreg + 12)
> +
> +	nop
> +
> +__kernel_sigtramp_rt:
> +	raw_syscall __NR_rt_sigreturn
> +endf	__kernel_sigtramp_rt
> +
> +#ifndef _ARCH_PPC64
> +	/*
> +	 * The non-rt sigreturn has the same layout at a different offset.
> +	 * Move the CFA and leave all othe other descriptions the same.
> +	 */
> +	.cfi_def_cfa	1, SIGNAL_FRAMESIZE + offsetof_sigframe_mcontext
> +	nop
> +__kernel_sigtramp32:
> +	raw_syscall __NR_sigreturn
> +endf	__kernel_sigtramp32
> +#endif
> +
> +	.cfi_endproc



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH v6 09/19] linux-user/i386: Add vdso
  2023-09-30  2:15 ` [PATCH v6 09/19] linux-user/i386: Add vdso Richard Henderson
@ 2023-10-05 16:42   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 37+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-10-05 16:42 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: alex.bennee, laurent, Paolo Bonzini

On 30/9/23 04:15, Richard Henderson wrote:
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1267
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   linux-user/i386/vdso-asmoffset.h |   6 ++
>   linux-user/elfload.c             |  19 +++-
>   linux-user/i386/signal.c         |  11 +++
>   linux-user/i386/Makefile.vdso    |  11 +++
>   linux-user/i386/meson.build      |   7 ++
>   linux-user/i386/vdso.S           | 143 +++++++++++++++++++++++++++++++
>   linux-user/i386/vdso.ld          |  76 ++++++++++++++++
>   linux-user/i386/vdso.so          | Bin 0 -> 2672 bytes
>   8 files changed, 271 insertions(+), 2 deletions(-)
>   create mode 100644 linux-user/i386/vdso-asmoffset.h
>   create mode 100644 linux-user/i386/Makefile.vdso
>   create mode 100644 linux-user/i386/vdso.S
>   create mode 100644 linux-user/i386/vdso.ld
>   create mode 100755 linux-user/i386/vdso.so

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>

> diff --git a/linux-user/i386/vdso-asmoffset.h b/linux-user/i386/vdso-asmoffset.h
> new file mode 100644
> index 0000000000..4e5ee0dd49
> --- /dev/null
> +++ b/linux-user/i386/vdso-asmoffset.h
> @@ -0,0 +1,6 @@
> +/*
> + * offsetof(struct sigframe, sc.eip)
> + * offsetof(struct rt_sigframe, uc.tuc_mcontext.eip)
> + */
> +#define SIGFRAME_SIGCONTEXT_eip      64
> +#define RT_SIGFRAME_SIGCONTEXT_eip  220
> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
> index 9c97d14b7e..314ae7cacf 100644
> --- a/linux-user/elfload.c
> +++ b/linux-user/elfload.c
> @@ -305,12 +305,27 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *en
>       (*regs)[15] = tswapreg(env->regs[R_ESP]);
>       (*regs)[16] = tswapreg(env->segs[R_SS].selector & 0xffff);
>   }
> -#endif
> +
> +/*
> + * i386 is the only target which supplies AT_SYSINFO for the vdso.
> + * All others only supply AT_SYSINFO_EHDR.
> + */
> +#define DLINFO_ARCH_ITEMS (vdso_info != NULL)
> +#define ARCH_DLINFO                                     \
> +    do {                                                \
> +        if (vdso_info) {                                \
> +            NEW_AUX_ENT(AT_SYSINFO, vdso_info->entry);  \
> +        }                                               \
> +    } while (0)
> +
> +#define VDSO_HEADER "vdso.c.inc"
> +
> +#endif /* TARGET_X86_64 */
>   
>   #define USE_ELF_CORE_DUMP
>   #define ELF_EXEC_PAGESIZE       4096
>   
> -#endif
> +#endif /* TARGET_I386 */
>   
>   #ifdef TARGET_ARM
>   
> diff --git a/linux-user/i386/signal.c b/linux-user/i386/signal.c
> index 60fa07d6f9..bc5d45302e 100644
> --- a/linux-user/i386/signal.c
> +++ b/linux-user/i386/signal.c
> @@ -214,6 +214,17 @@ struct rt_sigframe {
>   };
>   #define TARGET_RT_SIGFRAME_FXSAVE_OFFSET (                                 \
>       offsetof(struct rt_sigframe, fpstate) + TARGET_FPSTATE_FXSAVE_OFFSET)
> +
> +/*
> + * Verify that vdso-asmoffset.h constants match.
> + */
> +#include "i386/vdso-asmoffset.h"
> +
> +QEMU_BUILD_BUG_ON(offsetof(struct sigframe, sc.eip)
> +                  != SIGFRAME_SIGCONTEXT_eip);
> +QEMU_BUILD_BUG_ON(offsetof(struct rt_sigframe, uc.tuc_mcontext.eip)
> +                  != RT_SIGFRAME_SIGCONTEXT_eip);
> +
>   #else
>   
>   struct rt_sigframe {
> diff --git a/linux-user/i386/Makefile.vdso b/linux-user/i386/Makefile.vdso
> new file mode 100644
> index 0000000000..95bc616f6d
> --- /dev/null
> +++ b/linux-user/i386/Makefile.vdso
> @@ -0,0 +1,11 @@
> +include $(BUILD_DIR)/tests/tcg/i386-linux-user/config-target.mak
> +
> +SUBDIR = $(SRC_PATH)/linux-user/i386
> +VPATH += $(SUBDIR)
> +
> +all: $(SUBDIR)/vdso.so
> +
> +$(SUBDIR)/vdso.so: vdso.S vdso.ld vdso-asmoffset.h
> +	$(CC) -o $@ -m32 -nostdlib -shared -Wl,-h,linux-gate.so.1 \
> +	  -Wl,--build-id=sha1 -Wl,--hash-style=both \
> +	  -Wl,-T,$(SUBDIR)/vdso.ld $<
> diff --git a/linux-user/i386/meson.build b/linux-user/i386/meson.build
> index ee523019a5..d42fc6cbc9 100644
> --- a/linux-user/i386/meson.build
> +++ b/linux-user/i386/meson.build
> @@ -3,3 +3,10 @@ syscall_nr_generators += {
>                       arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ],
>                       output: '@BASENAME@_nr.h')
>   }
> +
> +vdso_inc = gen_vdso.process('vdso.so', extra_args: [
> +                                '-s', '__kernel_sigreturn',
> +                                '-r', '__kernel_rt_sigreturn'
> +                            ])
> +
> +linux_user_ss.add(when: 'TARGET_I386', if_true: vdso_inc)
> diff --git a/linux-user/i386/vdso.S b/linux-user/i386/vdso.S
> new file mode 100644
> index 0000000000..e7a1f333a1
> --- /dev/null
> +++ b/linux-user/i386/vdso.S
> @@ -0,0 +1,143 @@
> +/*
> + * i386 linux replacement vdso.
> + *
> + * Copyright 2023 Linaro, Ltd.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#include <asm/unistd.h>
> +#include "vdso-asmoffset.h"
> +
> +.macro endf name
> +	.globl	\name
> +	.type	\name, @function
> +	.size	\name, . - \name
> +.endm
> +
> +.macro vdso_syscall1 name, nr
> +\name:
> +	.cfi_startproc
> +	mov	%ebx, %edx
> +	.cfi_register %ebx, %edx
> +	mov	4(%esp), %ebx
> +	mov	$\nr, %eax
> +	int	$0x80
> +	mov	%edx, %ebx
> +	ret
> +	.cfi_endproc
> +endf	\name
> +.endm
> +
> +.macro vdso_syscall2 name, nr
> +\name:
> +	.cfi_startproc
> +	mov	%ebx, %edx
> +	.cfi_register %ebx, %edx
> +	mov	4(%esp), %ebx
> +	mov	8(%esp), %ecx
> +	mov	$\nr, %eax
> +	int	$0x80
> +	mov	%edx, %ebx
> +	ret
> +	.cfi_endproc
> +endf	\name
> +.endm
> +
> +.macro vdso_syscall3 name, nr
> +\name:
> +	.cfi_startproc
> +	push	%ebx
> +	.cfi_adjust_cfa_offset 4
> +	.cfi_rel_offset %ebx, 0
> +	mov	8(%esp), %ebx
> +	mov	12(%esp), %ecx
> +	mov	16(%esp), %edx
> +	mov	$\nr, %eax
> +	int	$0x80
> +	pop	%ebx
> +	.cfi_adjust_cfa_offset -4
> +	.cfi_restore %ebx
> +	ret
> +	.cfi_endproc
> +endf	\name
> +.endm
> +
> +__kernel_vsyscall:
> +	.cfi_startproc
> +	int	$0x80
> +	ret
> +	.cfi_endproc
> +endf	__kernel_vsyscall
> +
> +vdso_syscall2 __vdso_clock_gettime, __NR_clock_gettime
> +vdso_syscall2 __vdso_clock_gettime64, __NR_clock_gettime64
> +vdso_syscall2 __vdso_clock_getres, __NR_clock_getres
> +vdso_syscall2 __vdso_gettimeofday, __NR_gettimeofday
> +vdso_syscall1 __vdso_time, __NR_time
> +vdso_syscall3 __vdso_getcpu, __NR_gettimeofday
> +
> +/*
> + * Signal return handlers.
> + */
> +
> +	.cfi_startproc simple
> +	.cfi_signal_frame
> +
> +/*
> + * For convenience, put the cfa just above eip in sigcontext, and count
> + * offsets backward from there.  Re-compute the cfa in the two contexts
> + * we have for signal unwinding.  This is far simpler than the
> + * DW_CFA_expression form that the kernel uses, and is equally correct.
> + */
> +
> +	.cfi_def_cfa	%esp, SIGFRAME_SIGCONTEXT_eip + 4
> +
> +	.cfi_offset	%eip, -4
> +			/* err, -8 */
> +			/* trapno, -12 */
> +	.cfi_offset	%eax, -16
> +	.cfi_offset	%ecx, -20
> +	.cfi_offset	%edx, -24
> +	.cfi_offset	%ebx, -28
> +	.cfi_offset	%esp, -32
> +	.cfi_offset	%ebp, -36
> +	.cfi_offset	%esi, -40
> +	.cfi_offset	%edi, -44
> +
> +/*
> + * While this frame is marked as a signal frame, that only applies to how
> + * the return address is handled for the outer frame.  The return address
> + * that arrived here, from the inner frame, is not marked as a signal frame
> + * and so the unwinder still tries to subtract 1 to examine the presumed
> + * call insn.  Thus we must extend the unwind info to a nop before the start.
> + */
> +	nop
> +
> +__kernel_sigreturn:
> +	popl	%eax	/* pop sig */
> +	.cfi_adjust_cfa_offset -4
> +	movl	$__NR_sigreturn, %eax
> +	int	$0x80
> +endf	__kernel_sigreturn
> +
> +	.cfi_def_cfa_offset RT_SIGFRAME_SIGCONTEXT_eip + 4
> +	nop
> +
> +__kernel_rt_sigreturn:
> +	movl	$__NR_rt_sigreturn, %eax
> +	int	$0x80
> +endf	__kernel_rt_sigreturn
> +
> +	.cfi_endproc
> +
> +/*
> + * TODO: Add elf notes.  E.g.
> + *
> + * #include <linux/elfnote.h>
> + * ELFNOTE_START(Linux, 0, "a")
> + *   .long LINUX_VERSION_CODE
> + * ELFNOTE_END
> + *
> + * but what version number would we set for QEMU?
> + */
> diff --git a/linux-user/i386/vdso.ld b/linux-user/i386/vdso.ld
> new file mode 100644
> index 0000000000..326b7a8f98
> --- /dev/null
> +++ b/linux-user/i386/vdso.ld
> @@ -0,0 +1,76 @@
> +/*
> + * Linker script for linux i386 replacement vdso.
> + *
> + * Copyright 2023 Linaro, Ltd.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +ENTRY(__kernel_vsyscall)
> +
> +VERSION {
> +        LINUX_2.6 {
> +        global:
> +                __vdso_clock_gettime;
> +                __vdso_gettimeofday;
> +                __vdso_time;
> +                __vdso_clock_getres;
> +                __vdso_clock_gettime64;
> +                __vdso_getcpu;
> +        };
> +
> +        LINUX_2.5 {
> +        global:
> +                __kernel_vsyscall;
> +                __kernel_sigreturn;
> +                __kernel_rt_sigreturn;
> +        local: *;
> +        };
> +}
> +
> +PHDRS {
> +        phdr            PT_PHDR         FLAGS(4) PHDRS;
> +        load            PT_LOAD         FLAGS(7) FILEHDR PHDRS; /* FLAGS=RWX */
> +        dynamic         PT_DYNAMIC      FLAGS(4);
> +        eh_frame_hdr    PT_GNU_EH_FRAME;
> +        note            PT_NOTE         FLAGS(4);
> +}
> +
> +SECTIONS {
> +        . = SIZEOF_HEADERS;
> +
> +        /*
> +         * The following, including the FILEHDRS and PHDRS, are modified
> +         * when we relocate the binary.  We want them to be initially
> +         * writable for the relocation; we'll force them read-only after.
> +         */
> +        .note           : { *(.note*) }         :load :note
> +        .dynamic        : { *(.dynamic) }       :load :dynamic
> +        .dynsym         : { *(.dynsym) }        :load
> +        .data           : {
> +                /*
> +                 * There ought not be any real read-write data.
> +                 * But since we manipulated the segment layout,
> +                 * we have to put these sections somewhere.
> +                 */
> +                *(.data*)
> +                *(.sdata*)
> +                *(.got.plt) *(.got)
> +                *(.gnu.linkonce.d.*)
> +                *(.bss*)
> +                *(.dynbss*)
> +                *(.gnu.linkonce.b.*)
> +        }
> +
> +        .rodata         : { *(.rodata*) }
> +        .hash           : { *(.hash) }
> +        .gnu.hash       : { *(.gnu.hash) }
> +        .dynstr         : { *(.dynstr) }
> +        .gnu.version    : { *(.gnu.version) }
> +        .gnu.version_d  : { *(.gnu.version_d) }
> +        .gnu.version_r  : { *(.gnu.version_r) }
> +        .eh_frame_hdr   : { *(.eh_frame_hdr) }  :load :eh_frame_hdr
> +        .eh_frame       : { *(.eh_frame) }      :load
> +
> +        .text           : { *(.text*) }         :load   =0x90909090
> +}
> diff --git a/linux-user/i386/vdso.so b/linux-user/i386/vdso.so
> new file mode 100755
> index 0000000000000000000000000000000000000000..bdece5dfcf8da036d013262d4e37208350283cfa
> GIT binary patch
> literal 2672
> zcmbtWU1%It6u#5lG_z^4ZB?X_C>9o5sxCF8QBlyONt?nZ)?|y73e)ZGba%;SR(597
> zjTXE8QIiHtY6YPbDhO>6s(mPS(FX(Z2Q`g?1xp_^KInr_=|f8&)b;yj=5}w=eGok1
> z%XiMX=brmB_ny0ldSlx(O%qZAA|PnR8-(ZpuhYGj4)L&P5F5p65f&@qVw=PV(21ar
> zS~fT!zaSUUNMnr<D?qmul%W%{|IXi?lnz58hBiXBldmd>Kqu7p`(Ouv?E|~S#J4vR
> z?eBj&+ji~rg~eZ!zf~VSJr_pXM}D8DFrl0ORPzVHn5LKmbB!e|qzOC^tO77~@mIB)
> zzl6kpgPDI3e2U8d6uIY2bq_`x0-wZWxDMLSfe$J6M%crOeHivUY<@1rr@`l7bI!EC
> z1WQ>fZdBic@iW@_P1t@f_$4LZXEGSfcpH2f?e~Kj&v`Zj+$T!NBlkb|jQhnHeiL+a
> z&lJb<kCS@_*v@tHJTOn=lluBDy{$|iW0~jDvC(tlyVi??Q=2p0KUP})m@B{A^3Fp?
> z#y5Ta$e&ZC6Ayg2)jAG+!^M53FpOcdV3|2%)E={wiChkz(UhGxlDT|x*hrg>lO18$
> z-OkRAyW9oSmOj5{et#-4CVgruv?pIJqQxKI&ZY~dQ!H3DSHUrA-dxrymL5+h95ZU?
> zqfdy~j)7gfjrM5g9c>HN9>C7<kIZ}NS==-4@5JK#YMzfafM=QF?WZPg6+aHhHu){t
> z#@l_<Z)3bX7g}rJnLgP3J~0HQz%PJH;3Rk&d;okNJPDowp8;P3e*#_ve+BLUI4(td
> zZBS?jb*;5I7#xS6XOVMV0Ql`GjNJ_U;OnA06ySNFpY!>?j(;zF-_-GQuCsOgock95
> z$CvrnLFHO513c5BE36+~5f2BEAVM30`47nj^o(oe;NgZND~~oF)87oe)%5l%caD!C
> zZUR`#4&CABw}%(BE9KdV>yxiUf|Id`UI}64SIQGVslJnSd`)$H14yd$t+Ysc2<dgC
> zZ=Q@t)>OQ(J+srhD+k<&>B<F{@o$-65V!Wyt>HxRj<L>q5)uze70i3T0nE36-;4MD
> zX|P(C`eCbeVGnF6>~F$Q>&)x0)jBo>TdiYfVXJlMbJ%KKV=Y$enlO4^9_Z@du@yHB
> zwchCMGqw$O_4gWmJ%e{HQ)lfOF0TyrZnl4$<)z$G>%HU>FE1lXy;xFj>Xa70cGRgB
> zZe?<tMbsV}aT5E$PQl}h)U3Q?ifC%gN{nQau7X$*O<ToiCShkhk5lkGqh`U*=B*`$
> zkrGieW9%;^Moc4<LZq}r)G<pAcKN?aE5cZ-d1tTskoO0sTmQ-H0oHh)quV~pVEQOL
> zf~-B80KOf}$M=_*fzCLdUB>YqcLID@7{~XU=z-4s6vh$lz%9JdjN|)G?1a8N?pfc*
> zIKKY`&zcmDP2m_-KOf(Hg0)2EV}IgBfWHx_^Y;P~hc5SkbEE79n459x?;V(~$T$m@
> zjElobxDGGOT`N`AK*n(#-do~0bSZKjGMDr(AZ`H$D-74d^xS8@>$IiJAn|o+fMq_`
> OKQ-<Y4#gXF;{FA}h_Ctp
> 
> literal 0
> HcmV?d00001
> 



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH v6 10/19] linux-user/x86_64: Add vdso
  2023-09-30  2:15 ` [PATCH v6 10/19] linux-user/x86_64: " Richard Henderson
@ 2023-10-05 16:44   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 37+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-10-05 16:44 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: alex.bennee, laurent, Paolo Bonzini

On 30/9/23 04:15, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   linux-user/elfload.c            |   4 +-
>   linux-user/x86_64/Makefile.vdso |  11 +++++
>   linux-user/x86_64/meson.build   |   4 ++
>   linux-user/x86_64/vdso.S        |  78 ++++++++++++++++++++++++++++++++
>   linux-user/x86_64/vdso.ld       |  73 ++++++++++++++++++++++++++++++
>   linux-user/x86_64/vdso.so       | Bin 0 -> 2968 bytes
>   6 files changed, 168 insertions(+), 2 deletions(-)
>   create mode 100644 linux-user/x86_64/Makefile.vdso
>   create mode 100644 linux-user/x86_64/vdso.S
>   create mode 100644 linux-user/x86_64/vdso.ld
>   create mode 100755 linux-user/x86_64/vdso.so

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>

> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
> index 314ae7cacf..1e1fdce656 100644
> --- a/linux-user/elfload.c
> +++ b/linux-user/elfload.c
> @@ -318,10 +318,10 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *en
>           }                                               \
>       } while (0)
>   
> -#define VDSO_HEADER "vdso.c.inc"
> -
>   #endif /* TARGET_X86_64 */
>   
> +#define VDSO_HEADER "vdso.c.inc"
> +
>   #define USE_ELF_CORE_DUMP
>   #define ELF_EXEC_PAGESIZE       4096
>   
> diff --git a/linux-user/x86_64/Makefile.vdso b/linux-user/x86_64/Makefile.vdso
> new file mode 100644
> index 0000000000..26552b66db
> --- /dev/null
> +++ b/linux-user/x86_64/Makefile.vdso
> @@ -0,0 +1,11 @@
> +include $(BUILD_DIR)/tests/tcg/x86_64-linux-user/config-target.mak
> +
> +SUBDIR = $(SRC_PATH)/linux-user/x86_64
> +VPATH += $(SUBDIR)
> +
> +all: $(SUBDIR)/vdso.so
> +
> +$(SUBDIR)/vdso.so: vdso.S vdso.ld
> +	$(CC) -o $@ -nostdlib -shared -Wl,-h,linux-vdso.so.1 \
> +	  -Wl,--build-id=sha1 -Wl,--hash-style=both \
> +	  -Wl,-T,$(SUBDIR)/vdso.ld $<
> diff --git a/linux-user/x86_64/meson.build b/linux-user/x86_64/meson.build
> index 203af9a60c..8c60da7a60 100644
> --- a/linux-user/x86_64/meson.build
> +++ b/linux-user/x86_64/meson.build
> @@ -3,3 +3,7 @@ syscall_nr_generators += {
>                         arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ],
>                         output: '@BASENAME@_nr.h')
>   }
> +
> +vdso_inc = gen_vdso.process('vdso.so')
> +
> +linux_user_ss.add(when: 'TARGET_X86_64', if_true: vdso_inc)
> diff --git a/linux-user/x86_64/vdso.S b/linux-user/x86_64/vdso.S
> new file mode 100644
> index 0000000000..47d16c00ab
> --- /dev/null
> +++ b/linux-user/x86_64/vdso.S
> @@ -0,0 +1,78 @@
> +/*
> + * x86-64 linux replacement vdso.
> + *
> + * Copyright 2023 Linaro, Ltd.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#include <asm/unistd.h>
> +
> +.macro endf name
> +	.globl	\name
> +	.type	\name, @function
> +	.size	\name, . - \name
> +.endm
> +
> +.macro weakalias name
> +\name	= __vdso_\name
> +	.weak	\name
> +.endm
> +
> +.macro vdso_syscall name, nr
> +__vdso_\name:
> +	mov	$\nr, %eax
> +	syscall
> +	ret
> +endf	__vdso_\name
> +weakalias \name
> +.endm
> +
> +	.cfi_startproc
> +
> +vdso_syscall clock_gettime, __NR_clock_gettime
> +vdso_syscall clock_getres, __NR_clock_getres
> +vdso_syscall gettimeofday, __NR_gettimeofday
> +vdso_syscall time, __NR_time
> +
> +__vdso_getcpu:
> +	/*
> +         * There is no syscall number for this allocated on x64.
> +	 * We can handle this several ways:
> +         *
> +	 * (1) Invent a syscall number for use within qemu.
> +         *     It should be easy enough to pick a number that
> +         *     is well out of the way of the kernel numbers.
> +         *
> +         * (2) Force the emulated cpu to support the rdtscp insn,
> +	 *     and initialize the TSC_AUX value the appropriate value.
> +         *
> +	 * (3) Pretend that we're always running on cpu 0.
> +         *
> +	 * This last is the one that's implemented here, with the
> +	 * tiny bit of extra code to support rdtscp in place.
> +         */
> +	xor	%ecx, %ecx		/* rdtscp w/ tsc_aux = 0 */
> +
> +	/* if (cpu != NULL) *cpu = (ecx & 0xfff); */
> +	test	%rdi, %rdi
> +	jz	1f
> +	mov	%ecx, %eax
> +	and	$0xfff, %eax
> +	mov	%eax, (%rdi)
> +
> +	/* if (node != NULL) *node = (ecx >> 12); */
> +1:	test	%rsi, %rsi
> +	jz	2f
> +	shr	$12, %ecx
> +	mov	%ecx, (%rsi)
> +
> +2:	xor	%eax, %eax
> +	ret
> +endf	__vdso_getcpu
> +
> +weakalias getcpu
> +
> +	.cfi_endproc
> +
> +/* TODO: Add elf note for LINUX_VERSION_CODE */
> diff --git a/linux-user/x86_64/vdso.ld b/linux-user/x86_64/vdso.ld
> new file mode 100644
> index 0000000000..ca6001cc3c
> --- /dev/null
> +++ b/linux-user/x86_64/vdso.ld
> @@ -0,0 +1,73 @@
> +/*
> + * Linker script for linux x86-64 replacement vdso.
> + *
> + * Copyright 2023 Linaro, Ltd.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +VERSION {
> +        LINUX_2.6 {
> +        global:
> +                clock_gettime;
> +                __vdso_clock_gettime;
> +                gettimeofday;
> +                __vdso_gettimeofday;
> +                getcpu;
> +                __vdso_getcpu;
> +                time;
> +                __vdso_time;
> +                clock_getres;
> +                __vdso_clock_getres;
> +
> +        local: *;
> +        };
> +}
> +
> +
> +PHDRS {
> +        phdr            PT_PHDR         FLAGS(4) PHDRS;
> +        load            PT_LOAD         FLAGS(7) FILEHDR PHDRS; /* FLAGS=RWX */
> +        dynamic         PT_DYNAMIC      FLAGS(4);
> +        eh_frame_hdr    PT_GNU_EH_FRAME;
> +        note            PT_NOTE         FLAGS(4);
> +}
> +
> +SECTIONS {
> +        . = SIZEOF_HEADERS;
> +
> +        /*
> +         * The following, including the FILEHDRS and PHDRS, are modified
> +         * when we relocate the binary.  We want them to be initially
> +         * writable for the relocation; we'll force them read-only after.
> +         */
> +        .note           : { *(.note*) }         :load :note
> +        .dynamic        : { *(.dynamic) }       :load :dynamic
> +        .dynsym         : { *(.dynsym) }        :load
> +        .data           : {
> +                /*
> +                 * There ought not be any real read-write data.
> +                 * But since we manipulated the segment layout,
> +                 * we have to put these sections somewhere.
> +                 */
> +                *(.data*)
> +                *(.sdata*)
> +                *(.got.plt) *(.got)
> +                *(.gnu.linkonce.d.*)
> +                *(.bss*)
> +                *(.dynbss*)
> +                *(.gnu.linkonce.b.*)
> +        }
> +
> +        .rodata         : { *(.rodata*) }
> +        .hash           : { *(.hash) }
> +        .gnu.hash       : { *(.gnu.hash) }
> +        .dynstr         : { *(.dynstr) }
> +        .gnu.version    : { *(.gnu.version) }
> +        .gnu.version_d  : { *(.gnu.version_d) }
> +        .gnu.version_r  : { *(.gnu.version_r) }
> +        .eh_frame_hdr   : { *(.eh_frame_hdr) }  :load :eh_frame_hdr
> +        .eh_frame       : { *(.eh_frame) }      :load
> +
> +        .text           : { *(.text*) }         :load   =0x90909090
> +}
> diff --git a/linux-user/x86_64/vdso.so b/linux-user/x86_64/vdso.so
> new file mode 100755
> index 0000000000000000000000000000000000000000..c873d6ea580b393825506d2ffbddcf9827d89e14
> GIT binary patch
> literal 2968
> zcmcgtO=w(I6uvKUOl$t7l}J=nY6?Lgol-PVEvcEL6HP)om@-1c>vZO|6VjQnGcRQ#
> zQlk(xE{v3}x(Eh$E+iYFJ0pdXxDr=E=&lLvMs(4vwBz~aoiCl-j=CuHBzL}hzkANP
> z=iPhmJs%H_3^h28p){If=E2CAex2B8q6WA=6OrF`(`KF&`Uz?MI&EW@IwS5;J<v5S
> zm3;u8M8ZDNbcEvu0jxKter?<dUgx>q_-2rSodh0=h5M8yR&|8~q9xUzjR(|@2weye
> zz8a;S7@IIXlUIKD#o1b1+rN5odUE>L=z;rh$dv40C`m=ye*;62d-p2^;2j+^>^@b*
> z{zK-lF(OZeV2X;(id~9-RYHGjYX7&6)!h7{<L?-V+C6T-xxH+fO-w(S=h!R!)55=J
> z@z1ONh{Zpn`Zga`ecR75)jw_d8B~3nM_M2rJI<`|o#xMqz%F@5M$pfwf5Z(rDGlFi
> z^EmbvX*g$?a37>=_DaLK@yv17h==zIwme4kF^2|U3rG4QL%vz2K73uCxOLI|+`aN!
> z$F-%z;-Tzk@6K<ve)YnqSIbKuJ^SrI{>$E*Jv}RD{ao_%it)TlnNq<^Unr!fz4Lw$
> zOy&HC$f92&rz(YWnba(~S{s>9e=uV%Oyy_Fufeq||4}nCJT{T^4!f^Qd<}K~WJ1Kz
> zzvUl)Z^gZPP8#nNzOg~(w`aa@<o(9^K%DNzqu`(ulXgfNgnG`03FDMIobHyUJzt9w
> zo+0?gnY<+pa{adav`21S-&8!KxE^A3Jw9Iv_AacwQfZf+Z;H=v2a%udwk)(oS8s^Q
> ze+lApB>FjYY9u^!IW^5APGzK1@7^HK>gD4>;p^R}arI;0o1?04=jpKWw!W)=?0Yt=
> zynUbER^IkMss3a7y}So_=McZ`$9S>#$BvH<4@j=b`|AzHy`jYM(LpaBOVlKlW^ujb
> z)P%J2ye6gV=6*G&ja!<{1*x-wK{3QEd-+1(8#gnXPvxf4)sE;I_k4cF&8AA(kO_(*
> zbIC83rV9C8121D-KkJ<<rgFZQ&4?yP#tr;(AUpEt(k(9Vj<7ELTixSId}la*Nji9E
> z@a{mEzeGvus<3|XJhjXlyz_X^xc;1Wh%eUIqf2|%IlLE07230&5^>idjF0yGj>9sy
> zEwzyLtiMFu4~T6avc|lrbF^o@CbB+LUq6S#>RVK)S)cWo$nWI(T!)Byg4)h8>pihg
> zSHk{7hu^QXIU^m!MEjk0M(-crN9uFmIL=%4U1~>sm5Pe?`en6ee(>HC`S#L{y??u6
> vr;^|o8ppUAv<ink<oeuK)I;vAba!M!1G>D!gdKbRPND1BpVH#|fA;?X5$6$T
> 
> literal 0
> HcmV?d00001
> 



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH v6 11/19] linux-user/aarch64: Add vdso
  2023-09-30  2:15 ` [PATCH v6 11/19] linux-user/aarch64: " Richard Henderson
@ 2023-10-05 16:47   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 37+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-10-05 16:47 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel; +Cc: alex.bennee, laurent, Peter Maydell

On 30/9/23 04:15, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   linux-user/elfload.c             |   6 +++
>   linux-user/aarch64/Makefile.vdso |  15 +++++++
>   linux-user/aarch64/meson.build   |  11 +++++
>   linux-user/aarch64/vdso-be.so    | Bin 0 -> 3216 bytes
>   linux-user/aarch64/vdso-le.so    | Bin 0 -> 3216 bytes
>   linux-user/aarch64/vdso.S        |  71 ++++++++++++++++++++++++++++++
>   linux-user/aarch64/vdso.ld       |  72 +++++++++++++++++++++++++++++++
>   linux-user/meson.build           |   1 +
>   8 files changed, 176 insertions(+)
>   create mode 100644 linux-user/aarch64/Makefile.vdso
>   create mode 100644 linux-user/aarch64/meson.build
>   create mode 100755 linux-user/aarch64/vdso-be.so
>   create mode 100755 linux-user/aarch64/vdso-le.so
>   create mode 100644 linux-user/aarch64/vdso.S
>   create mode 100644 linux-user/aarch64/vdso.ld

Comments are well appreciated, thanks.

To the best of my knowledge,
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>

> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
> index 1e1fdce656..693ebc94bd 100644
> --- a/linux-user/elfload.c
> +++ b/linux-user/elfload.c
> @@ -944,6 +944,12 @@ const char *elf_hwcap2_str(uint32_t bit)
>   
>   #undef GET_FEATURE_ID
>   
> +#if TARGET_BIG_ENDIAN
> +# define VDSO_HEADER  "vdso-be.c.inc"
> +#else
> +# define VDSO_HEADER  "vdso-le.c.inc"
> +#endif
> +
>   #endif /* not TARGET_AARCH64 */
>   #endif /* TARGET_ARM */
>   
> diff --git a/linux-user/aarch64/Makefile.vdso b/linux-user/aarch64/Makefile.vdso
> new file mode 100644
> index 0000000000..599958116b
> --- /dev/null
> +++ b/linux-user/aarch64/Makefile.vdso
> @@ -0,0 +1,15 @@
> +include $(BUILD_DIR)/tests/tcg/aarch64-linux-user/config-target.mak
> +
> +SUBDIR = $(SRC_PATH)/linux-user/aarch64
> +VPATH += $(SUBDIR)
> +
> +all: $(SUBDIR)/vdso-be.so $(SUBDIR)/vdso-le.so
> +
> +LDFLAGS = -nostdlib -shared -Wl,-h,linux-vdso.so.1 -Wl,--build-id=sha1 \
> +	  -Wl,--hash-style=both -Wl,-T,$(SUBDIR)/vdso.ld
> +
> +$(SUBDIR)/vdso-be.so: vdso.S vdso.ld
> +	$(CC) -o $@ $(LDFLAGS) -mbig-endian $<
> +
> +$(SUBDIR)/vdso-le.so: vdso.S vdso.ld
> +	$(CC) -o $@ $(LDFLAGS) -mlittle-endian $<
> diff --git a/linux-user/aarch64/meson.build b/linux-user/aarch64/meson.build
> new file mode 100644
> index 0000000000..248c578d15
> --- /dev/null
> +++ b/linux-user/aarch64/meson.build
> @@ -0,0 +1,11 @@
> +# TARGET_BIG_ENDIAN is defined to 'n' for little-endian; which means it
> +# is always true as far as source_set.apply() is concerned.  Always build
> +# both header files and include the right one via #if.
> +
> +vdso_be_inc = gen_vdso.process('vdso-be.so',
> +                               extra_args: ['-r', '__kernel_rt_sigreturn'])
> +
> +vdso_le_inc = gen_vdso.process('vdso-le.so',
> +                               extra_args: ['-r', '__kernel_rt_sigreturn'])
> +
> +linux_user_ss.add(when: 'TARGET_AARCH64', if_true: [vdso_be_inc, vdso_le_inc])
> diff --git a/linux-user/aarch64/vdso-be.so b/linux-user/aarch64/vdso-be.so
> new file mode 100755
> index 0000000000000000000000000000000000000000..6084f3d1a701316004894fcdd739c4e1e0463b68
> GIT binary patch
> literal 3216
> zcmc&$O>A355T57v+64N8Q&ABq6>X&mRj7RmMS`Gmu!EhX$W24qs-c&yv0q~6$41XD
> z#X$mc;KBh>)D!9f7jbE&o<UsN14xy6s{mC(f)i3Dq>3KO1&W#3omsDqjgUAn$-Zyr
> zo0*+`yF2UmUcNA$N_k+#hcB@25ZaP4_Th`HO~N+FKpLJveLJ?m*pV~RgWjm21z{L<
> z$}wd4LC@e<V_`J2N+HMjyq2;54GrCSjp1_g^L!^RXc~uJgeN&rkn%{wuD59Hy$Csu
> z6QuW}xHPtHGjnI)CU#JW^L5YkDUVO~&u;(z;i>e4`!_DFeDmp#mw&i^<zSxu2zGP-
> z93zc`;?p}pz5VAyLe#f3U`~Vnm#otsp`=<G03K(2i*W~|-luxI{fE(m3?b@|j1IK+
> zq|3fcF#mr*xCdaTNgUke3DA1y9R42jv>z)Y(0;(W3!dXI>qX-{<?y#SfcSq9uZ2e1
> zUtVwB=e^KjQdiCy);`2j+up*`@G|ff>*VL(Jr;fPar2{J(&x^9ec+i^?x(BSN1)Vd
> z6xX6PwHzf$bv>#tm5ZAlwzO6+t%|J=9Y>808z-t!U5=w<Bd)<(wYJeba-rO)hxq>-
> z6pqiGSyV^E7sBUX!r9;<vVWv`=5N>i8&^=H^Slq6Ij8hSDe#8W?GM<704wzH#{6Rl
> z<WF81Y=^Ot=r#7<UVxzav^TbMzi@OmX}>3kP~-l0hxTsW!QgLi`s#bF@9x%T9lbJQ
> zY!o|4aN}q$C{o`>LtdYI<XeWZJeo*sU1<$TsZTvuP2vN2smpoc2$ARWV(V9%ksmUC
> zwvL6T^NbSoj{g|*8H47D<8ZypeP?;D``}`aztok~1DU;`fBleezjdSEhJND^CwV`|
> zzLf#v@9}KjuJs?oz<%!)cKrQWJ2>781M2@Zr_SAbWZB{G@i?^Z?>M}yPa6444u6aN
> z(@-i+W?!6HJsZ|xybR+_P`TIVvL}weg5`%7zsk?5>4ofxyqe7|fSM_soXQr|$?54+
> z`P1rjcB+t9-4$r--d6bFQntST=8k}{vALcU-#|=agB9u3>PZA)d9zkrua<NNeG!XE
> z5yIu#Mp!8}Duz#D!(52sMzvn+QdAkjsG^qQ;(DYiW%Lvc!X#=YylDRs=v;8!*t%Ub
> zW7@jT_2i&^6*-6<_x?sz&YeZ_l^oQUcsd8qVw2xfzBf`W<WK~G>W$*LZfyK0az`B=
> zOP9o-=tekTbo-S2gfC;0-yF_wz7ueqd5$=Y$YX0p;sews@%Q~V_LKN6qx+07iF&_y
> za+`8&63=yF?=kuAAb%2B2kO6y`P<Y%;dr^{1oge*=4U_cf428~1@Fm>9?hbjKdryS
> z$@`Pr5;mES<ZqGz$6>VJiH5fKy;kWM_r}wHqu6`)kkRea&Hpa463^!_;Pn&K^S8m+
> zp?wpfSa~nu80C99^(GSZO}Up1l7AF+`VDc{mR$&j&a-ljQ9$NP`UtiG@xy#y!}}7*
> HXyg9^8}}&g
> 
> literal 0
> HcmV?d00001
> 
> diff --git a/linux-user/aarch64/vdso-le.so b/linux-user/aarch64/vdso-le.so
> new file mode 100755
> index 0000000000000000000000000000000000000000..947d534ec1899740edbd6921da6bc6e70e2ecd09
> GIT binary patch
> literal 3216
> zcmcguL2MgU5FKYzk|v=|N~=Z+qD6{Og<utmRJD|Y9c(v2Zd%etExr7@_Qp0%>~_6L
> z9VDO!E}RJB#LXZsa7BWO3q5c^;)VcKz2t<11S;tPP82h<JI`MKYy}b$WB;B1-^~2^
> z`~S@Be=AqW52R8Aa_9@{jfm1J*c^t2V8>|}KgVe=J;LxHx3r3FKB<#|V;X^n)Fz2-
> z%cM-;q^lZWOhj#+*XG^Ds~rB${uGqOuBG$Zd_T*Cz*Q~uCH;#!pUtzO6%jc6iOo2-
> zUEEGBEQ!`_!5rx^Nnd=)Smd95v^A8^_@B?;{q2QA>mys0rC%Ro5$%x&)1`=ocG5ko
> z6aD^Iry=8;Iu?IIw{$G$Bh;3SV;YGV-B3QNd{X(JooK$aERgAej@6vDbv&c;NbCQ9
> zy6kcvjnN%lhwQabmYd)|D~|JcjqwS(-w~ZS$+3$5Eo+{GihpC_aoczwaVXo4J(oVt
> zLv%HS2r(>}=m;)N?7pOQiiV@`7Cn)F;GMkl%e$@jzP@~EJllTi@Po`JTV%{t&#!wc
> zrs4%bZPjZmmx~)cw6xMFU4<+G_Pu5g^#jwaReUd4^Xs%ytFN`5T`xBqF8`mS!u-P0
> zMRU|W=01Od7sIQ^Pev*IefZVAM<t#g=Z097cN$>%JKvfi<dvL*P-@CKDVXS_xjn;8
> z2<Mo3eUS!RPo$>C4uzP+=NPvcQDQRF&JRZp-29I1zrXF6AH(sU{_$LFT%Cwyk#+LZ
> z;ng6&;~EaXMOzkXk;A9cMq<Qd4rl3%9GpcCM+5RUE^_$fk-z=;P&beJ@nK5JKZkY`
> z^0r@pq+9p;@lo2;`0mGh`2bvAe=s3`<V@rg?S0!D;ydSw^hfFA1iwl1?+a(Y-?8_9
> zDx81kdr4hL@jB<M{m(L<l>e_Vo>WIFiraPM4aMzx@xJ0a>P4w^{aUtsrS3Lpx=hn8
> zGTB!bGN<QX;`HOfZ*p@cznD3lGjrKRGN%e>W-|qICZ9i-J8#ZsW(zsfpMl-H?`HVJ
> zQ@N}AZ)ya&&5hNdc!hc3N4$z&y%BiimN)9f)mka+urBjrP$aifUvsO)W;MbCKSI_$
> zzgcV4`v#^=u2(h7esR?^)iP^hL~h`<0^Y;_N)i`xuRvNNF2N-Z;)L%5uqU}Abr|7;
> zxC7_l3JG@?*rRSe%~JWM!awQ*_-14tu2H6fJ-)w38511-QAfZJvn)=q2Y-=;^38#N
> z)EjWrS<DYRq~me6{e!>put!}27rBsaAE89EDuX@lA>g=oKwq~LLwcEeotS^rIq;}{
> z^!&pQ_yx9?I}66Bhu~O0Vg&Dx1uSz%)&%>9-4mgYeZyE{IBt*n3VsBN%5DE|sy*%y
> zs59VLKc=z$$9+Rb__iuu(-)I_<pFN+KPgH~ySd?PLqH#wHQ+yugWR{zZ-TKT`w?~Y
> I_CMJF4X7R_od5s;
> 
> literal 0
> HcmV?d00001
> 
> diff --git a/linux-user/aarch64/vdso.S b/linux-user/aarch64/vdso.S
> new file mode 100644
> index 0000000000..34d3a9ebd2
> --- /dev/null
> +++ b/linux-user/aarch64/vdso.S
> @@ -0,0 +1,71 @@
> +/*
> + * aarch64 linux replacement vdso.
> + *
> + * Copyright 2023 Linaro, Ltd.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#include <asm/unistd.h>
> +
> +/* ??? These are in include/elf.h, which is not ready for inclusion in asm. */
> +#define NT_GNU_PROPERTY_TYPE_0  5
> +#define GNU_PROPERTY_AARCH64_FEATURE_1_AND      0xc0000000
> +#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI      (1U << 0)
> +#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC      (1U << 1)
> +
> +#define GNU_PROPERTY_AARCH64_FEATURE_1_DEFAULT \
> +    (GNU_PROPERTY_AARCH64_FEATURE_1_BTI | GNU_PROPERTY_AARCH64_FEATURE_1_PAC)
> +
> +	.section .note.gnu.property
> +	.align	3
> +	.long	2f - 1f
> +	.long	6f - 3f
> +	.long	NT_GNU_PROPERTY_TYPE_0
> +1:	.string	"GNU"
> +2:	.align	3
> +3:	.long	GNU_PROPERTY_AARCH64_FEATURE_1_AND
> +	.long	5f - 4f
> +4:	.long	GNU_PROPERTY_AARCH64_FEATURE_1_DEFAULT
> +5:	.align	3
> +6:
> +
> +	.text
> +
> +.macro endf name
> +	.globl	\name
> +	.type	\name, @function
> +	.size	\name, . - \name
> +.endm
> +
> +.macro vdso_syscall name, nr
> +\name:
> +	bti	c
> +	mov	x8, #\nr
> +	svc	#0
> +	ret
> +endf	\name
> +.endm
> +
> +	.cfi_startproc
> +
> +vdso_syscall __kernel_gettimeofday, __NR_gettimeofday
> +vdso_syscall __kernel_clock_gettime, __NR_clock_gettime
> +vdso_syscall __kernel_clock_getres, __NR_clock_getres
> +
> +	.cfi_endproc
> +
> +
> +/*
> + * TODO: The kernel makes a big deal of turning off the .cfi directives,
> + * because they cause libgcc to crash, but that's because they're wrong.
> + *
> + * For now, elide the unwind info for __kernel_rt_sigreturn and rely on
> + * the libgcc fallback routine as we have always done.  This requires
> + * that the code sequence used be exact.
> + */
> +__kernel_rt_sigreturn:
> +	/* No BTI C insn here -- we arrive via RET. */
> +	mov	x8, #__NR_rt_sigreturn
> +	svc	#0
> +endf	__kernel_rt_sigreturn
> diff --git a/linux-user/aarch64/vdso.ld b/linux-user/aarch64/vdso.ld
> new file mode 100644
> index 0000000000..4c12f33352
> --- /dev/null
> +++ b/linux-user/aarch64/vdso.ld
> @@ -0,0 +1,72 @@
> +/*
> + * Linker script for linux aarch64 replacement vdso.
> + *
> + * Copyright 2021 Linaro, Ltd.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +VERSION {
> +        LINUX_2.6.39 {
> +        global:
> +                __kernel_rt_sigreturn;
> +                __kernel_gettimeofday;
> +                __kernel_clock_gettime;
> +                __kernel_clock_getres;
> +
> +        local: *;
> +        };
> +}
> +
> +
> +PHDRS {
> +        phdr            PT_PHDR         FLAGS(4) PHDRS;
> +        load            PT_LOAD         FLAGS(7) FILEHDR PHDRS;
> +        dynamic         PT_DYNAMIC      FLAGS(4);
> +        eh_frame_hdr    PT_GNU_EH_FRAME;
> +        note            PT_NOTE         FLAGS(4);
> +}
> +
> +SECTIONS {
> +        /*
> +         * We can't prelink to any address without knowing something about
> +         * the virtual memory space of the host, since that leaks over into
> +         * the available memory space of the guest.
> +         */
> +        . = SIZEOF_HEADERS;
> +
> +        /*
> +         * The following, including the FILEHDRS and PHDRS, are modified
> +         * when we relocate the binary.  We want them to be initially
> +         * writable for the relocation; we'll force them read-only after.
> +         */
> +        .note           : { *(.note*) }         :load :note
> +        .dynamic        : { *(.dynamic) }       :load :dynamic
> +        .dynsym         : { *(.dynsym) }        :load
> +        /*
> +         * There ought not be any real read-write data.
> +         * But since we manipulated the segment layout,
> +         * we have to put these sections somewhere.
> +         */
> +        .data           : {
> +                *(.data*)
> +                *(.sdata*)
> +                *(.got.plt) *(.got)
> +                *(.gnu.linkonce.d.*)
> +                *(.bss*)
> +                *(.dynbss*)
> +                *(.gnu.linkonce.b.*)
> +        }
> +
> +        .rodata         : { *(.rodata*) }
> +        .hash           : { *(.hash) }
> +        .gnu.hash       : { *(.gnu.hash) }
> +        .dynstr         : { *(.dynstr) }
> +        .gnu.version    : { *(.gnu.version) }
> +        .gnu.version_d  : { *(.gnu.version_d) }
> +        .gnu.version_r  : { *(.gnu.version_r) }
> +        .eh_frame_hdr   : { *(.eh_frame_hdr) }  :load :eh_frame_hdr
> +        .eh_frame       : { *(.eh_frame) }      :load
> +
> +        .text           : { *(.text*) }         :load   =0xd503201f
> +}
> diff --git a/linux-user/meson.build b/linux-user/meson.build
> index e4cb70ed2d..dd24389052 100644
> --- a/linux-user/meson.build
> +++ b/linux-user/meson.build
> @@ -35,6 +35,7 @@ gen_vdso_exe = executable('gen-vdso', 'gen-vdso.c',
>   gen_vdso = generator(gen_vdso_exe, output: '@BASENAME@.c.inc',
>                        arguments: ['-o', '@OUTPUT@', '@EXTRA_ARGS@', '@INPUT@'])
>   
> +subdir('aarch64')
>   subdir('alpha')
>   subdir('arm')
>   subdir('hppa')



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [PATCH v6 18/19] linux-user/s390x: Add vdso
  2023-10-05 16:14       ` Philippe Mathieu-Daudé
@ 2023-10-06  7:30         ` Thomas Huth
  0 siblings, 0 replies; 37+ messages in thread
From: Thomas Huth @ 2023-10-06  7:30 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, Richard Henderson, qemu-devel
  Cc: alex.bennee, laurent, David Hildenbrand

On 05/10/2023 18.14, Philippe Mathieu-Daudé wrote:
> On 4/10/23 01:01, Richard Henderson wrote:
>> On 10/3/23 06:07, Philippe Mathieu-Daudé wrote:
>>>> +++ b/linux-user/s390x/vdso.ld
>>>> @@ -0,0 +1,69 @@
>>>> +/*
>>>> + * Linker script for linux x86-64 replacement vdso.

Should that be s390x instead of x86-64 ?

>>>> + * Copyright 2023 Linaro, Ltd.
>>>> + *
>>>> + * SPDX-License-Identifier: GPL-2.0-or-later
>>>> + */
>>>> +
>>>> +VERSION {
>>>> +        LINUX_2.6.29 {
>>>> +        global:
>>>> +                __kernel_gettimeofday;
>>>> +                __kernel_clock_gettime;
>>>> +                __kernel_clock_getres;
>>>> +                __kernel_getcpu;
>>>> +                __kernel_restart_syscall;
>>>
>>> Where is __kernel_restart_syscall defined?
>>
>> It isn't, and I guess isn't needed for qemu (we have QEMU_ERESTARTSYS).
>> I'm not sure why it's an exported symbol for the s390x vdso for the 
>> kernel, even if they do require some user-space code.
>>
>> Anyway, I'll remove the symbol here.
> 
> OK.
> 
> I dare to give:
> 
> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> 
> But still I'm Cc'ing David / Thomas who better know s390x :)

Uh, oh, vdso ... I remember some dark magic here on the real kernels on 
s390x, involving access registers ... good that we don't need those here :-)

I quickly glanced through the code, and apart from the typo above, it looks 
good to me, so:

Acked-by: Thomas Huth <thuth@redhat.com>



^ permalink raw reply	[flat|nested] 37+ messages in thread

end of thread, other threads:[~2023-10-06  7:30 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-09-30  2:15 [PATCH v6 00/19] linux-user: Implement VDSOs Richard Henderson
2023-09-30  2:15 ` [PATCH v6 01/19] linux-user: Introduce imgsrc_read, imgsrc_read_alloc Richard Henderson
2023-09-30  2:15 ` [PATCH v6 02/19] linux-user: Tidy loader_exec Richard Henderson
2023-09-30  2:15 ` [PATCH v6 03/19] linux-user: Do not clobber bprm_buf swapping ehdr Richard Henderson
2023-09-30  2:15 ` [PATCH v6 04/19] linux-user: Use ImageSource in load_elf_image Richard Henderson
2023-10-02 13:22   ` Philippe Mathieu-Daudé
2023-09-30  2:15 ` [PATCH v6 05/19] linux-user: Use ImageSource in load_symbols Richard Henderson
2023-09-30  2:15 ` [PATCH v6 06/19] linux-user: Replace bprm->fd with bprm->src.fd Richard Henderson
2023-09-30  2:15 ` [PATCH v6 07/19] linux-user: Load vdso image if available Richard Henderson
2023-10-03 12:47   ` Philippe Mathieu-Daudé
2023-09-30  2:15 ` [PATCH v6 08/19] linux-user: Add gen-vdso tool Richard Henderson
2023-10-03 13:00   ` Philippe Mathieu-Daudé
2023-10-03 23:05     ` Richard Henderson
2023-10-05 16:25       ` Philippe Mathieu-Daudé
2023-09-30  2:15 ` [PATCH v6 09/19] linux-user/i386: Add vdso Richard Henderson
2023-10-05 16:42   ` Philippe Mathieu-Daudé
2023-09-30  2:15 ` [PATCH v6 10/19] linux-user/x86_64: " Richard Henderson
2023-10-05 16:44   ` Philippe Mathieu-Daudé
2023-09-30  2:15 ` [PATCH v6 11/19] linux-user/aarch64: " Richard Henderson
2023-10-05 16:47   ` Philippe Mathieu-Daudé
2023-09-30  2:15 ` [PATCH v6 12/19] linux-user/arm: " Richard Henderson
2023-09-30  2:15 ` [PATCH v6 13/19] linux-user/hppa: " Richard Henderson
2023-10-05 16:16   ` Philippe Mathieu-Daudé
2023-09-30  2:15 ` [PATCH v6 14/19] linux-user/riscv: " Richard Henderson
2023-10-05 16:24   ` Philippe Mathieu-Daudé
2023-09-30  2:15 ` [PATCH v6 15/19] linux-user/loongarch64: " Richard Henderson
2023-10-05 16:18   ` Philippe Mathieu-Daudé
2023-09-30  2:15 ` [PATCH v6 16/19] linux-user/ppc: " Richard Henderson
2023-10-05 16:35   ` Philippe Mathieu-Daudé
2023-09-30  2:15 ` [PATCH v6 17/19] linux-user/s390x: Rename __SIGNAL_FRAMESIZE to STACK_FRAME_OVERHEAD Richard Henderson
2023-09-30  2:15 ` [PATCH v6 18/19] linux-user/s390x: Add vdso Richard Henderson
2023-10-03 13:07   ` Philippe Mathieu-Daudé
2023-10-03 23:01     ` Richard Henderson
2023-10-05 16:14       ` Philippe Mathieu-Daudé
2023-10-06  7:30         ` Thomas Huth
2023-09-30  2:15 ` [PATCH v6 19/19] build: Add update-linux-vdso makefile rule Richard Henderson
2023-10-03 13:02   ` Philippe Mathieu-Daudé

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).