Accurately handle MemoryState for virtual memory

Previously all non-free blocks were marked as Reserved
This commit is contained in:
PSI-Rockin 2024-05-03 21:44:07 -04:00
parent f230384444
commit 9b20801dde
6 changed files with 108 additions and 63 deletions

View file

@ -239,23 +239,14 @@ private:
return (addr & pageMask) == 0; return (addr & pageMask) == 0;
} }
// Allocate "size" bytes of RAM starting from FCRAM index "paddr" (We pick it ourself if paddr == 0) bool allocMemory(u32 vaddr, s32 pages, FcramRegion region, bool r, bool w, bool x, KernelMemoryTypes::MemoryState state);
// 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
// This function is for interacting with the *user* portion of FCRAM mainly. For OS RAM, we use other internal functions below
// r, w, x: Permissions for the allocated memory
// adjustAddrs: If it's true paddr == 0 or vaddr == 0 tell the allocator to pick its own addresses. Used for eg svc ControlMemory
// isMap: Shows whether this is a reserve operation, that allocates memory and maps it to the addr space, or if it's a map operation,
// which just maps memory from paddr to vaddr without hassle. The latter is useful for shared memory mapping, the "map" ControlMemory, op, etc
// Returns the vaddr the FCRAM was mapped to or nullopt if allocation failed
//std::optional<u32> allocateMemory(u32 vaddr, u32 paddr, u32 size, bool linear, bool r = true, bool w = true, bool x = true,
//bool adjustsAddrs = false, bool isMap = false);
bool allocMemory(u32 vaddr, s32 pages, FcramRegion region, bool r, bool w, bool x);
bool allocMemoryLinear(u32& outVaddr, u32 inVaddr, s32 pages, FcramRegion region, bool r, bool w, bool x); bool allocMemoryLinear(u32& outVaddr, u32 inVaddr, s32 pages, FcramRegion region, bool r, bool w, bool x);
bool mapPhysicalMemory(u32 vaddr, u32 paddr, s32 pages, bool r, bool w, bool x); bool mapPhysicalMemory(u32 vaddr, u32 paddr, s32 pages, bool r, bool w, bool x, KernelMemoryTypes::MemoryState state);
bool mapVirtualMemory(u32 dstVaddr, u32 srcVaddr, s32 pages, bool r, bool w, bool x); bool mapVirtualMemory(u32 dstVaddr, u32 srcVaddr, s32 pages, bool r, bool w, bool x,
KernelMemoryTypes::MemoryState oldDstState, KernelMemoryTypes::MemoryState oldSrcState,
KernelMemoryTypes::MemoryState newDstState, KernelMemoryTypes::MemoryState newSrcState);
Result::HorizonResult queryMemory(KernelMemoryTypes::MemoryInfo& out, u32 vaddr); Result::HorizonResult queryMemory(KernelMemoryTypes::MemoryInfo& out, u32 vaddr);
Result::HorizonResult testMemoryState(u32 vaddr, s32 pages, KernelMemoryTypes::MemoryState desiredState);
void copyToVaddr(u32 dstVaddr, const u8* srcHost, s32 size); void copyToVaddr(u32 dstVaddr, const u8* srcHost, s32 size);
@ -265,10 +256,6 @@ private:
// Returns a pointer to the FCRAM block used for the memory if allocation succeeded // Returns a pointer to the FCRAM block used for the memory if allocation succeeded
u8* mapSharedMemory(Handle handle, u32 vaddr, u32 myPerms, u32 otherPerms); u8* mapSharedMemory(Handle handle, u32 vaddr, u32 myPerms, u32 otherPerms);
// Mirrors the page mapping for "size" bytes starting from sourceAddress, to "size" bytes in destAddress
// All of the above must be page-aligned.
// void mirrorMapping(u32 destAddress, u32 sourceAddress, u32 size);
// Backup of the game's CXI partition info, if any // Backup of the game's CXI partition info, if any
std::optional<NCCH> loadedCXI = std::nullopt; std::optional<NCCH> loadedCXI = std::nullopt;
std::optional<HB3DSX> loaded3DSX = std::nullopt; std::optional<HB3DSX> loaded3DSX = std::nullopt;

View file

@ -16,6 +16,8 @@ idle_thread_main:
b idle_thread_main b idle_thread_main
*/ */
using namespace KernelMemoryTypes;
static constexpr u8 idleThreadCode[] = { static constexpr u8 idleThreadCode[] = {
0x00, 0x00, 0xA0, 0xE3, // mov r0, #0 0x00, 0x00, 0xA0, 0xE3, // mov r0, #0
0x00, 0x10, 0xA0, 0xE3, // mov r1, #0 0x00, 0x10, 0xA0, 0xE3, // mov r1, #0
@ -30,7 +32,7 @@ void Kernel::setupIdleThread() {
// Reserve some memory for the idle thread's code. We map this memory to vaddr 3FC00000 which shouldn't be accessed by applications // Reserve some memory for the idle thread's code. We map this memory to vaddr 3FC00000 which shouldn't be accessed by applications
// We only allocate 4KB (1 page) because our idle code is pretty small // We only allocate 4KB (1 page) because our idle code is pretty small
constexpr u32 codeAddress = 0x3FC00000; constexpr u32 codeAddress = 0x3FC00000;
if (!mem.allocMemory(codeAddress, 1, FcramRegion::Base, true, true, false)) Helpers::panic("Failed to setup idle thread"); if (!mem.allocMemory(codeAddress, 1, FcramRegion::Base, true, true, false, MemoryState::Locked)) Helpers::panic("Failed to setup idle thread");
// Copy idle thread code to the allocated FCRAM // Copy idle thread code to the allocated FCRAM
mem.copyToVaddr(codeAddress, idleThreadCode, sizeof(idleThreadCode)); mem.copyToVaddr(codeAddress, idleThreadCode, sizeof(idleThreadCode));

View file

@ -30,6 +30,8 @@ namespace MemoryPermissions {
}; };
} }
using namespace KernelMemoryTypes;
// Returns whether "value" is aligned to a page boundary (Ie a boundary of 4096 bytes) // Returns whether "value" is aligned to a page boundary (Ie a boundary of 4096 bytes)
static constexpr bool isAligned(u32 value) { static constexpr bool isAligned(u32 value) {
return (value & 0xFFF) == 0; return (value & 0xFFF) == 0;
@ -78,7 +80,7 @@ void Kernel::controlMemory() {
if (linear) { if (linear) {
if (!mem.allocMemoryLinear(outAddr, addr0, pages, region, r, w, false)) Helpers::panic("ControlMemory: Failed to allocate linear memory"); if (!mem.allocMemoryLinear(outAddr, addr0, pages, region, r, w, false)) Helpers::panic("ControlMemory: Failed to allocate linear memory");
} else { } else {
if (!mem.allocMemory(addr0, pages, region, r, w, false)) Helpers::panic("ControlMemory: Failed to allocate memory"); if (!mem.allocMemory(addr0, pages, region, r, w, false, MemoryState::Private)) Helpers::panic("ControlMemory: Failed to allocate memory");
outAddr = addr0; outAddr = addr0;
} }
@ -87,7 +89,8 @@ void Kernel::controlMemory() {
} }
case Operation::Map: case Operation::Map:
if (!mem.mapVirtualMemory(addr0, addr1, pages, r, w, false)) Helpers::panic("ControlMemory: Failed to map memory"); if (!mem.mapVirtualMemory(addr0, addr1, pages, r, w, false, MemoryState::Free, MemoryState::Private,
MemoryState::Alias, MemoryState::Aliased)) Helpers::panic("ControlMemory: Failed to map memory");
break; break;
case Operation::Protect: case Operation::Protect:

View file

@ -6,6 +6,8 @@
#include "memory.hpp" #include "memory.hpp"
#include "kernel/fcram.hpp" #include "kernel/fcram.hpp"
using namespace KernelMemoryTypes;
bool Memory::mapCXI(NCSD& ncsd, NCCH& cxi) { bool Memory::mapCXI(NCSD& ncsd, NCCH& cxi) {
printf("Text address = %08X, size = %08X\n", cxi.text.address, cxi.text.size); printf("Text address = %08X, size = %08X\n", cxi.text.address, cxi.text.size);
printf("Rodata address = %08X, size = %08X\n", cxi.rodata.address, cxi.rodata.size); printf("Rodata address = %08X, size = %08X\n", cxi.rodata.address, cxi.rodata.size);
@ -66,9 +68,9 @@ bool Memory::mapCXI(NCSD& ncsd, NCCH& cxi) {
// TODO: base this off the exheader // TODO: base this off the exheader
auto region = FcramRegion::App; auto region = FcramRegion::App;
allocMemory(textAddr, cxi.text.pageCount, region, true, false, true); allocMemory(textAddr, cxi.text.pageCount, region, true, false, true, MemoryState::Code);
allocMemory(rodataAddr, cxi.rodata.pageCount, region, true, false, false); allocMemory(rodataAddr, cxi.rodata.pageCount, region, true, false, false, MemoryState::Code);
allocMemory(dataAddr, cxi.data.pageCount + (bssSize >> 12), region, true, true, false); // Merge data and BSS segments allocMemory(dataAddr, cxi.data.pageCount + (bssSize >> 12), region, true, true, false, MemoryState::Private); // Merge data and BSS segments
// Copy .code file to FCRAM // Copy .code file to FCRAM
copyToVaddr(textAddr, code.data(), textSize); copyToVaddr(textAddr, code.data(), textSize);

View file

@ -40,7 +40,7 @@ void Memory::reset() {
// Map 4 KB of FCRAM for each thread // Map 4 KB of FCRAM for each thread
// TODO: the region should be taken from the exheader // TODO: the region should be taken from the exheader
// TODO: each thread should only have 512 bytes - an FCRAM page should account for 8 threads // TODO: each thread should only have 512 bytes - an FCRAM page should account for 8 threads
assert(allocMemory(VirtualAddrs::TLSBase, appResourceLimits.maxThreads, FcramRegion::App, true, true, false)); assert(allocMemory(VirtualAddrs::TLSBase, appResourceLimits.maxThreads, FcramRegion::App, true, true, false, MemoryState::Locked));
// Initialize shared memory blocks and reserve memory for them // Initialize shared memory blocks and reserve memory for them
for (auto& e : sharedMemBlocks) { for (auto& e : sharedMemBlocks) {
@ -62,7 +62,7 @@ void Memory::reset() {
u32 vaddr = VirtualAddrs::DSPMemStart; u32 vaddr = VirtualAddrs::DSPMemStart;
u32 paddr = vaddr; u32 paddr = vaddr;
mapPhysicalMemory(vaddr, paddr, dspRamPages, true, true, false); mapPhysicalMemory(vaddr, paddr, dspRamPages, true, true, false, MemoryState::Static);
// Later adjusted based on ROM header when possible // Later adjusted based on ROM header when possible
region = Regions::USA; region = Regions::USA;
@ -72,7 +72,7 @@ bool Memory::allocateMainThreadStack(u32 size) {
// Map stack pages as R/W // Map stack pages as R/W
// TODO: get the region from the exheader // TODO: get the region from the exheader
const u32 stackBottom = VirtualAddrs::StackTop - size; const u32 stackBottom = VirtualAddrs::StackTop - size;
return allocMemory(stackBottom, size >> 12, FcramRegion::App, true, true, false); return allocMemory(stackBottom, size >> 12, FcramRegion::App, true, true, false, MemoryState::Locked);
} }
u8 Memory::read8(u32 vaddr) { u8 Memory::read8(u32 vaddr) {
@ -285,15 +285,17 @@ std::string Memory::readString(u32 address, u32 maxSize) {
// thanks to the New 3DS having more FCRAM // thanks to the New 3DS having more FCRAM
u32 Memory::getLinearHeapVaddr() { return (kernelVersion < 0x22C) ? VirtualAddrs::LinearHeapStartOld : VirtualAddrs::LinearHeapStartNew; } u32 Memory::getLinearHeapVaddr() { return (kernelVersion < 0x22C) ? VirtualAddrs::LinearHeapStartOld : VirtualAddrs::LinearHeapStartNew; }
bool Memory::allocMemory(u32 vaddr, s32 pages, FcramRegion region, bool r, bool w, bool x) bool Memory::allocMemory(u32 vaddr, s32 pages, FcramRegion region, bool r, bool w, bool x, MemoryState state) {
{ auto res = testMemoryState(vaddr, pages, MemoryState::Free);
if (res.isFailure()) return false;
FcramBlockList memList; FcramBlockList memList;
fcramManager.alloc(memList, pages, region, false); fcramManager.alloc(memList, pages, region, false);
bool succeeded = true; bool succeeded = true;
for (auto it = memList.begin(); it != memList.end(); it++) { for (auto it = memList.begin(); it != memList.end(); it++) {
succeeded = mapPhysicalMemory(vaddr, it->paddr, it->pages, r, w, x); succeeded = mapPhysicalMemory(vaddr, it->paddr, it->pages, r, w, x, state);
if (!succeeded) break; if (!succeeded) break;
vaddr += it->pages << 12; vaddr += it->pages << 12;
} }
@ -302,8 +304,7 @@ bool Memory::allocMemory(u32 vaddr, s32 pages, FcramRegion region, bool r, bool
return succeeded; return succeeded;
} }
bool Memory::allocMemoryLinear(u32& outVaddr, u32 inVaddr, s32 pages, FcramRegion region, bool r, bool w, bool x) bool Memory::allocMemoryLinear(u32& outVaddr, u32 inVaddr, s32 pages, FcramRegion region, bool r, bool w, bool x) {
{
if (inVaddr) Helpers::panic("inVaddr specified for linear allocation!"); if (inVaddr) Helpers::panic("inVaddr specified for linear allocation!");
FcramBlockList memList; FcramBlockList memList;
@ -311,19 +312,20 @@ bool Memory::allocMemoryLinear(u32& outVaddr, u32 inVaddr, s32 pages, FcramRegio
u32 paddr = memList.begin()->paddr; u32 paddr = memList.begin()->paddr;
u32 vaddr = getLinearHeapVaddr() + paddr; u32 vaddr = getLinearHeapVaddr() + paddr;
if (!mapPhysicalMemory(vaddr, paddr, pages, r, w, x)) Helpers::panic("Failed to map linear memory!"); if (!mapPhysicalMemory(vaddr, paddr, pages, r, w, x, MemoryState::Continuous)) Helpers::panic("Failed to map linear memory!");
outVaddr = vaddr; outVaddr = vaddr;
return true; return true;
} }
bool Memory::mapPhysicalMemory(u32 vaddr, u32 paddr, s32 pages, bool r, bool w, bool x) bool Memory::mapPhysicalMemory(u32 vaddr, u32 paddr, s32 pages, bool r, bool w, bool x, MemoryState state) {
{
assert(!(vaddr & 0xFFF)); assert(!(vaddr & 0xFFF));
assert(!(paddr & 0xFFF)); assert(!(paddr & 0xFFF));
bool blockFound = false;
for (auto it = memoryInfo.begin(); it != memoryInfo.end(); it++) { for (auto it = memoryInfo.begin(); it != memoryInfo.end(); it++) {
// Look for a free block that the requested memory region fits directly inside // Find the block that the memory region is located in
u32 blockStart = it->baseAddr; u32 blockStart = it->baseAddr;
u32 blockEnd = it->end(); u32 blockEnd = it->end();
@ -331,27 +333,46 @@ bool Memory::mapPhysicalMemory(u32 vaddr, u32 paddr, s32 pages, bool r, bool w,
u32 reqEnd = vaddr + (pages << 12); u32 reqEnd = vaddr + (pages << 12);
if (!(reqStart >= blockStart && reqEnd <= blockEnd)) continue; if (!(reqStart >= blockStart && reqEnd <= blockEnd)) continue;
if (it->state != MemoryState::Free) continue;
// Now that a candidate block has been selected, fill it with the necessary info auto oldState = it->state;
// Now that the block has been found, fill it with the necessary info
it->baseAddr = reqStart; it->baseAddr = reqStart;
it->pages = pages; it->pages = pages;
it->perms = (r ? PERMISSION_R : 0) | (w ? PERMISSION_W : 0) | (x ? PERMISSION_X : 0); it->perms = (r ? PERMISSION_R : 0) | (w ? PERMISSION_W : 0) | (x ? PERMISSION_X : 0);
it->state = MemoryState::Private; // TODO: make this a function parameter it->state = state; // TODO: make this a function parameter
// If the requested memory region is smaller than the block found, the block must be split // If the requested memory region is smaller than the block found, the block must be split
if (blockStart < reqStart) { if (blockStart < reqStart) {
MemoryInfo startBlock(blockStart, (reqStart - blockStart) >> 12, 0, MemoryState::Free); MemoryInfo startBlock(blockStart, (reqStart - blockStart) >> 12, 0, oldState);
memoryInfo.insert(it, startBlock); memoryInfo.insert(it, startBlock);
} }
if (reqEnd < blockEnd) { if (reqEnd < blockEnd) {
auto itAfter = std::next(it); auto itAfter = std::next(it);
MemoryInfo endBlock(reqEnd, (blockEnd - reqEnd) >> 12, 0, MemoryState::Free); MemoryInfo endBlock(reqEnd, (blockEnd - reqEnd) >> 12, 0, oldState);
memoryInfo.insert(itAfter, endBlock); memoryInfo.insert(itAfter, endBlock);
} }
// Fill the paddr table as well as the host pointer tables // TODO: if the current block is adjacent to blocks with the same state, merge them
blockFound = true;
break;
}
if (!blockFound) Helpers::panic("Can't map physical memory!");
// Fill the paddr table as well as the host pointer tables
// If the memory region is free, ignore the paddr, otherwise use it
if (state == MemoryState::Free) {
for (int i = 0; i < pages; i++) {
u32 index = (vaddr >> 12) + i;
paddrTable[index] = 0;
readTable[index] = 0;
writeTable[index] = 0;
}
}
else {
// TODO: make this a separate function // TODO: make this a separate function
u8* hostPtr = nullptr; u8* hostPtr = nullptr;
if (paddr < FCRAM_SIZE) { if (paddr < FCRAM_SIZE) {
@ -361,39 +382,40 @@ bool Memory::mapPhysicalMemory(u32 vaddr, u32 paddr, s32 pages, bool r, bool w,
hostPtr = dspRam + (paddr - VirtualAddrs::DSPMemStart); hostPtr = dspRam + (paddr - VirtualAddrs::DSPMemStart);
} }
for (int i = 0; i < pages; i++) paddrTable[(vaddr >> 12) + i] = paddr + (i << 12); for (int i = 0; i < pages; i++) {
u32 index = (vaddr >> 12) + i;
if (r) { paddrTable[index] = paddr + (i << 12);
for (int i = 0; i < pages; i++) readTable[(vaddr >> 12) + i] = (uintptr_t)(hostPtr + (i << 12)); if (r) readTable[index] = (uintptr_t)(hostPtr + (i << 12));
if (w) writeTable[index] = (uintptr_t)(hostPtr + (i << 12));
} }
if (w) {
for (int i = 0; i < pages; i++) writeTable[(vaddr >> 12) + i] = (uintptr_t)(hostPtr + (i << 12));
}
return true;
} }
Helpers::panic("Can't map physical memory!"); return true;
return false;
} }
bool Memory::mapVirtualMemory(u32 dstVaddr, u32 srcVaddr, s32 pages, bool r, bool w, bool x) bool Memory::mapVirtualMemory(u32 dstVaddr, u32 srcVaddr, s32 pages, bool r, bool w, bool x, MemoryState oldDstState, MemoryState oldSrcState,
{ MemoryState newDstState, MemoryState newSrcState) {
// The regions must have the specified state
auto res = testMemoryState(srcVaddr, pages, oldSrcState);
if (res.isFailure()) return false;
res = testMemoryState(dstVaddr, pages, oldDstState);
if (res.isFailure()) return false;
// Get a list of physical blocks in the source region // Get a list of physical blocks in the source region
FcramBlockList physicalList; FcramBlockList physicalList;
u32 oldSrcVaddr = srcVaddr;
s32 srcPages = pages; s32 srcPages = pages;
for (auto& alloc : memoryInfo) { for (auto& alloc : memoryInfo) {
u32 blockStart = alloc.baseAddr; u32 blockStart = alloc.baseAddr;
u32 blockEnd = alloc.end(); u32 blockEnd = alloc.end();
if (!(srcVaddr >= blockStart && srcVaddr < blockEnd)) continue; if (!(srcVaddr >= blockStart && srcVaddr < blockEnd)) continue;
if (alloc.state == MemoryState::Free) Helpers::panic("Found free block when mapping virtual memory!");
s32 blockPaddr = paddrTable[srcVaddr >> 12]; s32 blockPaddr = paddrTable[srcVaddr >> 12];
s32 blockPages = alloc.pages - ((srcVaddr - blockStart) >> 12); s32 blockPages = alloc.pages - ((srcVaddr - blockStart) >> 12);
blockPages = std::min(pages, blockPages); blockPages = std::min(srcPages, blockPages);
FcramBlock physicalBlock(blockPaddr, blockPages); FcramBlock physicalBlock(blockPaddr, blockPages);
physicalList.push_back(physicalBlock); physicalList.push_back(physicalBlock);
@ -406,9 +428,13 @@ bool Memory::mapVirtualMemory(u32 dstVaddr, u32 srcVaddr, s32 pages, bool r, boo
// Map each physical block // Map each physical block
// FIXME: this is O(n^2)... // FIXME: this is O(n^2)...
srcVaddr = oldSrcVaddr;
for (auto& block : physicalList) { for (auto& block : physicalList) {
if (!mapPhysicalMemory(dstVaddr, block.paddr, block.pages, r, w, x)) Helpers::panic("Failed to map virtual memory!"); // TODO: how do permissions on the source side work?
if (!mapPhysicalMemory(srcVaddr, block.paddr, block.pages, true, true, false, newSrcState)) Helpers::panic("Failed to map src virtual memory!");
if (!mapPhysicalMemory(dstVaddr, block.paddr, block.pages, r, w, x, newDstState)) Helpers::panic("Failed to map dst virtual memory!");
srcVaddr += block.pages << 12;
dstVaddr += block.pages << 12; dstVaddr += block.pages << 12;
} }
@ -430,6 +456,21 @@ Result::HorizonResult Memory::queryMemory(MemoryInfo& out, u32 vaddr) {
return Result::FailurePlaceholder; return Result::FailurePlaceholder;
} }
Result::HorizonResult Memory::testMemoryState(u32 vaddr, s32 pages, MemoryState desiredState) {
for (auto& alloc : memoryInfo) {
// Don't bother checking if we're to the left of the requested region
if (vaddr >= alloc.end()) continue;
if (alloc.state != desiredState) return Result::FailurePlaceholder; // TODO: error for state mismatch
// If the end of this block comes after the end of the requested range with no errors, it's a success
if (alloc.end() >= vaddr + (pages << 12)) return Result::Success;
}
// TODO: error for when address is outside of userland
return Result::FailurePlaceholder;
}
void Memory::copyToVaddr(u32 dstVaddr, const u8* srcHost, s32 size) { void Memory::copyToVaddr(u32 dstVaddr, const u8* srcHost, s32 size) {
// TODO: check for noncontiguous allocations // TODO: check for noncontiguous allocations
u8* dstHost = (u8*)readTable[dstVaddr >> 12] + (dstVaddr & 0xFFF); u8* dstHost = (u8*)readTable[dstVaddr >> 12] + (dstVaddr & 0xFFF);
@ -454,7 +495,7 @@ u8* Memory::mapSharedMemory(Handle handle, u32 vaddr, u32 myPerms, u32 otherPerm
bool w = myPerms & 0b010; bool w = myPerms & 0b010;
bool x = myPerms & 0b100; bool x = myPerms & 0b100;
if (!mapPhysicalMemory(vaddr, paddr, size >> 12, true, true, false)) { if (!mapPhysicalMemory(vaddr, paddr, size >> 12, true, true, false, MemoryState::Shared)) {
Helpers::panic("Memory::mapSharedMemory: Failed to map shared memory block"); Helpers::panic("Memory::mapSharedMemory: Failed to map shared memory block");
return nullptr; return nullptr;
} }

View file

@ -141,6 +141,8 @@ static const std::string CRO_MAGIC("CRO0");
static const std::string CRO_MAGIC_FIXED("FIXD"); static const std::string CRO_MAGIC_FIXED("FIXD");
static const std::string CRR_MAGIC("CRR0"); static const std::string CRR_MAGIC("CRR0");
using namespace KernelMemoryTypes;
class CRO { class CRO {
Memory &mem; Memory &mem;
@ -1237,7 +1239,11 @@ void LDRService::initialize(u32 messagePointer) {
// Map CRO to output address // Map CRO to output address
// TODO: how to handle permissions? // TODO: how to handle permissions?
mem.mapVirtualMemory(mapVaddr, crsPointer, size >> 12, true, true, true); bool succeeded = mem.mapVirtualMemory(mapVaddr, crsPointer, size >> 12, true, true, true,
MemoryState::Free, MemoryState::Private, MemoryState::Locked, MemoryState::AliasCode);
if (!succeeded) {
Helpers::panic("Failed to map CRS");
}
CRO crs(mem, mapVaddr, false); CRO crs(mem, mapVaddr, false);
@ -1328,7 +1334,11 @@ void LDRService::loadCRO(u32 messagePointer, bool isNew) {
// Map CRO to output address // Map CRO to output address
// TODO: how to handle permissions? // TODO: how to handle permissions?
mem.mapVirtualMemory(mapVaddr, croPointer, size >> 12, true, true, true); bool succeeded = mem.mapVirtualMemory(mapVaddr, croPointer, size >> 12, true, true, true,
MemoryState::Free, MemoryState::Private, MemoryState::Locked, MemoryState::AliasCode);
if (!succeeded) {
Helpers::panic("Failed to map CRO");
}
CRO cro(mem, mapVaddr, true); CRO cro(mem, mapVaddr, true);