summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner2017-05-14 13:52:40 -0700
committerGravatar GitHub2017-05-14 13:52:40 -0700
commit180587bb8bd18feeb81028007556276ef4ecaafd (patch)
tree5939bfa2c92ced9b30ade0b725ace7b7dce3d040 /src/core/hle/kernel
parentMerge pull request #2695 from JayFoxRox/gs-regs (diff)
parentKernel: Map special regions according to ExHeader (diff)
downloadyuzu-180587bb8bd18feeb81028007556276ef4ecaafd.tar.gz
yuzu-180587bb8bd18feeb81028007556276ef4ecaafd.tar.xz
yuzu-180587bb8bd18feeb81028007556276ef4ecaafd.zip
Merge pull request #2687 from yuriks/address-mappings
Kernel: Map special regions according to ExHeader
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/memory.cpp112
-rw-r--r--src/core/hle/kernel/memory.h10
-rw-r--r--src/core/hle/kernel/process.cpp23
-rw-r--r--src/core/hle/kernel/process.h2
4 files changed, 102 insertions, 45 deletions
diff --git a/src/core/hle/kernel/memory.cpp b/src/core/hle/kernel/memory.cpp
index 33c165197..8250a90b5 100644
--- a/src/core/hle/kernel/memory.cpp
+++ b/src/core/hle/kernel/memory.cpp
@@ -2,11 +2,13 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cinttypes>
5#include <map> 6#include <map>
6#include <memory> 7#include <memory>
7#include <utility> 8#include <utility>
8#include <vector> 9#include <vector>
9#include "audio_core/audio_core.h" 10#include "audio_core/audio_core.h"
11#include "common/assert.h"
10#include "common/common_types.h" 12#include "common/common_types.h"
11#include "common/logging/log.h" 13#include "common/logging/log.h"
12#include "core/hle/config_mem.h" 14#include "core/hle/config_mem.h"
@@ -92,52 +94,96 @@ MemoryRegionInfo* GetMemoryRegion(MemoryRegion region) {
92 UNREACHABLE(); 94 UNREACHABLE();
93 } 95 }
94} 96}
95}
96
97namespace Memory {
98 97
99namespace { 98std::array<u8, Memory::VRAM_SIZE> vram;
99std::array<u8, Memory::N3DS_EXTRA_RAM_SIZE> n3ds_extra_ram;
100
101void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping) {
102 using namespace Memory;
103
104 struct MemoryArea {
105 VAddr vaddr_base;
106 PAddr paddr_base;
107 u32 size;
108 };
109
110 // The order of entries in this array is important. The VRAM and IO VAddr ranges overlap, and
111 // VRAM must be tried first.
112 static constexpr MemoryArea memory_areas[] = {
113 {VRAM_VADDR, VRAM_PADDR, VRAM_SIZE},
114 {IO_AREA_VADDR, IO_AREA_PADDR, IO_AREA_SIZE},
115 {DSP_RAM_VADDR, DSP_RAM_PADDR, DSP_RAM_SIZE},
116 {N3DS_EXTRA_RAM_VADDR, N3DS_EXTRA_RAM_PADDR, N3DS_EXTRA_RAM_SIZE - 0x20000},
117 };
118
119 VAddr mapping_limit = mapping.address + mapping.size;
120 if (mapping_limit < mapping.address) {
121 LOG_CRITICAL(Loader, "Mapping size overflowed: address=0x%08" PRIX32 " size=0x%" PRIX32,
122 mapping.address, mapping.size);
123 return;
124 }
100 125
101struct MemoryArea { 126 auto area =
102 u32 base; 127 std::find_if(std::begin(memory_areas), std::end(memory_areas), [&](const auto& area) {
103 u32 size; 128 return mapping.address >= area.vaddr_base &&
104 const char* name; 129 mapping_limit <= area.vaddr_base + area.size;
105}; 130 });
131 if (area == std::end(memory_areas)) {
132 LOG_ERROR(Loader, "Unhandled special mapping: address=0x%08" PRIX32 " size=0x%" PRIX32
133 " read_only=%d unk_flag=%d",
134 mapping.address, mapping.size, mapping.read_only, mapping.unk_flag);
135 return;
136 }
106 137
107// We don't declare the IO regions in here since its handled by other means. 138 u32 offset_into_region = mapping.address - area->vaddr_base;
108static MemoryArea memory_areas[] = { 139 if (area->paddr_base == IO_AREA_PADDR) {
109 {VRAM_VADDR, VRAM_SIZE, "VRAM"}, // Video memory (VRAM) 140 LOG_ERROR(Loader, "MMIO mappings are not supported yet. phys_addr=0x%08" PRIX32,
110}; 141 area->paddr_base + offset_into_region);
111} 142 return;
143 }
112 144
113void Init() { 145 // TODO(yuriks): Use GetPhysicalPointer when that becomes independent of the virtual
114 InitMemoryMap(); 146 // mappings.
115 LOG_DEBUG(HW_Memory, "initialized OK"); 147 u8* target_pointer = nullptr;
116} 148 switch (area->paddr_base) {
149 case VRAM_PADDR:
150 target_pointer = vram.data();
151 break;
152 case DSP_RAM_PADDR:
153 target_pointer = AudioCore::GetDspMemory().data();
154 break;
155 case N3DS_EXTRA_RAM_PADDR:
156 target_pointer = n3ds_extra_ram.data();
157 break;
158 default:
159 UNREACHABLE();
160 }
117 161
118void InitLegacyAddressSpace(Kernel::VMManager& address_space) { 162 // TODO(yuriks): This flag seems to have some other effect, but it's unknown what
119 using namespace Kernel; 163 MemoryState memory_state = mapping.unk_flag ? MemoryState::Static : MemoryState::IO;
120 164
121 for (MemoryArea& area : memory_areas) { 165 auto vma = address_space
122 auto block = std::make_shared<std::vector<u8>>(area.size); 166 .MapBackingMemory(mapping.address, target_pointer + offset_into_region,
123 address_space 167 mapping.size, memory_state)
124 .MapMemoryBlock(area.base, std::move(block), 0, area.size, MemoryState::Private) 168 .MoveFrom();
125 .Unwrap(); 169 address_space.Reprotect(vma,
126 } 170 mapping.read_only ? VMAPermission::Read : VMAPermission::ReadWrite);
171}
127 172
173void MapSharedPages(VMManager& address_space) {
128 auto cfg_mem_vma = address_space 174 auto cfg_mem_vma = address_space
129 .MapBackingMemory(CONFIG_MEMORY_VADDR, (u8*)&ConfigMem::config_mem, 175 .MapBackingMemory(Memory::CONFIG_MEMORY_VADDR,
130 CONFIG_MEMORY_SIZE, MemoryState::Shared) 176 reinterpret_cast<u8*>(&ConfigMem::config_mem),
177 Memory::CONFIG_MEMORY_SIZE, MemoryState::Shared)
131 .MoveFrom(); 178 .MoveFrom();
132 address_space.Reprotect(cfg_mem_vma, VMAPermission::Read); 179 address_space.Reprotect(cfg_mem_vma, VMAPermission::Read);
133 180
134 auto shared_page_vma = address_space 181 auto shared_page_vma = address_space
135 .MapBackingMemory(SHARED_PAGE_VADDR, (u8*)&SharedPage::shared_page, 182 .MapBackingMemory(Memory::SHARED_PAGE_VADDR,
136 SHARED_PAGE_SIZE, MemoryState::Shared) 183 reinterpret_cast<u8*>(&SharedPage::shared_page),
184 Memory::SHARED_PAGE_SIZE, MemoryState::Shared)
137 .MoveFrom(); 185 .MoveFrom();
138 address_space.Reprotect(shared_page_vma, VMAPermission::Read); 186 address_space.Reprotect(shared_page_vma, VMAPermission::Read);
139
140 AudioCore::AddAddressSpace(address_space);
141} 187}
142 188
143} // namespace 189} // namespace Kernel
diff --git a/src/core/hle/kernel/memory.h b/src/core/hle/kernel/memory.h
index 4e1856a41..08c1a9989 100644
--- a/src/core/hle/kernel/memory.h
+++ b/src/core/hle/kernel/memory.h
@@ -23,11 +23,7 @@ struct MemoryRegionInfo {
23void MemoryInit(u32 mem_type); 23void MemoryInit(u32 mem_type);
24void MemoryShutdown(); 24void MemoryShutdown();
25MemoryRegionInfo* GetMemoryRegion(MemoryRegion region); 25MemoryRegionInfo* GetMemoryRegion(MemoryRegion region);
26}
27 26
28namespace Memory { 27void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping);
29 28void MapSharedPages(VMManager& address_space);
30void Init(); 29} // namespace Kernel
31void InitLegacyAddressSpace(Kernel::VMManager& address_space);
32
33} // namespace
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index ba80fe7f8..32cb25fb7 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -35,7 +35,6 @@ SharedPtr<Process> Process::Create(SharedPtr<CodeSet> code_set) {
35 process->codeset = std::move(code_set); 35 process->codeset = std::move(code_set);
36 process->flags.raw = 0; 36 process->flags.raw = 0;
37 process->flags.memory_region.Assign(MemoryRegion::APPLICATION); 37 process->flags.memory_region.Assign(MemoryRegion::APPLICATION);
38 Memory::InitLegacyAddressSpace(process->vm_manager);
39 38
40 return process; 39 return process;
41} 40}
@@ -78,8 +77,15 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) {
78 77
79 AddressMapping mapping; 78 AddressMapping mapping;
80 mapping.address = descriptor << 12; 79 mapping.address = descriptor << 12;
81 mapping.size = (end_desc << 12) - mapping.address; 80 VAddr end_address = end_desc << 12;
82 mapping.writable = (descriptor & (1 << 20)) != 0; 81
82 if (mapping.address < end_address) {
83 mapping.size = end_address - mapping.address;
84 } else {
85 mapping.size = 0;
86 }
87
88 mapping.read_only = (descriptor & (1 << 20)) != 0;
83 mapping.unk_flag = (end_desc & (1 << 20)) != 0; 89 mapping.unk_flag = (end_desc & (1 << 20)) != 0;
84 90
85 address_mappings.push_back(mapping); 91 address_mappings.push_back(mapping);
@@ -88,8 +94,10 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) {
88 AddressMapping mapping; 94 AddressMapping mapping;
89 mapping.address = descriptor << 12; 95 mapping.address = descriptor << 12;
90 mapping.size = Memory::PAGE_SIZE; 96 mapping.size = Memory::PAGE_SIZE;
91 mapping.writable = true; // TODO: Not sure if correct 97 mapping.read_only = false;
92 mapping.unk_flag = false; 98 mapping.unk_flag = false;
99
100 address_mappings.push_back(mapping);
93 } else if ((type & 0xFE0) == 0xFC0) { // 0x01FF 101 } else if ((type & 0xFE0) == 0xFC0) { // 0x01FF
94 // Kernel version 102 // Kernel version
95 kernel_version = descriptor & 0xFFFF; 103 kernel_version = descriptor & 0xFFFF;
@@ -131,6 +139,12 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) {
131 misc_memory_used += stack_size; 139 misc_memory_used += stack_size;
132 memory_region->used += stack_size; 140 memory_region->used += stack_size;
133 141
142 // Map special address mappings
143 MapSharedPages(vm_manager);
144 for (const auto& mapping : address_mappings) {
145 HandleSpecialMapping(vm_manager, mapping);
146 }
147
134 vm_manager.LogLayout(Log::Level::Debug); 148 vm_manager.LogLayout(Log::Level::Debug);
135 Kernel::SetupMainThread(codeset->entrypoint, main_thread_priority); 149 Kernel::SetupMainThread(codeset->entrypoint, main_thread_priority);
136} 150}
@@ -138,6 +152,7 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) {
138VAddr Process::GetLinearHeapAreaAddress() const { 152VAddr Process::GetLinearHeapAreaAddress() const {
139 return kernel_version < 0x22C ? Memory::LINEAR_HEAP_VADDR : Memory::NEW_LINEAR_HEAP_VADDR; 153 return kernel_version < 0x22C ? Memory::LINEAR_HEAP_VADDR : Memory::NEW_LINEAR_HEAP_VADDR;
140} 154}
155
141VAddr Process::GetLinearHeapBase() const { 156VAddr Process::GetLinearHeapBase() const {
142 return GetLinearHeapAreaAddress() + memory_region->base; 157 return GetLinearHeapAreaAddress() + memory_region->base;
143} 158}
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index b566950b0..b52211d2a 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -20,7 +20,7 @@ struct AddressMapping {
20 // Address and size must be page-aligned 20 // Address and size must be page-aligned
21 VAddr address; 21 VAddr address;
22 u32 size; 22 u32 size;
23 bool writable; 23 bool read_only;
24 bool unk_flag; 24 bool unk_flag;
25}; 25};
26 26