process_capability.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <bitset>
  5. #include "common/common_types.h"
  6. union Result;
  7. namespace Kernel {
  8. class KPageTable;
  9. /// The possible types of programs that may be indicated
  10. /// by the program type capability descriptor.
  11. enum class ProgramType {
  12. SysModule,
  13. Application,
  14. Applet,
  15. };
  16. /// Handles kernel capability descriptors that are provided by
  17. /// application metadata. These descriptors provide information
  18. /// that alters certain parameters for kernel process instance
  19. /// that will run said application (or applet).
  20. ///
  21. /// Capabilities are a sequence of flag descriptors, that indicate various
  22. /// configurations and constraints for a particular process.
  23. ///
  24. /// Flag types are indicated by a sequence of set low bits. E.g. the
  25. /// types are indicated with the low bits as follows (where x indicates "don't care"):
  26. ///
  27. /// - Priority and core mask : 0bxxxxxxxxxxxx0111
  28. /// - Allowed service call mask: 0bxxxxxxxxxxx01111
  29. /// - Map physical memory : 0bxxxxxxxxx0111111
  30. /// - Map IO memory : 0bxxxxxxxx01111111
  31. /// - Interrupts : 0bxxxx011111111111
  32. /// - Application type : 0bxx01111111111111
  33. /// - Kernel version : 0bx011111111111111
  34. /// - Handle table size : 0b0111111111111111
  35. /// - Debugger flags : 0b1111111111111111
  36. ///
  37. /// These are essentially a bit offset subtracted by 1 to create a mask.
  38. /// e.g. The first entry in the above list is simply bit 3 (value 8 -> 0b1000)
  39. /// subtracted by one (7 -> 0b0111)
  40. ///
  41. /// An example of a bit layout (using the map physical layout):
  42. /// <example>
  43. /// The MapPhysical type indicates a sequence entry pair of:
  44. ///
  45. /// [initial, memory_flags], where:
  46. ///
  47. /// initial:
  48. /// bits:
  49. /// 7-24: Starting page to map memory at.
  50. /// 25 : Indicates if the memory should be mapped as read only.
  51. ///
  52. /// memory_flags:
  53. /// bits:
  54. /// 7-20 : Number of pages to map
  55. /// 21-25: Seems to be reserved (still checked against though)
  56. /// 26 : Whether or not the memory being mapped is IO memory, or physical memory
  57. /// </example>
  58. ///
  59. class ProcessCapabilities {
  60. public:
  61. using InterruptCapabilities = std::bitset<1024>;
  62. using SyscallCapabilities = std::bitset<192>;
  63. ProcessCapabilities() = default;
  64. ProcessCapabilities(const ProcessCapabilities&) = delete;
  65. ProcessCapabilities(ProcessCapabilities&&) = default;
  66. ProcessCapabilities& operator=(const ProcessCapabilities&) = delete;
  67. ProcessCapabilities& operator=(ProcessCapabilities&&) = default;
  68. /// Initializes this process capabilities instance for a kernel process.
  69. ///
  70. /// @param capabilities The capabilities to parse
  71. /// @param num_capabilities The number of capabilities to parse.
  72. /// @param page_table The memory manager to use for handling any mapping-related
  73. /// operations (such as mapping IO memory, etc).
  74. ///
  75. /// @returns ResultSuccess if this capabilities instance was able to be initialized,
  76. /// otherwise, an error code upon failure.
  77. ///
  78. Result InitializeForKernelProcess(const u32* capabilities, std::size_t num_capabilities,
  79. KPageTable& page_table);
  80. /// Initializes this process capabilities instance for a userland process.
  81. ///
  82. /// @param capabilities The capabilities to parse.
  83. /// @param num_capabilities The total number of capabilities to parse.
  84. /// @param page_table The memory manager to use for handling any mapping-related
  85. /// operations (such as mapping IO memory, etc).
  86. ///
  87. /// @returns ResultSuccess if this capabilities instance was able to be initialized,
  88. /// otherwise, an error code upon failure.
  89. ///
  90. Result InitializeForUserProcess(const u32* capabilities, std::size_t num_capabilities,
  91. KPageTable& page_table);
  92. /// Initializes this process capabilities instance for a process that does not
  93. /// have any metadata to parse.
  94. ///
  95. /// This is necessary, as we allow running raw executables, and the internal
  96. /// kernel process capabilities also determine what CPU cores the process is
  97. /// allowed to run on, and what priorities are allowed for threads. It also
  98. /// determines the max handle table size, what the program type is, whether or
  99. /// not the process can be debugged, or whether it's possible for a process to
  100. /// forcibly debug another process.
  101. ///
  102. /// Given the above, this essentially enables all capabilities across the board
  103. /// for the process. It allows the process to:
  104. ///
  105. /// - Run on any core
  106. /// - Use any thread priority
  107. /// - Use the maximum amount of handles a process is allowed to.
  108. /// - Be debuggable
  109. /// - Forcibly debug other processes.
  110. ///
  111. /// Note that this is not a behavior that the kernel allows a process to do via
  112. /// a single function like this. This is yuzu-specific behavior to handle
  113. /// executables with no capability descriptors whatsoever to derive behavior from.
  114. /// It being yuzu-specific is why this is also not the default behavior and not
  115. /// done by default in the constructor.
  116. ///
  117. void InitializeForMetadatalessProcess();
  118. /// Gets the allowable core mask
  119. u64 GetCoreMask() const {
  120. return core_mask;
  121. }
  122. /// Gets the allowable priority mask
  123. u64 GetPriorityMask() const {
  124. return priority_mask;
  125. }
  126. /// Gets the SVC access permission bits
  127. const SyscallCapabilities& GetServiceCapabilities() const {
  128. return svc_capabilities;
  129. }
  130. /// Gets the valid interrupt bits.
  131. const InterruptCapabilities& GetInterruptCapabilities() const {
  132. return interrupt_capabilities;
  133. }
  134. /// Gets the program type for this process.
  135. ProgramType GetProgramType() const {
  136. return program_type;
  137. }
  138. /// Gets the number of total allowable handles for the process' handle table.
  139. s32 GetHandleTableSize() const {
  140. return handle_table_size;
  141. }
  142. /// Gets the kernel version value.
  143. u32 GetKernelVersion() const {
  144. return kernel_version;
  145. }
  146. /// Whether or not this process can be debugged.
  147. bool IsDebuggable() const {
  148. return is_debuggable;
  149. }
  150. /// Whether or not this process can forcibly debug another
  151. /// process, even if that process is not considered debuggable.
  152. bool CanForceDebug() const {
  153. return can_force_debug;
  154. }
  155. private:
  156. /// Attempts to parse a given sequence of capability descriptors.
  157. ///
  158. /// @param capabilities The sequence of capability descriptors to parse.
  159. /// @param num_capabilities The number of descriptors within the given sequence.
  160. /// @param page_table The memory manager that will perform any memory
  161. /// mapping if necessary.
  162. ///
  163. /// @return ResultSuccess if no errors occur, otherwise an error code.
  164. ///
  165. Result ParseCapabilities(const u32* capabilities, std::size_t num_capabilities,
  166. KPageTable& page_table);
  167. /// Attempts to parse a capability descriptor that is only represented by a
  168. /// single flag set.
  169. ///
  170. /// @param set_flags Running set of flags that are used to catch
  171. /// flags being initialized more than once when they shouldn't be.
  172. /// @param set_svc_bits Running set of bits representing the allowed supervisor calls mask.
  173. /// @param flag The flag to attempt to parse.
  174. /// @param page_table The memory manager that will perform any memory
  175. /// mapping if necessary.
  176. ///
  177. /// @return ResultSuccess if no errors occurred, otherwise an error code.
  178. ///
  179. Result ParseSingleFlagCapability(u32& set_flags, u32& set_svc_bits, u32 flag,
  180. KPageTable& page_table);
  181. /// Clears the internal state of this process capability instance. Necessary,
  182. /// to have a sane starting point due to us allowing running executables without
  183. /// configuration metadata. We assume a process is not going to have metadata,
  184. /// and if it turns out that the process does, in fact, have metadata, then
  185. /// we attempt to parse it. Thus, we need this to reset data members back to
  186. /// a good state.
  187. ///
  188. /// DO NOT ever make this a public member function. This isn't an invariant
  189. /// anything external should depend upon (and if anything comes to rely on it,
  190. /// you should immediately be questioning the design of that thing, not this
  191. /// class. If the kernel itself can run without depending on behavior like that,
  192. /// then so can yuzu).
  193. ///
  194. void Clear();
  195. /// Handles flags related to the priority and core number capability flags.
  196. Result HandlePriorityCoreNumFlags(u32 flags);
  197. /// Handles flags related to determining the allowable SVC mask.
  198. Result HandleSyscallFlags(u32& set_svc_bits, u32 flags);
  199. /// Handles flags related to mapping physical memory pages.
  200. Result HandleMapPhysicalFlags(u32 flags, u32 size_flags, KPageTable& page_table);
  201. /// Handles flags related to mapping IO pages.
  202. Result HandleMapIOFlags(u32 flags, KPageTable& page_table);
  203. /// Handles flags related to mapping physical memory regions.
  204. Result HandleMapRegionFlags(u32 flags, KPageTable& page_table);
  205. /// Handles flags related to the interrupt capability flags.
  206. Result HandleInterruptFlags(u32 flags);
  207. /// Handles flags related to the program type.
  208. Result HandleProgramTypeFlags(u32 flags);
  209. /// Handles flags related to the handle table size.
  210. Result HandleHandleTableFlags(u32 flags);
  211. /// Handles flags related to the kernel version capability flags.
  212. Result HandleKernelVersionFlags(u32 flags);
  213. /// Handles flags related to debug-specific capabilities.
  214. Result HandleDebugFlags(u32 flags);
  215. SyscallCapabilities svc_capabilities;
  216. InterruptCapabilities interrupt_capabilities;
  217. u64 core_mask = 0;
  218. u64 priority_mask = 0;
  219. s32 handle_table_size = 0;
  220. u32 kernel_version = 0;
  221. ProgramType program_type = ProgramType::SysModule;
  222. bool is_debuggable = false;
  223. bool can_force_debug = false;
  224. };
  225. } // namespace Kernel