Map pages properly maybe

This commit is contained in:
wheremyfoodat 2023-06-16 17:04:33 +03:00
parent a174aa1e6a
commit db2608eb14
4 changed files with 91 additions and 3 deletions

View file

@ -8,8 +8,12 @@
#include "helpers.hpp"
#include "handles.hpp"
#include "loader/ncsd.hpp"
#include "MemArena/memory_arena.hpp"
#include "services/shared_font.hpp"
// Comment this out to disable fastmem
#define PANDA3DS_HARDWARE_FASTMEM
namespace PhysicalAddrs {
enum : u32 {
VRAM = 0x18000000,
@ -100,7 +104,7 @@ class Memory {
u64& cpuTicks; // Reference to the CPU tick counter
using SharedMemoryBlock = KernelMemoryTypes::SharedMemoryBlock;
// Our dynarmic core uses page tables for reads and writes with 4096 byte pages
// Our memory core uses page tables for reads and writes with 4096 byte pages
std::vector<uintptr_t> readTable, writeTable;
// This tracks our OS' memory allocations
@ -128,6 +132,36 @@ public:
static constexpr u32 DSP_DATA_MEMORY_OFFSET = 256_KB;
private:
// We also use MMU-accelerated fastmem for fast memory emulation
// This means that we've got a 4GB memory arena which is organized the same way as the emulated 3DS' memory map
// And we can access this directly instead of calling the memory read/write functions, which would be slower
// Regions that are not mapped or can't be accelerated this way will segfault, and the caller (eg dynarmic), will
// handle this segfault and call the Slower memory read/write functions
bool useFastmem = false;
u8* fastmemArenaBase = nullptr;
static constexpr size_t FASTMEM_FCRAM_OFFSET = 0; // Offset of FCRAM in the fastmem arena
static constexpr size_t FASTMEM_DSP_RAM_OFFSET = FASTMEM_FCRAM_OFFSET + FCRAM_SIZE; // Offset of DSP RAM
#ifdef PANDA3DS_HARDWARE_FASTMEM
Common::MemoryArena arena;
std::vector<Common::MemoryArena::View> fastmemViews;
void resetFastmemViews() { fastmemViews.clear(); }
void addFastmemView(u32 guestVaddr, size_t arenaOffset, size_t size, bool w, bool x = false) {
if (useFastmem) {
const auto hostAddr = fastmemArenaBase + guestVaddr;
auto view = arena.CreateView(arenaOffset, size, w, x, hostAddr);
if (view) {
fastmemViews.push_back(std::move(view.value()));
}
}
}
#else
void resetFastmemViews() {}
void addFastmemView(u32 guestVaddr, size_t arenaOffset, size_t size, bool r, bool w, bool x = false) {}
#endif
std::bitset<FCRAM_PAGE_COUNT> usedFCRAMPages;
std::optional<u32> findPaddr(u32 size);
u64 timeSince3DSEpoch();
@ -202,6 +236,9 @@ public:
return (addr & pageMask) == 0;
}
bool isFastmemEnabled() { return useFastmem; }
u8* getFastmemArenaBase() { return fastmemArenaBase; }
// Allocate "size" bytes of RAM starting from FCRAM index "paddr" (We pick it ourself if paddr == 0)
// And map them to virtual address "vaddr" (We also pick it ourself if vaddr == 0).
// If the "linear" flag is on, the paddr pages must be adjacent in FCRAM

View file

@ -12,7 +12,8 @@ CPU::CPU(Memory& mem, Kernel& kernel) : mem(mem), env(mem, kernel, *this) {
config.define_unpredictable_behaviour = true;
config.global_monitor = &exclusiveMonitor;
config.processor_id = 0;
config.fastmem_pointer = mem.isFastmemEnabled() ? mem.getFastmemArenaBase() : nullptr;
jit = std::make_unique<Dynarmic::A32::Jit>(config);
}

View file

@ -13,6 +13,51 @@ Memory::Memory(u64& cpuTicks) : cpuTicks(cpuTicks) {
readTable.resize(totalPageCount, 0);
writeTable.resize(totalPageCount, 0);
memoryInfo.reserve(32); // Pre-allocate some room for memory allocation info to avoid dynamic allocs
#ifdef PANDA3DS_HARDWARE_FASTMEM
constexpr size_t FASTMEM_MEMORY_SIZE = 0x100000000; // Total size of the virtual address space we will occupy (4GB)
u8* arenaFcram = nullptr;
u8* arenaDSPRam = nullptr;
constexpr size_t MEMORY_ARENA_SIZE = FCRAM_SIZE + DSP_RAM_SIZE;
if (!arena.Create(MEMORY_ARENA_SIZE, true, false) || !arena.IsValid()) {
printf("Failed to create fastmem memory arena\n");
goto fastmemSetupFail;
}
fastmemArenaBase = (u8*)arena.FindBaseAddressForMapping(FASTMEM_MEMORY_SIZE);
if (!fastmemArenaBase) {
printf("Couldn't find base address for fastmem\n");
goto fastmemSetupFail;
}
arenaFcram = (u8*)arena.CreateViewPtr(FASTMEM_FCRAM_OFFSET, FCRAM_SIZE, true, false);
if (!arenaFcram) {
printf("Couldn't allocate FCRAM for fastmem");
goto fastmemSetupFail;
}
arenaDSPRam = (u8*)arena.CreateViewPtr(FASTMEM_DSP_RAM_OFFSET, DSP_RAM_SIZE, true, false);
if (!arenaDSPRam) {
printf("Couldn't allocate FCRAM for fastmem");
goto fastmemSetupFail;
}
fcram = arenaFcram;
dspRam = arenaDSPRam;
useFastmem = true;
return;
fastmemSetupFail:
if (arenaFcram) arena.ReleaseViewPtr(arenaFcram, FCRAM_SIZE);
if (arenaDSPRam) arena.ReleaseViewPtr(arenaDSPRam, DSP_RAM_SIZE);
useFastmem = false;
fastmemArenaBase = nullptr;
return;
#else
useFastmem = false;
fastmemArenaBase = nullptr;
#endif
}
void Memory::reset() {
@ -27,6 +72,9 @@ void Memory::reset() {
writeTable[i] = 0;
}
resetFastmemViews(); // Reset the entire fastmem state
addFastmemView(VirtualAddrs::DSPMemStart, FASTMEM_DSP_RAM_OFFSET, DSP_RAM_SIZE, true, false); // Allocate RW mapping for DSP RAM
// Map stack pages as R/W
// We have 16KB for the stack, so we allocate the last 16KB of APPLICATION FCRAM for the stack
u32 basePaddrForStack = FCRAM_APPLICATION_SIZE - VirtualAddrs::DefaultStackSize;
@ -284,6 +332,9 @@ std::optional<u32> Memory::allocateMemory(u32 vaddr, u32 paddr, u32 size, bool l
// Mark FCRAM page as allocated and go on
usedFCRAMPages[physPage] = true;
// Add mapping to the fastmem arena
addFastmemView(size_t(virtualPage) * pageSize, FASTMEM_FCRAM_OFFSET + size_t(physPage) * pageSize, pageSize, w, false);
virtualPage++;
physPage++;
}

View file

@ -125,7 +125,6 @@ static std::string GetFileMappingName()
#endif
std::string ret = std::string("Alber_") + std::to_string(pid);
printf("File mapping name: %s\n", ret.c_str());
return ret;
}