mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-08 23:25:40 +12:00
Proper stack management
This commit is contained in:
parent
4a12e59c2f
commit
2ec3884189
4 changed files with 48 additions and 8 deletions
|
@ -29,7 +29,6 @@ namespace VirtualAddrs {
|
||||||
// Stack for main ARM11 thread.
|
// Stack for main ARM11 thread.
|
||||||
// Typically 0x4000 bytes, determined by exheader
|
// Typically 0x4000 bytes, determined by exheader
|
||||||
StackTop = 0x10000000,
|
StackTop = 0x10000000,
|
||||||
StackBottom = 0x0FFFC000,
|
|
||||||
DefaultStackSize = 0x4000,
|
DefaultStackSize = 0x4000,
|
||||||
|
|
||||||
NormalHeapStart = 0x08000000,
|
NormalHeapStart = 0x08000000,
|
||||||
|
@ -248,4 +247,5 @@ public:
|
||||||
u32 getUsedUserMem() { return usedUserMemory; }
|
u32 getUsedUserMem() { return usedUserMemory; }
|
||||||
|
|
||||||
void setVRAM(u8* pointer) { vram = pointer; }
|
void setVRAM(u8* pointer) { vram = pointer; }
|
||||||
|
bool allocateMainThreadStack(u32 size);
|
||||||
};
|
};
|
|
@ -14,6 +14,13 @@ std::optional<u32> Memory::loadELF(std::ifstream& file) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allocate stack space. For ELFs we use the default stack size, which is 16KB
|
||||||
|
if (!allocateMainThreadStack(VirtualAddrs::DefaultStackSize)) {
|
||||||
|
// Should be unreachable
|
||||||
|
printf("Failed to allocate stack space for ELF file\n");
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
auto segNum = reader.segments.size();
|
auto segNum = reader.segments.size();
|
||||||
printf("Number of segments: %d\n", segNum);
|
printf("Number of segments: %d\n", segNum);
|
||||||
printf(" # Perms Vaddr File Size Mem Size\n");
|
printf(" # Perms Vaddr File Size Mem Size\n");
|
||||||
|
|
|
@ -9,6 +9,27 @@ 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);
|
||||||
printf("Data address = %08X, size = %08X\n", cxi.data.address, cxi.data.size);
|
printf("Data address = %08X, size = %08X\n", cxi.data.address, cxi.data.size);
|
||||||
|
printf("Stack size: %08X\n", cxi.stackSize);
|
||||||
|
|
||||||
|
if (!isAligned(cxi.stackSize)) {
|
||||||
|
Helpers::warn("CXI has a suspicious stack size of %08X which is not a multiple of 4KB", cxi.stackSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Round up the size of the CXI stack size to a page (4KB) boundary, as the OS can only allocate memory this way
|
||||||
|
u32 stackSize = (cxi.stackSize + pageSize - 1) & -pageSize;
|
||||||
|
|
||||||
|
if (stackSize > 512_KB) {
|
||||||
|
// TODO: Figure out the actual max stack size
|
||||||
|
Helpers::warn("CXI stack size is %08X which seems way too big. Clamping to 512KB", stackSize);
|
||||||
|
stackSize = 512_KB;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate stack
|
||||||
|
if (!allocateMainThreadStack(stackSize)) {
|
||||||
|
// Should be unreachable
|
||||||
|
printf("Failed to allocate stack for CXI partition. Requested stack size: %08X\n", stackSize);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Map code file to memory
|
// Map code file to memory
|
||||||
auto& code = cxi.codeFile;
|
auto& code = cxi.codeFile;
|
||||||
|
|
|
@ -28,16 +28,16 @@ void Memory::reset() {
|
||||||
writeTable[i] = 0;
|
writeTable[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map stack pages as R/W
|
// Map (32 * 4) KB of FCRAM before the stack for the TLS of each thread
|
||||||
// We have 16KB for the stack, so we allocate the last 16KB of APPLICATION FCRAM for the stack
|
std::optional<u32> tlsBaseOpt = findPaddr(32 * 4_KB);
|
||||||
u32 basePaddrForStack = FCRAM_APPLICATION_SIZE - VirtualAddrs::DefaultStackSize;
|
if (!tlsBaseOpt.has_value()) { // Should be unreachable but still good to have
|
||||||
allocateMemory(VirtualAddrs::StackBottom, basePaddrForStack, VirtualAddrs::DefaultStackSize, true);
|
Helpers::panic("Failed to allocate memory for thread-local storage");
|
||||||
|
}
|
||||||
|
|
||||||
// And map (4 * 32)KB of FCRAM before the stack for the TLS of each thread
|
u32 basePaddrForTLS = tlsBaseOpt.value();
|
||||||
u32 basePaddrForTLS = basePaddrForStack;
|
|
||||||
for (int i = 0; i < appResourceLimits.maxThreads; i++) {
|
for (int i = 0; i < appResourceLimits.maxThreads; i++) {
|
||||||
u32 vaddr = VirtualAddrs::TLSBase + i * VirtualAddrs::TLSSize;
|
u32 vaddr = VirtualAddrs::TLSBase + i * VirtualAddrs::TLSSize;
|
||||||
basePaddrForTLS -= VirtualAddrs::TLSSize;
|
basePaddrForTLS += VirtualAddrs::TLSSize;
|
||||||
allocateMemory(vaddr, basePaddrForTLS, VirtualAddrs::TLSSize, true);
|
allocateMemory(vaddr, basePaddrForTLS, VirtualAddrs::TLSSize, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +59,18 @@ void Memory::reset() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Memory::allocateMainThreadStack(u32 size) {
|
||||||
|
// Map stack pages as R/W
|
||||||
|
std::optional<u32> basePaddr = findPaddr(size);
|
||||||
|
if (!basePaddr.has_value()) { // Should also be unreachable but still good to have
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 stackBottom = VirtualAddrs::StackTop - size;
|
||||||
|
std::optional<u32> result = allocateMemory(stackBottom, basePaddr.value(), size, true); // Should never be nullopt
|
||||||
|
return result.has_value();
|
||||||
|
}
|
||||||
|
|
||||||
u8 Memory::read8(u32 vaddr) {
|
u8 Memory::read8(u32 vaddr) {
|
||||||
const u32 page = vaddr >> pageShift;
|
const u32 page = vaddr >> pageShift;
|
||||||
const u32 offset = vaddr & pageMask;
|
const u32 offset = vaddr & pageMask;
|
||||||
|
|
Loading…
Add table
Reference in a new issue