2020-04-19 23:04:05 +02:00
// SPDX-License-Identifier: MPL-2.0
2020-03-27 20:36:02 +01:00
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
2019-09-24 22:54:27 +02:00
# pragma once
2020-03-26 15:33:19 +01:00
# include <list>
2020-10-07 17:41:13 +02:00
# include <kernel/memory.h>
2020-10-21 19:09:35 +02:00
# include <vfs/npdm.h>
2019-09-24 22:54:27 +02:00
# include "KThread.h"
Framebuffer and NativeActivity
What was added:
* Framebuffer
* NativeActivity
* NV Services
* IOCTL Handler
* NV Devices:
* * /dev/nvmap - 0xC0080101, 0xC0080103, 0xC0200104, 0xC0180105, 0xC00C0109, 0xC008010E
* * /dev/nvhost-as-gpu
* * /dev/nvhost-channel - 0x40044801, 0xC0104809, 0xC010480B, 0xC018480C, 0x4004480D, 0xC020481A, 0x40084714
* * /dev/nvhost-ctrl
* * /dev/nvhost-ctrl-gpu - 0x80044701, 0x80284702, 0xC0184706, 0xC0B04705, 0x80084714
* SVCs:
* * SetMemoryAttribute
* * CreateTransferMemory
* * ResetSignal
* * GetSystemTick
* Addition of Compact Logger
What was fixed:
* SVCs:
* * SetHeapSize
* * SetMemoryAttribute
* * QueryMemory
* A release build would not set CMAKE_BUILD_TYPE to "RELEASE"
* The logger code was simplified
2019-11-13 21:09:31 +01:00
# include "KTransferMemory.h"
2019-09-24 22:54:27 +02:00
# include "KSession.h"
Framebuffer and NativeActivity
What was added:
* Framebuffer
* NativeActivity
* NV Services
* IOCTL Handler
* NV Devices:
* * /dev/nvmap - 0xC0080101, 0xC0080103, 0xC0200104, 0xC0180105, 0xC00C0109, 0xC008010E
* * /dev/nvhost-as-gpu
* * /dev/nvhost-channel - 0x40044801, 0xC0104809, 0xC010480B, 0xC018480C, 0x4004480D, 0xC020481A, 0x40084714
* * /dev/nvhost-ctrl
* * /dev/nvhost-ctrl-gpu - 0x80044701, 0x80284702, 0xC0184706, 0xC0B04705, 0x80084714
* SVCs:
* * SetMemoryAttribute
* * CreateTransferMemory
* * ResetSignal
* * GetSystemTick
* Addition of Compact Logger
What was fixed:
* SVCs:
* * SetHeapSize
* * SetMemoryAttribute
* * QueryMemory
* A release build would not set CMAKE_BUILD_TYPE to "RELEASE"
* The logger code was simplified
2019-11-13 21:09:31 +01:00
# include "KEvent.h"
2019-09-24 22:54:27 +02:00
2020-03-25 18:59:37 +01:00
namespace skyline {
namespace constant {
2020-09-26 07:17:57 +02:00
constexpr u16 TlsSlotSize { 0x200 } ; //!< The size of a single TLS slot
constexpr u8 TlsSlots { PAGE_SIZE / TlsSlotSize } ; //!< The amount of TLS slots in a single page
2020-09-28 12:05:17 +02:00
constexpr KHandle BaseHandleIndex { 0xD000 } ; //!< The index of the base handle
2020-09-26 07:17:57 +02:00
constexpr u32 MtxOwnerMask { 0xBFFFFFFF } ; //!< The mask of values which contain the owner of a mutex
2020-03-25 18:59:37 +01:00
}
namespace kernel : : type {
2019-09-24 22:54:27 +02:00
/**
2020-10-07 17:41:13 +02:00
* @ brief KProcess manages process - global state such as memory , kernel handles allocated to the process and synchronization primitives
2020-09-28 12:05:17 +02:00
*/
2020-03-25 18:59:37 +01:00
class KProcess : public KSyncObject {
2020-11-03 10:44:09 +01:00
public : // We have intermittent public/private members to ensure proper construction/destruction order
MemoryManager memory ;
2020-10-20 11:22:15 +02:00
2020-03-25 18:59:37 +01:00
private :
2020-10-07 17:41:13 +02:00
struct WaitStatus {
std : : atomic_bool flag { false } ;
i8 priority ;
KHandle handle ;
2020-11-08 20:54:15 +01:00
u32 * mutex { } ;
2020-10-07 17:41:13 +02:00
WaitStatus ( i8 priority , KHandle handle ) ;
2020-11-08 20:54:15 +01:00
WaitStatus ( i8 priority , KHandle handle , u32 * mutex ) ;
2020-10-07 17:41:13 +02:00
} ;
std : : unordered_map < u64 , std : : vector < std : : shared_ptr < WaitStatus > > > mutexes ; //!< A map from a mutex's address to a vector of Mutex objects for threads waiting on it
std : : unordered_map < u64 , std : : list < std : : shared_ptr < WaitStatus > > > conditionals ; //!< A map from a conditional variable's address to a vector of threads waiting on it
2020-10-28 17:00:39 +01:00
std : : mutex mutexLock ;
std : : mutex conditionalLock ;
2020-09-25 16:35:10 +02:00
2020-11-03 10:44:09 +01:00
size_t threadIndex { } ; //!< The ID assigned to the next created thread
2019-09-24 22:54:27 +02:00
/**
2020-09-28 12:05:17 +02:00
* @ brief The status of a single TLS page ( A page is 4096 bytes on ARMv8 )
* Each TLS page has 8 slots , each 0x200 ( 512 ) bytes in size
* The first slot of the first page is reserved for user - mode exception handling
* @ url https : //switchbrew.org/wiki/Thread_Local_Storage
2020-03-25 18:59:37 +01:00
*/
struct TlsPage {
2020-09-26 07:17:57 +02:00
u8 index { } ; //!< The slots are assigned sequentially, this holds the index of the last TLS slot reserved
2020-10-07 17:41:13 +02:00
std : : shared_ptr < KPrivateMemory > memory ;
2020-03-25 18:59:37 +01:00
2020-11-08 20:54:15 +01:00
TlsPage ( const std : : shared_ptr < KPrivateMemory > & memory ) ;
2020-03-25 18:59:37 +01:00
2020-11-08 20:54:15 +01:00
u8 * ReserveSlot ( ) ;
2020-03-25 18:59:37 +01:00
2020-11-08 20:54:15 +01:00
u8 * Get ( u8 index ) ;
2020-10-07 17:41:13 +02:00
2020-03-25 18:59:37 +01:00
bool Full ( ) ;
} ;
2019-09-24 22:54:27 +02:00
2020-10-07 17:41:13 +02:00
public :
2020-10-17 13:38:27 +02:00
std : : shared_ptr < KPrivateMemory > mainThreadStack ;
2020-10-07 17:41:13 +02:00
std : : shared_ptr < KPrivateMemory > heap ;
std : : vector < std : : shared_ptr < TlsPage > > tlsPages ;
2020-11-03 10:44:09 +01:00
std : : shared_ptr < KThread > mainThread ;
2020-10-21 19:09:35 +02:00
vfs : : NPDM npdm ;
2020-10-07 17:41:13 +02:00
2020-11-03 10:44:09 +01:00
private :
std : : shared_mutex handleMutex ;
std : : vector < std : : shared_ptr < KObject > > handles ;
public :
2020-10-07 17:41:13 +02:00
KProcess ( const DeviceState & state ) ;
2019-09-24 22:54:27 +02:00
/**
2020-10-07 17:41:13 +02:00
* @ note This requires VMM regions to be initialized , it will map heap at an arbitrary location otherwise
2020-09-28 12:05:17 +02:00
*/
2020-10-07 17:41:13 +02:00
void InitializeHeap ( ) ;
2019-09-24 22:54:27 +02:00
/**
2020-10-07 17:41:13 +02:00
* @ return A 0x200 TLS slot allocated inside the TLS / IO region
2020-09-28 12:05:17 +02:00
*/
2020-11-08 20:54:15 +01:00
u8 * AllocateTlsSlot ( ) ;
2020-01-21 08:16:57 +01:00
2020-10-21 19:09:35 +02:00
/**
* @ note The default values are for the main thread and will use values from the NPDM
*/
std : : shared_ptr < KThread > CreateThread ( void * entry , u64 argument = 0 , void * stackTop = nullptr , i8 priority = - 1 , i8 idealCore = - 1 ) ;
2020-01-21 08:16:57 +01:00
2020-03-25 18:59:37 +01:00
/**
2020-09-28 12:05:17 +02:00
* @ brief The output for functions that return created kernel objects
2020-03-25 18:59:37 +01:00
* @ tparam objectClass The class of the kernel object
*/
template < typename objectClass >
struct HandleOut {
std : : shared_ptr < objectClass > item ; //!< A shared pointer to the object
KHandle handle ; //!< The handle of the object in the process
} ;
2020-02-05 07:42:53 +01:00
2020-03-25 18:59:37 +01:00
/**
* @ brief Creates a new handle to a KObject and adds it to the process handle_table
* @ tparam objectClass The class of the kernel object to create
* @ param args The arguments for the kernel object except handle , pid and state
*/
template < typename objectClass , typename . . . objectArgs >
HandleOut < objectClass > NewHandle ( objectArgs . . . args ) {
2020-10-07 17:41:13 +02:00
std : : unique_lock lock ( handleMutex ) ;
2020-03-25 18:59:37 +01:00
std : : shared_ptr < objectClass > item ;
if constexpr ( std : : is_same < objectClass , KThread > ( ) )
2020-10-07 17:41:13 +02:00
item = std : : make_shared < objectClass > ( state , constant : : BaseHandleIndex + handles . size ( ) , args . . . ) ;
2020-03-25 18:59:37 +01:00
else
item = std : : make_shared < objectClass > ( state , args . . . ) ;
2020-09-25 16:35:10 +02:00
handles . push_back ( std : : static_pointer_cast < KObject > ( item ) ) ;
2020-10-07 17:41:13 +02:00
return { item , static_cast < KHandle > ( ( constant : : BaseHandleIndex + handles . size ( ) ) - 1 ) } ;
2020-03-25 18:59:37 +01:00
}
2019-09-24 22:54:27 +02:00
2020-03-25 18:59:37 +01:00
/**
* @ brief Inserts an item into the process handle table
* @ return The handle of the corresponding item in the handle table
*/
template < typename objectClass >
KHandle InsertItem ( std : : shared_ptr < objectClass > & item ) {
2020-10-07 17:41:13 +02:00
std : : unique_lock lock ( handleMutex ) ;
2020-09-25 16:35:10 +02:00
handles . push_back ( std : : static_pointer_cast < KObject > ( item ) ) ;
2020-10-07 17:41:13 +02:00
return static_cast < KHandle > ( ( constant : : BaseHandleIndex + handles . size ( ) ) - 1 ) ;
2020-03-25 18:59:37 +01:00
}
2019-10-13 10:04:47 +02:00
2020-10-07 17:41:13 +02:00
template < typename objectClass = KObject >
2020-03-25 18:59:37 +01:00
std : : shared_ptr < objectClass > GetHandle ( KHandle handle ) {
2020-10-07 17:41:13 +02:00
std : : shared_lock lock ( handleMutex ) ;
2020-03-25 18:59:37 +01:00
KType objectType ;
2020-10-21 19:09:35 +02:00
if constexpr ( std : : is_same < objectClass , KThread > ( ) ) {
constexpr KHandle threadSelf { 0xFFFF8000 } ; // The handle used by threads to refer to themselves
if ( handle = = threadSelf )
return state . thread ;
2020-04-18 23:40:18 +02:00
objectType = KType : : KThread ;
2020-10-21 19:09:35 +02:00
} else if constexpr ( std : : is_same < objectClass , KProcess > ( ) )
2020-04-18 23:40:18 +02:00
objectType = KType : : KProcess ;
2020-03-25 18:59:37 +01:00
else if constexpr ( std : : is_same < objectClass , KSharedMemory > ( ) )
2020-04-18 23:40:18 +02:00
objectType = KType : : KSharedMemory ;
2020-03-25 18:59:37 +01:00
else if constexpr ( std : : is_same < objectClass , KTransferMemory > ( ) )
2020-04-18 23:40:18 +02:00
objectType = KType : : KTransferMemory ;
2020-03-25 18:59:37 +01:00
else if constexpr ( std : : is_same < objectClass , KPrivateMemory > ( ) )
2020-04-18 23:40:18 +02:00
objectType = KType : : KPrivateMemory ;
2020-03-25 18:59:37 +01:00
else if constexpr ( std : : is_same < objectClass , KSession > ( ) )
2020-04-18 23:40:18 +02:00
objectType = KType : : KSession ;
2020-03-25 18:59:37 +01:00
else if constexpr ( std : : is_same < objectClass , KEvent > ( ) )
2020-04-18 23:40:18 +02:00
objectType = KType : : KEvent ;
2019-09-24 22:54:27 +02:00
else
2020-03-25 18:59:37 +01:00
throw exception ( " KProcess::GetHandle couldn't determine object type " ) ;
try {
2020-11-08 20:54:15 +01:00
auto & item { handles . at ( handle - constant : : BaseHandleIndex ) } ;
2020-09-25 16:35:10 +02:00
if ( item ! = nullptr & & item - > objectType = = objectType )
2020-03-25 18:59:37 +01:00
return std : : static_pointer_cast < objectClass > ( item ) ;
2020-09-25 16:35:10 +02:00
else if ( item = = nullptr )
throw exception ( " GetHandle was called with a deleted handle: 0x{:X} " , handle ) ;
2020-03-25 18:59:37 +01:00
else
throw exception ( " Tried to get kernel object (0x{:X}) with different type : { } when object is { } " , handle, objectType, item->objectType);
} catch ( std : : out_of_range ) {
2020-10-23 20:23:16 +02:00
throw std : : out_of_range ( fmt : : format ( " GetHandle was called with an invalid handle: 0x{:X} " , handle ) ) ;
2020-03-25 18:59:37 +01:00
}
2019-09-24 22:54:27 +02:00
}
2019-10-16 14:41:30 +02:00
2020-10-07 17:41:13 +02:00
template < >
std : : shared_ptr < KObject > GetHandle < KObject > ( KHandle handle ) {
return handles . at ( handle - constant : : BaseHandleIndex ) ;
}
2020-03-25 18:59:37 +01:00
/**
* @ brief Retrieves a kernel memory object that owns the specified address
* @ param address The address to look for
* @ return A shared pointer to the corresponding KMemory object
*/
2020-11-08 20:54:15 +01:00
std : : optional < HandleOut < KMemory > > GetMemoryObject ( u8 * ptr ) ;
2020-01-21 08:16:57 +01:00
2020-03-25 18:59:37 +01:00
/**
2020-09-28 12:05:17 +02:00
* @ brief Closes a handle in the handle table
*/
inline void CloseHandle ( KHandle handle ) {
2020-09-25 16:35:10 +02:00
handles . at ( handle - constant : : BaseHandleIndex ) = nullptr ;
2020-03-25 18:59:37 +01:00
}
2020-01-21 08:16:57 +01:00
2020-03-25 18:59:37 +01:00
/**
2020-09-28 12:05:17 +02:00
* @ brief Locks the Mutex at the specified address
2020-03-25 18:59:37 +01:00
* @ param owner The handle of the current mutex owner
* @ return If the mutex was successfully locked
*/
2020-11-08 20:54:15 +01:00
bool MutexLock ( u32 * mutex , KHandle owner ) ;
2019-10-16 14:41:30 +02:00
2020-03-25 18:59:37 +01:00
/**
2020-09-28 12:05:17 +02:00
* @ brief Unlocks the Mutex at the specified address
2020-03-25 18:59:37 +01:00
* @ return If the mutex was successfully unlocked
*/
2020-11-08 20:54:15 +01:00
bool MutexUnlock ( u32 * mutex ) ;
2020-02-01 16:51:32 +01:00
2020-03-25 18:59:37 +01:00
/**
* @ param timeout The amount of time to wait for the conditional variable
* @ return If the conditional variable was successfully waited for or timed out
*/
2020-11-08 20:54:15 +01:00
bool ConditionalVariableWait ( void * conditional , u32 * mutex , u64 timeout ) ;
2020-02-01 16:51:32 +01:00
2020-03-25 18:59:37 +01:00
/**
2020-09-28 12:05:17 +02:00
* @ brief Signals a number of conditional variable waiters
2020-03-25 18:59:37 +01:00
* @ param amount The amount of waiters to signal
*/
2020-11-08 20:54:15 +01:00
void ConditionalVariableSignal ( void * conditional , u64 amount ) ;
Framebuffer and NativeActivity
What was added:
* Framebuffer
* NativeActivity
* NV Services
* IOCTL Handler
* NV Devices:
* * /dev/nvmap - 0xC0080101, 0xC0080103, 0xC0200104, 0xC0180105, 0xC00C0109, 0xC008010E
* * /dev/nvhost-as-gpu
* * /dev/nvhost-channel - 0x40044801, 0xC0104809, 0xC010480B, 0xC018480C, 0x4004480D, 0xC020481A, 0x40084714
* * /dev/nvhost-ctrl
* * /dev/nvhost-ctrl-gpu - 0x80044701, 0x80284702, 0xC0184706, 0xC0B04705, 0x80084714
* SVCs:
* * SetMemoryAttribute
* * CreateTransferMemory
* * ResetSignal
* * GetSystemTick
* Addition of Compact Logger
What was fixed:
* SVCs:
* * SetHeapSize
* * SetMemoryAttribute
* * QueryMemory
* A release build would not set CMAKE_BUILD_TYPE to "RELEASE"
* The logger code was simplified
2019-11-13 21:09:31 +01:00
2020-03-25 18:59:37 +01:00
/**
2020-09-28 12:05:17 +02:00
* @ brief Resets the object to an unsignalled state
*/
2020-03-25 18:59:37 +01:00
inline void ResetSignal ( ) {
signalled = false ;
}
} ;
}
2019-09-24 22:54:27 +02:00
}