summaryrefslogtreecommitdiff
path: root/src/core/hle
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner2015-07-11 20:07:49 -0700
committerGravatar Yuri Kunde Schlesner2015-07-11 20:07:49 -0700
commit4e900d56f3dd2b5c9871b523689322028123d891 (patch)
tree2b233263cff7c001506f660373e2364c8e702637 /src/core/hle
parentMerge pull request #914 from yuriks/bitfield-mask (diff)
parentCore: Properly configure address space when loading a binary (diff)
downloadyuzu-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.cpp2
-rw-r--r--src/core/hle/kernel/event.h1
-rw-r--r--src/core/hle/kernel/kernel.h1
-rw-r--r--src/core/hle/kernel/process.cpp38
-rw-r--r--src/core/hle/kernel/process.h43
-rw-r--r--src/core/hle/kernel/vm_manager.cpp14
-rw-r--r--src/core/hle/kernel/vm_manager.h6
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
52enum { 53enum {
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
14namespace Kernel { 17namespace Kernel {
15 18
19SharedPtr<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
28CodeSet::CodeSet() {}
29CodeSet::~CodeSet() {}
30
16u32 Process::next_process_id; 31u32 Process::next_process_id;
17 32
18SharedPtr<Process> Process::Create(std::string name, u64 program_id) { 33SharedPtr<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
90void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) { 105void 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
94Kernel::Process::Process() {} 120Kernel::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
49class ResourceLimit; 49class ResourceLimit;
50class VMManager;
51
52struct 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
77private:
78 CodeSet();
79 ~CodeSet() override;
80};
50 81
51class Process final : public Object { 82class Process final : public Object {
52public: 83public:
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
96private: 125private:
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
38VMManager::~VMManager() {
39 Reset();
40}
41
38void VMManager::Reset() { 42void 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
137void 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
133VMManager::VMAIter VMManager::StripIterConstness(const VMAHandle & iter) { 147VMManager::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 */
104class VMManager { 104class VMManager final {
105 // TODO(yuriks): Make page tables switchable to support multiple VMManagers 105 // TODO(yuriks): Make page tables switchable to support multiple VMManagers
106public: 106public:
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
171private: 175private:
172 using VMAIter = decltype(vma_map)::iterator; 176 using VMAIter = decltype(vma_map)::iterator;
173 177