mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-19 12:10:59 +12:00
Memory: Rework FCRAM management entirely
Disables a lot of functionality... but I didn't want to commit too much to this commit Also reworks virtual memory management somewhat (but needs more work)
This commit is contained in:
parent
8e303d8d08
commit
f230384444
16 changed files with 411 additions and 251 deletions
47
include/kernel/fcram.hpp
Normal file
47
include/kernel/fcram.hpp
Normal file
|
@ -0,0 +1,47 @@
|
|||
#pragma once
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include "kernel_types.hpp"
|
||||
|
||||
class Memory;
|
||||
|
||||
typedef std::list<FcramBlock> FcramBlockList;
|
||||
|
||||
class KFcram {
|
||||
struct Region {
|
||||
struct Block {
|
||||
s32 pages;
|
||||
s32 pageOffs;
|
||||
bool used;
|
||||
|
||||
Block(s32 pages, u32 pageOffs) : pages(pages), pageOffs(pageOffs), used(false) {}
|
||||
};
|
||||
|
||||
std::list<Block> blocks;
|
||||
u32 start;
|
||||
s32 pages;
|
||||
s32 freePages;
|
||||
public:
|
||||
Region() : start(0), pages(0) {}
|
||||
void reset(u32 start, size_t size);
|
||||
void alloc(std::list<FcramBlock>& out, s32 pages, bool linear);
|
||||
|
||||
u32 getUsedCount();
|
||||
u32 getFreeCount();
|
||||
};
|
||||
|
||||
Memory& mem;
|
||||
|
||||
Region appRegion, sysRegion, baseRegion;
|
||||
uint8_t* fcram;
|
||||
std::unique_ptr<u32> refs;
|
||||
public:
|
||||
KFcram(Memory& memory);
|
||||
void reset(size_t ramSize, size_t appSize, size_t sysSize, size_t baseSize);
|
||||
void alloc(FcramBlockList& out, s32 pages, FcramRegion region, bool linear);
|
||||
|
||||
void incRef(FcramBlockList& list);
|
||||
void decRef(FcramBlockList& list);
|
||||
|
||||
u32 getUsedCount(FcramRegion region);
|
||||
};
|
|
@ -7,6 +7,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include "config.hpp"
|
||||
#include "fcram.hpp"
|
||||
#include "helpers.hpp"
|
||||
#include "kernel_types.hpp"
|
||||
#include "logger.hpp"
|
||||
|
@ -21,6 +22,8 @@ class Kernel {
|
|||
CPU& cpu;
|
||||
Memory& mem;
|
||||
|
||||
KFcram fcramManager;
|
||||
|
||||
// The handle number for the next kernel object to be created
|
||||
u32 handleCounter;
|
||||
// A list of our OS threads, the max number of which depends on the resource limit (hardcoded 32 per process on retail it seems).
|
||||
|
@ -243,6 +246,7 @@ public:
|
|||
}
|
||||
|
||||
ServiceManager& getServiceManager() { return serviceManager; }
|
||||
KFcram& getFcramManager() { return fcramManager; }
|
||||
|
||||
void sendGPUInterrupt(GPUInterrupt type) { serviceManager.sendGPUInterrupt(type); }
|
||||
void clearInstructionCache();
|
||||
|
|
|
@ -44,6 +44,12 @@ enum class ProcessorID : s32 {
|
|||
New3DSExtra2 = 3
|
||||
};
|
||||
|
||||
enum class FcramRegion {
|
||||
App = 0x100,
|
||||
Sys = 0x200,
|
||||
Base = 0x300
|
||||
};
|
||||
|
||||
struct AddressArbiter {};
|
||||
|
||||
struct ResourceLimits {
|
||||
|
@ -242,4 +248,11 @@ struct KernelObject {
|
|||
Helpers::panic("Called GetWaitList on kernel object without a waitlist (Type: %s)", getTypeName());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct FcramBlock {
|
||||
u32 paddr;
|
||||
s32 pages;
|
||||
|
||||
FcramBlock(u32 paddr, s32 pages) : paddr(paddr), pages(pages) {}
|
||||
};
|
|
@ -4,14 +4,17 @@
|
|||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <optional>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
#include "config.hpp"
|
||||
#include "crypto/aes_engine.hpp"
|
||||
#include "handles.hpp"
|
||||
#include "helpers.hpp"
|
||||
#include "kernel/kernel_types.hpp"
|
||||
#include "loader/ncsd.hpp"
|
||||
#include "loader/3dsx.hpp"
|
||||
#include "result/result.hpp"
|
||||
#include "services/region_codes.hpp"
|
||||
|
||||
namespace PhysicalAddrs {
|
||||
|
@ -45,7 +48,7 @@ namespace VirtualAddrs {
|
|||
LinearHeapEndNew = 0x40000000,
|
||||
|
||||
// Start of TLS for first thread. Next thread's storage will be at TLSBase + 0x1000, and so on
|
||||
TLSBase = 0xFF400000,
|
||||
TLSBase = 0x1FF82000,
|
||||
TLSSize = 0x1000,
|
||||
|
||||
VramStart = 0x1F000000,
|
||||
|
@ -77,17 +80,15 @@ namespace KernelMemoryTypes {
|
|||
PERMISSION_X = 1 << 2
|
||||
};
|
||||
|
||||
// I assume this is referring to a single piece of allocated memory? If it's for pages, it makes no sense.
|
||||
// If it's for multiple allocations, it also makes no sense
|
||||
struct MemoryInfo {
|
||||
u32 baseAddr; // Base process virtual address. Used as a paddr in lockedMemoryInfo instead
|
||||
u32 size; // Of what?
|
||||
u32 perms; // Is this referring to a single page or?
|
||||
u32 baseAddr;
|
||||
u32 pages;
|
||||
u32 perms;
|
||||
u32 state;
|
||||
|
||||
u32 end() { return baseAddr + size; }
|
||||
MemoryInfo(u32 baseAddr, u32 size, u32 perms, u32 state) : baseAddr(baseAddr), size(size)
|
||||
, perms(perms), state(state) {}
|
||||
u32 end() { return baseAddr + (pages << 12); }
|
||||
MemoryInfo() : baseAddr(0), pages(0), perms(0), state(0) {}
|
||||
MemoryInfo(u32 baseAddr, u32 pages, u32 perms, u32 state) : baseAddr(baseAddr), pages(pages), perms(perms), state(state) {}
|
||||
};
|
||||
|
||||
// Shared memory block for HID, GSP:GPU etc
|
||||
|
@ -101,6 +102,9 @@ namespace KernelMemoryTypes {
|
|||
};
|
||||
}
|
||||
|
||||
class KFcram;
|
||||
enum class FcramRegion;
|
||||
|
||||
class Memory {
|
||||
u8* fcram;
|
||||
u8* dspRam; // Provided to us by Audio
|
||||
|
@ -109,11 +113,17 @@ class Memory {
|
|||
u64& cpuTicks; // Reference to the CPU tick counter
|
||||
using SharedMemoryBlock = KernelMemoryTypes::SharedMemoryBlock;
|
||||
|
||||
// TODO: remove this reference when Peach's excellent page table code is moved to a better home
|
||||
KFcram& fcramManager;
|
||||
|
||||
// Our dynarmic core uses page tables for reads and writes with 4096 byte pages
|
||||
std::vector<uintptr_t> readTable, writeTable;
|
||||
|
||||
// vaddr->paddr translation table
|
||||
std::vector<u32> paddrTable;
|
||||
|
||||
// This tracks our OS' memory allocations
|
||||
std::vector<KernelMemoryTypes::MemoryInfo> memoryInfo;
|
||||
std::list<KernelMemoryTypes::MemoryInfo> memoryInfo;
|
||||
|
||||
std::array<SharedMemoryBlock, 5> sharedMemBlocks = {
|
||||
SharedMemoryBlock(0, 0, KernelHandles::FontSharedMemHandle), // Shared memory for the system font (size is 0 because we read the size from the cmrc filesystem
|
||||
|
@ -131,6 +141,9 @@ public:
|
|||
|
||||
static constexpr u32 FCRAM_SIZE = u32(128_MB);
|
||||
static constexpr u32 FCRAM_APPLICATION_SIZE = u32(64_MB);
|
||||
static constexpr u32 FCRAM_SYSTEM_SIZE = u32(44_MB);
|
||||
static constexpr u32 FCRAM_BASE_SIZE = u32(20_MB);
|
||||
|
||||
static constexpr u32 FCRAM_PAGE_COUNT = FCRAM_SIZE / pageSize;
|
||||
static constexpr u32 FCRAM_APPLICATION_PAGE_COUNT = FCRAM_APPLICATION_SIZE / pageSize;
|
||||
|
||||
|
@ -139,8 +152,8 @@ public:
|
|||
static constexpr u32 DSP_DATA_MEMORY_OFFSET = u32(256_KB);
|
||||
|
||||
private:
|
||||
std::bitset<FCRAM_PAGE_COUNT> usedFCRAMPages;
|
||||
std::optional<u32> findPaddr(u32 size);
|
||||
//std::bitset<FCRAM_PAGE_COUNT> usedFCRAMPages;
|
||||
//std::optional<u32> findPaddr(u32 size);
|
||||
u64 timeSince3DSEpoch();
|
||||
|
||||
// https://www.3dbrew.org/wiki/Configuration_Memory#ENVINFO
|
||||
|
@ -167,10 +180,8 @@ private:
|
|||
|
||||
public:
|
||||
u16 kernelVersion = 0;
|
||||
u32 usedUserMemory = u32(0_MB); // How much of the APPLICATION FCRAM range is used (allocated to the appcore)
|
||||
u32 usedSystemMemory = u32(0_MB); // Similar for the SYSTEM range (reserved for the syscore)
|
||||
|
||||
Memory(u64& cpuTicks, const EmulatorConfig& config);
|
||||
Memory(KFcram& fcramManager, u64& cpuTicks, const EmulatorConfig& config);
|
||||
void reset();
|
||||
void* getReadPointer(u32 address);
|
||||
void* getWritePointer(u32 address);
|
||||
|
@ -196,22 +207,6 @@ private:
|
|||
u32 getLinearHeapVaddr();
|
||||
u8* getFCRAM() { return fcram; }
|
||||
|
||||
// Total amount of OS-only FCRAM available (Can vary depending on how much FCRAM the app requests via the cart exheader)
|
||||
u32 totalSysFCRAM() {
|
||||
return FCRAM_SIZE - FCRAM_APPLICATION_SIZE;
|
||||
}
|
||||
|
||||
// Amount of OS-only FCRAM currently available
|
||||
u32 remainingSysFCRAM() {
|
||||
return totalSysFCRAM() - usedSystemMemory;
|
||||
}
|
||||
|
||||
// Physical FCRAM index to the start of OS FCRAM
|
||||
// We allocate the first part of physical FCRAM for the application, and the rest to the OS. So the index for the OS = application ram size
|
||||
u32 sysFCRAMIndex() {
|
||||
return FCRAM_APPLICATION_SIZE;
|
||||
}
|
||||
|
||||
enum class BatteryLevel {
|
||||
Empty = 0, AlmostEmpty, OneBar, TwoBars, ThreeBars, FourBars
|
||||
};
|
||||
|
@ -253,14 +248,16 @@ private:
|
|||
// 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);
|
||||
KernelMemoryTypes::MemoryInfo queryMemory(u32 vaddr);
|
||||
//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);
|
||||
|
||||
// For internal use
|
||||
// Allocates a "size"-sized chunk of system FCRAM and returns the index of physical FCRAM used for the allocation
|
||||
// Used for allocating things like shared memory and the like
|
||||
u32 allocateSysMemory(u32 size);
|
||||
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 mapPhysicalMemory(u32 vaddr, u32 paddr, s32 pages, bool r, bool w, bool x);
|
||||
bool mapVirtualMemory(u32 dstVaddr, u32 srcVaddr, s32 pages, bool r, bool w, bool x);
|
||||
Result::HorizonResult queryMemory(KernelMemoryTypes::MemoryInfo& out, u32 vaddr);
|
||||
|
||||
void copyToVaddr(u32 dstVaddr, const u8* srcHost, s32 size);
|
||||
|
||||
// Map a shared memory block to virtual address vaddr with permissions "myPerms"
|
||||
// The kernel has a second permission parameter in MapMemoryBlock but not sure what's used for
|
||||
|
@ -270,7 +267,7 @@ private:
|
|||
|
||||
// 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);
|
||||
// void mirrorMapping(u32 destAddress, u32 sourceAddress, u32 size);
|
||||
|
||||
// Backup of the game's CXI partition info, if any
|
||||
std::optional<NCCH> loadedCXI = std::nullopt;
|
||||
|
@ -283,7 +280,6 @@ private:
|
|||
u8* getDSPMem() { return dspRam; }
|
||||
u8* getDSPDataMem() { return &dspRam[DSP_DATA_MEMORY_OFFSET]; }
|
||||
u8* getDSPCodeMem() { return &dspRam[DSP_CODE_MEMORY_OFFSET]; }
|
||||
u32 getUsedUserMem() { return usedUserMemory; }
|
||||
|
||||
void setVRAM(u8* pointer) { vram = pointer; }
|
||||
void setDSPMem(u8* pointer) { dspRam = pointer; }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue