No longer need SPRR and probe it runtime
This commit is contained in:
@@ -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)
|
static bool tb_exec_is_locked(struct uc_struct *uc)
|
||||||
{
|
{
|
||||||
return uc->current_executable;
|
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)
|
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) {
|
if (uc->current_executable != executable) {
|
||||||
jit_write_protect(executable);
|
jit_write_protect(executable);
|
||||||
uc->current_executable = executable;
|
uc->current_executable = executable;
|
||||||
assert(
|
assert_executable(executable);
|
||||||
executable == thread_executable()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else /* not needed on non-Darwin platforms */
|
#else /* not needed on non-Darwin platforms */
|
||||||
|
|||||||
7
qemu/configure
vendored
7
qemu/configure
vendored
@@ -2155,11 +2155,17 @@ int main() {
|
|||||||
|
|
||||||
// In Apple Hypervisor, this value is not accessbile and
|
// In Apple Hypervisor, this value is not accessbile and
|
||||||
// pthread_jit_write_protect_np essentially is a no-op
|
// pthread_jit_write_protect_np essentially is a no-op
|
||||||
|
|
||||||
|
/*
|
||||||
if (!commpage_sprr) {
|
if (!commpage_sprr) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Now it is accessible but always zero, let's probe it runtime.
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
if ! compile_prog ""; then
|
if ! compile_prog ""; then
|
||||||
@@ -2171,7 +2177,6 @@ EOF
|
|||||||
have_sprr='yes'
|
have_sprr='yes'
|
||||||
else
|
else
|
||||||
have_sprr='no'
|
have_sprr='no'
|
||||||
have_pthread_jit_protect='no'
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -25,18 +25,18 @@
|
|||||||
#ifndef TCG_APPLE_JIT_H
|
#ifndef TCG_APPLE_JIT_H
|
||||||
#define 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 */
|
#if defined(__APPLE__) && defined(HAVE_SPRR) && (defined(__arm__) || defined(__aarch64__))
|
||||||
static inline void jit_write_protect(int enabled)
|
|
||||||
{
|
|
||||||
return pthread_jit_write_protect_np(enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the S3_6_c15_c1_5 register's value
|
// Returns the S3_6_c15_c1_5 register's value
|
||||||
// Taken from
|
// Taken from
|
||||||
// https://stackoverflow.com/questions/70019553/lldb-how-to-read-the-permissions-of-a-memory-region-for-a-thread
|
// 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/
|
// 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)
|
static inline uint64_t read_sprr_perm(void)
|
||||||
{
|
{
|
||||||
uint64_t v;
|
uint64_t v;
|
||||||
@@ -50,7 +50,11 @@ __attribute__((unused)) static inline uint8_t thread_mask()
|
|||||||
{
|
{
|
||||||
uint64_t v = read_sprr_perm();
|
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()
|
__attribute__((unused)) static inline bool thread_writeable()
|
||||||
@@ -63,25 +67,69 @@ __attribute__((unused)) static inline bool thread_executable()
|
|||||||
return thread_mask() == 1;
|
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) \
|
#define JIT_CALLBACK_GUARD(x) \
|
||||||
{ \
|
{ \
|
||||||
bool executable = uc->current_executable; \
|
bool executable = uc->current_executable; \
|
||||||
assert (executable == thread_executable()); \
|
assert_executable(executable); \
|
||||||
x; \
|
x; \
|
||||||
if (executable != thread_executable()) { \
|
jit_write_protect(executable); \
|
||||||
jit_write_protect(executable); \
|
|
||||||
} \
|
|
||||||
} \
|
} \
|
||||||
|
|
||||||
|
|
||||||
#define JIT_CALLBACK_GUARD_VAR(var, x) \
|
#define JIT_CALLBACK_GUARD_VAR(var, x) \
|
||||||
{ \
|
{ \
|
||||||
bool executable = uc->current_executable; \
|
bool executable = uc->current_executable; \
|
||||||
assert (executable == thread_executable()); \
|
assert_executable(executable); \
|
||||||
var = x; \
|
var = x; \
|
||||||
if (executable != thread_executable()) { \
|
jit_write_protect(executable); \
|
||||||
jit_write_protect(executable); \
|
|
||||||
} \
|
|
||||||
} \
|
} \
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
5
uc.c
5
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_snapshot(uc_engine *uc);
|
||||||
static uc_err uc_restore_latest_snapshot(uc_engine *uc);
|
static uc_err uc_restore_latest_snapshot(uc_engine *uc);
|
||||||
|
|
||||||
#if defined(__APPLE__) && defined(HAVE_PTHREAD_JIT_PROTECT) && \
|
#if defined(__APPLE__) && defined(HAVE_PTHREAD_JIT_PROTECT) && (defined(__arm__) || defined(__aarch64__))
|
||||||
defined(HAVE_SPRR) && (defined(__arm__) || defined(__aarch64__))
|
|
||||||
static void save_jit_state(uc_engine *uc)
|
static void save_jit_state(uc_engine *uc)
|
||||||
{
|
{
|
||||||
if (!uc->nested) {
|
if (!uc->nested) {
|
||||||
@@ -51,7 +50,7 @@ static void restore_jit_state(uc_engine *uc)
|
|||||||
{
|
{
|
||||||
assert(uc->nested > 0);
|
assert(uc->nested > 0);
|
||||||
if (uc->nested == 1) {
|
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->current_executable != uc->thread_executable_entry) {
|
||||||
if (uc->thread_executable_entry) {
|
if (uc->thread_executable_entry) {
|
||||||
jit_write_protect(true);
|
jit_write_protect(true);
|
||||||
|
|||||||
Reference in New Issue
Block a user