summaryrefslogtreecommitdiffstats
path: root/accel/tcg
diff options
context:
space:
mode:
authorRichard Henderson2020-10-29 06:49:42 +0100
committerRichard Henderson2021-01-07 16:09:42 +0100
commita8c35b2cadfc7bef5221ceee0725493461568528 (patch)
treec216f79f95c50877a229a710eed2001d98121cc8 /accel/tcg
parenttcg: Add --accel tcg,split-wx property (diff)
downloadqemu-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>
Diffstat (limited to 'accel/tcg')
-rw-r--r--accel/tcg/translate-all.c84
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)