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 21: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: Resultr1: handle to KClientSession
 | 
| 0x32 | SendSyncRequest | r0: handle to KClientSession
 | 
r0: Result |