mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-11 08:39:48 +12:00
[Kernel] Implement CreateMemoryBlock
This commit is contained in:
parent
ec7c0b86b7
commit
980139e588
5 changed files with 93 additions and 7 deletions
|
@ -45,6 +45,7 @@ class Kernel {
|
|||
Handle makePort(const char* name);
|
||||
Handle makeSession(Handle port);
|
||||
Handle makeThread(u32 entrypoint, u32 initialSP, u32 priority, s32 id, u32 arg,ThreadStatus status = ThreadStatus::Dormant);
|
||||
Handle makeMemoryBlock(u32 addr, u32 size, u32 myPermission, u32 otherPermission);
|
||||
|
||||
public:
|
||||
Handle makeEvent(ResetType resetType); // Needs to be public to be accessible to the APT/HID services
|
||||
|
|
|
@ -17,13 +17,17 @@ namespace SVCResult {
|
|||
BadHandle = 0xD8E007F7,
|
||||
BadHandleAlt = 0xD9001BF7,
|
||||
|
||||
InvalidCombination = 0xE0E01BEE, // Used for invalid memory permission combinations
|
||||
UnalignedAddr = 0xE0E01BF1,
|
||||
UnalignedSize = 0xE0E01BF2,
|
||||
|
||||
BadThreadPriority = 0xE0E01BFD,
|
||||
PortNameTooLong = 0xE0E0181E,
|
||||
};
|
||||
}
|
||||
|
||||
enum class KernelObjectType : u8 {
|
||||
AddressArbiter, Archive, File, Process, ResourceLimit, Session, Dummy,
|
||||
AddressArbiter, Archive, File, MemoryBlock, Process, ResourceLimit, Session, Dummy,
|
||||
// Bundle waitable objects together in the enum to let the compiler optimize certain checks better
|
||||
Event, Mutex, Port, Semaphore, Timer, Thread
|
||||
};
|
||||
|
@ -142,6 +146,7 @@ static const char* kernelObjectTypeToString(KernelObjectType t) {
|
|||
case KernelObjectType::Archive: return "archive";
|
||||
case KernelObjectType::Event: return "event";
|
||||
case KernelObjectType::File: return "file";
|
||||
case KernelObjectType::MemoryBlock: return "memory block";
|
||||
case KernelObjectType::Port: return "port";
|
||||
case KernelObjectType::Process: return "process";
|
||||
case KernelObjectType::ResourceLimit: return "resource limit";
|
||||
|
@ -168,6 +173,17 @@ struct Semaphore {
|
|||
Semaphore(u32 initialCount, u32 maximumCount) : initialCount(initialCount), maximumCount(maximumCount) {}
|
||||
};
|
||||
|
||||
struct MemoryBlock {
|
||||
u32 addr = 0;
|
||||
u32 size = 0;
|
||||
u32 myPermission = 0;
|
||||
u32 otherPermission = 0;
|
||||
bool mapped = false;
|
||||
|
||||
MemoryBlock(u32 addr, u32 size, u32 myPerm, u32 otherPerm) : addr(addr), size(size), myPermission(myPerm), otherPermission(otherPerm),
|
||||
mapped(false) {}
|
||||
};
|
||||
|
||||
// Generic kernel object class
|
||||
struct KernelObject {
|
||||
Handle handle = 0; // A u32 the OS will use to identify objects
|
||||
|
|
|
@ -10,6 +10,7 @@ class MICService {
|
|||
MAKE_LOG_FUNCTION(log, micLogger)
|
||||
|
||||
// Service commands
|
||||
void mapSharedMem(u32 messagePointer);
|
||||
|
||||
public:
|
||||
MICService(Memory& mem) : mem(mem) {}
|
||||
|
|
|
@ -16,6 +16,21 @@ namespace Operation {
|
|||
};
|
||||
}
|
||||
|
||||
namespace MemoryPermissions {
|
||||
enum : u32 {
|
||||
None = 0, // ---
|
||||
Read = 1, // R--
|
||||
Write = 2, // -W-
|
||||
ReadWrite = 3, // RW-
|
||||
Execute = 4, // --X
|
||||
ReadExecute = 5, // R-X
|
||||
WriteExecute = 6, // -WX
|
||||
ReadWriteExecute = 7, // RWX
|
||||
|
||||
DontCare = 0x10000000
|
||||
};
|
||||
}
|
||||
|
||||
// Returns whether "value" is aligned to a page boundary (Ie a boundary of 4096 bytes)
|
||||
static constexpr bool isAligned(u32 value) {
|
||||
return (value & 0xFFF) == 0;
|
||||
|
@ -32,8 +47,8 @@ void Kernel::controlMemory() {
|
|||
u32 size = regs[3];
|
||||
u32 perms = regs[4];
|
||||
|
||||
if (perms == 0x10000000) {
|
||||
perms = 3; // We make "don't care" equivalent to read-write
|
||||
if (perms == MemoryPermissions::DontCare) {
|
||||
perms = MemoryPermissions::ReadWrite; // We make "don't care" equivalent to read-write
|
||||
Helpers::panic("Unimplemented allocation permission: DONTCARE");
|
||||
}
|
||||
|
||||
|
@ -126,13 +141,56 @@ void Kernel::mapMemoryBlock() {
|
|||
regs[0] = SVCResult::Success;
|
||||
}
|
||||
|
||||
Handle Kernel::makeMemoryBlock(u32 addr, u32 size, u32 myPermission, u32 otherPermission) {
|
||||
Handle ret = makeObject(KernelObjectType::MemoryBlock);
|
||||
objects[ret].data = new MemoryBlock(addr, size, myPermission, otherPermission);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Kernel::createMemoryBlock() {
|
||||
const u32 addr = regs[1];
|
||||
const u32 size = regs[2];
|
||||
const u32 myPermission = regs[3];
|
||||
const u32 otherPermission = regs[4];
|
||||
u32 myPermission = regs[3];
|
||||
u32 otherPermission = mem.read32(regs[13] + 4); // This is placed on the stack rather than r4
|
||||
logSVC("CreateMemoryBlock (addr = %08X, size = %08X, myPermission = %d, otherPermission = %d)\n", addr, size, myPermission, otherPermission);
|
||||
|
||||
regs[0] = SVCResult::Success; regs[1] = 0x66666666;
|
||||
//Helpers::panic("Kernel::CreateMemoryBlock");
|
||||
// Returns whether a permission is valid
|
||||
auto isPermValid = [](u32 permission) {
|
||||
switch (permission) {
|
||||
case MemoryPermissions::None:
|
||||
case MemoryPermissions::Read:
|
||||
case MemoryPermissions::Write:
|
||||
case MemoryPermissions::ReadWrite:
|
||||
case MemoryPermissions::DontCare:
|
||||
return true;
|
||||
|
||||
default: // Permissions with the executable flag enabled or invalid permissions are not allowed
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// Throw error if the size of the shared memory block is not aligned to page boundary
|
||||
if (!isAligned(size)) {
|
||||
regs[0] = SVCResult::UnalignedSize;
|
||||
return;
|
||||
}
|
||||
|
||||
// Throw error if one of the permissions is not valid
|
||||
if (!isPermValid(myPermission) || !isPermValid(otherPermission)) {
|
||||
regs[0] = SVCResult::InvalidCombination;
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: The address needs to be in a specific range otherwise it throws an invalid address error
|
||||
|
||||
if (addr == 0)
|
||||
Helpers::panic("CreateMemoryBlock: Tried to use addr = 0");
|
||||
|
||||
// Implement "Don't care" permission as RW
|
||||
if (myPermission == MemoryPermissions::DontCare) myPermission = MemoryPermissions::ReadWrite;
|
||||
if (otherPermission == MemoryPermissions::DontCare) otherPermission = MemoryPermissions::ReadWrite;
|
||||
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[1] = makeMemoryBlock(addr, size, myPermission, otherPermission);
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace MICCommands {
|
||||
enum : u32 {
|
||||
MapSharedMem = 0x00010042
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -16,6 +17,15 @@ void MICService::reset() {}
|
|||
void MICService::handleSyncRequest(u32 messagePointer) {
|
||||
const u32 command = mem.read32(messagePointer);
|
||||
switch (command) {
|
||||
case MICCommands::MapSharedMem: mapSharedMem(messagePointer); break;
|
||||
default: Helpers::panic("MIC service requested. Command: %08X\n", command);
|
||||
}
|
||||
}
|
||||
|
||||
void MICService::mapSharedMem(u32 messagePointer) {
|
||||
u32 size = mem.read32(messagePointer + 4);
|
||||
u32 handle = mem.read32(messagePointer + 12);
|
||||
|
||||
log("MIC::MapSharedMem (size = %08X, handle = %X) (stubbed)\n", size, handle);
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
Loading…
Add table
Reference in a new issue