There's a change in mprotect() behaviour [1] in the latest macOS on M1 and it's not yet clear if it's going to be fixed by Apple.
In this case, instead of changing permissions of N guard pages, we change permissions of N rwx regions. The same number of syscalls are required either way. [1] https://gist.github.com/hikalium/75ae822466ee4da13cbbe486498a191f Buglink: https://bugs.launchpad.net/qemu/+bug/1914849 Signed-off-by: Richard Henderson <richard.hender...@linaro.org> --- tcg/region.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tcg/region.c b/tcg/region.c index fac416ebf5..53f78965c7 100644 --- a/tcg/region.c +++ b/tcg/region.c @@ -765,12 +765,15 @@ static int alloc_code_gen_buffer(size_t size, int splitwx, Error **errp) error_free_or_abort(errp); } - prot = PROT_READ | PROT_WRITE | PROT_EXEC; + /* + * macOS 11.2 has a bug (Apple Feedback FB8994773) in which mprotect + * rejects a permission change from RWX -> NONE when reserving the + * guard pages later. We can go the other way with the same number + * of syscalls, so always begin with PROT_NONE. + */ + prot = PROT_NONE; flags = MAP_PRIVATE | MAP_ANONYMOUS; -#ifdef CONFIG_TCG_INTERPRETER - /* The tcg interpreter does not need execute permission. */ - prot = PROT_READ | PROT_WRITE; -#elif defined(CONFIG_DARWIN) +#ifdef CONFIG_DARWIN /* Applicable to both iOS and macOS (Apple Silicon). */ if (!splitwx) { flags |= MAP_JIT; -- 2.25.1