Skip to content

Commit

Permalink
Get rid of MAP_FIXED that can cause memory corruption on Mac ARM, rem…
Browse files Browse the repository at this point in the history
…oved unnecessary APPLE checks
  • Loading branch information
aglab2 committed Jan 17, 2023
1 parent 197957d commit 3b4fffd
Show file tree
Hide file tree
Showing 17 changed files with 56 additions and 109 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,4 @@ Release/

new_dynarec_debug.txt
new_dynarec_disasm.txt
*.zip
4 changes: 0 additions & 4 deletions libretro/libretro.c
Original file line number Diff line number Diff line change
Expand Up @@ -2085,10 +2085,6 @@ static void format_saved_memory(void)

bool retro_load_game(const struct retro_game_info *game)
{
#if defined(__APPLE__) && defined(__arm64__)
extern void new_dynarec_create_mapping();
new_dynarec_create_mapping();
#endif
format_saved_memory();

update_variables(true);
Expand Down
2 changes: 1 addition & 1 deletion mupen64plus-core/src/memory/m64p_memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
#include <stddef.h>
#include <stdint.h>

#if !defined(__APPLE__) || !defined(__arm64__)
#if !defined(__arm64__)
#if NEW_DYNAREC < NEW_DYNAREC_ARM
// address : address of the read/write operation being done
uint32_t address = 0;
Expand Down
4 changes: 2 additions & 2 deletions mupen64plus-core/src/memory/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@
#define write_hword_in_memory() writememh[mupencoreaddress >>16]()
#define write_dword_in_memory() writememd[mupencoreaddress >>16]()

#if !defined(__APPLE__) || !defined(__arm64__)
#if !defined(__arm64__)
extern uint32_t address, cpu_word;
extern uint8_t cpu_byte;
extern uint16_t cpu_hword;
extern uint64_t cpu_dword;
#define mupencoreaddress address
#else
#include "../r4300/new_dynarec/arm64/apple_memory_layout.h"
#include "../r4300/new_dynarec/arm64/memory_layout_arm64.h"
#define mupencoreaddress (RECOMPILER_MEMORY->rml_address)
#define cpu_word (RECOMPILER_MEMORY->rml_cpu_word)
#define cpu_byte (RECOMPILER_MEMORY->rml_cpu_byte)
Expand Down
2 changes: 1 addition & 1 deletion mupen64plus-core/src/r4300/cp0.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
#endif

/* global variable */
#if !defined(__APPLE__) || !defined(__arm64__)
#if !defined(__arm64__)
#if NEW_DYNAREC < NEW_DYNAREC_ARM
/* ARM backend requires a different memory layout
* and therefore manually allocate that variable */
Expand Down
4 changes: 2 additions & 2 deletions mupen64plus-core/src/r4300/cp0_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@

#include "cp0.h"

#if !defined(__APPLE__) || !defined(__arm64__)
#if !defined(__arm64__)
extern uint32_t g_cp0_regs[CP0_REGS_COUNT];
#else
#include "new_dynarec/arm64/apple_memory_layout.h"
#include "new_dynarec/arm64/memory_layout_arm64.h"
#define g_cp0_regs (RECOMPILER_MEMORY->rml_g_cp0_regs)
#endif

Expand Down
4 changes: 2 additions & 2 deletions mupen64plus-core/src/r4300/cp1.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

#include "new_dynarec/new_dynarec.h"

#if !defined(__APPLE__) || !defined(__arm64__)
#if !defined(__arm64__)
#if NEW_DYNAREC < NEW_DYNAREC_ARM
float *reg_cop1_simple[32];
double *reg_cop1_double[32];
Expand All @@ -35,7 +35,7 @@ uint32_t FCR0, FCR31;
#else
/* ARM backend requires a different memory layout
* and therefore manually allocates these variables */
#include "new_dynarec/arm64/apple_memory_layout.h"
#include "new_dynarec/arm64/memory_layout_arm64.h"
#define reg_cop1_simple (RECOMPILER_MEMORY->rml_reg_cop1_simple)
#define reg_cop1_double (RECOMPILER_MEMORY->rml_reg_cop1_double)
#define FCR0 (RECOMPILER_MEMORY->rml_FCR0)
Expand Down
4 changes: 2 additions & 2 deletions mupen64plus-core/src/r4300/cp1_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@

#include "cp1.h"

#if !defined(__APPLE__) || !defined(__arm64__)
#if !defined(__arm64__)
extern float *reg_cop1_simple[32];
extern double *reg_cop1_double[32];
extern uint32_t FCR0, FCR31;
#else
#include "new_dynarec/arm64/apple_memory_layout.h"
#include "new_dynarec/arm64/memory_layout_arm64.h"
#define reg_cop1_simple (RECOMPILER_MEMORY->rml_reg_cop1_simple)
#define reg_cop1_double (RECOMPILER_MEMORY->rml_reg_cop1_double)
#define FCR0 (RECOMPILER_MEMORY->rml_FCR0)
Expand Down
9 changes: 1 addition & 8 deletions mupen64plus-core/src/r4300/new_dynarec/arm64/assem_arm64.c
Original file line number Diff line number Diff line change
Expand Up @@ -313,14 +313,10 @@ static void set_jump_target(intptr_t addr,uintptr_t target)
static void *dynamic_linker_impl(void * src, u_int vaddr);
static void *dynamic_linker(void * src, u_int vaddr)
{
#if defined(__APPLE__) && defined(__arm64__)
apple_jit_wx_unprotect_enter();
void* r = dynamic_linker_impl(src, vaddr);
apple_jit_wx_unprotect_exit();
return r;
#else
return dynamic_linker_impl(src, vaddr);
#endif
}

static void *dynamic_linker_impl(void * src, u_int vaddr)
Expand Down Expand Up @@ -427,14 +423,10 @@ static void *dynamic_linker_impl(void * src, u_int vaddr)
static void *dynamic_linker_ds_impl(void * src, u_int vaddr);
static void *dynamic_linker_ds(void * src, u_int vaddr)
{
#if defined(__APPLE__) && defined(__arm64__)
apple_jit_wx_unprotect_enter();
void* r = dynamic_linker_ds_impl(src, vaddr);
apple_jit_wx_unprotect_exit();
return r;
#else
return dynamic_linker_ds_impl(src, vaddr);
#endif
}

static void *dynamic_linker_ds_impl(void * src, u_int vaddr)
Expand Down Expand Up @@ -6763,6 +6755,7 @@ static void arch_init(void) {
jump_table_symbols[18] = (intptr_t) cached_interpreter_table.TLBP;
#endif

trampoline_init(base_addr);
apple_jit_wx_unprotect_enter();
trampolines_reg_jump_t jumps = trampoline_alloc_reg_jump(&jump_vaddr);
apple_jit_wx_unprotect_exit();
Expand Down
2 changes: 1 addition & 1 deletion mupen64plus-core/src/r4300/new_dynarec/arm64/assem_arm64.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ void write_rdramd_new(void);
void breakpoint(void);

#ifdef __APPLE__
#include "apple_memory_layout.h"
#include "memory_layout_arm64.h"
#define invc_ptr (RECOMPILER_MEMORY->rml_invc_ptr)
#define cycle_count (RECOMPILER_MEMORY->rml_cycle_count)
#define last_count (RECOMPILER_MEMORY->rml_last_count)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,11 +289,8 @@ GLOBAL_FUNCTION(_jump_eret):
b .E8

GLOBAL_FUNCTION(_new_dyna_start):
adrp x1, _base_addr@PAGE
add x1, x1, _base_addr@PAGEOFF
ldr x16, [x1] /* _extra_memory=base_addr */
mov x17, #0x2000000
add x16, x16, x17 /* _dynarec_local */
adrp x16, _memory_layout@PAGE
add x16, x16, _memory_layout@PAGEOFF
add x16, x16, #152
mov w0, #0xa4000000
stp x19,x20,[x16,#0]
Expand All @@ -303,6 +300,8 @@ GLOBAL_FUNCTION(_new_dyna_start):
stp x27,x28,[x16,#64]
stp x29,x30,[x16,#80]
sub x29, x16, #152
adrp x1, _base_addr@PAGE
add x1, x1, _base_addr@PAGEOFF
ldr x19, [x1]
add w0, w0, #0x40
bl _new_recompile_block
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
#pragma once
#ifndef M64P_MEMORY_LAYOUT_ARM64_H
#define M64P_MEMORY_LAYOUT_ARM64_H

#ifdef __APPLE__
#include <stdint.h>
#ifdef __APPLE__
#include <sys/types.h>
#endif

#include "../../recomp_types.h"

typedef struct recompiler_memory_layout
{
char rml_extra_memory[0x2000000]; // rwx memory
char rml_dynarec_local[256];
uint32_t rml_next_interrupt;
int rml_cycle_count;
Expand Down Expand Up @@ -44,12 +46,12 @@ typedef struct recompiler_memory_layout
uint64_t rml_memory_map[1048576];
} recompiler_memory_layout_t;

extern recompiler_memory_layout_t* base_addr;
#define RECOMPILER_MEMORY (base_addr)
extern recompiler_memory_layout_t memory_layout;
#define RECOMPILER_MEMORY (&memory_layout)

// Copied from linkage_aarch64.S declaration
#define RML_SIZE_EXTRA_MEMORY 0
#define RML_SIZE_DYNAREC_LOCAL RML_SIZE_EXTRA_MEMORY + 33554432
#define RML_SIZE_DYNAREC_LOCAL RML_SIZE_EXTRA_MEMORY + 0
#define RML_SIZE_NEXT_INTERRUPT RML_SIZE_DYNAREC_LOCAL + 256
#define RML_SIZE_CYCLE_COUNT RML_SIZE_NEXT_INTERRUPT + 4
#define RML_SIZE_LAST_COUNT RML_SIZE_CYCLE_COUNT + 4
Expand Down Expand Up @@ -82,6 +84,7 @@ extern recompiler_memory_layout_t* base_addr;
#define RML_SIZE_LINK_REGISTER RML_SIZE_INSTR_ADDR + 8
#define RML_SIZE_MEMORY_MAP RML_SIZE_LINK_REGISTER + 8

#if __STDC_VERSION__ > 201112L
#define RML_CHECK_SIZE(name, off) _Static_assert(offsetof(recompiler_memory_layout_t, name) == (off), "Recompiler layout for '" #name "' does not match asm")
RML_CHECK_SIZE(rml_dynarec_local , RML_SIZE_DYNAREC_LOCAL);
RML_CHECK_SIZE(rml_next_interrupt , RML_SIZE_NEXT_INTERRUPT);
Expand Down Expand Up @@ -116,5 +119,6 @@ RML_CHECK_SIZE(rml_instr_addr , RML_SIZE_INSTR_ADDR);
RML_CHECK_SIZE(rml_link_register , RML_SIZE_LINK_REGISTER);
RML_CHECK_SIZE(rml_memory_map , RML_SIZE_MEMORY_MAP);
#undef RML_CHECK_SIZE
#endif

#endif
4 changes: 2 additions & 2 deletions mupen64plus-core/src/r4300/new_dynarec/new_dynarec.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
#define NEW_DYNAREC_ARM 3
#define NEW_DYNAREC_ARM64 4

#if !defined(__APPLE__) || !defined(__arm64__)
#if !defined(__arm64__)
#ifdef __cplusplus
extern "C" {
#endif
Expand All @@ -40,7 +40,7 @@ extern int pending_exception;
}
#endif
#else
#include "arm64/apple_memory_layout.h"
#include "arm64/memory_layout_arm64.h"
#define pcaddr (RECOMPILER_MEMORY->rml_pcaddr)
#define pending_exception (RECOMPILER_MEMORY->rml_pending_exception)
#endif
Expand Down
90 changes: 22 additions & 68 deletions mupen64plus-core/src/r4300/new_dynarec/new_dynarec_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
#include "arm/assem_arm.h"
#elif NEW_DYNAREC == NEW_DYNAREC_ARM64
#include "arm64/apple_jit_protect.h"
#include "arm64/apple_memory_layout.h"
#include "arm64/memory_layout_arm64.h"
#include "arm64/assem_arm64.h"
#else
#error Unsupported dynarec architecture
Expand Down Expand Up @@ -107,11 +107,10 @@ struct ll_entry
struct ll_entry *next;
};

#ifdef __APPLE__
recompiler_memory_layout_t* base_addr = NULL;
#else
void *base_addr = NULL;
#ifdef __arm64__
recompiler_memory_layout_t memory_layout;
#endif
void *base_addr = NULL;

u_char *out;
ALIGN(16, uintptr_t hash_table[65536][4]);
Expand Down Expand Up @@ -1305,6 +1304,7 @@ void invalidate_block(u_int block)
#ifdef USE_MINI_HT
memset(mini_ht,-1,sizeof(mini_ht));
#endif

apple_jit_wx_unprotect_exit();
}

Expand Down Expand Up @@ -7752,57 +7752,6 @@ static void disassemble_inst(int i)
}
#endif

#if defined(__APPLE__) && defined(__arm64__)
#include "arm64/trampoline_arm64.h"

void new_dynarec_create_mapping(void)
{
if (base_addr)
return;

// For Mac ARM (and it can be ported to other ARM64 platforms), we want a special layout
// <- 0x2000000 -> |
// -------------------|-------------------|-------------------
// RW^X ^ RW^X ^ RW
// base_addr dynarec_local

// pre base_addr is trampolines we need to have, growing like a stack downwards
// after base_addr is normal JIT stuff generated
// We also want addresses to be in 32-bit space because there are some casts to 32bit unsigned int

// On macOS we are not allowed to use MAP_FIXED with MAP_JIT so allocate first 2 segments together, then use MAP_FIXED for RW segment
// This is a stupid hack - we want part of mapping to be RWX and other part of map to be RW
// We hope that the 2nd map wont fail but really this should just do it couple hundred times

#define ATTEMPTS_COUNT 1000

for (int i = 0; i < ATTEMPTS_COUNT; i++)
{
char* addr = (char*) mmap(NULL, 2 * (1<<TARGET_SIZE_2), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE | MAP_JIT, -1, 0);
if (addr == MAP_FAILED)
{
DebugMessage(M64MSG_ERROR, "mmap() for JIT failed: %d[%s]", errno, strerror(errno));
return;
}

// now we need need to attach the RW buffer right after
void* expected_rw_addr = addr + 2 * (1<<TARGET_SIZE_2);
void* rw_addr = mmap(expected_rw_addr, 1 << TARGET_SIZE_2, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
if (rw_addr == MAP_FAILED)
{
DebugMessage(M64MSG_WARNING, "Failed to append RW pages at %p after JIT pages to %p", expected_rw_addr, addr);
continue;
}

// We have everything setup now, can use base_addr
base_addr = (recompiler_memory_layout_t*) (addr + (1<<TARGET_SIZE_2));
trampoline_init(base_addr);
// TODO DK: debug without this break for large addresses
break;
}
}
#endif

void new_dynarec_init(void)
{
#ifdef NEW_DYNAREC_DEBUG
Expand All @@ -7815,15 +7764,25 @@ void new_dynarec_init(void)
#ifndef PROFILER
DebugMessage(M64MSG_INFO, "Init new dynarec");

#if !defined(__APPLE__) || !defined(__arm64__)
#if NEW_DYNAREC >= NEW_DYNAREC_ARM
if ((base_addr = mmap ((u_char *)BASE_ADDR, 1<<TARGET_SIZE_2,
#if defined(__arm64__)
// trampolines are put behind the base_addr so allocate a bit extra memory
// TODO: Don't allocate 32MB, it is definitely too much
if ((base_addr = mmap (NULL, 2 * (1<<TARGET_SIZE_2),
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS
MAP_PRIVATE | MAP_ANONYMOUS
#ifdef __APPLE__
| MAP_JIT
#endif
,
,
-1, 0)) <= 0) {DebugMessage(M64MSG_ERROR, "mmap() failed");}

DebugMessage(M64MSG_INFO, "MAP_JIT pages are allocated at %p", base_addr);
base_addr = ((char*)base_addr) + (1<<TARGET_SIZE_2);
#else
#if NEW_DYNAREC >= NEW_DYNAREC_ARM
if ((base_addr = mmap ((u_char *)BASE_ADDR, 1<<TARGET_SIZE_2,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0)) <= 0) {DebugMessage(M64MSG_ERROR, "mmap() failed");}
#else
#if defined(WIN32)
Expand Down Expand Up @@ -7909,8 +7868,8 @@ void new_dynarec_cleanup(void)
#endif
int n;

#if defined(__APPLE__) && defined(__arm64__)
// We are not doing anything, too unsafe
#if defined(__arm64__)
if (munmap (((char*)base_addr) - (1<<TARGET_SIZE_2), 2 * (1<<TARGET_SIZE_2)) < 0) {DebugMessage(M64MSG_ERROR, "munmap() failed");}
#else
#if defined(WIN32)
VirtualFree(base_addr, 0, MEM_RELEASE);
Expand All @@ -7933,14 +7892,10 @@ void new_dynarec_cleanup(void)
static int new_recompile_block_impl(int addr);
int new_recompile_block(int addr)
{
#if defined(__APPLE__) && defined(__arm64__)
apple_jit_wx_unprotect_enter();
int r = new_recompile_block_impl(addr);
apple_jit_wx_unprotect_exit();
return r;
#else
return new_recompile_block_impl(addr);
#endif
}

static int new_recompile_block_impl(int addr)
Expand Down Expand Up @@ -7983,7 +7938,6 @@ static int new_recompile_block_impl(int addr)
else {
assem_debug("Compile at unmapped memory address: %x ", (int)addr);
assem_debug("start: %x next: %x",memory_map[start>>12],memory_map[(start+4096)>>12]);
__builtin_debugtrap();
return 1; // Caller will invoke exception handler
}
//DebugMessage(M64MSG_VERBOSE, "source= %x",(intptr_t)source);
Expand Down
Loading

0 comments on commit 3b4fffd

Please sign in to comment.