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-10-13 10:04:47 +02:00
# include <os.h>
2020-09-28 12:05:17 +02:00
# include <kernel/types/KProcess.h>
2020-09-03 20:43:52 +02:00
# include "results.h"
2020-03-26 15:33:19 +01:00
# include "svc.h"
2019-09-24 22:54:27 +02:00
namespace skyline : : kernel : : svc {
2020-10-10 17:53:14 +02:00
void SetHeapSize ( const DeviceState & state ) {
auto size { state . ctx - > gpr . w1 } ;
2020-03-25 18:59:37 +01:00
2020-04-22 19:02:27 +02:00
if ( ! util : : IsAligned ( size , 0x200000 ) ) {
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidSize ;
state . ctx - > gpr . x1 = 0 ;
2020-03-25 18:59:37 +01:00
2019-11-17 21:19:01 +01:00
state . logger - > Warn ( " svcSetHeapSize: 'size' not divisible by 2MB: {} " , size ) ;
return ;
}
2020-03-25 18:59:37 +01:00
2020-09-26 07:17:57 +02:00
auto & heap { state . process - > heap } ;
2020-01-21 08:16:57 +01:00
heap - > Resize ( size ) ;
2020-03-25 18:59:37 +01:00
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = Result { } ;
state . ctx - > gpr . x1 = reinterpret_cast < u64 > ( heap - > ptr ) ;
2020-03-25 18:59:37 +01:00
2020-10-10 17:53:14 +02:00
state . logger - > Debug ( " svcSetHeapSize: Allocated at {} for 0x{:X} bytes " , heap - > ptr , heap - > size ) ;
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-10-10 17:53:14 +02:00
void SetMemoryAttribute ( const DeviceState & state ) {
auto pointer { reinterpret_cast < u8 * > ( state . ctx - > gpr . x0 ) } ;
2020-10-04 20:18:34 +02:00
if ( ! util : : PageAligned ( pointer ) ) {
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidAddress ;
2020-10-05 11:19:23 +02:00
state . logger - > Warn ( " svcSetMemoryAttribute: 'pointer' not page aligned: 0x{:X} " , pointer ) ;
2019-11-17 21:19:01 +01:00
return ;
}
2020-04-18 23:40:18 +02:00
2020-10-10 17:53:14 +02:00
auto size { state . ctx - > gpr . x1 } ;
2020-04-17 23:19:19 +02:00
if ( ! util : : PageAligned ( size ) ) {
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidSize ;
2020-01-21 08:16:57 +01:00
state . logger - > Warn ( " svcSetMemoryAttribute: 'size' {}: 0x{:X} " , size ? " not page aligned " : " is zero " , size ) ;
2019-11-17 21:19:01 +01:00
return ;
}
2020-04-18 23:40:18 +02:00
2020-10-10 17:53:14 +02:00
memory : : MemoryAttribute mask { . value = state . ctx - > gpr . w2 } ;
memory : : MemoryAttribute value { . value = state . ctx - > gpr . w3 } ;
2020-04-18 23:40:18 +02:00
2020-09-26 07:17:57 +02:00
auto maskedValue { mask . value | value . value } ;
2020-01-21 08:16:57 +01:00
if ( maskedValue ! = mask . value | | ! mask . isUncached | | mask . isDeviceShared | | mask . isBorrowed | | mask . isIpcLocked ) {
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidCombination ;
2020-01-21 08:16:57 +01:00
state . logger - > Warn ( " svcSetMemoryAttribute: 'mask' invalid: 0x{:X}, 0x{:X} " , mask . value , value . value ) ;
2019-11-17 21:19:01 +01:00
return ;
}
2020-04-18 23:40:18 +02:00
2020-10-07 17:41:13 +02:00
auto chunk { state . process - > memory . Get ( pointer ) } ;
2020-10-04 18:40:52 +02:00
if ( ! chunk ) {
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidAddress ;
2020-10-05 11:19:23 +02:00
state . logger - > Warn ( " svcSetMemoryAttribute: Cannot find memory region: 0x{:X} " , pointer ) ;
2020-01-21 08:16:57 +01:00
return ;
}
2020-04-18 23:40:18 +02:00
2020-03-25 18:59:37 +01:00
if ( ! chunk - > state . attributeChangeAllowed ) {
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidState ;
2020-10-05 11:19:23 +02:00
state . logger - > Warn ( " svcSetMemoryAttribute: Attribute change not allowed for chunk: 0x{:X} " , pointer ) ;
2020-01-21 08:16:57 +01:00
return ;
}
2020-04-18 23:40:18 +02:00
2020-10-04 18:40:52 +02:00
auto newChunk { * chunk } ;
2020-10-04 20:18:34 +02:00
newChunk . ptr = pointer ;
2020-10-04 18:40:52 +02:00
newChunk . size = size ;
newChunk . attributes . isUncached = value . isUncached ;
2020-10-07 17:41:13 +02:00
state . process - > memory . InsertChunk ( newChunk ) ;
2020-04-18 23:40:18 +02:00
2020-10-10 19:40:12 +02:00
state . logger - > Debug ( " svcSetMemoryAttribute: Set caching to {} at 0x{:X} for 0x{:X} bytes " , static_cast < bool > ( value . isUncached ) , pointer , size ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = Result { } ;
2020-01-21 08:16:57 +01:00
}
2020-10-10 17:53:14 +02:00
void MapMemory ( const DeviceState & state ) {
auto destination { reinterpret_cast < u8 * > ( state . ctx - > gpr . x0 ) } ;
auto source { reinterpret_cast < u8 * > ( state . ctx - > gpr . x1 ) } ;
auto size { state . ctx - > gpr . x2 } ;
2020-04-18 23:40:18 +02:00
2020-04-17 23:19:19 +02:00
if ( ! util : : PageAligned ( destination ) | | ! util : : PageAligned ( source ) ) {
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidAddress ;
2020-10-05 11:19:23 +02:00
state . logger - > Warn ( " svcMapMemory: Addresses not page aligned: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes) " , source , destination , size ) ;
2020-01-21 08:16:57 +01:00
return ;
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-04-18 23:40:18 +02:00
2020-04-17 23:19:19 +02:00
if ( ! util : : PageAligned ( size ) ) {
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidSize ;
2020-01-21 08:16:57 +01:00
state . logger - > Warn ( " svcMapMemory: 'size' {}: 0x{:X} " , size ? " not page aligned " : " is zero " , size ) ;
return ;
}
2020-04-18 23:40:18 +02:00
2020-10-07 17:41:13 +02:00
auto stack { state . process - > memory . stack } ;
2020-02-05 07:42:53 +01:00
if ( ! stack . IsInside ( destination ) ) {
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidMemoryRegion ;
2020-10-05 11:19:23 +02:00
state . logger - > Warn ( " svcMapMemory: Destination not within stack region: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes) " , source , destination , size ) ;
2020-01-21 08:16:57 +01:00
return ;
}
2020-03-25 19:57:05 +01:00
2020-10-07 17:41:13 +02:00
auto chunk { state . process - > memory . Get ( source ) } ;
2020-10-04 18:40:52 +02:00
if ( ! chunk ) {
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidAddress ;
2020-10-05 11:19:23 +02:00
state . logger - > Warn ( " svcMapMemory: Source has no descriptor: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes) " , source , destination , size ) ;
2020-01-21 08:16:57 +01:00
return ;
}
2020-10-04 18:40:52 +02:00
if ( ! chunk - > state . mapAllowed ) {
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidState ;
2020-10-05 11:19:23 +02:00
state . logger - > Warn ( " svcMapMemory: Source doesn't allow usage of svcMapMemory: Source: 0x{:X}, Destination: 0x{:X}, Size: 0x{:X}, MemoryState: 0x{:X} " , source , destination , size , chunk - > state . value ) ;
2019-11-17 21:19:01 +01:00
return ;
}
2020-03-25 19:57:05 +01:00
2020-10-04 18:40:52 +02:00
state . process - > NewHandle < type : : KPrivateMemory > ( destination , size , chunk - > permission , memory : : states : : Stack ) ;
memcpy ( destination , source , size ) ;
2020-03-25 19:57:05 +01:00
2020-09-26 07:17:57 +02:00
auto object { state . process - > GetMemoryObject ( source ) } ;
2020-02-05 07:42:53 +01:00
if ( ! object )
2020-10-05 11:19:23 +02:00
throw exception ( " svcMapMemory: Cannot find memory object in handle table for address 0x{:X} " , source ) ;
2020-02-01 16:51:32 +01:00
object - > item - > UpdatePermission ( source , size , { false , false , false } ) ;
2020-03-25 19:57:05 +01:00
2020-10-10 19:40:12 +02:00
state . logger - > Debug ( " svcMapMemory: Mapped range 0x{:X} - 0x{:X} to 0x{:X} - 0x{:X} (Size: 0x{:X} bytes) " , source , source + size , destination , destination + size , size ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = Result { } ;
2019-09-24 22:54:27 +02:00
}
2020-10-10 17:53:14 +02:00
void UnmapMemory ( const DeviceState & state ) {
auto source { reinterpret_cast < u8 * > ( state . ctx - > gpr . x0 ) } ;
auto destination { reinterpret_cast < u8 * > ( state . ctx - > gpr . x1 ) } ;
auto size { state . ctx - > gpr . x2 } ;
2020-03-25 19:57:05 +01:00
2020-04-17 23:19:19 +02:00
if ( ! util : : PageAligned ( destination ) | | ! util : : PageAligned ( source ) ) {
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidAddress ;
2020-02-01 16:51:32 +01:00
state . logger - > Warn ( " svcUnmapMemory: Addresses not page aligned: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes) " , source , destination , size ) ;
return ;
}
2020-03-25 19:57:05 +01:00
2020-04-17 23:19:19 +02:00
if ( ! util : : PageAligned ( size ) ) {
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidSize ;
2020-02-01 16:51:32 +01:00
state . logger - > Warn ( " svcUnmapMemory: 'size' {}: 0x{:X} " , size ? " not page aligned " : " is zero " , size ) ;
return ;
}
2020-03-25 19:57:05 +01:00
2020-10-07 17:41:13 +02:00
auto stack { state . process - > memory . stack } ;
2020-02-05 07:42:53 +01:00
if ( ! stack . IsInside ( source ) ) {
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidMemoryRegion ;
2020-02-01 16:51:32 +01:00
state . logger - > Warn ( " svcUnmapMemory: Source not within stack region: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes) " , source , destination , size ) ;
return ;
}
2020-03-25 19:57:05 +01:00
2020-10-07 17:41:13 +02:00
auto sourceChunk { state . process - > memory . Get ( source ) } ;
auto destChunk { state . process - > memory . Get ( destination ) } ;
2020-10-04 18:40:52 +02:00
if ( ! sourceChunk | | ! destChunk ) {
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidAddress ;
2020-02-01 16:51:32 +01:00
state . logger - > Warn ( " svcUnmapMemory: Addresses have no descriptor: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes) " , source , destination , size ) ;
return ;
}
2020-03-25 19:57:05 +01:00
2020-10-04 18:40:52 +02:00
if ( ! destChunk - > state . mapAllowed ) {
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidState ;
2020-10-04 18:40:52 +02:00
state . logger - > Warn ( " svcUnmapMemory: Destination doesn't allow usage of svcMapMemory: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes) 0x{:X} " , source , destination , size , destChunk - > state . value ) ;
2020-02-01 16:51:32 +01:00
return ;
}
2020-03-25 19:57:05 +01:00
2020-09-26 07:17:57 +02:00
auto destObject { state . process - > GetMemoryObject ( destination ) } ;
2020-02-05 07:42:53 +01:00
if ( ! destObject )
2020-02-01 16:51:32 +01:00
throw exception ( " svcUnmapMemory: Cannot find destination memory object in handle table for address 0x{:X} " , destination ) ;
2020-03-25 19:57:05 +01:00
2020-10-04 18:40:52 +02:00
destObject - > item - > UpdatePermission ( destination , size , sourceChunk - > permission ) ;
2020-03-25 19:57:05 +01:00
2020-10-04 18:40:52 +02:00
std : : memcpy ( source , destination , size ) ;
2020-03-25 19:57:05 +01:00
2020-09-26 07:17:57 +02:00
auto sourceObject { state . process - > GetMemoryObject ( destination ) } ;
2020-02-05 07:42:53 +01:00
if ( ! sourceObject )
2020-02-01 16:51:32 +01:00
throw exception ( " svcUnmapMemory: Cannot find source memory object in handle table for address 0x{:X} " , source ) ;
2020-03-25 19:57:05 +01:00
2020-09-28 12:05:17 +02:00
state . process - > CloseHandle ( sourceObject - > handle ) ;
2020-03-25 19:57:05 +01:00
2020-02-01 16:51:32 +01:00
state . logger - > Debug ( " svcUnmapMemory: Unmapped range 0x{:X} - 0x{:X} to 0x{:X} - 0x{:X} (Size: 0x{:X} bytes) " , source , source + size , destination , destination + size , size ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = Result { } ;
2020-02-01 16:51:32 +01:00
}
2020-10-10 17:53:14 +02:00
void QueryMemory ( const DeviceState & state ) {
2020-01-01 14:11:25 +01:00
memory : : MemoryInfo memInfo { } ;
2020-03-25 19:57:05 +01:00
2020-10-10 17:53:14 +02:00
auto pointer { reinterpret_cast < u8 * > ( state . ctx - > gpr . x2 ) } ;
2020-10-07 17:41:13 +02:00
auto chunk { state . process - > memory . Get ( pointer ) } ;
2020-03-25 19:57:05 +01:00
2020-10-04 18:40:52 +02:00
if ( chunk ) {
2020-01-21 08:16:57 +01:00
memInfo = {
2020-10-04 18:40:52 +02:00
. address = reinterpret_cast < u64 > ( chunk - > ptr ) ,
. size = chunk - > size ,
. type = static_cast < u32 > ( chunk - > state . type ) ,
. attributes = chunk - > attributes . value ,
. permissions = static_cast < u32 > ( chunk - > permission . Get ( ) ) ,
2020-01-21 08:16:57 +01:00
. deviceRefCount = 0 ,
. ipcRefCount = 0 ,
} ;
2020-03-25 19:57:05 +01:00
2020-10-10 19:40:12 +02:00
state . logger - > Debug ( " svcQueryMemory: Address: 0x{:X}, Size: 0x{:X}, Type: 0x{:X}, Is Uncached: {}, Permissions: {}{}{} " , memInfo . address , memInfo . size , memInfo . type , static_cast < bool > ( chunk - > attributes . isUncached ) , chunk - > permission . r ? ' R ' : ' - ' , chunk - > permission . w ? ' W ' : ' - ' , chunk - > permission . x ? ' X ' : ' - ' ) ;
2020-01-21 08:16:57 +01:00
} else {
2020-10-07 17:41:13 +02:00
auto addressSpaceEnd { reinterpret_cast < u64 > ( state . process - > memory . addressSpace . address + state . process - > memory . addressSpace . size ) } ;
2020-03-25 19:57:05 +01:00
2020-01-21 08:16:57 +01:00
memInfo = {
2020-07-05 22:21:08 +02:00
. address = addressSpaceEnd ,
. size = ~ addressSpaceEnd + 1 ,
. type = static_cast < u32 > ( memory : : MemoryType : : Reserved ) ,
2020-01-21 08:16:57 +01:00
} ;
2020-03-25 19:57:05 +01:00
2020-10-05 11:19:23 +02:00
state . logger - > Debug ( " svcQueryMemory: Trying to query memory outside of the application's address space: 0x{:X} " , pointer ) ;
2019-09-24 22:54:27 +02:00
}
2020-03-25 19:57:05 +01:00
2020-10-10 17:53:14 +02:00
* reinterpret_cast < memory : : MemoryInfo * > ( state . ctx - > gpr . x0 ) = memInfo ;
2020-03-25 19:57:05 +01:00
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = Result { } ;
2019-09-24 22:54:27 +02:00
}
2020-10-10 17:53:14 +02:00
void ExitProcess ( const DeviceState & state ) {
2020-10-07 17:41:13 +02:00
state . logger - > Debug ( " svcExitProcess: Exiting process " ) ;
//state.os->KillThread(state.process->pid);
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-10-10 17:53:14 +02:00
void CreateThread ( const DeviceState & state ) {
auto entry { reinterpret_cast < void * > ( state . ctx - > gpr . x1 ) } ;
auto entryArgument { state . ctx - > gpr . x2 } ;
auto stackTop { reinterpret_cast < u8 * > ( state . ctx - > gpr . x3 ) } ;
auto priority { static_cast < i8 > ( state . ctx - > gpr . w4 ) } ;
2020-03-25 19:57:05 +01:00
2020-10-07 17:41:13 +02:00
if ( ! constant : : HosPriority . Valid ( priority ) ) {
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidAddress ;
2019-11-22 15:59:50 +01:00
state . logger - > Warn ( " svcCreateThread: 'priority' invalid: {} " , priority ) ;
2019-11-17 21:19:01 +01:00
return ;
}
2020-03-25 19:57:05 +01:00
2020-10-07 17:41:13 +02:00
auto stack { state . process - > GetMemoryObject ( stackTop ) } ;
if ( ! stack )
throw exception ( " svcCreateThread: Cannot find memory object in handle table for thread stack: 0x{:X} " , stackTop ) ;
auto thread { state . process - > CreateThread ( entry , entryArgument , priority , static_pointer_cast < type : : KPrivateMemory > ( stack - > item ) ) } ;
state . logger - > Debug ( " svcCreateThread: Created thread with handle 0x{:X} (Entry Point: 0x{:X}, Argument: 0x{:X}, Stack Pointer: 0x{:X}, Priority: {}, ID: {}) " , thread - > handle , entry , entryArgument , stackTop , priority , thread - > id ) ;
2020-03-25 19:57:05 +01:00
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w1 = thread - > handle ;
state . ctx - > gpr . w0 = Result { } ;
2019-09-24 22:54:27 +02:00
}
2020-10-10 17:53:14 +02:00
void StartThread ( const DeviceState & state ) {
auto handle { state . ctx - > gpr . w0 } ;
2019-11-17 21:19:01 +01:00
try {
2020-09-26 07:17:57 +02:00
auto thread { state . process - > GetHandle < type : : KThread > ( handle ) } ;
2020-10-07 17:41:13 +02:00
state . logger - > Debug ( " svcStartThread: Starting thread: 0x{:X}, PID: {} " , handle , thread - > id ) ;
2019-11-17 21:19:01 +01:00
thread - > Start ( ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = Result { } ;
2020-01-11 05:52:25 +01:00
} catch ( const std : : exception & ) {
2019-11-17 21:19:01 +01:00
state . logger - > Warn ( " svcStartThread: 'handle' invalid: 0x{:X} " , handle ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidHandle ;
2019-11-17 21:19:01 +01:00
}
2019-09-24 22:54:27 +02:00
}
2020-10-10 17:53:14 +02:00
void ExitThread ( const DeviceState & state ) {
2020-10-07 17:41:13 +02:00
state . logger - > Debug ( " svcExitThread: Exiting current thread: {} " , state . thread - > id ) ;
state . os - > KillThread ( state . thread - > id ) ;
2019-09-24 22:54:27 +02:00
}
2020-10-10 17:53:14 +02:00
void SleepThread ( const DeviceState & state ) {
auto in { state . ctx - > gpr . x0 } ;
2020-03-25 19:57:05 +01:00
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
switch ( in ) {
2019-10-13 10:04:47 +02:00
case 0 :
case 1 :
case 2 :
2019-11-17 21:19:01 +01:00
state . logger - > Debug ( " svcSleepThread: Yielding thread: {} " , in ) ;
break ;
2019-10-13 10:04:47 +02:00
default :
2020-07-06 23:11:18 +02:00
state . logger - > Debug ( " svcSleepThread: Thread sleeping for {} ns " , in ) ;
2020-09-26 07:17:57 +02:00
struct timespec spec {
2020-10-10 17:53:14 +02:00
. tv_sec = static_cast < time_t > ( state . ctx - > gpr . x0 / 1000000000 ) ,
. tv_nsec = static_cast < long > ( state . ctx - > gpr . x0 % 1000000000 )
2020-01-15 19:58:58 +01:00
} ;
nanosleep ( & spec , nullptr ) ;
2019-10-13 10:04:47 +02:00
}
}
2020-10-10 17:53:14 +02:00
void GetThreadPriority ( const DeviceState & state ) {
auto handle { state . ctx - > gpr . w1 } ;
2019-11-17 21:19:01 +01:00
try {
2020-09-26 07:17:57 +02:00
auto priority { state . process - > GetHandle < type : : KThread > ( handle ) - > priority } ;
2020-02-15 10:38:17 +01:00
state . logger - > Debug ( " svcGetThreadPriority: Writing thread priority {} " , priority ) ;
2020-03-25 19:57:05 +01:00
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w1 = priority ;
state . ctx - > gpr . w0 = Result { } ;
2020-01-11 05:52:25 +01:00
} catch ( const std : : exception & ) {
2019-11-17 21:19:01 +01:00
state . logger - > Warn ( " svcGetThreadPriority: 'handle' invalid: 0x{:X} " , handle ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidHandle ;
2019-11-17 21:19:01 +01:00
}
2019-09-24 22:54:27 +02:00
}
2020-10-10 17:53:14 +02:00
void SetThreadPriority ( const DeviceState & state ) {
auto handle { state . ctx - > gpr . w0 } ;
auto priority { state . ctx - > gpr . w1 } ;
2020-03-25 19:57:05 +01:00
2019-11-17 21:19:01 +01:00
try {
2020-02-15 10:38:17 +01:00
state . logger - > Debug ( " svcSetThreadPriority: Setting thread priority to {} " , priority ) ;
2020-01-01 14:11:25 +01:00
state . process - > GetHandle < type : : KThread > ( handle ) - > UpdatePriority ( static_cast < u8 > ( priority ) ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = Result { } ;
2020-01-11 05:52:25 +01:00
} catch ( const std : : exception & ) {
2019-11-17 21:19:01 +01:00
state . logger - > Warn ( " svcSetThreadPriority: 'handle' invalid: 0x{:X} " , handle ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidHandle ;
2019-11-17 21:19:01 +01:00
}
2019-09-24 22:54:27 +02:00
}
2020-10-10 17:53:14 +02:00
void ClearEvent ( const DeviceState & state ) {
auto object { state . process - > GetHandle < type : : KEvent > ( state . ctx - > gpr . w0 ) } ;
2020-07-09 15:10:18 +02:00
object - > signalled = false ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = Result { } ;
2020-07-09 15:10:18 +02:00
}
2020-10-10 17:53:14 +02:00
void MapSharedMemory ( const DeviceState & state ) {
2019-11-17 21:19:01 +01:00
try {
2020-10-10 17:53:14 +02:00
auto object { state . process - > GetHandle < type : : KSharedMemory > ( state . ctx - > gpr . w0 ) } ;
auto pointer { reinterpret_cast < u8 * > ( state . ctx - > gpr . x1 ) } ;
2020-03-25 19:57:05 +01:00
2020-10-04 20:18:34 +02:00
if ( ! util : : PageAligned ( pointer ) ) {
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidAddress ;
2020-10-04 20:18:34 +02:00
state . logger - > Warn ( " svcMapSharedMemory: 'pointer' not page aligned: 0x{:X} " , pointer ) ;
2019-11-17 21:19:01 +01:00
return ;
}
2020-03-25 19:57:05 +01:00
2020-10-10 17:53:14 +02:00
auto size { state . ctx - > gpr . x2 } ;
2020-04-17 23:19:19 +02:00
if ( ! util : : PageAligned ( size ) ) {
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidSize ;
2020-01-21 08:16:57 +01:00
state . logger - > Warn ( " svcMapSharedMemory: 'size' {}: 0x{:X} " , size ? " not page aligned " : " is zero " , size ) ;
2019-11-17 21:19:01 +01:00
return ;
}
2020-03-25 19:57:05 +01:00
2020-10-10 17:53:14 +02:00
auto permission { * reinterpret_cast < memory : : Permission * > ( & state . ctx - > gpr . w3 ) } ;
2019-11-17 21:19:01 +01:00
if ( ( permission . w & & ! permission . r ) | | ( permission . x & & ! permission . r ) ) {
2020-10-04 18:40:52 +02:00
state . logger - > Warn ( " svcMapSharedMemory: 'permission' invalid: {}{}{} " , permission . r ? ' R ' : ' - ' , permission . w ? ' W ' : ' - ' , permission . x ? ' X ' : ' - ' ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidNewMemoryPermission ;
2019-11-17 21:19:01 +01:00
return ;
}
2020-03-25 19:57:05 +01:00
2020-10-04 20:18:34 +02:00
state . logger - > Debug ( " svcMapSharedMemory: Mapping shared memory at 0x{:X} for {} bytes ({}{}{}) " , pointer , size , permission . r ? ' R ' : ' - ' , permission . w ? ' W ' : ' - ' , permission . x ? ' X ' : ' - ' ) ;
2020-03-25 19:57:05 +01:00
2020-10-04 20:18:34 +02:00
object - > Map ( pointer , size , permission ) ;
2020-03-25 19:57:05 +01:00
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = Result { } ;
2019-11-17 21:19:01 +01:00
} catch ( const std : : exception & ) {
2020-10-10 17:53:14 +02:00
state . logger - > Warn ( " svcMapSharedMemory: 'handle' invalid: 0x{:X} " , state . ctx - > gpr . w0 ) ;
state . ctx - > gpr . w0 = result : : InvalidHandle ;
2019-09-24 22:54:27 +02:00
}
}
2020-10-10 17:53:14 +02:00
void CreateTransferMemory ( const DeviceState & state ) {
auto pointer { reinterpret_cast < u8 * > ( state . ctx - > gpr . x1 ) } ;
2020-10-04 20:18:34 +02:00
if ( ! util : : PageAligned ( pointer ) ) {
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidAddress ;
2020-10-04 20:18:34 +02:00
state . logger - > Warn ( " svcCreateTransferMemory: 'pointer' not page aligned: 0x{:X} " , pointer ) ;
2019-11-17 21:19:01 +01:00
return ;
}
2020-03-25 19:57:05 +01:00
2020-10-10 17:53:14 +02:00
auto size { state . ctx - > gpr . x2 } ;
2020-04-17 23:19:19 +02:00
if ( ! util : : PageAligned ( size ) ) {
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidSize ;
2020-01-21 08:16:57 +01:00
state . logger - > Warn ( " svcCreateTransferMemory: 'size' {}: 0x{:X} " , size ? " not page aligned " : " is zero " , size ) ;
2019-11-17 21:19:01 +01:00
return ;
}
2020-03-25 19:57:05 +01:00
2020-10-10 17:53:14 +02:00
auto permission { * reinterpret_cast < memory : : Permission * > ( & state . ctx - > gpr . w3 ) } ;
2019-11-17 21:19:01 +01:00
if ( ( permission . w & & ! permission . r ) | | ( permission . x & & ! permission . r ) ) {
2020-10-04 18:40:52 +02:00
state . logger - > Warn ( " svcCreateTransferMemory: 'permission' invalid: {}{}{} " , permission . r ? ' R ' : ' - ' , permission . w ? ' W ' : ' - ' , permission . x ? ' X ' : ' - ' ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidNewMemoryPermission ;
2019-11-17 21:19:01 +01:00
return ;
}
2020-03-25 19:57:05 +01:00
2020-10-04 20:18:34 +02:00
auto tmem { state . process - > NewHandle < type : : KTransferMemory > ( pointer , size , permission ) } ;
2020-10-05 11:19:23 +02:00
state . logger - > Debug ( " svcCreateTransferMemory: Creating transfer memory at 0x{:X} for {} bytes ({}{}{}) " , pointer , size , permission . r ? ' R ' : ' - ' , permission . w ? ' W ' : ' - ' , permission . x ? ' X ' : ' - ' ) ;
2020-03-25 19:57:05 +01:00
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = Result { } ;
state . ctx - > gpr . w1 = tmem . handle ;
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-10-10 17:53:14 +02:00
void CloseHandle ( const DeviceState & state ) {
auto handle { static_cast < KHandle > ( state . ctx - > gpr . w0 ) } ;
2019-11-17 21:19:01 +01:00
try {
2020-09-28 12:05:17 +02:00
state . process - > CloseHandle ( handle ) ;
2019-11-17 21:19:01 +01:00
state . logger - > Debug ( " svcCloseHandle: Closing handle: 0x{:X} " , handle ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = Result { } ;
2020-01-11 05:52:25 +01:00
} catch ( const std : : exception & ) {
2019-11-17 21:19:01 +01:00
state . logger - > Warn ( " svcCloseHandle: 'handle' invalid: 0x{:X} " , handle ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidHandle ;
2019-11-17 21:19:01 +01:00
}
}
2020-10-10 17:53:14 +02:00
void ResetSignal ( const DeviceState & state ) {
auto handle { state . ctx - > gpr . w0 } ;
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
try {
2020-10-07 17:41:13 +02:00
auto object { state . process - > GetHandle ( handle ) } ;
2019-11-17 21:19:01 +01:00
switch ( object - > objectType ) {
2020-04-22 19:02:27 +02:00
case type : : KType : : KEvent :
2019-11-17 21:19:01 +01:00
std : : static_pointer_cast < type : : KEvent > ( object ) - > ResetSignal ( ) ;
break ;
2020-03-25 19:57:05 +01:00
2020-04-22 19:02:27 +02:00
case type : : KType : : KProcess :
2019-11-17 21:19:01 +01:00
std : : static_pointer_cast < type : : KProcess > ( object ) - > ResetSignal ( ) ;
break ;
2020-03-25 19:57:05 +01:00
2019-11-17 21:19:01 +01:00
default : {
state . logger - > Warn ( " svcResetSignal: 'handle' type invalid: 0x{:X} ({}) " , handle , object - > objectType ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidHandle ;
2019-11-17 21:19:01 +01:00
return ;
}
}
2020-03-25 19:57:05 +01:00
2019-11-17 21:19:01 +01:00
state . logger - > Debug ( " svcResetSignal: Resetting signal: 0x{:X} " , handle ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = Result { } ;
2020-01-11 05:52:25 +01:00
} catch ( const std : : out_of_range & ) {
2019-11-17 21:19:01 +01:00
state . logger - > Warn ( " svcResetSignal: 'handle' invalid: 0x{:X} " , handle ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidHandle ;
2019-11-17 21:19:01 +01:00
return ;
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-10-10 17:53:14 +02:00
void WaitSynchronization ( const DeviceState & state ) {
2020-09-26 07:17:57 +02:00
constexpr u8 maxSyncHandles { 0x40 } ; // The total amount of handles that can be passed to WaitSynchronization
2020-03-25 19:57:05 +01:00
2020-10-10 17:53:14 +02:00
auto numHandles { state . ctx - > gpr . w2 } ;
2020-03-25 18:59:37 +01:00
if ( numHandles > maxSyncHandles ) {
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : OutOfHandles ;
2019-09-24 22:54:27 +02:00
return ;
}
2020-03-25 18:59:37 +01:00
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
std : : string handleStr ;
2020-03-25 18:59:37 +01:00
std : : vector < std : : shared_ptr < type : : KSyncObject > > objectTable ;
2020-10-10 17:53:14 +02:00
span waitHandles ( reinterpret_cast < KHandle * > ( state . ctx - > gpr . x1 ) , numHandles ) ;
2020-03-25 18:59:37 +01:00
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
for ( const auto & handle : waitHandles ) {
handleStr + = fmt : : format ( " * 0x{:X} \n " , handle ) ;
2020-03-25 18:59:37 +01:00
2020-10-07 17:41:13 +02:00
auto object { state . process - > GetHandle ( handle ) } ;
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
switch ( object - > objectType ) {
2019-10-13 10:04:47 +02:00
case type : : KType : : KProcess :
case type : : KType : : KThread :
case type : : KType : : KEvent :
case type : : KType : : KSession :
break ;
2020-03-25 18:59:37 +01:00
2019-11-15 15:19:24 +01:00
default : {
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidHandle ;
2019-10-13 10:04:47 +02:00
return ;
2019-11-15 15:19:24 +01:00
}
2019-10-13 10:04:47 +02:00
}
2020-03-25 18:59:37 +01:00
2020-01-11 05:52:25 +01:00
objectTable . push_back ( std : : static_pointer_cast < type : : KSyncObject > ( object ) ) ;
}
2020-03-25 18:59:37 +01:00
2020-10-10 17:53:14 +02:00
auto timeout { state . ctx - > gpr . x3 } ;
2020-01-12 21:37:22 +01:00
state . logger - > Debug ( " svcWaitSynchronization: Waiting on handles: \n {}Timeout: 0x{:X} ns " , handleStr , timeout ) ;
2020-03-25 18:59:37 +01:00
2020-09-26 07:17:57 +02:00
auto start { util : : GetTimeNs ( ) } ;
2020-01-11 05:52:25 +01:00
while ( true ) {
2020-02-05 07:42:53 +01:00
if ( state . thread - > cancelSync ) {
2020-02-01 16:51:32 +01:00
state . thread - > cancelSync = false ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : Cancelled ;
2020-02-01 16:51:32 +01:00
break ;
}
2020-03-25 18:59:37 +01:00
2020-01-11 05:52:25 +01:00
uint index { } ;
for ( const auto & object : objectTable ) {
if ( object - > signalled ) {
2020-10-04 20:18:34 +02:00
state . logger - > Debug ( " svcWaitSynchronization: Signalled handle: 0x{:X} " , waitHandles [ index ] ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = Result { } ;
state . ctx - > gpr . w1 = index ;
2020-01-11 05:52:25 +01:00
return ;
}
index + + ;
}
2020-03-25 18:59:37 +01:00
2020-04-17 23:19:19 +02:00
if ( ( util : : GetTimeNs ( ) - start ) > = timeout ) {
2020-01-12 21:37:22 +01:00
state . logger - > Debug ( " svcWaitSynchronization: Wait has timed out " ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : TimedOut ;
2019-10-13 10:04:47 +02:00
return ;
}
}
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-10-10 17:53:14 +02:00
void CancelSynchronization ( const DeviceState & state ) {
2020-02-01 16:51:32 +01:00
try {
2020-10-10 17:53:14 +02:00
state . process - > GetHandle < type : : KThread > ( state . ctx - > gpr . w0 ) - > cancelSync = true ;
2020-02-01 16:51:32 +01:00
} catch ( const std : : exception & ) {
2020-10-10 17:53:14 +02:00
state . logger - > Warn ( " svcCancelSynchronization: 'handle' invalid: 0x{:X} " , state . ctx - > gpr . w0 ) ;
state . ctx - > gpr . w0 = result : : InvalidHandle ;
2020-02-01 16:51:32 +01:00
}
}
2020-10-10 17:53:14 +02:00
void ArbitrateLock ( const DeviceState & state ) {
auto pointer { reinterpret_cast < u32 * > ( state . ctx - > gpr . x1 ) } ;
2020-10-04 20:18:34 +02:00
if ( ! util : : WordAligned ( pointer ) ) {
2020-10-05 11:19:23 +02:00
state . logger - > Warn ( " svcArbitrateLock: 'pointer' not word aligned: 0x{:X} " , pointer ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidAddress ;
2019-11-17 21:19:01 +01:00
return ;
}
2020-03-25 19:57:05 +01:00
2020-10-10 17:53:14 +02:00
auto ownerHandle { state . ctx - > gpr . w0 } ;
auto requesterHandle { state . ctx - > gpr . w2 } ;
2020-02-01 16:51:32 +01:00
if ( requesterHandle ! = state . thread - > handle )
throw exception ( " svcWaitProcessWideKeyAtomic: Handle doesn't match current thread: 0x{:X} for thread 0x{:X} " , requesterHandle , state . thread - > handle ) ;
2020-03-25 19:57:05 +01:00
2020-10-05 11:19:23 +02:00
state . logger - > Debug ( " svcArbitrateLock: Locking mutex at 0x{:X} " , pointer ) ;
2020-03-25 19:57:05 +01:00
2020-10-04 20:18:34 +02:00
if ( state . process - > MutexLock ( pointer , ownerHandle ) )
2020-10-05 11:19:23 +02:00
state . logger - > Debug ( " svcArbitrateLock: Locked mutex at 0x{:X} " , pointer ) ;
2020-02-05 07:42:53 +01:00
else
2020-10-05 11:19:23 +02:00
state . logger - > Debug ( " svcArbitrateLock: Owner handle did not match current owner for mutex or didn't have waiter flag at 0x{:X} " , pointer ) ;
2020-03-25 19:57:05 +01:00
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = Result { } ;
2019-10-16 14:41:30 +02:00
}
2020-10-10 17:53:14 +02:00
void ArbitrateUnlock ( const DeviceState & state ) {
auto mutex { reinterpret_cast < u32 * > ( state . ctx - > gpr . x0 ) } ;
2020-10-04 20:18:34 +02:00
if ( ! util : : WordAligned ( mutex ) ) {
2020-10-10 19:40:12 +02:00
state . logger - > Warn ( " svcArbitrateUnlock: 'mutex' not word aligned: 0x{:X} " , mutex ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidAddress ;
2019-11-17 21:19:01 +01:00
return ;
}
2020-03-25 19:57:05 +01:00
2020-10-05 11:19:23 +02:00
state . logger - > Debug ( " svcArbitrateUnlock: Unlocking mutex at 0x{:X} " , mutex ) ;
2020-03-25 19:57:05 +01:00
2020-10-04 20:18:34 +02:00
if ( state . process - > MutexUnlock ( mutex ) ) {
2020-10-05 11:19:23 +02:00
state . logger - > Debug ( " svcArbitrateUnlock: Unlocked mutex at 0x{:X} " , mutex ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = Result { } ;
2020-02-01 16:51:32 +01:00
} else {
2020-10-05 11:19:23 +02:00
state . logger - > Debug ( " svcArbitrateUnlock: A non-owner thread tried to release a mutex at 0x{:X} " , mutex ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidAddress ;
2020-02-01 16:51:32 +01:00
}
2019-10-16 14:41:30 +02:00
}
2020-10-10 17:53:14 +02:00
void WaitProcessWideKeyAtomic ( const DeviceState & state ) {
auto mutex { reinterpret_cast < u32 * > ( state . ctx - > gpr . x0 ) } ;
2020-10-04 20:18:34 +02:00
if ( ! util : : WordAligned ( mutex ) ) {
2020-10-10 19:40:12 +02:00
state . logger - > Warn ( " svcWaitProcessWideKeyAtomic: 'mutex' not word aligned: 0x{:X} " , mutex ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidAddress ;
2020-02-01 16:51:32 +01:00
return ;
}
2020-03-25 19:57:05 +01:00
2020-10-10 17:53:14 +02:00
auto conditional { reinterpret_cast < void * > ( state . ctx - > gpr . x1 ) } ;
auto handle { state . ctx - > gpr . w2 } ;
2020-02-01 16:51:32 +01:00
if ( handle ! = state . thread - > handle )
throw exception ( " svcWaitProcessWideKeyAtomic: Handle doesn't match current thread: 0x{:X} for thread 0x{:X} " , handle , state . thread - > handle ) ;
2020-03-25 19:57:05 +01:00
2020-10-04 20:18:34 +02:00
if ( ! state . process - > MutexUnlock ( mutex ) ) {
2020-10-05 11:19:23 +02:00
state . logger - > Debug ( " WaitProcessWideKeyAtomic: A non-owner thread tried to release a mutex at 0x{:X} " , mutex ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidAddress ;
2020-02-01 16:51:32 +01:00
return ;
}
2020-03-25 19:57:05 +01:00
2020-10-10 17:53:14 +02:00
auto timeout { state . ctx - > gpr . x3 } ;
2020-10-05 11:19:23 +02:00
state . logger - > Debug ( " svcWaitProcessWideKeyAtomic: Mutex: 0x{:X}, Conditional-Variable: 0x{:X}, Timeout: {} ns " , mutex , conditional , timeout ) ;
2020-03-25 19:57:05 +01:00
2020-10-04 20:18:34 +02:00
if ( state . process - > ConditionalVariableWait ( conditional , mutex , timeout ) ) {
2020-02-01 16:51:32 +01:00
state . logger - > Debug ( " svcWaitProcessWideKeyAtomic: Waited for conditional variable and relocked mutex " ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = Result { } ;
2020-02-01 16:51:32 +01:00
} else {
state . logger - > Debug ( " svcWaitProcessWideKeyAtomic: Wait has timed out " ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : TimedOut ;
2019-10-16 14:41:30 +02:00
}
}
2020-10-10 17:53:14 +02:00
void SignalProcessWideKey ( const DeviceState & state ) {
auto conditional { reinterpret_cast < void * > ( state . ctx - > gpr . x0 ) } ;
auto count { state . ctx - > gpr . w1 } ;
2020-03-25 19:57:05 +01:00
2020-10-04 20:18:34 +02:00
state . logger - > Debug ( " svcSignalProcessWideKey: Signalling Conditional-Variable at 0x{:X} for {} " , conditional , count ) ;
state . process - > ConditionalVariableSignal ( conditional , count ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = Result { } ;
2019-11-17 21:19:01 +01:00
}
2020-10-10 17:53:14 +02:00
void GetSystemTick ( const DeviceState & state ) {
2019-11-17 21:19:01 +01:00
u64 tick ;
asm ( " STR X1, [SP, #-16]! \n \t "
" MRS %0, CNTVCT_EL0 \n \t "
" MOV X1, #0xF800 \n \t "
" MOVK X1, #0x124, lsl #16 \n \t "
" MUL %0, %0, X1 \n \t "
" MRS X1, CNTFRQ_EL0 \n \t "
" UDIV %0, %0, X1 \n \t "
" LDR X1, [SP], #16 " : " =r " ( tick ) ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . x0 = tick ;
2019-09-24 22:54:27 +02:00
}
2020-10-10 17:53:14 +02:00
void ConnectToNamedPort ( const DeviceState & state ) {
2020-10-02 13:07:13 +02:00
constexpr u8 portSize = 0x8 ; //!< The size of a port name string
2020-10-10 17:53:14 +02:00
std : : string_view port ( span ( reinterpret_cast < char * > ( state . ctx - > gpr . x1 ) , portSize ) . as_string ( true ) ) ;
2020-03-25 18:59:37 +01:00
KHandle handle { } ;
if ( port . compare ( " sm: " ) > = 0 ) {
2020-09-02 23:11:28 +02:00
handle = state . process - > NewHandle < type : : KSession > ( std : : static_pointer_cast < service : : BaseService > ( state . os - > serviceManager . smUserInterface ) ) . handle ;
2020-02-15 10:38:17 +01:00
} else {
2019-11-17 21:19:01 +01:00
state . logger - > Warn ( " svcConnectToNamedPort: Connecting to invalid port: '{}' " , port ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : NotFound ;
2019-11-17 21:19:01 +01:00
return ;
}
2020-03-25 18:59:37 +01:00
2019-11-17 21:19:01 +01:00
state . logger - > Debug ( " svcConnectToNamedPort: Connecting to port '{}' at 0x{:X} " , port , handle ) ;
2020-03-25 18:59:37 +01:00
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w1 = handle ;
state . ctx - > gpr . w0 = Result { } ;
2019-09-24 22:54:27 +02:00
}
2020-10-10 17:53:14 +02:00
void SendSyncRequest ( const DeviceState & state ) {
state . os - > serviceManager . SyncRequestHandler ( static_cast < KHandle > ( state . ctx - > gpr . x0 ) ) ;
state . ctx - > gpr . w0 = Result { } ;
2019-09-24 22:54:27 +02:00
}
2020-10-10 17:53:14 +02:00
void GetThreadId ( const DeviceState & state ) {
2020-09-28 12:05:17 +02:00
constexpr KHandle threadSelf { 0xFFFF8000 } ; // The handle used by threads to refer to themselves
2020-10-10 17:53:14 +02:00
auto handle { state . ctx - > gpr . w1 } ;
2020-03-25 18:59:37 +01:00
pid_t pid { } ;
if ( handle ! = threadSelf )
2020-10-07 17:41:13 +02:00
pid = state . process - > GetHandle < type : : KThread > ( handle ) - > id ;
2020-02-15 10:38:17 +01:00
else
2020-10-07 17:41:13 +02:00
pid = state . thread - > id ;
2020-03-25 18:59:37 +01:00
2019-11-17 21:19:01 +01:00
state . logger - > Debug ( " svcGetThreadId: Handle: 0x{:X}, PID: {} " , handle , pid ) ;
2020-03-25 18:59:37 +01:00
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . x1 = static_cast < u64 > ( pid ) ;
state . ctx - > gpr . w0 = Result { } ;
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-10-10 17:53:14 +02:00
void OutputDebugString ( const DeviceState & state ) {
auto debug { span ( reinterpret_cast < u8 * > ( state . ctx - > gpr . x0 ) , state . ctx - > gpr . x1 ) . as_string ( ) } ;
2020-03-25 19:57:05 +01:00
2020-01-11 05:52:25 +01:00
if ( debug . back ( ) = = ' \n ' )
2020-10-04 18:40:52 +02:00
debug . remove_suffix ( 1 ) ;
2020-03-25 19:57:05 +01:00
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
state . logger - > Info ( " Debug Output: {} " , debug ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = Result { } ;
2019-09-24 22:54:27 +02:00
}
2020-10-10 17:53:14 +02:00
void GetInfo ( const DeviceState & state ) {
auto id0 { state . ctx - > gpr . w1 } ;
auto handle { state . ctx - > gpr . w2 } ;
auto id1 { state . ctx - > gpr . x3 } ;
2020-03-25 18:59:37 +01:00
2019-11-17 21:19:01 +01:00
u64 out { } ;
2020-03-25 18:59:37 +01:00
2020-09-26 07:17:57 +02:00
constexpr u64 totalPhysicalMemory { 0xF8000000 } ; // ~4 GB of RAM
2020-03-25 19:57:05 +01:00
2019-11-17 21:19:01 +01:00
switch ( id0 ) {
2019-09-24 22:54:27 +02:00
case constant : : infoState : : AllowedCpuIdBitmask :
case constant : : infoState : : AllowedThreadPriorityMask :
case constant : : infoState : : IsCurrentProcessBeingDebugged :
case constant : : infoState : : TitleId :
case constant : : infoState : : PrivilegedProcessId :
break ;
2020-03-25 18:59:37 +01:00
2019-09-24 22:54:27 +02:00
case constant : : infoState : : AliasRegionBaseAddr :
2020-10-07 17:41:13 +02:00
out = state . process - > memory . alias . address ;
2019-09-24 22:54:27 +02:00
break ;
2020-03-25 18:59:37 +01:00
2019-09-24 22:54:27 +02:00
case constant : : infoState : : AliasRegionSize :
2020-10-07 17:41:13 +02:00
out = state . process - > memory . alias . size ;
2019-09-24 22:54:27 +02:00
break ;
2020-03-25 18:59:37 +01:00
2019-09-24 22:54:27 +02:00
case constant : : infoState : : HeapRegionBaseAddr :
2020-10-07 17:41:13 +02:00
out = state . process - > memory . heap . address ;
2019-09-24 22:54:27 +02:00
break ;
2020-03-25 18:59:37 +01:00
2019-09-24 22:54:27 +02:00
case constant : : infoState : : HeapRegionSize :
2020-10-07 17:41:13 +02:00
out = state . process - > memory . heap . size ;
2019-09-24 22:54:27 +02:00
break ;
2020-03-25 18:59:37 +01:00
2019-09-24 22:54:27 +02:00
case constant : : infoState : : TotalMemoryAvailable :
2020-03-25 18:59:37 +01:00
out = totalPhysicalMemory ;
2019-09-24 22:54:27 +02:00
break ;
2020-03-25 18:59:37 +01:00
2019-09-24 22:54:27 +02:00
case constant : : infoState : : TotalMemoryUsage :
2020-10-13 22:43:52 +02:00
out = state . process - > heap - > size + state . thread - > stack - > size + state . process - > memory . GetProgramSize ( ) ;
2019-09-24 22:54:27 +02:00
break ;
2020-03-25 18:59:37 +01:00
2019-09-24 22:54:27 +02:00
case constant : : infoState : : AddressSpaceBaseAddr :
2020-10-13 22:43:52 +02:00
out = state . process - > memory . addressSpace . address ;
2019-09-24 22:54:27 +02:00
break ;
2020-03-25 18:59:37 +01:00
2019-09-24 22:54:27 +02:00
case constant : : infoState : : AddressSpaceSize :
2020-10-13 22:43:52 +02:00
out = state . process - > memory . addressSpace . size ;
2019-09-24 22:54:27 +02:00
break ;
2020-03-25 18:59:37 +01:00
2019-09-24 22:54:27 +02:00
case constant : : infoState : : StackRegionBaseAddr :
2020-10-07 17:41:13 +02:00
out = state . process - > memory . stack . address ;
2019-09-24 22:54:27 +02:00
break ;
2020-03-25 18:59:37 +01:00
2019-09-24 22:54:27 +02:00
case constant : : infoState : : StackRegionSize :
2020-10-07 17:41:13 +02:00
out = state . process - > memory . stack . size ;
2019-09-24 22:54:27 +02:00
break ;
2020-03-25 18:59:37 +01:00
2019-09-24 22:54:27 +02:00
case constant : : infoState : : PersonalMmHeapSize :
2020-03-25 18:59:37 +01:00
out = totalPhysicalMemory ;
2019-09-24 22:54:27 +02:00
break ;
2020-03-25 18:59:37 +01:00
2019-09-24 22:54:27 +02:00
case constant : : infoState : : PersonalMmHeapUsage :
2020-10-13 22:43:52 +02:00
out = state . process - > heap - > size + state . thread - > stack - > size ;
2019-09-24 22:54:27 +02:00
break ;
2020-03-25 18:59:37 +01:00
2019-09-24 22:54:27 +02:00
case constant : : infoState : : TotalMemoryAvailableWithoutMmHeap :
2020-03-25 18:59:37 +01:00
out = totalPhysicalMemory ; // TODO: NPDM specifies SystemResourceSize, subtract that from this
2019-09-24 22:54:27 +02:00
break ;
2020-03-25 18:59:37 +01:00
2019-09-24 22:54:27 +02:00
case constant : : infoState : : TotalMemoryUsedWithoutMmHeap :
2020-10-13 22:43:52 +02:00
out = state . process - > heap - > size + state . thread - > stack - > size ; // TODO: Same as above
2019-09-24 22:54:27 +02:00
break ;
2020-03-25 18:59:37 +01:00
2019-09-24 22:54:27 +02:00
case constant : : infoState : : UserExceptionContextAddr :
2020-10-04 18:40:52 +02:00
out = reinterpret_cast < u64 > ( state . process - > tlsPages [ 0 ] - > Get ( 0 ) ) ;
2019-09-24 22:54:27 +02:00
break ;
2020-03-25 18:59:37 +01:00
2019-09-24 22:54:27 +02:00
default :
2019-11-17 21:19:01 +01:00
state . logger - > Warn ( " svcGetInfo: Unimplemented case ID0: {}, ID1: {} " , id0 , id1 ) ;
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . w0 = result : : InvalidEnumValue ;
2019-09-24 22:54:27 +02:00
return ;
}
2020-03-25 18:59:37 +01:00
2019-11-17 21:19:01 +01:00
state . logger - > Debug ( " svcGetInfo: ID0: {}, ID1: {}, Out: 0x{:X} " , id0 , id1 , out ) ;
2020-03-25 18:59:37 +01:00
2020-10-10 17:53:14 +02:00
state . ctx - > gpr . x1 = out ;
state . ctx - > gpr . w0 = Result { } ;
2019-09-24 22:54:27 +02:00
}
}