diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/errors.h | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/handle_table.h | 6 | ||||
| -rw-r--r-- | src/core/hle/kernel/process_capability.cpp | 253 | ||||
| -rw-r--r-- | src/core/hle/kernel/process_capability.h | 209 |
5 files changed, 468 insertions, 3 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 882c9ab59..a7d5e4431 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -113,6 +113,8 @@ add_library(core STATIC | |||
| 113 | hle/kernel/object.h | 113 | hle/kernel/object.h |
| 114 | hle/kernel/process.cpp | 114 | hle/kernel/process.cpp |
| 115 | hle/kernel/process.h | 115 | hle/kernel/process.h |
| 116 | hle/kernel/process_capability.cpp | ||
| 117 | hle/kernel/process_capability.h | ||
| 116 | hle/kernel/readable_event.cpp | 118 | hle/kernel/readable_event.cpp |
| 117 | hle/kernel/readable_event.h | 119 | hle/kernel/readable_event.h |
| 118 | hle/kernel/resource_limit.cpp | 120 | hle/kernel/resource_limit.cpp |
diff --git a/src/core/hle/kernel/errors.h b/src/core/hle/kernel/errors.h index 8b58d701d..a3d725866 100644 --- a/src/core/hle/kernel/errors.h +++ b/src/core/hle/kernel/errors.h | |||
| @@ -11,6 +11,7 @@ namespace Kernel { | |||
| 11 | // Confirmed Switch kernel error codes | 11 | // Confirmed Switch kernel error codes |
| 12 | 12 | ||
| 13 | constexpr ResultCode ERR_MAX_CONNECTIONS_REACHED{ErrorModule::Kernel, 7}; | 13 | constexpr ResultCode ERR_MAX_CONNECTIONS_REACHED{ErrorModule::Kernel, 7}; |
| 14 | constexpr ResultCode ERR_INVALID_CAPABILITY_DESCRIPTOR{ErrorModule::Kernel, 14}; | ||
| 14 | constexpr ResultCode ERR_INVALID_SIZE{ErrorModule::Kernel, 101}; | 15 | constexpr ResultCode ERR_INVALID_SIZE{ErrorModule::Kernel, 101}; |
| 15 | constexpr ResultCode ERR_INVALID_ADDRESS{ErrorModule::Kernel, 102}; | 16 | constexpr ResultCode ERR_INVALID_ADDRESS{ErrorModule::Kernel, 102}; |
| 16 | constexpr ResultCode ERR_HANDLE_TABLE_FULL{ErrorModule::Kernel, 105}; | 17 | constexpr ResultCode ERR_HANDLE_TABLE_FULL{ErrorModule::Kernel, 105}; |
diff --git a/src/core/hle/kernel/handle_table.h b/src/core/hle/kernel/handle_table.h index 6b7927fd8..89a3bc740 100644 --- a/src/core/hle/kernel/handle_table.h +++ b/src/core/hle/kernel/handle_table.h | |||
| @@ -43,6 +43,9 @@ enum KernelHandle : Handle { | |||
| 43 | */ | 43 | */ |
| 44 | class HandleTable final : NonCopyable { | 44 | class HandleTable final : NonCopyable { |
| 45 | public: | 45 | public: |
| 46 | /// This is the maximum limit of handles allowed per process in Horizon | ||
| 47 | static constexpr std::size_t MAX_COUNT = 1024; | ||
| 48 | |||
| 46 | HandleTable(); | 49 | HandleTable(); |
| 47 | ~HandleTable(); | 50 | ~HandleTable(); |
| 48 | 51 | ||
| @@ -91,9 +94,6 @@ public: | |||
| 91 | void Clear(); | 94 | void Clear(); |
| 92 | 95 | ||
| 93 | private: | 96 | private: |
| 94 | /// This is the maximum limit of handles allowed per process in Horizon | ||
| 95 | static constexpr std::size_t MAX_COUNT = 1024; | ||
| 96 | |||
| 97 | /// Stores the Object referenced by the handle or null if the slot is empty. | 97 | /// Stores the Object referenced by the handle or null if the slot is empty. |
| 98 | std::array<SharedPtr<Object>, MAX_COUNT> objects; | 98 | std::array<SharedPtr<Object>, MAX_COUNT> objects; |
| 99 | 99 | ||
diff --git a/src/core/hle/kernel/process_capability.cpp b/src/core/hle/kernel/process_capability.cpp new file mode 100644 index 000000000..8d787547b --- /dev/null +++ b/src/core/hle/kernel/process_capability.cpp | |||
| @@ -0,0 +1,253 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/bit_util.h" | ||
| 6 | #include "core/hle/kernel/errors.h" | ||
| 7 | #include "core/hle/kernel/handle_table.h" | ||
| 8 | #include "core/hle/kernel/process_capability.h" | ||
| 9 | #include "core/hle/kernel/vm_manager.h" | ||
| 10 | |||
| 11 | namespace Kernel { | ||
| 12 | namespace { | ||
| 13 | |||
| 14 | // clang-format off | ||
| 15 | |||
| 16 | // Shift offsets for kernel capability types. | ||
| 17 | enum : u32 { | ||
| 18 | CapabilityOffset_PriorityAndCoreNum = 3, | ||
| 19 | CapabilityOffset_Syscall = 4, | ||
| 20 | CapabilityOffset_MapPhysical = 6, | ||
| 21 | CapabilityOffset_MapIO = 7, | ||
| 22 | CapabilityOffset_Interrupt = 11, | ||
| 23 | CapabilityOffset_ProgramType = 13, | ||
| 24 | CapabilityOffset_KernelVersion = 14, | ||
| 25 | CapabilityOffset_HandleTableSize = 15, | ||
| 26 | CapabilityOffset_Debug = 16, | ||
| 27 | }; | ||
| 28 | |||
| 29 | // Combined mask of all parameters that may be initialized only once. | ||
| 30 | constexpr u32 InitializeOnceMask = (1U << CapabilityOffset_PriorityAndCoreNum) | | ||
| 31 | (1U << CapabilityOffset_ProgramType) | | ||
| 32 | (1U << CapabilityOffset_KernelVersion) | | ||
| 33 | (1U << CapabilityOffset_HandleTableSize) | | ||
| 34 | (1U << CapabilityOffset_Debug); | ||
| 35 | |||
| 36 | // Packed kernel version indicating 10.4.0 | ||
| 37 | constexpr u32 PackedKernelVersion = 0x520000; | ||
| 38 | |||
| 39 | // Indicates possible types of capabilities that can be specified. | ||
| 40 | enum class CapabilityType : u32 { | ||
| 41 | Unset = 0U, | ||
| 42 | PriorityAndCoreNum = (1U << CapabilityOffset_PriorityAndCoreNum) - 1, | ||
| 43 | Syscall = (1U << CapabilityOffset_Syscall) - 1, | ||
| 44 | MapPhysical = (1U << CapabilityOffset_MapPhysical) - 1, | ||
| 45 | MapIO = (1U << CapabilityOffset_MapIO) - 1, | ||
| 46 | Interrupt = (1U << CapabilityOffset_Interrupt) - 1, | ||
| 47 | ProgramType = (1U << CapabilityOffset_ProgramType) - 1, | ||
| 48 | KernelVersion = (1U << CapabilityOffset_KernelVersion) - 1, | ||
| 49 | HandleTableSize = (1U << CapabilityOffset_HandleTableSize) - 1, | ||
| 50 | Debug = (1U << CapabilityOffset_Debug) - 1, | ||
| 51 | Ignorable = 0xFFFFFFFFU, | ||
| 52 | }; | ||
| 53 | |||
| 54 | // clang-format on | ||
| 55 | |||
| 56 | constexpr CapabilityType GetCapabilityType(u32 value) { | ||
| 57 | return static_cast<CapabilityType>((~value & (value + 1)) - 1); | ||
| 58 | } | ||
| 59 | |||
| 60 | u32 GetFlagBitOffset(CapabilityType type) { | ||
| 61 | const auto value = static_cast<u32>(type); | ||
| 62 | return static_cast<u32>(Common::BitSize<u32>() - Common::CountLeadingZeroes32(value)); | ||
| 63 | } | ||
| 64 | |||
| 65 | } // Anonymous namespace | ||
| 66 | |||
| 67 | ResultCode ProcessCapabilities::InitializeForKernelProcess(const u32* capabilities, | ||
| 68 | std::size_t num_capabilities, | ||
| 69 | VMManager& vm_manager) { | ||
| 70 | Clear(); | ||
| 71 | |||
| 72 | // Allow all cores and priorities. | ||
| 73 | core_mask = 0xF; | ||
| 74 | priority_mask = 0xFFFFFFFFFFFFFFFF; | ||
| 75 | kernel_version = PackedKernelVersion; | ||
| 76 | |||
| 77 | return ParseCapabilities(capabilities, num_capabilities, vm_manager); | ||
| 78 | } | ||
| 79 | |||
| 80 | ResultCode ProcessCapabilities::InitializeForUserProcess(const u32* capabilities, | ||
| 81 | std::size_t num_capabilities, | ||
| 82 | VMManager& vm_manager) { | ||
| 83 | Clear(); | ||
| 84 | |||
| 85 | return ParseCapabilities(capabilities, num_capabilities, vm_manager); | ||
| 86 | } | ||
| 87 | |||
| 88 | void ProcessCapabilities::InitializeForMetadatalessProcess() { | ||
| 89 | // Allow all cores and priorities | ||
| 90 | core_mask = 0xF; | ||
| 91 | priority_mask = 0xFFFFFFFFFFFFFFFF; | ||
| 92 | kernel_version = PackedKernelVersion; | ||
| 93 | |||
| 94 | // Allow all system calls and interrupts. | ||
| 95 | svc_capabilities.set(); | ||
| 96 | interrupt_capabilities.set(); | ||
| 97 | |||
| 98 | // Allow using the maximum possible amount of handles | ||
| 99 | handle_table_size = static_cast<u32>(HandleTable::MAX_COUNT); | ||
| 100 | |||
| 101 | // Allow all debugging capabilities. | ||
| 102 | is_debuggable = true; | ||
| 103 | can_force_debug = true; | ||
| 104 | } | ||
| 105 | |||
| 106 | ResultCode ProcessCapabilities::ParseCapabilities(const u32* capabilities, | ||
| 107 | std::size_t num_capabilities, | ||
| 108 | VMManager& vm_manager) { | ||
| 109 | u32 set_flags = 0; | ||
| 110 | u32 set_svc_bits = 0; | ||
| 111 | |||
| 112 | for (std::size_t i = 0; i < num_capabilities; ++i) { | ||
| 113 | const u32 descriptor = capabilities[i]; | ||
| 114 | const auto type = GetCapabilityType(descriptor); | ||
| 115 | |||
| 116 | if (type == CapabilityType::MapPhysical) { | ||
| 117 | i++; | ||
| 118 | |||
| 119 | // The MapPhysical type uses two descriptor flags for its parameters. | ||
| 120 | // If there's only one, then there's a problem. | ||
| 121 | if (i >= num_capabilities) { | ||
| 122 | return ERR_INVALID_COMBINATION; | ||
| 123 | } | ||
| 124 | |||
| 125 | const auto size_flags = capabilities[i]; | ||
| 126 | if (GetCapabilityType(size_flags) != CapabilityType::MapPhysical) { | ||
| 127 | return ERR_INVALID_COMBINATION; | ||
| 128 | } | ||
| 129 | |||
| 130 | const auto result = HandleMapPhysicalFlags(descriptor, size_flags, vm_manager); | ||
| 131 | if (result.IsError()) { | ||
| 132 | return result; | ||
| 133 | } | ||
| 134 | } else { | ||
| 135 | const auto result = | ||
| 136 | ParseSingleFlagCapability(set_flags, set_svc_bits, descriptor, vm_manager); | ||
| 137 | if (result.IsError()) { | ||
| 138 | return result; | ||
| 139 | } | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 143 | return RESULT_SUCCESS; | ||
| 144 | } | ||
| 145 | |||
| 146 | ResultCode ProcessCapabilities::ParseSingleFlagCapability(u32& set_flags, u32& set_svc_bits, | ||
| 147 | u32 flag, VMManager& vm_manager) { | ||
| 148 | const auto type = GetCapabilityType(flag); | ||
| 149 | |||
| 150 | if (type == CapabilityType::Unset) { | ||
| 151 | return ERR_INVALID_CAPABILITY_DESCRIPTOR; | ||
| 152 | } | ||
| 153 | |||
| 154 | // Bail early on ignorable entries, as one would expect, | ||
| 155 | // ignorable descriptors can be ignored. | ||
| 156 | if (type == CapabilityType::Ignorable) { | ||
| 157 | return RESULT_SUCCESS; | ||
| 158 | } | ||
| 159 | |||
| 160 | // Ensure that the give flag hasn't already been initialized before. | ||
| 161 | // If it has been, then bail. | ||
| 162 | const u32 flag_length = GetFlagBitOffset(type); | ||
| 163 | const u32 set_flag = 1U << flag_length; | ||
| 164 | if ((set_flag & set_flags & InitializeOnceMask) != 0) { | ||
| 165 | return ERR_INVALID_COMBINATION; | ||
| 166 | } | ||
| 167 | set_flags |= set_flag; | ||
| 168 | |||
| 169 | switch (type) { | ||
| 170 | case CapabilityType::PriorityAndCoreNum: | ||
| 171 | return HandlePriorityCoreNumFlags(flag); | ||
| 172 | case CapabilityType::Syscall: | ||
| 173 | return HandleSyscallFlags(set_svc_bits, flag); | ||
| 174 | case CapabilityType::MapIO: | ||
| 175 | return HandleMapIOFlags(flag, vm_manager); | ||
| 176 | case CapabilityType::Interrupt: | ||
| 177 | return HandleInterruptFlags(flag); | ||
| 178 | case CapabilityType::ProgramType: | ||
| 179 | return HandleProgramTypeFlags(flag); | ||
| 180 | case CapabilityType::KernelVersion: | ||
| 181 | return HandleKernelVersionFlags(flag); | ||
| 182 | case CapabilityType::HandleTableSize: | ||
| 183 | return HandleHandleTableFlags(flag); | ||
| 184 | case CapabilityType::Debug: | ||
| 185 | return HandleDebugFlags(flag); | ||
| 186 | default: | ||
| 187 | break; | ||
| 188 | } | ||
| 189 | |||
| 190 | return ERR_INVALID_CAPABILITY_DESCRIPTOR; | ||
| 191 | } | ||
| 192 | |||
| 193 | void ProcessCapabilities::Clear() { | ||
| 194 | svc_capabilities.reset(); | ||
| 195 | interrupt_capabilities.reset(); | ||
| 196 | |||
| 197 | core_mask = 0; | ||
| 198 | priority_mask = 0; | ||
| 199 | |||
| 200 | handle_table_size = 0; | ||
| 201 | kernel_version = 0; | ||
| 202 | |||
| 203 | is_debuggable = false; | ||
| 204 | can_force_debug = false; | ||
| 205 | } | ||
| 206 | |||
| 207 | ResultCode ProcessCapabilities::HandlePriorityCoreNumFlags(u32 flags) { | ||
| 208 | // TODO: Implement | ||
| 209 | return RESULT_SUCCESS; | ||
| 210 | } | ||
| 211 | |||
| 212 | ResultCode ProcessCapabilities::HandleSyscallFlags(u32& set_svc_bits, u32 flags) { | ||
| 213 | // TODO: Implement | ||
| 214 | return RESULT_SUCCESS; | ||
| 215 | } | ||
| 216 | |||
| 217 | ResultCode ProcessCapabilities::HandleMapPhysicalFlags(u32 flags, u32 size_flags, | ||
| 218 | VMManager& vm_manager) { | ||
| 219 | // TODO(Lioncache): Implement once the memory manager can handle this. | ||
| 220 | return RESULT_SUCCESS; | ||
| 221 | } | ||
| 222 | |||
| 223 | ResultCode ProcessCapabilities::HandleMapIOFlags(u32 flags, VMManager& vm_manager) { | ||
| 224 | // TODO(Lioncache): Implement once the memory manager can handle this. | ||
| 225 | return RESULT_SUCCESS; | ||
| 226 | } | ||
| 227 | |||
| 228 | ResultCode ProcessCapabilities::HandleInterruptFlags(u32 flags) { | ||
| 229 | // TODO: Implement | ||
| 230 | return RESULT_SUCCESS; | ||
| 231 | } | ||
| 232 | |||
| 233 | ResultCode ProcessCapabilities::HandleProgramTypeFlags(u32 flags) { | ||
| 234 | // TODO: Implement | ||
| 235 | return RESULT_SUCCESS; | ||
| 236 | } | ||
| 237 | |||
| 238 | ResultCode ProcessCapabilities::HandleKernelVersionFlags(u32 flags) { | ||
| 239 | // TODO: Implement | ||
| 240 | return RESULT_SUCCESS; | ||
| 241 | } | ||
| 242 | |||
| 243 | ResultCode ProcessCapabilities::HandleHandleTableFlags(u32 flags) { | ||
| 244 | // TODO: Implement | ||
| 245 | return RESULT_SUCCESS; | ||
| 246 | } | ||
| 247 | |||
| 248 | ResultCode ProcessCapabilities::HandleDebugFlags(u32 flags) { | ||
| 249 | // TODO: Implement | ||
| 250 | return RESULT_SUCCESS; | ||
| 251 | } | ||
| 252 | |||
| 253 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/process_capability.h b/src/core/hle/kernel/process_capability.h new file mode 100644 index 000000000..5cff10476 --- /dev/null +++ b/src/core/hle/kernel/process_capability.h | |||
| @@ -0,0 +1,209 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <bitset> | ||
| 8 | |||
| 9 | #include "common/common_types.h" | ||
| 10 | |||
| 11 | union ResultCode; | ||
| 12 | |||
| 13 | namespace Kernel { | ||
| 14 | |||
| 15 | class VMManager; | ||
| 16 | |||
| 17 | /// Handles kernel capability descriptors that are provided by | ||
| 18 | /// application metadata. These descriptors provide information | ||
| 19 | /// that alters certain parameters for kernel process instance | ||
| 20 | /// that will run said application (or applet). | ||
| 21 | /// | ||
| 22 | /// Capabilities are a sequence of flag descriptors, that indicate various | ||
| 23 | /// configurations and constraints for a particular process. | ||
| 24 | /// | ||
| 25 | /// Flag types are indicated by a sequence of set low bits. E.g. the | ||
| 26 | /// types are indicated with the low bits as follows (where x indicates "don't care"): | ||
| 27 | /// | ||
| 28 | /// - Priority and core mask : 0bxxxxxxxxxxxx0111 | ||
| 29 | /// - Allowed service call mask: 0bxxxxxxxxxxx01111 | ||
| 30 | /// - Map physical memory : 0bxxxxxxxxx0111111 | ||
| 31 | /// - Map IO memory : 0bxxxxxxxx01111111 | ||
| 32 | /// - Interrupts : 0bxxxx011111111111 | ||
| 33 | /// - Application type : 0bxx01111111111111 | ||
| 34 | /// - Kernel version : 0bx011111111111111 | ||
| 35 | /// - Handle table size : 0b0111111111111111 | ||
| 36 | /// - Debugger flags : 0b1111111111111111 | ||
| 37 | /// | ||
| 38 | /// These are essentially a bit offset subtracted by 1 to create a mask. | ||
| 39 | /// e.g. The first entry in the above list is simply bit 3 (value 8 -> 0b1000) | ||
| 40 | /// subtracted by one (7 -> 0b0111) | ||
| 41 | /// | ||
| 42 | /// An example of a bit layout (using the map physical layout): | ||
| 43 | /// <example> | ||
| 44 | /// The MapPhysical type indicates a sequence entry pair of: | ||
| 45 | /// | ||
| 46 | /// [initial, memory_flags], where: | ||
| 47 | /// | ||
| 48 | /// initial: | ||
| 49 | /// bits: | ||
| 50 | /// 7-24: Starting page to map memory at. | ||
| 51 | /// 25 : Indicates if the memory should be mapped as read only. | ||
| 52 | /// | ||
| 53 | /// memory_flags: | ||
| 54 | /// bits: | ||
| 55 | /// 7-20 : Number of pages to map | ||
| 56 | /// 21-25: Seems to be reserved (still checked against though) | ||
| 57 | /// 26 : Whether or not the memory being mapped is IO memory, or physical memory | ||
| 58 | /// </example> | ||
| 59 | /// | ||
| 60 | class ProcessCapabilities { | ||
| 61 | public: | ||
| 62 | using InterruptCapabilities = std::bitset<1024>; | ||
| 63 | using SyscallCapabilities = std::bitset<128>; | ||
| 64 | |||
| 65 | ProcessCapabilities() = default; | ||
| 66 | ProcessCapabilities(const ProcessCapabilities&) = delete; | ||
| 67 | ProcessCapabilities(ProcessCapabilities&&) = default; | ||
| 68 | |||
| 69 | ProcessCapabilities& operator=(const ProcessCapabilities&) = delete; | ||
| 70 | ProcessCapabilities& operator=(ProcessCapabilities&&) = default; | ||
| 71 | |||
| 72 | /// Initializes this process capabilities instance for a kernel process. | ||
| 73 | /// | ||
| 74 | /// @param capabilities The capabilities to parse | ||
| 75 | /// @param num_capabilities The number of capabilities to parse. | ||
| 76 | /// @param vm_manager The memory manager to use for handling any mapping-related | ||
| 77 | /// operations (such as mapping IO memory, etc). | ||
| 78 | /// | ||
| 79 | /// @returns RESULT_SUCCESS if this capabilities instance was able to be initialized, | ||
| 80 | /// otherwise, an error code upon failure. | ||
| 81 | /// | ||
| 82 | ResultCode InitializeForKernelProcess(const u32* capabilities, std::size_t num_capabilities, | ||
| 83 | VMManager& vm_manager); | ||
| 84 | |||
| 85 | /// Initializes this process capabilities instance for a userland process. | ||
| 86 | /// | ||
| 87 | /// @param capabilities The capabilities to parse. | ||
| 88 | /// @param num_capabilities The total number of capabilities to parse. | ||
| 89 | /// @param vm_manager The memory manager to use for handling any mapping-related | ||
| 90 | /// operations (such as mapping IO memory, etc). | ||
| 91 | /// | ||
| 92 | /// @returns RESULT_SUCCESS if this capabilities instance was able to be initialized, | ||
| 93 | /// otherwise, an error code upon failure. | ||
| 94 | /// | ||
| 95 | ResultCode InitializeForUserProcess(const u32* capabilities, std::size_t num_capabilities, | ||
| 96 | VMManager& vm_manager); | ||
| 97 | |||
| 98 | /// Initializes this process capabilities instance for a process that does not | ||
| 99 | /// have any metadata to parse. | ||
| 100 | /// | ||
| 101 | /// This is necessary, as we allow running raw executables, and the internal | ||
| 102 | /// kernel process capabilities also determine what CPU cores the process is | ||
| 103 | /// allowed to run on, and what priorities are allowed for threads. It also | ||
| 104 | /// determines the max handle table size, what the program type is, whether or | ||
| 105 | /// not the process can be debugged, or whether it's possible for a process to | ||
| 106 | /// forcibly debug another process. | ||
| 107 | /// | ||
| 108 | /// Given the above, this essentially enables all capabilities across the board | ||
| 109 | /// for the process. It allows the process to: | ||
| 110 | /// | ||
| 111 | /// - Run on any core | ||
| 112 | /// - Use any thread priority | ||
| 113 | /// - Use the maximum amount of handles a process is allowed to. | ||
| 114 | /// - Be debuggable | ||
| 115 | /// - Forcibly debug other processes. | ||
| 116 | /// | ||
| 117 | /// Note that this is not a behavior that the kernel allows a process to do via | ||
| 118 | /// a single function like this. This is yuzu-specific behavior to handle | ||
| 119 | /// executables with no capability descriptors whatsoever to derive behavior from. | ||
| 120 | /// It being yuzu-specific is why this is also not the default behavior and not | ||
| 121 | /// done by default in the constructor. | ||
| 122 | /// | ||
| 123 | void InitializeForMetadatalessProcess(); | ||
| 124 | |||
| 125 | private: | ||
| 126 | /// Attempts to parse a given sequence of capability descriptors. | ||
| 127 | /// | ||
| 128 | /// @param capabilities The sequence of capability descriptors to parse. | ||
| 129 | /// @param num_capabilities The number of descriptors within the given sequence. | ||
| 130 | /// @param vm_manager The memory manager that will perform any memory | ||
| 131 | /// mapping if necessary. | ||
| 132 | /// | ||
| 133 | /// @return RESULT_SUCCESS if no errors occur, otherwise an error code. | ||
| 134 | /// | ||
| 135 | ResultCode ParseCapabilities(const u32* capabilities, std::size_t num_capabilities, | ||
| 136 | VMManager& vm_manager); | ||
| 137 | |||
| 138 | /// Attempts to parse a capability descriptor that is only represented by a | ||
| 139 | /// single flag set. | ||
| 140 | /// | ||
| 141 | /// @param set_flags Running set of flags that are used to catch | ||
| 142 | /// flags being initialized more than once when they shouldn't be. | ||
| 143 | /// @param set_svc_bits Running set of bits representing the allowed supervisor calls mask. | ||
| 144 | /// @param flag The flag to attempt to parse. | ||
| 145 | /// @param vm_manager The memory manager that will perform any memory | ||
| 146 | /// mapping if necessary. | ||
| 147 | /// | ||
| 148 | /// @return RESULT_SUCCESS if no errors occurred, otherwise an error code. | ||
| 149 | /// | ||
| 150 | ResultCode ParseSingleFlagCapability(u32& set_flags, u32& set_svc_bits, u32 flag, | ||
| 151 | VMManager& vm_manager); | ||
| 152 | |||
| 153 | /// Clears the internal state of this process capability instance. Necessary, | ||
| 154 | /// to have a sane starting point due to us allowing running executables without | ||
| 155 | /// configuration metadata. We assume a process is not going to have metadata, | ||
| 156 | /// and if it turns out that the process does, in fact, have metadata, then | ||
| 157 | /// we attempt to parse it. Thus, we need this to reset data members back to | ||
| 158 | /// a good state. | ||
| 159 | /// | ||
| 160 | /// DO NOT ever make this a public member function. This isn't an invariant | ||
| 161 | /// anything external should depend upon (and if anything comes to rely on it, | ||
| 162 | /// you should immediately be questioning the design of that thing, not this | ||
| 163 | /// class. If the kernel itself can run without depending on behavior like that, | ||
| 164 | /// then so can yuzu). | ||
| 165 | /// | ||
| 166 | void Clear(); | ||
| 167 | |||
| 168 | /// Handles flags related to the priority and core number capability flags. | ||
| 169 | ResultCode HandlePriorityCoreNumFlags(u32 flags); | ||
| 170 | |||
| 171 | /// Handles flags related to determining the allowable SVC mask. | ||
| 172 | ResultCode HandleSyscallFlags(u32& set_svc_bits, u32 flags); | ||
| 173 | |||
| 174 | /// Handles flags related to mapping physical memory pages. | ||
| 175 | ResultCode HandleMapPhysicalFlags(u32 flags, u32 size_flags, VMManager& vm_manager); | ||
| 176 | |||
| 177 | /// Handles flags related to mapping IO pages. | ||
| 178 | ResultCode HandleMapIOFlags(u32 flags, VMManager& vm_manager); | ||
| 179 | |||
| 180 | /// Handles flags related to the interrupt capability flags. | ||
| 181 | ResultCode HandleInterruptFlags(u32 flags); | ||
| 182 | |||
| 183 | /// Handles flags related to the program type. | ||
| 184 | ResultCode HandleProgramTypeFlags(u32 flags); | ||
| 185 | |||
| 186 | /// Handles flags related to the handle table size. | ||
| 187 | ResultCode HandleHandleTableFlags(u32 flags); | ||
| 188 | |||
| 189 | /// Handles flags related to the kernel version capability flags. | ||
| 190 | ResultCode HandleKernelVersionFlags(u32 flags); | ||
| 191 | |||
| 192 | /// Handles flags related to debug-specific capabilities. | ||
| 193 | ResultCode HandleDebugFlags(u32 flags); | ||
| 194 | |||
| 195 | SyscallCapabilities svc_capabilities; | ||
| 196 | InterruptCapabilities interrupt_capabilities; | ||
| 197 | |||
| 198 | u64 core_mask = 0; | ||
| 199 | u64 priority_mask = 0; | ||
| 200 | |||
| 201 | u32 handle_table_size = 0; | ||
| 202 | u32 kernel_version = 0; | ||
| 203 | u32 program_type = 0; | ||
| 204 | |||
| 205 | bool is_debuggable = false; | ||
| 206 | bool can_force_debug = false; | ||
| 207 | }; | ||
| 208 | |||
| 209 | } // namespace Kernel | ||