| 
									
										
										
										
											2018-12-19 12:57:47 -05:00
										 |  |  | // Copyright 2018 yuzu emulator team
 | 
					
						
							|  |  |  | // Licensed under GPLv2 or any later version
 | 
					
						
							|  |  |  | // Refer to the license.txt file included.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <bitset>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "common/common_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | union ResultCode; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace Kernel { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-12 17:58:31 -08:00
										 |  |  | class KPageTable; | 
					
						
							| 
									
										
										
										
											2018-12-19 12:57:47 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-19 21:14:47 -05:00
										 |  |  | /// The possible types of programs that may be indicated
 | 
					
						
							|  |  |  | /// by the program type capability descriptor.
 | 
					
						
							|  |  |  | enum class ProgramType { | 
					
						
							|  |  |  |     SysModule, | 
					
						
							|  |  |  |     Application, | 
					
						
							|  |  |  |     Applet, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-19 12:57:47 -05:00
										 |  |  | /// Handles kernel capability descriptors that are provided by
 | 
					
						
							|  |  |  | /// application metadata. These descriptors provide information
 | 
					
						
							|  |  |  | /// that alters certain parameters for kernel process instance
 | 
					
						
							|  |  |  | /// that will run said application (or applet).
 | 
					
						
							|  |  |  | ///
 | 
					
						
							|  |  |  | /// Capabilities are a sequence of flag descriptors, that indicate various
 | 
					
						
							|  |  |  | /// configurations and constraints for a particular process.
 | 
					
						
							|  |  |  | ///
 | 
					
						
							|  |  |  | /// Flag types are indicated by a sequence of set low bits. E.g. the
 | 
					
						
							|  |  |  | /// types are indicated with the low bits as follows (where x indicates "don't care"):
 | 
					
						
							|  |  |  | ///
 | 
					
						
							|  |  |  | /// - Priority and core mask   : 0bxxxxxxxxxxxx0111
 | 
					
						
							|  |  |  | /// - Allowed service call mask: 0bxxxxxxxxxxx01111
 | 
					
						
							|  |  |  | /// - Map physical memory      : 0bxxxxxxxxx0111111
 | 
					
						
							|  |  |  | /// - Map IO memory            : 0bxxxxxxxx01111111
 | 
					
						
							|  |  |  | /// - Interrupts               : 0bxxxx011111111111
 | 
					
						
							|  |  |  | /// - Application type         : 0bxx01111111111111
 | 
					
						
							|  |  |  | /// - Kernel version           : 0bx011111111111111
 | 
					
						
							|  |  |  | /// - Handle table size        : 0b0111111111111111
 | 
					
						
							|  |  |  | /// - Debugger flags           : 0b1111111111111111
 | 
					
						
							|  |  |  | ///
 | 
					
						
							|  |  |  | /// These are essentially a bit offset subtracted by 1 to create a mask.
 | 
					
						
							|  |  |  | /// e.g. The first entry in the above list is simply bit 3 (value 8 -> 0b1000)
 | 
					
						
							|  |  |  | ///      subtracted by one (7 -> 0b0111)
 | 
					
						
							|  |  |  | ///
 | 
					
						
							|  |  |  | /// An example of a bit layout (using the map physical layout):
 | 
					
						
							|  |  |  | /// <example>
 | 
					
						
							|  |  |  | ///   The MapPhysical type indicates a sequence entry pair of:
 | 
					
						
							|  |  |  | ///
 | 
					
						
							|  |  |  | ///   [initial, memory_flags], where:
 | 
					
						
							|  |  |  | ///
 | 
					
						
							|  |  |  | ///   initial:
 | 
					
						
							|  |  |  | ///     bits:
 | 
					
						
							|  |  |  | ///       7-24: Starting page to map memory at.
 | 
					
						
							|  |  |  | ///       25  : Indicates if the memory should be mapped as read only.
 | 
					
						
							|  |  |  | ///
 | 
					
						
							|  |  |  | ///   memory_flags:
 | 
					
						
							|  |  |  | ///     bits:
 | 
					
						
							|  |  |  | ///       7-20 : Number of pages to map
 | 
					
						
							|  |  |  | ///       21-25: Seems to be reserved (still checked against though)
 | 
					
						
							|  |  |  | ///       26   : Whether or not the memory being mapped is IO memory, or physical memory
 | 
					
						
							|  |  |  | /// </example>
 | 
					
						
							|  |  |  | ///
 | 
					
						
							|  |  |  | class ProcessCapabilities { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     using InterruptCapabilities = std::bitset<1024>; | 
					
						
							| 
									
										
										
										
											2021-04-07 00:35:47 -04:00
										 |  |  |     using SyscallCapabilities = std::bitset<192>; | 
					
						
							| 
									
										
										
										
											2018-12-19 12:57:47 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ProcessCapabilities() = default; | 
					
						
							|  |  |  |     ProcessCapabilities(const ProcessCapabilities&) = delete; | 
					
						
							|  |  |  |     ProcessCapabilities(ProcessCapabilities&&) = default; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ProcessCapabilities& operator=(const ProcessCapabilities&) = delete; | 
					
						
							|  |  |  |     ProcessCapabilities& operator=(ProcessCapabilities&&) = default; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /// Initializes this process capabilities instance for a kernel process.
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     /// @param capabilities     The capabilities to parse
 | 
					
						
							|  |  |  |     /// @param num_capabilities The number of capabilities to parse.
 | 
					
						
							| 
									
										
										
										
											2020-04-08 17:30:34 -04:00
										 |  |  |     /// @param page_table       The memory manager to use for handling any mapping-related
 | 
					
						
							| 
									
										
										
										
											2018-12-19 12:57:47 -05:00
										 |  |  |     ///                         operations (such as mapping IO memory, etc).
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							| 
									
										
										
										
											2021-05-21 01:05:04 -04:00
										 |  |  |     /// @returns ResultSuccess if this capabilities instance was able to be initialized,
 | 
					
						
							| 
									
										
										
										
											2018-12-19 12:57:47 -05:00
										 |  |  |     ///          otherwise, an error code upon failure.
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     ResultCode InitializeForKernelProcess(const u32* capabilities, std::size_t num_capabilities, | 
					
						
							| 
									
										
										
										
											2021-02-12 17:58:31 -08:00
										 |  |  |                                           KPageTable& page_table); | 
					
						
							| 
									
										
										
										
											2018-12-19 12:57:47 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /// Initializes this process capabilities instance for a userland process.
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     /// @param capabilities     The capabilities to parse.
 | 
					
						
							|  |  |  |     /// @param num_capabilities The total number of capabilities to parse.
 | 
					
						
							| 
									
										
										
										
											2020-04-08 17:30:34 -04:00
										 |  |  |     /// @param page_table       The memory manager to use for handling any mapping-related
 | 
					
						
							| 
									
										
										
										
											2018-12-19 12:57:47 -05:00
										 |  |  |     ///                         operations (such as mapping IO memory, etc).
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							| 
									
										
										
										
											2021-05-21 01:05:04 -04:00
										 |  |  |     /// @returns ResultSuccess if this capabilities instance was able to be initialized,
 | 
					
						
							| 
									
										
										
										
											2018-12-19 12:57:47 -05:00
										 |  |  |     ///          otherwise, an error code upon failure.
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     ResultCode InitializeForUserProcess(const u32* capabilities, std::size_t num_capabilities, | 
					
						
							| 
									
										
										
										
											2021-02-12 17:58:31 -08:00
										 |  |  |                                         KPageTable& page_table); | 
					
						
							| 
									
										
										
										
											2018-12-19 12:57:47 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /// Initializes this process capabilities instance for a process that does not
 | 
					
						
							|  |  |  |     /// have any metadata to parse.
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     /// This is necessary, as we allow running raw executables, and the internal
 | 
					
						
							|  |  |  |     /// kernel process capabilities also determine what CPU cores the process is
 | 
					
						
							|  |  |  |     /// allowed to run on, and what priorities are allowed for  threads. It also
 | 
					
						
							|  |  |  |     /// determines the max handle table size, what the program type is, whether or
 | 
					
						
							|  |  |  |     /// not the process can be debugged, or whether it's possible for a process to
 | 
					
						
							|  |  |  |     /// forcibly debug another process.
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     /// Given the above, this essentially enables all capabilities across the board
 | 
					
						
							|  |  |  |     /// for the process. It allows the process to:
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     /// - Run on any core
 | 
					
						
							|  |  |  |     /// - Use any thread priority
 | 
					
						
							|  |  |  |     /// - Use the maximum amount of handles a process is allowed to.
 | 
					
						
							|  |  |  |     /// - Be debuggable
 | 
					
						
							|  |  |  |     /// - Forcibly debug other processes.
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     /// Note that this is not a behavior that the kernel allows a process to do via
 | 
					
						
							|  |  |  |     /// a single function like this. This is yuzu-specific behavior to handle
 | 
					
						
							|  |  |  |     /// executables with no capability descriptors whatsoever to derive behavior from.
 | 
					
						
							|  |  |  |     /// It being yuzu-specific is why this is also not the default behavior and not
 | 
					
						
							|  |  |  |     /// done by default in the constructor.
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     void InitializeForMetadatalessProcess(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-19 19:09:18 -05:00
										 |  |  |     /// Gets the allowable core mask
 | 
					
						
							|  |  |  |     u64 GetCoreMask() const { | 
					
						
							|  |  |  |         return core_mask; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /// Gets the allowable priority mask
 | 
					
						
							|  |  |  |     u64 GetPriorityMask() const { | 
					
						
							|  |  |  |         return priority_mask; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-20 22:54:05 -05:00
										 |  |  |     /// Gets the SVC access permission bits
 | 
					
						
							|  |  |  |     const SyscallCapabilities& GetServiceCapabilities() const { | 
					
						
							|  |  |  |         return svc_capabilities; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-19 21:14:47 -05:00
										 |  |  |     /// Gets the valid interrupt bits.
 | 
					
						
							|  |  |  |     const InterruptCapabilities& GetInterruptCapabilities() const { | 
					
						
							|  |  |  |         return interrupt_capabilities; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /// Gets the program type for this process.
 | 
					
						
							|  |  |  |     ProgramType GetProgramType() const { | 
					
						
							|  |  |  |         return program_type; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-19 21:43:10 -05:00
										 |  |  |     /// Gets the number of total allowable handles for the process' handle table.
 | 
					
						
							| 
									
										
										
										
											2019-02-25 10:13:52 -05:00
										 |  |  |     s32 GetHandleTableSize() const { | 
					
						
							| 
									
										
										
										
											2018-12-19 21:43:10 -05:00
										 |  |  |         return handle_table_size; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-19 21:28:44 -05:00
										 |  |  |     /// Gets the kernel version value.
 | 
					
						
							|  |  |  |     u32 GetKernelVersion() const { | 
					
						
							|  |  |  |         return kernel_version; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-20 23:40:30 -05:00
										 |  |  |     /// Whether or not this process can be debugged.
 | 
					
						
							|  |  |  |     bool IsDebuggable() const { | 
					
						
							|  |  |  |         return is_debuggable; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /// Whether or not this process can forcibly debug another
 | 
					
						
							|  |  |  |     /// process, even if that process is not considered debuggable.
 | 
					
						
							|  |  |  |     bool CanForceDebug() const { | 
					
						
							|  |  |  |         return can_force_debug; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-19 12:57:47 -05:00
										 |  |  | private: | 
					
						
							|  |  |  |     /// Attempts to parse a given sequence of capability descriptors.
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     /// @param capabilities     The sequence of capability descriptors to parse.
 | 
					
						
							|  |  |  |     /// @param num_capabilities The number of descriptors within the given sequence.
 | 
					
						
							| 
									
										
										
										
											2020-04-08 17:30:34 -04:00
										 |  |  |     /// @param page_table       The memory manager that will perform any memory
 | 
					
						
							| 
									
										
										
										
											2018-12-19 12:57:47 -05:00
										 |  |  |     ///                         mapping if necessary.
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							| 
									
										
										
										
											2021-05-21 01:05:04 -04:00
										 |  |  |     /// @return ResultSuccess if no errors occur, otherwise an error code.
 | 
					
						
							| 
									
										
										
										
											2018-12-19 12:57:47 -05:00
										 |  |  |     ///
 | 
					
						
							|  |  |  |     ResultCode ParseCapabilities(const u32* capabilities, std::size_t num_capabilities, | 
					
						
							| 
									
										
										
										
											2021-02-12 17:58:31 -08:00
										 |  |  |                                  KPageTable& page_table); | 
					
						
							| 
									
										
										
										
											2018-12-19 12:57:47 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /// Attempts to parse a capability descriptor that is only represented by a
 | 
					
						
							|  |  |  |     /// single flag set.
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     /// @param set_flags    Running set of flags that are used to catch
 | 
					
						
							|  |  |  |     ///                     flags being initialized more than once when they shouldn't be.
 | 
					
						
							|  |  |  |     /// @param set_svc_bits Running set of bits representing the allowed supervisor calls mask.
 | 
					
						
							|  |  |  |     /// @param flag         The flag to attempt to parse.
 | 
					
						
							| 
									
										
										
										
											2020-04-08 17:30:34 -04:00
										 |  |  |     /// @param page_table   The memory manager that will perform any memory
 | 
					
						
							| 
									
										
										
										
											2018-12-19 12:57:47 -05:00
										 |  |  |     ///                     mapping if necessary.
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							| 
									
										
										
										
											2021-05-21 01:05:04 -04:00
										 |  |  |     /// @return ResultSuccess if no errors occurred, otherwise an error code.
 | 
					
						
							| 
									
										
										
										
											2018-12-19 12:57:47 -05:00
										 |  |  |     ///
 | 
					
						
							|  |  |  |     ResultCode ParseSingleFlagCapability(u32& set_flags, u32& set_svc_bits, u32 flag, | 
					
						
							| 
									
										
										
										
											2021-02-12 17:58:31 -08:00
										 |  |  |                                          KPageTable& page_table); | 
					
						
							| 
									
										
										
										
											2018-12-19 12:57:47 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /// Clears the internal state of this process capability instance. Necessary,
 | 
					
						
							|  |  |  |     /// to have a sane starting point due to us allowing running executables without
 | 
					
						
							|  |  |  |     /// configuration metadata. We assume a process is not going to have metadata,
 | 
					
						
							|  |  |  |     /// and if it turns out that the process does, in fact, have metadata, then
 | 
					
						
							|  |  |  |     /// we attempt to parse it. Thus, we need this to reset data members back to
 | 
					
						
							|  |  |  |     /// a good state.
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     /// DO NOT ever make this a public member function. This isn't an invariant
 | 
					
						
							|  |  |  |     /// anything external should depend upon (and if anything comes to rely on it,
 | 
					
						
							|  |  |  |     /// you should immediately be questioning the design of that thing, not this
 | 
					
						
							|  |  |  |     /// class. If the kernel itself can run without depending on behavior like that,
 | 
					
						
							|  |  |  |     /// then so can yuzu).
 | 
					
						
							|  |  |  |     ///
 | 
					
						
							|  |  |  |     void Clear(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /// Handles flags related to the priority and core number capability flags.
 | 
					
						
							|  |  |  |     ResultCode HandlePriorityCoreNumFlags(u32 flags); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /// Handles flags related to determining the allowable SVC mask.
 | 
					
						
							|  |  |  |     ResultCode HandleSyscallFlags(u32& set_svc_bits, u32 flags); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /// Handles flags related to mapping physical memory pages.
 | 
					
						
							| 
									
										
										
										
											2021-02-12 17:58:31 -08:00
										 |  |  |     ResultCode HandleMapPhysicalFlags(u32 flags, u32 size_flags, KPageTable& page_table); | 
					
						
							| 
									
										
										
										
											2018-12-19 12:57:47 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /// Handles flags related to mapping IO pages.
 | 
					
						
							| 
									
										
										
										
											2021-02-12 17:58:31 -08:00
										 |  |  |     ResultCode HandleMapIOFlags(u32 flags, KPageTable& page_table); | 
					
						
							| 
									
										
										
										
											2018-12-19 12:57:47 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-25 01:44:46 -04:00
										 |  |  |     /// Handles flags related to mapping physical memory regions.
 | 
					
						
							|  |  |  |     ResultCode HandleMapRegionFlags(u32 flags, KPageTable& page_table); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-19 12:57:47 -05:00
										 |  |  |     /// Handles flags related to the interrupt capability flags.
 | 
					
						
							|  |  |  |     ResultCode HandleInterruptFlags(u32 flags); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /// Handles flags related to the program type.
 | 
					
						
							|  |  |  |     ResultCode HandleProgramTypeFlags(u32 flags); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /// Handles flags related to the handle table size.
 | 
					
						
							|  |  |  |     ResultCode HandleHandleTableFlags(u32 flags); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /// Handles flags related to the kernel version capability flags.
 | 
					
						
							|  |  |  |     ResultCode HandleKernelVersionFlags(u32 flags); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /// Handles flags related to debug-specific capabilities.
 | 
					
						
							|  |  |  |     ResultCode HandleDebugFlags(u32 flags); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     SyscallCapabilities svc_capabilities; | 
					
						
							|  |  |  |     InterruptCapabilities interrupt_capabilities; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     u64 core_mask = 0; | 
					
						
							|  |  |  |     u64 priority_mask = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-25 10:13:52 -05:00
										 |  |  |     s32 handle_table_size = 0; | 
					
						
							| 
									
										
										
										
											2018-12-19 12:57:47 -05:00
										 |  |  |     u32 kernel_version = 0; | 
					
						
							| 
									
										
										
										
											2018-12-19 21:14:47 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ProgramType program_type = ProgramType::SysModule; | 
					
						
							| 
									
										
										
										
											2018-12-19 12:57:47 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     bool is_debuggable = false; | 
					
						
							|  |  |  |     bool can_force_debug = false; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // namespace Kernel
 |