summaryrefslogtreecommitdiff
path: root/src
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
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')
-rw-r--r--src/core/file_sys/program_metadata.cpp11
-rw-r--r--src/core/file_sys/program_metadata.h6
-rw-r--r--src/core/hle/kernel/process.cpp80
-rw-r--r--src/core/hle/kernel/process.h58
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp5
-rw-r--r--src/core/loader/loader.cpp4
-rw-r--r--src/core/loader/loader.h2
7 files changed, 44 insertions, 122 deletions
diff --git a/src/core/file_sys/program_metadata.cpp b/src/core/file_sys/program_metadata.cpp
index 8903ed1d3..e90c8c2de 100644
--- a/src/core/file_sys/program_metadata.cpp
+++ b/src/core/file_sys/program_metadata.cpp
@@ -40,6 +40,13 @@ Loader::ResultStatus ProgramMetadata::Load(VirtualFile file) {
40 if (sizeof(FileAccessHeader) != file->ReadObject(&aci_file_access, aci_header.fah_offset)) 40 if (sizeof(FileAccessHeader) != file->ReadObject(&aci_file_access, aci_header.fah_offset))
41 return Loader::ResultStatus::ErrorBadFileAccessHeader; 41 return Loader::ResultStatus::ErrorBadFileAccessHeader;
42 42
43 aci_kernel_capabilities.resize(aci_header.kac_size / sizeof(u32));
44 const u64 read_size = aci_header.kac_size;
45 const u64 read_offset = npdm_header.aci_offset + aci_header.kac_offset;
46 if (file->ReadBytes(aci_kernel_capabilities.data(), read_size, read_offset) != read_size) {
47 return Loader::ResultStatus::ErrorBadKernelCapabilityDescriptors;
48 }
49
43 return Loader::ResultStatus::Success; 50 return Loader::ResultStatus::Success;
44} 51}
45 52
@@ -71,6 +78,10 @@ u64 ProgramMetadata::GetFilesystemPermissions() const {
71 return aci_file_access.permissions; 78 return aci_file_access.permissions;
72} 79}
73 80
81const ProgramMetadata::KernelCapabilityDescriptors& ProgramMetadata::GetKernelCapabilities() const {
82 return aci_kernel_capabilities;
83}
84
74void ProgramMetadata::Print() const { 85void ProgramMetadata::Print() const {
75 LOG_DEBUG(Service_FS, "Magic: {:.4}", npdm_header.magic.data()); 86 LOG_DEBUG(Service_FS, "Magic: {:.4}", npdm_header.magic.data());
76 LOG_DEBUG(Service_FS, "Main thread priority: 0x{:02X}", npdm_header.main_thread_priority); 87 LOG_DEBUG(Service_FS, "Main thread priority: 0x{:02X}", npdm_header.main_thread_priority);
diff --git a/src/core/file_sys/program_metadata.h b/src/core/file_sys/program_metadata.h
index e4470d6f0..0033ba347 100644
--- a/src/core/file_sys/program_metadata.h
+++ b/src/core/file_sys/program_metadata.h
@@ -5,6 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8#include <vector>
8#include "common/bit_field.h" 9#include "common/bit_field.h"
9#include "common/common_types.h" 10#include "common/common_types.h"
10#include "common/swap.h" 11#include "common/swap.h"
@@ -38,6 +39,8 @@ enum class ProgramFilePermission : u64 {
38 */ 39 */
39class ProgramMetadata { 40class ProgramMetadata {
40public: 41public:
42 using KernelCapabilityDescriptors = std::vector<u32>;
43
41 ProgramMetadata(); 44 ProgramMetadata();
42 ~ProgramMetadata(); 45 ~ProgramMetadata();
43 46
@@ -50,6 +53,7 @@ public:
50 u32 GetMainThreadStackSize() const; 53 u32 GetMainThreadStackSize() const;
51 u64 GetTitleID() const; 54 u64 GetTitleID() const;
52 u64 GetFilesystemPermissions() const; 55 u64 GetFilesystemPermissions() const;
56 const KernelCapabilityDescriptors& GetKernelCapabilities() const;
53 57
54 void Print() const; 58 void Print() const;
55 59
@@ -154,6 +158,8 @@ private:
154 158
155 FileAccessControl acid_file_access; 159 FileAccessControl acid_file_access;
156 FileAccessHeader aci_file_access; 160 FileAccessHeader aci_file_access;
161
162 KernelCapabilityDescriptors aci_kernel_capabilities;
157}; 163};
158 164
159} // namespace FileSys 165} // namespace FileSys
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.
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index ac04d72d7..07aa7a1cd 100644
--- a/src/core/loader/deconstructed_rom_directory.cpp
+++ b/src/core/loader/deconstructed_rom_directory.cpp
@@ -129,7 +129,10 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(Kernel::Process& process)
129 return ResultStatus::Error32BitISA; 129 return ResultStatus::Error32BitISA;
130 } 130 }
131 131
132 process.LoadFromMetadata(metadata); 132 if (process.LoadFromMetadata(metadata).IsError()) {
133 return ResultStatus::ErrorUnableToParseKernelMetadata;
134 }
135
133 const FileSys::PatchManager pm(metadata.GetTitleID()); 136 const FileSys::PatchManager pm(metadata.GetTitleID());
134 137
135 // Load NSO modules 138 // Load NSO modules
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp
index 9cd0b0ccd..d8cc30959 100644
--- a/src/core/loader/loader.cpp
+++ b/src/core/loader/loader.cpp
@@ -93,7 +93,7 @@ std::string GetFileTypeString(FileType type) {
93 return "unknown"; 93 return "unknown";
94} 94}
95 95
96constexpr std::array<const char*, 60> RESULT_MESSAGES{ 96constexpr std::array<const char*, 62> RESULT_MESSAGES{
97 "The operation completed successfully.", 97 "The operation completed successfully.",
98 "The loader requested to load is already loaded.", 98 "The loader requested to load is already loaded.",
99 "The operation is not implemented.", 99 "The operation is not implemented.",
@@ -103,6 +103,7 @@ constexpr std::array<const char*, 60> RESULT_MESSAGES{
103 "The NPDM has a bad ACI header,", 103 "The NPDM has a bad ACI header,",
104 "The NPDM file has a bad file access control.", 104 "The NPDM file has a bad file access control.",
105 "The NPDM has a bad file access header.", 105 "The NPDM has a bad file access header.",
106 "The NPDM has bad kernel capability descriptors.",
106 "The PFS/HFS partition has a bad header.", 107 "The PFS/HFS partition has a bad header.",
107 "The PFS/HFS partition has incorrect size as determined by the header.", 108 "The PFS/HFS partition has incorrect size as determined by the header.",
108 "The NCA file has a bad header.", 109 "The NCA file has a bad header.",
@@ -125,6 +126,7 @@ constexpr std::array<const char*, 60> RESULT_MESSAGES{
125 "The file could not be found or does not exist.", 126 "The file could not be found or does not exist.",
126 "The game is missing a program metadata file (main.npdm).", 127 "The game is missing a program metadata file (main.npdm).",
127 "The game uses the currently-unimplemented 32-bit architecture.", 128 "The game uses the currently-unimplemented 32-bit architecture.",
129 "Unable to completely parse the kernel metadata when loading the emulated process",
128 "The RomFS could not be found.", 130 "The RomFS could not be found.",
129 "The ELF file has incorrect size as determined by the header.", 131 "The ELF file has incorrect size as determined by the header.",
130 "There was a general error loading the NRO into emulated memory.", 132 "There was a general error loading the NRO into emulated memory.",
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index 0838e303b..a39cb812d 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -67,6 +67,7 @@ enum class ResultStatus : u16 {
67 ErrorBadACIHeader, 67 ErrorBadACIHeader,
68 ErrorBadFileAccessControl, 68 ErrorBadFileAccessControl,
69 ErrorBadFileAccessHeader, 69 ErrorBadFileAccessHeader,
70 ErrorBadKernelCapabilityDescriptors,
70 ErrorBadPFSHeader, 71 ErrorBadPFSHeader,
71 ErrorIncorrectPFSFileSize, 72 ErrorIncorrectPFSFileSize,
72 ErrorBadNCAHeader, 73 ErrorBadNCAHeader,
@@ -89,6 +90,7 @@ enum class ResultStatus : u16 {
89 ErrorNullFile, 90 ErrorNullFile,
90 ErrorMissingNPDM, 91 ErrorMissingNPDM,
91 Error32BitISA, 92 Error32BitISA,
93 ErrorUnableToParseKernelMetadata,
92 ErrorNoRomFS, 94 ErrorNoRomFS,
93 ErrorIncorrectELFFileSize, 95 ErrorIncorrectELFFileSize,
94 ErrorLoadingNRO, 96 ErrorLoadingNRO,