Difference between revisions of "JIT services"

From Nintendo Switch Brew
Jump to navigation Jump to search
Line 3: Line 3:
 
nnMain just initializes [[RO_services|ro:1]], then starts hosting the service from the main-thread with max_sessions=1 (threads are not created for service-hosting).
 
nnMain just initializes [[RO_services|ro:1]], then starts hosting the service from the main-thread with max_sessions=1 (threads are not created for service-hosting).
  
This is intended to only be used by Applications. The initialization in sdknso uses [[Applet_Manager_services#PrepareForJit|PrepareForJit]] at the start. sdknso later uses [[SVC|svcCreateCodeMemory]].
+
This is intended to only be used by Applications. The service-init in sdknso just uses [[Applet_Manager_services#PrepareForJit|PrepareForJit]] at the start, then gets the service.
 +
 
 +
sdknso CreateJitEnvironment implements the remaining initialization. After some validation, this uses [[SVC|svcCreateCodeMemory]] (can be called twice). Then [[#CreateJitEnvironment]] is used. TransferMemory with an user-specified buffer is created with permissions=None, which is then used with [[#LoadPlugin]]. When successful, this lastly uses [[#GetCodeAddress]].
  
 
This loads the user-specified [[NRO]] into sysmodule-context ("DllPlugin"), and calls various symbols from that NRO. It seems the code writing (in cmd GenerateCode) is done via symbol-calling, allowing the NRO to handle input_buffer->code translation+writing.
 
This loads the user-specified [[NRO]] into sysmodule-context ("DllPlugin"), and calls various symbols from that NRO. It seems the code writing (in cmd GenerateCode) is done via symbol-calling, allowing the NRO to handle input_buffer->code translation+writing.
Line 12: Line 14:
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
! Cmd || Name || Notes
+
! Cmd || Name
 
|-
 
|-
| 0 || CreateJitEnvironment || Returns an [[#IJitEnvironment]]
+
| 0 || [[#CreateJitEnvironment]]
 
|-
 
|-
 
|}
 
|}
 +
 +
== CreateJitEnvironment ==
 +
Takes two input u64s, 3 input handles, returns an [[#IJitEnvironment]].
  
 
= IJitEnvironment =
 
= IJitEnvironment =
Line 25: Line 30:
 
! Cmd || Name
 
! Cmd || Name
 
|-
 
|-
| 0 || GenerateCode
+
| 0 || [[#GenerateCode]]
 
|-
 
|-
| 1 || Control
+
| 1 || [[#Control]]
 
|-
 
|-
| 1000 || LoadPlugin
+
| 1000 || [[#LoadPlugin]]
 
|-
 
|-
| 1001 || GetCodeAddress
+
| 1001 || [[#GetCodeAddress]]
 
|}
 
|}
 +
 +
== GenerateCode ==
 +
Takes an u32, an u64, a [[#CodeRange]], a [[#CodeRange]], a [[#Struct32]], a type-0x5 input buffer, a type-0x6 output buffer, and returns an output s32, a [[#CodeRange]], a [[#CodeRange]].
 +
 +
== Control ==
 +
Takes an input u64, a type-0x5 input buffer, a type-0x6 output buffer, and returns an output s32.
 +
 +
== LoadPlugin ==
 +
Takes an input u64, a handle, two type-0x5 input buffers, no output.
 +
 +
== GetCodeAddress ==
 +
No input, returns two output u64s which are loaded from state.
 +
 +
== CodeRange ==
 +
This is "nn::jit::CodeRange". This is a 0x10-byte struct. This is 8-byte aligned.
 +
 +
== Struct32 ==
 +
This is "nn::jitsrv::Struct32". This is a 0x20-byte struct. This is 8-byte aligned.

Revision as of 16:52, 15 April 2020

JIT is a sysmodule for run-time code generation (allowing for overlapping R-X and RW- views of memory). This was added to retail with [10.0.0+]. This was also supported in sdknso for a number of versions prior.

nnMain just initializes ro:1, then starts hosting the service from the main-thread with max_sessions=1 (threads are not created for service-hosting).

This is intended to only be used by Applications. The service-init in sdknso just uses PrepareForJit at the start, then gets the service.

sdknso CreateJitEnvironment implements the remaining initialization. After some validation, this uses svcCreateCodeMemory (can be called twice). Then #CreateJitEnvironment is used. TransferMemory with an user-specified buffer is created with permissions=None, which is then used with #LoadPlugin. When successful, this lastly uses #GetCodeAddress.

This loads the user-specified NRO into sysmodule-context ("DllPlugin"), and calls various symbols from that NRO. It seems the code writing (in cmd GenerateCode) is done via symbol-calling, allowing the NRO to handle input_buffer->code translation+writing.

jit:u

This is "nn::jitsrv::IJitService".

Cmd Name
0 #CreateJitEnvironment

CreateJitEnvironment

Takes two input u64s, 3 input handles, returns an #IJitEnvironment.

IJitEnvironment

This is "nn::jitsrv::IJitEnvironment".

Cmd Name
0 #GenerateCode
1 #Control
1000 #LoadPlugin
1001 #GetCodeAddress

GenerateCode

Takes an u32, an u64, a #CodeRange, a #CodeRange, a #Struct32, a type-0x5 input buffer, a type-0x6 output buffer, and returns an output s32, a #CodeRange, a #CodeRange.

Control

Takes an input u64, a type-0x5 input buffer, a type-0x6 output buffer, and returns an output s32.

LoadPlugin

Takes an input u64, a handle, two type-0x5 input buffers, no output.

GetCodeAddress

No input, returns two output u64s which are loaded from state.

CodeRange

This is "nn::jit::CodeRange". This is a 0x10-byte struct. This is 8-byte aligned.

Struct32

This is "nn::jitsrv::Struct32". This is a 0x20-byte struct. This is 8-byte aligned.