android: support 4KB and 16KB page sizes on 64-bit platforms

This commit is contained in:
Flyinghead 2025-07-06 22:16:06 +02:00
parent f3e0f09ca9
commit 6ea61b9084
9 changed files with 45 additions and 21 deletions

View File

@ -1330,6 +1330,7 @@ if(NOT LIBRETRO)
shell/android-studio/flycast/src/main/jni/src/android_keyboard.h) shell/android-studio/flycast/src/main/jni/src/android_keyboard.h)
target_link_libraries(${PROJECT_NAME} PRIVATE android log) target_link_libraries(${PROJECT_NAME} PRIVATE android log)
target_link_options(${PROJECT_NAME} PRIVATE "-Wl,-z,max-page-size=16384")
elseif(APPLE) elseif(APPLE)
string(TIMESTAMP YEAR "%Y") string(TIMESTAMP YEAR "%Y")
string(REGEX MATCH "^[^-]+" TAG_VERSION ${GIT_VERSION}) string(REGEX MATCH "^[^-]+" TAG_VERSION ${GIT_VERSION})

View File

@ -26,16 +26,14 @@
#include "hw/pvr/elan.h" #include "hw/pvr/elan.h"
#include "rend/TexCache.h" #include "rend/TexCache.h"
#include <unordered_map> #include <unordered_map>
#include <memory>
namespace memwatch namespace memwatch
{ {
struct Page struct Page
{ {
Page() { std::unique_ptr<u8[]> data = std::make_unique<u8[]>(PAGE_SIZE);
// don't initialize data
}
u8 data[PAGE_SIZE];
}; };
using PageMap = std::unordered_map<u32, Page>; using PageMap = std::unordered_map<u32, Page>;
@ -77,7 +75,7 @@ public:
if (offset == (u32)-1) if (offset == (u32)-1)
return false; return false;
offset &= ~PAGE_MASK; offset &= ~PAGE_MASK;
auto rv = pages.emplace(offset, Page()); auto rv = pages.try_emplace(offset);
if (!rv.second) if (!rv.second)
// already saved // already saved
return true; return true;

View File

@ -32,8 +32,9 @@ typedef std::map<void*, RuntimeBlockInfoPtr> bm_Map;
static bm_Set all_temp_blocks; static bm_Set all_temp_blocks;
static bm_List del_blocks; static bm_List del_blocks;
bool unprotected_pages[RAM_SIZE_MAX/PAGE_SIZE]; static u32 pageCount;
static std::set<RuntimeBlockInfo*> blocks_per_page[RAM_SIZE_MAX/PAGE_SIZE]; bool *unprotected_pages;
static std::set<RuntimeBlockInfo*> *blocks_per_page;
static bm_Map blkmap; static bm_Map blkmap;
// Stats // Stats
@ -302,10 +303,10 @@ void bm_ResetCache()
// blkmap includes temp blocks as well // blkmap includes temp blocks as well
all_temp_blocks.clear(); all_temp_blocks.clear();
for (auto& block_list : blocks_per_page) for (size_t i = 0; i < pageCount; i++)
block_list.clear(); blocks_per_page[i].clear();
memset(unprotected_pages, 0, sizeof(unprotected_pages)); memset(unprotected_pages, 0, pageCount);
#ifdef DYNA_OPROF #ifdef DYNA_OPROF
if (oprofHandle) if (oprofHandle)
@ -337,6 +338,10 @@ void bm_ResetTempCache(bool full)
void bm_Init() void bm_Init()
{ {
pageCount = RAM_SIZE_MAX / PAGE_SIZE;
unprotected_pages = new bool[pageCount];
blocks_per_page = new std::set<RuntimeBlockInfo*>[pageCount];
#ifdef DYNA_OPROF #ifdef DYNA_OPROF
oprofHandle=op_open_agent(); oprofHandle=op_open_agent();
if (oprofHandle==0) if (oprofHandle==0)
@ -354,6 +359,8 @@ void bm_Term()
oprofHandle=0; oprofHandle=0;
#endif #endif
bm_Reset(); bm_Reset();
delete[] unprotected_pages;
delete[] blocks_per_page;
} }
void bm_WriteBlockMap(const std::string& file) void bm_WriteBlockMap(const std::string& file)

View File

@ -86,7 +86,7 @@ void bm_Term();
void bm_vmem_pagefill(void** ptr,u32 size_bytes); void bm_vmem_pagefill(void** ptr,u32 size_bytes);
static inline bool bm_IsRamPageProtected(u32 addr) static inline bool bm_IsRamPageProtected(u32 addr)
{ {
extern bool unprotected_pages[RAM_SIZE_MAX/PAGE_SIZE]; extern bool *unprotected_pages;
addr &= RAM_MASK; addr &= RAM_MASK;
return !unprotected_pages[addr / PAGE_SIZE]; return !unprotected_pages[addr / PAGE_SIZE];
} }

View File

@ -226,13 +226,13 @@ static_assert(sizeof(Sh4Context) == 512, "Invalid Sh4Context size");
// For other systems we could use PAGE_SIZE, except on windows that has a 64 KB granularity for memory mapping // For other systems we could use PAGE_SIZE, except on windows that has a 64 KB granularity for memory mapping
#define FPCB_PAD 64_KB #define FPCB_PAD 64_KB
#endif #endif
struct alignas(PAGE_SIZE) Sh4RCB struct Sh4RCB
{ {
void* fpcb[FPCB_SIZE]; void* fpcb[FPCB_SIZE];
u8 _pad[FPCB_PAD - sizeof(Sh4Context)]; u8 _pad[FPCB_PAD - sizeof(Sh4Context)];
Sh4Context cntx; Sh4Context cntx;
}; };
static_assert((sizeof(Sh4RCB) % PAGE_SIZE) == 0, "sizeof(Sh4RCB) not multiple of PAGE_SIZE"); static_assert((sizeof(Sh4RCB) % MAX_PAGE_SIZE) == 0, "sizeof(Sh4RCB) not multiple of MAX_PAGE_SIZE");
extern Sh4RCB* p_sh4rcb; extern Sh4RCB* p_sh4rcb;
#define Sh4cntx (p_sh4rcb->cntx) #define Sh4cntx (p_sh4rcb->cntx)

View File

@ -171,7 +171,7 @@ void common_linux_setup()
signal(SIGINT, sigintHandler); signal(SIGINT, sigintHandler);
#endif #endif
DEBUG_LOG(BOOT, "Linux paging: %ld %08X %08X", sysconf(_SC_PAGESIZE), PAGE_SIZE, PAGE_MASK); DEBUG_LOG(BOOT, "Linux paging: sysconf %ld PAGE_SIZE %ld PAGE_MASK %lX", sysconf(_SC_PAGESIZE), (unsigned long)PAGE_SIZE, (long)PAGE_MASK);
verify(PAGE_MASK==(sysconf(_SC_PAGESIZE)-1)); verify(PAGE_MASK==(sysconf(_SC_PAGESIZE)-1));
} }

View File

@ -33,7 +33,12 @@ const std::array<f32, 16> D_Adjust_LoD_Bias = {
0.f, -4.f, -2.f, -1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f 0.f, -4.f, -2.f, -1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f
}; };
static std::vector<vram_block*> VramLocks[VRAM_SIZE_MAX / PAGE_SIZE]; static std::vector<vram_block*> *VramLocks;
static inline void initVramLocks() {
if (VramLocks == nullptr)
VramLocks = new std::vector<vram_block*>[VRAM_SIZE_MAX / PAGE_SIZE];
}
//List functions //List functions
// //
@ -76,7 +81,7 @@ static std::mutex vramlist_lock;
bool VramLockedWriteOffset(size_t offset) bool VramLockedWriteOffset(size_t offset)
{ {
if (offset >= VRAM_SIZE) if (offset >= VRAM_SIZE || VramLocks == nullptr)
return false; return false;
size_t addr_hash = offset / PAGE_SIZE; size_t addr_hash = offset / PAGE_SIZE;
@ -292,6 +297,8 @@ bool BaseTextureCacheData::Delete()
BaseTextureCacheData::BaseTextureCacheData(TSP tsp, TCW tcw) BaseTextureCacheData::BaseTextureCacheData(TSP tsp, TCW tcw)
{ {
initVramLocks();
if (tcw.VQ_Comp == 1 && tcw.MipMapped == 1) if (tcw.VQ_Comp == 1 && tcw.MipMapped == 1)
// Star Wars Demolition // Star Wars Demolition
tcw.ScanOrder = 0; tcw.ScanOrder = 0;

View File

@ -12,7 +12,9 @@
#include <vector> #include <vector>
#ifdef _WIN32 #ifdef _WIN32
#include <algorithm> #include <algorithm>
#elif defined(__ANDROID__)
#include <unistd.h>
#endif #endif
static std::string user_config_dir; static std::string user_config_dir;
@ -205,6 +207,10 @@ void cResetEvent::Wait()
state = false; state = false;
} }
#if defined(__ANDROID__) && (HOST_CPU == CPU_ARM64 || HOST_CPU == CPU_X64)
const unsigned long PAGE_SIZE = (unsigned long)sysconf(_SC_PAGESIZE);
#endif
void RamRegion::serialize(Serializer &ser) const { void RamRegion::serialize(Serializer &ser) const {
ser.serialize(data, size); ser.serialize(data, size);
} }

View File

@ -13,17 +13,22 @@
#include <cassert> #include <cassert>
#include <time.h> #include <time.h>
#ifdef __ANDROID__ #if defined(__ANDROID__) && (HOST_CPU == CPU_ARM64 || HOST_CPU == CPU_X64)
#include <sys/mman.h>
#undef PAGE_MASK #undef PAGE_MASK
#undef PAGE_SIZE
extern const unsigned long PAGE_SIZE;
#define MAX_PAGE_SIZE 16384ul
#elif defined(__APPLE__) && defined(__aarch64__) #elif defined(__APPLE__) && defined(__aarch64__)
#define PAGE_SIZE 16384 #define PAGE_SIZE 16384ul
#elif !defined(PAGE_SIZE) #elif !defined(PAGE_SIZE)
#define PAGE_SIZE 4096 #define PAGE_SIZE 4096ul
#endif #endif
#ifndef PAGE_MASK #ifndef PAGE_MASK
#define PAGE_MASK (PAGE_SIZE-1) #define PAGE_MASK (PAGE_SIZE-1)
#endif #endif
#ifndef MAX_PAGE_SIZE
#define MAX_PAGE_SIZE PAGE_SIZE
#endif
class cThread class cThread
{ {