mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-09 15:45:40 +12:00
Memory: Implement Protect operation in ControlMemory
This commit is contained in:
parent
1161703ed6
commit
c65b91e6f1
3 changed files with 49 additions and 21 deletions
|
@ -102,6 +102,7 @@ namespace KernelMemoryTypes {
|
|||
};
|
||||
}
|
||||
|
||||
struct FcramBlock;
|
||||
class KFcram;
|
||||
enum class FcramRegion;
|
||||
|
||||
|
@ -187,6 +188,7 @@ private:
|
|||
static constexpr std::array<u8, 6> MACAddress = {0x40, 0xF4, 0x07, 0xFF, 0xFF, 0xEE};
|
||||
|
||||
void changeMemoryState(u32 vaddr, s32 pages, const Operation& op);
|
||||
void queryPhysicalBlocks(std::list<FcramBlock>& outList, u32 vaddr, s32 pages);
|
||||
void mapPhysicalMemory(u32 vaddr, u32 paddr, s32 pages, bool r, bool w, bool x);
|
||||
void unmapPhysicalMemory(u32 vaddr, u32 paddr, s32 pages);
|
||||
|
||||
|
@ -256,6 +258,7 @@ private:
|
|||
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);
|
||||
void changePermissions(u32 vaddr, s32 pages, bool r, bool w, bool x);
|
||||
Result::HorizonResult queryMemory(KernelMemoryTypes::MemoryInfo& out, u32 vaddr);
|
||||
Result::HorizonResult testMemoryState(u32 vaddr, s32 pages, KernelMemoryTypes::MemoryState desiredState);
|
||||
|
||||
|
|
|
@ -94,7 +94,15 @@ void Kernel::controlMemory() {
|
|||
break;
|
||||
|
||||
case Operation::Protect:
|
||||
Helpers::warn("Ignoring mprotect! Hope nothing goes wrong but if the game accesses invalid memory or crashes then we prolly need to implement this\n");
|
||||
// Official kernel has an internal state bit to indicate that the region's permissions may be changed
|
||||
// But this should account for all cases
|
||||
if (!mem.testMemoryState(addr0, pages, MemoryState::Private) &&
|
||||
!mem.testMemoryState(addr0, pages, MemoryState::Alias) &&
|
||||
!mem.testMemoryState(addr0, pages, MemoryState::Aliased) &&
|
||||
!mem.testMemoryState(addr0, pages, MemoryState::AliasCode)) Helpers::panic("Tried to mprotect invalid region!");
|
||||
|
||||
mem.changePermissions(addr0, pages, r, w, false);
|
||||
regs[1] = addr0;
|
||||
break;
|
||||
|
||||
default: Helpers::warn("ControlMemory: unknown operation %X\n", operation); break;
|
||||
|
|
|
@ -346,6 +346,28 @@ void Memory::changeMemoryState(u32 vaddr, s32 pages, const Operation& op) {
|
|||
}
|
||||
}
|
||||
|
||||
void Memory::queryPhysicalBlocks(FcramBlockList& outList, u32 vaddr, s32 pages) {
|
||||
s32 srcPages = pages;
|
||||
for (auto& alloc : memoryInfo) {
|
||||
u32 blockStart = alloc.baseAddr;
|
||||
u32 blockEnd = alloc.end();
|
||||
|
||||
if (!(vaddr >= blockStart && vaddr < blockEnd)) continue;
|
||||
|
||||
s32 blockPaddr = paddrTable[vaddr >> 12];
|
||||
s32 blockPages = alloc.pages - ((vaddr - blockStart) >> 12);
|
||||
blockPages = std::min(srcPages, blockPages);
|
||||
FcramBlock physicalBlock(blockPaddr, blockPages);
|
||||
outList.push_back(physicalBlock);
|
||||
|
||||
vaddr += blockPages << 12;
|
||||
srcPages -= blockPages;
|
||||
if (srcPages == 0) break;
|
||||
}
|
||||
|
||||
if (srcPages != 0) Helpers::panic("Unable to find virtual pages to map!");
|
||||
}
|
||||
|
||||
void Memory::mapPhysicalMemory(u32 vaddr, u32 paddr, s32 pages, bool r, bool w, bool x) {
|
||||
assert(!(vaddr & 0xFFF));
|
||||
assert(!(paddr & 0xFFF));
|
||||
|
@ -431,26 +453,7 @@ bool Memory::mapVirtualMemory(u32 dstVaddr, u32 srcVaddr, s32 pages, bool r, boo
|
|||
|
||||
// Get a list of physical blocks in the source region
|
||||
FcramBlockList physicalList;
|
||||
|
||||
s32 srcPages = pages;
|
||||
for (auto& alloc : memoryInfo) {
|
||||
u32 blockStart = alloc.baseAddr;
|
||||
u32 blockEnd = alloc.end();
|
||||
|
||||
if (!(srcVaddr >= blockStart && srcVaddr < blockEnd)) continue;
|
||||
|
||||
s32 blockPaddr = paddrTable[srcVaddr >> 12];
|
||||
s32 blockPages = alloc.pages - ((srcVaddr - blockStart) >> 12);
|
||||
blockPages = std::min(srcPages, blockPages);
|
||||
FcramBlock physicalBlock(blockPaddr, blockPages);
|
||||
physicalList.push_back(physicalBlock);
|
||||
|
||||
srcVaddr += blockPages << 12;
|
||||
srcPages -= blockPages;
|
||||
if (srcPages == 0) break;
|
||||
}
|
||||
|
||||
if (srcPages != 0) Helpers::panic("Unable to find virtual pages to map!");
|
||||
queryPhysicalBlocks(physicalList, srcVaddr, pages);
|
||||
|
||||
// Map or unmap each physical block
|
||||
for (auto& block : physicalList) {
|
||||
|
@ -462,6 +465,20 @@ bool Memory::mapVirtualMemory(u32 dstVaddr, u32 srcVaddr, s32 pages, bool r, boo
|
|||
return true;
|
||||
}
|
||||
|
||||
void Memory::changePermissions(u32 vaddr, s32 pages, bool r, bool w, bool x) {
|
||||
Operation op{ .r = r, .w = w, .x = x, .changePerms = true };
|
||||
changeMemoryState(vaddr, pages, op);
|
||||
|
||||
// Now that permissions have been changed, update the corresponding host tables
|
||||
FcramBlockList physicalList;
|
||||
queryPhysicalBlocks(physicalList, vaddr, pages);
|
||||
|
||||
for (auto& block : physicalList) {
|
||||
mapPhysicalMemory(vaddr, block.paddr, block.pages, r, w, x);
|
||||
vaddr += block.pages;
|
||||
}
|
||||
}
|
||||
|
||||
Result::HorizonResult Memory::queryMemory(MemoryInfo& out, u32 vaddr) {
|
||||
// Check each allocation
|
||||
for (auto& alloc : memoryInfo) {
|
||||
|
|
Loading…
Add table
Reference in a new issue