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)
target_link_libraries(${PROJECT_NAME} PRIVATE android log)
target_link_options(${PROJECT_NAME} PRIVATE "-Wl,-z,max-page-size=16384")
elseif(APPLE)
string(TIMESTAMP YEAR "%Y")
string(REGEX MATCH "^[^-]+" TAG_VERSION ${GIT_VERSION})

View File

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

View File

@ -32,8 +32,9 @@ typedef std::map<void*, RuntimeBlockInfoPtr> bm_Map;
static bm_Set all_temp_blocks;
static bm_List del_blocks;
bool unprotected_pages[RAM_SIZE_MAX/PAGE_SIZE];
static std::set<RuntimeBlockInfo*> blocks_per_page[RAM_SIZE_MAX/PAGE_SIZE];
static u32 pageCount;
bool *unprotected_pages;
static std::set<RuntimeBlockInfo*> *blocks_per_page;
static bm_Map blkmap;
// Stats
@ -302,10 +303,10 @@ void bm_ResetCache()
// blkmap includes temp blocks as well
all_temp_blocks.clear();
for (auto& block_list : blocks_per_page)
block_list.clear();
for (size_t i = 0; i < pageCount; i++)
blocks_per_page[i].clear();
memset(unprotected_pages, 0, sizeof(unprotected_pages));
memset(unprotected_pages, 0, pageCount);
#ifdef DYNA_OPROF
if (oprofHandle)
@ -337,6 +338,10 @@ void bm_ResetTempCache(bool full)
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
oprofHandle=op_open_agent();
if (oprofHandle==0)
@ -354,6 +359,8 @@ void bm_Term()
oprofHandle=0;
#endif
bm_Reset();
delete[] unprotected_pages;
delete[] blocks_per_page;
}
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);
static inline bool bm_IsRamPageProtected(u32 addr)
{
extern bool unprotected_pages[RAM_SIZE_MAX/PAGE_SIZE];
extern bool *unprotected_pages;
addr &= RAM_MASK;
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
#define FPCB_PAD 64_KB
#endif
struct alignas(PAGE_SIZE) Sh4RCB
struct Sh4RCB
{
void* fpcb[FPCB_SIZE];
u8 _pad[FPCB_PAD - sizeof(Sh4Context)];
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;
#define Sh4cntx (p_sh4rcb->cntx)

View File

@ -171,7 +171,7 @@ void common_linux_setup()
signal(SIGINT, sigintHandler);
#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));
}

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
};
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
//
@ -76,7 +81,7 @@ static std::mutex vramlist_lock;
bool VramLockedWriteOffset(size_t offset)
{
if (offset >= VRAM_SIZE)
if (offset >= VRAM_SIZE || VramLocks == nullptr)
return false;
size_t addr_hash = offset / PAGE_SIZE;
@ -292,6 +297,8 @@ bool BaseTextureCacheData::Delete()
BaseTextureCacheData::BaseTextureCacheData(TSP tsp, TCW tcw)
{
initVramLocks();
if (tcw.VQ_Comp == 1 && tcw.MipMapped == 1)
// Star Wars Demolition
tcw.ScanOrder = 0;

View File

@ -12,7 +12,9 @@
#include <vector>
#ifdef _WIN32
#include <algorithm>
#include <algorithm>
#elif defined(__ANDROID__)
#include <unistd.h>
#endif
static std::string user_config_dir;
@ -205,6 +207,10 @@ void cResetEvent::Wait()
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 {
ser.serialize(data, size);
}

View File

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