Kernel ABI: Difference between revisions
No edit summary |
GasInfinity (talk | contribs) m typo |
||
(11 intermediate revisions by 5 users not shown) | |||
Line 1: | Line 1: | ||
= Calling Convention = | |||
Seems to be [https://github.com/ARM-software/abi-aa/blob/main/aapcs32/aapcs32.rst#the-base-procedure-call-standard AAPCS]-based (with modifications) | |||
== Overview == | |||
=== Inputs === | |||
* <code>r0–r3</code> : Argument / Scratch registers (caller-saved), inherited from AAPCS. ''If an input is to be placed on the stack, it will instead use the next free register starting from <code>r0</code>.'' | |||
=== Outputs === | |||
* <code>r0-r1</code> : Result, inherited from AAPCS. ''If multiple outputs are returned (e.g., <code>ControlMemory</code>), they are placed in consecutive registers starting from <code>r0</code>.'' | |||
== Example == | |||
<code>Result ControlMemory(uintptr_t* out, uintptr_t addr0, uintptr_t addr1, size_t size, MemoryOperation operation, MemoryPermission permissions)</code> | |||
=== Inputs === | |||
Following standard [https://github.com/ARM-software/abi-aa/blob/main/aapcs32/aapcs32.rst#the-base-procedure-call-standard AAPCS] register selection: | |||
; <code>r1</code> -> addr0 | |||
; <code>r2</code> -> addr1 | |||
; <code>r3</code> -> size | |||
As there are still more arguments, the next free registers are selected starting from <code>r0</code> | |||
; <code>r0</code> -> operation | |||
; <code>r4</code> -> permissions | |||
=== Outputs === | |||
; <code>r0</code> -> Result | |||
; <code>r1</code> -> uintptr_t out | |||
== System calls == | |||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
! | ! ID | ||
! Name | ! Name | ||
! Inputs | ! Inputs | ||
! Outputs | ! Outputs | ||
|- | |||
| 0x01 | |||
| ControlMemory | |||
| | |||
<code>r0</code>: <code>[[Memory Management#enum_MemoryOperation|MemoryOperation]] operation</code><br> | |||
<code>r1</code>: <code>u32/void* addr0</code><br> | |||
<code>r2</code>: <code>u32/void* addr1</code><br> | |||
<code>r3</code>: <code>u32 size</code><br> | |||
<code>r4</code>: <code>[[Memory Management#enum_MemoryPermission|MemoryPermission]] permissions</code> | |||
| | |||
<code>r0</code>: <code>Result</code><br> | |||
<code>r1</code>: <code>u32/void* addr_out</code> | |||
|- | |||
| 0x02 | |||
| QueryMemory | |||
| | |||
<code>r2</code>?: <code>u32/void* addr</code> | |||
| | |||
<code>r0</code>: <code>Result</code><br> | |||
<code>r1</code>: <code>u32 base_process_virtual_address</code><br> | |||
<code>r2</code>: <code>u32 size</code><br> | |||
<code>r3</code>: <code>[[Memory Management#enum_MemoryPermission|MemoryPermission]] permission</code><br> | |||
<code>r4</code>: <code>[[Memory_Management#enum_MemoryState|MemoryState]] state</code><br> | |||
<code>r5</code>: <code>[[Memory_Management#enum_PageFlags|PageFlags]] page_flags</code> | |||
|- | |||
| 0x03 | |||
| ExitProcess | |||
| None | |||
| None, doesn't return | |||
|- | |||
| 0x04 | |||
| GetProcessAffinityMask | |||
| | |||
<code>r0</code>: <code>[out] u8* affinitymask</code><br> | |||
<code>r1</code>: <code>Handle<[[KProcess]]> process</code><br> | |||
<code>r2</code>: <code>s32 processorcount</code> | |||
| | |||
<code>r0</code>: <code>Result</code> | |||
|- | |||
| 0x05 | |||
| SetProcessAffinityMask | |||
| | |||
<code>r0</code>: <code>Handle<[[KProcess]]> process</code><br> | |||
<code>r1</code>: <code>[in] const u8* affinitymask</code><br> | |||
<code>r2</code>: <code>s32 processorcount</code> | |||
| | |||
<code>r0</code>: <code>Result</code> | |||
|- | |||
| 0x06 | |||
| GetProcessIdealProcessor | |||
| | |||
<code>r1</code>?: <code>Handle<[[KProcess]]> process</code> | |||
| | |||
<code>r0</code>: <code>Result</code><br> | |||
<code>r1</code>: <code>s32 processorid</code><br> | |||
<code>r2</code>: Clobbered? | |||
|- | |||
| 0x07 | |||
| SetProcessIdealProcessor | |||
| | |||
<code>r0</code>: <code>Handle<[[KProcess]]> process</code><br> | |||
<code>r1</code>: <code>s32 processorid</code> | |||
| | |||
<code>r0</code>: <code>Result</code><br> | |||
|- | |||
| 0x08 | |||
| CreateThread | |||
| | |||
<code>r0</code>: <code>s32 thread_priority</code><br> | |||
<code>r1</code>: <code>ThreadFunc entrypoint</code><br> | |||
<code>r2</code>: <code>u32 arg</code><br> | |||
<code>r3</code>: <code>u32/void* stack_top</code><br> | |||
<code>r4</code>: <code>s32 processor_id</code> | |||
| | |||
<code>r0</code>: <code>Result</code><br> | |||
<code>r1</code>: <code>Handle<[[KThread]]> thread_handle</code> | |||
|- | |||
| 0x09 | |||
| ExitThread | |||
| None | |||
| None, doesn't return | |||
|- | |||
| 0x0A | |||
| SleepThread | |||
| | |||
<code>r0-r1</code>: <code>s64 nanoseconds</code> | |||
| None | |||
|- | |||
| 0x0B | |||
| GetThreadPriority | |||
| | |||
<code>r0</code>: Ignored?<br> | |||
<code>r1</code>: <code>Handle thread_handle</code> | |||
| | |||
<code>r0</code>: <code>Result</code><br> | |||
<code>r1</code>: <code>s32 thread_priority</code><br> | |||
<code>r2</code>: Clobbered? | |||
|- | |||
| 0x0C | |||
| SetThreadPriority | |||
| | |||
<code>r0</code>: <code>Handle<[[KThread]]> thread_handle</code><br> | |||
<code>r1</code>: <code>s32 thread_priority</code> | |||
| | |||
<code>r0</code>: <code>Result</code> | |||
|- | |||
| 0x0D | |||
| GetThreadAffinityMask | |||
| | |||
<code>r0</code>: <code>[out] u8* affinitymask</code><br> | |||
<code>r1</code>: <code>Handle<[[KThread]]> thread_handle</code><br> | |||
<code>r2</code>: <code>s32 processorcount</code> | |||
| | |||
<code>r0</code>: <code>Result</code> | |||
|- | |||
| 0x0E | |||
| SetThreadAffinityMask | |||
| | |||
<code>r0</code>: <code>Handle<[[KThread]]> thread_handle</code><br> | |||
<code>r1</code>: <code>[in] const u8* affinitymask</code><br> | |||
<code>r2</code>: <code>s32 processorcount</code> | |||
| | |||
<code>r0</code>: <code>Result</code> | |||
|- | |||
| 0x0F | |||
| GetThreadIdealProcessor | |||
| | |||
<code>r0</code>: Ignored?<br> | |||
<code>r1</code>: <code>Handle<[[KThread]]> thread_handle</code> | |||
| | |||
<code>r0</code>: <code>Result</code><br> | |||
<code>r1</code>: <code>s32 processorid</code> | |||
|- | |||
| 0x10 | |||
| SetThreadIdealProcessor | |||
| | |||
<code>r0</code>: <code>Handle<[[KThread]]> thread_handle</code><br> | |||
<code>r1</code>: <code>s32 processorid</code> | |||
| | |||
<code>r0</code>: <code>Result</code> | |||
|- | |||
| 0x11 | |||
| GetProcessorID | |||
| | |||
None | |||
| | |||
<code>r0</code>: <code>s32 processorid</code> | |||
|- | |||
| 0x24 | |||
| WaitSynchronization1 | |||
| | |||
<code>r0</code>: <code>Handle<[[KSynchronizationObject]]> handle</code><br> | |||
<code>r2-r3</code>: <code>s64 timeout</code> | |||
| | |||
<code>r0</code>: <code>Result</code> | |||
|- | |- | ||
| 0x1B | | 0x1B | ||
Line 12: | Line 194: | ||
| Timer handle, initial_low, interval_low, initial_high, interval_high | | Timer handle, initial_low, interval_low, initial_high, interval_high | ||
| Result | | Result | ||
|- | |||
| 0x28 | |||
| GetSystemTick | |||
| None | |||
| | |||
<code>r0</code>: <code>Low 32 bits of the tick count</code> | |||
<br><code>r1</code>: <code>High 32 bits of the tick count</code> | |||
|- | |- | ||
| 0x2D | | 0x2D | ||
| ConnectToPort | | ConnectToPort | ||
| ?? | | ??<br><code>r1</code>: <code>pointer to port name</code> | ||
| Result | | <code>r0</code>: <code>Result</code><br><code>r1</code>: <code>handle to [[KClientSession]]</code> | ||
|- | |- | ||
| 0x32 | | 0x32 | ||
| SendSyncRequest | | SendSyncRequest | ||
| handle to [[KClientSession]] | | <code>r0</code>: <code>handle to [[KClientSession]]</code> | ||
| Result | | <code>r0</code>: <code>Result<code> | ||
|} | |} |
Latest revision as of 22:08, 29 August 2025
Calling Convention
Seems to be AAPCS-based (with modifications)
Overview
Inputs
r0–r3
: Argument / Scratch registers (caller-saved), inherited from AAPCS. If an input is to be placed on the stack, it will instead use the next free register starting fromr0
.
Outputs
r0-r1
: Result, inherited from AAPCS. If multiple outputs are returned (e.g.,ControlMemory
), they are placed in consecutive registers starting fromr0
.
Example
Result ControlMemory(uintptr_t* out, uintptr_t addr0, uintptr_t addr1, size_t size, MemoryOperation operation, MemoryPermission permissions)
Inputs
Following standard AAPCS register selection:
r1
-> addr0r2
-> addr1r3
-> size
As there are still more arguments, the next free registers are selected starting from r0
r0
-> operationr4
-> permissions
Outputs
r0
-> Resultr1
-> uintptr_t out
System calls
ID | Name | Inputs | Outputs |
---|---|---|---|
0x01 | ControlMemory |
|
|
0x02 | QueryMemory |
|
|
0x03 | ExitProcess | None | None, doesn't return |
0x04 | GetProcessAffinityMask |
|
|
0x05 | SetProcessAffinityMask |
|
|
0x06 | GetProcessIdealProcessor |
|
|
0x07 | SetProcessIdealProcessor |
|
|
0x08 | CreateThread |
|
|
0x09 | ExitThread | None | None, doesn't return |
0x0A | SleepThread |
|
None |
0x0B | GetThreadPriority |
|
|
0x0C | SetThreadPriority |
|
|
0x0D | GetThreadAffinityMask |
|
|
0x0E | SetThreadAffinityMask |
|
|
0x0F | GetThreadIdealProcessor |
|
|
0x10 | SetThreadIdealProcessor |
|
|
0x11 | GetProcessorID |
None |
|
0x24 | WaitSynchronization1 |
|
|
0x1B | SetTimer | Timer handle, initial_low, interval_low, initial_high, interval_high | Result |
0x28 | GetSystemTick | None |
|
0x2D | ConnectToPort | ??r1 : pointer to port name
|
r0 : Result r1 : handle to KClientSession
|
0x32 | SendSyncRequest | r0 : handle to KClientSession
|
r0 : Result |