summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
authorGravatar Lioncash2018-12-19 23:50:20 -0500
committerGravatar Lioncash2018-12-21 07:05:34 -0500
commit002ae08bbd3e5e851d8a682203462efbcf59e3dd (patch)
tree231239717b1035634a2d6ec5d09622fd7a5c6f4b /src/core/hle/kernel
parentkernel/process_capability: Handle debug capability flags (diff)
downloadyuzu-002ae08bbd3e5e851d8a682203462efbcf59e3dd.tar.gz
yuzu-002ae08bbd3e5e851d8a682203462efbcf59e3dd.tar.xz
yuzu-002ae08bbd3e5e851d8a682203462efbcf59e3dd.zip
kernel/process: Hook up the process capability parser to the process itself
While we're at it, we can also toss out the leftover capability parsing from Citra.
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/process.cpp80
-rw-r--r--src/core/hle/kernel/process.h58
2 files changed, 18 insertions, 120 deletions
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 5356a4a3f..4f209a979 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -28,13 +28,11 @@ SharedPtr<Process> Process::Create(KernelCore& kernel, std::string&& name) {
28 SharedPtr<Process> process(new Process(kernel)); 28 SharedPtr<Process> process(new Process(kernel));
29 29
30 process->name = std::move(name); 30 process->name = std::move(name);
31 process->flags.raw = 0;
32 process->flags.memory_region.Assign(MemoryRegion::APPLICATION);
33 process->resource_limit = kernel.GetSystemResourceLimit(); 31 process->resource_limit = kernel.GetSystemResourceLimit();
34 process->status = ProcessStatus::Created; 32 process->status = ProcessStatus::Created;
35 process->program_id = 0; 33 process->program_id = 0;
36 process->process_id = kernel.CreateNewProcessID(); 34 process->process_id = kernel.CreateNewProcessID();
37 process->svc_access_mask.set(); 35 process->capabilities.InitializeForMetadatalessProcess();
38 36
39 std::mt19937 rng(Settings::values.rng_seed.value_or(0)); 37 std::mt19937 rng(Settings::values.rng_seed.value_or(0));
40 std::uniform_int_distribution<u64> distribution; 38 std::uniform_int_distribution<u64> distribution;
@@ -64,83 +62,15 @@ ResultCode Process::ClearSignalState() {
64 return RESULT_SUCCESS; 62 return RESULT_SUCCESS;
65} 63}
66 64
67void Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) { 65ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) {
68 program_id = metadata.GetTitleID(); 66 program_id = metadata.GetTitleID();
69 ideal_processor = metadata.GetMainThreadCore(); 67 ideal_processor = metadata.GetMainThreadCore();
70 is_64bit_process = metadata.Is64BitProgram(); 68 is_64bit_process = metadata.Is64BitProgram();
71 vm_manager.Reset(metadata.GetAddressSpaceType());
72}
73
74void Process::ParseKernelCaps(const u32* kernel_caps, std::size_t len) {
75 for (std::size_t i = 0; i < len; ++i) {
76 u32 descriptor = kernel_caps[i];
77 u32 type = descriptor >> 20;
78
79 if (descriptor == 0xFFFFFFFF) {
80 // Unused descriptor entry
81 continue;
82 } else if ((type & 0xF00) == 0xE00) { // 0x0FFF
83 // Allowed interrupts list
84 LOG_WARNING(Loader, "ExHeader allowed interrupts list ignored");
85 } else if ((type & 0xF80) == 0xF00) { // 0x07FF
86 // Allowed syscalls mask
87 unsigned int index = ((descriptor >> 24) & 7) * 24;
88 u32 bits = descriptor & 0xFFFFFF;
89
90 while (bits && index < svc_access_mask.size()) {
91 svc_access_mask.set(index, bits & 1);
92 ++index;
93 bits >>= 1;
94 }
95 } else if ((type & 0xFF0) == 0xFE0) { // 0x00FF
96 // Handle table size
97 handle_table_size = descriptor & 0x3FF;
98 } else if ((type & 0xFF8) == 0xFF0) { // 0x007F
99 // Misc. flags
100 flags.raw = descriptor & 0xFFFF;
101 } else if ((type & 0xFFE) == 0xFF8) { // 0x001F
102 // Mapped memory range
103 if (i + 1 >= len || ((kernel_caps[i + 1] >> 20) & 0xFFE) != 0xFF8) {
104 LOG_WARNING(Loader, "Incomplete exheader memory range descriptor ignored.");
105 continue;
106 }
107 u32 end_desc = kernel_caps[i + 1];
108 ++i; // Skip over the second descriptor on the next iteration
109 69
110 AddressMapping mapping; 70 vm_manager.Reset(metadata.GetAddressSpaceType());
111 mapping.address = descriptor << 12;
112 VAddr end_address = end_desc << 12;
113
114 if (mapping.address < end_address) {
115 mapping.size = end_address - mapping.address;
116 } else {
117 mapping.size = 0;
118 }
119 71
120 mapping.read_only = (descriptor & (1 << 20)) != 0; 72 const auto& caps = metadata.GetKernelCapabilities();
121 mapping.unk_flag = (end_desc & (1 << 20)) != 0; 73 return capabilities.InitializeForUserProcess(caps.data(), caps.size(), vm_manager);
122
123 address_mappings.push_back(mapping);
124 } else if ((type & 0xFFF) == 0xFFE) { // 0x000F
125 // Mapped memory page
126 AddressMapping mapping;
127 mapping.address = descriptor << 12;
128 mapping.size = Memory::PAGE_SIZE;
129 mapping.read_only = false;
130 mapping.unk_flag = false;
131
132 address_mappings.push_back(mapping);
133 } else if ((type & 0xFE0) == 0xFC0) { // 0x01FF
134 // Kernel version
135 kernel_version = descriptor & 0xFFFF;
136
137 int minor = kernel_version & 0xFF;
138 int major = (kernel_version >> 8) & 0xFF;
139 LOG_INFO(Loader, "ExHeader kernel version: {}.{}", major, minor);
140 } else {
141 LOG_ERROR(Loader, "Unhandled kernel caps descriptor: 0x{:08X}", descriptor);
142 }
143 }
144} 74}
145 75
146void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) { 76void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) {
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index 459eedfa6..f6fb72770 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -11,9 +11,9 @@
11#include <string> 11#include <string>
12#include <vector> 12#include <vector>
13#include <boost/container/static_vector.hpp> 13#include <boost/container/static_vector.hpp>
14#include "common/bit_field.h"
15#include "common/common_types.h" 14#include "common/common_types.h"
16#include "core/hle/kernel/handle_table.h" 15#include "core/hle/kernel/handle_table.h"
16#include "core/hle/kernel/process_capability.h"
17#include "core/hle/kernel/thread.h" 17#include "core/hle/kernel/thread.h"
18#include "core/hle/kernel/vm_manager.h" 18#include "core/hle/kernel/vm_manager.h"
19#include "core/hle/kernel/wait_object.h" 19#include "core/hle/kernel/wait_object.h"
@@ -42,24 +42,6 @@ enum class MemoryRegion : u16 {
42 BASE = 3, 42 BASE = 3,
43}; 43};
44 44
45union ProcessFlags {
46 u16 raw;
47
48 BitField<0, 1, u16>
49 allow_debug; ///< Allows other processes to attach to and debug this process.
50 BitField<1, 1, u16> force_debug; ///< Allows this process to attach to processes even if they
51 /// don't have allow_debug set.
52 BitField<2, 1, u16> allow_nonalphanum;
53 BitField<3, 1, u16> shared_page_writable; ///< Shared page is mapped with write permissions.
54 BitField<4, 1, u16> privileged_priority; ///< Can use priority levels higher than 24.
55 BitField<5, 1, u16> allow_main_args;
56 BitField<6, 1, u16> shared_device_mem;
57 BitField<7, 1, u16> runnable_on_sleep;
58 BitField<8, 4, MemoryRegion>
59 memory_region; ///< Default region for memory allocations for this process
60 BitField<12, 1, u16> loaded_high; ///< Application loaded high (not at 0x00100000).
61};
62
63/** 45/**
64 * Indicates the status of a Process instance. 46 * Indicates the status of a Process instance.
65 * 47 *
@@ -180,13 +162,13 @@ public:
180 } 162 }
181 163
182 /// Gets the bitmask of allowed CPUs that this process' threads can run on. 164 /// Gets the bitmask of allowed CPUs that this process' threads can run on.
183 u32 GetAllowedProcessorMask() const { 165 u64 GetAllowedProcessorMask() const {
184 return allowed_processor_mask; 166 return capabilities.GetCoreMask();
185 } 167 }
186 168
187 /// Gets the bitmask of allowed thread priorities. 169 /// Gets the bitmask of allowed thread priorities.
188 u32 GetAllowedThreadPriorityMask() const { 170 u64 GetAllowedThreadPriorityMask() const {
189 return allowed_thread_priority_mask; 171 return capabilities.GetPriorityMask();
190 } 172 }
191 173
192 u32 IsVirtualMemoryEnabled() const { 174 u32 IsVirtualMemoryEnabled() const {
@@ -227,15 +209,12 @@ public:
227 * Loads process-specifics configuration info with metadata provided 209 * Loads process-specifics configuration info with metadata provided
228 * by an executable. 210 * by an executable.
229 * 211 *
230 * @param metadata The provided metadata to load process specific info. 212 * @param metadata The provided metadata to load process specific info from.
231 */ 213 *
232 void LoadFromMetadata(const FileSys::ProgramMetadata& metadata); 214 * @returns RESULT_SUCCESS if all relevant metadata was able to be
233 215 * loaded and parsed. Otherwise, an error code is returned.
234 /**
235 * Parses a list of kernel capability descriptors (as found in the ExHeader) and applies them
236 * to this process.
237 */ 216 */
238 void ParseKernelCaps(const u32* kernel_caps, std::size_t len); 217 ResultCode LoadFromMetadata(const FileSys::ProgramMetadata& metadata);
239 218
240 /** 219 /**
241 * Applies address space changes and launches the process main thread. 220 * Applies address space changes and launches the process main thread.
@@ -296,22 +275,8 @@ private:
296 /// Resource limit descriptor for this process 275 /// Resource limit descriptor for this process
297 SharedPtr<ResourceLimit> resource_limit; 276 SharedPtr<ResourceLimit> resource_limit;
298 277
299 /// The process may only call SVCs which have the corresponding bit set.
300 std::bitset<0x80> svc_access_mask;
301 /// Maximum size of the handle table for the process.
302 u32 handle_table_size = 0x200;
303 /// Special memory ranges mapped into this processes address space. This is used to give
304 /// processes access to specific I/O regions and device memory.
305 boost::container::static_vector<AddressMapping, 8> address_mappings;
306 ProcessFlags flags;
307 /// Kernel compatibility version for this process
308 u16 kernel_version = 0;
309 /// The default CPU for this process, threads are scheduled on this cpu by default. 278 /// The default CPU for this process, threads are scheduled on this cpu by default.
310 u8 ideal_processor = 0; 279 u8 ideal_processor = 0;
311 /// Bitmask of allowed CPUs that this process' threads can run on. TODO(Subv): Actually parse
312 /// this value from the process header.
313 u32 allowed_processor_mask = THREADPROCESSORID_DEFAULT_MASK;
314 u32 allowed_thread_priority_mask = 0xFFFFFFFF;
315 u32 is_virtual_address_memory_enabled = 0; 280 u32 is_virtual_address_memory_enabled = 0;
316 281
317 /// The Thread Local Storage area is allocated as processes create threads, 282 /// The Thread Local Storage area is allocated as processes create threads,
@@ -321,6 +286,9 @@ private:
321 /// This vector will grow as more pages are allocated for new threads. 286 /// This vector will grow as more pages are allocated for new threads.
322 std::vector<std::bitset<8>> tls_slots; 287 std::vector<std::bitset<8>> tls_slots;
323 288
289 /// Contains the parsed process capability descriptors.
290 ProcessCapabilities capabilities;
291
324 /// Whether or not this process is AArch64, or AArch32. 292 /// Whether or not this process is AArch64, or AArch32.
325 /// By default, we currently assume this is true, unless otherwise 293 /// By default, we currently assume this is true, unless otherwise
326 /// specified by metadata provided to the process during loading. 294 /// specified by metadata provided to the process during loading.