[Kernel, Memory] Add GetProcessInfo, fix memory management bugs

This commit is contained in:
wheremyfoodat 2022-09-21 22:43:43 +03:00
parent 71ca62e2cc
commit db48d08c34
6 changed files with 66 additions and 7 deletions

View file

@ -35,8 +35,9 @@ std::optional<u32> Memory::loadELF(std::ifstream& file) {
u64 endAddress = (u64)vaddr + (u64)fileSize;
const bool isGood = vaddr >= VirtualAddrs::ExecutableStart && endAddress < VirtualAddrs::ExecutableEnd;
if (!isGood) {
Helpers::panic("ELF is loaded at invalid place");
return std::nullopt;
// We're ignoring this for now because some ELFs define a segment at the vaddr for IPC buffer mapping
// Helpers::panic("ELF is loaded at invalid place");
// return std::nullopt;
}
if (memorySize & pageMask) {

View file

@ -12,6 +12,8 @@ Kernel::Kernel(CPU& cpu, Memory& mem, GPU& gpu)
threads[i].tlsBase = VirtualAddrs::TLSBase + i * VirtualAddrs::TLSSize;
threads[i].status = ThreadStatus::Dead;
}
setVersion(1, 69);
}
void Kernel::serviceSVC(u32 svc) {
@ -27,6 +29,7 @@ void Kernel::serviceSVC(u32 svc) {
case 0x23: svcCloseHandle(); break;
case 0x24: waitSynchronization1(); break;
case 0x28: getSystemTick(); break;
case 0x2B: getProcessInfo(); break;
case 0x2D: connectToPort(); break;
case 0x32: sendSyncRequest(); break;
case 0x38: getResourceLimit(); break;
@ -37,6 +40,13 @@ void Kernel::serviceSVC(u32 svc) {
}
}
void Kernel::setVersion(u8 major, u8 minor) {
u16 descriptor = (u16(major) << 8) | u16(minor);
kernelVersion = descriptor;
mem.kernelVersion = descriptor; // The memory objects needs a copy because you can read the kernel ver from config mem
}
Handle Kernel::makeProcess() {
const Handle processHandle = makeObject(KernelObjectType::Process);
const Handle resourceLimitHandle = makeObject(KernelObjectType::ResourceLimit);
@ -129,6 +139,30 @@ void Kernel::outputDebugString() {
regs[0] = SVCResult::Success;
}
void Kernel::getProcessInfo() {
const auto pid = regs[1];
const auto type = regs[2];
const auto process = getProcessFromPID(pid);
printf("GetProcessInfo(process: %s, type = %d)\n", getProcessName(pid).c_str(), type);
if (process == nullptr) [[unlikely]] {
regs[0] = SVCResult::BadHandle;
return;
}
switch (type) {
case 20:
regs[1] = PhysicalAddrs::FCRAM - mem.getLinearHeapVaddr();
regs[2] = 0;
break;
default:
Helpers::panic("GetProcessInfo: unimplemented type %d", type);
}
regs[0] = SVCResult::Success;
}
std::string Kernel::getProcessName(u32 pid) {
if (pid == KernelHandles::CurrentProcess) {
return "current";

View file

@ -56,7 +56,8 @@ u8 Memory::read8(u32 vaddr) {
}
else {
switch (vaddr) {
case ConfigMem::KernelVersionMinor: return 38;
case ConfigMem::KernelVersionMinor: return u8(kernelVersion & 0xff);
case ConfigMem::KernelVersionMajor: return u8(kernelVersion >> 8);
default: Helpers::panic("Unimplemented 8-bit read, addr: %08X", vaddr);
}
}
@ -169,6 +170,12 @@ std::string Memory::readString(u32 address, u32 maxSize) {
return string;
}
// Return a pointer to the linear heap vaddr based on the kernel ver, because it needed to be moved
// thanks to the New 3DS having more FCRAM
u32 Memory::getLinearHeapVaddr() {
return (kernelVersion < 0x22C) ? VirtualAddrs::LinearHeapStartOld : VirtualAddrs::LinearHeapStartNew;
}
std::optional<u32> Memory::allocateMemory(u32 vaddr, u32 paddr, u32 size, bool linear, bool r, bool w, bool x,
bool adjustAddrs) {
// Kernel-allocated memory & size must always be aligned to a page boundary
@ -190,7 +197,7 @@ std::optional<u32> Memory::allocateMemory(u32 vaddr, u32 paddr, u32 size, bool l
// Get the full vaddr.
// TODO: Fix this
if (vaddr == 0 && adjustAddrs) {
vaddr = usedUserMemory + (linear ? VirtualAddrs::LinearHeapStart : VirtualAddrs::NormalHeapStart);
vaddr = usedUserMemory + (linear ? getLinearHeapVaddr() : VirtualAddrs::NormalHeapStart);
}
usedUserMemory += size;
@ -234,6 +241,7 @@ std::optional<u32> Memory::allocateMemory(u32 vaddr, u32 paddr, u32 size, bool l
// Find a paddr which we can use for allocating "size" bytes
std::optional<u32> Memory::findPaddr(u32 size) {
assert(isAligned(size));
const u32 neededPages = size / pageSize;
// The FCRAM page we're testing to see if it's appropriate to use
@ -250,7 +258,8 @@ std::optional<u32> Memory::findPaddr(u32 size) {
else { // Our candidate page has 1 mor
counter++;
// Check if there's enough free memory to use this page
if (counter == neededPages) {
// We use == instead of >= because some software does 0-byte allocations
if (counter >= neededPages) {
return candidatePage * pageSize;
}
}

View file

@ -251,7 +251,7 @@ void GPUService::memoryFill(u32* cmd) {
// Actually send command list (aka display list) to GPU
void GPUService::processCommandList(u32* cmd) {
u32 address = cmd[1]; // Buffer address
u32 address = cmd[1] & ~7; // Buffer address
u32 size = cmd[2] * 8; // Buffer size in bytes
bool updateGas = cmd[3] == 1; // Update gas additive blend results (0 = don't update, 1 = update)
bool flushBuffer = cmd[7] == 1; // Flush buffer (0 = don't flush, 1 = flush)