From 958ed091536ad2deb5a792f744af24be5be54b6b Mon Sep 17 00:00:00 2001 From: lazymio Date: Sat, 7 Dec 2024 23:33:34 +0800 Subject: [PATCH] No longer need SPRR and probe it runtime --- qemu/accel/tcg/translate-all.c | 8 ++-- qemu/configure | 7 ++- qemu/include/tcg/tcg-apple-jit.h | 78 ++++++++++++++++++++++++++------ uc.c | 5 +- 4 files changed, 74 insertions(+), 24 deletions(-) diff --git a/qemu/accel/tcg/translate-all.c b/qemu/accel/tcg/translate-all.c index 366f3a4f..3f6d2630 100644 --- a/qemu/accel/tcg/translate-all.c +++ b/qemu/accel/tcg/translate-all.c @@ -2172,7 +2172,7 @@ void tcg_flush_softmmu_tlb(struct uc_struct *uc) } -#if defined(__APPLE__) && defined(HAVE_PTHREAD_JIT_PROTECT) && defined(HAVE_SPRR) && (defined(__arm__) || defined(__aarch64__)) +#if defined(__APPLE__) && defined(HAVE_PTHREAD_JIT_PROTECT) && (defined(__arm__) || defined(__aarch64__)) static bool tb_exec_is_locked(struct uc_struct *uc) { return uc->current_executable; @@ -2180,13 +2180,11 @@ static bool tb_exec_is_locked(struct uc_struct *uc) static void tb_exec_change(struct uc_struct *uc, bool executable) { - assert(uc->current_executable == thread_executable()); + assert_executable(uc->current_executable); if (uc->current_executable != executable) { jit_write_protect(executable); uc->current_executable = executable; - assert( - executable == thread_executable() - ); + assert_executable(executable); } } #else /* not needed on non-Darwin platforms */ diff --git a/qemu/configure b/qemu/configure index bd97f5c8..9d17e009 100755 --- a/qemu/configure +++ b/qemu/configure @@ -2155,11 +2155,17 @@ int main() { // In Apple Hypervisor, this value is not accessbile and // pthread_jit_write_protect_np essentially is a no-op + + /* if (!commpage_sprr) { return 1; } else { return 0; } + */ + + // Now it is accessible but always zero, let's probe it runtime. + return 0; } EOF if ! compile_prog ""; then @@ -2171,7 +2177,6 @@ EOF have_sprr='yes' else have_sprr='no' - have_pthread_jit_protect='no' fi fi fi diff --git a/qemu/include/tcg/tcg-apple-jit.h b/qemu/include/tcg/tcg-apple-jit.h index 9c86b3a2..0cf9146a 100644 --- a/qemu/include/tcg/tcg-apple-jit.h +++ b/qemu/include/tcg/tcg-apple-jit.h @@ -25,18 +25,18 @@ #ifndef TCG_APPLE_JIT_H #define TCG_APPLE_JIT_H -#if defined(__APPLE__) && defined(HAVE_PTHREAD_JIT_PROTECT) && defined(HAVE_SPRR) && (defined(__arm__) || defined(__aarch64__)) +#include "assert.h" +#include "stdint.h" +#include "stdlib.h" +#include "stdbool.h" -/* write protect enable = write disable */ -static inline void jit_write_protect(int enabled) -{ - return pthread_jit_write_protect_np(enabled); -} +#if defined(__APPLE__) && defined(HAVE_SPRR) && (defined(__arm__) || defined(__aarch64__)) // Returns the S3_6_c15_c1_5 register's value // Taken from // https://stackoverflow.com/questions/70019553/lldb-how-to-read-the-permissions-of-a-memory-region-for-a-thread // https://blog.svenpeter.dev/posts/m1_sprr_gxf/ +// On Github Action (Virtualized environment), this shall always returns 0 static inline uint64_t read_sprr_perm(void) { uint64_t v; @@ -50,7 +50,11 @@ __attribute__((unused)) static inline uint8_t thread_mask() { uint64_t v = read_sprr_perm(); - return (v >> 20) & 3; + if (v == 0) { + return 0; + } else { + return (v >> 20) & 3; + } } __attribute__((unused)) static inline bool thread_writeable() @@ -63,25 +67,69 @@ __attribute__((unused)) static inline bool thread_executable() return thread_mask() == 1; } +static inline void assert_executable(bool executable) { + uint64_t v = read_sprr_perm(); + + if (!v) { + assert(executable == thread_executable()); + } +} + +#else + +// Returns the S3_6_c15_c1_5 register's value +// Taken from +// https://stackoverflow.com/questions/70019553/lldb-how-to-read-the-permissions-of-a-memory-region-for-a-thread +// https://blog.svenpeter.dev/posts/m1_sprr_gxf/ +static inline uint64_t read_sprr_perm(void) +{ + return 0; +} + +__attribute__((unused)) static inline uint8_t thread_mask() +{ + return 0; +} + +__attribute__((unused)) static inline bool thread_writeable() +{ + return false; +} + +__attribute__((unused)) static inline bool thread_executable() +{ + return false; +} + +static inline void assert_executable(bool executable) { +} + +#endif + + +#if defined(__APPLE__) && defined(HAVE_PTHREAD_JIT_PROTECT) && defined(HAVE_SPRR) && (defined(__arm__) || defined(__aarch64__)) + +/* write protect enable = write disable */ +static inline void jit_write_protect(int enabled) +{ + return pthread_jit_write_protect_np(enabled); +} + #define JIT_CALLBACK_GUARD(x) \ { \ bool executable = uc->current_executable; \ - assert (executable == thread_executable()); \ + assert_executable(executable); \ x; \ - if (executable != thread_executable()) { \ - jit_write_protect(executable); \ - } \ + jit_write_protect(executable); \ } \ #define JIT_CALLBACK_GUARD_VAR(var, x) \ { \ bool executable = uc->current_executable; \ - assert (executable == thread_executable()); \ + assert_executable(executable); \ var = x; \ - if (executable != thread_executable()) { \ - jit_write_protect(executable); \ - } \ + jit_write_protect(executable); \ } \ diff --git a/uc.c b/uc.c index 5f6a35f9..895bd4fa 100644 --- a/uc.c +++ b/uc.c @@ -35,8 +35,7 @@ static void clear_deleted_hooks(uc_engine *uc); static uc_err uc_snapshot(uc_engine *uc); static uc_err uc_restore_latest_snapshot(uc_engine *uc); -#if defined(__APPLE__) && defined(HAVE_PTHREAD_JIT_PROTECT) && \ - defined(HAVE_SPRR) && (defined(__arm__) || defined(__aarch64__)) +#if defined(__APPLE__) && defined(HAVE_PTHREAD_JIT_PROTECT) && (defined(__arm__) || defined(__aarch64__)) static void save_jit_state(uc_engine *uc) { if (!uc->nested) { @@ -51,7 +50,7 @@ static void restore_jit_state(uc_engine *uc) { assert(uc->nested > 0); if (uc->nested == 1) { - assert(uc->current_executable == thread_executable()); + assert_executable(uc->current_executable); if (uc->current_executable != uc->thread_executable_entry) { if (uc->thread_executable_entry) { jit_write_protect(true);