aboutsummaryrefslogtreecommitdiff
path: root/src/ARMJIT_Memory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ARMJIT_Memory.cpp')
-rw-r--r--src/ARMJIT_Memory.cpp303
1 files changed, 218 insertions, 85 deletions
diff --git a/src/ARMJIT_Memory.cpp b/src/ARMJIT_Memory.cpp
index d321d2f..33d6bcf 100644
--- a/src/ARMJIT_Memory.cpp
+++ b/src/ARMJIT_Memory.cpp
@@ -1,5 +1,6 @@
#if defined(__SWITCH__)
-#include "switch/compat_switch.h"
+#include <switch.h>
+#include "frontend/switch/FaultHandler.h"
#elif defined(_WIN32)
#include <windows.h>
#else
@@ -10,6 +11,12 @@
#include <signal.h>
#endif
+#if defined(__ANDROID__)
+#include <dlfcn.h>
+#include <linux/ashmem.h>
+#include <sys/ioctl.h>
+#endif
+
#include "ARMJIT_Memory.h"
#include "ARMJIT_Internal.h"
@@ -22,7 +29,7 @@
#include "NDSCart.h"
#include "SPU.h"
-#include <malloc.h>
+#include <stdlib.h>
/*
We're handling fastmem here.
@@ -40,7 +47,8 @@
We handle this by only mapping those regions which are actually
used and by praying the games don't go wild.
- Beware, this file is full of platform specific code.
+ Beware, this file is full of platform specific code and copied
+ from Dolphin, so enjoy the copied comments!
*/
@@ -49,12 +57,16 @@ namespace ARMJIT_Memory
struct FaultDescription
{
u32 EmulatedFaultAddr;
- u64 FaultPC;
+ u8* FaultPC;
};
-bool FaultHandler(FaultDescription* faultDesc, s32& offset);
+bool FaultHandler(FaultDescription& faultDesc);
}
+#if defined(__ANDROID__)
+#define ASHMEM_DEVICE "/dev/ashmem"
+#endif
+
#if defined(__SWITCH__)
// with LTO the symbols seem to be not properly overriden
// if they're somewhere else
@@ -75,7 +87,7 @@ void __libnx_exception_handler(ThreadExceptionDump* ctx)
ARMJIT_Memory::FaultDescription desc;
u8* curArea = (u8*)(NDS::CurCPU == 0 ? ARMJIT_Memory::FastMem9Start : ARMJIT_Memory::FastMem7Start);
desc.EmulatedFaultAddr = (u8*)ctx->far.x - curArea;
- desc.FaultPC = ctx->pc.x;
+ desc.FaultPC = (u8*)ctx->pc.x;
u64 integerRegisters[33];
memcpy(integerRegisters, &ctx->cpu_gprs[0].x, 8*29);
@@ -84,23 +96,14 @@ void __libnx_exception_handler(ThreadExceptionDump* ctx)
integerRegisters[31] = ctx->sp.x;
integerRegisters[32] = ctx->pc.x;
- s32 offset;
- if (ARMJIT_Memory::FaultHandler(&desc, offset))
+ if (ARMJIT_Memory::FaultHandler(desc))
{
- integerRegisters[32] += offset;
+ integerRegisters[32] = (u64)desc.FaultPC;
ARM_RestoreContext(integerRegisters);
}
- if (ctx->pc.x >= (u64)&__start__ && ctx->pc.x < (u64)&__rodata_start)
- {
- printf("unintentional fault in .text at 0x%x (type %d) (trying to access 0x%x?)\n",
- ctx->pc.x - (u64)&__start__, ctx->error_desc, ctx->far.x);
- }
- else
- {
- printf("unintentional fault somewhere in deep (address) space at %x (type %d)\n", ctx->pc.x, ctx->error_desc);
- }
+ HandleFault(ctx->pc.x, ctx->lr.x, ctx->fp.x, ctx->far.x, ctx->error_desc);
}
}
@@ -117,12 +120,11 @@ static LONG ExceptionHandler(EXCEPTION_POINTERS* exceptionInfo)
ARMJIT_Memory::FaultDescription desc;
u8* curArea = (u8*)(NDS::CurCPU == 0 ? ARMJIT_Memory::FastMem9Start : ARMJIT_Memory::FastMem7Start);
desc.EmulatedFaultAddr = (u8*)exceptionInfo->ExceptionRecord->ExceptionInformation[1] - curArea;
- desc.FaultPC = exceptionInfo->ContextRecord->Rip;
+ desc.FaultPC = (u8*)exceptionInfo->ContextRecord->Rip;
- s32 offset = 0;
- if (ARMJIT_Memory::FaultHandler(&desc, offset))
+ if (ARMJIT_Memory::FaultHandler(desc))
{
- exceptionInfo->ContextRecord->Rip += offset;
+ exceptionInfo->ContextRecord->Rip = (u64)desc.FaultPC;
return EXCEPTION_CONTINUE_EXECUTION;
}
@@ -131,50 +133,84 @@ static LONG ExceptionHandler(EXCEPTION_POINTERS* exceptionInfo)
#else
-struct sigaction NewSa;
-struct sigaction OldSa;
+static struct sigaction OldSaSegv;
+static struct sigaction OldSaBus;
static void SigsegvHandler(int sig, siginfo_t* info, void* rawContext)
{
+ if (sig != SIGSEGV && sig != SIGBUS)
+ {
+ // We are not interested in other signals - handle it as usual.
+ return;
+ }
+ if (info->si_code != SEGV_MAPERR && info->si_code != SEGV_ACCERR)
+ {
+ // Huh? Return.
+ return;
+ }
+
ucontext_t* context = (ucontext_t*)rawContext;
-
+
ARMJIT_Memory::FaultDescription desc;
u8* curArea = (u8*)(NDS::CurCPU == 0 ? ARMJIT_Memory::FastMem9Start : ARMJIT_Memory::FastMem7Start);
#ifdef __x86_64__
desc.EmulatedFaultAddr = (u8*)info->si_addr - curArea;
- desc.FaultPC = context->uc_mcontext.gregs[REG_RIP];
+ #ifdef __APPLE__
+ desc.FaultPC = (u8*)context->uc_mcontext->__ss.__rip;
+ #else
+ desc.FaultPC = (u8*)context->uc_mcontext.gregs[REG_RIP];
+ #endif
+
#else
- desc.EmulatedFaultAddr = (u8*)context->uc_mcontext.fault_address - curArea;
- desc.FaultPC = context->uc_mcontext.pc;
+ #ifdef __APPLE__
+ desc.EmulatedFaultAddr = (u8*)context->uc_mcontext->__es.__far - curArea;
+ desc.FaultPC = (u8*)context->uc_mcontext->__ss.__pc;
+ #else
+ desc.EmulatedFaultAddr = (u8*)context->uc_mcontext.fault_address - curArea;
+ desc.FaultPC = (u8*)context->uc_mcontext.pc;
+ #endif
#endif
- s32 offset = 0;
- if (ARMJIT_Memory::FaultHandler(&desc, offset))
+ if (ARMJIT_Memory::FaultHandler(desc))
{
#ifdef __x86_64__
- context->uc_mcontext.gregs[REG_RIP] += offset;
+ #ifdef __APPLE__
+ context->uc_mcontext->__ss.__rip = (u64)desc.FaultPC;
+ #else
+ context->uc_mcontext.gregs[REG_RIP] = (u64)desc.FaultPC;
+ #endif
#else
- context->uc_mcontext.pc += offset;
+ #ifdef __APPLE__
+ context->uc_mcontext->__ss.__pc = (u64)desc.FaultPC;
+ #else
+ context->uc_mcontext.pc = (u64)desc.FaultPC;
+ #endif
#endif
return;
}
- if (OldSa.sa_flags & SA_SIGINFO)
+ struct sigaction* oldSa;
+ if (sig == SIGSEGV)
+ oldSa = &OldSaSegv;
+ else
+ oldSa = &OldSaBus;
+
+ if (oldSa->sa_flags & SA_SIGINFO)
{
- OldSa.sa_sigaction(sig, info, rawContext);
+ oldSa->sa_sigaction(sig, info, rawContext);
return;
}
- if (OldSa.sa_handler == SIG_DFL)
+ if (oldSa->sa_handler == SIG_DFL)
{
signal(sig, SIG_DFL);
return;
}
- if (OldSa.sa_handler == SIG_IGN)
+ if (oldSa->sa_handler == SIG_IGN)
{
// Ignore signal
return;
}
- OldSa.sa_handler(sig);
+ oldSa->sa_handler(sig);
}
#endif
@@ -231,7 +267,7 @@ enum
{
memstate_Unmapped,
memstate_MappedRW,
- // on switch this is unmapped as well
+ // on Switch this is unmapped as well
memstate_MappedProtected,
};
@@ -314,14 +350,16 @@ struct Mapping
void Unmap(int region)
{
+ u32 dtcmStart = NDS::ARM9->DTCMBase;
+ u32 dtcmSize = NDS::ARM9->DTCMSize;
bool skipDTCM = Num == 0 && region != memregion_DTCM;
u8* statuses = Num == 0 ? MappingStatus9 : MappingStatus7;
u32 offset = 0;
while (offset < Size)
{
- if (skipDTCM && Addr + offset == NDS::ARM9->DTCMBase)
+ if (skipDTCM && Addr + offset == dtcmStart)
{
- offset += NDS::ARM9->DTCMSize;
+ offset += dtcmSize;
}
else
{
@@ -329,7 +367,7 @@ struct Mapping
u8 status = statuses[(Addr + offset) >> 12];
while (statuses[(Addr + offset) >> 12] == status
&& offset < Size
- && (!skipDTCM || Addr + offset != NDS::ARM9->DTCMBase))
+ && (!skipDTCM || Addr + offset != dtcmStart))
{
assert(statuses[(Addr + offset) >> 12] != memstate_Unmapped);
statuses[(Addr + offset) >> 12] = memstate_Unmapped;
@@ -347,9 +385,33 @@ struct Mapping
#endif
}
}
+
#ifndef __SWITCH__
- bool succeded = UnmapFromRange(Addr, Num, OffsetsPerRegion[region] + LocalOffset, Size);
- assert(succeded);
+#ifndef _WIN32
+ u32 dtcmEnd = dtcmStart + dtcmSize;
+ if (Num == 0
+ && dtcmEnd >= Addr
+ && dtcmStart < Addr + Size)
+ {
+ bool success;
+ if (dtcmStart > Addr)
+ {
+ success = UnmapFromRange(Addr, 0, OffsetsPerRegion[region] + LocalOffset, dtcmStart - Addr);
+ assert(success);
+ }
+ if (dtcmEnd < Addr + Size)
+ {
+ u32 offset = dtcmStart - Addr + dtcmSize;
+ success = UnmapFromRange(dtcmEnd, 0, OffsetsPerRegion[region] + LocalOffset + offset, Size - offset);
+ assert(success);
+ }
+ }
+ else
+#endif
+ {
+ bool succeded = UnmapFromRange(Addr, Num, OffsetsPerRegion[region] + LocalOffset, Size);
+ assert(succeded);
+ }
#endif
}
};
@@ -418,10 +480,10 @@ void RemapDTCM(u32 newBase, u32 newSize)
printf("unmapping %d %x %x %x %x\n", region, mapping.Addr, mapping.Size, mapping.Num, mapping.LocalOffset);
- bool oldOverlap = NDS::ARM9->DTCMSize > 0 && !(oldDTCMBase >= end || oldDTCBEnd <= start);
- bool newOverlap = newSize > 0 && !(newBase >= end || newEnd <= start);
+ bool overlap = (NDS::ARM9->DTCMSize > 0 && oldDTCMBase < end && oldDTCBEnd > start)
+ || (newSize > 0 && newBase < end && newEnd > start);
- if (mapping.Num == 0 && (oldOverlap || newOverlap))
+ if (mapping.Num == 0 && overlap)
{
mapping.Unmap(region);
Mappings[region].Remove(i);
@@ -445,8 +507,8 @@ void RemapNWRAM(int num)
for (int i = 0; i < Mappings[memregion_SharedWRAM].Length;)
{
Mapping& mapping = Mappings[memregion_SharedWRAM][i];
- if (!(DSi::NWRAMStart[mapping.Num][num] >= mapping.Addr + mapping.Size
- || DSi::NWRAMEnd[mapping.Num][num] < mapping.Addr))
+ if (DSi::NWRAMStart[mapping.Num][num] < mapping.Addr + mapping.Size
+ && DSi::NWRAMEnd[mapping.Num][num] > mapping.Addr)
{
mapping.Unmap(memregion_SharedWRAM);
Mappings[memregion_SharedWRAM].Remove(i);
@@ -469,7 +531,7 @@ void RemapSWRAM()
for (int i = 0; i < Mappings[memregion_WRAM7].Length;)
{
Mapping& mapping = Mappings[memregion_WRAM7][i];
- if (mapping.Addr + mapping.Size < 0x03800000)
+ if (mapping.Addr + mapping.Size <= 0x03800000)
{
mapping.Unmap(memregion_WRAM7);
Mappings[memregion_WRAM7].Remove(i);
@@ -501,26 +563,53 @@ bool MapAtAddress(u32 addr)
return false;
u8* states = num == 0 ? MappingStatus9 : MappingStatus7;
- printf("trying to create mapping %x, %x %x %d %d\n", mirrorStart, mirrorSize, memoryOffset, region, num);
+ printf("mapping mirror %x, %x %x %d %d\n", mirrorStart, mirrorSize, memoryOffset, region, num);
bool isExecutable = ARMJIT::CodeMemRegions[region];
+ u32 dtcmStart = NDS::ARM9->DTCMBase;
+ u32 dtcmSize = NDS::ARM9->DTCMSize;
+ u32 dtcmEnd = dtcmStart + dtcmSize;
#ifndef __SWITCH__
- bool succeded = MapIntoRange(mirrorStart, num, OffsetsPerRegion[region] + memoryOffset, mirrorSize);
- assert(succeded);
+#ifndef _WIN32
+ if (num == 0
+ && dtcmEnd >= mirrorStart
+ && dtcmStart < mirrorStart + mirrorSize)
+ {
+ bool success;
+ if (dtcmStart > mirrorStart)
+ {
+ success = MapIntoRange(mirrorStart, 0, OffsetsPerRegion[region] + memoryOffset, dtcmStart - mirrorStart);
+ assert(success);
+ }
+ if (dtcmEnd < mirrorStart + mirrorSize)
+ {
+ u32 offset = dtcmStart - mirrorStart + dtcmSize;
+ success = MapIntoRange(dtcmEnd, 0, OffsetsPerRegion[region] + memoryOffset + offset, mirrorSize - offset);
+ assert(success);
+ }
+ }
+ else
+#endif
+ {
+ bool succeded = MapIntoRange(mirrorStart, num, OffsetsPerRegion[region] + memoryOffset, mirrorSize);
+ assert(succeded);
+ }
#endif
ARMJIT::AddressRange* range = ARMJIT::CodeMemRegions[region] + memoryOffset / 512;
// this overcomplicated piece of code basically just finds whole pieces of code memory
- // which can be mapped
+ // which can be mapped/protected
u32 offset = 0;
bool skipDTCM = num == 0 && region != memregion_DTCM;
while (offset < mirrorSize)
{
- if (skipDTCM && mirrorStart + offset == NDS::ARM9->DTCMBase)
+ if (skipDTCM && mirrorStart + offset == dtcmStart)
{
- SetCodeProtectionRange(NDS::ARM9->DTCMBase, NDS::ARM9->DTCMSize, 0, 0);
- offset += NDS::ARM9->DTCMSize;
+#ifdef _WIN32
+ SetCodeProtectionRange(dtcmStart, dtcmSize, 0, 0);
+#endif
+ offset += dtcmSize;
}
else
{
@@ -557,37 +646,36 @@ bool MapAtAddress(u32 addr)
Mapping mapping{mirrorStart, mirrorSize, memoryOffset, num};
Mappings[region].Add(mapping);
- printf("mapped mirror at %08x-%08x\n", mirrorStart, mirrorStart + mirrorSize - 1);
+ //printf("mapped mirror at %08x-%08x\n", mirrorStart, mirrorStart + mirrorSize - 1);
return true;
}
-bool FaultHandler(FaultDescription* faultDesc, s32& offset)
+bool FaultHandler(FaultDescription& faultDesc)
{
- if (ARMJIT::JITCompiler->IsJITFault(faultDesc->FaultPC))
+ if (ARMJIT::JITCompiler->IsJITFault(faultDesc.FaultPC))
{
bool rewriteToSlowPath = true;
- u32 addr = faultDesc->EmulatedFaultAddr;
+ u8* memStatus = NDS::CurCPU == 0 ? MappingStatus9 : MappingStatus7;
- if ((NDS::CurCPU == 0 ? MappingStatus9 : MappingStatus7)[addr >> 12] == memstate_Unmapped)
- rewriteToSlowPath = !MapAtAddress(faultDesc->EmulatedFaultAddr);
+ if (memStatus[faultDesc.EmulatedFaultAddr >> 12] == memstate_Unmapped)
+ rewriteToSlowPath = !MapAtAddress(faultDesc.EmulatedFaultAddr);
if (rewriteToSlowPath)
- {
- offset = ARMJIT::JITCompiler->RewriteMemAccess(faultDesc->FaultPC);
- }
+ faultDesc.FaultPC = ARMJIT::JITCompiler->RewriteMemAccess(faultDesc.FaultPC);
+
return true;
}
return false;
}
+const u64 AddrSpaceSize = 0x100000000;
+
void Init()
{
- const u64 AddrSpaceSize = 0x100000000;
-
#if defined(__SWITCH__)
- MemoryBase = (u8*)memalign(0x1000, MemoryTotalSize);
+ MemoryBase = (u8*)aligned_alloc(0x1000, MemoryTotalSize);
MemoryBaseCodeMem = (u8*)virtmemReserve(MemoryTotalSize);
bool succeded = R_SUCCEEDED(svcMapProcessCodeMemory(envGetOwnProcessHandle(), (u64)MemoryBaseCodeMem,
@@ -624,22 +712,52 @@ void Init()
u8* basePtr = MemoryBase;
#else
- FastMem9Start = mmap(NULL, AddrSpaceSize, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
- FastMem7Start = mmap(NULL, AddrSpaceSize, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
-
- MemoryBase = (u8*)mmap(NULL, MemoryTotalSize, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
-
+ // this used to be allocated with three different mmaps
+ // The idea was to give the OS more freedom where to position the buffers,
+ // but something was bad about this so instead we take this vmem eating monster
+ // which seems to work better.
+ MemoryBase = (u8*)mmap(NULL, AddrSpaceSize*4, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
+ munmap(MemoryBase, AddrSpaceSize*4);
+ FastMem9Start = MemoryBase;
+ FastMem7Start = MemoryBase + AddrSpaceSize;
+ MemoryBase = MemoryBase + AddrSpaceSize*2;
+
+#if defined(__ANDROID__)
+ static void* libandroid = dlopen("libandroid.so", RTLD_LAZY | RTLD_LOCAL);
+ using type_ASharedMemory_create = int(*)(const char* name, size_t size);
+ static void* symbol = dlsym(libandroid, "ASharedMemory_create");
+ static auto shared_memory_create = reinterpret_cast<type_ASharedMemory_create>(symbol);
+
+ if (shared_memory_create)
+ {
+ MemoryFile = shared_memory_create("melondsfastmem", MemoryTotalSize);
+ }
+ else
+ {
+ int fd = open(ASHMEM_DEVICE, O_RDWR);
+ ioctl(fd, ASHMEM_SET_NAME, "melondsfastmem");
+ ioctl(fd, ASHMEM_SET_SIZE, MemoryTotalSize);
+ MemoryFile = fd;
+ }
+#elif defined(__APPLE__)
+ char* fastmemPidName = new char[snprintf(NULL, 0, "melondsfastmem%d", getpid()) + 1];
+ sprintf(fastmemPidName, "melondsfastmem%d", getpid());
+ MemoryFile = shm_open(fastmemPidName, O_RDWR|O_CREAT, 0600);
+ delete[] fastmemPidName;
+#else
MemoryFile = memfd_create("melondsfastmem", 0);
+#endif
ftruncate(MemoryFile, MemoryTotalSize);
- NewSa.sa_flags = SA_SIGINFO;
- sigemptyset(&NewSa.sa_mask);
- NewSa.sa_sigaction = SigsegvHandler;
- sigaction(SIGSEGV, &NewSa, &OldSa);
-
- munmap(MemoryBase, MemoryTotalSize);
- munmap(FastMem9Start, AddrSpaceSize);
- munmap(FastMem7Start, AddrSpaceSize);
+ struct sigaction sa;
+ sa.sa_handler = nullptr;
+ sa.sa_sigaction = &SigsegvHandler;
+ sa.sa_flags = SA_SIGINFO;
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGSEGV, &sa, &OldSaSegv);
+#ifdef __APPLE__
+ sigaction(SIGBUS, &sa, &OldSaBus);
+#endif
mmap(MemoryBase, MemoryTotalSize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, MemoryFile, 0);
@@ -657,17 +775,30 @@ void Init()
void DeInit()
{
#if defined(__SWITCH__)
- virtmemFree(FastMem9Start, 0x100000000);
- virtmemFree(FastMem7Start, 0x100000000);
+ virtmemFree(FastMem9Start, AddrSpaceSize);
+ virtmemFree(FastMem7Start, AddrSpaceSize);
svcUnmapProcessCodeMemory(envGetOwnProcessHandle(), (u64)MemoryBaseCodeMem, (u64)MemoryBase, MemoryTotalSize);
virtmemFree(MemoryBaseCodeMem, MemoryTotalSize);
free(MemoryBase);
+#elif defined(__APPLE__)
+ char* fastmemPidName = new char[snprintf(NULL, 0, "melondsfastmem%d", getpid()) + 1];
+ sprintf(fastmemPidName, "melondsfastmem%d", getpid());
+ shm_unlink(fastmemPidName);
+ delete[] fastmemPidName;
#elif defined(_WIN32)
assert(UnmapViewOfFile(MemoryBase));
CloseHandle(MemoryFile);
RemoveVectoredExceptionHandler(ExceptionHandlerHandle);
+#else
+ sigaction(SIGSEGV, &OldSaSegv, nullptr);
+#ifdef __APPLE__
+ sigaction(SIGBUS, &OldSaBus, nullptr);
+#endif
+
+ munmap(MemoryBase, MemoryTotalSize);
+ close(MemoryFile);
#endif
}
@@ -997,9 +1128,11 @@ int ClassifyAddress7(u32 addr)
case 0x06000000:
case 0x06800000:
return memregion_VWRAM;
+
+ default:
+ return memregion_Other;
}
}
- return memregion_Other;
}
void WifiWrite32(u32 addr, u32 val)
@@ -1176,4 +1309,4 @@ void* GetFuncForAddr(ARM* cpu, u32 addr, bool store, int size)
return NULL;
}
-} \ No newline at end of file
+}