diff options
| author | 2017-10-19 23:00:46 -0400 | |
|---|---|---|
| committer | 2017-10-19 23:00:46 -0400 | |
| commit | dcd6bb82f7a5bc1daaa8570f710ffb062fa4c596 (patch) | |
| tree | 95f6a5d5f816a9c8a6367889dd4d551deb625eb0 /src/core | |
| parent | lm: Implement lm::Initialize and Logger::log. (diff) | |
| download | yuzu-dcd6bb82f7a5bc1daaa8570f710ffb062fa4c596.tar.gz yuzu-dcd6bb82f7a5bc1daaa8570f710ffb062fa4c596.tar.xz yuzu-dcd6bb82f7a5bc1daaa8570f710ffb062fa4c596.zip | |
hle: Fix QueryMemory response for MemoryInfo.
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/hle/function_wrappers.h | 18 | ||||
| -rw-r--r-- | src/core/hle/kernel/memory.cpp | 66 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.cpp | 42 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/vm_manager.h | 19 | ||||
| -rw-r--r-- | src/core/hle/svc.cpp | 28 | ||||
| -rw-r--r-- | src/core/hle/svc.h | 5 |
7 files changed, 31 insertions, 149 deletions
diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index 31fda6db3..3e886fdba 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h | |||
| @@ -133,25 +133,13 @@ void Wrap() { | |||
| 133 | 133 | ||
| 134 | Memory::Write64(PARAM(0), memory_info.base_address); | 134 | Memory::Write64(PARAM(0), memory_info.base_address); |
| 135 | Memory::Write64(PARAM(0) + 8, memory_info.size); | 135 | Memory::Write64(PARAM(0) + 8, memory_info.size); |
| 136 | Memory::Write64(PARAM(0) + 16, memory_info.permission); | 136 | Memory::Write32(PARAM(0) + 16, memory_info.type); |
| 137 | Memory::Write64(PARAM(0) + 24, memory_info.state); | 137 | Memory::Write32(PARAM(0) + 20, memory_info.attributes); |
| 138 | Memory::Write32(PARAM(0) + 24, memory_info.permission); | ||
| 138 | 139 | ||
| 139 | FuncReturn(retval); | 140 | FuncReturn(retval); |
| 140 | } | 141 | } |
| 141 | 142 | ||
| 142 | template <ResultCode func(MemoryInfo*, PageInfo*, Kernel::Handle, u32)> | ||
| 143 | void Wrap() { | ||
| 144 | MemoryInfo memory_info = {}; | ||
| 145 | PageInfo page_info = {}; | ||
| 146 | u32 retval = func(&memory_info, &page_info, PARAM(2), PARAM(3)).raw; | ||
| 147 | Core::CPU().SetReg(1, memory_info.base_address); | ||
| 148 | Core::CPU().SetReg(2, memory_info.size); | ||
| 149 | Core::CPU().SetReg(3, memory_info.permission); | ||
| 150 | Core::CPU().SetReg(4, memory_info.state); | ||
| 151 | Core::CPU().SetReg(5, page_info.flags); | ||
| 152 | FuncReturn(retval); | ||
| 153 | } | ||
| 154 | |||
| 155 | template <ResultCode func(s32*, u32)> | 143 | template <ResultCode func(s32*, u32)> |
| 156 | void Wrap() { | 144 | void Wrap() { |
| 157 | s32 param_1 = 0; | 145 | s32 param_1 = 0; |
diff --git a/src/core/hle/kernel/memory.cpp b/src/core/hle/kernel/memory.cpp index 7f27e9655..95d3a6bf6 100644 --- a/src/core/hle/kernel/memory.cpp +++ b/src/core/hle/kernel/memory.cpp | |||
| @@ -96,75 +96,9 @@ MemoryRegionInfo* GetMemoryRegion(MemoryRegion region) { | |||
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping) { | 98 | void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping) { |
| 99 | using namespace Memory; | ||
| 100 | |||
| 101 | struct MemoryArea { | ||
| 102 | VAddr vaddr_base; | ||
| 103 | PAddr paddr_base; | ||
| 104 | u32 size; | ||
| 105 | }; | ||
| 106 | |||
| 107 | // The order of entries in this array is important. The VRAM and IO VAddr ranges overlap, and | ||
| 108 | // VRAM must be tried first. | ||
| 109 | static constexpr MemoryArea memory_areas[] = { | ||
| 110 | {VRAM_VADDR, VRAM_PADDR, VRAM_SIZE}, | ||
| 111 | {IO_AREA_VADDR, IO_AREA_PADDR, IO_AREA_SIZE}, | ||
| 112 | {DSP_RAM_VADDR, DSP_RAM_PADDR, DSP_RAM_SIZE}, | ||
| 113 | {N3DS_EXTRA_RAM_VADDR, N3DS_EXTRA_RAM_PADDR, N3DS_EXTRA_RAM_SIZE - 0x20000}, | ||
| 114 | }; | ||
| 115 | |||
| 116 | VAddr mapping_limit = mapping.address + mapping.size; | ||
| 117 | if (mapping_limit < mapping.address) { | ||
| 118 | LOG_CRITICAL(Loader, "Mapping size overflowed: address=0x%08" PRIX32 " size=0x%" PRIX32, | ||
| 119 | mapping.address, mapping.size); | ||
| 120 | return; | ||
| 121 | } | ||
| 122 | |||
| 123 | auto area = | ||
| 124 | std::find_if(std::begin(memory_areas), std::end(memory_areas), [&](const auto& area) { | ||
| 125 | return mapping.address >= area.vaddr_base && | ||
| 126 | mapping_limit <= area.vaddr_base + area.size; | ||
| 127 | }); | ||
| 128 | if (area == std::end(memory_areas)) { | ||
| 129 | LOG_ERROR(Loader, "Unhandled special mapping: address=0x%08" PRIX32 " size=0x%" PRIX32 | ||
| 130 | " read_only=%d unk_flag=%d", | ||
| 131 | mapping.address, mapping.size, mapping.read_only, mapping.unk_flag); | ||
| 132 | return; | ||
| 133 | } | ||
| 134 | |||
| 135 | u32 offset_into_region = mapping.address - area->vaddr_base; | ||
| 136 | if (area->paddr_base == IO_AREA_PADDR) { | ||
| 137 | LOG_ERROR(Loader, "MMIO mappings are not supported yet. phys_addr=0x%08" PRIX32, | ||
| 138 | area->paddr_base + offset_into_region); | ||
| 139 | return; | ||
| 140 | } | ||
| 141 | |||
| 142 | u8* target_pointer = Memory::GetPhysicalPointer(area->paddr_base + offset_into_region); | ||
| 143 | |||
| 144 | // TODO(yuriks): This flag seems to have some other effect, but it's unknown what | ||
| 145 | MemoryState memory_state = mapping.unk_flag ? MemoryState::Static : MemoryState::IO; | ||
| 146 | |||
| 147 | auto vma = | ||
| 148 | address_space.MapBackingMemory(mapping.address, target_pointer, mapping.size, memory_state) | ||
| 149 | .Unwrap(); | ||
| 150 | address_space.Reprotect(vma, | ||
| 151 | mapping.read_only ? VMAPermission::Read : VMAPermission::ReadWrite); | ||
| 152 | } | 99 | } |
| 153 | 100 | ||
| 154 | void MapSharedPages(VMManager& address_space) { | 101 | void MapSharedPages(VMManager& address_space) { |
| 155 | auto cfg_mem_vma = address_space | ||
| 156 | .MapBackingMemory(Memory::CONFIG_MEMORY_VADDR, | ||
| 157 | reinterpret_cast<u8*>(&ConfigMem::config_mem), | ||
| 158 | Memory::CONFIG_MEMORY_SIZE, MemoryState::Shared) | ||
| 159 | .Unwrap(); | ||
| 160 | address_space.Reprotect(cfg_mem_vma, VMAPermission::Read); | ||
| 161 | |||
| 162 | auto shared_page_vma = address_space | ||
| 163 | .MapBackingMemory(Memory::SHARED_PAGE_VADDR, | ||
| 164 | reinterpret_cast<u8*>(&SharedPage::shared_page), | ||
| 165 | Memory::SHARED_PAGE_SIZE, MemoryState::Shared) | ||
| 166 | .Unwrap(); | ||
| 167 | address_space.Reprotect(shared_page_vma, VMAPermission::Read); | ||
| 168 | } | 102 | } |
| 169 | 103 | ||
| 170 | } // namespace Kernel | 104 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 9e145866f..98c5b0905 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp | |||
| @@ -117,7 +117,7 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) { | |||
| 117 | vm_manager | 117 | vm_manager |
| 118 | .MapMemoryBlock(Memory::HEAP_VADDR_END - stack_size, | 118 | .MapMemoryBlock(Memory::HEAP_VADDR_END - stack_size, |
| 119 | std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size, | 119 | std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size, |
| 120 | MemoryState::Locked) | 120 | MemoryState::Heap) |
| 121 | .Unwrap(); | 121 | .Unwrap(); |
| 122 | misc_memory_used += stack_size; | 122 | misc_memory_used += stack_size; |
| 123 | memory_region->used += stack_size; | 123 | memory_region->used += stack_size; |
| @@ -148,7 +148,7 @@ void Process::LoadModule(SharedPtr<CodeSet> module_, VAddr base_addr) { | |||
| 148 | }; | 148 | }; |
| 149 | 149 | ||
| 150 | // Map CodeSet segments | 150 | // Map CodeSet segments |
| 151 | MapSegment(module_->code, VMAPermission::ReadWrite, MemoryState::Private); | 151 | MapSegment(module_->code, VMAPermission::ReadExecute, MemoryState::Code); |
| 152 | MapSegment(module_->rodata, VMAPermission::Read, MemoryState::Static); | 152 | MapSegment(module_->rodata, VMAPermission::Read, MemoryState::Static); |
| 153 | MapSegment(module_->data, VMAPermission::ReadWrite, MemoryState::Static); | 153 | MapSegment(module_->data, VMAPermission::ReadWrite, MemoryState::Static); |
| 154 | } | 154 | } |
| @@ -193,7 +193,7 @@ ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission per | |||
| 193 | ASSERT(heap_end - heap_start == heap_memory->size()); | 193 | ASSERT(heap_end - heap_start == heap_memory->size()); |
| 194 | 194 | ||
| 195 | CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, heap_memory, target - heap_start, | 195 | CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, heap_memory, target - heap_start, |
| 196 | size, MemoryState::Private)); | 196 | size, MemoryState::Heap)); |
| 197 | vm_manager.Reprotect(vma, perms); | 197 | vm_manager.Reprotect(vma, perms); |
| 198 | 198 | ||
| 199 | heap_used += size; | 199 | heap_used += size; |
| @@ -223,40 +223,8 @@ ResultCode Process::HeapFree(VAddr target, u32 size) { | |||
| 223 | } | 223 | } |
| 224 | 224 | ||
| 225 | ResultVal<VAddr> Process::LinearAllocate(VAddr target, u32 size, VMAPermission perms) { | 225 | ResultVal<VAddr> Process::LinearAllocate(VAddr target, u32 size, VMAPermission perms) { |
| 226 | auto& linheap_memory = memory_region->linear_heap_memory; | 226 | UNIMPLEMENTED(); |
| 227 | 227 | return {}; | |
| 228 | VAddr heap_end = GetLinearHeapBase() + (u32)linheap_memory->size(); | ||
| 229 | // Games and homebrew only ever seem to pass 0 here (which lets the kernel decide the address), | ||
| 230 | // but explicit addresses are also accepted and respected. | ||
| 231 | if (target == 0) { | ||
| 232 | target = heap_end; | ||
| 233 | } | ||
| 234 | |||
| 235 | if (target < GetLinearHeapBase() || target + size > GetLinearHeapLimit() || target > heap_end || | ||
| 236 | target + size < target) { | ||
| 237 | |||
| 238 | return ERR_INVALID_ADDRESS; | ||
| 239 | } | ||
| 240 | |||
| 241 | // Expansion of the linear heap is only allowed if you do an allocation immediately at its | ||
| 242 | // end. It's possible to free gaps in the middle of the heap and then reallocate them later, | ||
| 243 | // but expansions are only allowed at the end. | ||
| 244 | if (target == heap_end) { | ||
| 245 | linheap_memory->insert(linheap_memory->end(), size, 0); | ||
| 246 | vm_manager.RefreshMemoryBlockMappings(linheap_memory.get()); | ||
| 247 | } | ||
| 248 | |||
| 249 | // TODO(yuriks): As is, this lets processes map memory allocated by other processes from the | ||
| 250 | // same region. It is unknown if or how the 3DS kernel checks against this. | ||
| 251 | size_t offset = target - GetLinearHeapBase(); | ||
| 252 | CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, linheap_memory, offset, size, | ||
| 253 | MemoryState::Continuous)); | ||
| 254 | vm_manager.Reprotect(vma, perms); | ||
| 255 | |||
| 256 | linear_heap_used += size; | ||
| 257 | memory_region->used += size; | ||
| 258 | |||
| 259 | return MakeResult<VAddr>(target); | ||
| 260 | } | 228 | } |
| 261 | 229 | ||
| 262 | ResultCode Process::LinearFree(VAddr target, u32 size) { | 230 | ResultCode Process::LinearFree(VAddr target, u32 size) { |
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 75df49ac2..8b72084bf 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -446,7 +446,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, | |||
| 446 | // Map the page to the current process' address space. | 446 | // Map the page to the current process' address space. |
| 447 | // TODO(Subv): Find the correct MemoryState for this region. | 447 | // TODO(Subv): Find the correct MemoryState for this region. |
| 448 | vm_manager.MapMemoryBlock(Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE, | 448 | vm_manager.MapMemoryBlock(Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE, |
| 449 | linheap_memory, offset, Memory::PAGE_SIZE, MemoryState::Static); | 449 | linheap_memory, offset, Memory::PAGE_SIZE, MemoryState::ThreadLocalStorage); |
| 450 | } | 450 | } |
| 451 | 451 | ||
| 452 | // Mark the slot as used | 452 | // Mark the slot as used |
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h index cb5bb8243..d3db1ca8d 100644 --- a/src/core/hle/kernel/vm_manager.h +++ b/src/core/hle/kernel/vm_manager.h | |||
| @@ -40,19 +40,16 @@ enum class VMAPermission : u8 { | |||
| 40 | }; | 40 | }; |
| 41 | 41 | ||
| 42 | /// Set of values returned in MemoryInfo.state by svcQueryMemory. | 42 | /// Set of values returned in MemoryInfo.state by svcQueryMemory. |
| 43 | enum class MemoryState : u8 { | 43 | enum class MemoryState : u32 { |
| 44 | Free = 0, | 44 | Free = 0, |
| 45 | Reserved = 1, | 45 | IO = 1, |
| 46 | IO = 2, | 46 | Normal = 2, |
| 47 | Static = 3, | 47 | Code = 3, |
| 48 | Code = 4, | 48 | Static = 4, |
| 49 | Private = 5, | 49 | Heap = 5, |
| 50 | Shared = 6, | 50 | Shared = 6, |
| 51 | Continuous = 7, | 51 | Mapped = 6, |
| 52 | Aliased = 8, | 52 | ThreadLocalStorage = 12, |
| 53 | Alias = 9, | ||
| 54 | AliasCode = 10, | ||
| 55 | Locked = 11, | ||
| 56 | }; | 53 | }; |
| 57 | 54 | ||
| 58 | /** | 55 | /** |
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 9da6c0adf..0401f763b 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp | |||
| @@ -110,28 +110,22 @@ static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* /*page_i | |||
| 110 | Kernel::Handle process_handle, u64 addr) { | 110 | Kernel::Handle process_handle, u64 addr) { |
| 111 | using Kernel::Process; | 111 | using Kernel::Process; |
| 112 | Kernel::SharedPtr<Process> process = Kernel::g_handle_table.Get<Process>(process_handle); | 112 | Kernel::SharedPtr<Process> process = Kernel::g_handle_table.Get<Process>(process_handle); |
| 113 | if (process == nullptr) | 113 | if (process == nullptr) { |
| 114 | return ERR_INVALID_HANDLE; | 114 | return ERR_INVALID_HANDLE; |
| 115 | 115 | } | |
| 116 | auto vma = process->vm_manager.FindVMA(addr); | 116 | auto vma = process->vm_manager.FindVMA(addr); |
| 117 | 117 | memory_info->attributes = 0; | |
| 118 | if (vma == Kernel::g_current_process->vm_manager.vma_map.end()) | 118 | if (vma == Kernel::g_current_process->vm_manager.vma_map.end()) { |
| 119 | { | ||
| 120 | //return Kernel::ERR_INVALID_ADDRESS; | ||
| 121 | |||
| 122 | memory_info->base_address = 0; | 119 | memory_info->base_address = 0; |
| 123 | memory_info->permission = static_cast<u64>(Kernel::VMAPermission::None); | 120 | memory_info->permission = static_cast<u32>(Kernel::VMAPermission::None); |
| 124 | memory_info->size = 0; | 121 | memory_info->size = 0; |
| 125 | memory_info->state = static_cast<u64>(Kernel::MemoryState::Free); | 122 | memory_info->type = static_cast<u32>(Kernel::MemoryState::Free); |
| 126 | 123 | } else { | |
| 127 | return RESULT_SUCCESS; | 124 | memory_info->base_address = vma->second.base; |
| 125 | memory_info->permission = static_cast<u32>(vma->second.permissions); | ||
| 126 | memory_info->size = vma->second.size; | ||
| 127 | memory_info->type = static_cast<u32>(vma->second.meminfo_state); | ||
| 128 | } | 128 | } |
| 129 | |||
| 130 | memory_info->base_address = vma->second.base; | ||
| 131 | memory_info->permission = static_cast<u64>(vma->second.permissions); | ||
| 132 | memory_info->size = vma->second.size; | ||
| 133 | memory_info->state = static_cast<u64>(vma->second.meminfo_state); | ||
| 134 | |||
| 135 | LOG_TRACE(Kernel_SVC, "called process=0x%08X addr=%llx", process_handle, addr); | 129 | LOG_TRACE(Kernel_SVC, "called process=0x%08X addr=%llx", process_handle, addr); |
| 136 | return RESULT_SUCCESS; | 130 | return RESULT_SUCCESS; |
| 137 | } | 131 | } |
diff --git a/src/core/hle/svc.h b/src/core/hle/svc.h index 993c074bf..417a1735f 100644 --- a/src/core/hle/svc.h +++ b/src/core/hle/svc.h | |||
| @@ -12,8 +12,9 @@ | |||
| 12 | struct MemoryInfo { | 12 | struct MemoryInfo { |
| 13 | u64 base_address; | 13 | u64 base_address; |
| 14 | u64 size; | 14 | u64 size; |
| 15 | u64 permission; | 15 | u32 type; |
| 16 | u64 state; | 16 | u32 attributes; |
| 17 | u32 permission; | ||
| 17 | }; | 18 | }; |
| 18 | 19 | ||
| 19 | struct PageInfo { | 20 | struct PageInfo { |