diff mbox series

[v3,15/41] accel/tcg: Support split-wx for linux with memfd

Message ID 20201106032921.600200-16-richard.henderson@linaro.org
State Superseded
Headers show
Series Mirror map JIT memory for TCG | expand

Commit Message

Richard Henderson Nov. 6, 2020, 3:28 a.m. UTC
We cannot use a real temp file, because we would need to find
a filesystem that does not have noexec enabled.  However, a
memfd is not associated with any filesystem.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

---
 accel/tcg/translate-all.c | 84 +++++++++++++++++++++++++++++++++++----
 1 file changed, 76 insertions(+), 8 deletions(-)

-- 
2.25.1

Comments

Alex Bennée Nov. 10, 2020, 5:03 p.m. UTC | #1
Richard Henderson <richard.henderson@linaro.org> writes:

> We cannot use a real temp file, because we would need to find

> a filesystem that does not have noexec enabled.  However, a

> memfd is not associated with any filesystem.

>

> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>


It looks like this breaks --enable-tcg-interpreter:

  FAILED: libqemu-ppc64-softmmu.fa.p/accel_tcg_translate-all.c.o
  cc -Ilibqemu-ppc64-softmmu.fa.p -I. -I../.. -Itarget/ppc -I../../target/ppc -I../../dtc/libfdt -I../../capstone/include/capstone -Iqapi -Itrace -Iui -Iui/shader -I/usr/include/spice-server -I/usr/include/spice-1 -I/usr/include/pixman-1 -I/usr/include/libdrm -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -fdiagnostics-color=auto -pipe -Wall -Winvalid-pch -Werror -std=gnu99 -O2 -g -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -m64 -mcx16 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes -Wredundant-decls -Wundef -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing -fno-common -fwrapv -Wold-style-declaration -Wold-style-definition -Wtype-limits -Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers -Wempty-body -Wnested-externs -Wendif-labels -Wexpansion-to-defined -Wno-missing-include-dirs -Wno-shift-negative-value -Wno-psabi -fstack-protector-strong -DLEGACY_RDMA_REG_MR -isystem /home/alex/lsrc/qemu.git/linux-headers -isystem linux-headers -iquote /home/alex/lsrc/qemu.git/tcg/tci -iquote . -iquote /home/alex/lsrc/qemu.git -iquote /home/alex/lsrc/qemu.git/accel/tcg -iquote /home/alex/lsrc/qemu.git/include -iquote /home/alex/lsrc/qemu.git/disas/libvixl -pthread -fPIC -isystem../../linux-headers -isystemlinux-headers -DNEED_CPU_H '-DCONFIG_TARGET="ppc64-softmmu-config-target.h"' '-DCONFIG_DEVICES="ppc64-softmmu-config-devices.h"' -MD -MQ libqemu-ppc64-softmmu.fa.p/accel_tcg_translate-all.c.o -MF libqemu-ppc64-softmmu.fa.p/accel_tcg_translate-all.c.o.d -o libqemu-ppc64-softmmu.fa.p/accel_tcg_translate-all.c.o -c ../../accel/tcg/translate-all.c
  ../../accel/tcg/translate-all.c:1138:13: error: ‘alloc_code_gen_buffer_splitwx_memfd’ defined but not used [-Werror=unused-function]
   static bool alloc_code_gen_buffer_splitwx_memfd(size_t size, Error **errp)
               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  cc1: all warnings being treated as errors


> ---

>  accel/tcg/translate-all.c | 84 +++++++++++++++++++++++++++++++++++----

>  1 file changed, 76 insertions(+), 8 deletions(-)

>

> diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c

> index a29cb4a42e..1931e65365 100644

> --- a/accel/tcg/translate-all.c

> +++ b/accel/tcg/translate-all.c

> @@ -1078,17 +1078,11 @@ static bool alloc_code_gen_buffer(size_t size, int splitwx, Error **errp)

>      return true;

>  }

>  #else

> -static bool alloc_code_gen_buffer(size_t size, int splitwx, Error **errp)

> +static bool alloc_code_gen_buffer_anon(size_t size, int prot,

> +                                       int flags, Error **errp)

>  {

> -    int prot = PROT_WRITE | PROT_READ | PROT_EXEC;

> -    int flags = MAP_PRIVATE | MAP_ANONYMOUS;

>      void *buf;

>  

> -    if (splitwx > 0) {

> -        error_setg(errp, "jit split-wx not supported");

> -        return false;

> -    }

> -

>      buf = mmap(NULL, size, prot, flags, -1, 0);

>      if (buf == MAP_FAILED) {

>          error_setg_errno(errp, errno,

> @@ -1137,6 +1131,80 @@ static bool alloc_code_gen_buffer(size_t size, int splitwx, Error **errp)

>      tcg_ctx->code_gen_buffer = buf;

>      return true;

>  }

> +

> +#ifdef CONFIG_POSIX

> +#include "qemu/memfd.h"

> +

> +static bool alloc_code_gen_buffer_splitwx_memfd(size_t size, Error **errp)

> +{

> +    void *buf_rw, *buf_rx;

> +    int fd = -1;

> +

> +    buf_rw = qemu_memfd_alloc("tcg-jit", size, 0, &fd, errp);

> +    if (buf_rw == NULL) {

> +        return false;

> +    }

> +

> +    buf_rx = mmap(NULL, size, PROT_READ | PROT_EXEC, MAP_SHARED, fd, 0);

> +    if (buf_rx == MAP_FAILED) {

> +        error_setg_errno(errp, errno,

> +                         "failed to map shared memory for execute");

> +        munmap(buf_rw, size);

> +        close(fd);

> +        return false;

> +    }

> +    close(fd);

> +

> +    tcg_ctx->code_gen_buffer = buf_rw;

> +    tcg_ctx->code_gen_buffer_size = size;

> +    tcg_splitwx_diff = buf_rx - buf_rw;

> +

> +    /* Request large pages for the buffer and the splitwx.  */

> +    qemu_madvise(buf_rw, size, QEMU_MADV_HUGEPAGE);

> +    qemu_madvise(buf_rx, size, QEMU_MADV_HUGEPAGE);

> +    return true;

> +}

> +#endif /* CONFIG_POSIX */

> +

> +static bool alloc_code_gen_buffer_splitwx(size_t size, Error **errp)

> +{

> +    if (TCG_TARGET_SUPPORT_MIRROR) {

> +#ifdef CONFIG_POSIX

> +        return alloc_code_gen_buffer_splitwx_memfd(size, errp);

> +#endif

> +    }

> +    error_setg(errp, "jit split-wx not supported");

> +    return false;

> +}

> +

> +static bool alloc_code_gen_buffer(size_t size, int splitwx, Error **errp)

> +{

> +    ERRP_GUARD();

> +    int prot, flags;

> +

> +    if (splitwx) {

> +        if (alloc_code_gen_buffer_splitwx(size, errp)) {

> +            return true;

> +        }

> +        /*

> +         * If splitwx force-on (1), fail;

> +         * if splitwx default-on (-1), fall through to splitwx off.

> +         */

> +        if (splitwx > 0) {

> +            return false;

> +        }

> +        error_free_or_abort(errp);

> +    }

> +

> +    prot = PROT_READ | PROT_WRITE | PROT_EXEC;

> +    flags = MAP_PRIVATE | MAP_ANONYMOUS;

> +#ifdef CONFIG_TCG_INTERPRETER

> +    /* The tcg interpreter does not need execute permission. */

> +    prot = PROT_READ | PROT_WRITE;

> +#endif

> +

> +    return alloc_code_gen_buffer_anon(size, prot, flags, errp);

> +}

>  #endif /* USE_STATIC_CODE_GEN_BUFFER, WIN32, POSIX */

>  

>  static bool tb_cmp(const void *ap, const void *bp)



-- 
Alex Bennée
Richard Henderson Nov. 10, 2020, 5:26 p.m. UTC | #2
On 11/10/20 9:03 AM, Alex Bennée wrote:
> 

> Richard Henderson <richard.henderson@linaro.org> writes:

> 

>> We cannot use a real temp file, because we would need to find

>> a filesystem that does not have noexec enabled.  However, a

>> memfd is not associated with any filesystem.

>>

>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

> 

> It looks like this breaks --enable-tcg-interpreter:

> 

>   FAILED: libqemu-ppc64-softmmu.fa.p/accel_tcg_translate-all.c.o

>   cc -Ilibqemu-ppc64-softmmu.fa.p -I. -I../.. -Itarget/ppc -I../../target/ppc -I../../dtc/libfdt -I../../capstone/include/capstone -Iqapi -Itrace -Iui -Iui/shader -I/usr/include/spice-server -I/usr/include/spice-1 -I/usr/include/pixman-1 -I/usr/include/libdrm -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -fdiagnostics-color=auto -pipe -Wall -Winvalid-pch -Werror -std=gnu99 -O2 -g -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -m64 -mcx16 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes -Wredundant-decls -Wundef -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing -fno-common -fwrapv -Wold-style-declaration -Wold-style-definition -Wtype-limits -Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers -Wempty-body -Wnested-externs -Wendif-labels -Wexpansion-to-defined -Wno-missing-include-dirs -Wno-shift-negative-value -Wno-psabi -fstack-protector-strong -DLEGACY_RDMA_REG_MR -isystem /home/alex/lsrc/qemu.git/linux-headers -isystem linux-headers -iquote /home/alex/lsrc/qemu.git/tcg/tci -iquote . -iquote /home/alex/lsrc/qemu.git -iquote /home/alex/lsrc/qemu.git/accel/tcg -iquote /home/alex/lsrc/qemu.git/include -iquote /home/alex/lsrc/qemu.git/disas/libvixl -pthread -fPIC -isystem../../linux-headers -isystemlinux-headers -DNEED_CPU_H '-DCONFIG_TARGET="ppc64-softmmu-config-target.h"' '-DCONFIG_DEVICES="ppc64-softmmu-config-devices.h"' -MD -MQ libqemu-ppc64-softmmu.fa.p/accel_tcg_translate-all.c.o -MF libqemu-ppc64-softmmu.fa.p/accel_tcg_translate-all.c.o.d -o libqemu-ppc64-softmmu.fa.p/accel_tcg_translate-all.c.o -c ../../accel/tcg/translate-all.c

>   ../../accel/tcg/translate-all.c:1138:13: error: ‘alloc_code_gen_buffer_splitwx_memfd’ defined but not used [-Werror=unused-function]

>    static bool alloc_code_gen_buffer_splitwx_memfd(size_t size, Error **errp)

>                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

>   cc1: all warnings being treated as errors


Bah, this will actually be patch 39, where I switch from if to ifdef.  I'll
have to rearrange those.


r~
diff mbox series

Patch

diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index a29cb4a42e..1931e65365 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -1078,17 +1078,11 @@  static bool alloc_code_gen_buffer(size_t size, int splitwx, Error **errp)
     return true;
 }
 #else
-static bool alloc_code_gen_buffer(size_t size, int splitwx, Error **errp)
+static bool alloc_code_gen_buffer_anon(size_t size, int prot,
+                                       int flags, Error **errp)
 {
-    int prot = PROT_WRITE | PROT_READ | PROT_EXEC;
-    int flags = MAP_PRIVATE | MAP_ANONYMOUS;
     void *buf;
 
-    if (splitwx > 0) {
-        error_setg(errp, "jit split-wx not supported");
-        return false;
-    }
-
     buf = mmap(NULL, size, prot, flags, -1, 0);
     if (buf == MAP_FAILED) {
         error_setg_errno(errp, errno,
@@ -1137,6 +1131,80 @@  static bool alloc_code_gen_buffer(size_t size, int splitwx, Error **errp)
     tcg_ctx->code_gen_buffer = buf;
     return true;
 }
+
+#ifdef CONFIG_POSIX
+#include "qemu/memfd.h"
+
+static bool alloc_code_gen_buffer_splitwx_memfd(size_t size, Error **errp)
+{
+    void *buf_rw, *buf_rx;
+    int fd = -1;
+
+    buf_rw = qemu_memfd_alloc("tcg-jit", size, 0, &fd, errp);
+    if (buf_rw == NULL) {
+        return false;
+    }
+
+    buf_rx = mmap(NULL, size, PROT_READ | PROT_EXEC, MAP_SHARED, fd, 0);
+    if (buf_rx == MAP_FAILED) {
+        error_setg_errno(errp, errno,
+                         "failed to map shared memory for execute");
+        munmap(buf_rw, size);
+        close(fd);
+        return false;
+    }
+    close(fd);
+
+    tcg_ctx->code_gen_buffer = buf_rw;
+    tcg_ctx->code_gen_buffer_size = size;
+    tcg_splitwx_diff = buf_rx - buf_rw;
+
+    /* Request large pages for the buffer and the splitwx.  */
+    qemu_madvise(buf_rw, size, QEMU_MADV_HUGEPAGE);
+    qemu_madvise(buf_rx, size, QEMU_MADV_HUGEPAGE);
+    return true;
+}
+#endif /* CONFIG_POSIX */
+
+static bool alloc_code_gen_buffer_splitwx(size_t size, Error **errp)
+{
+    if (TCG_TARGET_SUPPORT_MIRROR) {
+#ifdef CONFIG_POSIX
+        return alloc_code_gen_buffer_splitwx_memfd(size, errp);
+#endif
+    }
+    error_setg(errp, "jit split-wx not supported");
+    return false;
+}
+
+static bool alloc_code_gen_buffer(size_t size, int splitwx, Error **errp)
+{
+    ERRP_GUARD();
+    int prot, flags;
+
+    if (splitwx) {
+        if (alloc_code_gen_buffer_splitwx(size, errp)) {
+            return true;
+        }
+        /*
+         * If splitwx force-on (1), fail;
+         * if splitwx default-on (-1), fall through to splitwx off.
+         */
+        if (splitwx > 0) {
+            return false;
+        }
+        error_free_or_abort(errp);
+    }
+
+    prot = PROT_READ | PROT_WRITE | PROT_EXEC;
+    flags = MAP_PRIVATE | MAP_ANONYMOUS;
+#ifdef CONFIG_TCG_INTERPRETER
+    /* The tcg interpreter does not need execute permission. */
+    prot = PROT_READ | PROT_WRITE;
+#endif
+
+    return alloc_code_gen_buffer_anon(size, prot, flags, errp);
+}
 #endif /* USE_STATIC_CODE_GEN_BUFFER, WIN32, POSIX */
 
 static bool tb_cmp(const void *ap, const void *bp)