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-03-26 15:33:19 +01:00
# include "svc.h"
2019-09-24 22:54:27 +02:00
namespace skyline : : kernel : : svc {
void SetHeapSize ( DeviceState & state ) {
2020-03-25 19:57:05 +01:00
auto size = state . ctx - > registers . w1 ;
2020-03-25 18:59:37 +01:00
2020-04-22 19:02:27 +02:00
if ( ! util : : IsAligned ( size , 0x200000 ) ) {
2020-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : InvSize ;
2020-02-03 03:12:24 +01:00
state . ctx - > registers . 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-02-05 07:42:53 +01: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-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : Success ;
state . ctx - > registers . x1 = heap - > address ;
2020-03-25 18:59:37 +01:00
2019-11-17 21:19:01 +01:00
state . logger - > Debug ( " svcSetHeapSize: Allocated at 0x{:X} for 0x{:X} bytes " , heap - > address , 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
}
void SetMemoryAttribute ( DeviceState & state ) {
2020-03-25 19:57:05 +01:00
auto address = state . ctx - > registers . x0 ;
2020-04-17 23:19:19 +02:00
if ( ! util : : PageAligned ( address ) ) {
2020-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : InvAddress ;
2020-01-21 08:16:57 +01:00
state . logger - > Warn ( " svcSetMemoryAttribute: 'address' not page aligned: 0x{:X} " , address ) ;
2019-11-17 21:19:01 +01:00
return ;
}
2020-04-18 23:40:18 +02:00
2020-03-25 19:57:05 +01:00
auto size = state . ctx - > registers . x1 ;
2020-04-17 23:19:19 +02:00
if ( ! util : : PageAligned ( size ) ) {
2020-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : InvSize ;
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-01-21 08:16:57 +01:00
memory : : MemoryAttribute mask { . value = state . ctx - > registers . w2 } ;
memory : : MemoryAttribute value { . value = state . ctx - > registers . w3 } ;
2020-04-18 23:40:18 +02:00
2020-03-25 19:57:05 +01: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-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : InvCombination ;
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-01-21 08:16:57 +01:00
auto chunk = state . os - > memory . GetChunk ( address ) ;
auto block = state . os - > memory . GetBlock ( address ) ;
if ( ! chunk | | ! block ) {
state . ctx - > registers . w0 = constant : : status : : InvAddress ;
state . logger - > Warn ( " svcSetMemoryAttribute: Cannot find memory region: 0x{:X} " , address ) ;
return ;
}
2020-04-18 23:40:18 +02:00
2020-03-25 18:59:37 +01:00
if ( ! chunk - > state . attributeChangeAllowed ) {
2020-01-21 08:16:57 +01:00
state . ctx - > registers . w0 = constant : : status : : InvState ;
state . logger - > Warn ( " svcSetMemoryAttribute: Attribute change not allowed for chunk: 0x{:X} " , address ) ;
return ;
}
2020-04-18 23:40:18 +02:00
2020-01-21 08:16:57 +01:00
block - > attributes . isUncached = value . isUncached ;
MemoryManager : : InsertBlock ( chunk , * block ) ;
2020-04-18 23:40:18 +02:00
2020-01-21 08:16:57 +01:00
state . logger - > Debug ( " svcSetMemoryAttribute: Set caching to {} at 0x{:X} for 0x{:X} bytes " , ! block - > attributes . isUncached , address , size ) ;
state . ctx - > registers . w0 = constant : : status : : Success ;
}
void MapMemory ( DeviceState & state ) {
2020-03-25 19:57:05 +01:00
auto destination = state . ctx - > registers . x0 ;
auto source = state . ctx - > registers . x1 ;
auto size = state . ctx - > registers . 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-01-21 08:16:57 +01:00
state . ctx - > registers . w0 = constant : : status : : InvAddress ;
state . logger - > Warn ( " svcMapMemory: Addresses not page aligned: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes) " , source , destination , size ) ;
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-01-21 08:16:57 +01:00
state . ctx - > registers . w0 = constant : : status : : InvSize ;
state . logger - > Warn ( " svcMapMemory: 'size' {}: 0x{:X} " , size ? " not page aligned " : " is zero " , size ) ;
return ;
}
2020-04-18 23:40:18 +02:00
2020-07-06 13:03:32 +02:00
auto stack = state . os - > memory . stack ;
2020-02-05 07:42:53 +01:00
if ( ! stack . IsInside ( destination ) ) {
2020-01-21 08:16:57 +01:00
state . ctx - > registers . w0 = constant : : status : : InvMemRange ;
2020-02-01 16:51:32 +01: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-01-21 08:16:57 +01:00
auto descriptor = state . os - > memory . Get ( source ) ;
2020-02-05 07:42:53 +01:00
if ( ! descriptor ) {
2020-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : InvAddress ;
2020-01-21 08:16:57 +01:00
state . logger - > Warn ( " svcMapMemory: Source has no descriptor: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes) " , source , destination , size ) ;
return ;
}
2020-03-25 18:59:37 +01:00
if ( ! descriptor - > chunk . state . mapAllowed ) {
2020-01-21 08:16:57 +01:00
state . ctx - > registers . w0 = constant : : status : : InvState ;
state . logger - > Warn ( " svcMapMemory: Source doesn't allow usage of svcMapMemory: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes) 0x{:X} " , source , destination , size , descriptor - > chunk . state . value ) ;
2019-11-17 21:19:01 +01:00
return ;
}
2020-03-25 19:57:05 +01:00
2020-03-25 18:59:37 +01:00
state . process - > NewHandle < type : : KPrivateMemory > ( destination , size , descriptor - > block . permission , memory : : states : : Stack ) ;
2020-01-21 08:16:57 +01:00
state . process - > CopyMemory ( source , destination , size ) ;
2020-03-25 19:57:05 +01:00
2020-01-21 08:16:57 +01:00
auto object = state . process - > GetMemoryObject ( source ) ;
2020-02-05 07:42:53 +01:00
if ( ! object )
2020-01-21 08:16:57 +01:00
throw exception ( " svcMapMemory: Cannot find memory object in handle table for address 0x{:X} " , source ) ;
2020-03-25 19:57:05 +01:00
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-01-21 08:16:57 +01: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-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : Success ;
2019-09-24 22:54:27 +02:00
}
2020-02-01 16:51:32 +01:00
void UnmapMemory ( DeviceState & state ) {
2020-03-25 19:57:05 +01:00
auto source = state . ctx - > registers . x0 ;
auto destination = state . ctx - > registers . x1 ;
auto size = state . ctx - > registers . x2 ;
2020-04-17 23:19:19 +02:00
if ( ! util : : PageAligned ( destination ) | | ! util : : PageAligned ( source ) ) {
2020-02-01 16:51:32 +01:00
state . ctx - > registers . w0 = constant : : status : : InvAddress ;
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-02-01 16:51:32 +01:00
state . ctx - > registers . w0 = constant : : status : : InvSize ;
state . logger - > Warn ( " svcUnmapMemory: 'size' {}: 0x{:X} " , size ? " not page aligned " : " is zero " , size ) ;
return ;
}
2020-03-25 19:57:05 +01:00
2020-07-06 13:03:32 +02:00
auto stack = state . os - > memory . stack ;
2020-02-05 07:42:53 +01:00
if ( ! stack . IsInside ( source ) ) {
2020-02-01 16:51:32 +01:00
state . ctx - > registers . w0 = constant : : status : : InvMemRange ;
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-02-01 16:51:32 +01:00
auto sourceDesc = state . os - > memory . Get ( source ) ;
auto destDesc = state . os - > memory . Get ( destination ) ;
2020-02-05 07:42:53 +01:00
if ( ! sourceDesc | | ! destDesc ) {
2020-02-01 16:51:32 +01:00
state . ctx - > registers . w0 = constant : : status : : InvAddress ;
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-03-25 18:59:37 +01:00
if ( ! destDesc - > chunk . state . mapAllowed ) {
2020-02-01 16:51:32 +01:00
state . ctx - > registers . w0 = constant : : status : : InvState ;
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 , destDesc - > chunk . state . value ) ;
return ;
}
2020-03-25 19:57:05 +01:00
2020-02-01 16:51:32 +01: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-02-01 16:51:32 +01:00
destObject - > item - > UpdatePermission ( destination , size , sourceDesc - > block . permission ) ;
2020-03-25 19:57:05 +01:00
2020-02-01 16:51:32 +01:00
state . process - > CopyMemory ( destination , source , size ) ;
2020-03-25 19:57:05 +01:00
2020-02-01 16:51:32 +01: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-02-01 16:51:32 +01:00
state . process - > DeleteHandle ( 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 ) ;
state . ctx - > registers . w0 = constant : : status : : Success ;
}
2019-09-24 22:54:27 +02:00
void QueryMemory ( DeviceState & state ) {
2020-01-01 14:11:25 +01:00
memory : : MemoryInfo memInfo { } ;
2020-03-25 19:57:05 +01:00
auto address = state . ctx - > registers . x2 ;
2020-01-21 08:16:57 +01:00
auto descriptor = state . os - > memory . Get ( address ) ;
2020-03-25 19:57:05 +01:00
2020-01-21 08:16:57 +01:00
if ( descriptor ) {
memInfo = {
. address = descriptor - > block . address ,
. size = descriptor - > block . size ,
. type = static_cast < u32 > ( descriptor - > chunk . state . type ) ,
2020-02-01 16:51:32 +01:00
. attributes = descriptor - > block . attributes . value ,
. permissions = static_cast < u32 > ( descriptor - > block . permission . Get ( ) ) ,
2020-01-21 08:16:57 +01:00
. deviceRefCount = 0 ,
. ipcRefCount = 0 ,
} ;
2020-03-25 19:57:05 +01:00
2020-02-01 16:51:32 +01: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 > ( descriptor - > block . attributes . isUncached ) , descriptor - > block . permission . r ? " R " : " - " , descriptor - > block . permission . w ? " W " : " - " , descriptor - > block . permission . x ? " X " : " - " ) ;
2020-01-21 08:16:57 +01:00
} else {
2020-07-06 13:03:32 +02:00
auto region = state . os - > memory . base ;
2020-02-01 16:51:32 +01:00
auto baseEnd = region . address + region . size ;
2020-03-25 19:57:05 +01:00
2020-01-21 08:16:57 +01:00
memInfo = {
2020-02-01 16:51:32 +01:00
. address = region . address ,
. size = ~ baseEnd + 1 ,
. type = static_cast < u32 > ( memory : : MemoryType : : Unmapped ) ,
2020-01-21 08:16:57 +01:00
} ;
2020-03-25 19:57:05 +01:00
2020-01-21 08:16:57 +01:00
state . logger - > Debug ( " svcQueryMemory: Cannot find block of address: 0x{:X} " , address ) ;
2019-09-24 22:54:27 +02:00
}
2020-03-25 19:57:05 +01:00
2020-01-21 08:16:57 +01:00
state . process - > WriteMemory ( memInfo , state . ctx - > registers . x0 ) ;
2020-03-25 19:57:05 +01:00
2020-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : Success ;
2019-09-24 22:54:27 +02: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
void ExitProcess ( DeviceState & state ) {
2020-01-01 14:11:25 +01:00
state . logger - > Debug ( " svcExitProcess: Exiting current process: {} " , state . process - > pid ) ;
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
}
2019-09-24 22:54:27 +02:00
void CreateThread ( DeviceState & state ) {
2020-04-22 19:02:27 +02:00
auto entryAddress = state . ctx - > registers . x1 ;
auto entryArgument = state . ctx - > registers . x2 ;
auto stackTop = state . ctx - > registers . x3 ;
auto priority = static_cast < i8 > ( state . ctx - > registers . w4 ) ;
2020-03-25 19:57:05 +01:00
2020-04-22 19:02:27 +02:00
if ( ! state . thread - > switchPriority . Valid ( priority ) ) {
2020-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : InvAddress ;
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-01-21 08:16:57 +01:00
auto thread = state . process - > CreateThread ( entryAddress , entryArgument , stackTop , priority ) ;
2020-04-22 19:02:27 +02:00
state . logger - > Debug ( " svcCreateThread: Created thread with handle 0x{:X} (Entry Point: 0x{:X}, Argument: 0x{:X}, Stack Pointer: 0x{:X}, Priority: {}, TID: {}) " , thread - > handle , entryAddress , entryArgument , stackTop , priority , thread - > tid ) ;
2020-03-25 19:57:05 +01:00
2020-01-07 03:36:08 +01:00
state . ctx - > registers . w1 = thread - > handle ;
state . ctx - > registers . w0 = constant : : status : : Success ;
2019-09-24 22:54:27 +02:00
}
void StartThread ( DeviceState & state ) {
2020-01-07 03:36:08 +01:00
auto handle = state . ctx - > registers . w0 ;
2019-11-17 21:19:01 +01:00
try {
2020-01-01 14:11:25 +01:00
auto thread = state . process - > GetHandle < type : : KThread > ( handle ) ;
2020-04-19 21:56:49 +02:00
state . logger - > Debug ( " svcStartThread: Starting thread: 0x{:X}, PID: {} " , handle , thread - > tid ) ;
2019-11-17 21:19:01 +01:00
thread - > Start ( ) ;
2020-02-01 16:51:32 +01:00
state . ctx - > registers . w0 = constant : : status : : Success ;
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-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : InvHandle ;
2019-11-17 21:19:01 +01:00
}
2019-09-24 22:54:27 +02:00
}
void ExitThread ( DeviceState & state ) {
2020-04-19 21:56:49 +02:00
state . logger - > Debug ( " svcExitThread: Exiting current thread: {} " , state . thread - > tid ) ;
state . os - > KillThread ( state . thread - > tid ) ;
2019-09-24 22:54:27 +02:00
}
2019-10-13 10:04:47 +02:00
void SleepThread ( DeviceState & state ) {
2020-01-07 03:36:08 +01:00
auto in = state . ctx - > registers . 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-01-15 19:58:58 +01:00
struct timespec spec = {
. tv_sec = static_cast < time_t > ( state . ctx - > registers . x0 / 1000000000 ) ,
. tv_nsec = static_cast < long > ( state . ctx - > registers . x0 % 1000000000 )
} ;
nanosleep ( & spec , nullptr ) ;
2019-11-17 21:19:01 +01:00
state . logger - > Debug ( " svcSleepThread: Thread sleeping for {} ns " , in ) ;
2019-10-13 10:04:47 +02:00
}
}
2019-09-24 22:54:27 +02:00
void GetThreadPriority ( DeviceState & state ) {
2020-06-27 17:57:11 +02:00
auto handle = state . ctx - > registers . w1 ;
2019-11-17 21:19:01 +01:00
try {
2020-01-01 14:11:25 +01: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-01-07 03:36:08 +01:00
state . ctx - > registers . w1 = priority ;
state . ctx - > registers . w0 = constant : : status : : Success ;
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-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : InvHandle ;
2019-11-17 21:19:01 +01:00
}
2019-09-24 22:54:27 +02:00
}
void SetThreadPriority ( DeviceState & state ) {
2020-01-07 03:36:08 +01:00
auto handle = state . ctx - > registers . w0 ;
auto priority = state . ctx - > registers . 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-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : Success ;
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-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : InvHandle ;
2019-11-17 21:19:01 +01:00
}
2019-09-24 22:54:27 +02:00
}
2019-10-13 10:04:47 +02:00
void MapSharedMemory ( DeviceState & state ) {
2019-11-17 21:19:01 +01:00
try {
2020-01-07 03:36:08 +01:00
auto object = state . process - > GetHandle < type : : KSharedMemory > ( state . ctx - > registers . w0 ) ;
2020-04-22 19:02:27 +02:00
auto address = state . ctx - > registers . x1 ;
2020-03-25 19:57:05 +01:00
2020-04-17 23:19:19 +02:00
if ( ! util : : PageAligned ( address ) ) {
2020-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : InvAddress ;
2020-01-21 08:16:57 +01:00
state . logger - > Warn ( " svcMapSharedMemory: 'address' not page aligned: 0x{:X} " , address ) ;
2019-11-17 21:19:01 +01:00
return ;
}
2020-03-25 19:57:05 +01:00
auto size = state . ctx - > registers . x2 ;
2020-04-17 23:19:19 +02:00
if ( ! util : : PageAligned ( size ) ) {
2020-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : InvSize ;
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-04-22 19:02:27 +02:00
memory : : Permission permission = * reinterpret_cast < memory : : Permission * > ( & state . ctx - > registers . w3 ) ;
2019-11-17 21:19:01 +01:00
if ( ( permission . w & & ! permission . r ) | | ( permission . x & & ! permission . r ) ) {
state . logger - > Warn ( " svcMapSharedMemory: 'permission' invalid: {}{}{} " , permission . r ? " R " : " - " , permission . w ? " W " : " - " , permission . x ? " X " : " - " ) ;
2020-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : InvPermission ;
2019-11-17 21:19:01 +01:00
return ;
}
2020-03-25 19:57:05 +01:00
2020-01-21 08:16:57 +01:00
state . logger - > Debug ( " svcMapSharedMemory: Mapping shared memory at 0x{:X} for {} bytes ({}{}{}) " , address , size , permission . r ? " R " : " - " , permission . w ? " W " : " - " , permission . x ? " X " : " - " ) ;
2020-03-25 19:57:05 +01:00
2020-01-21 08:16:57 +01:00
object - > Map ( address , size , permission ) ;
2020-03-25 19:57:05 +01:00
2020-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : Success ;
2019-11-17 21:19:01 +01:00
} catch ( const std : : exception & ) {
2020-01-07 03:36:08 +01:00
state . logger - > Warn ( " svcMapSharedMemory: 'handle' invalid: 0x{:X} " , state . ctx - > registers . w0 ) ;
state . ctx - > registers . w0 = constant : : status : : InvHandle ;
2019-09-24 22:54:27 +02: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
void CreateTransferMemory ( DeviceState & state ) {
2020-04-22 19:02:27 +02:00
auto address = state . ctx - > registers . x1 ;
2020-04-17 23:19:19 +02:00
if ( ! util : : PageAligned ( address ) ) {
2020-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : InvAddress ;
2020-01-21 08:16:57 +01:00
state . logger - > Warn ( " svcCreateTransferMemory: 'address' not page aligned: 0x{:X} " , address ) ;
2019-11-17 21:19:01 +01:00
return ;
}
2020-03-25 19:57:05 +01:00
2020-04-22 19:02:27 +02:00
auto size = state . ctx - > registers . x2 ;
2020-04-17 23:19:19 +02:00
if ( ! util : : PageAligned ( size ) ) {
2020-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : InvSize ;
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-04-22 19:02:27 +02:00
memory : : Permission permission = * reinterpret_cast < memory : : Permission * > ( & state . ctx - > registers . w3 ) ;
2019-11-17 21:19:01 +01:00
if ( ( permission . w & & ! permission . r ) | | ( permission . x & & ! permission . r ) ) {
state . logger - > Warn ( " svcCreateTransferMemory: 'permission' invalid: {}{}{} " , permission . r ? " R " : " - " , permission . w ? " W " : " - " , permission . x ? " X " : " - " ) ;
2020-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : InvPermission ;
2019-11-17 21:19:01 +01:00
return ;
}
2020-03-25 19:57:05 +01:00
2020-01-21 08:16:57 +01:00
state . logger - > Debug ( " svcCreateTransferMemory: Creating transfer memory at 0x{:X} for {} bytes ({}{}{}) " , address , size , permission . r ? " R " : " - " , permission . w ? " W " : " - " , permission . x ? " X " : " - " ) ;
2020-03-25 19:57:05 +01:00
2020-01-21 08:16:57 +01:00
auto shmem = state . process - > NewHandle < type : : KTransferMemory > ( state . process - > pid , address , size , permission ) ;
2020-03-25 19:57:05 +01:00
2020-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : Success ;
state . ctx - > registers . w1 = shmem . 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
}
2019-11-17 21:19:01 +01:00
void CloseHandle ( DeviceState & state ) {
2020-03-25 18:59:37 +01:00
auto handle = static_cast < KHandle > ( state . ctx - > registers . w0 ) ;
2019-11-17 21:19:01 +01:00
try {
2020-01-21 08:16:57 +01:00
state . process - > handles . erase ( handle ) ;
2019-11-17 21:19:01 +01:00
state . logger - > Debug ( " svcCloseHandle: Closing handle: 0x{:X} " , handle ) ;
2020-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : Success ;
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-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : InvHandle ;
2019-11-17 21:19:01 +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
void ResetSignal ( DeviceState & state ) {
2020-01-07 03:36:08 +01:00
auto handle = state . ctx - > registers . 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-01-21 08:16:57 +01:00
auto & object = state . process - > handles . at ( 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-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : InvHandle ;
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-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : Success ;
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-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : InvHandle ;
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
}
}
2019-09-24 22:54:27 +02:00
void WaitSynchronization ( DeviceState & state ) {
2020-03-25 18:59:37 +01:00
constexpr auto maxSyncHandles = 0x40 ; // The total amount of handles that can be passed to WaitSynchronization
2020-03-25 19:57:05 +01:00
2020-01-07 03:36:08 +01:00
auto numHandles = state . ctx - > registers . w2 ;
2020-03-25 18:59:37 +01:00
if ( numHandles > maxSyncHandles ) {
2020-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : MaxHandles ;
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 ;
std : : vector < KHandle > waitHandles ( numHandles ) ;
state . process - > ReadMemory ( waitHandles . data ( ) , state . ctx - > registers . x1 , numHandles * sizeof ( KHandle ) ) ;
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-01-21 08:16:57 +01:00
auto object = state . process - > handles . at ( 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-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : InvHandle ;
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-01-12 21:37:22 +01:00
auto timeout = state . ctx - > registers . x3 ;
state . logger - > Debug ( " svcWaitSynchronization: Waiting on handles: \n {}Timeout: 0x{:X} ns " , handleStr , timeout ) ;
2020-03-25 18:59:37 +01:00
2020-04-17 23:19:19 +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 ;
state . ctx - > registers . w0 = constant : : status : : Interrupted ;
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 ) {
state . logger - > Debug ( " svcWaitSynchronization: Signalled handle: 0x{:X} " , waitHandles . at ( index ) ) ;
state . ctx - > registers . w0 = constant : : status : : Success ;
state . ctx - > registers . w1 = index ;
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-01-11 05:52:25 +01:00
state . ctx - > registers . w0 = constant : : status : : Timeout ;
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-02-01 16:51:32 +01:00
void CancelSynchronization ( DeviceState & state ) {
try {
state . process - > GetHandle < type : : KThread > ( state . ctx - > registers . w0 ) - > cancelSync = true ;
} catch ( const std : : exception & ) {
state . logger - > Warn ( " svcCancelSynchronization: 'handle' invalid: 0x{:X} " , state . ctx - > registers . w0 ) ;
state . ctx - > registers . w0 = constant : : status : : InvHandle ;
}
}
2019-10-16 14:41:30 +02:00
void ArbitrateLock ( DeviceState & state ) {
2020-02-01 16:51:32 +01:00
auto address = state . ctx - > registers . x1 ;
2020-04-17 23:19:19 +02:00
if ( ! util : : WordAligned ( address ) ) {
2020-02-01 16:51:32 +01:00
state . logger - > Warn ( " svcArbitrateLock: 'address' not word aligned: 0x{:X} " , address ) ;
2020-02-05 07:42:53 +01:00
state . ctx - > registers . w0 = constant : : status : : InvAddress ;
2019-11-17 21:19:01 +01:00
return ;
}
2020-03-25 19:57:05 +01:00
2020-02-01 16:51:32 +01:00
auto ownerHandle = state . ctx - > registers . w0 ;
auto requesterHandle = state . ctx - > registers . w2 ;
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-02-05 07:42:53 +01:00
state . logger - > Debug ( " svcArbitrateLock: Locking mutex at 0x{:X} " , address ) ;
2020-03-25 19:57:05 +01:00
2020-02-05 07:42:53 +01:00
if ( state . process - > MutexLock ( address , ownerHandle ) )
state . logger - > Debug ( " svcArbitrateLock: Locked mutex at 0x{:X} " , address ) ;
else
2020-04-02 08:39:24 +02:00
state . logger - > Debug ( " svcArbitrateLock: Owner handle did not match current owner for mutex or didn't have waiter flag at 0x{:X} " , address ) ;
2020-03-25 19:57:05 +01:00
2020-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : Success ;
2019-10-16 14:41:30 +02:00
}
void ArbitrateUnlock ( DeviceState & state ) {
2020-01-21 08:16:57 +01:00
auto address = state . ctx - > registers . x0 ;
2020-04-17 23:19:19 +02:00
if ( ! util : : WordAligned ( address ) ) {
2020-01-21 08:16:57 +01:00
state . logger - > Warn ( " svcArbitrateUnlock: 'address' not word aligned: 0x{:X} " , address ) ;
2020-02-05 07:42:53 +01:00
state . ctx - > registers . w0 = constant : : status : : InvAddress ;
2019-11-17 21:19:01 +01:00
return ;
}
2020-03-25 19:57:05 +01:00
2020-01-21 08:16:57 +01:00
state . logger - > Debug ( " svcArbitrateUnlock: Unlocking mutex at 0x{:X} " , address ) ;
2020-03-25 19:57:05 +01:00
2020-02-05 07:42:53 +01:00
if ( state . process - > MutexUnlock ( address ) ) {
2020-02-01 16:51:32 +01:00
state . logger - > Debug ( " svcArbitrateUnlock: Unlocked mutex at 0x{:X} " , address ) ;
2020-02-05 07:42:53 +01:00
state . ctx - > registers . w0 = constant : : status : : Success ;
2020-02-01 16:51:32 +01:00
} else {
state . logger - > Debug ( " svcArbitrateUnlock: A non-owner thread tried to release a mutex at 0x{:X} " , address ) ;
2020-02-05 07:42:53 +01:00
state . ctx - > registers . w0 = constant : : status : : InvAddress ;
2020-02-01 16:51:32 +01:00
}
2019-10-16 14:41:30 +02:00
}
void WaitProcessWideKeyAtomic ( DeviceState & state ) {
2020-01-21 08:16:57 +01:00
auto mtxAddress = state . ctx - > registers . x0 ;
2020-04-17 23:19:19 +02:00
if ( ! util : : WordAligned ( mtxAddress ) ) {
2020-02-01 16:51:32 +01:00
state . logger - > Warn ( " svcWaitProcessWideKeyAtomic: mutex address not word aligned: 0x{:X} " , mtxAddress ) ;
2020-02-05 07:42:53 +01:00
state . ctx - > registers . w0 = constant : : status : : InvAddress ;
2020-02-01 16:51:32 +01:00
return ;
}
2020-03-25 19:57:05 +01:00
2020-01-21 08:16:57 +01:00
auto condAddress = state . ctx - > registers . x1 ;
2020-02-01 16:51:32 +01:00
auto handle = state . ctx - > registers . w2 ;
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-02-05 07:42:53 +01:00
if ( ! state . process - > MutexUnlock ( mtxAddress ) ) {
2020-02-01 16:51:32 +01:00
state . logger - > Debug ( " WaitProcessWideKeyAtomic: A non-owner thread tried to release a mutex at 0x{:X} " , mtxAddress ) ;
2020-02-05 07:42:53 +01:00
state . ctx - > registers . w0 = constant : : status : : InvAddress ;
2020-02-01 16:51:32 +01:00
return ;
}
2020-03-25 19:57:05 +01:00
2020-02-01 16:51:32 +01:00
auto timeout = state . ctx - > registers . x3 ;
state . logger - > Debug ( " svcWaitProcessWideKeyAtomic: Mutex: 0x{:X}, Conditional-Variable: 0x{:X}, Timeout: {} ns " , mtxAddress , condAddress , timeout ) ;
2020-03-25 19:57:05 +01:00
2020-02-05 07:42:53 +01:00
if ( state . process - > ConditionalVariableWait ( condAddress , mtxAddress , timeout ) ) {
2020-02-01 16:51:32 +01:00
state . logger - > Debug ( " svcWaitProcessWideKeyAtomic: Waited for conditional variable and relocked mutex " ) ;
2020-02-05 07:42:53 +01:00
state . ctx - > registers . w0 = constant : : status : : Success ;
2020-02-01 16:51:32 +01:00
} else {
state . logger - > Debug ( " svcWaitProcessWideKeyAtomic: Wait has timed out " ) ;
2020-02-05 07:42:53 +01:00
state . ctx - > registers . w0 = constant : : status : : Timeout ;
2019-10-16 14:41:30 +02:00
}
}
void SignalProcessWideKey ( DeviceState & state ) {
2020-01-07 03:36:08 +01:00
auto address = state . ctx - > registers . x0 ;
2020-01-12 21:37:22 +01:00
auto count = state . ctx - > registers . w1 ;
2020-03-25 19:57:05 +01:00
2020-02-01 16:51:32 +01:00
state . logger - > Debug ( " svcSignalProcessWideKey: Signalling Conditional-Variable at 0x{:X} for {} " , address , count ) ;
state . process - > ConditionalVariableSignal ( address , count ) ;
2020-01-11 05:52:25 +01:00
state . ctx - > registers . w0 = constant : : status : : Success ;
2019-11-17 21:19:01 +01:00
}
void GetSystemTick ( DeviceState & state ) {
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-01-07 03:36:08 +01:00
state . ctx - > registers . x0 = tick ;
2019-09-24 22:54:27 +02:00
}
void ConnectToNamedPort ( DeviceState & state ) {
2020-03-25 18:59:37 +01:00
constexpr auto portSize = 0x8 ; //!< The size of a port name string
std : : string_view port ( state . process - > GetPointer < char > ( state . ctx - > registers . x1 ) , portSize ) ;
KHandle handle { } ;
if ( port . compare ( " sm: " ) > = 0 ) {
2020-02-16 20:11:43 +01:00
handle = state . os - > serviceManager . NewSession ( service : : Service : : sm_IUserInterface ) ;
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-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : 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-01-07 03:36:08 +01:00
state . ctx - > registers . w1 = handle ;
state . ctx - > registers . w0 = constant : : status : : Success ;
2019-09-24 22:54:27 +02:00
}
void SendSyncRequest ( DeviceState & state ) {
2020-03-25 18:59:37 +01:00
state . os - > serviceManager . SyncRequestHandler ( static_cast < KHandle > ( state . ctx - > registers . x0 ) ) ;
2020-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : Success ;
2019-09-24 22:54:27 +02: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
void GetThreadId ( DeviceState & state ) {
2020-03-25 18:59:37 +01:00
constexpr KHandle threadSelf = 0xFFFF8000 ; // This is the handle used by threads to refer to themselves
2020-01-07 03:36:08 +01:00
auto handle = state . ctx - > registers . w1 ;
2020-03-25 18:59:37 +01:00
pid_t pid { } ;
if ( handle ! = threadSelf )
2020-04-19 21:56:49 +02:00
pid = state . process - > GetHandle < type : : KThread > ( handle ) - > tid ;
2020-02-15 10:38:17 +01:00
else
2020-04-19 21:56:49 +02:00
pid = state . thread - > tid ;
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-01-07 03:36:08 +01:00
state . ctx - > registers . x1 = static_cast < u64 > ( pid ) ;
state . ctx - > registers . w0 = constant : : status : : Success ;
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
}
2019-09-24 22:54:27 +02:00
void OutputDebugString ( DeviceState & state ) {
2020-02-15 10:38:17 +01:00
auto debug = state . process - > GetString ( state . ctx - > registers . x0 , state . ctx - > registers . x1 ) ;
2020-03-25 19:57:05 +01:00
2020-01-11 05:52:25 +01:00
if ( debug . back ( ) = = ' \n ' )
2019-11-23 19:48:22 +01:00
debug . pop_back ( ) ;
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-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : Success ;
2019-09-24 22:54:27 +02:00
}
void GetInfo ( DeviceState & state ) {
2020-01-07 03:36:08 +01:00
auto id0 = state . ctx - > registers . w1 ;
auto handle = state . ctx - > registers . w2 ;
auto id1 = state . ctx - > registers . 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-03-25 19:57:05 +01:00
constexpr auto totalPhysicalMemory = 0xF8000000 ; // ~4 GB of RAM
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-07-06 13:03:32 +02:00
out = state . os - > 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-07-06 13:03:32 +02:00
out = state . os - > 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-07-06 13:03:32 +02:00
out = state . os - > 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-07-06 13:03:32 +02:00
out = state . os - > 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-01-21 08:16:57 +01:00
out = state . process - > heap - > address + constant : : DefStackSize + state . os - > 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-07-06 13:03:32 +02:00
out = state . os - > memory . base . 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-07-06 13:03:32 +02:00
out = state . os - > memory . base . 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-07-06 13:03:32 +02:00
out = state . os - > 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-07-06 13:03:32 +02:00
out = state . os - > 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-01-21 08:16:57 +01:00
out = state . process - > heap - > address + constant : : DefStackSize ;
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-01-21 08:16:57 +01:00
out = state . process - > heap - > size + constant : : DefStackSize ; // 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-01-01 14:11:25 +01:00
out = 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-01-07 03:36:08 +01:00
state . ctx - > registers . w0 = constant : : status : : Unimpl ;
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-01-07 03:36:08 +01:00
state . ctx - > registers . x1 = out ;
state . ctx - > registers . w0 = constant : : status : : Success ;
2019-09-24 22:54:27 +02:00
}
}