// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include #include "common/bit_field.h" #include "common/common_funcs.h" #include "common/common_types.h" namespace Kernel::Svc { using Handle = u32; enum class MemoryState : u32 { Free = 0x00, Io = 0x01, Static = 0x02, Code = 0x03, CodeData = 0x04, Normal = 0x05, Shared = 0x06, Alias = 0x07, AliasCode = 0x08, AliasCodeData = 0x09, Ipc = 0x0A, Stack = 0x0B, ThreadLocal = 0x0C, Transferred = 0x0D, SharedTransferred = 0x0E, SharedCode = 0x0F, Inaccessible = 0x10, NonSecureIpc = 0x11, NonDeviceIpc = 0x12, Kernel = 0x13, GeneratedCode = 0x14, CodeOut = 0x15, Coverage = 0x16, Insecure = 0x17, }; DECLARE_ENUM_FLAG_OPERATORS(MemoryState); enum class MemoryAttribute : u32 { Locked = (1 << 0), IpcLocked = (1 << 1), DeviceShared = (1 << 2), Uncached = (1 << 3), PermissionLocked = (1 << 4), }; DECLARE_ENUM_FLAG_OPERATORS(MemoryAttribute); enum class MemoryPermission : u32 { None = (0 << 0), Read = (1 << 0), Write = (1 << 1), Execute = (1 << 2), ReadWrite = Read | Write, ReadExecute = Read | Execute, DontCare = (1 << 28), }; DECLARE_ENUM_FLAG_OPERATORS(MemoryPermission); enum class SignalType : u32 { Signal = 0, SignalAndIncrementIfEqual = 1, SignalAndModifyByWaitingCountIfEqual = 2, }; enum class ArbitrationType : u32 { WaitIfLessThan = 0, DecrementAndWaitIfLessThan = 1, WaitIfEqual = 2, }; enum class YieldType : s64 { WithoutCoreMigration = 0, WithCoreMigration = -1, ToAnyThread = -2, }; enum class ThreadExitReason : u32 { ExitThread = 0, TerminateThread = 1, ExitProcess = 2, TerminateProcess = 3, }; enum class ThreadActivity : u32 { Runnable = 0, Paused = 1, }; constexpr inline s32 IdealCoreDontCare = -1; constexpr inline s32 IdealCoreUseProcessValue = -2; constexpr inline s32 IdealCoreNoUpdate = -3; constexpr inline s32 LowestThreadPriority = 63; constexpr inline s32 HighestThreadPriority = 0; constexpr inline s32 SystemThreadPriorityHighest = 16; enum class ProcessState : u32 { Created = 0, CreatedAttached = 1, Running = 2, Crashed = 3, RunningAttached = 4, Terminating = 5, Terminated = 6, DebugBreak = 7, }; enum class ProcessExitReason : u32 { ExitProcess = 0, TerminateProcess = 1, Exception = 2, }; constexpr inline size_t ThreadLocalRegionSize = 0x200; struct PageInfo { u32 flags; }; // Info Types. enum class InfoType : u32 { CoreMask = 0, PriorityMask = 1, AliasRegionAddress = 2, AliasRegionSize = 3, HeapRegionAddress = 4, HeapRegionSize = 5, TotalMemorySize = 6, UsedMemorySize = 7, DebuggerAttached = 8, ResourceLimit = 9, IdleTickCount = 10, RandomEntropy = 11, AslrRegionAddress = 12, AslrRegionSize = 13, StackRegionAddress = 14, StackRegionSize = 15, SystemResourceSizeTotal = 16, SystemResourceSizeUsed = 17, ProgramId = 18, InitialProcessIdRange = 19, UserExceptionContextAddress = 20, TotalNonSystemMemorySize = 21, UsedNonSystemMemorySize = 22, IsApplication = 23, FreeThreadCount = 24, ThreadTickCount = 25, IsSvcPermitted = 26, IoRegionHint = 27, MesosphereMeta = 65000, MesosphereCurrentProcess = 65001, }; enum class BreakReason : u32 { Panic = 0, Assert = 1, User = 2, PreLoadDll = 3, PostLoadDll = 4, PreUnloadDll = 5, PostUnloadDll = 6, CppException = 7, NotificationOnlyFlag = 0x80000000, }; DECLARE_ENUM_FLAG_OPERATORS(BreakReason); enum class DebugEvent : u32 { CreateProcess = 0, CreateThread = 1, ExitProcess = 2, ExitThread = 3, Exception = 4, }; enum class DebugThreadParam : u32 { Priority = 0, State = 1, IdealCore = 2, CurrentCore = 3, AffinityMask = 4, }; enum class DebugException : u32 { UndefinedInstruction = 0, InstructionAbort = 1, DataAbort = 2, AlignmentFault = 3, DebuggerAttached = 4, BreakPoint = 5, UserBreak = 6, DebuggerBreak = 7, UndefinedSystemCall = 8, MemorySystemError = 9, }; enum class DebugEventFlag : u32 { Stopped = (1u << 0), }; enum class BreakPointType : u32 { HardwareInstruction = 0, HardwareData = 1, }; enum class HardwareBreakPointRegisterName : u32 { I0 = 0, I1 = 1, I2 = 2, I3 = 3, I4 = 4, I5 = 5, I6 = 6, I7 = 7, I8 = 8, I9 = 9, I10 = 10, I11 = 11, I12 = 12, I13 = 13, I14 = 14, I15 = 15, D0 = 16, D1 = 17, D2 = 18, D3 = 19, D4 = 20, D5 = 21, D6 = 22, D7 = 23, D8 = 24, D9 = 25, D10 = 26, D11 = 27, D12 = 28, D13 = 29, D14 = 30, D15 = 31, }; namespace lp64 { struct LastThreadContext { u64 fp; u64 sp; u64 lr; u64 pc; }; struct PhysicalMemoryInfo { u64 physical_address; u64 virtual_address; u64 size; }; struct DebugInfoCreateProcess { u64 program_id; u64 process_id; std::array name; u32 flags; u64 user_exception_context_address; // 5.0.0+ }; struct DebugInfoCreateThread { u64 thread_id; u64 tls_address; // Removed in 11.0.0 u64 entrypoint; }; struct DebugInfoExitProcess { ProcessExitReason reason; }; struct DebugInfoExitThread { ThreadExitReason reason; }; struct DebugInfoUndefinedInstructionException { u32 insn; }; struct DebugInfoDataAbortException { u64 address; }; struct DebugInfoAlignmentFaultException { u64 address; }; struct DebugInfoBreakPointException { BreakPointType type; u64 address; }; struct DebugInfoUserBreakException { BreakReason break_reason; u64 address; u64 size; }; struct DebugInfoDebuggerBreakException { std::array active_thread_ids; }; struct DebugInfoUndefinedSystemCallException { u32 id; }; union DebugInfoSpecificException { DebugInfoUndefinedInstructionException undefined_instruction; DebugInfoDataAbortException data_abort; DebugInfoAlignmentFaultException alignment_fault; DebugInfoBreakPointException break_point; DebugInfoUserBreakException user_break; DebugInfoDebuggerBreakException debugger_break; DebugInfoUndefinedSystemCallException undefined_system_call; u64 raw; }; struct DebugInfoException { DebugException type; u64 address; DebugInfoSpecificException specific; }; union DebugInfo { DebugInfoCreateProcess create_process; DebugInfoCreateThread create_thread; DebugInfoExitProcess exit_process; DebugInfoExitThread exit_thread; DebugInfoException exception; }; struct DebugEventInfo { DebugEvent type; u32 flags; u64 thread_id; DebugInfo info; }; static_assert(sizeof(DebugEventInfo) >= 0x40); struct SecureMonitorArguments { std::array r; }; static_assert(sizeof(SecureMonitorArguments) == 0x40); } // namespace lp64 namespace ilp32 { struct LastThreadContext { u32 fp; u32 sp; u32 lr; u32 pc; }; struct PhysicalMemoryInfo { u64 physical_address; u32 virtual_address; u32 size; }; struct DebugInfoCreateProcess { u64 program_id; u64 process_id; std::array name; u32 flags; u32 user_exception_context_address; // 5.0.0+ }; struct DebugInfoCreateThread { u64 thread_id; u32 tls_address; // Removed in 11.0.0 u32 entrypoint; }; struct DebugInfoExitProcess { ProcessExitReason reason; }; struct DebugInfoExitThread { ThreadExitReason reason; }; struct DebugInfoUndefinedInstructionException { u32 insn; }; struct DebugInfoDataAbortException { u32 address; }; struct DebugInfoAlignmentFaultException { u32 address; }; struct DebugInfoBreakPointException { BreakPointType type; u32 address; }; struct DebugInfoUserBreakException { BreakReason break_reason; u32 address; u32 size; }; struct DebugInfoDebuggerBreakException { std::array active_thread_ids; }; struct DebugInfoUndefinedSystemCallException { u32 id; }; union DebugInfoSpecificException { DebugInfoUndefinedInstructionException undefined_instruction; DebugInfoDataAbortException data_abort; DebugInfoAlignmentFaultException alignment_fault; DebugInfoBreakPointException break_point; DebugInfoUserBreakException user_break; DebugInfoDebuggerBreakException debugger_break; DebugInfoUndefinedSystemCallException undefined_system_call; u64 raw; }; struct DebugInfoException { DebugException type; u32 address; DebugInfoSpecificException specific; }; union DebugInfo { DebugInfoCreateProcess create_process; DebugInfoCreateThread create_thread; DebugInfoExitProcess exit_process; DebugInfoExitThread exit_thread; DebugInfoException exception; }; struct DebugEventInfo { DebugEvent type; u32 flags; u64 thread_id; DebugInfo info; }; struct SecureMonitorArguments { std::array r; }; static_assert(sizeof(SecureMonitorArguments) == 0x20); } // namespace ilp32 struct ThreadContext { std::array r; u64 fp; u64 lr; u64 sp; u64 pc; u32 pstate; u32 padding; std::array v; u32 fpcr; u32 fpsr; u64 tpidr; }; static_assert(sizeof(ThreadContext) == 0x320); struct MemoryInfo { u64 base_address; u64 size; MemoryState state; MemoryAttribute attribute; MemoryPermission permission; u32 ipc_count; u32 device_count; u32 padding; }; enum class LimitableResource : u32 { PhysicalMemoryMax = 0, ThreadCountMax = 1, EventCountMax = 2, TransferMemoryCountMax = 3, SessionCountMax = 4, Count, }; enum class IoPoolType : u32 { // Not supported. Count = 0, }; enum class MemoryMapping : u32 { IoRegister = 0, Uncached = 1, Memory = 2, }; enum class MapDeviceAddressSpaceFlag : u32 { None = (0U << 0), NotIoRegister = (1U << 0), }; DECLARE_ENUM_FLAG_OPERATORS(MapDeviceAddressSpaceFlag); union MapDeviceAddressSpaceOption { u32 raw; BitField<0, 16, MemoryPermission> permission; BitField<16, 1, MapDeviceAddressSpaceFlag> flags; BitField<17, 15, u32> reserved; }; enum class KernelDebugType : u32 { Thread = 0, ThreadCallStack = 1, KernelObject = 2, Handle_ = 3, Memory = 4, PageTable = 5, CpuUtilization = 6, Process = 7, SuspendProcess = 8, ResumeProcess = 9, Port = 10, }; enum class KernelTraceState : u32 { Disabled = 0, Enabled = 1, }; enum class CodeMemoryOperation : u32 { Map = 0, MapToOwner = 1, Unmap = 2, UnmapFromOwner = 3, }; enum class InterruptType : u32 { Edge = 0, Level = 1, }; enum class DeviceName { Afi = 0, Avpc = 1, Dc = 2, Dcb = 3, Hc = 4, Hda = 5, Isp2 = 6, MsencNvenc = 7, Nv = 8, Nv2 = 9, Ppcs = 10, Sata = 11, Vi = 12, Vic = 13, XusbHost = 14, XusbDev = 15, Tsec = 16, Ppcs1 = 17, Dc1 = 18, Sdmmc1a = 19, Sdmmc2a = 20, Sdmmc3a = 21, Sdmmc4a = 22, Isp2b = 23, Gpu = 24, Gpub = 25, Ppcs2 = 26, Nvdec = 27, Ape = 28, Se = 29, Nvjpg = 30, Hc1 = 31, Se1 = 32, Axiap = 33, Etr = 34, Tsecb = 35, Tsec1 = 36, Tsecb1 = 37, Nvdec1 = 38, Count, }; enum class SystemInfoType : u32 { TotalPhysicalMemorySize = 0, UsedPhysicalMemorySize = 1, InitialProcessIdRange = 2, }; enum class ProcessInfoType : u32 { ProcessState = 0, }; enum class ProcessActivity : u32 { Runnable, Paused, }; enum class CreateProcessFlag : u32 { // Is 64 bit? Is64Bit = (1 << 0), // What kind of address space? AddressSpaceShift = 1, AddressSpaceMask = (7 << AddressSpaceShift), AddressSpace32Bit = (0 << AddressSpaceShift), AddressSpace64BitDeprecated = (1 << AddressSpaceShift), AddressSpace32BitWithoutAlias = (2 << AddressSpaceShift), AddressSpace64Bit = (3 << AddressSpaceShift), // Should JIT debug be done on crash? EnableDebug = (1 << 4), // Should ASLR be enabled for the process? EnableAslr = (1 << 5), // Is the process an application? IsApplication = (1 << 6), // 4.x deprecated: Should use secure memory? DeprecatedUseSecureMemory = (1 << 7), // 5.x+ Pool partition type. PoolPartitionShift = 7, PoolPartitionMask = (0xF << PoolPartitionShift), PoolPartitionApplication = (0 << PoolPartitionShift), PoolPartitionApplet = (1 << PoolPartitionShift), PoolPartitionSystem = (2 << PoolPartitionShift), PoolPartitionSystemNonSecure = (3 << PoolPartitionShift), // 7.x+ Should memory allocation be optimized? This requires IsApplication. OptimizeMemoryAllocation = (1 << 11), // 11.x+ DisableDeviceAddressSpaceMerge. DisableDeviceAddressSpaceMerge = (1 << 12), // Mask of all flags. All = Is64Bit | AddressSpaceMask | EnableDebug | EnableAslr | IsApplication | PoolPartitionMask | OptimizeMemoryAllocation | DisableDeviceAddressSpaceMerge, }; DECLARE_ENUM_FLAG_OPERATORS(CreateProcessFlag); struct CreateProcessParameter { std::array name; u32 version; u64 program_id; u64 code_address; s32 code_num_pages; CreateProcessFlag flags; Handle reslimit; s32 system_resource_num_pages; }; static_assert(sizeof(CreateProcessParameter) == 0x30); constexpr size_t NumSupervisorCalls = 0xC0; using SvcAccessFlagSet = std::bitset; enum class InitialProcessIdRangeInfo : u64 { Minimum = 0, Maximum = 1, }; } // namespace Kernel::Svc