Skip to content

Commit

Permalink
No longer need SPRR and probe it runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
wtdcode committed Dec 7, 2024
1 parent b719926 commit 958ed09
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 24 deletions.
8 changes: 3 additions & 5 deletions qemu/accel/tcg/translate-all.c
Original file line number Diff line number Diff line change
Expand Up @@ -2172,21 +2172,19 @@ 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;
}

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 */
Expand Down
7 changes: 6 additions & 1 deletion qemu/configure
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -2171,7 +2177,6 @@ EOF
have_sprr='yes'
else
have_sprr='no'
have_pthread_jit_protect='no'
fi
fi
fi
Expand Down
78 changes: 63 additions & 15 deletions qemu/include/tcg/tcg-apple-jit.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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()
Expand All @@ -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); \
} \


Expand Down
5 changes: 2 additions & 3 deletions uc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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);
Expand Down

0 comments on commit 958ed09

Please sign in to comment.