diff --git a/.gitignore b/.gitignore index 01c0268ea7..2beadcfc83 100644 --- a/.gitignore +++ b/.gitignore @@ -91,6 +91,7 @@ android/assets/lang android/assets/flash0 ppge_atlas.zim.png local.properties +r.sh # For vim *.swp diff --git a/Common/MemArenaPosix.cpp b/Common/MemArenaPosix.cpp index d550d5aaab..5ee371ed17 100644 --- a/Common/MemArenaPosix.cpp +++ b/Common/MemArenaPosix.cpp @@ -103,9 +103,25 @@ void MemArena::ReleaseView(void* view, size_t size) { u8* MemArena::Find4GBBase() { // Now, create views in high memory where there's plenty of space. #if PPSSPP_ARCH(64BIT) && !defined(USE_ADDRESS_SANITIZER) - // Very precarious - mmap cannot return an error when trying to map already used pages. - // This makes the Windows approach above unusable on Linux, so we will simply pray... - return reinterpret_cast(0x2300000000ULL); + // We should probably just go look in /proc/self/maps for some free space. + // But let's try the anonymous mmap trick, just like on 32-bit, but bigger and + // aligned to 4GB for the movk trick. We can ensure that we get an aligned 4GB + // address by grabbing 8GB and aligning the pointer. + const uint64_t EIGHT_GIGS = 0x200000000ULL; + void *base = mmap(0, EIGHT_GIGS, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0); + if (base) { + INFO_LOG(MEMMAP, "base: %p", base); + uint64_t aligned_base = ((uint64_t)base + 0xFFFFFFFF) & ~0xFFFFFFFFULL; + INFO_LOG(MEMMAP, "aligned_base: %p", (void *)aligned_base); + munmap(base, EIGHT_GIGS); + return reinterpret_cast(aligned_base); + } else { + u8 *hardcoded_ptr = reinterpret_cast(0x2300000000ULL); + INFO_LOG(MEMMAP, "Failed to anonymously map 8GB. Fall back to the hardcoded pointer %p.", hardcoded_ptr); + // Just grab some random 4GB... + // This has been known to fail lately though, see issue #12249. + return hardcoded_ptr; + } #else size_t size = 0x10000000; void* base = mmap(0, size, PROT_READ | PROT_WRITE,