mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	Memory: move memory chunk into pImpl and make them dynamically allocated
Otherwise MSVC would give out-of-memory error on compile time
This commit is contained in:
		
							parent
							
								
									ac1cda21c3
								
							
						
					
					
						commit
						7e8ba6ed8e
					
				
					 6 changed files with 64 additions and 36 deletions
				
			
		|  | @ -188,10 +188,10 @@ ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission per | |||
|         u32 interval_size = interval.upper() - interval.lower(); | ||||
|         LOG_DEBUG(Kernel, "Allocated FCRAM region lower={:08X}, upper={:08X}", interval.lower(), | ||||
|                   interval.upper()); | ||||
|         std::fill(kernel.memory.fcram.begin() + interval.lower(), | ||||
|                   kernel.memory.fcram.begin() + interval.upper(), 0); | ||||
|         std::fill(kernel.memory.GetFCRAMPointer(interval.lower()), | ||||
|                   kernel.memory.GetFCRAMPointer(interval.upper()), 0); | ||||
|         auto vma = vm_manager.MapBackingMemory(interval_target, | ||||
|                                                kernel.memory.fcram.data() + interval.lower(), | ||||
|                                                kernel.memory.GetFCRAMPointer(interval.lower()), | ||||
|                                                interval_size, memory_state); | ||||
|         ASSERT(vma.Succeeded()); | ||||
|         vm_manager.Reprotect(vma.Unwrap(), perms); | ||||
|  | @ -263,7 +263,7 @@ ResultVal<VAddr> Process::LinearAllocate(VAddr target, u32 size, VMAPermission p | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     u8* backing_memory = kernel.memory.fcram.data() + physical_offset; | ||||
|     u8* backing_memory = kernel.memory.GetFCRAMPointer(physical_offset); | ||||
| 
 | ||||
|     std::fill(backing_memory, backing_memory + size, 0); | ||||
|     auto vma = vm_manager.MapBackingMemory(target, backing_memory, size, MemoryState::Continuous); | ||||
|  |  | |||
|  | @ -43,8 +43,8 @@ ResultVal<SharedPtr<SharedMemory>> KernelSystem::CreateSharedMemory( | |||
| 
 | ||||
|         ASSERT_MSG(offset, "Not enough space in region to allocate shared memory!"); | ||||
| 
 | ||||
|         std::fill(memory.fcram.data() + *offset, memory.fcram.data() + *offset + size, 0); | ||||
|         shared_memory->backing_blocks = {{memory.fcram.data() + *offset, size}}; | ||||
|         std::fill(memory.GetFCRAMPointer(*offset), memory.GetFCRAMPointer(*offset + size), 0); | ||||
|         shared_memory->backing_blocks = {{memory.GetFCRAMPointer(*offset), size}}; | ||||
|         shared_memory->holding_memory += MemoryRegionInfo::Interval(*offset, *offset + size); | ||||
|         shared_memory->linear_heap_phys_offset = *offset; | ||||
| 
 | ||||
|  | @ -86,8 +86,8 @@ SharedPtr<SharedMemory> KernelSystem::CreateSharedMemoryForApplet( | |||
|     shared_memory->other_permissions = other_permissions; | ||||
|     for (const auto& interval : backing_blocks) { | ||||
|         shared_memory->backing_blocks.push_back( | ||||
|             {memory.fcram.data() + interval.lower(), interval.upper() - interval.lower()}); | ||||
|         std::fill(memory.fcram.data() + interval.lower(), memory.fcram.data() + interval.upper(), | ||||
|             {memory.GetFCRAMPointer(interval.lower()), interval.upper() - interval.lower()}); | ||||
|         std::fill(memory.GetFCRAMPointer(interval.lower()), memory.GetFCRAMPointer(interval.upper()), | ||||
|                   0); | ||||
|     } | ||||
|     shared_memory->base_address = Memory::HEAP_VADDR + offset; | ||||
|  |  | |||
|  | @ -355,7 +355,7 @@ ResultVal<SharedPtr<Thread>> KernelSystem::CreateThread(std::string name, VAddr | |||
| 
 | ||||
|         // Map the page to the current process' address space.
 | ||||
|         vm_manager.MapBackingMemory(Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE, | ||||
|                                     memory.fcram.data() + *offset, Memory::PAGE_SIZE, | ||||
|                                     memory.GetFCRAMPointer(*offset), Memory::PAGE_SIZE, | ||||
|                                     MemoryState::Locked); | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -21,15 +21,34 @@ | |||
| 
 | ||||
| namespace Memory { | ||||
| 
 | ||||
| class MemorySystem::Impl { | ||||
| public: | ||||
|     Impl() { | ||||
|         std::fill(fcram.get(), fcram.get() + Memory::FCRAM_N3DS_SIZE, 0); | ||||
|         std::fill(vram.get(), vram.get() + Memory::VRAM_SIZE, 0); | ||||
|         std::fill(n3ds_extra_ram.get(), n3ds_extra_ram.get() + Memory::N3DS_EXTRA_RAM_SIZE, 0); | ||||
|     } | ||||
| 
 | ||||
|     // Visual Studio would try to allocate these on compile time if they are std::array, which would exceed the memory limit.
 | ||||
|     std::unique_ptr<u8[]> fcram = std::make_unique<u8[]>(Memory::FCRAM_N3DS_SIZE); | ||||
|     std::unique_ptr<u8[]> vram = std::make_unique<u8[]>(Memory::VRAM_SIZE); | ||||
|     std::unique_ptr<u8[]> n3ds_extra_ram = std::make_unique<u8[]>(Memory::N3DS_EXTRA_RAM_SIZE); | ||||
| 
 | ||||
|     PageTable* current_page_table = nullptr; | ||||
| }; | ||||
| 
 | ||||
| MemorySystem::MemorySystem() : impl(std::make_unique<Impl>()) {} | ||||
| MemorySystem::~MemorySystem() = default; | ||||
| 
 | ||||
| void MemorySystem::SetCurrentPageTable(PageTable* page_table) { | ||||
|     current_page_table = page_table; | ||||
|     impl->current_page_table = page_table; | ||||
|     if (Core::System::GetInstance().IsPoweredOn()) { | ||||
|         Core::CPU().PageTableChanged(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| PageTable* MemorySystem::GetCurrentPageTable() const { | ||||
|     return current_page_table; | ||||
|     return impl->current_page_table; | ||||
| } | ||||
| 
 | ||||
| static void MapPages(PageTable& page_table, u32 base, u32 size, u8* memory, PageType type) { | ||||
|  | @ -74,13 +93,13 @@ void UnmapRegion(PageTable& page_table, VAddr base, u32 size) { | |||
| 
 | ||||
| u8* MemorySystem::GetPointerForRasterizerCache(VAddr addr) { | ||||
|     if (addr >= LINEAR_HEAP_VADDR && addr < LINEAR_HEAP_VADDR_END) { | ||||
|         return fcram.data() + (addr - LINEAR_HEAP_VADDR); | ||||
|         return impl->fcram.get() + (addr - LINEAR_HEAP_VADDR); | ||||
|     } | ||||
|     if (addr >= NEW_LINEAR_HEAP_VADDR && addr < NEW_LINEAR_HEAP_VADDR_END) { | ||||
|         return fcram.data() + (addr - NEW_LINEAR_HEAP_VADDR); | ||||
|         return impl->fcram.get() + (addr - NEW_LINEAR_HEAP_VADDR); | ||||
|     } | ||||
|     if (addr >= VRAM_VADDR && addr < VRAM_VADDR_END) { | ||||
|         return vram.data() + (addr - VRAM_VADDR); | ||||
|         return impl->vram.get() + (addr - VRAM_VADDR); | ||||
|     } | ||||
|     UNREACHABLE(); | ||||
| } | ||||
|  | @ -103,7 +122,7 @@ T ReadMMIO(MMIORegionPointer mmio_handler, VAddr addr); | |||
| 
 | ||||
| template <typename T> | ||||
| T MemorySystem::Read(const VAddr vaddr) { | ||||
|     const u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; | ||||
|     const u8* page_pointer = impl->current_page_table->pointers[vaddr >> PAGE_BITS]; | ||||
|     if (page_pointer) { | ||||
|         // NOTE: Avoid adding any extra logic to this fast-path block
 | ||||
|         T value; | ||||
|  | @ -114,7 +133,7 @@ T MemorySystem::Read(const VAddr vaddr) { | |||
|     // The memory access might do an MMIO or cached access, so we have to lock the HLE kernel state
 | ||||
|     std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock); | ||||
| 
 | ||||
|     PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; | ||||
|     PageType type = impl->current_page_table->attributes[vaddr >> PAGE_BITS]; | ||||
|     switch (type) { | ||||
|     case PageType::Unmapped: | ||||
|         LOG_ERROR(HW_Memory, "unmapped Read{} @ 0x{:08X}", sizeof(T) * 8, vaddr); | ||||
|  | @ -130,7 +149,7 @@ T MemorySystem::Read(const VAddr vaddr) { | |||
|         return value; | ||||
|     } | ||||
|     case PageType::Special: | ||||
|         return ReadMMIO<T>(GetMMIOHandler(*current_page_table, vaddr), vaddr); | ||||
|         return ReadMMIO<T>(GetMMIOHandler(*impl->current_page_table, vaddr), vaddr); | ||||
|     default: | ||||
|         UNREACHABLE(); | ||||
|     } | ||||
|  | @ -141,7 +160,7 @@ void WriteMMIO(MMIORegionPointer mmio_handler, VAddr addr, const T data); | |||
| 
 | ||||
| template <typename T> | ||||
| void MemorySystem::Write(const VAddr vaddr, const T data) { | ||||
|     u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; | ||||
|     u8* page_pointer = impl->current_page_table->pointers[vaddr >> PAGE_BITS]; | ||||
|     if (page_pointer) { | ||||
|         // NOTE: Avoid adding any extra logic to this fast-path block
 | ||||
|         std::memcpy(&page_pointer[vaddr & PAGE_MASK], &data, sizeof(T)); | ||||
|  | @ -151,7 +170,7 @@ void MemorySystem::Write(const VAddr vaddr, const T data) { | |||
|     // The memory access might do an MMIO or cached access, so we have to lock the HLE kernel state
 | ||||
|     std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock); | ||||
| 
 | ||||
|     PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; | ||||
|     PageType type = impl->current_page_table->attributes[vaddr >> PAGE_BITS]; | ||||
|     switch (type) { | ||||
|     case PageType::Unmapped: | ||||
|         LOG_ERROR(HW_Memory, "unmapped Write{} 0x{:08X} @ 0x{:08X}", sizeof(data) * 8, (u32)data, | ||||
|  | @ -166,7 +185,7 @@ void MemorySystem::Write(const VAddr vaddr, const T data) { | |||
|         break; | ||||
|     } | ||||
|     case PageType::Special: | ||||
|         WriteMMIO<T>(GetMMIOHandler(*current_page_table, vaddr), vaddr, data); | ||||
|         WriteMMIO<T>(GetMMIOHandler(*impl->current_page_table, vaddr), vaddr, data); | ||||
|         break; | ||||
|     default: | ||||
|         UNREACHABLE(); | ||||
|  | @ -199,12 +218,12 @@ bool MemorySystem::IsValidPhysicalAddress(const PAddr paddr) { | |||
| } | ||||
| 
 | ||||
| u8* MemorySystem::GetPointer(const VAddr vaddr) { | ||||
|     u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; | ||||
|     u8* page_pointer = impl->current_page_table->pointers[vaddr >> PAGE_BITS]; | ||||
|     if (page_pointer) { | ||||
|         return page_pointer + (vaddr & PAGE_MASK); | ||||
|     } | ||||
| 
 | ||||
|     if (current_page_table->attributes[vaddr >> PAGE_BITS] == PageType::RasterizerCachedMemory) { | ||||
|     if (impl->current_page_table->attributes[vaddr >> PAGE_BITS] == PageType::RasterizerCachedMemory) { | ||||
|         return GetPointerForRasterizerCache(vaddr); | ||||
|     } | ||||
| 
 | ||||
|  | @ -256,16 +275,16 @@ u8* MemorySystem::GetPhysicalPointer(PAddr address) { | |||
|     u8* target_pointer = nullptr; | ||||
|     switch (area->paddr_base) { | ||||
|     case VRAM_PADDR: | ||||
|         target_pointer = vram.data() + offset_into_region; | ||||
|         target_pointer = impl->vram.get() + offset_into_region; | ||||
|         break; | ||||
|     case DSP_RAM_PADDR: | ||||
|         target_pointer = Core::DSP().GetDspMemory().data() + offset_into_region; | ||||
|         break; | ||||
|     case FCRAM_PADDR: | ||||
|         target_pointer = fcram.data() + offset_into_region; | ||||
|         target_pointer = impl->fcram.get() + offset_into_region; | ||||
|         break; | ||||
|     case N3DS_EXTRA_RAM_PADDR: | ||||
|         target_pointer = n3ds_extra_ram.data() + offset_into_region; | ||||
|         target_pointer = impl->n3ds_extra_ram.get() + offset_into_region; | ||||
|         break; | ||||
|     default: | ||||
|         UNREACHABLE(); | ||||
|  | @ -303,7 +322,7 @@ void MemorySystem::RasterizerMarkRegionCached(PAddr start, u32 size, bool cached | |||
| 
 | ||||
|     for (unsigned i = 0; i < num_pages; ++i, paddr += PAGE_SIZE) { | ||||
|         for (VAddr vaddr : PhysicalToVirtualAddressForRasterizer(paddr)) { | ||||
|             PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS]; | ||||
|             PageType& page_type = impl->current_page_table->attributes[vaddr >> PAGE_BITS]; | ||||
| 
 | ||||
|             if (cached) { | ||||
|                 // Switch page type to cached if now cached
 | ||||
|  | @ -314,7 +333,7 @@ void MemorySystem::RasterizerMarkRegionCached(PAddr start, u32 size, bool cached | |||
|                     break; | ||||
|                 case PageType::Memory: | ||||
|                     page_type = PageType::RasterizerCachedMemory; | ||||
|                     current_page_table->pointers[vaddr >> PAGE_BITS] = nullptr; | ||||
|                     impl->current_page_table->pointers[vaddr >> PAGE_BITS] = nullptr; | ||||
|                     break; | ||||
|                 default: | ||||
|                     UNREACHABLE(); | ||||
|  | @ -328,7 +347,7 @@ void MemorySystem::RasterizerMarkRegionCached(PAddr start, u32 size, bool cached | |||
|                     break; | ||||
|                 case PageType::RasterizerCachedMemory: { | ||||
|                     page_type = PageType::Memory; | ||||
|                     current_page_table->pointers[vaddr >> PAGE_BITS] = | ||||
|                     impl->current_page_table->pointers[vaddr >> PAGE_BITS] = | ||||
|                         GetPointerForRasterizerCache(vaddr & ~PAGE_MASK); | ||||
|                     break; | ||||
|                 } | ||||
|  | @ -730,8 +749,13 @@ void WriteMMIO<u64>(MMIORegionPointer mmio_handler, VAddr addr, const u64 data) | |||
| } | ||||
| 
 | ||||
| u32 MemorySystem::GetFCRAMOffset(u8* pointer) { | ||||
|     ASSERT(pointer >= fcram.data() && pointer < fcram.data() + fcram.size()); | ||||
|     return pointer - fcram.data(); | ||||
|     ASSERT(pointer >= impl->fcram.get() && pointer <= impl->fcram.get() + Memory::FCRAM_N3DS_SIZE); | ||||
|     return pointer - impl->fcram.get(); | ||||
| } | ||||
| 
 | ||||
| u8* MemorySystem::GetFCRAMPointer(u32 offset) { | ||||
|     ASSERT(offset <= Memory::FCRAM_N3DS_SIZE); | ||||
|     return impl->fcram.get() + offset; | ||||
| } | ||||
| 
 | ||||
| } // namespace Memory
 | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ | |||
| 
 | ||||
| #include <array> | ||||
| #include <cstddef> | ||||
| #include <memory> | ||||
| #include <string> | ||||
| #include <vector> | ||||
| #include "common/common_types.h" | ||||
|  | @ -210,6 +211,9 @@ void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode); | |||
| 
 | ||||
| class MemorySystem { | ||||
| public: | ||||
|     MemorySystem(); | ||||
|     ~MemorySystem(); | ||||
| 
 | ||||
|     /// Currently active page table
 | ||||
|     void SetCurrentPageTable(PageTable* page_table); | ||||
|     PageTable* GetCurrentPageTable() const; | ||||
|  | @ -248,13 +252,14 @@ public: | |||
|     /// Gets offset in FCRAM from a pointer inside FCRAM range
 | ||||
|     u32 GetFCRAMOffset(u8* pointer); | ||||
| 
 | ||||
|     /// Gets pointer in FCRAM with given offset
 | ||||
|     u8* GetFCRAMPointer(u32 offset); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Mark each page touching the region as cached. | ||||
|      */ | ||||
|     void RasterizerMarkRegionCached(PAddr start, u32 size, bool cached); | ||||
| 
 | ||||
|     std::array<u8, Memory::FCRAM_N3DS_SIZE> fcram{}; | ||||
| 
 | ||||
| private: | ||||
|     template <typename T> | ||||
|     T Read(const VAddr vaddr); | ||||
|  | @ -270,10 +275,9 @@ private: | |||
|      */ | ||||
|     u8* GetPointerForRasterizerCache(VAddr addr); | ||||
| 
 | ||||
|     std::array<u8, Memory::VRAM_SIZE> vram{}; | ||||
|     std::array<u8, Memory::N3DS_EXTRA_RAM_SIZE> n3ds_extra_ram{}; | ||||
|     class Impl; | ||||
| 
 | ||||
|     PageTable* current_page_table = nullptr; | ||||
|     std::unique_ptr<Impl> impl; | ||||
| }; | ||||
| 
 | ||||
| /// Determines if the given VAddr is valid for the specified process.
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue