diff options
| author | 2018-12-19 23:50:20 -0500 | |
|---|---|---|
| committer | 2018-12-21 07:05:34 -0500 | |
| commit | 002ae08bbd3e5e851d8a682203462efbcf59e3dd (patch) | |
| tree | 231239717b1035634a2d6ec5d09622fd7a5c6f4b /src/core/hle/kernel | |
| parent | kernel/process_capability: Handle debug capability flags (diff) | |
| download | yuzu-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.cpp | 80 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.h | 58 |
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 | ||
| 67 | void Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) { | 65 | ResultCode 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 | |||
| 74 | void 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 | ||
| 146 | void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) { | 76 | void 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 | ||
| 45 | union 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. |