diff options
| -rw-r--r-- | src/core/file_sys/archive_savedata.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/event.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/event.h | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.cpp | 38 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.h | 43 | ||||
| -rw-r--r-- | src/core/hle/kernel/vm_manager.cpp | 14 | ||||
| -rw-r--r-- | src/core/hle/kernel/vm_manager.h | 6 | ||||
| -rw-r--r-- | src/core/loader/3dsx.cpp | 69 | ||||
| -rw-r--r-- | src/core/loader/elf.cpp | 81 | ||||
| -rw-r--r-- | src/core/loader/ncch.cpp | 32 | ||||
| -rw-r--r-- | src/core/mem_map.cpp | 14 | ||||
| -rw-r--r-- | src/core/mem_map.h | 5 | ||||
| -rw-r--r-- | src/core/memory.cpp | 6 |
14 files changed, 242 insertions, 74 deletions
diff --git a/src/core/file_sys/archive_savedata.cpp b/src/core/file_sys/archive_savedata.cpp index 98823aec3..12876899f 100644 --- a/src/core/file_sys/archive_savedata.cpp +++ b/src/core/file_sys/archive_savedata.cpp | |||
| @@ -37,7 +37,7 @@ ArchiveFactory_SaveData::ArchiveFactory_SaveData(const std::string& sdmc_directo | |||
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveData::Open(const Path& path) { | 39 | ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveData::Open(const Path& path) { |
| 40 | std::string concrete_mount_point = GetSaveDataPath(mount_point, Kernel::g_current_process->program_id); | 40 | std::string concrete_mount_point = GetSaveDataPath(mount_point, Kernel::g_current_process->codeset->program_id); |
| 41 | if (!FileUtil::Exists(concrete_mount_point)) { | 41 | if (!FileUtil::Exists(concrete_mount_point)) { |
| 42 | // When a SaveData archive is created for the first time, it is not yet formatted | 42 | // When a SaveData archive is created for the first time, it is not yet formatted |
| 43 | // and the save file/directory structure expected by the game has not yet been initialized. | 43 | // and the save file/directory structure expected by the game has not yet been initialized. |
| @@ -52,7 +52,7 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveData::Open(const P | |||
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | ResultCode ArchiveFactory_SaveData::Format(const Path& path) { | 54 | ResultCode ArchiveFactory_SaveData::Format(const Path& path) { |
| 55 | std::string concrete_mount_point = GetSaveDataPath(mount_point, Kernel::g_current_process->program_id); | 55 | std::string concrete_mount_point = GetSaveDataPath(mount_point, Kernel::g_current_process->codeset->program_id); |
| 56 | FileUtil::DeleteDirRecursively(concrete_mount_point); | 56 | FileUtil::DeleteDirRecursively(concrete_mount_point); |
| 57 | FileUtil::CreateFullPath(concrete_mount_point); | 57 | FileUtil::CreateFullPath(concrete_mount_point); |
| 58 | return RESULT_SUCCESS; | 58 | return RESULT_SUCCESS; |
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index f338f3266..53feebbc0 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp | |||
| @@ -21,7 +21,7 @@ SharedPtr<Event> Event::Create(ResetType reset_type, std::string name) { | |||
| 21 | SharedPtr<Event> evt(new Event); | 21 | SharedPtr<Event> evt(new Event); |
| 22 | 22 | ||
| 23 | evt->signaled = false; | 23 | evt->signaled = false; |
| 24 | evt->reset_type = evt->intitial_reset_type = reset_type; | 24 | evt->reset_type = reset_type; |
| 25 | evt->name = std::move(name); | 25 | evt->name = std::move(name); |
| 26 | 26 | ||
| 27 | return evt; | 27 | return evt; |
diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index fba960d2a..89d405236 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h | |||
| @@ -26,7 +26,6 @@ public: | |||
| 26 | static const HandleType HANDLE_TYPE = HandleType::Event; | 26 | static const HandleType HANDLE_TYPE = HandleType::Event; |
| 27 | HandleType GetHandleType() const override { return HANDLE_TYPE; } | 27 | HandleType GetHandleType() const override { return HANDLE_TYPE; } |
| 28 | 28 | ||
| 29 | ResetType intitial_reset_type; ///< ResetType specified at Event initialization | ||
| 30 | ResetType reset_type; ///< Current ResetType | 29 | ResetType reset_type; ///< Current ResetType |
| 31 | 30 | ||
| 32 | bool signaled; ///< Whether the event has already been signaled | 31 | bool signaled; ///< Whether the event has already been signaled |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index b29260b5d..4c4486c19 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -47,6 +47,7 @@ enum class HandleType : u32 { | |||
| 47 | Semaphore = 10, | 47 | Semaphore = 10, |
| 48 | Timer = 11, | 48 | Timer = 11, |
| 49 | ResourceLimit = 12, | 49 | ResourceLimit = 12, |
| 50 | CodeSet = 13, | ||
| 50 | }; | 51 | }; |
| 51 | 52 | ||
| 52 | enum { | 53 | enum { |
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index b0e75ba59..a7892c652 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp | |||
| @@ -5,24 +5,39 @@ | |||
| 5 | #include "common/assert.h" | 5 | #include "common/assert.h" |
| 6 | #include "common/common_funcs.h" | 6 | #include "common/common_funcs.h" |
| 7 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 8 | #include "common/make_unique.h" | ||
| 8 | 9 | ||
| 9 | #include "core/hle/kernel/process.h" | 10 | #include "core/hle/kernel/process.h" |
| 10 | #include "core/hle/kernel/resource_limit.h" | 11 | #include "core/hle/kernel/resource_limit.h" |
| 11 | #include "core/hle/kernel/thread.h" | 12 | #include "core/hle/kernel/thread.h" |
| 13 | #include "core/hle/kernel/vm_manager.h" | ||
| 14 | #include "core/mem_map.h" | ||
| 12 | #include "core/memory.h" | 15 | #include "core/memory.h" |
| 13 | 16 | ||
| 14 | namespace Kernel { | 17 | namespace Kernel { |
| 15 | 18 | ||
| 19 | SharedPtr<CodeSet> CodeSet::Create(std::string name, u64 program_id) { | ||
| 20 | SharedPtr<CodeSet> codeset(new CodeSet); | ||
| 21 | |||
| 22 | codeset->name = std::move(name); | ||
| 23 | codeset->program_id = program_id; | ||
| 24 | |||
| 25 | return codeset; | ||
| 26 | } | ||
| 27 | |||
| 28 | CodeSet::CodeSet() {} | ||
| 29 | CodeSet::~CodeSet() {} | ||
| 30 | |||
| 16 | u32 Process::next_process_id; | 31 | u32 Process::next_process_id; |
| 17 | 32 | ||
| 18 | SharedPtr<Process> Process::Create(std::string name, u64 program_id) { | 33 | SharedPtr<Process> Process::Create(SharedPtr<CodeSet> code_set) { |
| 19 | SharedPtr<Process> process(new Process); | 34 | SharedPtr<Process> process(new Process); |
| 20 | 35 | ||
| 21 | process->name = std::move(name); | 36 | process->codeset = std::move(code_set); |
| 22 | process->program_id = program_id; | ||
| 23 | |||
| 24 | process->flags.raw = 0; | 37 | process->flags.raw = 0; |
| 25 | process->flags.memory_region = MemoryRegion::APPLICATION; | 38 | process->flags.memory_region = MemoryRegion::APPLICATION; |
| 39 | process->address_space = Common::make_unique<VMManager>(); | ||
| 40 | Memory::InitLegacyAddressSpace(*process->address_space); | ||
| 26 | 41 | ||
| 27 | return process; | 42 | return process; |
| 28 | } | 43 | } |
| @@ -87,8 +102,19 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) { | |||
| 87 | } | 102 | } |
| 88 | } | 103 | } |
| 89 | 104 | ||
| 90 | void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) { | 105 | void Process::Run(s32 main_thread_priority, u32 stack_size) { |
| 91 | Kernel::SetupMainThread(entry_point, main_thread_priority); | 106 | auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions, MemoryState memory_state) { |
| 107 | auto vma = address_space->MapMemoryBlock(segment.addr, codeset->memory, | ||
| 108 | segment.offset, segment.size, memory_state).Unwrap(); | ||
| 109 | address_space->Reprotect(vma, permissions); | ||
| 110 | }; | ||
| 111 | |||
| 112 | MapSegment(codeset->code, VMAPermission::ReadExecute, MemoryState::Code); | ||
| 113 | MapSegment(codeset->rodata, VMAPermission::Read, MemoryState::Code); | ||
| 114 | MapSegment(codeset->data, VMAPermission::ReadWrite, MemoryState::Private); | ||
| 115 | |||
| 116 | address_space->LogLayout(); | ||
| 117 | Kernel::SetupMainThread(codeset->entrypoint, main_thread_priority); | ||
| 92 | } | 118 | } |
| 93 | 119 | ||
| 94 | Kernel::Process::Process() {} | 120 | Kernel::Process::Process() {} |
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index 674f5093a..92fa0fa6f 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h | |||
| @@ -47,23 +47,51 @@ union ProcessFlags { | |||
| 47 | }; | 47 | }; |
| 48 | 48 | ||
| 49 | class ResourceLimit; | 49 | class ResourceLimit; |
| 50 | class VMManager; | ||
| 51 | |||
| 52 | struct CodeSet final : public Object { | ||
| 53 | static SharedPtr<CodeSet> Create(std::string name, u64 program_id); | ||
| 54 | |||
| 55 | std::string GetTypeName() const override { return "CodeSet"; } | ||
| 56 | std::string GetName() const override { return name; } | ||
| 57 | |||
| 58 | static const HandleType HANDLE_TYPE = HandleType::CodeSet; | ||
| 59 | HandleType GetHandleType() const override { return HANDLE_TYPE; } | ||
| 60 | |||
| 61 | /// Name of the process | ||
| 62 | std::string name; | ||
| 63 | /// Title ID corresponding to the process | ||
| 64 | u64 program_id; | ||
| 65 | |||
| 66 | std::shared_ptr<std::vector<u8>> memory; | ||
| 67 | |||
| 68 | struct Segment { | ||
| 69 | size_t offset = 0; | ||
| 70 | VAddr addr = 0; | ||
| 71 | u32 size = 0; | ||
| 72 | }; | ||
| 73 | |||
| 74 | Segment code, rodata, data; | ||
| 75 | VAddr entrypoint; | ||
| 76 | |||
| 77 | private: | ||
| 78 | CodeSet(); | ||
| 79 | ~CodeSet() override; | ||
| 80 | }; | ||
| 50 | 81 | ||
| 51 | class Process final : public Object { | 82 | class Process final : public Object { |
| 52 | public: | 83 | public: |
| 53 | static SharedPtr<Process> Create(std::string name, u64 program_id); | 84 | static SharedPtr<Process> Create(SharedPtr<CodeSet> code_set); |
| 54 | 85 | ||
| 55 | std::string GetTypeName() const override { return "Process"; } | 86 | std::string GetTypeName() const override { return "Process"; } |
| 56 | std::string GetName() const override { return name; } | 87 | std::string GetName() const override { return codeset->name; } |
| 57 | 88 | ||
| 58 | static const HandleType HANDLE_TYPE = HandleType::Process; | 89 | static const HandleType HANDLE_TYPE = HandleType::Process; |
| 59 | HandleType GetHandleType() const override { return HANDLE_TYPE; } | 90 | HandleType GetHandleType() const override { return HANDLE_TYPE; } |
| 60 | 91 | ||
| 61 | static u32 next_process_id; | 92 | static u32 next_process_id; |
| 62 | 93 | ||
| 63 | /// Name of the process | 94 | SharedPtr<CodeSet> codeset; |
| 64 | std::string name; | ||
| 65 | /// Title ID corresponding to the process | ||
| 66 | u64 program_id; | ||
| 67 | /// Resource limit descriptor for this process | 95 | /// Resource limit descriptor for this process |
| 68 | SharedPtr<ResourceLimit> resource_limit; | 96 | SharedPtr<ResourceLimit> resource_limit; |
| 69 | 97 | ||
| @@ -81,6 +109,7 @@ public: | |||
| 81 | 109 | ||
| 82 | /// Bitmask of the used TLS slots | 110 | /// Bitmask of the used TLS slots |
| 83 | std::bitset<300> used_tls_slots; | 111 | std::bitset<300> used_tls_slots; |
| 112 | std::unique_ptr<VMManager> address_space; | ||
| 84 | 113 | ||
| 85 | /** | 114 | /** |
| 86 | * Parses a list of kernel capability descriptors (as found in the ExHeader) and applies them | 115 | * Parses a list of kernel capability descriptors (as found in the ExHeader) and applies them |
| @@ -91,7 +120,7 @@ public: | |||
| 91 | /** | 120 | /** |
| 92 | * Applies address space changes and launches the process main thread. | 121 | * Applies address space changes and launches the process main thread. |
| 93 | */ | 122 | */ |
| 94 | void Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size); | 123 | void Run(s32 main_thread_priority, u32 stack_size); |
| 95 | 124 | ||
| 96 | private: | 125 | private: |
| 97 | Process(); | 126 | Process(); |
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index ec437cd61..205cc7b53 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp | |||
| @@ -35,6 +35,10 @@ VMManager::VMManager() { | |||
| 35 | Reset(); | 35 | Reset(); |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | VMManager::~VMManager() { | ||
| 39 | Reset(); | ||
| 40 | } | ||
| 41 | |||
| 38 | void VMManager::Reset() { | 42 | void VMManager::Reset() { |
| 39 | vma_map.clear(); | 43 | vma_map.clear(); |
| 40 | 44 | ||
| @@ -130,6 +134,16 @@ void VMManager::Reprotect(VMAHandle vma_handle, VMAPermission new_perms) { | |||
| 130 | MergeAdjacent(iter); | 134 | MergeAdjacent(iter); |
| 131 | } | 135 | } |
| 132 | 136 | ||
| 137 | void VMManager::LogLayout() const { | ||
| 138 | for (const auto& p : vma_map) { | ||
| 139 | const VirtualMemoryArea& vma = p.second; | ||
| 140 | LOG_DEBUG(Kernel, "%08X - %08X size: %8X %c%c%c", vma.base, vma.base + vma.size, vma.size, | ||
| 141 | (u8)vma.permissions & (u8)VMAPermission::Read ? 'R' : '-', | ||
| 142 | (u8)vma.permissions & (u8)VMAPermission::Write ? 'W' : '-', | ||
| 143 | (u8)vma.permissions & (u8)VMAPermission::Execute ? 'X' : '-'); | ||
| 144 | } | ||
| 145 | } | ||
| 146 | |||
| 133 | VMManager::VMAIter VMManager::StripIterConstness(const VMAHandle & iter) { | 147 | VMManager::VMAIter VMManager::StripIterConstness(const VMAHandle & iter) { |
| 134 | // This uses a neat C++ trick to convert a const_iterator to a regular iterator, given | 148 | // This uses a neat C++ trick to convert a const_iterator to a regular iterator, given |
| 135 | // non-const access to its container. | 149 | // non-const access to its container. |
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h index 271e2333e..b3795a94a 100644 --- a/src/core/hle/kernel/vm_manager.h +++ b/src/core/hle/kernel/vm_manager.h | |||
| @@ -101,7 +101,7 @@ struct VirtualMemoryArea { | |||
| 101 | * - http://duartes.org/gustavo/blog/post/how-the-kernel-manages-your-memory/ | 101 | * - http://duartes.org/gustavo/blog/post/how-the-kernel-manages-your-memory/ |
| 102 | * - http://duartes.org/gustavo/blog/post/page-cache-the-affair-between-memory-and-files/ | 102 | * - http://duartes.org/gustavo/blog/post/page-cache-the-affair-between-memory-and-files/ |
| 103 | */ | 103 | */ |
| 104 | class VMManager { | 104 | class VMManager final { |
| 105 | // TODO(yuriks): Make page tables switchable to support multiple VMManagers | 105 | // TODO(yuriks): Make page tables switchable to support multiple VMManagers |
| 106 | public: | 106 | public: |
| 107 | /** | 107 | /** |
| @@ -121,6 +121,7 @@ public: | |||
| 121 | using VMAHandle = decltype(vma_map)::const_iterator; | 121 | using VMAHandle = decltype(vma_map)::const_iterator; |
| 122 | 122 | ||
| 123 | VMManager(); | 123 | VMManager(); |
| 124 | ~VMManager(); | ||
| 124 | 125 | ||
| 125 | /// Clears the address space map, re-initializing with a single free area. | 126 | /// Clears the address space map, re-initializing with a single free area. |
| 126 | void Reset(); | 127 | void Reset(); |
| @@ -168,6 +169,9 @@ public: | |||
| 168 | /// Changes the permissions of the given VMA. | 169 | /// Changes the permissions of the given VMA. |
| 169 | void Reprotect(VMAHandle vma, VMAPermission new_perms); | 170 | void Reprotect(VMAHandle vma, VMAPermission new_perms); |
| 170 | 171 | ||
| 172 | /// Dumps the address space layout to the log, for debugging | ||
| 173 | void LogLayout() const; | ||
| 174 | |||
| 171 | private: | 175 | private: |
| 172 | using VMAIter = decltype(vma_map)::iterator; | 176 | using VMAIter = decltype(vma_map)::iterator; |
| 173 | 177 | ||
diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp index 14aeebebb..055661363 100644 --- a/src/core/loader/3dsx.cpp +++ b/src/core/loader/3dsx.cpp | |||
| @@ -19,7 +19,7 @@ | |||
| 19 | 19 | ||
| 20 | namespace Loader { | 20 | namespace Loader { |
| 21 | 21 | ||
| 22 | /** | 22 | /* |
| 23 | * File layout: | 23 | * File layout: |
| 24 | * - File header | 24 | * - File header |
| 25 | * - Code, rodata and data relocation table headers | 25 | * - Code, rodata and data relocation table headers |
| @@ -39,13 +39,16 @@ namespace Loader { | |||
| 39 | * The entrypoint is always the start of the code segment. | 39 | * The entrypoint is always the start of the code segment. |
| 40 | * The BSS section must be cleared manually by the application. | 40 | * The BSS section must be cleared manually by the application. |
| 41 | */ | 41 | */ |
| 42 | |||
| 42 | enum THREEDSX_Error { | 43 | enum THREEDSX_Error { |
| 43 | ERROR_NONE = 0, | 44 | ERROR_NONE = 0, |
| 44 | ERROR_READ = 1, | 45 | ERROR_READ = 1, |
| 45 | ERROR_FILE = 2, | 46 | ERROR_FILE = 2, |
| 46 | ERROR_ALLOC = 3 | 47 | ERROR_ALLOC = 3 |
| 47 | }; | 48 | }; |
| 49 | |||
| 48 | static const u32 RELOCBUFSIZE = 512; | 50 | static const u32 RELOCBUFSIZE = 512; |
| 51 | static const unsigned int NUM_SEGMENTS = 3; | ||
| 49 | 52 | ||
| 50 | // File header | 53 | // File header |
| 51 | #pragma pack(1) | 54 | #pragma pack(1) |
| @@ -98,7 +101,10 @@ static u32 TranslateAddr(u32 addr, const THREEloadinfo *loadinfo, u32* offsets) | |||
| 98 | return loadinfo->seg_addrs[2] + addr - offsets[1]; | 101 | return loadinfo->seg_addrs[2] + addr - offsets[1]; |
| 99 | } | 102 | } |
| 100 | 103 | ||
| 101 | static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr) | 104 | using Kernel::SharedPtr; |
| 105 | using Kernel::CodeSet; | ||
| 106 | |||
| 107 | static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, SharedPtr<CodeSet>* out_codeset) | ||
| 102 | { | 108 | { |
| 103 | if (!file.IsOpen()) | 109 | if (!file.IsOpen()) |
| 104 | return ERROR_FILE; | 110 | return ERROR_FILE; |
| @@ -116,15 +122,13 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr) | |||
| 116 | loadinfo.seg_sizes[1] = (hdr.rodata_seg_size + 0xFFF) &~0xFFF; | 122 | loadinfo.seg_sizes[1] = (hdr.rodata_seg_size + 0xFFF) &~0xFFF; |
| 117 | loadinfo.seg_sizes[2] = (hdr.data_seg_size + 0xFFF) &~0xFFF; | 123 | loadinfo.seg_sizes[2] = (hdr.data_seg_size + 0xFFF) &~0xFFF; |
| 118 | u32 offsets[2] = { loadinfo.seg_sizes[0], loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] }; | 124 | u32 offsets[2] = { loadinfo.seg_sizes[0], loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] }; |
| 119 | u32 data_load_size = (hdr.data_seg_size - hdr.bss_size + 0xFFF) &~0xFFF; | 125 | u32 n_reloc_tables = hdr.reloc_hdr_size / sizeof(u32); |
| 120 | u32 bss_load_size = loadinfo.seg_sizes[2] - data_load_size; | 126 | std::vector<u8> program_image(loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] + loadinfo.seg_sizes[2]); |
| 121 | u32 n_reloc_tables = hdr.reloc_hdr_size / 4; | ||
| 122 | std::vector<u8> all_mem(loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] + loadinfo.seg_sizes[2] + 3 * n_reloc_tables); | ||
| 123 | 127 | ||
| 124 | loadinfo.seg_addrs[0] = base_addr; | 128 | loadinfo.seg_addrs[0] = base_addr; |
| 125 | loadinfo.seg_addrs[1] = loadinfo.seg_addrs[0] + loadinfo.seg_sizes[0]; | 129 | loadinfo.seg_addrs[1] = loadinfo.seg_addrs[0] + loadinfo.seg_sizes[0]; |
| 126 | loadinfo.seg_addrs[2] = loadinfo.seg_addrs[1] + loadinfo.seg_sizes[1]; | 130 | loadinfo.seg_addrs[2] = loadinfo.seg_addrs[1] + loadinfo.seg_sizes[1]; |
| 127 | loadinfo.seg_ptrs[0] = &all_mem[0]; | 131 | loadinfo.seg_ptrs[0] = program_image.data(); |
| 128 | loadinfo.seg_ptrs[1] = loadinfo.seg_ptrs[0] + loadinfo.seg_sizes[0]; | 132 | loadinfo.seg_ptrs[1] = loadinfo.seg_ptrs[0] + loadinfo.seg_sizes[0]; |
| 129 | loadinfo.seg_ptrs[2] = loadinfo.seg_ptrs[1] + loadinfo.seg_sizes[1]; | 133 | loadinfo.seg_ptrs[2] = loadinfo.seg_ptrs[1] + loadinfo.seg_sizes[1]; |
| 130 | 134 | ||
| @@ -132,10 +136,9 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr) | |||
| 132 | file.Seek(hdr.header_size, SEEK_SET); | 136 | file.Seek(hdr.header_size, SEEK_SET); |
| 133 | 137 | ||
| 134 | // Read the relocation headers | 138 | // Read the relocation headers |
| 135 | u32* relocs = (u32*)(loadinfo.seg_ptrs[2] + hdr.data_seg_size); | 139 | std::vector<u32> relocs(n_reloc_tables * NUM_SEGMENTS); |
| 136 | 140 | for (unsigned int current_segment = 0; current_segment < NUM_SEGMENTS; ++current_segment) { | |
| 137 | for (unsigned current_segment : {0, 1, 2}) { | 141 | size_t size = n_reloc_tables * sizeof(u32); |
| 138 | size_t size = n_reloc_tables * 4; | ||
| 139 | if (file.ReadBytes(&relocs[current_segment * n_reloc_tables], size) != size) | 142 | if (file.ReadBytes(&relocs[current_segment * n_reloc_tables], size) != size) |
| 140 | return ERROR_READ; | 143 | return ERROR_READ; |
| 141 | } | 144 | } |
| @@ -152,7 +155,7 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr) | |||
| 152 | memset((char*)loadinfo.seg_ptrs[2] + hdr.data_seg_size - hdr.bss_size, 0, hdr.bss_size); | 155 | memset((char*)loadinfo.seg_ptrs[2] + hdr.data_seg_size - hdr.bss_size, 0, hdr.bss_size); |
| 153 | 156 | ||
| 154 | // Relocate the segments | 157 | // Relocate the segments |
| 155 | for (unsigned current_segment : {0, 1, 2}) { | 158 | for (unsigned int current_segment = 0; current_segment < NUM_SEGMENTS; ++current_segment) { |
| 156 | for (unsigned current_segment_reloc_table = 0; current_segment_reloc_table < n_reloc_tables; current_segment_reloc_table++) { | 159 | for (unsigned current_segment_reloc_table = 0; current_segment_reloc_table < n_reloc_tables; current_segment_reloc_table++) { |
| 157 | u32 n_relocs = relocs[current_segment * n_reloc_tables + current_segment_reloc_table]; | 160 | u32 n_relocs = relocs[current_segment * n_reloc_tables + current_segment_reloc_table]; |
| 158 | if (current_segment_reloc_table >= 2) { | 161 | if (current_segment_reloc_table >= 2) { |
| @@ -160,7 +163,7 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr) | |||
| 160 | file.Seek(n_relocs*sizeof(THREEDSX_Reloc), SEEK_CUR); | 163 | file.Seek(n_relocs*sizeof(THREEDSX_Reloc), SEEK_CUR); |
| 161 | continue; | 164 | continue; |
| 162 | } | 165 | } |
| 163 | static THREEDSX_Reloc reloc_table[RELOCBUFSIZE]; | 166 | THREEDSX_Reloc reloc_table[RELOCBUFSIZE]; |
| 164 | 167 | ||
| 165 | u32* pos = (u32*)loadinfo.seg_ptrs[current_segment]; | 168 | u32* pos = (u32*)loadinfo.seg_ptrs[current_segment]; |
| 166 | const u32* end_pos = pos + (loadinfo.seg_sizes[current_segment] / 4); | 169 | const u32* end_pos = pos + (loadinfo.seg_sizes[current_segment] / 4); |
| @@ -179,7 +182,7 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr) | |||
| 179 | pos += table.skip; | 182 | pos += table.skip; |
| 180 | s32 num_patches = table.patch; | 183 | s32 num_patches = table.patch; |
| 181 | while (0 < num_patches && pos < end_pos) { | 184 | while (0 < num_patches && pos < end_pos) { |
| 182 | u32 in_addr = (char*)pos - (char*)&all_mem[0]; | 185 | u32 in_addr = (u8*)pos - program_image.data(); |
| 183 | u32 addr = TranslateAddr(*pos, &loadinfo, offsets); | 186 | u32 addr = TranslateAddr(*pos, &loadinfo, offsets); |
| 184 | LOG_TRACE(Loader, "Patching %08X <-- rel(%08X,%d) (%08X)\n", | 187 | LOG_TRACE(Loader, "Patching %08X <-- rel(%08X,%d) (%08X)\n", |
| 185 | base_addr + in_addr, addr, current_segment_reloc_table, *pos); | 188 | base_addr + in_addr, addr, current_segment_reloc_table, *pos); |
| @@ -201,14 +204,29 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr) | |||
| 201 | } | 204 | } |
| 202 | } | 205 | } |
| 203 | 206 | ||
| 204 | // Write the data | 207 | // Create the CodeSet |
| 205 | memcpy(Memory::GetPointer(base_addr), &all_mem[0], loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] + loadinfo.seg_sizes[2]); | 208 | SharedPtr<CodeSet> code_set = CodeSet::Create("", 0); |
| 209 | |||
| 210 | code_set->code.offset = loadinfo.seg_ptrs[0] - program_image.data(); | ||
| 211 | code_set->code.addr = loadinfo.seg_addrs[0]; | ||
| 212 | code_set->code.size = loadinfo.seg_sizes[0]; | ||
| 213 | |||
| 214 | code_set->rodata.offset = loadinfo.seg_ptrs[1] - program_image.data(); | ||
| 215 | code_set->rodata.addr = loadinfo.seg_addrs[1]; | ||
| 216 | code_set->rodata.size = loadinfo.seg_sizes[1]; | ||
| 206 | 217 | ||
| 207 | LOG_DEBUG(Loader, "CODE: %u pages\n", loadinfo.seg_sizes[0] / 0x1000); | 218 | code_set->data.offset = loadinfo.seg_ptrs[2] - program_image.data(); |
| 208 | LOG_DEBUG(Loader, "RODATA: %u pages\n", loadinfo.seg_sizes[1] / 0x1000); | 219 | code_set->data.addr = loadinfo.seg_addrs[2]; |
| 209 | LOG_DEBUG(Loader, "DATA: %u pages\n", data_load_size / 0x1000); | 220 | code_set->data.size = loadinfo.seg_sizes[2]; |
| 210 | LOG_DEBUG(Loader, "BSS: %u pages\n", bss_load_size / 0x1000); | ||
| 211 | 221 | ||
| 222 | code_set->entrypoint = code_set->code.addr; | ||
| 223 | code_set->memory = std::make_shared<std::vector<u8>>(std::move(program_image)); | ||
| 224 | |||
| 225 | LOG_DEBUG(Loader, "code size: 0x%X", loadinfo.seg_sizes[0]); | ||
| 226 | LOG_DEBUG(Loader, "rodata size: 0x%X", loadinfo.seg_sizes[1]); | ||
| 227 | LOG_DEBUG(Loader, "data size: 0x%X (including 0x%X of bss)", loadinfo.seg_sizes[2], hdr.bss_size); | ||
| 228 | |||
| 229 | *out_codeset = code_set; | ||
| 212 | return ERROR_NONE; | 230 | return ERROR_NONE; |
| 213 | } | 231 | } |
| 214 | 232 | ||
| @@ -231,16 +249,19 @@ ResultStatus AppLoader_THREEDSX::Load() { | |||
| 231 | if (!file->IsOpen()) | 249 | if (!file->IsOpen()) |
| 232 | return ResultStatus::Error; | 250 | return ResultStatus::Error; |
| 233 | 251 | ||
| 234 | Kernel::g_current_process = Kernel::Process::Create(filename, 0); | 252 | SharedPtr<CodeSet> codeset; |
| 253 | if (Load3DSXFile(*file, Memory::PROCESS_IMAGE_VADDR, &codeset) != ERROR_NONE) | ||
| 254 | return ResultStatus::Error; | ||
| 255 | codeset->name = filename; | ||
| 256 | |||
| 257 | Kernel::g_current_process = Kernel::Process::Create(std::move(codeset)); | ||
| 235 | Kernel::g_current_process->svc_access_mask.set(); | 258 | Kernel::g_current_process->svc_access_mask.set(); |
| 236 | Kernel::g_current_process->address_mappings = default_address_mappings; | 259 | Kernel::g_current_process->address_mappings = default_address_mappings; |
| 237 | 260 | ||
| 238 | // Attach the default resource limit (APPLICATION) to the process | 261 | // Attach the default resource limit (APPLICATION) to the process |
| 239 | Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); | 262 | Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); |
| 240 | 263 | ||
| 241 | Load3DSXFile(*file, Memory::PROCESS_IMAGE_VADDR); | 264 | Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE); |
| 242 | |||
| 243 | Kernel::g_current_process->Run(Memory::PROCESS_IMAGE_VADDR, 48, Kernel::DEFAULT_STACK_SIZE); | ||
| 244 | 265 | ||
| 245 | is_loaded = true; | 266 | is_loaded = true; |
| 246 | return ResultStatus::Success; | 267 | return ResultStatus::Success; |
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index a7eea78aa..ca3c18a9f 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp | |||
| @@ -16,6 +16,9 @@ | |||
| 16 | #include "core/loader/elf.h" | 16 | #include "core/loader/elf.h" |
| 17 | #include "core/memory.h" | 17 | #include "core/memory.h" |
| 18 | 18 | ||
| 19 | using Kernel::SharedPtr; | ||
| 20 | using Kernel::CodeSet; | ||
| 21 | |||
| 19 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 22 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 20 | // ELF Header Constants | 23 | // ELF Header Constants |
| 21 | 24 | ||
| @@ -97,6 +100,12 @@ enum ElfSectionFlags | |||
| 97 | #define PT_LOPROC 0x70000000 | 100 | #define PT_LOPROC 0x70000000 |
| 98 | #define PT_HIPROC 0x7FFFFFFF | 101 | #define PT_HIPROC 0x7FFFFFFF |
| 99 | 102 | ||
| 103 | // Segment flags | ||
| 104 | #define PF_X 0x1 | ||
| 105 | #define PF_W 0x2 | ||
| 106 | #define PF_R 0x4 | ||
| 107 | #define PF_MASKPROC 0xF0000000 | ||
| 108 | |||
| 100 | typedef unsigned int Elf32_Addr; | 109 | typedef unsigned int Elf32_Addr; |
| 101 | typedef unsigned short Elf32_Half; | 110 | typedef unsigned short Elf32_Half; |
| 102 | typedef unsigned int Elf32_Off; | 111 | typedef unsigned int Elf32_Off; |
| @@ -193,7 +202,7 @@ public: | |||
| 193 | ElfMachine GetMachine() const { return (ElfMachine)(header->e_machine); } | 202 | ElfMachine GetMachine() const { return (ElfMachine)(header->e_machine); } |
| 194 | u32 GetEntryPoint() const { return entryPoint; } | 203 | u32 GetEntryPoint() const { return entryPoint; } |
| 195 | u32 GetFlags() const { return (u32)(header->e_flags); } | 204 | u32 GetFlags() const { return (u32)(header->e_flags); } |
| 196 | void LoadInto(u32 vaddr); | 205 | SharedPtr<CodeSet> LoadInto(u32 vaddr); |
| 197 | bool LoadSymbols(); | 206 | bool LoadSymbols(); |
| 198 | 207 | ||
| 199 | int GetNumSegments() const { return (int)(header->e_phnum); } | 208 | int GetNumSegments() const { return (int)(header->e_phnum); } |
| @@ -249,7 +258,7 @@ const char *ElfReader::GetSectionName(int section) const { | |||
| 249 | return nullptr; | 258 | return nullptr; |
| 250 | } | 259 | } |
| 251 | 260 | ||
| 252 | void ElfReader::LoadInto(u32 vaddr) { | 261 | SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) { |
| 253 | LOG_DEBUG(Loader, "String section: %i", header->e_shstrndx); | 262 | LOG_DEBUG(Loader, "String section: %i", header->e_shstrndx); |
| 254 | 263 | ||
| 255 | // Should we relocate? | 264 | // Should we relocate? |
| @@ -267,19 +276,61 @@ void ElfReader::LoadInto(u32 vaddr) { | |||
| 267 | u32 segment_addr[32]; | 276 | u32 segment_addr[32]; |
| 268 | u32 base_addr = relocate ? vaddr : 0; | 277 | u32 base_addr = relocate ? vaddr : 0; |
| 269 | 278 | ||
| 270 | for (unsigned i = 0; i < header->e_phnum; i++) { | 279 | u32 total_image_size = 0; |
| 271 | Elf32_Phdr* p = segments + i; | 280 | for (unsigned int i = 0; i < header->e_phnum; ++i) { |
| 272 | LOG_DEBUG(Loader, "Type: %i Vaddr: %08x Filesz: %i Memsz: %i ", p->p_type, p->p_vaddr, | 281 | Elf32_Phdr* p = &segments[i]; |
| 282 | if (p->p_type == PT_LOAD) { | ||
| 283 | total_image_size += (p->p_memsz + 0xFFF) & ~0xFFF; | ||
| 284 | } | ||
| 285 | } | ||
| 286 | |||
| 287 | std::vector<u8> program_image(total_image_size); | ||
| 288 | size_t current_image_position = 0; | ||
| 289 | |||
| 290 | SharedPtr<CodeSet> codeset = CodeSet::Create("", 0); | ||
| 291 | |||
| 292 | for (unsigned int i = 0; i < header->e_phnum; ++i) { | ||
| 293 | Elf32_Phdr* p = &segments[i]; | ||
| 294 | LOG_DEBUG(Loader, "Type: %i Vaddr: %08X Filesz: %8X Memsz: %8X ", p->p_type, p->p_vaddr, | ||
| 273 | p->p_filesz, p->p_memsz); | 295 | p->p_filesz, p->p_memsz); |
| 274 | 296 | ||
| 275 | if (p->p_type == PT_LOAD) { | 297 | if (p->p_type == PT_LOAD) { |
| 276 | segment_addr[i] = base_addr + p->p_vaddr; | 298 | CodeSet::Segment* codeset_segment; |
| 277 | memcpy(Memory::GetPointer(segment_addr[i]), GetSegmentPtr(i), p->p_filesz); | 299 | u32 permission_flags = p->p_flags & (PF_R | PF_W | PF_X); |
| 278 | LOG_DEBUG(Loader, "Loadable Segment Copied to %08x, size %08x", segment_addr[i], | 300 | if (permission_flags == (PF_R | PF_X)) { |
| 279 | p->p_memsz); | 301 | codeset_segment = &codeset->code; |
| 302 | } else if (permission_flags == (PF_R)) { | ||
| 303 | codeset_segment = &codeset->rodata; | ||
| 304 | } else if (permission_flags == (PF_R | PF_W)) { | ||
| 305 | codeset_segment = &codeset->data; | ||
| 306 | } else { | ||
| 307 | LOG_ERROR(Loader, "Unexpected ELF PT_LOAD segment id %u with flags %X", i, p->p_flags); | ||
| 308 | continue; | ||
| 309 | } | ||
| 310 | |||
| 311 | if (codeset_segment->size != 0) { | ||
| 312 | LOG_ERROR(Loader, "ELF has more than one segment of the same type. Skipping extra segment (id %i)", i); | ||
| 313 | continue; | ||
| 314 | } | ||
| 315 | |||
| 316 | u32 segment_addr = base_addr + p->p_vaddr; | ||
| 317 | u32 aligned_size = (p->p_memsz + 0xFFF) & ~0xFFF; | ||
| 318 | |||
| 319 | codeset_segment->offset = current_image_position; | ||
| 320 | codeset_segment->addr = segment_addr; | ||
| 321 | codeset_segment->size = aligned_size; | ||
| 322 | |||
| 323 | memcpy(&program_image[current_image_position], GetSegmentPtr(i), p->p_filesz); | ||
| 324 | current_image_position += aligned_size; | ||
| 280 | } | 325 | } |
| 281 | } | 326 | } |
| 327 | |||
| 328 | codeset->entrypoint = base_addr + header->e_entry; | ||
| 329 | codeset->memory = std::make_shared<std::vector<u8>>(std::move(program_image)); | ||
| 330 | |||
| 282 | LOG_DEBUG(Loader, "Done loading."); | 331 | LOG_DEBUG(Loader, "Done loading."); |
| 332 | |||
| 333 | return codeset; | ||
| 283 | } | 334 | } |
| 284 | 335 | ||
| 285 | SectionID ElfReader::GetSectionByName(const char *name, int firstSection) const { | 336 | SectionID ElfReader::GetSectionByName(const char *name, int firstSection) const { |
| @@ -352,18 +403,18 @@ ResultStatus AppLoader_ELF::Load() { | |||
| 352 | if (file->ReadBytes(&buffer[0], size) != size) | 403 | if (file->ReadBytes(&buffer[0], size) != size) |
| 353 | return ResultStatus::Error; | 404 | return ResultStatus::Error; |
| 354 | 405 | ||
| 355 | Kernel::g_current_process = Kernel::Process::Create(filename, 0); | 406 | ElfReader elf_reader(&buffer[0]); |
| 407 | SharedPtr<CodeSet> codeset = elf_reader.LoadInto(Memory::PROCESS_IMAGE_VADDR); | ||
| 408 | codeset->name = filename; | ||
| 409 | |||
| 410 | Kernel::g_current_process = Kernel::Process::Create(std::move(codeset)); | ||
| 356 | Kernel::g_current_process->svc_access_mask.set(); | 411 | Kernel::g_current_process->svc_access_mask.set(); |
| 357 | Kernel::g_current_process->address_mappings = default_address_mappings; | 412 | Kernel::g_current_process->address_mappings = default_address_mappings; |
| 358 | 413 | ||
| 359 | // Attach the default resource limit (APPLICATION) to the process | 414 | // Attach the default resource limit (APPLICATION) to the process |
| 360 | Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); | 415 | Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); |
| 361 | 416 | ||
| 362 | ElfReader elf_reader(&buffer[0]); | 417 | Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE); |
| 363 | elf_reader.LoadInto(Memory::PROCESS_IMAGE_VADDR); | ||
| 364 | // TODO: Fill application title | ||
| 365 | |||
| 366 | Kernel::g_current_process->Run(elf_reader.GetEntryPoint(), 48, Kernel::DEFAULT_STACK_SIZE); | ||
| 367 | 418 | ||
| 368 | is_loaded = true; | 419 | is_loaded = true; |
| 369 | return ResultStatus::Success; | 420 | return ResultStatus::Success; |
diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index 2b26b31cf..87603d198 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp | |||
| @@ -118,6 +118,9 @@ FileType AppLoader_NCCH::IdentifyType(FileUtil::IOFile& file) { | |||
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | ResultStatus AppLoader_NCCH::LoadExec() const { | 120 | ResultStatus AppLoader_NCCH::LoadExec() const { |
| 121 | using Kernel::SharedPtr; | ||
| 122 | using Kernel::CodeSet; | ||
| 123 | |||
| 121 | if (!is_loaded) | 124 | if (!is_loaded) |
| 122 | return ResultStatus::ErrorNotLoaded; | 125 | return ResultStatus::ErrorNotLoaded; |
| 123 | 126 | ||
| @@ -126,7 +129,30 @@ ResultStatus AppLoader_NCCH::LoadExec() const { | |||
| 126 | std::string process_name = Common::StringFromFixedZeroTerminatedBuffer( | 129 | std::string process_name = Common::StringFromFixedZeroTerminatedBuffer( |
| 127 | (const char*)exheader_header.codeset_info.name, 8); | 130 | (const char*)exheader_header.codeset_info.name, 8); |
| 128 | u64 program_id = *reinterpret_cast<u64_le const*>(&ncch_header.program_id[0]); | 131 | u64 program_id = *reinterpret_cast<u64_le const*>(&ncch_header.program_id[0]); |
| 129 | Kernel::g_current_process = Kernel::Process::Create(process_name, program_id); | 132 | |
| 133 | SharedPtr<CodeSet> codeset = CodeSet::Create(process_name, program_id); | ||
| 134 | |||
| 135 | codeset->code.offset = 0; | ||
| 136 | codeset->code.addr = exheader_header.codeset_info.text.address; | ||
| 137 | codeset->code.size = exheader_header.codeset_info.text.num_max_pages * Memory::PAGE_SIZE; | ||
| 138 | |||
| 139 | codeset->rodata.offset = codeset->code.offset + codeset->code.size; | ||
| 140 | codeset->rodata.addr = exheader_header.codeset_info.ro.address; | ||
| 141 | codeset->rodata.size = exheader_header.codeset_info.ro.num_max_pages * Memory::PAGE_SIZE; | ||
| 142 | |||
| 143 | // TODO(yuriks): Not sure if the bss size is added to the page-aligned .data size or just | ||
| 144 | // to the regular size. Playing it safe for now. | ||
| 145 | u32 bss_page_size = (exheader_header.codeset_info.bss_size + 0xFFF) & ~0xFFF; | ||
| 146 | code.resize(code.size() + bss_page_size, 0); | ||
| 147 | |||
| 148 | codeset->data.offset = codeset->rodata.offset + codeset->rodata.size; | ||
| 149 | codeset->data.addr = exheader_header.codeset_info.data.address; | ||
| 150 | codeset->data.size = exheader_header.codeset_info.data.num_max_pages * Memory::PAGE_SIZE + bss_page_size; | ||
| 151 | |||
| 152 | codeset->entrypoint = codeset->code.addr; | ||
| 153 | codeset->memory = std::make_shared<std::vector<u8>>(std::move(code)); | ||
| 154 | |||
| 155 | Kernel::g_current_process = Kernel::Process::Create(std::move(codeset)); | ||
| 130 | 156 | ||
| 131 | // Attach a resource limit to the process based on the resource limit category | 157 | // Attach a resource limit to the process based on the resource limit category |
| 132 | Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory( | 158 | Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory( |
| @@ -137,11 +163,9 @@ ResultStatus AppLoader_NCCH::LoadExec() const { | |||
| 137 | std::copy_n(exheader_header.arm11_kernel_caps.descriptors, kernel_caps.size(), begin(kernel_caps)); | 163 | std::copy_n(exheader_header.arm11_kernel_caps.descriptors, kernel_caps.size(), begin(kernel_caps)); |
| 138 | Kernel::g_current_process->ParseKernelCaps(kernel_caps.data(), kernel_caps.size()); | 164 | Kernel::g_current_process->ParseKernelCaps(kernel_caps.data(), kernel_caps.size()); |
| 139 | 165 | ||
| 140 | Memory::WriteBlock(entry_point, &code[0], code.size()); | ||
| 141 | |||
| 142 | s32 priority = exheader_header.arm11_system_local_caps.priority; | 166 | s32 priority = exheader_header.arm11_system_local_caps.priority; |
| 143 | u32 stack_size = exheader_header.codeset_info.stack_size; | 167 | u32 stack_size = exheader_header.codeset_info.stack_size; |
| 144 | Kernel::g_current_process->Run(entry_point, priority, stack_size); | 168 | Kernel::g_current_process->Run(priority, stack_size); |
| 145 | return ResultStatus::Success; | 169 | return ResultStatus::Success; |
| 146 | } | 170 | } |
| 147 | return ResultStatus::Error; | 171 | return ResultStatus::Error; |
diff --git a/src/core/mem_map.cpp b/src/core/mem_map.cpp index d8cae50dd..cbe993fbe 100644 --- a/src/core/mem_map.cpp +++ b/src/core/mem_map.cpp | |||
| @@ -32,7 +32,6 @@ struct MemoryArea { | |||
| 32 | 32 | ||
| 33 | // We don't declare the IO regions in here since its handled by other means. | 33 | // We don't declare the IO regions in here since its handled by other means. |
| 34 | static MemoryArea memory_areas[] = { | 34 | static MemoryArea memory_areas[] = { |
| 35 | {PROCESS_IMAGE_VADDR, PROCESS_IMAGE_MAX_SIZE, "Process Image"}, // ExeFS:/.code is loaded here | ||
| 36 | {HEAP_VADDR, HEAP_SIZE, "Heap"}, // Application heap (main memory) | 35 | {HEAP_VADDR, HEAP_SIZE, "Heap"}, // Application heap (main memory) |
| 37 | {SHARED_MEMORY_VADDR, SHARED_MEMORY_SIZE, "Shared Memory"}, // Shared memory | 36 | {SHARED_MEMORY_VADDR, SHARED_MEMORY_SIZE, "Shared Memory"}, // Shared memory |
| 38 | {LINEAR_HEAP_VADDR, LINEAR_HEAP_SIZE, "Linear Heap"}, // Linear heap (main memory) | 37 | {LINEAR_HEAP_VADDR, LINEAR_HEAP_SIZE, "Linear Heap"}, // Linear heap (main memory) |
| @@ -132,13 +131,13 @@ VAddr PhysicalToVirtualAddress(const PAddr addr) { | |||
| 132 | return addr | 0x80000000; | 131 | return addr | 0x80000000; |
| 133 | } | 132 | } |
| 134 | 133 | ||
| 135 | // TODO(yuriks): Move this into Process | ||
| 136 | static Kernel::VMManager address_space; | ||
| 137 | |||
| 138 | void Init() { | 134 | void Init() { |
| 139 | using namespace Kernel; | ||
| 140 | |||
| 141 | InitMemoryMap(); | 135 | InitMemoryMap(); |
| 136 | LOG_DEBUG(HW_Memory, "initialized OK"); | ||
| 137 | } | ||
| 138 | |||
| 139 | void InitLegacyAddressSpace(Kernel::VMManager& address_space) { | ||
| 140 | using namespace Kernel; | ||
| 142 | 141 | ||
| 143 | for (MemoryArea& area : memory_areas) { | 142 | for (MemoryArea& area : memory_areas) { |
| 144 | auto block = std::make_shared<std::vector<u8>>(area.size); | 143 | auto block = std::make_shared<std::vector<u8>>(area.size); |
| @@ -152,14 +151,11 @@ void Init() { | |||
| 152 | auto shared_page_vma = address_space.MapBackingMemory(SHARED_PAGE_VADDR, | 151 | auto shared_page_vma = address_space.MapBackingMemory(SHARED_PAGE_VADDR, |
| 153 | (u8*)&SharedPage::shared_page, SHARED_PAGE_SIZE, MemoryState::Shared).MoveFrom(); | 152 | (u8*)&SharedPage::shared_page, SHARED_PAGE_SIZE, MemoryState::Shared).MoveFrom(); |
| 154 | address_space.Reprotect(shared_page_vma, VMAPermission::Read); | 153 | address_space.Reprotect(shared_page_vma, VMAPermission::Read); |
| 155 | |||
| 156 | LOG_DEBUG(HW_Memory, "initialized OK"); | ||
| 157 | } | 154 | } |
| 158 | 155 | ||
| 159 | void Shutdown() { | 156 | void Shutdown() { |
| 160 | heap_map.clear(); | 157 | heap_map.clear(); |
| 161 | heap_linear_map.clear(); | 158 | heap_linear_map.clear(); |
| 162 | address_space.Reset(); | ||
| 163 | 159 | ||
| 164 | LOG_DEBUG(HW_Memory, "shutdown OK"); | 160 | LOG_DEBUG(HW_Memory, "shutdown OK"); |
| 165 | } | 161 | } |
diff --git a/src/core/mem_map.h b/src/core/mem_map.h index ba50914a8..229ef82c5 100644 --- a/src/core/mem_map.h +++ b/src/core/mem_map.h | |||
| @@ -6,9 +6,14 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | 8 | ||
| 9 | namespace Kernel { | ||
| 10 | class VMManager; | ||
| 11 | } | ||
| 12 | |||
| 9 | namespace Memory { | 13 | namespace Memory { |
| 10 | 14 | ||
| 11 | void Init(); | 15 | void Init(); |
| 16 | void InitLegacyAddressSpace(Kernel::VMManager& address_space); | ||
| 12 | void Shutdown(); | 17 | void Shutdown(); |
| 13 | 18 | ||
| 14 | /** | 19 | /** |
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 172ae9054..1f66bb27d 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -59,14 +59,12 @@ static void MapPages(u32 base, u32 size, u8* memory, PageType type) { | |||
| 59 | while (base != end) { | 59 | while (base != end) { |
| 60 | ASSERT_MSG(base < PageTable::NUM_ENTRIES, "out of range mapping at %08X", base); | 60 | ASSERT_MSG(base < PageTable::NUM_ENTRIES, "out of range mapping at %08X", base); |
| 61 | 61 | ||
| 62 | if (current_page_table->attributes[base] != PageType::Unmapped && type != PageType::Unmapped) { | ||
| 63 | LOG_ERROR(HW_Memory, "overlapping memory ranges at %08X", base * PAGE_SIZE); | ||
| 64 | } | ||
| 65 | current_page_table->attributes[base] = type; | 62 | current_page_table->attributes[base] = type; |
| 66 | current_page_table->pointers[base] = memory; | 63 | current_page_table->pointers[base] = memory; |
| 67 | 64 | ||
| 68 | base += 1; | 65 | base += 1; |
| 69 | memory += PAGE_SIZE; | 66 | if (memory != nullptr) |
| 67 | memory += PAGE_SIZE; | ||
| 70 | } | 68 | } |
| 71 | } | 69 | } |
| 72 | 70 | ||