diff options
author | Richard Henderson | 2020-10-29 06:49:42 +0100 |
---|---|---|
committer | Richard Henderson | 2021-01-07 16:09:42 +0100 |
commit | a8c35b2cadfc7bef5221ceee0725493461568528 (patch) | |
tree | c216f79f95c50877a229a710eed2001d98121cc8 | |
parent | tcg: Add --accel tcg,split-wx property (diff) | |
download | qemu-a8c35b2cadfc7bef5221ceee0725493461568528.tar.gz qemu-a8c35b2cadfc7bef5221ceee0725493461568528.tar.xz qemu-a8c35b2cadfc7bef5221ceee0725493461568528.zip |
accel/tcg: Support split-wx for linux with memfd
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.
Reviewed-by: Joelle van Dyne <j@getutm.app>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
-rw-r--r-- | accel/tcg/translate-all.c | 84 |
1 files changed, 76 insertions, 8 deletions
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 022f9c743d..3b6804578d 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) |