mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu.git
				synced 2025-05-12 00:45:25 +00:00 
			
		
		
		
	Merge pull request #908 from lioncash/memory
core/memory: Get rid of 3DS leftovers
This commit is contained in:
		
						commit
						40e63ede6d
					
				| @ -63,8 +63,6 @@ add_library(core STATIC | ||||
|     hle/kernel/hle_ipc.h | ||||
|     hle/kernel/kernel.cpp | ||||
|     hle/kernel/kernel.h | ||||
|     hle/kernel/memory.cpp | ||||
|     hle/kernel/memory.h | ||||
|     hle/kernel/mutex.cpp | ||||
|     hle/kernel/mutex.h | ||||
|     hle/kernel/object.cpp | ||||
|  | ||||
| @ -110,7 +110,7 @@ System::ResultStatus System::Load(EmuWindow& emu_window, const std::string& file | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     ResultStatus init_result{Init(emu_window, system_mode.first.get())}; | ||||
|     ResultStatus init_result{Init(emu_window)}; | ||||
|     if (init_result != ResultStatus::Success) { | ||||
|         LOG_CRITICAL(Core, "Failed to initialize system (Error {})!", | ||||
|                      static_cast<int>(init_result)); | ||||
| @ -161,7 +161,7 @@ Cpu& System::CpuCore(size_t core_index) { | ||||
|     return *cpu_cores[core_index]; | ||||
| } | ||||
| 
 | ||||
| System::ResultStatus System::Init(EmuWindow& emu_window, u32 system_mode) { | ||||
| System::ResultStatus System::Init(EmuWindow& emu_window) { | ||||
|     LOG_DEBUG(HW_Memory, "initialized OK"); | ||||
| 
 | ||||
|     CoreTiming::Init(); | ||||
| @ -178,7 +178,7 @@ System::ResultStatus System::Init(EmuWindow& emu_window, u32 system_mode) { | ||||
|     telemetry_session = std::make_unique<Core::TelemetrySession>(); | ||||
|     service_manager = std::make_shared<Service::SM::ServiceManager>(); | ||||
| 
 | ||||
|     Kernel::Init(system_mode); | ||||
|     Kernel::Init(); | ||||
|     Service::Init(service_manager); | ||||
|     GDBStub::Init(); | ||||
| 
 | ||||
|  | ||||
| @ -189,10 +189,9 @@ private: | ||||
|      * Initialize the emulated system. | ||||
|      * @param emu_window Reference to the host-system window used for video output and keyboard | ||||
|      *                   input. | ||||
|      * @param system_mode The system mode. | ||||
|      * @return ResultStatus code, indicating if the operation succeeded. | ||||
|      */ | ||||
|     ResultStatus Init(EmuWindow& emu_window, u32 system_mode); | ||||
|     ResultStatus Init(EmuWindow& emu_window); | ||||
| 
 | ||||
|     /// AppLoader used to load the current executing application
 | ||||
|     std::unique_ptr<Loader::AppLoader> app_loader; | ||||
|  | ||||
| @ -4,7 +4,6 @@ | ||||
| 
 | ||||
| #include "core/hle/kernel/handle_table.h" | ||||
| #include "core/hle/kernel/kernel.h" | ||||
| #include "core/hle/kernel/memory.h" | ||||
| #include "core/hle/kernel/process.h" | ||||
| #include "core/hle/kernel/resource_limit.h" | ||||
| #include "core/hle/kernel/thread.h" | ||||
| @ -15,9 +14,7 @@ namespace Kernel { | ||||
| unsigned int Object::next_object_id; | ||||
| 
 | ||||
| /// Initialize the kernel
 | ||||
| void Init(u32 system_mode) { | ||||
|     Kernel::MemoryInit(system_mode); | ||||
| 
 | ||||
| void Init() { | ||||
|     Kernel::ResourceLimitsInit(); | ||||
|     Kernel::ThreadingInit(); | ||||
|     Kernel::TimersInit(); | ||||
| @ -37,7 +34,6 @@ void Shutdown() { | ||||
| 
 | ||||
|     Kernel::TimersShutdown(); | ||||
|     Kernel::ResourceLimitsShutdown(); | ||||
|     Kernel::MemoryShutdown(); | ||||
| } | ||||
| 
 | ||||
| } // namespace Kernel
 | ||||
|  | ||||
| @ -9,7 +9,7 @@ | ||||
| namespace Kernel { | ||||
| 
 | ||||
| /// Initialize the kernel with the specified system mode.
 | ||||
| void Init(u32 system_mode); | ||||
| void Init(); | ||||
| 
 | ||||
| /// Shutdown the kernel
 | ||||
| void Shutdown(); | ||||
|  | ||||
| @ -1,90 +0,0 @@ | ||||
| // Copyright 2014 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include <cinttypes> | ||||
| #include <memory> | ||||
| #include <utility> | ||||
| #include <vector> | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "core/hle/kernel/memory.h" | ||||
| #include "core/hle/kernel/process.h" | ||||
| #include "core/hle/kernel/vm_manager.h" | ||||
| #include "core/memory.h" | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| namespace Kernel { | ||||
| 
 | ||||
| MemoryRegionInfo memory_regions[3]; | ||||
| 
 | ||||
| /// Size of the APPLICATION, SYSTEM and BASE memory regions (respectively) for each system
 | ||||
| /// memory configuration type.
 | ||||
| static const u32 memory_region_sizes[8][3] = { | ||||
|     // Old 3DS layouts
 | ||||
|     {0x04000000, 0x02C00000, 0x01400000}, // 0
 | ||||
|     {/* This appears to be unused. */},   // 1
 | ||||
|     {0x06000000, 0x00C00000, 0x01400000}, // 2
 | ||||
|     {0x05000000, 0x01C00000, 0x01400000}, // 3
 | ||||
|     {0x04800000, 0x02400000, 0x01400000}, // 4
 | ||||
|     {0x02000000, 0x04C00000, 0x01400000}, // 5
 | ||||
| 
 | ||||
|     // New 3DS layouts
 | ||||
|     {0x07C00000, 0x06400000, 0x02000000}, // 6
 | ||||
|     {0x0B200000, 0x02E00000, 0x02000000}, // 7
 | ||||
| }; | ||||
| 
 | ||||
| void MemoryInit(u32 mem_type) { | ||||
|     // TODO(yuriks): On the n3DS, all o3DS configurations (<=5) are forced to 6 instead.
 | ||||
|     ASSERT_MSG(mem_type <= 5, "New 3DS memory configuration aren't supported yet!"); | ||||
|     ASSERT(mem_type != 1); | ||||
| 
 | ||||
|     // The kernel allocation regions (APPLICATION, SYSTEM and BASE) are laid out in sequence, with
 | ||||
|     // the sizes specified in the memory_region_sizes table.
 | ||||
|     VAddr base = 0; | ||||
|     for (int i = 0; i < 3; ++i) { | ||||
|         memory_regions[i].base = base; | ||||
|         memory_regions[i].size = memory_region_sizes[mem_type][i]; | ||||
|         memory_regions[i].used = 0; | ||||
|         memory_regions[i].linear_heap_memory = std::make_shared<std::vector<u8>>(); | ||||
|         // Reserve enough space for this region of FCRAM.
 | ||||
|         // We do not want this block of memory to be relocated when allocating from it.
 | ||||
|         memory_regions[i].linear_heap_memory->reserve(memory_regions[i].size); | ||||
| 
 | ||||
|         base += memory_regions[i].size; | ||||
|     } | ||||
| 
 | ||||
|     // We must've allocated the entire FCRAM by the end
 | ||||
|     ASSERT(base == Memory::FCRAM_SIZE); | ||||
| } | ||||
| 
 | ||||
| void MemoryShutdown() { | ||||
|     for (auto& region : memory_regions) { | ||||
|         region.base = 0; | ||||
|         region.size = 0; | ||||
|         region.used = 0; | ||||
|         region.linear_heap_memory = nullptr; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| MemoryRegionInfo* GetMemoryRegion(MemoryRegion region) { | ||||
|     switch (region) { | ||||
|     case MemoryRegion::APPLICATION: | ||||
|         return &memory_regions[0]; | ||||
|     case MemoryRegion::SYSTEM: | ||||
|         return &memory_regions[1]; | ||||
|     case MemoryRegion::BASE: | ||||
|         return &memory_regions[2]; | ||||
|     default: | ||||
|         UNREACHABLE(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping) {} | ||||
| 
 | ||||
| void MapSharedPages(VMManager& address_space) {} | ||||
| 
 | ||||
| } // namespace Kernel
 | ||||
| @ -1,34 +0,0 @@ | ||||
| // Copyright 2014 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <memory> | ||||
| #include <vector> | ||||
| 
 | ||||
| #include "common/common_types.h" | ||||
| 
 | ||||
| namespace Kernel { | ||||
| 
 | ||||
| class VMManager; | ||||
| enum class MemoryRegion : u16; | ||||
| struct AddressMapping; | ||||
| 
 | ||||
| struct MemoryRegionInfo { | ||||
|     u64 base; // Not an address, but offset from start of FCRAM
 | ||||
|     u64 size; | ||||
|     u64 used; | ||||
| 
 | ||||
|     std::shared_ptr<std::vector<u8>> linear_heap_memory; | ||||
| }; | ||||
| 
 | ||||
| void MemoryInit(u32 mem_type); | ||||
| void MemoryShutdown(); | ||||
| MemoryRegionInfo* GetMemoryRegion(MemoryRegion region); | ||||
| 
 | ||||
| void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping); | ||||
| void MapSharedPages(VMManager& address_space); | ||||
| 
 | ||||
| extern MemoryRegionInfo memory_regions[3]; | ||||
| } // namespace Kernel
 | ||||
| @ -8,7 +8,6 @@ | ||||
| #include "common/common_funcs.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "core/hle/kernel/errors.h" | ||||
| #include "core/hle/kernel/memory.h" | ||||
| #include "core/hle/kernel/process.h" | ||||
| #include "core/hle/kernel/resource_limit.h" | ||||
| #include "core/hle/kernel/thread.h" | ||||
| @ -125,14 +124,6 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) { | ||||
|                         std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size, | ||||
|                         MemoryState::Mapped) | ||||
|         .Unwrap(); | ||||
|     misc_memory_used += stack_size; | ||||
|     memory_region->used += stack_size; | ||||
| 
 | ||||
|     // Map special address mappings
 | ||||
|     MapSharedPages(vm_manager); | ||||
|     for (const auto& mapping : address_mappings) { | ||||
|         HandleSpecialMapping(vm_manager, mapping); | ||||
|     } | ||||
| 
 | ||||
|     vm_manager.LogLayout(); | ||||
|     status = ProcessStatus::Running; | ||||
| @ -141,17 +132,13 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) { | ||||
| } | ||||
| 
 | ||||
| void Process::LoadModule(SharedPtr<CodeSet> module_, VAddr base_addr) { | ||||
|     memory_region = GetMemoryRegion(flags.memory_region); | ||||
| 
 | ||||
|     auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions, | ||||
|                           MemoryState memory_state) { | ||||
|     const auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions, | ||||
|                                 MemoryState memory_state) { | ||||
|         auto vma = vm_manager | ||||
|                        .MapMemoryBlock(segment.addr + base_addr, module_->memory, segment.offset, | ||||
|                                        segment.size, memory_state) | ||||
|                        .Unwrap(); | ||||
|         vm_manager.Reprotect(vma, permissions); | ||||
|         misc_memory_used += segment.size; | ||||
|         memory_region->used += segment.size; | ||||
|     }; | ||||
| 
 | ||||
|     // Map CodeSet segments
 | ||||
| @ -160,20 +147,6 @@ void Process::LoadModule(SharedPtr<CodeSet> module_, VAddr base_addr) { | ||||
|     MapSegment(module_->data, VMAPermission::ReadWrite, MemoryState::CodeMutable); | ||||
| } | ||||
| 
 | ||||
| VAddr Process::GetLinearHeapAreaAddress() const { | ||||
|     // Starting from system version 8.0.0 a new linear heap layout is supported to allow usage of
 | ||||
|     // the extra RAM in the n3DS.
 | ||||
|     return kernel_version < 0x22C ? Memory::LINEAR_HEAP_VADDR : Memory::NEW_LINEAR_HEAP_VADDR; | ||||
| } | ||||
| 
 | ||||
| VAddr Process::GetLinearHeapBase() const { | ||||
|     return GetLinearHeapAreaAddress() + memory_region->base; | ||||
| } | ||||
| 
 | ||||
| VAddr Process::GetLinearHeapLimit() const { | ||||
|     return GetLinearHeapBase() + memory_region->size; | ||||
| } | ||||
| 
 | ||||
| ResultVal<VAddr> Process::HeapAllocate(VAddr target, u64 size, VMAPermission perms) { | ||||
|     if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END || | ||||
|         target + size < target) { | ||||
| @ -206,7 +179,6 @@ ResultVal<VAddr> Process::HeapAllocate(VAddr target, u64 size, VMAPermission per | ||||
|     vm_manager.Reprotect(vma, perms); | ||||
| 
 | ||||
|     heap_used = size; | ||||
|     memory_region->used += size; | ||||
| 
 | ||||
|     return MakeResult<VAddr>(heap_end - size); | ||||
| } | ||||
| @ -226,52 +198,6 @@ ResultCode Process::HeapFree(VAddr target, u32 size) { | ||||
|         return result; | ||||
| 
 | ||||
|     heap_used -= size; | ||||
|     memory_region->used -= size; | ||||
| 
 | ||||
|     return RESULT_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| ResultVal<VAddr> Process::LinearAllocate(VAddr target, u32 size, VMAPermission perms) { | ||||
|     UNIMPLEMENTED(); | ||||
|     return {}; | ||||
| } | ||||
| 
 | ||||
| ResultCode Process::LinearFree(VAddr target, u32 size) { | ||||
|     auto& linheap_memory = memory_region->linear_heap_memory; | ||||
| 
 | ||||
|     if (target < GetLinearHeapBase() || target + size > GetLinearHeapLimit() || | ||||
|         target + size < target) { | ||||
| 
 | ||||
|         return ERR_INVALID_ADDRESS; | ||||
|     } | ||||
| 
 | ||||
|     if (size == 0) { | ||||
|         return RESULT_SUCCESS; | ||||
|     } | ||||
| 
 | ||||
|     VAddr heap_end = GetLinearHeapBase() + (u32)linheap_memory->size(); | ||||
|     if (target + size > heap_end) { | ||||
|         return ERR_INVALID_ADDRESS_STATE; | ||||
|     } | ||||
| 
 | ||||
|     ResultCode result = vm_manager.UnmapRange(target, size); | ||||
|     if (result.IsError()) | ||||
|         return result; | ||||
| 
 | ||||
|     linear_heap_used -= size; | ||||
|     memory_region->used -= size; | ||||
| 
 | ||||
|     if (target + size == heap_end) { | ||||
|         // End of linear heap has been freed, so check what's the last allocated block in it and
 | ||||
|         // reduce the size.
 | ||||
|         auto vma = vm_manager.FindVMA(target); | ||||
|         ASSERT(vma != vm_manager.vma_map.end()); | ||||
|         ASSERT(vma->second.type == VMAType::Free); | ||||
|         VAddr new_end = vma->second.base; | ||||
|         if (new_end >= GetLinearHeapBase()) { | ||||
|             linheap_memory->resize(new_end - GetLinearHeapBase()); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return RESULT_SUCCESS; | ||||
| } | ||||
|  | ||||
| @ -53,7 +53,6 @@ union ProcessFlags { | ||||
| enum class ProcessStatus { Created, Running, Exited }; | ||||
| 
 | ||||
| class ResourceLimit; | ||||
| struct MemoryRegionInfo; | ||||
| 
 | ||||
| struct CodeSet final : public Object { | ||||
|     static SharedPtr<CodeSet> Create(std::string name); | ||||
| @ -163,12 +162,11 @@ public: | ||||
|     // This makes deallocation and reallocation of holes fast and keeps process memory contiguous
 | ||||
|     // in the emulator address space, allowing Memory::GetPointer to be reasonably safe.
 | ||||
|     std::shared_ptr<std::vector<u8>> heap_memory; | ||||
| 
 | ||||
|     // The left/right bounds of the address space covered by heap_memory.
 | ||||
|     VAddr heap_start = 0, heap_end = 0; | ||||
| 
 | ||||
|     u64 heap_used = 0, linear_heap_used = 0, misc_memory_used = 0; | ||||
| 
 | ||||
|     MemoryRegionInfo* memory_region = nullptr; | ||||
|     VAddr heap_start = 0; | ||||
|     VAddr heap_end = 0; | ||||
|     u64 heap_used = 0; | ||||
| 
 | ||||
|     /// The Thread Local Storage area is allocated as processes create threads,
 | ||||
|     /// each TLS area is 0x200 bytes, so one page (0x1000) is split up in 8 parts, and each part
 | ||||
| @ -179,16 +177,9 @@ public: | ||||
| 
 | ||||
|     std::string name; | ||||
| 
 | ||||
|     VAddr GetLinearHeapAreaAddress() const; | ||||
|     VAddr GetLinearHeapBase() const; | ||||
|     VAddr GetLinearHeapLimit() const; | ||||
| 
 | ||||
|     ResultVal<VAddr> HeapAllocate(VAddr target, u64 size, VMAPermission perms); | ||||
|     ResultCode HeapFree(VAddr target, u32 size); | ||||
| 
 | ||||
|     ResultVal<VAddr> LinearAllocate(VAddr target, u32 size, VMAPermission perms); | ||||
|     ResultCode LinearFree(VAddr target, u32 size); | ||||
| 
 | ||||
|     ResultCode MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size); | ||||
| 
 | ||||
|     ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size); | ||||
|  | ||||
| @ -8,7 +8,6 @@ | ||||
| #include "common/logging/log.h" | ||||
| #include "core/core.h" | ||||
| #include "core/hle/kernel/errors.h" | ||||
| #include "core/hle/kernel/memory.h" | ||||
| #include "core/hle/kernel/shared_memory.h" | ||||
| #include "core/memory.h" | ||||
| 
 | ||||
| @ -29,51 +28,22 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u | ||||
|     shared_memory->permissions = permissions; | ||||
|     shared_memory->other_permissions = other_permissions; | ||||
| 
 | ||||
|     if (address == 0) { | ||||
|         // We need to allocate a block from the Linear Heap ourselves.
 | ||||
|         // We'll manually allocate some memory from the linear heap in the specified region.
 | ||||
|         MemoryRegionInfo* memory_region = GetMemoryRegion(region); | ||||
|         auto& linheap_memory = memory_region->linear_heap_memory; | ||||
|     auto& vm_manager = shared_memory->owner_process->vm_manager; | ||||
| 
 | ||||
|         ASSERT_MSG(linheap_memory->size() + size <= memory_region->size, | ||||
|                    "Not enough space in region to allocate shared memory!"); | ||||
|     // The memory is already available and mapped in the owner process.
 | ||||
|     auto vma = vm_manager.FindVMA(address); | ||||
|     ASSERT_MSG(vma != vm_manager.vma_map.end(), "Invalid memory address"); | ||||
|     ASSERT_MSG(vma->second.backing_block, "Backing block doesn't exist for address"); | ||||
| 
 | ||||
|         shared_memory->backing_block = linheap_memory; | ||||
|         shared_memory->backing_block_offset = linheap_memory->size(); | ||||
|         // Allocate some memory from the end of the linear heap for this region.
 | ||||
|         linheap_memory->insert(linheap_memory->end(), size, 0); | ||||
|         memory_region->used += size; | ||||
| 
 | ||||
|         shared_memory->linear_heap_phys_address = | ||||
|             Memory::FCRAM_PADDR + memory_region->base + | ||||
|             static_cast<PAddr>(shared_memory->backing_block_offset); | ||||
| 
 | ||||
|         // Increase the amount of used linear heap memory for the owner process.
 | ||||
|         if (shared_memory->owner_process != nullptr) { | ||||
|             shared_memory->owner_process->linear_heap_used += size; | ||||
|         } | ||||
| 
 | ||||
|         // Refresh the address mappings for the current process.
 | ||||
|         if (Core::CurrentProcess() != nullptr) { | ||||
|             Core::CurrentProcess()->vm_manager.RefreshMemoryBlockMappings(linheap_memory.get()); | ||||
|         } | ||||
|     } else { | ||||
|         auto& vm_manager = shared_memory->owner_process->vm_manager; | ||||
|         // The memory is already available and mapped in the owner process.
 | ||||
|         auto vma = vm_manager.FindVMA(address); | ||||
|         ASSERT_MSG(vma != vm_manager.vma_map.end(), "Invalid memory address"); | ||||
|         ASSERT_MSG(vma->second.backing_block, "Backing block doesn't exist for address"); | ||||
| 
 | ||||
|         // The returned VMA might be a bigger one encompassing the desired address.
 | ||||
|         auto vma_offset = address - vma->first; | ||||
|         ASSERT_MSG(vma_offset + size <= vma->second.size, | ||||
|                    "Shared memory exceeds bounds of mapped block"); | ||||
| 
 | ||||
|         shared_memory->backing_block = vma->second.backing_block; | ||||
|         shared_memory->backing_block_offset = vma->second.offset + vma_offset; | ||||
|     } | ||||
|     // The returned VMA might be a bigger one encompassing the desired address.
 | ||||
|     auto vma_offset = address - vma->first; | ||||
|     ASSERT_MSG(vma_offset + size <= vma->second.size, | ||||
|                "Shared memory exceeds bounds of mapped block"); | ||||
| 
 | ||||
|     shared_memory->backing_block = vma->second.backing_block; | ||||
|     shared_memory->backing_block_offset = vma->second.offset + vma_offset; | ||||
|     shared_memory->base_address = address; | ||||
| 
 | ||||
|     return shared_memory; | ||||
| } | ||||
| 
 | ||||
| @ -124,11 +94,6 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi | ||||
| 
 | ||||
|     VAddr target_address = address; | ||||
| 
 | ||||
|     if (base_address == 0 && target_address == 0) { | ||||
|         // Calculate the address at which to map the memory block.
 | ||||
|         target_address = Memory::PhysicalToVirtualAddress(linear_heap_phys_address).value(); | ||||
|     } | ||||
| 
 | ||||
|     // Map the memory block into the target process
 | ||||
|     auto result = target_process->vm_manager.MapMemoryBlock( | ||||
|         target_address, backing_block, backing_block_offset, size, MemoryState::Shared); | ||||
|  | ||||
| @ -111,9 +111,6 @@ public: | ||||
|     SharedPtr<Process> owner_process; | ||||
|     /// Address of shared memory block in the owner process if specified.
 | ||||
|     VAddr base_address; | ||||
|     /// Physical address of the shared memory block in the linear heap if no address was specified
 | ||||
|     /// during creation.
 | ||||
|     PAddr linear_heap_phys_address; | ||||
|     /// Backing memory for this shared memory block.
 | ||||
|     std::shared_ptr<std::vector<u8>> backing_block; | ||||
|     /// Offset into the backing block for this shared memory.
 | ||||
|  | ||||
| @ -20,7 +20,6 @@ | ||||
| #include "core/core_timing_util.h" | ||||
| #include "core/hle/kernel/errors.h" | ||||
| #include "core/hle/kernel/handle_table.h" | ||||
| #include "core/hle/kernel/memory.h" | ||||
| #include "core/hle/kernel/object.h" | ||||
| #include "core/hle/kernel/process.h" | ||||
| #include "core/hle/kernel/thread.h" | ||||
| @ -81,8 +80,8 @@ void Thread::Stop() { | ||||
|     wait_objects.clear(); | ||||
| 
 | ||||
|     // Mark the TLS slot in the thread's page as free.
 | ||||
|     u64 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE; | ||||
|     u64 tls_slot = | ||||
|     const u64 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE; | ||||
|     const u64 tls_slot = | ||||
|         ((tls_address - Memory::TLS_AREA_VADDR) % Memory::PAGE_SIZE) / Memory::TLS_ENTRY_SIZE; | ||||
|     Core::CurrentProcess()->tls_slots[tls_page].reset(tls_slot); | ||||
| } | ||||
| @ -336,38 +335,10 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, | ||||
|     auto& tls_slots = owner_process->tls_slots; | ||||
| 
 | ||||
|     auto [available_page, available_slot, needs_allocation] = GetFreeThreadLocalSlot(tls_slots); | ||||
| 
 | ||||
|     if (needs_allocation) { | ||||
|         // There are no already-allocated pages with free slots, lets allocate a new one.
 | ||||
|         // TLS pages are allocated from the BASE region in the linear heap.
 | ||||
|         MemoryRegionInfo* memory_region = GetMemoryRegion(MemoryRegion::BASE); | ||||
|         auto& linheap_memory = memory_region->linear_heap_memory; | ||||
| 
 | ||||
|         if (linheap_memory->size() + Memory::PAGE_SIZE > memory_region->size) { | ||||
|             LOG_ERROR(Kernel_SVC, | ||||
|                       "Not enough space in region to allocate a new TLS page for thread"); | ||||
|             return ERR_OUT_OF_MEMORY; | ||||
|         } | ||||
| 
 | ||||
|         size_t offset = linheap_memory->size(); | ||||
| 
 | ||||
|         // Allocate some memory from the end of the linear heap for this region.
 | ||||
|         linheap_memory->insert(linheap_memory->end(), Memory::PAGE_SIZE, 0); | ||||
|         memory_region->used += Memory::PAGE_SIZE; | ||||
|         owner_process->linear_heap_used += Memory::PAGE_SIZE; | ||||
| 
 | ||||
|         tls_slots.emplace_back(0); // The page is completely available at the start
 | ||||
|         available_page = tls_slots.size() - 1; | ||||
|         available_slot = 0; // Use the first slot in the new page
 | ||||
| 
 | ||||
|         auto& vm_manager = owner_process->vm_manager; | ||||
|         vm_manager.RefreshMemoryBlockMappings(linheap_memory.get()); | ||||
| 
 | ||||
|         // Map the page to the current process' address space.
 | ||||
|         // TODO(Subv): Find the correct MemoryState for this region.
 | ||||
|         vm_manager.MapMemoryBlock(Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE, | ||||
|                                   linheap_memory, offset, Memory::PAGE_SIZE, | ||||
|                                   MemoryState::ThreadLocal); | ||||
|     } | ||||
| 
 | ||||
|     // Mark the slot as used
 | ||||
|  | ||||
| @ -14,7 +14,6 @@ | ||||
| #include "common/swap.h" | ||||
| #include "core/arm/arm_interface.h" | ||||
| #include "core/core.h" | ||||
| #include "core/hle/kernel/memory.h" | ||||
| #include "core/hle/kernel/process.h" | ||||
| #include "core/hle/lock.h" | ||||
| #include "core/memory.h" | ||||
| @ -24,8 +23,6 @@ | ||||
| 
 | ||||
| namespace Memory { | ||||
| 
 | ||||
| static std::array<u8, Memory::VRAM_SIZE> vram; | ||||
| 
 | ||||
| static PageTable* current_page_table = nullptr; | ||||
| 
 | ||||
| void SetCurrentPageTable(PageTable* page_table) { | ||||
| @ -242,10 +239,6 @@ bool IsKernelVirtualAddress(const VAddr vaddr) { | ||||
|     return KERNEL_REGION_VADDR <= vaddr && vaddr < KERNEL_REGION_END; | ||||
| } | ||||
| 
 | ||||
| bool IsValidPhysicalAddress(const PAddr paddr) { | ||||
|     return GetPhysicalPointer(paddr) != nullptr; | ||||
| } | ||||
| 
 | ||||
| u8* GetPointer(const VAddr vaddr) { | ||||
|     u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; | ||||
|     if (page_pointer) { | ||||
| @ -274,61 +267,6 @@ std::string ReadCString(VAddr vaddr, std::size_t max_length) { | ||||
|     return string; | ||||
| } | ||||
| 
 | ||||
| u8* GetPhysicalPointer(PAddr address) { | ||||
|     struct MemoryArea { | ||||
|         PAddr paddr_base; | ||||
|         u32 size; | ||||
|     }; | ||||
| 
 | ||||
|     static constexpr MemoryArea memory_areas[] = { | ||||
|         {VRAM_PADDR, VRAM_SIZE}, | ||||
|         {IO_AREA_PADDR, IO_AREA_SIZE}, | ||||
|         {DSP_RAM_PADDR, DSP_RAM_SIZE}, | ||||
|         {FCRAM_PADDR, FCRAM_N3DS_SIZE}, | ||||
|     }; | ||||
| 
 | ||||
|     const auto area = | ||||
|         std::find_if(std::begin(memory_areas), std::end(memory_areas), [&](const auto& area) { | ||||
|             return address >= area.paddr_base && address < area.paddr_base + area.size; | ||||
|         }); | ||||
| 
 | ||||
|     if (area == std::end(memory_areas)) { | ||||
|         LOG_ERROR(HW_Memory, "Unknown GetPhysicalPointer @ 0x{:016X}", address); | ||||
|         return nullptr; | ||||
|     } | ||||
| 
 | ||||
|     if (area->paddr_base == IO_AREA_PADDR) { | ||||
|         LOG_ERROR(HW_Memory, "MMIO mappings are not supported yet. phys_addr={:016X}", address); | ||||
|         return nullptr; | ||||
|     } | ||||
| 
 | ||||
|     u64 offset_into_region = address - area->paddr_base; | ||||
| 
 | ||||
|     u8* target_pointer = nullptr; | ||||
|     switch (area->paddr_base) { | ||||
|     case VRAM_PADDR: | ||||
|         target_pointer = vram.data() + offset_into_region; | ||||
|         break; | ||||
|     case DSP_RAM_PADDR: | ||||
|         break; | ||||
|     case FCRAM_PADDR: | ||||
|         for (const auto& region : Kernel::memory_regions) { | ||||
|             if (offset_into_region >= region.base && | ||||
|                 offset_into_region < region.base + region.size) { | ||||
|                 target_pointer = | ||||
|                     region.linear_heap_memory->data() + offset_into_region - region.base; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|         ASSERT_MSG(target_pointer != nullptr, "Invalid FCRAM address"); | ||||
|         break; | ||||
|     default: | ||||
|         UNREACHABLE(); | ||||
|     } | ||||
| 
 | ||||
|     return target_pointer; | ||||
| } | ||||
| 
 | ||||
| void RasterizerMarkRegionCached(Tegra::GPUVAddr gpu_addr, u64 size, bool cached) { | ||||
|     if (gpu_addr == 0) { | ||||
|         return; | ||||
| @ -666,48 +604,4 @@ void CopyBlock(VAddr dest_addr, VAddr src_addr, size_t size) { | ||||
|     CopyBlock(*Core::CurrentProcess(), dest_addr, src_addr, size); | ||||
| } | ||||
| 
 | ||||
| boost::optional<PAddr> TryVirtualToPhysicalAddress(const VAddr addr) { | ||||
|     if (addr == 0) { | ||||
|         return 0; | ||||
|     } else if (addr >= VRAM_VADDR && addr < VRAM_VADDR_END) { | ||||
|         return addr - VRAM_VADDR + VRAM_PADDR; | ||||
|     } else if (addr >= LINEAR_HEAP_VADDR && addr < LINEAR_HEAP_VADDR_END) { | ||||
|         return addr - LINEAR_HEAP_VADDR + FCRAM_PADDR; | ||||
|     } else if (addr >= NEW_LINEAR_HEAP_VADDR && addr < NEW_LINEAR_HEAP_VADDR_END) { | ||||
|         return addr - NEW_LINEAR_HEAP_VADDR + FCRAM_PADDR; | ||||
|     } else if (addr >= DSP_RAM_VADDR && addr < DSP_RAM_VADDR_END) { | ||||
|         return addr - DSP_RAM_VADDR + DSP_RAM_PADDR; | ||||
|     } else if (addr >= IO_AREA_VADDR && addr < IO_AREA_VADDR_END) { | ||||
|         return addr - IO_AREA_VADDR + IO_AREA_PADDR; | ||||
|     } | ||||
| 
 | ||||
|     return boost::none; | ||||
| } | ||||
| 
 | ||||
| PAddr VirtualToPhysicalAddress(const VAddr addr) { | ||||
|     auto paddr = TryVirtualToPhysicalAddress(addr); | ||||
|     if (!paddr) { | ||||
|         LOG_ERROR(HW_Memory, "Unknown virtual address @ 0x{:016X}", addr); | ||||
|         // To help with debugging, set bit on address so that it's obviously invalid.
 | ||||
|         return addr | 0x80000000; | ||||
|     } | ||||
|     return *paddr; | ||||
| } | ||||
| 
 | ||||
| boost::optional<VAddr> PhysicalToVirtualAddress(const PAddr addr) { | ||||
|     if (addr == 0) { | ||||
|         return 0; | ||||
|     } else if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) { | ||||
|         return addr - VRAM_PADDR + VRAM_VADDR; | ||||
|     } else if (addr >= FCRAM_PADDR && addr < FCRAM_PADDR_END) { | ||||
|         return addr - FCRAM_PADDR + Core::CurrentProcess()->GetLinearHeapAreaAddress(); | ||||
|     } else if (addr >= DSP_RAM_PADDR && addr < DSP_RAM_PADDR_END) { | ||||
|         return addr - DSP_RAM_PADDR + DSP_RAM_VADDR; | ||||
|     } else if (addr >= IO_AREA_PADDR && addr < IO_AREA_PADDR_END) { | ||||
|         return addr - IO_AREA_PADDR + IO_AREA_VADDR; | ||||
|     } | ||||
| 
 | ||||
|     return boost::none; | ||||
| } | ||||
| 
 | ||||
| } // namespace Memory
 | ||||
|  | ||||
| @ -6,12 +6,9 @@ | ||||
| 
 | ||||
| #include <array> | ||||
| #include <cstddef> | ||||
| #include <map> | ||||
| #include <string> | ||||
| #include <tuple> | ||||
| #include <vector> | ||||
| #include <boost/icl/interval_map.hpp> | ||||
| #include <boost/optional.hpp> | ||||
| #include "common/common_types.h" | ||||
| #include "core/memory_hook.h" | ||||
| #include "video_core/memory_manager.h" | ||||
| @ -85,40 +82,6 @@ struct PageTable { | ||||
|     std::array<PageType, PAGE_TABLE_NUM_ENTRIES> attributes; | ||||
| }; | ||||
| 
 | ||||
| /// Physical memory regions as seen from the ARM11
 | ||||
| enum : PAddr { | ||||
|     /// IO register area
 | ||||
|     IO_AREA_PADDR = 0x10100000, | ||||
|     IO_AREA_SIZE = 0x01000000, ///< IO area size (16MB)
 | ||||
|     IO_AREA_PADDR_END = IO_AREA_PADDR + IO_AREA_SIZE, | ||||
| 
 | ||||
|     /// MPCore internal memory region
 | ||||
|     MPCORE_RAM_PADDR = 0x17E00000, | ||||
|     MPCORE_RAM_SIZE = 0x00002000, ///< MPCore internal memory size (8KB)
 | ||||
|     MPCORE_RAM_PADDR_END = MPCORE_RAM_PADDR + MPCORE_RAM_SIZE, | ||||
| 
 | ||||
|     /// Video memory
 | ||||
|     VRAM_PADDR = 0x18000000, | ||||
|     VRAM_SIZE = 0x00600000, ///< VRAM size (6MB)
 | ||||
|     VRAM_PADDR_END = VRAM_PADDR + VRAM_SIZE, | ||||
| 
 | ||||
|     /// DSP memory
 | ||||
|     DSP_RAM_PADDR = 0x1FF00000, | ||||
|     DSP_RAM_SIZE = 0x00080000, ///< DSP memory size (512KB)
 | ||||
|     DSP_RAM_PADDR_END = DSP_RAM_PADDR + DSP_RAM_SIZE, | ||||
| 
 | ||||
|     /// AXI WRAM
 | ||||
|     AXI_WRAM_PADDR = 0x1FF80000, | ||||
|     AXI_WRAM_SIZE = 0x00080000, ///< AXI WRAM size (512KB)
 | ||||
|     AXI_WRAM_PADDR_END = AXI_WRAM_PADDR + AXI_WRAM_SIZE, | ||||
| 
 | ||||
|     /// Main FCRAM
 | ||||
|     FCRAM_PADDR = 0x20000000, | ||||
|     FCRAM_SIZE = 0x08000000,      ///< FCRAM size on the Old 3DS (128MB)
 | ||||
|     FCRAM_N3DS_SIZE = 0x10000000, ///< FCRAM size on the New 3DS (256MB)
 | ||||
|     FCRAM_PADDR_END = FCRAM_PADDR + FCRAM_SIZE, | ||||
| }; | ||||
| 
 | ||||
| /// Virtual user-space memory regions
 | ||||
| enum : VAddr { | ||||
|     /// Where the application text, data and bss reside.
 | ||||
| @ -126,24 +89,6 @@ enum : VAddr { | ||||
|     PROCESS_IMAGE_MAX_SIZE = 0x08000000, | ||||
|     PROCESS_IMAGE_VADDR_END = PROCESS_IMAGE_VADDR + PROCESS_IMAGE_MAX_SIZE, | ||||
| 
 | ||||
|     /// Maps 1:1 to an offset in FCRAM. Used for HW allocations that need to be linear in physical
 | ||||
|     /// memory.
 | ||||
|     LINEAR_HEAP_VADDR = 0x14000000, | ||||
|     LINEAR_HEAP_SIZE = 0x08000000, | ||||
|     LINEAR_HEAP_VADDR_END = LINEAR_HEAP_VADDR + LINEAR_HEAP_SIZE, | ||||
| 
 | ||||
|     /// Maps 1:1 to the IO register area.
 | ||||
|     IO_AREA_VADDR = 0x1EC00000, | ||||
|     IO_AREA_VADDR_END = IO_AREA_VADDR + IO_AREA_SIZE, | ||||
| 
 | ||||
|     /// Maps 1:1 to VRAM.
 | ||||
|     VRAM_VADDR = 0x1F000000, | ||||
|     VRAM_VADDR_END = VRAM_VADDR + VRAM_SIZE, | ||||
| 
 | ||||
|     /// Maps 1:1 to DSP memory.
 | ||||
|     DSP_RAM_VADDR = 0x1FF00000, | ||||
|     DSP_RAM_VADDR_END = DSP_RAM_VADDR + DSP_RAM_SIZE, | ||||
| 
 | ||||
|     /// Read-only page containing kernel and system configuration values.
 | ||||
|     CONFIG_MEMORY_VADDR = 0x1FF80000, | ||||
|     CONFIG_MEMORY_SIZE = 0x00001000, | ||||
| @ -154,13 +99,8 @@ enum : VAddr { | ||||
|     SHARED_PAGE_SIZE = 0x00001000, | ||||
|     SHARED_PAGE_VADDR_END = SHARED_PAGE_VADDR + SHARED_PAGE_SIZE, | ||||
| 
 | ||||
|     /// Equivalent to LINEAR_HEAP_VADDR, but expanded to cover the extra memory in the New 3DS.
 | ||||
|     NEW_LINEAR_HEAP_VADDR = 0x30000000, | ||||
|     NEW_LINEAR_HEAP_SIZE = 0x10000000, | ||||
|     NEW_LINEAR_HEAP_VADDR_END = NEW_LINEAR_HEAP_VADDR + NEW_LINEAR_HEAP_SIZE, | ||||
| 
 | ||||
|     /// Area where TLS (Thread-Local Storage) buffers are allocated.
 | ||||
|     TLS_AREA_VADDR = NEW_LINEAR_HEAP_VADDR_END, | ||||
|     TLS_AREA_VADDR = 0x40000000, | ||||
|     TLS_ENTRY_SIZE = 0x200, | ||||
|     TLS_AREA_SIZE = 0x10000000, | ||||
|     TLS_AREA_VADDR_END = TLS_AREA_VADDR + TLS_AREA_SIZE, | ||||
| @ -205,8 +145,6 @@ bool IsValidVirtualAddress(const VAddr addr); | ||||
| /// Determines if the given VAddr is a kernel address
 | ||||
| bool IsKernelVirtualAddress(const VAddr addr); | ||||
| 
 | ||||
| bool IsValidPhysicalAddress(const PAddr addr); | ||||
| 
 | ||||
| u8 Read8(VAddr addr); | ||||
| u16 Read16(VAddr addr); | ||||
| u32 Read32(VAddr addr); | ||||
| @ -230,30 +168,6 @@ u8* GetPointer(VAddr virtual_address); | ||||
| 
 | ||||
| std::string ReadCString(VAddr virtual_address, std::size_t max_length); | ||||
| 
 | ||||
| /**
 | ||||
|  * Converts a virtual address inside a region with 1:1 mapping to physical memory to a physical | ||||
|  * address. This should be used by services to translate addresses for use by the hardware. | ||||
|  */ | ||||
| boost::optional<PAddr> TryVirtualToPhysicalAddress(VAddr addr); | ||||
| 
 | ||||
| /**
 | ||||
|  * Converts a virtual address inside a region with 1:1 mapping to physical memory to a physical | ||||
|  * address. This should be used by services to translate addresses for use by the hardware. | ||||
|  * | ||||
|  * @deprecated Use TryVirtualToPhysicalAddress(), which reports failure. | ||||
|  */ | ||||
| PAddr VirtualToPhysicalAddress(VAddr addr); | ||||
| 
 | ||||
| /**
 | ||||
|  * Undoes a mapping performed by VirtualToPhysicalAddress(). | ||||
|  */ | ||||
| boost::optional<VAddr> PhysicalToVirtualAddress(PAddr addr); | ||||
| 
 | ||||
| /**
 | ||||
|  * Gets a pointer to the memory region beginning at the specified physical address. | ||||
|  */ | ||||
| u8* GetPhysicalPointer(PAddr address); | ||||
| 
 | ||||
| enum class FlushMode { | ||||
|     /// Write back modified surfaces to RAM
 | ||||
|     Flush, | ||||
|  | ||||
| @ -3,7 +3,6 @@ add_executable(tests | ||||
|     core/arm/arm_test_common.cpp | ||||
|     core/arm/arm_test_common.h | ||||
|     core/core_timing.cpp | ||||
|     core/memory/memory.cpp | ||||
|     glad.cpp | ||||
|     tests.cpp | ||||
| ) | ||||
|  | ||||
| @ -1,56 +0,0 @@ | ||||
| // Copyright 2017 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <catch.hpp> | ||||
| #include "core/hle/kernel/memory.h" | ||||
| #include "core/hle/kernel/process.h" | ||||
| #include "core/memory.h" | ||||
| 
 | ||||
| TEST_CASE("Memory::IsValidVirtualAddress", "[core][memory][!hide]") { | ||||
|     SECTION("these regions should not be mapped on an empty process") { | ||||
|         auto process = Kernel::Process::Create(""); | ||||
|         CHECK(Memory::IsValidVirtualAddress(*process, Memory::PROCESS_IMAGE_VADDR) == false); | ||||
|         CHECK(Memory::IsValidVirtualAddress(*process, Memory::HEAP_VADDR) == false); | ||||
|         CHECK(Memory::IsValidVirtualAddress(*process, Memory::LINEAR_HEAP_VADDR) == false); | ||||
|         CHECK(Memory::IsValidVirtualAddress(*process, Memory::VRAM_VADDR) == false); | ||||
|         CHECK(Memory::IsValidVirtualAddress(*process, Memory::CONFIG_MEMORY_VADDR) == false); | ||||
|         CHECK(Memory::IsValidVirtualAddress(*process, Memory::SHARED_PAGE_VADDR) == false); | ||||
|         CHECK(Memory::IsValidVirtualAddress(*process, Memory::TLS_AREA_VADDR) == false); | ||||
|     } | ||||
| 
 | ||||
|     SECTION("CONFIG_MEMORY_VADDR and SHARED_PAGE_VADDR should be valid after mapping them") { | ||||
|         auto process = Kernel::Process::Create(""); | ||||
|         Kernel::MapSharedPages(process->vm_manager); | ||||
|         CHECK(Memory::IsValidVirtualAddress(*process, Memory::CONFIG_MEMORY_VADDR) == true); | ||||
|         CHECK(Memory::IsValidVirtualAddress(*process, Memory::SHARED_PAGE_VADDR) == true); | ||||
|     } | ||||
| 
 | ||||
|     SECTION("special regions should be valid after mapping them") { | ||||
|         auto process = Kernel::Process::Create(""); | ||||
|         SECTION("VRAM") { | ||||
|             Kernel::HandleSpecialMapping(process->vm_manager, | ||||
|                                          {Memory::VRAM_VADDR, Memory::VRAM_SIZE, false, false}); | ||||
|             CHECK(Memory::IsValidVirtualAddress(*process, Memory::VRAM_VADDR) == true); | ||||
|         } | ||||
| 
 | ||||
|         SECTION("IO (Not yet implemented)") { | ||||
|             Kernel::HandleSpecialMapping( | ||||
|                 process->vm_manager, {Memory::IO_AREA_VADDR, Memory::IO_AREA_SIZE, false, false}); | ||||
|             CHECK_FALSE(Memory::IsValidVirtualAddress(*process, Memory::IO_AREA_VADDR) == true); | ||||
|         } | ||||
| 
 | ||||
|         SECTION("DSP") { | ||||
|             Kernel::HandleSpecialMapping( | ||||
|                 process->vm_manager, {Memory::DSP_RAM_VADDR, Memory::DSP_RAM_SIZE, false, false}); | ||||
|             CHECK(Memory::IsValidVirtualAddress(*process, Memory::DSP_RAM_VADDR) == true); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     SECTION("Unmapping a VAddr should make it invalid") { | ||||
|         auto process = Kernel::Process::Create(""); | ||||
|         Kernel::MapSharedPages(process->vm_manager); | ||||
|         process->vm_manager.UnmapRange(Memory::CONFIG_MEMORY_VADDR, Memory::CONFIG_MEMORY_SIZE); | ||||
|         CHECK(Memory::IsValidVirtualAddress(*process, Memory::CONFIG_MEMORY_VADDR) == false); | ||||
|     } | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 bunnei
						bunnei