diff options
| author | 2015-07-11 20:07:49 -0700 | |
|---|---|---|
| committer | 2015-07-11 20:07:49 -0700 | |
| commit | 4e900d56f3dd2b5c9871b523689322028123d891 (patch) | |
| tree | 2b233263cff7c001506f660373e2364c8e702637 /src/core/hle | |
| parent | Merge pull request #914 from yuriks/bitfield-mask (diff) | |
| parent | Core: Properly configure address space when loading a binary (diff) | |
| download | yuzu-4e900d56f3dd2b5c9871b523689322028123d891.tar.gz yuzu-4e900d56f3dd2b5c9871b523689322028123d891.tar.xz yuzu-4e900d56f3dd2b5c9871b523689322028123d891.zip | |
Merge pull request #912 from yuriks/process-loading
Core: Properly configure address space during binary loading
Diffstat (limited to 'src/core/hle')
| -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 |
7 files changed, 89 insertions, 16 deletions
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 | ||