<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://switchbrew.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Gdkchan</id>
	<title>Nintendo Switch Brew - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://switchbrew.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Gdkchan"/>
	<link rel="alternate" type="text/html" href="https://switchbrew.org/wiki/Special:Contributions/Gdkchan"/>
	<updated>2026-05-02T14:08:48Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.1</generator>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=SVC&amp;diff=4756</id>
		<title>SVC</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=SVC&amp;diff=4756"/>
		<updated>2018-06-11T13:33:35Z</updated>

		<summary type="html">&lt;p&gt;Gdkchan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&lt;br /&gt;
= System calls =&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Id || Name || In || Out&lt;br /&gt;
|-&lt;br /&gt;
|  0x1 || [[#svcSetHeapSize]] || W1=size || W0=result, X1=outaddr&lt;br /&gt;
|-&lt;br /&gt;
|  0x2 || [[#svcSetMemoryPermission]] || X0=addr, X1=size, W2=prot || W0=result&lt;br /&gt;
|-&lt;br /&gt;
|  0x3 || [[#svcSetMemoryAttribute]] || X0=addr, X1=size, W2=state0, W3=state1 || W0=result&lt;br /&gt;
|-&lt;br /&gt;
|  0x4 || [[#svcMapMemory]] || X0=dstaddr, X1=srcaddr, X2=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
|  0x5 || [[#svcUnmapMemory]] || X0=dstaddr, X1=srcaddr, X2=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
|  0x6 || [[#svcQueryMemory]] || X0=MemoryInfo*, X2=addr || W0=result, W1=PageInfo                                                         &lt;br /&gt;
|-&lt;br /&gt;
|  0x7 || [[#svcExitProcess]] || None ||&lt;br /&gt;
|-&lt;br /&gt;
|  0x8 || [[#svcCreateThread]] || X1=entry, X2=thread_context, X3=stacktop, W4=prio, W5=processor_id  || W0=result, W1=handle&lt;br /&gt;
|-&lt;br /&gt;
|  0x9 || [[#svcStartThread]] || W0=thread_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
|  0xA || [[#svcExitThread]] || None ||                                                         &lt;br /&gt;
|-&lt;br /&gt;
|  0xB || [[#svcSleepThread]] || X0=nano || W0=result&lt;br /&gt;
|-&lt;br /&gt;
|  0xC || [[#svcGetThreadPriority]] || W1=thread_handle || W0=result, W1=prio&lt;br /&gt;
|-&lt;br /&gt;
|  0xD || [[#svcSetThreadPriority]] || W0=thread_handle, W1=prio || W0=result&lt;br /&gt;
|-&lt;br /&gt;
|  0xE || [[#svcGetThreadCoreMask]] || W2=thread_handle || W0=result, W1=out, X2=out&lt;br /&gt;
|-&lt;br /&gt;
|  0xF || [[#svcSetThreadCoreMask]] || W0=thread_handle, W1=in, X2=in2 || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#svcGetCurrentProcessorNumber]] || None || W0/X0=cpuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || svcSignalEvent || W0=wevent_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || svcClearEvent || W0=wevent_or_revent_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x13 || [[#svcMapSharedMemory]] || W0=shmem_handle, X1=addr, X2=size, W3=perm || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x14 || svcUnmapSharedMemory || W0=shmem_handle, X1=addr, X2=size || W0=result                                                 &lt;br /&gt;
|-&lt;br /&gt;
| 0x15 || [[#svcCreateTransferMemory]] || X1=addr, X2=size, W3=perm || W0=result, W1=tmem_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x16 || svcCloseHandle || W0=handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x17 || svcResetSignal || W0=revent_or_process_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || [[#svcWaitSynchronization]] || X1=handles_ptr, W2=num_handles. X3=timeout || W0=result, W1=handle_idx&lt;br /&gt;
|-&lt;br /&gt;
| 0x19 || svcCancelSynchronization || W0=thread_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A || svcArbitrateLock || W0=cur_thread_handle, X1=ptr, W2=req_thread_handle ||                                     &lt;br /&gt;
|-&lt;br /&gt;
| 0x1B || svcArbitrateUnlock || X0=ptr ||&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || svcWaitProcessWideKeyAtomic || X0=ptr0, X1=ptr, W2=thread_handle, X3=timeout || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x1D || svcSignalProcessWideKey || X0=ptr, W1=value || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x1E || [[#svcGetSystemTick]] || None || X0={value of cntpct_el0}&lt;br /&gt;
|-&lt;br /&gt;
| 0x1F || svcConnectToNamedPort || X1=port_name_str || W0=result, W1=handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || svcSendSyncRequestLight || W0=light_session_handle, X1=? || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x21 || svcSendSyncRequest || X0=normal_session_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x22 || [[#svcSendSyncRequestWithUserBuffer]] || X0=cmdbufptr, X1=size, X2=handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x23 || svcSendAsyncRequestWithUserBuffer || X1=cmdbufptr, X2=size, X3=handle || W0=result, W1=revent_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || svcGetProcessId || W1=thread_or_process_or_debug_handle || W0=result, X1=pid&lt;br /&gt;
|-&lt;br /&gt;
| 0x25 || svcGetThreadId || W1=thread_handle || W0=result, X1=out&lt;br /&gt;
|-&lt;br /&gt;
| 0x26 || [[#svcBreak]] || X0=break_reason,X1,X2=info || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x27 || svcOutputDebugString || X0=str, X1=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || svcReturnFromException || X0=result || &lt;br /&gt;
|-&lt;br /&gt;
| 0x29 || [[#svcGetInfo]] || X1=info_id, X2=handle, X3=info_sub_id || W0=result, X1=out&lt;br /&gt;
|-&lt;br /&gt;
| 0x2A || svcFlushEntireDataCache || None || None&lt;br /&gt;
|-&lt;br /&gt;
| 0x2B || svcFlushDataCache || X0=addr, X1=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C || [3.0.0+] [[#svcMapPhysicalMemory]] || X0=addr, X1=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x2D || [3.0.0+] svcUnmapPhysicalMemory || X0=addr, X1=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x2E || [5.0.0+] svcGetFutureThreadInfo || X3=timeout || W0=result, bunch of crap&lt;br /&gt;
|-&lt;br /&gt;
| 0x2F || svcGetLastThreadInfo || None || W0=result, W1,W2,W3,W4=unk, W5=truncated_u64, W6=bool&lt;br /&gt;
|-&lt;br /&gt;
| 0x30 || svcGetResourceLimitLimitValue || W1=reslimit_handle, W2=[[#LimitableResource]] || W0=result, X1=value&lt;br /&gt;
|-&lt;br /&gt;
| 0x31 || svcGetResourceLimitCurrentValue || W1=reslimit_handle, W2=[[#LimitableResource]] || W0=result, X1=value&lt;br /&gt;
|-&lt;br /&gt;
| 0x32 || svcSetThreadActivity || W0=thread_handle, W1=bool || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x33 || svcGetThreadContext3 || X0=[[#ThreadContext]]*, W1=thread_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x34 || [4.0.0+] svcWaitForAddress || X0=ptr, W1=ArbitrationType, X2=? X3=timeout ||&lt;br /&gt;
|-&lt;br /&gt;
| 0x35 || [4.0.0+] svcSignalToAddress || X0=ptr, W1=SignalType, X2=? W3=? ||&lt;br /&gt;
|- style=&amp;quot;border-top: double&amp;quot;&lt;br /&gt;
| 0x3C || [[#svcDumpInfo]] || ||&lt;br /&gt;
|-&lt;br /&gt;
| 0x3D || [4.0.0+] svcDumpInfoNew || ||&lt;br /&gt;
|- style=&amp;quot;border-top: double&amp;quot;&lt;br /&gt;
| 0x40 || svcCreateSession || W2=is_light, X3=? || W0=result, W1=server_handle, W2=client_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x41 || [[#svcAcceptSession]] || W1=port_handle || W0=result, W1=session_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x42 || svcReplyAndReceiveLight || W0=light_session_handle || W0=result, W1,W2,W3,W4,W5,W6,W7=out&lt;br /&gt;
|-&lt;br /&gt;
| 0x43 || [[#svcReplyAndReceive]] || X1=ptr_handles, W2=num_handles, X3=replytarget_handle(0=none), X4=timeout || W0=result, W1=handle_idx&lt;br /&gt;
|-&lt;br /&gt;
| 0x44 || svcReplyAndReceiveWithUserBuffer|| X1=buf, X2=sz, X3=ptr_handles, W4=num_handles, X5=replytarget_handle(0=none), X6=timeout || W0=result, W1=handle_idx&lt;br /&gt;
|-&lt;br /&gt;
| 0x45 || svcCreateEvent || None || W0=result, W1=wevent_handle, W2=revent_handle&lt;br /&gt;
|- style=&amp;quot;border-top: double&amp;quot;&lt;br /&gt;
| 0x48 || [5.0.0+] [[#svcMapPhysicalMemoryUnsafe]] || X0=addr, X1=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x49 || [5.0.0+] svcUnmapPhysicalMemoryUnsafe || X0=addr, X1=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x4A || [5.0.0+] svcSetUnsafeLimit || X0=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x4B || [4.0.0+] [[#svcCreateCodeMemory]] || X1=addr, X2=size || W0=result, W1=code_memory_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x4C || [4.0.0+] [[#svcControlCodeMemory]] || W0=code_memory_handle, W1=[[#CodeMemoryOperation]], X2=dstaddr, X3=size, W4=perm || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x4D || svcSleepSystem || None || None&lt;br /&gt;
|-&lt;br /&gt;
| 0x4E || [[#svcReadWriteRegister]] || X1=reg_addr, W2=rw_mask, W3=in_val || W0=result, W1=out_val&lt;br /&gt;
|-&lt;br /&gt;
| 0x4F || svcSetProcessActivity || W0=process_handle, W1=bool || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || [[#svcCreateSharedMemory]] || W1=size, W2=myperm, W3=otherperm || W0=result, W1=shmem_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x51 || [[#svcMapTransferMemory]] || X0=tmem_handle, X1=addr, X2=size, W3=perm || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x52 || [[#svcUnmapTransferMemory]] || W0=tmemhandle, X1=addr, X2=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x53 || svcCreateInterruptEvent || X1=irq_num, W2=flag || W0=result, W1=handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || [[#svcQueryPhysicalAddress]] || X1=addr || W0=result, X1=physaddr, X2=kerneladdr, X3=size&lt;br /&gt;
|-&lt;br /&gt;
| 0x55 || [[#svcQueryIoMapping]] || X1=physaddr, X2=size || W0=result, X1=virtaddr&lt;br /&gt;
|-&lt;br /&gt;
| 0x56 || [[#svcCreateDeviceAddressSpace]] || X1=dev_as_start_addr, X2=dev_as_end_addr || W0=result, W1=dev_as_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x57 || [[#svcAttachDeviceAddressSpace]] || W0=device, X1=dev_as_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x58 || [[#svcDetachDeviceAddressSpace]] || W0=device, X1=dev_as_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x59 || [[#svcMapDeviceAddressSpaceByForce]] || W0=dev_as_handle, W1=proc_handle, X2=dev_map_addr, X3=dev_as_size, X4=dev_as_addr, W5=perm || W0=result &lt;br /&gt;
|-&lt;br /&gt;
| 0x5A || [[#svcMapDeviceAddressSpaceAligned]] || W0=dev_as_handle, W1=proc_handle, X2=dev_map_addr, X3=dev_as_size, X4=dev_as_addr, W5=perm || W0=result &lt;br /&gt;
|-&lt;br /&gt;
| 0x5B || svcMapDeviceAddressSpace || || &lt;br /&gt;
|-&lt;br /&gt;
| 0x5C || [[#svcUnmapDeviceAddressSpace]] || W0=dev_as_handle, W1=proc_handle, X2=dev_map_addr, X3=dev_as_size, X4=dev_as_addr || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x5D || svcInvalidateProcessDataCache || W0=process_handle, X1=addr, X2=size || W0=size&lt;br /&gt;
|-&lt;br /&gt;
| 0x5E || svcStoreProcessDataCache || W0=process_handle, X1=addr, X2=size || W0=size&lt;br /&gt;
|-&lt;br /&gt;
| 0x5F || svcFlushProcessDataCache || W0=process_handle, X1=addr, X2=size || W0=size&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || svcDebugActiveProcess || X1=pid || W0=result, W1=debug_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x61 || svcBreakDebugProcess || W0=debug_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x62 || svcTerminateDebugProcess || W0=debug_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x63 || svcGetDebugEvent || X0=[[#DebugEventInfo]]*, W1=debug_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x64 || svcContinueDebugEvent || W0=debug_handle, W1=[[#ContinueDebugFlags]], X2=thread_id || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x65 || svcGetProcessList || X1=pids_out_ptr, W2=max_out || W0=result, W1=num_out &lt;br /&gt;
|-&lt;br /&gt;
| 0x66 || svcGetThreadList || X1=tids_out_ptr, W2=max_out, W3=debug_handle_or_zero || W0=result, X1=num_out&lt;br /&gt;
|-&lt;br /&gt;
| 0x67 || svcGetDebugThreadContext || X0=ThreadContext*, X1=debug_handle, X2=thread_id, W3=[[#ThreadContextFlags]] || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || svcSetDebugThreadContext || W0=debug_handle, W1=[[#ThreadContextFlags]], X2=ThreadContext* || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x69 || svcQueryDebugProcessMemory || X0=[[#MemoryInfo]]*, X2=debug_handle, X3=addr || W0=result, W1=PageInfo&lt;br /&gt;
|-&lt;br /&gt;
| 0x6A || svcReadDebugProcessMemory || X0=buffer*, X1=debug_handle, X2=src_addr, X3=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x6B || svcWriteDebugProcessMemory || X0=debug_handle, X1=buffer*, X2=dst_addr, X3=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x6C || svcSetHardwareBreakPoint || W0=HardwareBreakpointId, X1=watchpoint_flags, X2=watchpoint_value/debug_handle? || &lt;br /&gt;
|-&lt;br /&gt;
| 0x6D || svcGetDebugThreadParam || X2=debug_handle, X3=thread_id, W4=[[#DebugThreadParam]] || W0=result, X1=out0, W2=out1&lt;br /&gt;
|- style=&amp;quot;border-top: double&amp;quot;&lt;br /&gt;
| 0x6F || [5.0.0+] [[#svcGetSystemInfo]] || X1=info_id, X2=handle, X3=info_sub_id || W0=result, X1=out&lt;br /&gt;
|-&lt;br /&gt;
| 0x70 || svcCreatePort || W2=max_sessions, W3=unk_bool, X4=name_ptr || W0=result, W1=clientport_handle, W2=serverport_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x71 || svcManageNamedPort || X1=name_ptr, W2=max_sessions || W0=result, W1=serverport_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x72 || svcConnectToPort || W1=clientport_handle || W0=result, W1=session_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x73 || [[#svcSetProcessMemoryPermission]] || W0=process_handle, X1=addr, X2=size, W3=perm || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x74 || [[#svcMapProcessMemory]] || X0=srcaddr, W1=process_handle, X2=dstaddr, X3=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x75 || [[#svcUnmapProcessMemory]] || W0=process_handle, X1=dstaddr, X2=srcaddr, X3=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x76 || [[#svcQueryProcessMemory]] || X0=meminfo_ptr, W2=process_handle, X3=addr || W0=result, W1=pageinfo&lt;br /&gt;
|-&lt;br /&gt;
| 0x77 || [[#svcMapProcessCodeMemory]] || W0=process_handle, X1=dstaddr, X2=srcaddr, X3=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x78 || [[#svcUnmapProcessCodeMemory]] || W0=process_handle, X1=dstaddr, X2=srcaddr, X3=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x79 || [[#svcCreateProcess]] || X1=procinfo_ptr, X2=caps_ptr, W3=cap_num ||  W0=result, W1=process_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x7A || svcStartProcess || W0=process_handle, W1=main_thread_prio, W2=default_cpuid, W3=main_thread_stacksz || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x7B || svcTerminateProcess || W0=process_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x7C || [[#svcGetProcessInfo]] || W0=process_handle || W0=result, X1=[[#ProcessState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x7D || svcCreateResourceLimit || None || W0=result, W1=reslimit_handle &lt;br /&gt;
|-&lt;br /&gt;
| 0x7E || svcSetResourceLimitLimitValue || W0=reslimit_handle, W1=[[#LimitableResource]], X2=value || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x7F || svcCallSecureMonitor || X0=smc_sub_id, X1,X2,X3,X4,X5,X6,X7=smc_args || X0,X1,X2,X3,X4,X5,X6,X7=result&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== svcSetHeapSize ==&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) X1 || u64 || OutAddr&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Set the process heap to a given Size. It can both extend and shrink the heap.&lt;br /&gt;
&lt;br /&gt;
Size must be a multiple of 0x200000.&lt;br /&gt;
&lt;br /&gt;
On success, the heap base-address (which is fixed by kernel, aslr&#039;d) is written to OutAddr.&lt;br /&gt;
&lt;br /&gt;
Uses current process pool partition.&lt;br /&gt;
&lt;br /&gt;
[2.0.0+] Size must be less than 0x18000000.&lt;br /&gt;
&lt;br /&gt;
== svcSetMemoryPermission ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || void* || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || [[#Permission]] || Prot&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Change permission of page-aligned memory region.&lt;br /&gt;
&lt;br /&gt;
Bit2 of permission (exec) is not allowed. Setting write-only is not allowed either (bit1).&lt;br /&gt;
&lt;br /&gt;
This can be used to move back and forth between ---, r-- and rw-.&lt;br /&gt;
&lt;br /&gt;
== svcSetMemoryAttribute ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || void* || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || u32 || State0&lt;br /&gt;
|-&lt;br /&gt;
| (In) W3 || u32 || State1&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Change attribute of page-aligned memory region. &lt;br /&gt;
&lt;br /&gt;
This is used to turn on/off caching for a given memory area. Useful when talking to devices such as the GPU.&lt;br /&gt;
&lt;br /&gt;
What happens &amp;quot;under the hood&amp;quot; is the &amp;quot;Memory Attribute Indirection Register&amp;quot; index is changed from 2 to 3 in the MMU descriptor.&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! State0 || State1 || Action&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 0 || Clear bit3 in [[#MemoryAttribute]].&lt;br /&gt;
|-&lt;br /&gt;
| 8 || 0 || Clear bit3 in [[#MemoryAttribute]].&lt;br /&gt;
|-&lt;br /&gt;
| 8 || 8 || Set bit3 in [[#MemoryAttribute]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== svcMapMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || void* || DstAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || void* || SrcAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Maps a memory range into a different range.&lt;br /&gt;
&lt;br /&gt;
Mainly used for adding guard pages around stack.&lt;br /&gt;
&lt;br /&gt;
Source range gets reprotected to --- (it can no longer be accessed), and bit0 is set in the source [[#MemoryAttribute]].&lt;br /&gt;
&lt;br /&gt;
If dstaddr &amp;gt;= LowerTreshold, the dst-range is enforced to be within the process&#039; &amp;quot;MapRegion&amp;quot;. Code can get the range of this region from [[#svcGetInfo]] id0=2,3.&lt;br /&gt;
&lt;br /&gt;
In this case, the mapped memory will have state 0x5C3C0B.&lt;br /&gt;
&lt;br /&gt;
As long as (dstaddr+size) &amp;lt; LowerThreshold, then you can map anywhere but the mapped memory will have state 0x482907 instead.&lt;br /&gt;
&lt;br /&gt;
LowerTreshold is 0x80000000 for 36-bit address spaces, and 0x40000000 for 32-bit ones.&lt;br /&gt;
&lt;br /&gt;
[2.0.0+] Support for the 0x482907 mappings outside the &amp;quot;MapRegion&amp;quot; were removed.&lt;br /&gt;
&lt;br /&gt;
== svcUnmapMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || void* || DstAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || void* || SrcAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Unmaps a region that was previously mapped with [[#svcMapMemory]].&lt;br /&gt;
&lt;br /&gt;
It&#039;s possible to unmap ranges partially, you don&#039;t need to unmap the entire range &amp;quot;in one go&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The srcaddr/dstaddr must match what was given when the pages were originally mapped.&lt;br /&gt;
&lt;br /&gt;
== svcQueryMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || [[#MemoryInfo]]* || MemInfo&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || void* || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || PageInfo || PageInfo&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Query information about an address. Will always fetch the lowest page-aligned mapping that contains the provided address.&lt;br /&gt;
&lt;br /&gt;
Outputs a [[#MemoryInfo]] struct.&lt;br /&gt;
&lt;br /&gt;
== svcExitProcess ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) None || || &lt;br /&gt;
|-&lt;br /&gt;
| (Out) None || ||&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Exits the current process.&lt;br /&gt;
&lt;br /&gt;
== svcCreateThread ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || void(*)(void*) || Entry&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || void* || ThreadContext&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || void* || StackTop&lt;br /&gt;
|-&lt;br /&gt;
| (In) W4 || u32 || Priority&lt;br /&gt;
|-&lt;br /&gt;
| (In) W5 || u32 || ProcessorId&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || Handle&amp;lt;Thread&amp;gt; || Handle&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Create a thread in the current process.&lt;br /&gt;
&lt;br /&gt;
Processor_id must be 0,1,2,3 or -2, where -2 uses the default cpuid for process.&lt;br /&gt;
&lt;br /&gt;
== svcStartThread ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;Thread&amp;gt; || Handle&lt;br /&gt;
|-&lt;br /&gt;
| (Out) None ||  ||&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Starts the thread for the provided handle.&lt;br /&gt;
&lt;br /&gt;
== svcExitThread ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) None || || &lt;br /&gt;
|-&lt;br /&gt;
| (Out) None || ||&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Exits the current thread.&lt;br /&gt;
&lt;br /&gt;
== svcSleepThread ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || u64 || Nano&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Sleep for a specified amount of time, or yield thread.&lt;br /&gt;
&lt;br /&gt;
Setting nano=0 means &amp;quot;yield thread&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== svcGetThreadPriority ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1|| Handle&amp;lt;Thread&amp;gt; || Handle&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || u64 || Priority&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Get priority of provided thread handle.&lt;br /&gt;
&lt;br /&gt;
== svcSetThreadPriority ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0|| Handle&amp;lt;Thread&amp;gt; || Handle&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1|| u32 || Priority&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Set priority of provided thread handle.&lt;br /&gt;
&lt;br /&gt;
Priority is a number 0-0x3F. Lower value means higher priority.&lt;br /&gt;
&lt;br /&gt;
== svcGetThreadCoreMask ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || Handle&amp;lt;Thread&amp;gt; || Handle&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || u32 || Out0&lt;br /&gt;
|-&lt;br /&gt;
| (Out) X2 || u64 || Out1&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Get affinity mask of provided thread handle.&lt;br /&gt;
&lt;br /&gt;
== svcSetThreadCoreMask ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;Thread&amp;gt; || Handle&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1 || u32 || In0&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || In1&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Set affinity mask of provided thread handle.&lt;br /&gt;
&lt;br /&gt;
== svcGetCurrentProcessorNumber ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) None || || &lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0/X0 || u64 || CpuId&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Get which cpu is executing the current thread.&lt;br /&gt;
&lt;br /&gt;
Cpu-id is an integer in the range 0-3.&lt;br /&gt;
&lt;br /&gt;
== svcMapSharedMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;SharedMemory&amp;gt; || MemHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || void* || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (In) W3 || [[#Permission]] || Permissions&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Maps the block supplied by the handle. The required permissions are different for the process that created the handle and all other processes.&lt;br /&gt;
&lt;br /&gt;
Increases reference count for the KSharedMemory object. Thus in order to release the memory associated with the object, all handles to it must be closed and all mappings must be unmapped.&lt;br /&gt;
&lt;br /&gt;
== svcCreateTransferMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || void* || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (In) W3 || [[#Permission]] || Permissions&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || Handle&amp;lt;TransferMemory&amp;gt; || Handle&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This one reprotects the src block with perms you give it. It also sets bit0 into [[#MemoryAttribute]].&lt;br /&gt;
&lt;br /&gt;
Executable bit perm not allowed.&lt;br /&gt;
&lt;br /&gt;
Closing all handles automatically causes the bit0 in [[#MemoryAttribute]] to clear, and the permission to reset.&lt;br /&gt;
&lt;br /&gt;
== svcWaitSynchronization ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || Handle* || HandlesPtr&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || u64 || HandlesNum&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || Timeout&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || u64 || HandleIndex&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Works with num_handles &amp;lt;= 0x40, error on num_handles == 0.&lt;br /&gt;
&lt;br /&gt;
Does not accept 0xFFFF8001 or 0xFFFF8000 as handles.&lt;br /&gt;
&lt;br /&gt;
=== Object types ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Port:&#039;&#039;&#039; signals when there is an incoming connection waiting to be [[#svcAcceptSession|accepted]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Session (server-side):&#039;&#039;&#039; signals when there is an incoming message waiting to be [[#svcReplyAndReceive|received]] or the pipe is closed.&lt;br /&gt;
&lt;br /&gt;
=== Result codes ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;0x0:&#039;&#039;&#039; Success. One of the objects was signalled before the timeout expired. Handle index is updated to indicate which object signalled.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;0xe401:&#039;&#039;&#039; Invalid handle. Returned when one of the handles passed is invalid. Handle index is not updated.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;0xea01:&#039;&#039;&#039; Timeout. Returned when no objects have been signalled within the timeout. Handle index is not updated.&lt;br /&gt;
&lt;br /&gt;
== svcGetSystemTick ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (Out) X0 || u64 || Ticks&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Returns the value of cntpct_el0.&lt;br /&gt;
&lt;br /&gt;
The frequency is 19200000 Hz (constant from official sw).&lt;br /&gt;
&lt;br /&gt;
Official sw reads cntpct_el0 directly from usermode without using this SVC. [[ExeFS|sdk-nso]] has this SVC, but it&#039;s not known to be called anywhere.&lt;br /&gt;
&lt;br /&gt;
== svcSendSyncRequestWithUserBuffer ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || void* || CmdPtr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || Handle&amp;lt;Session&amp;gt; || Handle&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Size must be 0x1000-aligned.&lt;br /&gt;
&lt;br /&gt;
== svcBreak ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || u64 || Break Reason&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 ||&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || Info&lt;br /&gt;
|-&lt;br /&gt;
| (Out) ? || ? || ?&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When used on retail where inx0 bit31 is clear, the system will throw a [[Error_codes|fatal-error]]. Otherwise when bit31 is set, it will return 0 and notify the debugger?&lt;br /&gt;
&lt;br /&gt;
== svcGetInfo ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || InfoId&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || Handle || Handle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || InfoSubId&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) X1 || u64 || Out&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Handle type || Id0 || Id1 || Description&lt;br /&gt;
|-&lt;br /&gt;
| Process || 0 || 0 || AllowedCpuIdBitmask&lt;br /&gt;
|-&lt;br /&gt;
| Process || 1 || 0 || AllowedThreadPrioBitmask&lt;br /&gt;
|-&lt;br /&gt;
| Process || 2 || 0 || MapRegionBaseAddr&lt;br /&gt;
|-&lt;br /&gt;
| Process || 3 || 0 || MapRegionSize&lt;br /&gt;
|-&lt;br /&gt;
| Process || 4 || 0 || HeapRegionBaseAddr&lt;br /&gt;
|-&lt;br /&gt;
| Process || 5 || 0 || HeapRegionSize&lt;br /&gt;
|-&lt;br /&gt;
| Process || 6 || 0 || TotalMemoryAvailable. Total memory available(free+used).&lt;br /&gt;
|-&lt;br /&gt;
| Process || 7 || 0 || TotalMemoryUsage. Total used size of codebin memory + main-thread stack + allocated heap.&lt;br /&gt;
|-&lt;br /&gt;
| Zero    || 8 || 0 || IsCurrentProcessBeingDebugged&lt;br /&gt;
|-&lt;br /&gt;
| Zero    || 9 || 0 || Returns ResourceLimit handle for current process. Used by [[Process_Manager_services|PM]].&lt;br /&gt;
|-&lt;br /&gt;
| Zero    || 10 || -1, {current coreid} || IdleTickCount&lt;br /&gt;
|-&lt;br /&gt;
| Zero    || 11 || 0-3 || RandomEntropy from current process. TRNG. Used to seed usermode PRNGs.&lt;br /&gt;
|-&lt;br /&gt;
| Process || 12 || 0 || [2.0.0+] AddressSpaceBaseAddr&lt;br /&gt;
|-&lt;br /&gt;
| Process || 13 || 0 || [2.0.0+] AddressSpaceSize&lt;br /&gt;
|-&lt;br /&gt;
| Process || 14 || 0 || [2.0.0+] NewMapRegionBaseAddr&lt;br /&gt;
|-&lt;br /&gt;
| Process || 15 || 0 || [2.0.0+] NewMapRegionSize&lt;br /&gt;
|-&lt;br /&gt;
| Process || 16 || 0 || [3.0.0+] PersonalMmHeapSize&lt;br /&gt;
|-&lt;br /&gt;
| Process || 17 || 0 || [3.0.0+] PersonalMmHeapUsage&lt;br /&gt;
|-&lt;br /&gt;
| Process || 18 || 0 || [3.0.0+] TitleId&lt;br /&gt;
|-&lt;br /&gt;
| Zero    || 19 || 0 || [4.0.0-4.1.0] PrivilegedProcessId_LowerBound&lt;br /&gt;
|-&lt;br /&gt;
| Zero    || 19 || 1 || [4.0.0-4.1.0] PrivilegedProcessId_UpperBound&lt;br /&gt;
|-&lt;br /&gt;
| Process || 20 || 0 || [5.0.0+] UserExceptionContextAddr&lt;br /&gt;
|-&lt;br /&gt;
| Thread  || 0xF0000002 || 0 || Performance counter related.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== svcMapPhysicalMemory ==&lt;br /&gt;
This is like svcSetHeapSize except you can allocate heap at any address you&#039;d like.&lt;br /&gt;
&lt;br /&gt;
Uses current process pool partition.&lt;br /&gt;
&lt;br /&gt;
== svcDumpInfo ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) None || || &lt;br /&gt;
|-&lt;br /&gt;
| (Out) None || ||&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Does nothing, just returns with registers set to all-zero.&lt;br /&gt;
&lt;br /&gt;
== svcAcceptSession ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1 || Handle&amp;lt;Port&amp;gt; || Port&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Result&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || Handle&amp;lt;ServerSession&amp;gt; || Session&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Result codes ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;0xf201:&#039;&#039;&#039; No session waiting to be accepted&lt;br /&gt;
&lt;br /&gt;
== svcReplyAndReceive ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1 || *Handle&amp;lt;Port or ServerSession&amp;gt; || Handles&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || u32 || NumHandles&lt;br /&gt;
|-&lt;br /&gt;
| (In) W3 || Handle&amp;lt;ServerSession&amp;gt; || ReplyTarget&lt;br /&gt;
|-&lt;br /&gt;
| (In) X4 || u64 (nanoseconds) || Timeout&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Result&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || u32 || HandleIndex&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If ReplyTarget is not zero, a reply from the TLS will be sent to that session.&lt;br /&gt;
Then it will wait until either of the passed sessions has an incoming message, is closed, a passed port has an incoming connection, or the timeout expires.&lt;br /&gt;
If there is an incoming message, it is copied to the TLS.&lt;br /&gt;
&lt;br /&gt;
After being validated, passed handles will be enumerated in order; even if a session has been closed, if one that appears earlier in the list has an incoming message, it will take priority and a result code of 0x0 will be returned.&lt;br /&gt;
&lt;br /&gt;
=== Result codes ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;0x0:&#039;&#039;&#039; Success. Either a session has an incoming message or a port has an incoming connection. HandleIndex is set appropriately.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;0xea01:&#039;&#039;&#039; Timeout. No handles were signalled before the timeout expired. HandleIndex is not updated.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;0xf601:&#039;&#039;&#039; Port remote dead. One of the sessions has been closed. HandleIndex is set appropriately.&lt;br /&gt;
&lt;br /&gt;
== svcMapPhysicalMemoryUnsafe ==&lt;br /&gt;
Same as [[#svcMapPhysicalMemory]] except it always uses pool partition 0.&lt;br /&gt;
&lt;br /&gt;
== svcCreateCodeMemory ==&lt;br /&gt;
Takes an address range with backing memory to create the code memory object.&lt;br /&gt;
&lt;br /&gt;
The memory is initially memset to 0xFF after being locked.&lt;br /&gt;
&lt;br /&gt;
== svcControlCodeMemory ==&lt;br /&gt;
Maps the backing memory for a Code memory object into the current process.&lt;br /&gt;
&lt;br /&gt;
For [[#CodeMemoryOperation|CodeMemoryOperation_MapOwner]], memory permission must be RW-.&lt;br /&gt;
&lt;br /&gt;
For [[#CodeMemoryOperation|CodeMemoryOperation_MapSlave]], memory permission must be R-- or R-X.&lt;br /&gt;
&lt;br /&gt;
Operations [[#CodeMemoryOperation|CodeMemoryOperation_UnmapOwner/CodeMemoryOperation_UnmapSlave]] unmap memory that was previously mapped this way.&lt;br /&gt;
&lt;br /&gt;
This allows one &amp;quot;secure JIT&amp;quot; process to map the code memory as RW-, and the other &amp;quot;slave&amp;quot; process to map it R-X.&lt;br /&gt;
&lt;br /&gt;
[5.0.0+] Error 0xE401 is now returned when the process owner of the Code memory object is the same as the current process.&lt;br /&gt;
&lt;br /&gt;
== svcReadWriteRegister ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || RegAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || u64 || RwMask&lt;br /&gt;
|-&lt;br /&gt;
| (In) W3 || u64 || InValue&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1|| u64 || OutValue&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Read/write IO registers with a hardcoded whitelist. Input address is physical-address and must be aligned to 4.&lt;br /&gt;
&lt;br /&gt;
rw_mask is 0 for reading and 0xffffffff for writing. You can also write individual bits by using a mask value.&lt;br /&gt;
&lt;br /&gt;
You can only write to registers inside physical pages 0x70019000 (MC), 0x7001C000 (MC0), 0x7001D000 (MC1), and they all share the same whitelist.&lt;br /&gt;
&lt;br /&gt;
The whitelist is same for writing as for reading.&lt;br /&gt;
&lt;br /&gt;
The whitelist is:&lt;br /&gt;
&lt;br /&gt;
0x054, 0x090, 0x094, 0x098, 0x09c, 0x0a0, 0x0a4, 0x0a8, 0x0ac, 0x0b0, 0x0b4, 0x0b8, 0x0bc, 0x0c0, 0x0c4, 0x0c8, 0x0d0, 0x0d4, 0x0d8, 0x0dc, 0x0e0, 0x100, 0x108, 0x10c, 0x118, 0x11c, 0x124, 0x128, 0x12c, 0x130, 0x134, 0x138, 0x13c, 0x158, 0x15c, 0x164, 0x168, 0x16c, 0x170, 0x174, 0x178, 0x17c, 0x200, 0x204, 0x2e4, 0x2e8, 0x2ec, 0x2f4, 0x2f8, 0x310, 0x314, 0x320, 0x328, 0x344, 0x348, 0x370, 0x374, 0x37c, 0x380, 0x390, 0x394, 0x398, 0x3ac, 0x3b8, 0x3bc, 0x3c0, 0x3c4, 0x3d8, 0x3e8, 0x41c, 0x420, 0x424, 0x428, 0x42c, 0x430, 0x44c, 0x47c, 0x480, 0x484, 0x50c, 0x554, 0x558, 0x55c, 0x670, 0x674, 0x690, 0x694, 0x698, 0x69c, 0x6a0, 0x6a4, 0x6c0, 0x6c4, 0x6f0, 0x6f4, 0x960, 0x970, 0x974, 0xa20, 0xa24, 0xb88, 0xb8c, 0xbc4, 0xbc8, 0xbcc, 0xbd0, 0xbd4, 0xbd8, 0xbdc, 0xbe0, 0xbe4, 0xbe8, 0xbec, 0xc00, 0xc5c, 0xcac&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[2.0.0+] Whitelist was extended with 0x4c4, 0x4c8, 0x4cc, 0x584, 0x588, 0x58c.&lt;br /&gt;
&lt;br /&gt;
[2.0.0+] The IO registers in range 0x7000E400 (PMC) size 0xC00 skip the whitelist, and do a TrustZone call using [[SMC]] Id1 0xC3000008(ReadWriteRegister).&lt;br /&gt;
&lt;br /&gt;
[4.0.0+] Access to the Memory Controller (0x70019000) also uses smcReadWriteRegister.&lt;br /&gt;
&lt;br /&gt;
Here is the whitelist imposed by that SMC, relative to the start of the PMC registers:&lt;br /&gt;
&lt;br /&gt;
0x000, 0x00c, 0x010, 0x014, 0x01c, 0x020, 0x02c, 0x030, 0x034, 0x038, 0x03c, 0x040, 0x044, 0x048, 0x0dc, 0x0e0, 0x0e4, 0x160, 0x164, 0x168, 0x170, 0x1a8, 0x1b8, 0x1bc, 0x1c0, 0x1c4, 0x1c8, 0x2b4, 0x2d4, 0x440, 0x4d8&lt;br /&gt;
&lt;br /&gt;
Here is the whitelist imposed by smcReadWriteRegister (checked in addition to the whitelist in svcReadWriteRegister), relative to the start of the MC registers:&lt;br /&gt;
&lt;br /&gt;
0x000, 0x004, 0x008, 0x00C, 0x010, 0x01C, 0x020, 0x030, 0x034, 0x050, 0x054, 0x090, 0x094, 0x098, 0x09C, 0x0A0, 0x0A4, 0x0A8, 0x0AC, 0x0B0, 0x0B4, 0x0B8, 0x0BC, 0x0C0, 0x0C4, 0x0C8, 0x0D0, 0x0D4, 0x0D8, 0x0DC, 0x0E0, 0x100, 0x108, 0x10C, 0x118, 0x11C, 0x124, 0x128, 0x12C, 0x130, 0x134, 0x138, 0x13C, 0x158, 0x15C, 0x164, 0x168, 0x16C, 0x170, 0x174, 0x178, 0x17C, 0x200, 0x204, 0x238, 0x240, 0x244, 0x250, 0x254, 0x258, 0x264, 0x268, 0x26C, 0x270, 0x274, 0x280, 0x284, 0x288, 0x28C, 0x294, 0x2E4, 0x2E8, 0x2EC, 0x2F4, 0x2F8, 0x310, 0x314, 0x320, 0x328, 0x344, 0x348, 0x370, 0x374, 0x37C, 0x380, 0x390, 0x394, 0x398, 0x3AC, 0x3B8, 0x3BC, 0x3C0, 0x3C4, 0x3D8, 0x3E8, 0x41C, 0x420, 0x424, 0x428, 0x42C, 0x430, 0x44C, 0x47C, 0x480, 0x484, 0x4C4, 0x4C8, 0x4CC, 0x50C, 0x554, 0x558, 0x55C, 0x584, 0x588, 0x58C, 0x670, 0x674, 0x690, 0x694, 0x698, 0x69C, 0x6A0, 0x6A4, 0x6C0, 0x6C4, 0x6F0, 0x6F4, 0x960, 0x970, 0x974, 0x9B8, 0xA20, 0xA24, 0xA88, 0xA94, 0xA98, 0xA9C, 0xAA0, 0xAA4, 0xAA8, 0xAAC, 0xAB0, 0xAB4, 0xAB8, 0xABC, 0xAC0, 0xAC4, 0xAC8, 0xACC, 0xAD0, 0xAD4, 0xAD8, 0xADC, 0xAE0, 0xB88, 0xB8C, 0xBC4, 0xBC8, 0xBCC, 0xBD0, 0xBD4, 0xBD8, 0xBDC, 0xBE0, 0xBE4, 0xBE8, 0xBEC, 0xC00, 0xC5C, 0xCAC&lt;br /&gt;
&lt;br /&gt;
== svcCreateSharedMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || [[#Permission]] || LocalPerm&lt;br /&gt;
|-&lt;br /&gt;
| (In) W3 || [[#Permission]] || RemotePerm&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || Handle&amp;lt;SharedMemory&amp;gt; || MemHandle&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other perm can be used to enforce permission 1, 3, or 0x10000000 if don&#039;t care.&lt;br /&gt;
&lt;br /&gt;
Allocates memory from the current process&#039; pool partition.&lt;br /&gt;
&lt;br /&gt;
== svcMapTransferMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || Handle&amp;lt;TransferMemory&amp;gt; || MemHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || void* || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (In) W3 || [[#Permission]] || Permissions&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The newly mapped pages will have [[#MemoryState]] type 0xE.&lt;br /&gt;
&lt;br /&gt;
You must pass same size and permissions as given in svcCreateMemoryMirror, otherwise error.&lt;br /&gt;
&lt;br /&gt;
== svcUnmapTransferMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || Handle&amp;lt;TransferMemory&amp;gt; || MemHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || void* || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Size must match size given in map syscall, otherwise there&#039;s an invalid-size error.&lt;br /&gt;
&lt;br /&gt;
== svcQueryPhysicalAddress ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]]|| Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) X1 || u64 || PhysAddr&lt;br /&gt;
|-&lt;br /&gt;
| (Out) X2 || u64 || KernelAddr&lt;br /&gt;
|-&lt;br /&gt;
| (Out) X3 || u64 || Size&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== svcQueryIoMapping ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || PhysAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) X1 || void* || VirtAddr&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Returns a virtual address mapped to a given IO range.&lt;br /&gt;
&lt;br /&gt;
== svcCreateDeviceAddressSpace ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || StartAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || EndAddr&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || Handle&amp;lt;DeviceAddressSpace&amp;gt; || AddressSpaceHandle&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Creates a virtual address space for binding device address spaces and returns a handle.&lt;br /&gt;
&lt;br /&gt;
dev_as_start_addr is normally set to 0 and dev_as_end_addr is normally set to 0xFFFFFFFF.&lt;br /&gt;
&lt;br /&gt;
== svcAttachDeviceAddressSpace ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || [[#DeviceName]] || DeviceId&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || Handle&amp;lt;DeviceAddressSpace&amp;gt; || DeviceAsHandle&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Attaches a device address space to a [[#DeviceName|device]].&lt;br /&gt;
&lt;br /&gt;
== svcDetachDeviceAddressSpace ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || [[#DeviceName]] || DeviceId&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || Handle&amp;lt;DeviceAddressSpace&amp;gt; || DeviceAsHandle&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Detaches a device address space from a [[#DeviceName|device]].&lt;br /&gt;
&lt;br /&gt;
== svcMapDeviceAddressSpaceByForce ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;DeviceAddressSpace&amp;gt; || DeviceAsHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || void* || SrcAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || DeviceAsSize&lt;br /&gt;
|-&lt;br /&gt;
| (In) X4 || u64 || DeviceAsAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) W5 || [[#Permission]] || Permissions&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Maps an attached device address space to an userspace address.&lt;br /&gt;
&lt;br /&gt;
dev_map_addr is the userspace destination address, while dev_as_addr is the source address between dev_as_start_addr and dev_as_end_addr (passed to [[#svcCreateDeviceAddressSpace]]).&lt;br /&gt;
&lt;br /&gt;
The userspace destination address must have the [[SVC#MemoryState|MapDeviceAllowed]] bit set. Bit [[SVC#MemoryAttribute|IsDeviceMapped]] will be set after mapping.&lt;br /&gt;
&lt;br /&gt;
== svcMapDeviceAddressSpaceAligned ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;DeviceAddressSpace&amp;gt; || DeviceAsHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || void* || SrcAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || DeviceAsSize&lt;br /&gt;
|-&lt;br /&gt;
| (In) X4 || u64 || DeviceAsAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) W5 || [[#Permission]] || Permissions&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Maps an attached device address space to an userspace address.&lt;br /&gt;
&lt;br /&gt;
Same as [[#svcMapDeviceAddressSpaceByForce]], but the userspace destination address must have the [[SVC#MemoryState|MapDeviceAlignedAllowed]] bit set instead.&lt;br /&gt;
&lt;br /&gt;
== svcUnmapDeviceAddressSpace ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;DeviceAddressSpace&amp;gt; || DeviceAsHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || void* || SrcAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || DeviceAsSize&lt;br /&gt;
|-&lt;br /&gt;
| (In) X4 || u64 || DeviceAsAddr&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Unmaps an attached device address space from an userspace address.&lt;br /&gt;
&lt;br /&gt;
== svcGetSystemInfo ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || InfoId&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || Handle || Handle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || InfoSubId&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) X1 || u64 || Out&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Handle type || Id0 || Id1 || Description&lt;br /&gt;
|-&lt;br /&gt;
| Zero    || 0 || 0 || TotalMemorySize_Application&lt;br /&gt;
|-&lt;br /&gt;
| Zero    || 0 || 1 || TotalMemorySize_Applet&lt;br /&gt;
|-&lt;br /&gt;
| Zero    || 0 || 2 || TotalMemorySize_System&lt;br /&gt;
|-&lt;br /&gt;
| Zero    || 0 || 3 || TotalMemorySize_SystemUnsafe&lt;br /&gt;
|-&lt;br /&gt;
| Zero    || 1 || 0 || CurrentMemorySize_Application&lt;br /&gt;
|-&lt;br /&gt;
| Zero    || 1 || 1 || CurrentMemorySize_Applet&lt;br /&gt;
|-&lt;br /&gt;
| Zero    || 1 || 2 || CurrentMemorySize_System&lt;br /&gt;
|-&lt;br /&gt;
| Zero    || 1 || 3 || CurrentMemorySize_SystemUnsafe&lt;br /&gt;
|-&lt;br /&gt;
| Zero    || 2 || 0 || PrivilegedProcessId_LowerBound&lt;br /&gt;
|-&lt;br /&gt;
| Zero    || 2 || 1 || PrivilegedProcessId_UpperBound&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== svcSetProcessMemoryPermission ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (In) W3 || void* || Perm&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This sets the memory permissions for the specified memory with the supplied process handle.&lt;br /&gt;
&lt;br /&gt;
This throws an error(0xD801) when the input perm is &amp;gt;0x5, hence -WX and RWX are not allowed.&lt;br /&gt;
&lt;br /&gt;
== svcMapProcessMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || u64 || DstAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || void* || SrcAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Maps the src address from the supplied process handle into the current process.&lt;br /&gt;
&lt;br /&gt;
This allows mapping code and rodata with RW- permission.&lt;br /&gt;
&lt;br /&gt;
== svcUnmapProcessMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || void* || DstAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || SrcAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Unmaps what was mapped by [[#svcMapProcessMemory]].&lt;br /&gt;
&lt;br /&gt;
== svcQueryProcessMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || [[#MemoryInfo]]* || MemInfoPtr&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || PageInfo || PageInfo&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Equivalent to [[#svcQueryMemory]] except takes a process handle.&lt;br /&gt;
&lt;br /&gt;
== svcMapProcessCodeMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || DstAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || SrcAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Takes a process handle, and maps normal heap in that process as executable code in that process. Used when loading NROs. This does not support using the current-process handle alias.&lt;br /&gt;
&lt;br /&gt;
== svcUnmapProcessCodeMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || DstAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || SrcAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Unmaps what was mapped by [[#svcMapProcessCodeMemory]].&lt;br /&gt;
&lt;br /&gt;
== svcCreateProcess ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || [[#CreateProcessInfo]]* || InfoPtr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || CapabilitiesPtr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || CapabilitiesNum&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Takes a [[#CreateProcessInfo]] as input.&lt;br /&gt;
&lt;br /&gt;
== svcGetProcessInfo ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || [[#ProcessState]] || State&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Returns an enum with value 0-7.&lt;br /&gt;
&lt;br /&gt;
== Debugging ==&lt;br /&gt;
[2.0.0+] Exactly 6 debug SVCs require that [[SPL_services#GetConfig|IsDebugMode]] is non-zero. Error 0x4201 is returned otherwise.&lt;br /&gt;
* svcBreakDebugProcess&lt;br /&gt;
* svcContinueDebugEvent&lt;br /&gt;
* svcWriteDebugProcessMemory&lt;br /&gt;
* svcSetDebugThreadContext&lt;br /&gt;
* svcTerminateDebugProcess&lt;br /&gt;
* svcSetHardwareBreakPoint&lt;br /&gt;
&lt;br /&gt;
svcDebugActiveProcess stops execution of the target process, the normal method for resuming it requires svcContinueDebugEvent(see above). Closing the debug handle also results in execution being resumed.&lt;br /&gt;
&lt;br /&gt;
= Enum/Structures =&lt;br /&gt;
== ThreadContextRequestFlags ==&lt;br /&gt;
Bitfield of one of more of these:&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Bit || Bitmask || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 1 || NormalContext&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 4 ||&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 8 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== DeviceName ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || DeviceName_AFI&lt;br /&gt;
|-&lt;br /&gt;
| 1 || DeviceName_AVPC&lt;br /&gt;
|-&lt;br /&gt;
| 2 || DeviceName_DC&lt;br /&gt;
|-&lt;br /&gt;
| 3 || DeviceName_DCB&lt;br /&gt;
|-&lt;br /&gt;
| 4 || DeviceName_HC&lt;br /&gt;
|-&lt;br /&gt;
| 5 || DeviceName_HDA&lt;br /&gt;
|-&lt;br /&gt;
| 6 || DeviceName_ISP2&lt;br /&gt;
|-&lt;br /&gt;
| 7 || DeviceName_MSENCNVENC&lt;br /&gt;
|-&lt;br /&gt;
| 8 || DeviceName_NV&lt;br /&gt;
|-&lt;br /&gt;
| 9 || DeviceName_NV2&lt;br /&gt;
|-&lt;br /&gt;
| 10 || DeviceName_PPCS&lt;br /&gt;
|-&lt;br /&gt;
| 11 || DeviceName_SATA&lt;br /&gt;
|-&lt;br /&gt;
| 12 || DeviceName_VI&lt;br /&gt;
|-&lt;br /&gt;
| 13 || DeviceName_VIC&lt;br /&gt;
|-&lt;br /&gt;
| 14 || DeviceName_XUSB_HOST&lt;br /&gt;
|-&lt;br /&gt;
| 15 || DeviceName_XUSB_DEV&lt;br /&gt;
|-&lt;br /&gt;
| 16 || DeviceName_TSEC&lt;br /&gt;
|-&lt;br /&gt;
| 17 || DeviceName_PPCS1&lt;br /&gt;
|-&lt;br /&gt;
| 18 || DeviceName_DC1&lt;br /&gt;
|-&lt;br /&gt;
| 19 || DeviceName_SDMMC1A&lt;br /&gt;
|-&lt;br /&gt;
| 20 || DeviceName_SDMMC2A&lt;br /&gt;
|-&lt;br /&gt;
| 21 || DeviceName_SDMMC3A&lt;br /&gt;
|-&lt;br /&gt;
| 22 || DeviceName_SDMMC4A&lt;br /&gt;
|-&lt;br /&gt;
| 23 || DeviceName_ISP2B&lt;br /&gt;
|-&lt;br /&gt;
| 24 || DeviceName_GPU&lt;br /&gt;
|-&lt;br /&gt;
| 25 || DeviceName_GPUB&lt;br /&gt;
|-&lt;br /&gt;
| 26 || DeviceName_PPCS2&lt;br /&gt;
|-&lt;br /&gt;
| 27 || DeviceName_NVDEC&lt;br /&gt;
|-&lt;br /&gt;
| 28 || DeviceName_APE&lt;br /&gt;
|-&lt;br /&gt;
| 29 || DeviceName_SE&lt;br /&gt;
|-&lt;br /&gt;
| 30 || DeviceName_NVJPG&lt;br /&gt;
|-&lt;br /&gt;
| 31 || DeviceName_HC1&lt;br /&gt;
|-&lt;br /&gt;
| 32 || DeviceName_SE1&lt;br /&gt;
|-&lt;br /&gt;
| 33 || DeviceName_AXIAP&lt;br /&gt;
|-&lt;br /&gt;
| 34 || DeviceName_ETR&lt;br /&gt;
|-&lt;br /&gt;
| 35 || DeviceName_TSECB&lt;br /&gt;
|-&lt;br /&gt;
| 36 || DeviceName_TSEC1&lt;br /&gt;
|-&lt;br /&gt;
| 37 || DeviceName_TSECB1&lt;br /&gt;
|-&lt;br /&gt;
| 38 || DeviceName_NVDEC1&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CodeMemoryOperation ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || CodeMemoryOperation_MapOwner&lt;br /&gt;
|-&lt;br /&gt;
| 1 || CodeMemoryOperation_MapSlave&lt;br /&gt;
|-&lt;br /&gt;
| 2 || CodeMemoryOperation_UnmapOwner&lt;br /&gt;
|-&lt;br /&gt;
| 3 || CodeMemoryOperation_UnmapSlave&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LimitableResource ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || LimitableResource_Memory&lt;br /&gt;
|-&lt;br /&gt;
| 1 || LimitableResource_Threads&lt;br /&gt;
|-&lt;br /&gt;
| 2 || LimitableResource_Events&lt;br /&gt;
|-&lt;br /&gt;
| 3 || LimitableResource_TransferMemories&lt;br /&gt;
|-&lt;br /&gt;
| 4 || LimitableResource_Sessions&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== ProcessEvent ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Name || Notes&lt;br /&gt;
|-&lt;br /&gt;
| 0 || ProcessEvent_Created ||&lt;br /&gt;
|-&lt;br /&gt;
| 1 || ProcessEvent_DebugAttached ||&lt;br /&gt;
|-&lt;br /&gt;
| 2 || ProcessEvent_DebugDetached ||&lt;br /&gt;
|-&lt;br /&gt;
| 3 || ProcessEvent_Crashed || Processes will not enter this state unless they were created with [[#CreateProcessInfo|EnableDebug]].&lt;br /&gt;
|-&lt;br /&gt;
| 4 || ProcessEvent_Running ||&lt;br /&gt;
|-&lt;br /&gt;
| 5 || ProcessEvent_Exiting ||&lt;br /&gt;
|-&lt;br /&gt;
| 6 || ProcessEvent_Exited ||&lt;br /&gt;
|-&lt;br /&gt;
| 7 || ProcessEvent_DebugSuspended ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== DebugThreadParam ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || DebugThreadParam_ActualPriority&lt;br /&gt;
|-&lt;br /&gt;
| 1 ||&lt;br /&gt;
|-&lt;br /&gt;
| 2 || DebugThreadParam_CpuCore&lt;br /&gt;
|-&lt;br /&gt;
| 3 ||&lt;br /&gt;
|-&lt;br /&gt;
| 4 || DebugThreadParam_CoreMask&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateProcessInfo ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Bits || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 12 || || ProcessName (doesn&#039;t have to be null-terminated)&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 4 || || ProcessCategory (0: regular title, 1: kernel built-in)&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 8 || || TitleId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 8 || || CodeAddr&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 4 || || CodeNumPages&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 4 || || MmuFlags&lt;br /&gt;
|-&lt;br /&gt;
| || || Bit0 || IsAarch64&lt;br /&gt;
|-&lt;br /&gt;
| || || Bit3-1 || [[#AddressSpaceType]]&lt;br /&gt;
|-&lt;br /&gt;
| || || Bit4 || [2.0.0+] EnableDebug&lt;br /&gt;
|-&lt;br /&gt;
| || || Bit5 || EnableAslr&lt;br /&gt;
|-&lt;br /&gt;
| || || Bit6 || UseSystemMemBlocks&lt;br /&gt;
|-&lt;br /&gt;
| || || Bit7 || [4.0.0] ?&lt;br /&gt;
|-&lt;br /&gt;
| || || Bit10-7 || [5.0.0+] PoolPartition (0=Application, 1=Applet, 2=Sysmodule, 3=Nvservices)&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 4 || || ResourceLimitHandle&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C || 4 || || [3.0.0+] PersonalMmHeapNumPages&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
On [1.0.0] there&#039;s only one pool.&lt;br /&gt;
&lt;br /&gt;
On [2.0.0-4.0.0] PoolPartition is 1 for built-ins and 0 for rest.&lt;br /&gt;
&lt;br /&gt;
On [5.0.0] PoolPartition is specified in CreateProcessArgs. There are now 4 pool partitions.&lt;br /&gt;
&lt;br /&gt;
=== AddressSpaceType ===&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Type || Name || Width || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Normal_32Bit || 32 ||&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Normal_36Bit || 36 ||&lt;br /&gt;
|-&lt;br /&gt;
| 2 || WithoutMap_32Bit || 32 || Appears to be missing map region [?]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [2.0.0+] Normal_39Bit || 39 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== MemoryInfo ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 8 || BaseAddress&lt;br /&gt;
|-&lt;br /&gt;
| 8 || 8 || Size&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 4 || MemoryType: lower 8 bits of [[#MemoryState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x14 || 4 || [[#MemoryAttribute]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 4 || Permission (bit0: R, bit1: W, bit2: X)&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 4 || IpcRefCount&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 4 || DeviceRefCount&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 4 || Padding: always zero&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== MemoryAttribute ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Bits || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || IsBorrowed&lt;br /&gt;
|-&lt;br /&gt;
| 1 || IsIpcMapped: when IpcRefCount &amp;gt; 0.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || IsDeviceMapped: when DeviceRefCount &amp;gt; 0.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || IsUncached&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== MemoryState ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Bits || Description&lt;br /&gt;
|-&lt;br /&gt;
| 7-0 || Type&lt;br /&gt;
|-&lt;br /&gt;
| 8 || [[#svcSetMemoryPermission|PermissionChangeAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 9 || ForceReadWritableByDebugSyscalls&lt;br /&gt;
|-&lt;br /&gt;
| 10 || IpcSendAllowed_Type0&lt;br /&gt;
|-&lt;br /&gt;
| 11 || IpcSendAllowed_Type3&lt;br /&gt;
|-&lt;br /&gt;
| 12 || IpcSendAllowed_Type1&lt;br /&gt;
|-&lt;br /&gt;
| 14 || [[#svcSetProcessMemoryPermission|ProcessPermissionChangeAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 15 || [[#svcMapMemory|MapAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 16 || [[#svcUnmapProcessCodeMemory|UnmapProcessCodeMemoryAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 17 || [[#svcCreateTransferMemory|TransferMemoryAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 18 || [[#svcQueryPhysicalAddress|QueryPhysicalAddressAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 19 || MapDeviceAllowed ([[#svcMapDeviceAddressSpace]] and [[#svcMapDeviceAddressSpaceByForce]])&lt;br /&gt;
|-&lt;br /&gt;
| 20 || [[#svcMapDeviceAddressSpaceAligned|MapDeviceAlignedAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 21 || [[#svcSendSyncRequestWithUserBuffer|IpcBufferAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 22 || IsPoolAllocated/IsReferenceCounted&lt;br /&gt;
|-&lt;br /&gt;
| 23 || [[#svcMapProcessMemory|MapProcessAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 24 || [[#svcSetMemoryAttribute|AttributeChangeAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 25 || [4.0.0+] CodeMemoryAllowed&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Type || Meaning&lt;br /&gt;
|-&lt;br /&gt;
| 0x00000000 || MemoryType_Unmapped ||&lt;br /&gt;
|-&lt;br /&gt;
| 0x00002001 || MemoryType_Io || Mapped by kernel capability parsing in [[#svcCreateProcess]]. &lt;br /&gt;
|-&lt;br /&gt;
| 0x00042002 || MemoryType_Normal || Mapped by kernel capability parsing in [[#svcCreateProcess]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x00DC7E03 || MemoryType_CodeStatic || Mapped during [[#svcCreateProcess]].&lt;br /&gt;
|-&lt;br /&gt;
| [1.0.0+]&lt;br /&gt;
&lt;br /&gt;
0x01FEBD04&lt;br /&gt;
&lt;br /&gt;
[4.0.0+]&lt;br /&gt;
&lt;br /&gt;
0x03FEBD04&lt;br /&gt;
|| MemoryType_CodeMutable || Transition from 0xDC7E03 performed by [[#svcSetProcessMemoryPermission]].&lt;br /&gt;
|-&lt;br /&gt;
| [1.0.0+]&lt;br /&gt;
0x017EBD05&lt;br /&gt;
&lt;br /&gt;
[4.0.0+]&lt;br /&gt;
&lt;br /&gt;
0x037EBD05&lt;br /&gt;
|| MemoryType_Heap || Mapped using [[#svcSetHeapSize]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x00402006 || MemoryType_SharedMemory || Mapped using [[#svcMapSharedMemory]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x00482907 || [1.0.0] MemoryType_WeirdMappedMemory || Mapped using [[#svcMapMemory]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x00DD7E08 || MemoryType_ModuleCodeStatic || Mapped using [[#svcMapProcessCodeMemory]].&lt;br /&gt;
|-&lt;br /&gt;
| [1.0.0+]&lt;br /&gt;
&lt;br /&gt;
0x01FFBD09&lt;br /&gt;
&lt;br /&gt;
[4.0.0+]&lt;br /&gt;
&lt;br /&gt;
0x03FFBD09&lt;br /&gt;
|| MemoryType_ModuleCodeMutable || Transition from 0xDD7E08 performed by [[#svcSetProcessMemoryPermission]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x005C3C0A || [[IPC_Marshalling|MemoryType_IpcBuffer0]] || IPC buffers with descriptor flags=0.&lt;br /&gt;
|-&lt;br /&gt;
| 0x005C3C0B || MemoryType_MappedMemory || Mapped using [[#svcMapMemory]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x0040200C || [[Thread Local Storage|MemoryType_ThreadLocal]] || Mapped during [[#svcCreateThread]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x015C3C0D || MemoryType_TransferMemoryIsolated || Mapped using [[#svcMapTransferMemory]] when the owning process has perm=0.&lt;br /&gt;
|-&lt;br /&gt;
| 0x005C380E || MemoryType_TransferMemory || Mapped using [[#svcMapTransferMemory]] when the owning process has perm!=0.&lt;br /&gt;
|-&lt;br /&gt;
| 0x0040380F || MemoryType_ProcessMemory || Mapped using [[#svcMapProcessMemory]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x00000010 || MemoryType_Reserved ||&lt;br /&gt;
|-&lt;br /&gt;
| 0x005C3811 || [[IPC_Marshalling|MemoryType_IpcBuffer1]] || IPC buffers with descriptor flags=1.&lt;br /&gt;
|-&lt;br /&gt;
| 0x004C2812 || [[IPC_Marshalling|MemoryType_IpcBuffer3]] || IPC buffers with descriptor flags=3.&lt;br /&gt;
|-&lt;br /&gt;
| 0x00002013 || MemoryType_KernelStack || Mapped in kernel during [[#svcCreateThread]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x00402214 || [4.0.0+] MemoryType_CodeReadOnly || Mapped in kernel during [[#svcControlCodeMemory]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x00402015 || [4.0.0+] MemoryType_CodeWritable || Mapped in kernel during [[#svcControlCodeMemory]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== ContinueDebugFlags ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Bit || Bitmask || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 1 || CancelSynchronization (only if ResumeAllThreads is set; cancels with error 0x6C01)&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 2 || SwallowException&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 4 || ResumeAllThreads&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== DebugEventInfo ==&lt;br /&gt;
&lt;br /&gt;
Size: 0x40&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || u32 || EventType&lt;br /&gt;
|-&lt;br /&gt;
| 4 || u32 || Flags (bit0: NeedsContinue)&lt;br /&gt;
|-&lt;br /&gt;
| 8 || u64 || ThreadId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || || PerTypeSpecifics&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
AttachProcess specific:&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || u64 || TitleId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || u64 || ProcessId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || char[12] || ProcessName&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C || u32 || MmuFlags&lt;br /&gt;
|-&lt;br /&gt;
| 0x30 || u64 || [5.0.0+] UserExceptionContextAddr&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
AttachThread specific:&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || u64 || ThreadId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || u64 || TlsPtr&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || u64 || Entrypoint&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Exit specific:&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || u64 || Type (0=PausedThread, 1=RunningThread, 2=TerminatedProcess)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Exception specific:&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || u64 || ExceptionType&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || u64 || FaultRegister&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || || PerExceptionSpecifics&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== DebugEventType ===&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || DebugEvent_AttachProcess&lt;br /&gt;
|-&lt;br /&gt;
| 1 || DebugEvent_AttachThread&lt;br /&gt;
|-&lt;br /&gt;
| 2 ||&lt;br /&gt;
|-&lt;br /&gt;
| 3 || DebugEvent_Exit&lt;br /&gt;
|-&lt;br /&gt;
| 4 || DebugEvent_Exception&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== DebugExceptionType ===&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Exception_UndefinedInstruction&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Exception_InstructionAbort&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Exception_DataAbortMisc&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Exception_PcSpAlignmentFault&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Exception_DebuggerAttached&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Exception_BreakPoint&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Exception_UserBreak&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Exception_DebuggerBreak&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Exception_BadSvcId&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
UndefinedInstruction specifics:&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || u32 || Opcode&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
BreakPoint specifics:&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || u32 || IsWatchpoint&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
UserBreak specifics:&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || u32 || Info0&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || u64 || Info1&lt;br /&gt;
|-&lt;br /&gt;
| 0x30 || u64 || Info2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
BadSvcId specifics:&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || u32 || SvcId&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Exception handling =&lt;br /&gt;
There is userland code for handling exceptions, however this doesn&#039;t seem to be executed on retail mode.&lt;br /&gt;
&lt;br /&gt;
When a usermode exception occurs, it jumps to the main code binary entrypoint (main_binary_address + 0 == &#039;&#039;&#039;_start&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
During normal boot &#039;&#039;&#039;_start&#039;&#039;&#039; is invoked with X0=0 and X1=main_thread_handle (triggering normal crt0 setup).&lt;br /&gt;
During an usermode exception &#039;&#039;&#039;_start&#039;&#039;&#039; is invoked with X0=exception_info0_ptr and X1=exception_info1_ptr instead.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;_start&#039;&#039;&#039; method determines whether to boot normally or handle an exception if X0 is set to 0 or not.&lt;/div&gt;</summary>
		<author><name>Gdkchan</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=SVC&amp;diff=4418</id>
		<title>SVC</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=SVC&amp;diff=4418"/>
		<updated>2018-04-04T17:10:19Z</updated>

		<summary type="html">&lt;p&gt;Gdkchan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&lt;br /&gt;
= System calls =&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Id || Name || In || Out&lt;br /&gt;
|-&lt;br /&gt;
|  0x1 || [[#svcSetHeapSize]] || W1=size || W0=result, X1=outaddr&lt;br /&gt;
|-&lt;br /&gt;
|  0x2 || [[#svcSetMemoryPermission]] || X0=addr, X1=size, W2=prot || W0=result&lt;br /&gt;
|-&lt;br /&gt;
|  0x3 || [[#svcSetMemoryAttribute]] || X0=addr, X1=size, W2=state0, W3=state1 || W0=result&lt;br /&gt;
|-&lt;br /&gt;
|  0x4 || [[#svcMapMemory]] || X0=dstaddr, X1=srcaddr, X2=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
|  0x5 || [[#svcUnmapMemory]] || X0=dstaddr, X1=srcaddr, X2=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
|  0x6 || [[#svcQueryMemory]] || X0=MemoryInfo*, X2=addr || W0=result, W1=PageInfo                                                         &lt;br /&gt;
|-&lt;br /&gt;
|  0x7 || [[#svcExitProcess]] || None ||&lt;br /&gt;
|-&lt;br /&gt;
|  0x8 || [[#svcCreateThread]] || X1=entry, X2=thread_context, X3=stacktop, W4=prio, W5=processor_id  || W0=result, W1=handle&lt;br /&gt;
|-&lt;br /&gt;
|  0x9 || [[#svcStartThread]] || W0=thread_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
|  0xA || [[#svcExitThread]] || None ||                                                         &lt;br /&gt;
|-&lt;br /&gt;
|  0xB || [[#svcSleepThread]] || X0=nano || W0=result&lt;br /&gt;
|-&lt;br /&gt;
|  0xC || [[#svcGetThreadPriority]] || W1=thread_handle || W0=result, W1=prio&lt;br /&gt;
|-&lt;br /&gt;
|  0xD || [[#svcSetThreadPriority]] || W0=thread_handle, W1=prio || W0=result&lt;br /&gt;
|-&lt;br /&gt;
|  0xE || [[#svcGetThreadCoreMask]] || W2=thread_handle || W0=result, W1=out, X2=out&lt;br /&gt;
|-&lt;br /&gt;
|  0xF || [[#svcSetThreadCoreMask]] || W0=thread_handle, W1=in, X2=in2 || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#svcGetCurrentProcessorNumber]] || None || W0/X0=cpuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || svcSignalEvent || W0=wevent_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || svcClearEvent || W0=wevent_or_revent_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x13 || [[#svcMapSharedMemory]] || W0=shmem_handle, X1=addr, X2=size, W3=perm || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x14 || svcUnmapSharedMemory || W0=shmem_handle, X1=addr, X2=size || W0=result                                                 &lt;br /&gt;
|-&lt;br /&gt;
| 0x15 || [[#svcCreateTransferMemory]] || X1=addr, X2=size, W3=perm || W0=result, W1=tmem_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x16 || svcCloseHandle || W0=handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x17 || svcResetSignal || W0=revent_or_process_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || [[#svcWaitSynchronization]] || X1=handles_ptr, W2=num_handles. X3=timeout || W0=result, W1=handle_idx&lt;br /&gt;
|-&lt;br /&gt;
| 0x19 || svcCancelSynchronization || W0=thread_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A || svcArbitrateLock || W0=cur_thread_handle, X1=ptr, W2=req_thread_handle ||                                     &lt;br /&gt;
|-&lt;br /&gt;
| 0x1B || svcArbitrateUnlock || X0=ptr ||&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || svcWaitProcessWideKeyAtomic || X0=ptr0, X1=ptr, W2=thread_handle, X3=timeout || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x1D || svcSignalProcessWideKey || X0=ptr, W1=value || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x1E || [[#svcGetSystemTick]] || None || X0={value of cntpct_el0}&lt;br /&gt;
|-&lt;br /&gt;
| 0x1F || svcConnectToNamedPort || X1=port_name_str || W0=result, W1=handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || svcSendSyncRequestLight || W0=light_session_handle, X1=? || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x21 || svcSendSyncRequest || X0=normal_session_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x22 || [[#svcSendSyncRequestWithUserBuffer]] || X0=cmdbufptr, X1=size, X2=handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x23 || svcSendAsyncRequestWithUserBuffer || X1=cmdbufptr, X2=size, X3=handle || W0=result, W1=event_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || svcGetProcessId || W1=thread_or_process_or_debug_handle || W0=result, X1=pid&lt;br /&gt;
|-&lt;br /&gt;
| 0x25 || svcGetThreadId || W1=thread_handle || W0=result, X1=out&lt;br /&gt;
|-&lt;br /&gt;
| 0x26 || [[#svcBreak]] || X0=break_reason,X1,X2=info || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x27 || svcOutputDebugString || X0=str, X1=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || svcReturnFromException || X0=result || &lt;br /&gt;
|-&lt;br /&gt;
| 0x29 || [[#svcGetInfo]] || X1=info_id, X2=handle, X3=info_sub_id || W0=result, X1=out&lt;br /&gt;
|-&lt;br /&gt;
| 0x2A || svcFlushEntireDataCache || None || None&lt;br /&gt;
|-&lt;br /&gt;
| 0x2B || svcFlushDataCache || X0=addr, X1=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C || [3.0.0+] [[#svcMapPhysicalMemory]] || X0=addr, X1=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x2D || [3.0.0+] svcUnmapPhysicalMemory || X0=addr, X1=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x2E || [5.0.0+] svcGetNextThreadInfo || X3=timeout || W0=result, bunch of crap&lt;br /&gt;
|-&lt;br /&gt;
| 0x2F || svcGetLastThreadInfo || None || W0=result, W1,W2,W3,W4=unk, W5=truncated_u64, W6=bool&lt;br /&gt;
|-&lt;br /&gt;
| 0x30 || svcGetResourceLimitLimitValue || W1=reslimit_handle, W2=[[#LimitableResource]] || W0=result, X1=value&lt;br /&gt;
|-&lt;br /&gt;
| 0x31 || svcGetResourceLimitCurrentValue || W1=reslimit_handle, W2=[[#LimitableResource]] || W0=result, X1=value&lt;br /&gt;
|-&lt;br /&gt;
| 0x32 || svcSetThreadActivity || W0=thread_handle, W1=bool || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x33 || svcGetThreadContext3 || W0=thread_handle, W1=[[#ThreadContext]]* || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x34 || [4.0.0+] svcWaitForAddress || X0=ptr, W1=ArbitrationType, X2=? X3=timeout ||&lt;br /&gt;
|-&lt;br /&gt;
| 0x35 || [4.0.0+] svcSignalToAddress || X0=ptr, W1=SignalType, X2=? W3=? ||&lt;br /&gt;
|- style=&amp;quot;border-top: double&amp;quot;&lt;br /&gt;
| 0x3C || [[#svcDumpInfo]] || ||&lt;br /&gt;
|-&lt;br /&gt;
| 0x3D || [4.0.0+] svcDumpInfoNew || ||&lt;br /&gt;
|- style=&amp;quot;border-top: double&amp;quot;&lt;br /&gt;
| 0x40 || svcCreateSession || W2=is_light, X3=? || W0=result, W1=server_handle, W2=client_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x41 || [[#svcAcceptSession]] || W1=port_handle || W0=result, W1=session_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x42 || svcReplyAndReceiveLight || W0=light_session_handle || W0=result, W1,W2,W3,W4,W5,W6,W7=out&lt;br /&gt;
|-&lt;br /&gt;
| 0x43 || [[#svcReplyAndReceive]] || X1=ptr_handles, W2=num_handles, X3=replytarget_handle(0=none), X4=timeout || W0=result, W1=handle_idx&lt;br /&gt;
|-&lt;br /&gt;
| 0x44 || svcReplyAndReceiveWithUserBuffer|| X1=buf, X2=sz, X3=ptr_handles, W4=num_handles, X5=replytarget_handle(0=none), X6=timeout || W0=result, W1=handle_idx&lt;br /&gt;
|-&lt;br /&gt;
| 0x45 || svcCreateEvent || None || W0=result, W1=client_handle ?, W2=server_handle ?&lt;br /&gt;
|- style=&amp;quot;border-top: double&amp;quot;&lt;br /&gt;
| 0x48 || [5.0.0+] [[#svcAllocateUnsafeMemory]] || X0=addr, X1=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x49 || [5.0.0+] svcFreeUnsafeMemory || X0=addr, X1=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x4A || [5.0.0+] svcSetUnsafeAllocationLimit || X0=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x4B || [4.0.0+] [[#svcCreateCodeMemory]] || X1=addr, X2=size || W0=result, W1=code_memory_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x4C || [4.0.0+] [[#svcControlCodeMemory]] || W0=code_memory_handle, W1=[[#CodeMemoryOperation]], X2=dstaddr, X3=size, W4=perm || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x4D || svcSleepSystem || None || None&lt;br /&gt;
|-&lt;br /&gt;
| 0x4E || [[#svcReadWriteRegister]] || X1=reg_addr, W2=rw_mask, W3=in_val || W0=result, W1=out_val&lt;br /&gt;
|-&lt;br /&gt;
| 0x4F || svcSetProcessActivity || W0=process_handle, W1=bool || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || [[#svcCreateSharedMemory]] || W1=size, W2=myperm, W3=otherperm || W0=result, W1=shmem_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x51 || [[#svcMapTransferMemory]] || X0=tmem_handle, X1=addr, X2=size, W3=perm || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x52 || [[#svcUnmapTransferMemory]] || W0=tmemhandle, X1=addr, X2=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x53 || svcCreateInterruptEvent || X1=irq_num, W2=flag || W0=result, W1=handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || [[#svcQueryPhysicalAddress]] || X1=addr || W0=result, X1=physaddr, X2=kerneladdr, X3=size&lt;br /&gt;
|-&lt;br /&gt;
| 0x55 || [[#svcQueryIoMapping]] || X1=physaddr, X2=size || W0=result, X1=virtaddr&lt;br /&gt;
|-&lt;br /&gt;
| 0x56 || [[#svcCreateDeviceAddressSpace]] || X1=dev_as_start_addr, X2=dev_as_end_addr || W0=result, W1=dev_as_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x57 || [[#svcAttachDeviceAddressSpace]] || W0=device, X1=dev_as_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x58 || [[#svcDetachDeviceAddressSpace]] || W0=device, X1=dev_as_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x59 || [[#svcMapDeviceAddressSpaceByForce]] || W0=dev_as_handle, W1=proc_handle, X2=dev_map_addr, X3=dev_as_size, X4=dev_as_addr, W5=perm || W0=result &lt;br /&gt;
|-&lt;br /&gt;
| 0x5A || [[#svcMapDeviceAddressSpaceAligned]] || W0=dev_as_handle, W1=proc_handle, X2=dev_map_addr, X3=dev_as_size, X4=dev_as_addr, W5=perm || W0=result &lt;br /&gt;
|-&lt;br /&gt;
| 0x5B || svcMapDeviceAddressSpace || || &lt;br /&gt;
|-&lt;br /&gt;
| 0x5C || [[#svcUnmapDeviceAddressSpace]] || W0=dev_as_handle, W1=proc_handle, X2=dev_map_addr, X3=dev_as_size, X4=dev_as_addr || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x5D || svcInvalidateProcessDataCache || W0=process_handle, X1=addr, X2=size || W0=size&lt;br /&gt;
|-&lt;br /&gt;
| 0x5E || svcStoreProcessDataCache || W0=process_handle, X1=addr, X2=size || W0=size&lt;br /&gt;
|-&lt;br /&gt;
| 0x5F || svcFlushProcessDataCache || W0=process_handle, X1=addr, X2=size || W0=size&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || svcDebugActiveProcess || X1=pid || W0=result, W1=debug_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x61 || svcBreakDebugProcess || W0=debug_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x62 || svcTerminateDebugProcess || W0=debug_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x63 || svcGetDebugEvent || X0=DebugEventInfo*, W1=debug_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x64 || svcContinueDebugEvent || W0=debug_handle, W1=[[#ContinueDebugFlags]], X2=thread_id || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x65 || svcGetProcessList || X1=pids_out_ptr, W2=max_out || W0=result, W1=num_out &lt;br /&gt;
|-&lt;br /&gt;
| 0x66 || svcGetThreadList || X1=tids_out_ptr, W2=max_out, W3=debug_handle_or_zero || W0=result, X1=num_out&lt;br /&gt;
|-&lt;br /&gt;
| 0x67 || svcGetDebugThreadContext || X0=ThreadContext*, X1=debug_handle, X2=thread_id, W3=[[#ThreadContextFlags]] || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || svcSetDebugThreadContext || W0=debug_handle, W1=[[#ThreadContextFlags]], X2=ThreadContext* || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x69 || svcQueryDebugProcessMemory || X0=[[#MemoryInfo]]*, X2=debug_handle, X3=addr || W0=result, W1=PageInfo&lt;br /&gt;
|-&lt;br /&gt;
| 0x6A || svcReadDebugProcessMemory || X0=buffer*, X1=debug_handle, X2=src_addr, X3=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x6B || svcWriteDebugProcessMemory || X0=debug_handle, X1=buffer*, X2=dst_addr, X3=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x6C || svcSetHardwareBreakPoint || W0=HardwareBreakpointId, X1=watchpoint_flags, X2=watchpoint_value/debug_handle? || &lt;br /&gt;
|-&lt;br /&gt;
| 0x6D || svcGetDebugThreadParam || X2=debug_handle, X3=thread_id, W4=[[#DebugThreadParam]] || W0=result, X1=out0, W2=out1&lt;br /&gt;
|- style=&amp;quot;border-top: double&amp;quot;&lt;br /&gt;
| 0x6F || [5.0.0+] svcGetMemoryInfo || X1=info_id, X2=handle, X3=info_sub_id || W0=result, X1=out&lt;br /&gt;
|-&lt;br /&gt;
| 0x70 || svcCreatePort || W2=max_sessions, W3=unk_bool, X4=name_ptr || W0=result, W1=clientport_handle, W2=serverport_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x71 || svcManageNamedPort || X1=name_ptr, W2=max_sessions || W0=result, W1=serverport_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x72 || svcConnectToPort || W1=clientport_handle || W0=result, W1=session_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x73 || [[#svcSetProcessMemoryPermission]] || W0=process_handle, X1=addr, X2=size, W3=perm || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x74 || [[#svcMapProcessMemory]] || X0=srcaddr, W1=process_handle, X2=dstaddr, X3=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x75 || [[#svcUnmapProcessMemory]] || W0=process_handle, X1=dstaddr, X2=srcaddr, X3=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x76 || [[#svcQueryProcessMemory]] || X0=meminfo_ptr, W2=process_handle, X3=addr || W0=result, W1=pageinfo&lt;br /&gt;
|-&lt;br /&gt;
| 0x77 || [[#svcMapProcessCodeMemory]] || W0=process_handle, X1=dstaddr, X2=srcaddr, X3=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x78 || [[#svcUnmapProcessCodeMemory]] || W0=process_handle, X1=dstaddr, X2=srcaddr, X3=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x79 || [[#svcCreateProcess]] || X1=procinfo_ptr, X2=caps_ptr, W3=cap_num ||  W0=result, W1=process_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x7A || svcStartProcess || W0=process_handle, W1=main_thread_prio, W2=default_cpuid, W3=main_thread_stacksz || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x7B || svcTerminateProcess || W0=process_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x7C || [[#svcGetProcessInfo]] || W0=process_handle || W0=result, X1=[[#ProcessState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x7D || svcCreateResourceLimit || None || W0=result, W1=reslimit_handle &lt;br /&gt;
|-&lt;br /&gt;
| 0x7E || svcSetResourceLimitLimitValue || W0=reslimit_handle, W1=[[#LimitableResource]], X2=value || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x7F || svcCallSecureMonitor || X0=smc_sub_id, X1,X2,X3,X4,X5,X6,X7=smc_args || X0,X1,X2,X3,X4,X5,X6,X7=result&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== svcSetHeapSize ==&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) X1 || u64 || OutAddr&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Set the process heap to a given Size. It can both extend and shrink the heap.&lt;br /&gt;
&lt;br /&gt;
Size must be a multiple of 0x200000.&lt;br /&gt;
&lt;br /&gt;
On success, the heap base-address (which is fixed by kernel, aslr&#039;d) is written to OutAddr.&lt;br /&gt;
&lt;br /&gt;
Uses current process pool partition.&lt;br /&gt;
&lt;br /&gt;
[2.0.0+] Size must be less than 0x18000000.&lt;br /&gt;
&lt;br /&gt;
== svcSetMemoryPermission ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || void* || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || [[#Permission]] || Prot&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Change permission of page-aligned memory region.&lt;br /&gt;
&lt;br /&gt;
Bit2 of permission (exec) is not allowed. Setting write-only is not allowed either (bit1).&lt;br /&gt;
&lt;br /&gt;
This can be used to move back and forth between ---, r-- and rw-.&lt;br /&gt;
&lt;br /&gt;
== svcSetMemoryAttribute ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || void* || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || u32 || State0&lt;br /&gt;
|-&lt;br /&gt;
| (In) W3 || u32 || State1&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Change attribute of page-aligned memory region. &lt;br /&gt;
&lt;br /&gt;
This is used to turn on/off caching for a given memory area. Useful when talking to devices such as the GPU.&lt;br /&gt;
&lt;br /&gt;
What happens &amp;quot;under the hood&amp;quot; is the &amp;quot;Memory Attribute Indirection Register&amp;quot; index is changed from 2 to 3 in the MMU descriptor.&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! State0 || State1 || Action&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 0 || Clear bit3 in [[#MemoryAttribute]].&lt;br /&gt;
|-&lt;br /&gt;
| 8 || 0 || Clear bit3 in [[#MemoryAttribute]].&lt;br /&gt;
|-&lt;br /&gt;
| 8 || 8 || Set bit3 in [[#MemoryAttribute]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== svcMapMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || void* || DstAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || void* || SrcAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Maps a memory range into a different range.&lt;br /&gt;
&lt;br /&gt;
Mainly used for adding guard pages around stack.&lt;br /&gt;
&lt;br /&gt;
Source range gets reprotected to --- (it can no longer be accessed), and bit0 is set in the source [[#MemoryAttribute]].&lt;br /&gt;
&lt;br /&gt;
If dstaddr &amp;gt;= LowerTreshold, the dst-range is enforced to be within the process&#039; &amp;quot;MapRegion&amp;quot;. Code can get the range of this region from [[#svcGetInfo]] id0=2,3.&lt;br /&gt;
&lt;br /&gt;
In this case, the mapped memory will have state 0x5C3C0B.&lt;br /&gt;
&lt;br /&gt;
As long as (dstaddr+size) &amp;lt; LowerThreshold, then you can map anywhere but the mapped memory will have state 0x482907 instead.&lt;br /&gt;
&lt;br /&gt;
LowerTreshold is 0x80000000 for 36-bit address spaces, and 0x40000000 for 32-bit ones.&lt;br /&gt;
&lt;br /&gt;
[2.0.0+] Support for the 0x482907 mappings outside the &amp;quot;MapRegion&amp;quot; were removed.&lt;br /&gt;
&lt;br /&gt;
== svcUnmapMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || void* || DstAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || void* || SrcAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Unmaps a region that was previously mapped with [[#svcMapMemory]].&lt;br /&gt;
&lt;br /&gt;
It&#039;s possible to unmap ranges partially, you don&#039;t need to unmap the entire range &amp;quot;in one go&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The srcaddr/dstaddr must match what was given when the pages were originally mapped.&lt;br /&gt;
&lt;br /&gt;
== svcQueryMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || [[#MemoryInfo]]* || MemInfo&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || void* || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || PageInfo || PageInfo&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Query information about an address. Will always fetch the lowest page-aligned mapping that contains the provided address.&lt;br /&gt;
&lt;br /&gt;
Outputs a [[#MemoryInfo]] struct.&lt;br /&gt;
&lt;br /&gt;
== svcExitProcess ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) None || || &lt;br /&gt;
|-&lt;br /&gt;
| (Out) None || ||&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Exits the current process.&lt;br /&gt;
&lt;br /&gt;
== svcCreateThread ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || void(*)(void*) || Entry&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || void* || ThreadContext&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || void* || StackTop&lt;br /&gt;
|-&lt;br /&gt;
| (In) W4 || u32 || Priority&lt;br /&gt;
|-&lt;br /&gt;
| (In) W5 || u32 || ProcessorId&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || Handle&amp;lt;Thread&amp;gt; || Handle&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Create a thread in the current process.&lt;br /&gt;
&lt;br /&gt;
Processor_id must be 0,1,2,3 or -2, where -2 uses the default cpuid for process.&lt;br /&gt;
&lt;br /&gt;
== svcStartThread ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;Thread&amp;gt; || Handle&lt;br /&gt;
|-&lt;br /&gt;
| (Out) None ||  ||&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Starts the thread for the provided handle.&lt;br /&gt;
&lt;br /&gt;
== svcExitThread ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) None || || &lt;br /&gt;
|-&lt;br /&gt;
| (Out) None || ||&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Exits the current thread.&lt;br /&gt;
&lt;br /&gt;
== svcSleepThread ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || u64 || Nano&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Sleep for a specified amount of time, or yield thread.&lt;br /&gt;
&lt;br /&gt;
Setting nano=0 means &amp;quot;yield thread&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== svcGetThreadPriority ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1|| Handle&amp;lt;Thread&amp;gt; || Handle&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || u64 || Priority&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Get priority of provided thread handle.&lt;br /&gt;
&lt;br /&gt;
== svcSetThreadPriority ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0|| Handle&amp;lt;Thread&amp;gt; || Handle&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1|| u32 || Priority&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Set priority of provided thread handle.&lt;br /&gt;
&lt;br /&gt;
Priority is a number 0-0x3F. Lower value means higher priority.&lt;br /&gt;
&lt;br /&gt;
== svcGetThreadCoreMask ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || Handle&amp;lt;Thread&amp;gt; || Handle&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || u32 || Out0&lt;br /&gt;
|-&lt;br /&gt;
| (Out) X2 || u64 || Out1&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Get affinity mask of provided thread handle.&lt;br /&gt;
&lt;br /&gt;
== svcSetThreadCoreMask ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;Thread&amp;gt; || Handle&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1 || u32 || In0&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || In1&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Set affinity mask of provided thread handle.&lt;br /&gt;
&lt;br /&gt;
== svcGetCurrentProcessorNumber ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) None || || &lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0/X0 || u64 || CpuId&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Get which cpu is executing the current thread.&lt;br /&gt;
&lt;br /&gt;
Cpu-id is an integer in the range 0-3.&lt;br /&gt;
&lt;br /&gt;
== svcMapSharedMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;SharedMemory&amp;gt; || MemHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || void* || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (In) W3 || [[#Permission]] || Permissions&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Maps the block supplied by the handle. The required permissions are different for the process that created the handle and all other processes.&lt;br /&gt;
&lt;br /&gt;
Increases reference count for the KSharedMemory object. Thus in order to release the memory associated with the object, all handles to it must be closed and all mappings must be unmapped.&lt;br /&gt;
&lt;br /&gt;
== svcCreateTransferMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || void* || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (In) W3 || [[#Permission]] || Permissions&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || Handle&amp;lt;TransferMemory&amp;gt; || Handle&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This one reprotects the src block with perms you give it. It also sets bit0 into [[#MemoryAttribute]].&lt;br /&gt;
&lt;br /&gt;
Executable bit perm not allowed.&lt;br /&gt;
&lt;br /&gt;
Closing all handles automatically causes the bit0 in [[#MemoryAttribute]] to clear, and the permission to reset.&lt;br /&gt;
&lt;br /&gt;
== svcWaitSynchronization ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || Handle* || HandlesPtr&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || u64 || HandlesNum&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || Timeout&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || u64 || HandleIndex&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Works with num_handles &amp;lt;= 0x40, error on num_handles == 0.&lt;br /&gt;
&lt;br /&gt;
Does not accept 0xFFFF8001 or 0xFFFF8000 as handles.&lt;br /&gt;
&lt;br /&gt;
=== Object types ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Port:&#039;&#039;&#039; signals when there is an incoming connection waiting to be [[#svcAcceptSession|accepted]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Session (server-side):&#039;&#039;&#039; signals when there is an incoming message waiting to be [[#svcReplyAndReceive|received]] or the pipe is closed.&lt;br /&gt;
&lt;br /&gt;
=== Result codes ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;0x0:&#039;&#039;&#039; Success. One of the objects was signalled before the timeout expired. Handle index is updated to indicate which object signalled.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;0xe401:&#039;&#039;&#039; Invalid handle. Returned when one of the handles passed is invalid. Handle index is not updated.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;0xea01:&#039;&#039;&#039; Timeout. Returned when no objects have been signalled within the timeout. Handle index is not updated.&lt;br /&gt;
&lt;br /&gt;
== svcGetSystemTick ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (Out) X0 || u64 || Ticks&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Returns the value of cntpct_el0.&lt;br /&gt;
&lt;br /&gt;
The frequency is 19200000 Hz (constant from official sw).&lt;br /&gt;
&lt;br /&gt;
Official sw reads cntpct_el0 directly from usermode without using this SVC. [[ExeFS|sdk-nso]] has this SVC, but it&#039;s not known to be called anywhere.&lt;br /&gt;
&lt;br /&gt;
== svcSendSyncRequestWithUserBuffer ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || void* || CmdPtr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || Handle&amp;lt;Session&amp;gt; || Handle&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Size must be 0x1000-aligned.&lt;br /&gt;
&lt;br /&gt;
== svcBreak ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || u64 || Break Reason&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 ||&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || Info&lt;br /&gt;
|-&lt;br /&gt;
| (Out) ? || ? || ?&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When used on retail where inx0 bit31 is clear, the system will throw a [[Error_codes|fatal-error]]. Otherwise when bit31 is set, it will return 0 and notify the debugger?&lt;br /&gt;
&lt;br /&gt;
== svcGetInfo ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || InfoId&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || Handle || Handle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || InfoSubId&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) X1 || u64 || Out&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Handle type || Id0 || Id1 || Description&lt;br /&gt;
|-&lt;br /&gt;
| Process || 0 || 0 || AllowedCpuIdBitmask&lt;br /&gt;
|-&lt;br /&gt;
| Process || 1 || 0 || AllowedThreadPrioBitmask&lt;br /&gt;
|-&lt;br /&gt;
| Process || 2 || 0 || MapRegionBaseAddr&lt;br /&gt;
|-&lt;br /&gt;
| Process || 3 || 0 || MapRegionSize&lt;br /&gt;
|-&lt;br /&gt;
| Process || 4 || 0 || HeapRegionBaseAddr&lt;br /&gt;
|-&lt;br /&gt;
| Process || 5 || 0 || HeapRegionSize&lt;br /&gt;
|-&lt;br /&gt;
| Process || 6 || 0 || TotalMemoryAvailable. Total memory available(free+used).&lt;br /&gt;
|-&lt;br /&gt;
| Process || 7 || 0 || TotalMemoryUsage. Total used size of codebin memory + main-thread stack + allocated heap.&lt;br /&gt;
|-&lt;br /&gt;
| Zero    || 8 || 0 || IsCurrentProcessBeingDebugged&lt;br /&gt;
|-&lt;br /&gt;
| Zero    || 9 || 0 || Returns ResourceLimit handle for current process. Used by [[Process_Manager_services|PM]].&lt;br /&gt;
|-&lt;br /&gt;
| Zero    || 10 || -1, {current coreid} || IdleTickCount&lt;br /&gt;
|-&lt;br /&gt;
| Zero    || 11 || 0-3 || RandomEntropy from current process. TRNG. Used to seed usermode PRNGs.&lt;br /&gt;
|-&lt;br /&gt;
| Process || 12 || 0 || [2.0.0+] AddressSpaceBaseAddr&lt;br /&gt;
|-&lt;br /&gt;
| Process || 13 || 0 || [2.0.0+] AddressSpaceSize&lt;br /&gt;
|-&lt;br /&gt;
| Process || 14 || 0 || [2.0.0+] NewMapRegionBaseAddr&lt;br /&gt;
|-&lt;br /&gt;
| Process || 15 || 0 || [2.0.0+] NewMapRegionSize&lt;br /&gt;
|-&lt;br /&gt;
| Process || 16 || 0 || [3.0.0+] PersonalMmHeapSize&lt;br /&gt;
|-&lt;br /&gt;
| Process || 17 || 0 || [3.0.0+] PersonalMmHeapUsage&lt;br /&gt;
|-&lt;br /&gt;
| Process || 18 || 0 || [3.0.0+] TitleId&lt;br /&gt;
|-&lt;br /&gt;
| Zero    || 19 || 0 || [4.0.0-4.1.0] PrivilegedProcessId_LowerBound&lt;br /&gt;
|-&lt;br /&gt;
| Zero    || 19 || 1 || [4.0.0-4.1.0] PrivilegedProcessId_UpperBound&lt;br /&gt;
|-&lt;br /&gt;
| Process || 20 || 0 || [5.0.0+] UserExceptionContextAddr&lt;br /&gt;
|-&lt;br /&gt;
| Thread  || 0xF0000002 || 0 || Performance counter related.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== svcMapPhysicalMemory ==&lt;br /&gt;
This is like svcSetHeapSize except you can allocate heap at any address you&#039;d like.&lt;br /&gt;
&lt;br /&gt;
Uses current process pool partition.&lt;br /&gt;
&lt;br /&gt;
== svcDumpInfo ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) None || || &lt;br /&gt;
|-&lt;br /&gt;
| (Out) None || ||&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Does nothing, just returns with registers set to all-zero.&lt;br /&gt;
&lt;br /&gt;
== svcAcceptSession ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1 || Handle&amp;lt;Port&amp;gt; || Port&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Result&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || Handle&amp;lt;ServerSession&amp;gt; || Session&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Result codes ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;0xf201:&#039;&#039;&#039; No session waiting to be accepted&lt;br /&gt;
&lt;br /&gt;
== svcReplyAndReceive ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1 || *Handle&amp;lt;Port or ServerSession&amp;gt; || Handles&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || u32 || NumHandles&lt;br /&gt;
|-&lt;br /&gt;
| (In) W3 || Handle&amp;lt;ServerSession&amp;gt; || ReplyTarget&lt;br /&gt;
|-&lt;br /&gt;
| (In) X4 || u64 (nanoseconds) || Timeout&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Result&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || u32 || HandleIndex&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If ReplyTarget is not zero, a reply from the TLS will be sent to that session.&lt;br /&gt;
Then it will wait until either of the passed sessions has an incoming message, is closed, a passed port has an incoming connection, or the timeout expires.&lt;br /&gt;
If there is an incoming message, it is copied to the TLS.&lt;br /&gt;
&lt;br /&gt;
After being validated, passed handles will be enumerated in order; even if a session has been closed, if one that appears earlier in the list has an incoming message, it will take priority and a result code of 0x0 will be returned.&lt;br /&gt;
&lt;br /&gt;
=== Result codes ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;0x0:&#039;&#039;&#039; Success. Either a session has an incoming message or a port has an incoming connection. HandleIndex is set appropriately.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;0xea01:&#039;&#039;&#039; Timeout. No handles were signalled before the timeout expired. HandleIndex is not updated.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;0xf601:&#039;&#039;&#039; Port remote dead. One of the sessions has been closed. HandleIndex is set appropriately.&lt;br /&gt;
&lt;br /&gt;
== svcAllocateUnsafeMemory ==&lt;br /&gt;
Same as [[#svcMapPhysicalMemory]] except it always uses pool partition 0.&lt;br /&gt;
&lt;br /&gt;
== svcCreateCodeMemory ==&lt;br /&gt;
Takes an address range with backing memory to create the code memory object.&lt;br /&gt;
&lt;br /&gt;
The memory is initially memset to 0xFF after being locked.&lt;br /&gt;
&lt;br /&gt;
== svcControlCodeMemory ==&lt;br /&gt;
Maps the backing memory for a Code memory object into the current process.&lt;br /&gt;
&lt;br /&gt;
For [[#CodeMemoryOperation|CodeMemoryOperation_MapOwner]], memory permission must be RW-.&lt;br /&gt;
&lt;br /&gt;
For [[#CodeMemoryOperation|CodeMemoryOperation_MapSlave]], memory permission must be R-- or R-X.&lt;br /&gt;
&lt;br /&gt;
Operations [[#CodeMemoryOperation|CodeMemoryOperation_UnmapOwner/CodeMemoryOperation_UnmapSlave]] unmap memory that was previously mapped this way.&lt;br /&gt;
&lt;br /&gt;
This allows one &amp;quot;secure JIT&amp;quot; process to map the code memory as RW-, and the other &amp;quot;slave&amp;quot; process to map it R-X.&lt;br /&gt;
&lt;br /&gt;
== svcReadWriteRegister ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || RegAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || u64 || RwMask&lt;br /&gt;
|-&lt;br /&gt;
| (In) W3 || u64 || InValue&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1|| u64 || OutValue&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Read/write IO registers with a hardcoded whitelist. Input address is physical-address and must be aligned to 4.&lt;br /&gt;
&lt;br /&gt;
rw_mask is 0 for reading and 0xffffffff for writing. You can also write individual bits by using a mask value.&lt;br /&gt;
&lt;br /&gt;
You can only write to registers inside physical pages 0x70019000 (MC), 0x7001C000 (MC0), 0x7001D000 (MC1), and they all share the same whitelist.&lt;br /&gt;
&lt;br /&gt;
The whitelist is same for writing as for reading.&lt;br /&gt;
&lt;br /&gt;
The whitelist is:&lt;br /&gt;
&lt;br /&gt;
0x054, 0x090, 0x094, 0x098, 0x09c, 0x0a0, 0x0a4, 0x0a8, 0x0ac, 0x0b0, 0x0b4, 0x0b8, 0x0bc, 0x0c0, 0x0c4, 0x0c8, 0x0d0, 0x0d4, 0x0d8, 0x0dc, 0x0e0, 0x100, 0x108, 0x10c, 0x118, 0x11c, 0x124, 0x128, 0x12c, 0x130, 0x134, 0x138, 0x13c, 0x158, 0x15c, 0x164, 0x168, 0x16c, 0x170, 0x174, 0x178, 0x17c, 0x200, 0x204, 0x2e4, 0x2e8, 0x2ec, 0x2f4, 0x2f8, 0x310, 0x314, 0x320, 0x328, 0x344, 0x348, 0x370, 0x374, 0x37c, 0x380, 0x390, 0x394, 0x398, 0x3ac, 0x3b8, 0x3bc, 0x3c0, 0x3c4, 0x3d8, 0x3e8, 0x41c, 0x420, 0x424, 0x428, 0x42c, 0x430, 0x44c, 0x47c, 0x480, 0x484, 0x50c, 0x554, 0x558, 0x55c, 0x670, 0x674, 0x690, 0x694, 0x698, 0x69c, 0x6a0, 0x6a4, 0x6c0, 0x6c4, 0x6f0, 0x6f4, 0x960, 0x970, 0x974, 0xa20, 0xa24, 0xb88, 0xb8c, 0xbc4, 0xbc8, 0xbcc, 0xbd0, 0xbd4, 0xbd8, 0xbdc, 0xbe0, 0xbe4, 0xbe8, 0xbec, 0xc00, 0xc5c, 0xcac&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[2.0.0+] Whitelist was extended with 0x4c4, 0x4c8, 0x4cc, 0x584, 0x588, 0x58c.&lt;br /&gt;
&lt;br /&gt;
[2.0.0+] The IO registers in range 0x7000E400 (PMC) size 0xC00 skip the whitelist, and do a TrustZone call using [[SMC]] Id1 0xC3000008(ReadWriteRegister).&lt;br /&gt;
&lt;br /&gt;
[4.0.0+] Access to the Memory Controller (0x70019000) also uses smcReadWriteRegister.&lt;br /&gt;
&lt;br /&gt;
Here is the whitelist imposed by that SMC, relative to the start of the PMC registers:&lt;br /&gt;
&lt;br /&gt;
0x000, 0x00c, 0x010, 0x014, 0x01c, 0x020, 0x02c, 0x030, 0x034, 0x038, 0x03c, 0x040, 0x044, 0x048, 0x0dc, 0x0e0, 0x0e4, 0x160, 0x164, 0x168, 0x170, 0x1a8, 0x1b8, 0x1bc, 0x1c0, 0x1c4, 0x1c8, 0x2b4, 0x2d4, 0x440, 0x4d8&lt;br /&gt;
&lt;br /&gt;
Here is the whitelist imposed by smcReadWriteRegister (checked in addition to the whitelist in svcReadWriteRegister), relative to the start of the MC registers:&lt;br /&gt;
&lt;br /&gt;
0x000, 0x004, 0x008, 0x00C, 0x010, 0x01C, 0x020, 0x030, 0x034, 0x050, 0x054, 0x090, 0x094, 0x098, 0x09C, 0x0A0, 0x0A4, 0x0A8, 0x0AC, 0x0B0, 0x0B4, 0x0B8, 0x0BC, 0x0C0, 0x0C4, 0x0C8, 0x0D0, 0x0D4, 0x0D8, 0x0DC, 0x0E0, 0x100, 0x108, 0x10C, 0x118, 0x11C, 0x124, 0x128, 0x12C, 0x130, 0x134, 0x138, 0x13C, 0x158, 0x15C, 0x164, 0x168, 0x16C, 0x170, 0x174, 0x178, 0x17C, 0x200, 0x204, 0x238, 0x240, 0x244, 0x250, 0x254, 0x258, 0x264, 0x268, 0x26C, 0x270, 0x274, 0x280, 0x284, 0x288, 0x28C, 0x294, 0x2E4, 0x2E8, 0x2EC, 0x2F4, 0x2F8, 0x310, 0x314, 0x320, 0x328, 0x344, 0x348, 0x370, 0x374, 0x37C, 0x380, 0x390, 0x394, 0x398, 0x3AC, 0x3B8, 0x3BC, 0x3C0, 0x3C4, 0x3D8, 0x3E8, 0x41C, 0x420, 0x424, 0x428, 0x42C, 0x430, 0x44C, 0x47C, 0x480, 0x484, 0x4C4, 0x4C8, 0x4CC, 0x50C, 0x554, 0x558, 0x55C, 0x584, 0x588, 0x58C, 0x670, 0x674, 0x690, 0x694, 0x698, 0x69C, 0x6A0, 0x6A4, 0x6C0, 0x6C4, 0x6F0, 0x6F4, 0x960, 0x970, 0x974, 0x9B8, 0xA20, 0xA24, 0xA88, 0xA94, 0xA98, 0xA9C, 0xAA0, 0xAA4, 0xAA8, 0xAAC, 0xAB0, 0xAB4, 0xAB8, 0xABC, 0xAC0, 0xAC4, 0xAC8, 0xACC, 0xAD0, 0xAD4, 0xAD8, 0xADC, 0xAE0, 0xB88, 0xB8C, 0xBC4, 0xBC8, 0xBCC, 0xBD0, 0xBD4, 0xBD8, 0xBDC, 0xBE0, 0xBE4, 0xBE8, 0xBEC, 0xC00, 0xC5C, 0xCAC&lt;br /&gt;
&lt;br /&gt;
== svcCreateSharedMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || [[#Permission]] || LocalPerm&lt;br /&gt;
|-&lt;br /&gt;
| (In) W3 || [[#Permission]] || RemotePerm&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || Handle&amp;lt;SharedMemory&amp;gt; || MemHandle&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other perm can be used to enforce permission 1, 3, or 0x10000000 if don&#039;t care.&lt;br /&gt;
&lt;br /&gt;
Allocates memory from the current process&#039; pool partition.&lt;br /&gt;
&lt;br /&gt;
== svcMapTransferMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || Handle&amp;lt;TransferMemory&amp;gt; || MemHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || void* || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (In) W3 || [[#Permission]] || Permissions&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The newly mapped pages will have [[#MemoryState]] type 0xE.&lt;br /&gt;
&lt;br /&gt;
You must pass same size and permissions as given in svcCreateMemoryMirror, otherwise error.&lt;br /&gt;
&lt;br /&gt;
== svcUnmapTransferMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || Handle&amp;lt;TransferMemory&amp;gt; || MemHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || void* || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Size must match size given in map syscall, otherwise there&#039;s an invalid-size error.&lt;br /&gt;
&lt;br /&gt;
== svcQueryPhysicalAddress ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]]|| Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) X1 || u64 || PhysAddr&lt;br /&gt;
|-&lt;br /&gt;
| (Out) X2 || u64 || KernelAddr&lt;br /&gt;
|-&lt;br /&gt;
| (Out) X3 || u64 || Size&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== svcQueryIoMapping ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || PhysAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) X1 || void* || VirtAddr&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Returns a virtual address mapped to a given IO range.&lt;br /&gt;
&lt;br /&gt;
== svcCreateDeviceAddressSpace ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || StartAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || EndAddr&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || Handle&amp;lt;DeviceAddressSpace&amp;gt; || AddressSpaceHandle&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Creates a virtual address space for binding device address spaces and returns a handle.&lt;br /&gt;
&lt;br /&gt;
dev_as_start_addr is normally set to 0 and dev_as_end_addr is normally set to 0xFFFFFFFF.&lt;br /&gt;
&lt;br /&gt;
== svcAttachDeviceAddressSpace ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || [[#DeviceName]] || DeviceId&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || Handle&amp;lt;DeviceAddressSpace&amp;gt; || DeviceAsHandle&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Attaches a device address space to a [[#DeviceName|device]].&lt;br /&gt;
&lt;br /&gt;
== svcDetachDeviceAddressSpace ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || [[#DeviceName]] || DeviceId&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || Handle&amp;lt;DeviceAddressSpace&amp;gt; || DeviceAsHandle&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Detaches a device address space from a [[#DeviceName|device]].&lt;br /&gt;
&lt;br /&gt;
== svcMapDeviceAddressSpaceByForce ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;DeviceAddressSpace&amp;gt; || DeviceAsHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || void* || SrcAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || DeviceAsSize&lt;br /&gt;
|-&lt;br /&gt;
| (In) X4 || u64 || DeviceAsAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) W5 || [[#Permission]] || Permissions&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Maps an attached device address space to an userspace address.&lt;br /&gt;
&lt;br /&gt;
dev_map_addr is the userspace destination address, while dev_as_addr is the source address between dev_as_start_addr and dev_as_end_addr (passed to [[#svcCreateDeviceAddressSpace]]).&lt;br /&gt;
&lt;br /&gt;
The userspace destination address must have the [[SVC#MemoryState|MapDeviceAllowed]] bit set. Bit [[SVC#MemoryAttribute|IsDeviceMapped]] will be set after mapping.&lt;br /&gt;
&lt;br /&gt;
== svcMapDeviceAddressSpaceAligned ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;DeviceAddressSpace&amp;gt; || DeviceAsHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || void* || SrcAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || DeviceAsSize&lt;br /&gt;
|-&lt;br /&gt;
| (In) X4 || u64 || DeviceAsAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) W5 || [[#Permission]] || Permissions&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Maps an attached device address space to an userspace address.&lt;br /&gt;
&lt;br /&gt;
Same as [[#svcMapDeviceAddressSpaceByForce]], but the userspace destination address must have the [[SVC#MemoryState|MapDeviceAlignedAllowed]] bit set instead.&lt;br /&gt;
&lt;br /&gt;
== svcUnmapDeviceAddressSpace ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;DeviceAddressSpace&amp;gt; || DeviceAsHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || void* || SrcAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || DeviceAsSize&lt;br /&gt;
|-&lt;br /&gt;
| (In) X4 || u64 || DeviceAsAddr&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Unmaps an attached device address space from an userspace address.&lt;br /&gt;
&lt;br /&gt;
== svcSetProcessMemoryPermission ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (In) W3 || void* || Perm&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This sets the memory permissions for the specified memory with the supplied process handle.&lt;br /&gt;
&lt;br /&gt;
This throws an error(0xD801) when the input perm is &amp;gt;0x5, hence -WX and RWX are not allowed.&lt;br /&gt;
&lt;br /&gt;
== svcMapProcessMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || u64 || SrcAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || void* || DstAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Maps the src address from the supplied process handle into the current process.&lt;br /&gt;
&lt;br /&gt;
This allows mapping code and rodata with RW- permission.&lt;br /&gt;
&lt;br /&gt;
== svcUnmapProcessMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || void* || DstAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || SrcAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Unmaps what was mapped by [[#svcMapProcessMemory]].&lt;br /&gt;
&lt;br /&gt;
== svcQueryProcessMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || [[#MemoryInfo]]* || MemInfoPtr&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || PageInfo || PageInfo&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Equivalent to [[#svcQueryMemory]] except takes a process handle.&lt;br /&gt;
&lt;br /&gt;
== svcMapProcessCodeMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || DstAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || SrcAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Takes a process handle, and maps normal heap in that process as executable code in that process. Used when loading NROs. This does not support using the current-process handle alias.&lt;br /&gt;
&lt;br /&gt;
== svcUnmapProcessCodeMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || DstAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || SrcAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Unmaps what was mapped by [[#svcMapProcessCodeMemory]].&lt;br /&gt;
&lt;br /&gt;
== svcCreateProcess ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || [[#CreateProcessInfo]]* || InfoPtr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || CapabilitiesPtr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || CapabilitiesNum&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Takes a [[#CreateProcessInfo]] as input.&lt;br /&gt;
&lt;br /&gt;
== svcGetProcessInfo ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || [[#ProcessState]] || State&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Returns an enum with value 0-7.&lt;br /&gt;
&lt;br /&gt;
== Debugging ==&lt;br /&gt;
[2.0.0+] Exactly 6 debug SVCs require that [[SPL_services#GetConfig|IsDebugMode]] is non-zero. Error 0x4201 is returned otherwise.&lt;br /&gt;
* svcBreakDebugProcess&lt;br /&gt;
* svcContinueDebugEvent&lt;br /&gt;
* svcWriteDebugProcessMemory&lt;br /&gt;
* svcSetDebugThreadContext&lt;br /&gt;
* svcTerminateDebugProcess&lt;br /&gt;
* svcSetHardwareBreakPoint&lt;br /&gt;
&lt;br /&gt;
svcDebugActiveProcess stops execution of the target process, the normal method for resuming it requires svcContinueDebugEvent(see above). Closing the debug handle also results in execution being resumed.&lt;br /&gt;
&lt;br /&gt;
= Enum/Structures =&lt;br /&gt;
== ThreadContextRequestFlags ==&lt;br /&gt;
Bitfield of one of more of these:&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Bit || Bitmask || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 1 || NormalContext&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 4 ||&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 8 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== DeviceName ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || DeviceName_AFI&lt;br /&gt;
|-&lt;br /&gt;
| 1 || DeviceName_AVPC&lt;br /&gt;
|-&lt;br /&gt;
| 2 || DeviceName_DC&lt;br /&gt;
|-&lt;br /&gt;
| 3 || DeviceName_DCB&lt;br /&gt;
|-&lt;br /&gt;
| 4 || DeviceName_HC&lt;br /&gt;
|-&lt;br /&gt;
| 5 || DeviceName_HDA&lt;br /&gt;
|-&lt;br /&gt;
| 6 || DeviceName_ISP2&lt;br /&gt;
|-&lt;br /&gt;
| 7 || DeviceName_MSENCNVENC&lt;br /&gt;
|-&lt;br /&gt;
| 8 || DeviceName_NV&lt;br /&gt;
|-&lt;br /&gt;
| 9 || DeviceName_NV2&lt;br /&gt;
|-&lt;br /&gt;
| 10 || DeviceName_PPCS&lt;br /&gt;
|-&lt;br /&gt;
| 11 || DeviceName_SATA&lt;br /&gt;
|-&lt;br /&gt;
| 12 || DeviceName_VI&lt;br /&gt;
|-&lt;br /&gt;
| 13 || DeviceName_VIC&lt;br /&gt;
|-&lt;br /&gt;
| 14 || DeviceName_XUSB_HOST&lt;br /&gt;
|-&lt;br /&gt;
| 15 || DeviceName_XUSB_DEV&lt;br /&gt;
|-&lt;br /&gt;
| 16 || DeviceName_TSEC&lt;br /&gt;
|-&lt;br /&gt;
| 17 || DeviceName_PPCS1&lt;br /&gt;
|-&lt;br /&gt;
| 18 || DeviceName_DC1&lt;br /&gt;
|-&lt;br /&gt;
| 19 || DeviceName_SDMMC1A&lt;br /&gt;
|-&lt;br /&gt;
| 20 || DeviceName_SDMMC2A&lt;br /&gt;
|-&lt;br /&gt;
| 21 || DeviceName_SDMMC3A&lt;br /&gt;
|-&lt;br /&gt;
| 22 || DeviceName_SDMMC4A&lt;br /&gt;
|-&lt;br /&gt;
| 23 || DeviceName_ISP2B&lt;br /&gt;
|-&lt;br /&gt;
| 24 || DeviceName_GPU&lt;br /&gt;
|-&lt;br /&gt;
| 25 || DeviceName_GPUB&lt;br /&gt;
|-&lt;br /&gt;
| 26 || DeviceName_PPCS2&lt;br /&gt;
|-&lt;br /&gt;
| 27 || DeviceName_NVDEC&lt;br /&gt;
|-&lt;br /&gt;
| 28 || DeviceName_APE&lt;br /&gt;
|-&lt;br /&gt;
| 29 || DeviceName_SE&lt;br /&gt;
|-&lt;br /&gt;
| 30 || DeviceName_NVJPG&lt;br /&gt;
|-&lt;br /&gt;
| 31 || DeviceName_HC1&lt;br /&gt;
|-&lt;br /&gt;
| 32 || DeviceName_SE1&lt;br /&gt;
|-&lt;br /&gt;
| 33 || DeviceName_AXIAP&lt;br /&gt;
|-&lt;br /&gt;
| 34 || DeviceName_ETR&lt;br /&gt;
|-&lt;br /&gt;
| 35 || DeviceName_TSECB&lt;br /&gt;
|-&lt;br /&gt;
| 36 || DeviceName_TSEC1&lt;br /&gt;
|-&lt;br /&gt;
| 37 || DeviceName_TSECB1&lt;br /&gt;
|-&lt;br /&gt;
| 38 || DeviceName_NVDEC1&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CodeMemoryOperation ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || CodeMemoryOperation_MapOwner&lt;br /&gt;
|-&lt;br /&gt;
| 1 || CodeMemoryOperation_MapSlave&lt;br /&gt;
|-&lt;br /&gt;
| 2 || CodeMemoryOperation_UnmapOwner&lt;br /&gt;
|-&lt;br /&gt;
| 3 || CodeMemoryOperation_UnmapSlave&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LimitableResource ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || LimitableResource_Memory&lt;br /&gt;
|-&lt;br /&gt;
| 1 || LimitableResource_Threads&lt;br /&gt;
|-&lt;br /&gt;
| 2 || LimitableResource_Events&lt;br /&gt;
|-&lt;br /&gt;
| 3 || LimitableResource_TransferMemories&lt;br /&gt;
|-&lt;br /&gt;
| 4 || LimitableResource_Sessions&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== ProcessEvent ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || ProcessEvent_Created&lt;br /&gt;
|-&lt;br /&gt;
| 1 || ProcessEvent_DebugAttached&lt;br /&gt;
|-&lt;br /&gt;
| 2 || ProcessEvent_DebugDetached&lt;br /&gt;
|-&lt;br /&gt;
| 3 || ProcessEvent_Crashed&lt;br /&gt;
|-&lt;br /&gt;
| 4 || ProcessEvent_Running&lt;br /&gt;
|-&lt;br /&gt;
| 5 || ProcessEvent_Exiting&lt;br /&gt;
|-&lt;br /&gt;
| 6 || ProcessEvent_Exited&lt;br /&gt;
|-&lt;br /&gt;
| 7 || ProcessEvent_DebugSuspended&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== DebugThreadParam ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || DebugThreadParam_ActualPriority&lt;br /&gt;
|-&lt;br /&gt;
| 1 ||&lt;br /&gt;
|-&lt;br /&gt;
| 2 || DebugThreadParam_CpuCore&lt;br /&gt;
|-&lt;br /&gt;
| 3 ||&lt;br /&gt;
|-&lt;br /&gt;
| 4 || DebugThreadParam_CoreMask&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateProcessInfo ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Bits || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 12 || || ProcessName (doesn&#039;t have to be null-terminated)&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 4 || || ProcessCategory (0: regular title, 1: kernel built-in)&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 8 || || TitleId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 8 || || CodeAddr&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 4 || || CodeNumPages&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 4 || || MmuFlags&lt;br /&gt;
|-&lt;br /&gt;
| || || Bit0 || IsAarch64&lt;br /&gt;
|-&lt;br /&gt;
| || || Bit3-1 || [[#AddressSpaceType]]&lt;br /&gt;
|-&lt;br /&gt;
| || || Bit4 ||&lt;br /&gt;
|-&lt;br /&gt;
| || || Bit5 || EnableAslr&lt;br /&gt;
|-&lt;br /&gt;
| || || Bit6 || UseSystemMemBlocks&lt;br /&gt;
|-&lt;br /&gt;
| || || Bit7 || [4.0.0] ?&lt;br /&gt;
|-&lt;br /&gt;
| || || Bit10-7 || [5.0.0+] PoolPartition (0=Application, 1=Applet, 2=Sysmodule, 3=Nvservices)&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 4 || || ResourceLimitHandle&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C || 4 || || [3.0.0+] PersonalMmHeapNumPages&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
On [1.0.0] there&#039;s only one pool.&lt;br /&gt;
&lt;br /&gt;
On [2.0.0-4.0.0] PoolPartition is 1 for built-ins and 0 for rest.&lt;br /&gt;
&lt;br /&gt;
On [5.0.0] PoolPartition is specified in CreateProcessArgs. There are now 4 pool partitions.&lt;br /&gt;
&lt;br /&gt;
=== AddressSpaceType ===&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Type || Name || Width || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Normal_32Bit || 32 ||&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Normal_36Bit || 36 ||&lt;br /&gt;
|-&lt;br /&gt;
| 2 || WithoutMap_32Bit || 32 || Appears to be missing map region [?]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [2.0.0+] Normal_39Bit || 39 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== MemoryInfo ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 8 || BaseAddress&lt;br /&gt;
|-&lt;br /&gt;
| 8 || 8 || Size&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 4 || MemoryType: lower 8 bits of [[#MemoryState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x14 || 4 || [[#MemoryAttribute]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 4 || Permission (bit0: R, bit1: W, bit2: X)&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 4 || IpcRefCount&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 4 || DeviceRefCount&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 4 || Padding: always zero&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== MemoryAttribute ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Bits || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || IsBorrowed&lt;br /&gt;
|-&lt;br /&gt;
| 1 || IsIpcMapped: when IpcRefCount &amp;gt; 0.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || IsDeviceMapped: when DeviceRefCount &amp;gt; 0.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || IsUncached&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== MemoryState ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Bits || Description&lt;br /&gt;
|-&lt;br /&gt;
| 7-0 || Type&lt;br /&gt;
|-&lt;br /&gt;
| 8 || [[#svcSetMemoryPermission|PermissionChangeAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 9 || ForceReadWritableByDebugSyscalls&lt;br /&gt;
|-&lt;br /&gt;
| 10 || IpcSendAllowed_Type0&lt;br /&gt;
|-&lt;br /&gt;
| 11 || IpcSendAllowed_Type3&lt;br /&gt;
|-&lt;br /&gt;
| 12 || IpcSendAllowed_Type1&lt;br /&gt;
|-&lt;br /&gt;
| 14 || [[#svcSetProcessMemoryPermission|ProcessPermissionChangeAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 15 || [[#svcMapMemory|MapAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 16 || [[#svcUnmapProcessCodeMemory|UnmapProcessCodeMemoryAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 17 || [[#svcCreateTransferMemory|TransferMemoryAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 18 || [[#svcQueryPhysicalAddress|QueryPhysicalAddressAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 19 || MapDeviceAllowed ([[#svcMapDeviceAddressSpace]] and [[#svcMapDeviceAddressSpaceByForce]])&lt;br /&gt;
|-&lt;br /&gt;
| 20 || [[#svcMapDeviceAddressSpaceAligned|MapDeviceAlignedAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 21 || [[#svcSendSyncRequestWithUserBuffer|IpcBufferAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 22 || IsPoolAllocated/IsReferenceCounted&lt;br /&gt;
|-&lt;br /&gt;
| 23 || [[#svcMapProcessMemory|MapProcessAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 24 || [[#svcSetMemoryAttribute|AttributeChangeAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 25 || [4.0.0+] CodeMemoryAllowed&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Type || Meaning&lt;br /&gt;
|-&lt;br /&gt;
| 0x00000000 || MemoryType_Unmapped ||&lt;br /&gt;
|-&lt;br /&gt;
| 0x00002001 || MemoryType_Io || Mapped by kernel capability parsing in [[#svcCreateProcess]]. &lt;br /&gt;
|-&lt;br /&gt;
| 0x00042002 || MemoryType_Normal || Mapped by kernel capability parsing in [[#svcCreateProcess]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x00DC7E03 || MemoryType_CodeStatic || Mapped during [[#svcCreateProcess]].&lt;br /&gt;
|-&lt;br /&gt;
| [1.0.0+]&lt;br /&gt;
&lt;br /&gt;
0x01FEBD04&lt;br /&gt;
&lt;br /&gt;
[4.0.0+]&lt;br /&gt;
&lt;br /&gt;
0x03FEBD04&lt;br /&gt;
|| MemoryType_CodeMutable || Transition from 0xDC7E03 performed by [[#svcSetProcessMemoryPermission]].&lt;br /&gt;
|-&lt;br /&gt;
| [1.0.0+]&lt;br /&gt;
0x017EBD05&lt;br /&gt;
&lt;br /&gt;
[4.0.0+]&lt;br /&gt;
&lt;br /&gt;
0x037EBD05&lt;br /&gt;
|| MemoryType_Heap || Mapped using [[#svcSetHeapSize]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x00402006 || MemoryType_SharedMemory || Mapped using [[#svcMapSharedMemory]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x00482907 || [1.0.0] MemoryType_WeirdMappedMemory || Mapped using [[#svcMapMemory]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x00DD7E08 || MemoryType_ModuleCodeStatic || Mapped using [[#svcMapProcessCodeMemory]].&lt;br /&gt;
|-&lt;br /&gt;
| [1.0.0+]&lt;br /&gt;
&lt;br /&gt;
0x01FFBD09&lt;br /&gt;
&lt;br /&gt;
[4.0.0+]&lt;br /&gt;
&lt;br /&gt;
0x03FFBD09&lt;br /&gt;
|| MemoryType_ModuleCodeMutable || Transition from 0xDD7E08 performed by [[#svcSetProcessMemoryPermission]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x005C3C0A || [[IPC_Marshalling|MemoryType_IpcBuffer0]] || IPC buffers with descriptor flags=0.&lt;br /&gt;
|-&lt;br /&gt;
| 0x005C3C0B || MemoryType_MappedMemory || Mapped using [[#svcMapMemory]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x0040200C || [[Thread Local Storage|MemoryType_ThreadLocal]] || Mapped during [[#svcCreateThread]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x015C3C0D || MemoryType_TransferMemoryIsolated || Mapped using [[#svcMapTransferMemory]] when the owning process has perm=0.&lt;br /&gt;
|-&lt;br /&gt;
| 0x005C380E || MemoryType_TransferMemory || Mapped using [[#svcMapTransferMemory]] when the owning process has perm!=0.&lt;br /&gt;
|-&lt;br /&gt;
| 0x0040380F || MemoryType_ProcessMemory || Mapped using [[#svcMapProcessMemory]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x00000010 || MemoryType_Reserved ||&lt;br /&gt;
|-&lt;br /&gt;
| 0x005C3811 || [[IPC_Marshalling|MemoryType_IpcBuffer1]] || IPC buffers with descriptor flags=1.&lt;br /&gt;
|-&lt;br /&gt;
| 0x004C2812 || [[IPC_Marshalling|MemoryType_IpcBuffer3]] || IPC buffers with descriptor flags=3.&lt;br /&gt;
|-&lt;br /&gt;
| 0x00002013 || MemoryType_KernelStack || Mapped in kernel during [[#svcCreateThread]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x00402214 || [4.0.0+] MemoryType_CodeReadOnly || Mapped in kernel during [[#svcControlCodeMemory]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x00402015 || [4.0.0+] MemoryType_CodeWritable || Mapped in kernel during [[#svcControlCodeMemory]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== ContinueDebugFlags ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Bit || Bitmask || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 1 || CancelSynchronization (only if ResumeAllThreads is set; cancels with error 0x6C01)&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 2 || SwallowException&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 4 || ResumeAllThreads&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== DebugEventInfo ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || u32 || EventType&lt;br /&gt;
|-&lt;br /&gt;
| 4 || u32 || Flags (bit0: NeedsContinue)&lt;br /&gt;
|-&lt;br /&gt;
| 8 || u64 || ThreadId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || || PerTypeSpecifics&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
AttachProcess specific:&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || u64 || TitleId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || u64 || ProcessId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || char[12] || ProcessName&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C || u32 || MmuFlags&lt;br /&gt;
|-&lt;br /&gt;
| 0x30 || u64 || [5.0.0+] UserExceptionContextAddr&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
AttachThread specific:&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || u64 || ThreadId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || u64 || TlsPtr&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || u64 || Entrypoint&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Exit specific:&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || u64 || Type (0=PausedThread, 1=RunningThread, 2=TerminatedProcess)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Exception specific:&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || u64 || ExceptionType&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || u64 || FaultRegister&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || || PerExceptionSpecifics&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== DebugEventType ===&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || DebugEvent_AttachProcess&lt;br /&gt;
|-&lt;br /&gt;
| 1 || DebugEvent_AttachThread&lt;br /&gt;
|-&lt;br /&gt;
| 2 ||&lt;br /&gt;
|-&lt;br /&gt;
| 3 || DebugEvent_Exit&lt;br /&gt;
|-&lt;br /&gt;
| 4 || DebugEvent_Exception&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== DebugExceptionType ===&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Exception_UndefinedInstruction&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Exception_InstructionAbort&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Exception_DataAbortMisc&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Exception_PcSpAlignmentFault&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Exception_DebuggerAttached&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Exception_BreakPoint&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Exception_UserBreak&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Exception_DebuggerBreak&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Exception_BadSvcId&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
UndefinedInstruction specifics:&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || u32 || Opcode&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
BreakPoint specifics:&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || u32 || IsWatchpoint&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
UserBreak specifics:&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || u32 || Info0&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || u64 || Info1&lt;br /&gt;
|-&lt;br /&gt;
| 0x30 || u64 || Info2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
BadSvcId specifics:&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || u32 || SvcId&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Exception handling =&lt;br /&gt;
There is userland code for handling exceptions, however this doesn&#039;t seem to be executed on retail mode.&lt;br /&gt;
&lt;br /&gt;
When a usermode exception occurs, it jumps to the main code binary entrypoint (main_binary_address + 0 == &#039;&#039;&#039;_start&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
During normal boot &#039;&#039;&#039;_start&#039;&#039;&#039; is invoked with X0=0 and X1=main_thread_handle (triggering normal crt0 setup).&lt;br /&gt;
During an usermode exception &#039;&#039;&#039;_start&#039;&#039;&#039; is invoked with X0=exception_info0_ptr and X1=exception_info1_ptr instead.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;_start&#039;&#039;&#039; method determines whether to boot normally or handle an exception if X0 is set to 0 or not.&lt;/div&gt;</summary>
		<author><name>Gdkchan</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=GPU&amp;diff=4415</id>
		<title>GPU</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=GPU&amp;diff=4415"/>
		<updated>2018-04-01T20:12:20Z</updated>

		<summary type="html">&lt;p&gt;Gdkchan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Mapping Memory ==&lt;br /&gt;
&lt;br /&gt;
First, to map a memory region on the GPU Address Space, caching needs to be disabled by using [[SVC#svcSetMemoryAttribute|svcSetMemoryAttribute]]. The Address passed is the Virtual Address of the region that will be mapped, the size is the region size, and State0/1 are both set to 8 to disable caching of the memory region. This is done to ensure that the GPU can actually &amp;quot;see&amp;quot; the data written there, and it doesn&#039;t get stuck on some cache.&lt;br /&gt;
&lt;br /&gt;
Then, [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]] is used to create a nvmap object with the desired size. After, [[NV_services#NVMAP_IOC_ALLOC|NVMAP_IOC_ALLOC]] is used to allocate the memory on the GPU Address Space, and map data on the process Address Space into the GPU Address Space, by passing the Virtual Address as the input addr parameter, and also the Handle returned from [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]]. Lastly, the actual mapping is done by using [[NV_services#NVGPU_AS_IOCTL_MAP_BUFFER_EX|NVGPU_AS_IOCTL_MAP_BUFFER_EX]], and the GPU Virtual Address is returned on the offset parameter. It&#039;s also possible to manually set the offset where the mapping should be made on the GPU Address Space, by passing the address on the &amp;quot;offset&amp;quot; parameter, and setting the bit 0 of the flags parameter to 1. However, for this to work, the desired GPU Virtual Address needs to be previously reserved using [[NV_services#NVGPU_AS_IOCTL_ALLOC_SPACE|NVGPU_AS_IOCTL_ALLOC_SPACE]].&lt;br /&gt;
&lt;br /&gt;
The above process is used to map all data that will be used by the GPU, like Textures, Command Lists (a.k.a. Push Buffers), Vertex/Index buffers and Shaders. They usually have their own mapping, but Command Lists can share the same mapping.&lt;br /&gt;
&lt;br /&gt;
== FIFO Commands ==&lt;br /&gt;
&lt;br /&gt;
The GPU implements a variation of Tegra&#039;s push buffer format for it&#039;s PFIFO engine. PFIFO is a special engine responsible for receiving user command lists and routing them to the appropriate engines (2D, 3D, DMA).&lt;br /&gt;
&lt;br /&gt;
Commands are submitted to the GPU&#039;s PFIFO engine through [[NV_services#NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO|NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO]].&lt;br /&gt;
&lt;br /&gt;
This ioctl takes an array of gpfifo entries where each entry points to a FIFO command list. This list is composed of alternating 32-bit words containing FIFO commands and their respective arguments.&lt;br /&gt;
&lt;br /&gt;
See the [[GPU|GPU]] page for a list of commands, with the register addresses and their descriptions.&lt;br /&gt;
&lt;br /&gt;
=== Command Structure ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Bits&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|12-0&lt;br /&gt;
|Method&lt;br /&gt;
|-&lt;br /&gt;
|15-13&lt;br /&gt;
|Subchannel&lt;br /&gt;
|-&lt;br /&gt;
|27-16&lt;br /&gt;
|Argument count (in 32-bits Words) or inline data (see below)&lt;br /&gt;
|-&lt;br /&gt;
|28?&lt;br /&gt;
|Hmm?&lt;br /&gt;
|-&lt;br /&gt;
|31-29&lt;br /&gt;
|[[#Submission_mode|Submission mode]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note: Methods are treated as 4-byte addressable locations, and hence their numbers are written down multiplied by 4.&lt;br /&gt;
&lt;br /&gt;
Note: The command&#039;s arguments, when present, follow the command word immediately.&lt;br /&gt;
&lt;br /&gt;
==== Submission mode ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Mode&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Offical name&lt;br /&gt;
|-&lt;br /&gt;
|0&lt;br /&gt;
|Increasing mode (old)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Increasing mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039;, while automatically incrementing the &#039;&#039;&#039;method&#039;&#039;&#039; value. This means that each argument will be written to a different method location.&lt;br /&gt;
|INCR&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Non-increasing mode (old)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Non-increasing mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039;. However, all arguments will be written to the same method location.&lt;br /&gt;
|NONINCR&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Inline mode - Tells PFIFO to read &#039;&#039;&#039;inline data&#039;&#039;&#039; from bits 28-16 of the command word, thus eliminating the need to pass additional words for the arguments.&lt;br /&gt;
|IMM&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|Increase-once mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039; and automatically increments the &#039;&#039;&#039;method&#039;&#039;&#039; value once only.&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== SetObject ===&lt;br /&gt;
&lt;br /&gt;
In order to bind an engine object to a specific subchannel, method 0 (SetObject) must be used first. The target subchannel is specified in bits 15-13 of the command word.&lt;br /&gt;
&lt;br /&gt;
After the engine object is bound to the desired subchannel, setting it&#039;s value in bits 15-13 of any subsequent command word will make PFIFO forward the command to the target engine.&lt;br /&gt;
&lt;br /&gt;
This method only takes one argument, an [[#Engine_IDs|Engine ID]].&lt;br /&gt;
&lt;br /&gt;
==== Engine IDs ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| ID&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Engine&lt;br /&gt;
|-&lt;br /&gt;
|0x902D&lt;br /&gt;
|FERMI_TWOD_A (2D)&lt;br /&gt;
|-&lt;br /&gt;
|0xB197&lt;br /&gt;
|MAXWELL_B (3D)&lt;br /&gt;
|-&lt;br /&gt;
|0xB1C0&lt;br /&gt;
|MAXWELL_COMPUTE_B&lt;br /&gt;
|-&lt;br /&gt;
|0xA140&lt;br /&gt;
|KEPLER_INLINE_TO_MEMORY_B&lt;br /&gt;
|-&lt;br /&gt;
|0xB0B5&lt;br /&gt;
|MAXWELL_DMA_COPY_A (DMA)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Macro ===&lt;br /&gt;
&lt;br /&gt;
Macros are small programs that can be uploaded to the gpu and are capable of reading and writing to the 3D engine registers on the GPU. The macros also accepts parameters, stored on a FIFO. Macros can be called using methods starting at 0xe00, where the first method triggers the macro execution, and the second one is used to push parameters to the FIFO, that can be read from the macro program using a instruction called &#039;&#039;parm&#039;&#039;. This instruction pops the FIFO and reads the next parameter, while also allowing programs to use a variable number of parameters if desired.&lt;br /&gt;
&lt;br /&gt;
The first parameter is written to 0xe00 + n * 2 (where n is the macro index), and all subsequent parameters should be pushed to the FIFO using 0xe01 + n * 2. The first parameter is placed at the general purpose register R1 in the macro program when execution starts.&lt;br /&gt;
&lt;br /&gt;
Official games uses those macros to conditionally write registers, one example of such uses is the macro at 0xe24, that is used to set shader registers (including shader address and binding the c1 Constant Buffer to the shader). In some cases, it&#039;s also used to set registers unconditionally.&lt;br /&gt;
&lt;br /&gt;
=== Fences ===&lt;br /&gt;
&lt;br /&gt;
Command lists can contain fences to ensure that commands are executed on the correct order, and subsequent commands are only sent when the previously sent commands were already processed by the GPU. Fences uses the ReportSemaphore* registers, and works like this:&lt;br /&gt;
&lt;br /&gt;
* First, register ReportSemaphoreOffset is set to High/Low 32 bits part of the 64-bits GPU Virtual Address where the fence is located. This GPU Virtual Address needs to be mapped to the process Virtual Address beforehand.&lt;br /&gt;
* Then, ReportSemaphorePayload is set with a sequential number. This number is basically a incrementing counter, so the first Command List can set ReportSemaphorePayload = 1, the next one to 2, then 3, 4... and so on.&lt;br /&gt;
* Finally, ReportSemaphoreControl is added and contains the mode and other unknown data.&lt;br /&gt;
&lt;br /&gt;
The above commands are added using the [[#Submission_mode|increasing mode]], since all those 4 registers are sequential.&lt;br /&gt;
&lt;br /&gt;
Official games sets Operation to 0 (Release), bit 4 to 1, bits 15-12 (Unit) to 0xF, and bit 28 to 1 (OneWord). The ReportSemaphorePayload value is then written by the GPU to the address pointed to by ReportSemaphoreOffset.&lt;br /&gt;
On the CPU side, the game code should wait until the value at the address pointed to by ReportSemaphoreOffset is &amp;gt;= to the last written value. Official code waits for this condition to be true on a loop, and won&#039;t send any further commands before that.&lt;br /&gt;
&lt;br /&gt;
== Vertex Data Submission ==&lt;br /&gt;
&lt;br /&gt;
Note: This is a observation on how the game Puyo Puyo Tetris sends textured squares to the GPU.&lt;br /&gt;
&lt;br /&gt;
# VERTEX_ATTRIB_FORMAT (0-15) are set (only the first 3 are really used, the rest are set float, with Size = 1 and offset at 0).&lt;br /&gt;
# VERTEX_ARRAY_FETCH (0) is set with the lower 12 bits set to 0x1c (Stride) and bit 12 to 1 (Enabled).&lt;br /&gt;
# VERTEX_ARRAY_START_HIGH/LOW (0) are set to the GPU Virtual Address where the Vertex Data is located.&lt;br /&gt;
# VERTEX_ARRAY_LIMIT_HIGH/LOW (0) are set to the GPU Virtual Address where the Vertex Data is located, plus the Vertex Data size in bytes minus 1.&lt;br /&gt;
# VERTEX_BEGIN_GL is used with the primitive type set to TRIANGLE_STRIP.&lt;br /&gt;
# VERTEX_BUFFER_FIRST with value 0 (indicating the index of the first primitive to render?).&lt;br /&gt;
# VERTEX_BUFFER_COUNT is set to 4, because the Vertex Buffer with the square has 4 vertices.&lt;br /&gt;
# VERTEX_END_GL is used with value 0 (currently unknown what this value means).&lt;br /&gt;
&lt;br /&gt;
== Texture View ==&lt;br /&gt;
&lt;br /&gt;
Texture information such as address, format and size is sent to the GPU through a structure know as Texture View (a.k.a. Texture Image Control, or TIC). Each texture that the game uses needs a separate TIC, and those TICs are written to a table, one after the other. Each [[#TIC_Structure|TIC entry]] has 0x20 bytes, and is composed of 8 32-bits words where the texture information is packed.&lt;br /&gt;
&lt;br /&gt;
The index of the TIC entries that should be used by the shader is sent to the GPU with the CB_POS/CB_DATA (0) methods. Games usually follows the following steps to write the TIC entry indexes:&lt;br /&gt;
&lt;br /&gt;
* Macro 0xe1a is used to set CB_ADDRESS_HIGH/LOW registers to the GPU Virtual Address of the Constant Buffer set on the register 0x982 (the &#039;&#039;Texture Constant Buffer&#039;&#039; index register), and also sets CB_SIZE.&lt;br /&gt;
* CB_POS is used to set the write offset of the Constant Buffer to n * 4, where &#039;&#039;n&#039;&#039; is the index of the &#039;&#039;Handle&#039;&#039; being used on the shader program (this index starts at 8, so CB_POS should be at least 8 * 4 = 0x20).&lt;br /&gt;
* CB_DATA (0) method is used to write the value into the Constant Buffer. The value is a &#039;&#039;Handle&#039;&#039; where the lower 20 bits is the TIC index, and the higher 12 bits is the TSC (Texture Sampler Control) index.&lt;br /&gt;
&lt;br /&gt;
The address of a given TIC entry can be calculates as:&lt;br /&gt;
&lt;br /&gt;
 tic_entry_address = tic_base_address + tic_index * 0x20&lt;br /&gt;
&lt;br /&gt;
Where &#039;&#039;tic_base_address&#039;&#039; is the address written to TIC_ADDRESS_HIGH/LOW (methods 0x1574 and 0x1578), &#039;&#039;tic_index&#039;&#039; is the lower 20 bits of the word written into the Const Buffer with CB_DATA (0), and 0x20 is the size of each TIC entry in bytes.&lt;br /&gt;
&lt;br /&gt;
The texture is accessed on the shader using one of the texture sampling instructions (usually the TEXS instruction). One of the parameters for this instruction is the &#039;&#039;Handle&#039;&#039; index. This index start at 8, so the index 8 will access the handle at 8 * 4 = 0x20 on the &#039;&#039;Texture Constant Buffer&#039;&#039;. Each shader stage has a separate Constant Buffer, so for fragment shaders, this is located at CB_ADDRESS + 4 * CB_SIZE + TEXS_index * 4 (where the first 4 is the index of the fragment shader stage, and the second 4 is the size of a word, 4 bytes).&lt;br /&gt;
&lt;br /&gt;
=== TIC Structure ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Word || Bits || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 6-0 || [[GPU_Texture_Formats#Texture_Formats|Texture Format]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 9-7 || [[#Channel_Data_Type|R Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 12-10 || [[#Channel_Data_Type|G Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 15-13 || [[#Channel_Data_Type|B Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 18-16 || [[#Channel_Data_Type|A Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 31-0 || Lower 32-bits of the Texture GPU Virtual Address&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 15-0 || Higher 16-bits of the Texture GPU Virtual Address&lt;br /&gt;
|-&lt;br /&gt;
| 4 || 15-0 || Texture Width minus 1&lt;br /&gt;
|-&lt;br /&gt;
| 5 || 15-0 || Texture Height minus 1&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Channel Data Type ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Type&lt;br /&gt;
|-&lt;br /&gt;
| 1 || SNORM&lt;br /&gt;
|-&lt;br /&gt;
| 2 || UNORM&lt;br /&gt;
|-&lt;br /&gt;
| 3 || SINT&lt;br /&gt;
|-&lt;br /&gt;
| 4 || UINT&lt;br /&gt;
|-&lt;br /&gt;
| 5 || SNORM_FORCE_FP16&lt;br /&gt;
|-&lt;br /&gt;
| 6 || UNORM_FORCE_FP16&lt;br /&gt;
|-&lt;br /&gt;
| 7 || FLOAT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
FIFO engine overview:&lt;br /&gt;
[https://envytools.readthedocs.io/en/latest/hw/fifo/intro.html]&lt;br /&gt;
&lt;br /&gt;
Method values from the Fermi family GPU (a bit older than the Tegra X1, but values seems to be mostly the same):&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/gf100_3d.xml]&lt;br /&gt;
&lt;br /&gt;
TIC structure used on a Maxwell GPU:&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/gm200_texture.xml]&lt;br /&gt;
&lt;br /&gt;
Values for some types used on the above XML:&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/nv_3ddefs.xml]&lt;br /&gt;
&lt;br /&gt;
Command word packing code used on Mesa3d:&lt;br /&gt;
[https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nvc0/nvc0_winsys.h]&lt;br /&gt;
&lt;br /&gt;
TIC entry pack/write code used on Mesa3d:&lt;br /&gt;
[https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c#n65]&lt;/div&gt;</summary>
		<author><name>Gdkchan</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=GPU&amp;diff=4414</id>
		<title>GPU</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=GPU&amp;diff=4414"/>
		<updated>2018-04-01T20:03:15Z</updated>

		<summary type="html">&lt;p&gt;Gdkchan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Mapping Memory ==&lt;br /&gt;
&lt;br /&gt;
First, to map a memory region on the GPU Address Space, caching needs to be disabled by using [[SVC#svcSetMemoryAttribute|svcSetMemoryAttribute]]. The Address passed is the Virtual Address of the region that will be mapped, the size is the region size, and State0/1 are both set to 8 to disable caching of the memory region. This is done to ensure that the GPU can actually &amp;quot;see&amp;quot; the data written there, and it doesn&#039;t get stuck on some cache.&lt;br /&gt;
&lt;br /&gt;
Then, [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]] is used to create a nvmap object with the desired size. After, [[NV_services#NVMAP_IOC_ALLOC|NVMAP_IOC_ALLOC]] is used to allocate the memory on the GPU Address Space, and map data on the process Address Space into the GPU Address Space, by passing the Virtual Address as the input addr parameter, and also the Handle returned from [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]]. Lastly, the actual mapping is done by using [[NV_services#NVGPU_AS_IOCTL_MAP_BUFFER_EX|NVGPU_AS_IOCTL_MAP_BUFFER_EX]], and the GPU Virtual Address is returned on the offset parameter. It&#039;s also possible to manually set the offset where the mapping should be made on the GPU Address Space, by passing the address on the &amp;quot;offset&amp;quot; parameter, and setting the bit 0 of the flags parameter to 1. However, for this to work, the desired GPU Virtual Address needs to be previously reserved using [[NV_services#NVGPU_AS_IOCTL_ALLOC_SPACE|NVGPU_AS_IOCTL_ALLOC_SPACE]].&lt;br /&gt;
&lt;br /&gt;
The above process is used to map all data that will be used by the GPU, like Textures, Command Lists (a.k.a. Push Buffers), Vertex/Index buffers and Shaders. They usually have their own mapping, but Command Lists can share the same mapping.&lt;br /&gt;
&lt;br /&gt;
== FIFO Commands ==&lt;br /&gt;
&lt;br /&gt;
The GPU implements a variation of Tegra&#039;s push buffer format for it&#039;s PFIFO engine. PFIFO is a special engine responsible for receiving user command lists and routing them to the appropriate engines (2D, 3D, DMA).&lt;br /&gt;
&lt;br /&gt;
Commands are submitted to the GPU&#039;s PFIFO engine through [[NV_services#NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO|NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO]].&lt;br /&gt;
&lt;br /&gt;
This ioctl takes an array of gpfifo entries where each entry points to a FIFO command list. This list is composed of alternating 32-bit words containing FIFO commands and their respective arguments.&lt;br /&gt;
&lt;br /&gt;
See the [[GPU|GPU]] page for a list of commands, with the register addresses and their descriptions.&lt;br /&gt;
&lt;br /&gt;
=== Command Structure ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Bits&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|12-0&lt;br /&gt;
|Method&lt;br /&gt;
|-&lt;br /&gt;
|15-13&lt;br /&gt;
|Subchannel&lt;br /&gt;
|-&lt;br /&gt;
|27-16&lt;br /&gt;
|Argument count (in 32-bits Words) or inline data (see below)&lt;br /&gt;
|-&lt;br /&gt;
|28?&lt;br /&gt;
|Hmm?&lt;br /&gt;
|-&lt;br /&gt;
|31-29&lt;br /&gt;
|[[#Submission_mode|Submission mode]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note: Methods are treated as 4-byte addressable locations, and hence their numbers are written down multiplied by 4.&lt;br /&gt;
&lt;br /&gt;
Note: The command&#039;s arguments, when present, follow the command word immediately.&lt;br /&gt;
&lt;br /&gt;
==== Submission mode ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Mode&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Offical name&lt;br /&gt;
|-&lt;br /&gt;
|0&lt;br /&gt;
|Increasing mode (old)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Increasing mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039;, while automatically incrementing the &#039;&#039;&#039;method&#039;&#039;&#039; value. This means that each argument will be written to a different method location.&lt;br /&gt;
|INCR&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Non-increasing mode (old)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Non-increasing mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039;. However, all arguments will be written to the same method location.&lt;br /&gt;
|NONINCR&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Inline mode - Tells PFIFO to read &#039;&#039;&#039;inline data&#039;&#039;&#039; from bits 28-16 of the command word, thus eliminating the need to pass additional words for the arguments.&lt;br /&gt;
|IMM&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|Increase-once mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039; and automatically increments the &#039;&#039;&#039;method&#039;&#039;&#039; value once only.&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== SetObject ===&lt;br /&gt;
&lt;br /&gt;
In order to bind an engine object to a specific subchannel, method 0 (SetObject) must be used first. The target subchannel is specified in bits 15-13 of the command word.&lt;br /&gt;
&lt;br /&gt;
After the engine object is bound to the desired subchannel, setting it&#039;s value in bits 15-13 of any subsequent command word will make PFIFO forward the command to the target engine.&lt;br /&gt;
&lt;br /&gt;
This method only takes one argument, an [[#Engine_IDs|Engine ID]].&lt;br /&gt;
&lt;br /&gt;
==== Engine IDs ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| ID&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Engine&lt;br /&gt;
|-&lt;br /&gt;
|0x902D&lt;br /&gt;
|FERMI_TWOD_A (2D)&lt;br /&gt;
|-&lt;br /&gt;
|0xB197&lt;br /&gt;
|MAXWELL_B (3D)&lt;br /&gt;
|-&lt;br /&gt;
|0xB1C0&lt;br /&gt;
|MAXWELL_COMPUTE_B&lt;br /&gt;
|-&lt;br /&gt;
|0xA140&lt;br /&gt;
|KEPLER_INLINE_TO_MEMORY_B&lt;br /&gt;
|-&lt;br /&gt;
|0xB0B5&lt;br /&gt;
|MAXWELL_DMA_COPY_A (DMA)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Macro ===&lt;br /&gt;
&lt;br /&gt;
Macros are small programs that can be uploaded to the gpu and are capable of reading and writing to the 3D engine registers on the GPU. The macros also accepts parameters, stored on a FIFO. Macros can be called using methods starting at 0xe00, where the first method triggers the macro execution, and the second one is used to push parameters to the FIFO, that can be read from the macro program using a instruction called &#039;&#039;parm&#039;&#039;. This instruction pops the FIFO and reads the next parameter, while also allowing programs to use a variable number of parameters if desired.&lt;br /&gt;
&lt;br /&gt;
The first parameter is written to 0xe00 + n * 2 (where n is the macro index), and all subsequent parameters should be pushed to the FIFO using 0xe01 + n * 2. The first parameter is placed at the general purpose register R1 in the macro program when execution starts.&lt;br /&gt;
&lt;br /&gt;
Official games uses those macros to conditionally write registers, one example of such uses is the macro at 0xe24, that is used to set shader registers (including shader address and binding the c1 Constant Buffer to the shader). In some cases, it&#039;s also used to set registers unconditionally.&lt;br /&gt;
&lt;br /&gt;
=== Fences ===&lt;br /&gt;
&lt;br /&gt;
Command lists can contain fences to ensure that commands are executed on the correct order, and subsequent commands are only sent when the previously sent commands were already processed by the GPU. Fences uses the QUERY_* commands, and works like this:&lt;br /&gt;
&lt;br /&gt;
* First, register ReportSemaphoreOffset is set to High/Low 32 bits part of the 64-bits GPU Virtual Address where the fence is located. This GPU Virtual Address needs to be mapped to the process Virtual Address beforehand.&lt;br /&gt;
* Then, ReportSemaphorePayload is set with a sequential number. This number is basically a incrementing counter, so the first Command List can set ReportSemaphorePayload = 1, the next one to 2, then 3, 4... and so on.&lt;br /&gt;
* Finally, ReportSemaphoreControl is added and contains the mode and other unknown data.&lt;br /&gt;
&lt;br /&gt;
The above commands are added using the [[#Submission_mode|increasing mode]], since all those 4 registers are sequential.&lt;br /&gt;
&lt;br /&gt;
Official games sets Operation to 0 (Release), bit 4 to 1, bits 15-12 (Unit) to 0xF, and bit 28 to 1 (OneWord). The ReportSemaphorePayload value is then written by the GPU to the address pointed to by ReportSemaphoreOffset.&lt;br /&gt;
On the CPU side, the game code should wait until the value at the address pointed to by ReportSemaphoreOffset is &amp;gt;= to the last written value. Official code waits for this condition to be true on a loop, and won&#039;t send any further commands before that.&lt;br /&gt;
&lt;br /&gt;
== Vertex Data Submission ==&lt;br /&gt;
&lt;br /&gt;
Note: This is a observation on how the game Puyo Puyo Tetris sends textured squares to the GPU.&lt;br /&gt;
&lt;br /&gt;
# VERTEX_ATTRIB_FORMAT (0-15) are set (only the first 3 are really used, the rest are set float, with Size = 1 and offset at 0).&lt;br /&gt;
# VERTEX_ARRAY_FETCH (0) is set with the lower 12 bits set to 0x1c (Stride) and bit 12 to 1 (Enabled).&lt;br /&gt;
# VERTEX_ARRAY_START_HIGH/LOW (0) are set to the GPU Virtual Address where the Vertex Data is located.&lt;br /&gt;
# VERTEX_ARRAY_LIMIT_HIGH/LOW (0) are set to the GPU Virtual Address where the Vertex Data is located, plus the Vertex Data size in bytes minus 1.&lt;br /&gt;
# VERTEX_BEGIN_GL is used with the primitive type set to TRIANGLE_STRIP.&lt;br /&gt;
# VERTEX_BUFFER_FIRST with value 0 (indicating the index of the first primitive to render?).&lt;br /&gt;
# VERTEX_BUFFER_COUNT is set to 4, because the Vertex Buffer with the square has 4 vertices.&lt;br /&gt;
# VERTEX_END_GL is used with value 0 (currently unknown what this value means).&lt;br /&gt;
&lt;br /&gt;
== Texture View ==&lt;br /&gt;
&lt;br /&gt;
Texture information such as address, format and size is sent to the GPU through a structure know as Texture View (a.k.a. Texture Image Control, or TIC). Each texture that the game uses needs a separate TIC, and those TICs are written to a table, one after the other. Each [[#TIC_Structure|TIC entry]] has 0x20 bytes, and is composed of 8 32-bits words where the texture information is packed.&lt;br /&gt;
&lt;br /&gt;
The index of the TIC entries that should be used by the shader is sent to the GPU with the CB_POS/CB_DATA (0) methods. Games usually follows the following steps to write the TIC entry indexes:&lt;br /&gt;
&lt;br /&gt;
* Macro 0xe1a is used to set CB_ADDRESS_HIGH/LOW registers to the GPU Virtual Address of the Constant Buffer set on the register 0x982 (the &#039;&#039;Texture Constant Buffer&#039;&#039; index register), and also sets CB_SIZE.&lt;br /&gt;
* CB_POS is used to set the write offset of the Constant Buffer to n * 4, where &#039;&#039;n&#039;&#039; is the index of the &#039;&#039;Handle&#039;&#039; being used on the shader program (this index starts at 8, so CB_POS should be at least 8 * 4 = 0x20).&lt;br /&gt;
* CB_DATA (0) method is used to write the value into the Constant Buffer. The value is a &#039;&#039;Handle&#039;&#039; where the lower 20 bits is the TIC index, and the higher 12 bits is the TSC (Texture Sampler Control) index.&lt;br /&gt;
&lt;br /&gt;
The address of a given TIC entry can be calculates as:&lt;br /&gt;
&lt;br /&gt;
 tic_entry_address = tic_base_address + tic_index * 0x20&lt;br /&gt;
&lt;br /&gt;
Where &#039;&#039;tic_base_address&#039;&#039; is the address written to TIC_ADDRESS_HIGH/LOW (methods 0x1574 and 0x1578), &#039;&#039;tic_index&#039;&#039; is the lower 20 bits of the word written into the Const Buffer with CB_DATA (0), and 0x20 is the size of each TIC entry in bytes.&lt;br /&gt;
&lt;br /&gt;
The texture is accessed on the shader using one of the texture sampling instructions (usually the TEXS instruction). One of the parameters for this instruction is the &#039;&#039;Handle&#039;&#039; index. This index start at 8, so the index 8 will access the handle at 8 * 4 = 0x20 on the &#039;&#039;Texture Constant Buffer&#039;&#039;. Each shader stage has a separate Constant Buffer, so for fragment shaders, this is located at CB_ADDRESS + 4 * CB_SIZE + TEXS_index * 4 (where the first 4 is the index of the fragment shader stage, and the second 4 is the size of a word, 4 bytes).&lt;br /&gt;
&lt;br /&gt;
=== TIC Structure ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Word || Bits || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 6-0 || [[GPU_Texture_Formats#Texture_Formats|Texture Format]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 9-7 || [[#Channel_Data_Type|R Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 12-10 || [[#Channel_Data_Type|G Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 15-13 || [[#Channel_Data_Type|B Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 18-16 || [[#Channel_Data_Type|A Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 31-0 || Lower 32-bits of the Texture GPU Virtual Address&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 15-0 || Higher 16-bits of the Texture GPU Virtual Address&lt;br /&gt;
|-&lt;br /&gt;
| 4 || 15-0 || Texture Width minus 1&lt;br /&gt;
|-&lt;br /&gt;
| 5 || 15-0 || Texture Height minus 1&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Channel Data Type ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Type&lt;br /&gt;
|-&lt;br /&gt;
| 1 || SNORM&lt;br /&gt;
|-&lt;br /&gt;
| 2 || UNORM&lt;br /&gt;
|-&lt;br /&gt;
| 3 || SINT&lt;br /&gt;
|-&lt;br /&gt;
| 4 || UINT&lt;br /&gt;
|-&lt;br /&gt;
| 5 || SNORM_FORCE_FP16&lt;br /&gt;
|-&lt;br /&gt;
| 6 || UNORM_FORCE_FP16&lt;br /&gt;
|-&lt;br /&gt;
| 7 || FLOAT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
FIFO engine overview:&lt;br /&gt;
[https://envytools.readthedocs.io/en/latest/hw/fifo/intro.html]&lt;br /&gt;
&lt;br /&gt;
Method values from the Fermi family GPU (a bit older than the Tegra X1, but values seems to be mostly the same):&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/gf100_3d.xml]&lt;br /&gt;
&lt;br /&gt;
TIC structure used on a Maxwell GPU:&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/gm200_texture.xml]&lt;br /&gt;
&lt;br /&gt;
Values for some types used on the above XML:&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/nv_3ddefs.xml]&lt;br /&gt;
&lt;br /&gt;
Command word packing code used on Mesa3d:&lt;br /&gt;
[https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nvc0/nvc0_winsys.h]&lt;br /&gt;
&lt;br /&gt;
TIC entry pack/write code used on Mesa3d:&lt;br /&gt;
[https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c#n65]&lt;/div&gt;</summary>
		<author><name>Gdkchan</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=GPU&amp;diff=4413</id>
		<title>GPU</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=GPU&amp;diff=4413"/>
		<updated>2018-04-01T19:58:22Z</updated>

		<summary type="html">&lt;p&gt;Gdkchan: Remove command lists, since we now have a better, more complete page for the commands, also change the names to use official names instead the ones from nouveau.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Mapping Memory ==&lt;br /&gt;
&lt;br /&gt;
First, to map a memory region on the GPU Address Space, caching needs to be disabled by using [[SVC#svcSetMemoryAttribute|svcSetMemoryAttribute]]. The Address passed is the Virtual Address of the region that will be mapped, the size is the region size, and State0/1 are both set to 8 to disable caching of the memory region. This is done to ensure that the GPU can actually &amp;quot;see&amp;quot; the data written there, and it doesn&#039;t get stuck on some cache.&lt;br /&gt;
&lt;br /&gt;
Then, [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]] is used to create a nvmap object with the desired size. After, [[NV_services#NVMAP_IOC_ALLOC|NVMAP_IOC_ALLOC]] is used to allocate the memory on the GPU Address Space, and map data on the process Address Space into the GPU Address Space, by passing the Virtual Address as the input addr parameter, and also the Handle returned from [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]]. Lastly, the actual mapping is done by using [[NV_services#NVGPU_AS_IOCTL_MAP_BUFFER_EX|NVGPU_AS_IOCTL_MAP_BUFFER_EX]], and the GPU Virtual Address is returned on the offset parameter. It&#039;s also possible to manually set the offset where the mapping should be made on the GPU Address Space, by passing the address on the &amp;quot;offset&amp;quot; parameter, and setting the bit 0 of the flags parameter to 1. However, for this to work, the desired GPU Virtual Address needs to be previously reserved using [[NV_services#NVGPU_AS_IOCTL_ALLOC_SPACE|NVGPU_AS_IOCTL_ALLOC_SPACE]].&lt;br /&gt;
&lt;br /&gt;
The above process is used to map all data that will be used by the GPU, like Textures, Command Lists (a.k.a. Push Buffers), Vertex/Index buffers and Shaders. They usually have their own mapping, but Command Lists can share the same mapping.&lt;br /&gt;
&lt;br /&gt;
== FIFO Commands ==&lt;br /&gt;
&lt;br /&gt;
The GPU implements a variation of Tegra&#039;s push buffer format for it&#039;s PFIFO engine. PFIFO is a special engine responsible for receiving user command lists and routing them to the appropriate engines (2D, 3D, DMA).&lt;br /&gt;
&lt;br /&gt;
Commands are submitted to the GPU&#039;s PFIFO engine through [[NV_services#NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO|NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO]].&lt;br /&gt;
&lt;br /&gt;
This ioctl takes an array of gpfifo entries where each entry points to a FIFO command list. This list is composed of alternating 32-bit words containing FIFO commands and their respective arguments.&lt;br /&gt;
&lt;br /&gt;
See the [[GPU|GPU]] page for a list of commands, with the register addresses and their descriptions.&lt;br /&gt;
&lt;br /&gt;
=== Command Structure ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Bits&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|12-0&lt;br /&gt;
|Method&lt;br /&gt;
|-&lt;br /&gt;
|15-13&lt;br /&gt;
|Subchannel&lt;br /&gt;
|-&lt;br /&gt;
|27-16&lt;br /&gt;
|Argument count (in 32-bits Words) or inline data (see below)&lt;br /&gt;
|-&lt;br /&gt;
|28?&lt;br /&gt;
|Hmm?&lt;br /&gt;
|-&lt;br /&gt;
|31-29&lt;br /&gt;
|[[#Submission_mode|Submission mode]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note: Methods are treated as 4-byte addressable locations, and hence their numbers are written down multiplied by 4.&lt;br /&gt;
&lt;br /&gt;
Note: The command&#039;s arguments, when present, follow the command word immediately.&lt;br /&gt;
&lt;br /&gt;
==== Submission mode ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Mode&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Offical name&lt;br /&gt;
|-&lt;br /&gt;
|0&lt;br /&gt;
|Increasing mode (old)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Increasing mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039;, while automatically incrementing the &#039;&#039;&#039;method&#039;&#039;&#039; value. This means that each argument will be written to a different method location.&lt;br /&gt;
|INCR&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Non-increasing mode (old)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Non-increasing mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039;. However, all arguments will be written to the same method location.&lt;br /&gt;
|NONINCR&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Inline mode - Tells PFIFO to read &#039;&#039;&#039;inline data&#039;&#039;&#039; from bits 28-16 of the command word, thus eliminating the need to pass additional words for the arguments.&lt;br /&gt;
|IMM&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|Increase-once mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039; and automatically increments the &#039;&#039;&#039;method&#039;&#039;&#039; value once only.&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== SetObject ===&lt;br /&gt;
&lt;br /&gt;
In order to bind an engine object to a specific subchannel, method 0 (SetObject) must be used first. The target subchannel is specified in bits 15-13 of the command word.&lt;br /&gt;
&lt;br /&gt;
After the engine object is bound to the desired subchannel, setting it&#039;s value in bits 15-13 of any subsequent command word will make PFIFO forward the command to the target engine.&lt;br /&gt;
&lt;br /&gt;
This method only takes one argument, an [[#Engine_IDs|Engine ID]].&lt;br /&gt;
&lt;br /&gt;
==== Engine IDs ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| ID&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Engine&lt;br /&gt;
|-&lt;br /&gt;
|0x902D&lt;br /&gt;
|FERMI_TWOD_A (2D)&lt;br /&gt;
|-&lt;br /&gt;
|0xB197&lt;br /&gt;
|MAXWELL_B (3D)&lt;br /&gt;
|-&lt;br /&gt;
|0xB1C0&lt;br /&gt;
|MAXWELL_COMPUTE_B&lt;br /&gt;
|-&lt;br /&gt;
|0xA140&lt;br /&gt;
|KEPLER_INLINE_TO_MEMORY_B&lt;br /&gt;
|-&lt;br /&gt;
|0xB0B5&lt;br /&gt;
|MAXWELL_DMA_COPY_A (DMA)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Macro ===&lt;br /&gt;
&lt;br /&gt;
Macros are small programs that can be uploaded to the gpu and are capable of reading and writing to the 3D engine registers on the GPU. The macros also accepts parameters, stored on a FIFO. Macros can be called using methods starting at 0xe00, where the first method triggers the macro execution, and the second one is used to push parameters to the FIFO, that can be read from the macro program using a instruction called &#039;&#039;parm&#039;&#039;. This instruction pops the FIFO and reads the next parameter, while also allowing programs to use a variable number of parameters if desired.&lt;br /&gt;
&lt;br /&gt;
The first parameter is written to 0xe00 + n * 2 (where n is the macro index), and all subsequent parameters should be pushed to the FIFO using 0xe01 + n * 2. The first parameter is placed at the general purpose register R1 in the macro program when execution starts.&lt;br /&gt;
&lt;br /&gt;
Official games uses those macros to conditionally write registers, one example of such uses is the macro at 0xe24, that is used to set shader registers (including shader address and binding the c1 Constant Buffer to the shader). In some cases, it&#039;s also used to set registers unconditionally.&lt;br /&gt;
&lt;br /&gt;
=== Fences ===&lt;br /&gt;
&lt;br /&gt;
Command lists can contain fences to ensure that commands are executed on the correct order, and subsequent commands are only sent when the previously sent commands were already processed by the GPU. Fences uses the QUERY_* commands, and works like this:&lt;br /&gt;
&lt;br /&gt;
* First, register ReportSemaphoreOffset is set to High/Low 32 bits part of the 64-bits GPU Virtual Address where the fence is located. This GPU Virtual Address needs to be mapped to the process Virtual Address beforehand.&lt;br /&gt;
* Then, ReportSemaphorePayload is set with a sequential number. This number is basically a incrementing counter, so the first Command List can set ReportSemaphorePayload = 1, the next one to 2, then 3, 4... and so on.&lt;br /&gt;
* Finally, ReportSemaphoreControl is added and contains the mode and other unknown data.&lt;br /&gt;
&lt;br /&gt;
The above commands are added using the [[#Submission_mode|increasing mode]], since all those 4 registers are sequential.&lt;br /&gt;
&lt;br /&gt;
Official games will sets Operation to 0 (Release), bit 4 to 1, bits 15-12 (Unit) to 0xF, and bit 28 to 1 (OneWord). The ReportSemaphorePayload value is then written by the GPU to the address pointed to by ReportSemaphoreOffset.&lt;br /&gt;
On the CPU side, the game code should wait until the value at the address pointed to by ReportSemaphoreOffset is &amp;gt;= to the last written value. Official code waits for this condition to be true on a loop, and won&#039;t send any further commands before that.&lt;br /&gt;
&lt;br /&gt;
== Vertex Data Submission ==&lt;br /&gt;
&lt;br /&gt;
Note: This is a observation on how the game Puyo Puyo Tetris sends textured squares to the GPU.&lt;br /&gt;
&lt;br /&gt;
# VERTEX_ATTRIB_FORMAT (0-15) are set (only the first 3 are really used, the rest are set float, with Size = 1 and offset at 0).&lt;br /&gt;
# VERTEX_ARRAY_FETCH (0) is set with the lower 12 bits set to 0x1c (Stride) and bit 12 to 1 (Enabled).&lt;br /&gt;
# VERTEX_ARRAY_START_HIGH/LOW (0) are set to the GPU Virtual Address where the Vertex Data is located.&lt;br /&gt;
# VERTEX_ARRAY_LIMIT_HIGH/LOW (0) are set to the GPU Virtual Address where the Vertex Data is located, plus the Vertex Data size in bytes minus 1.&lt;br /&gt;
# VERTEX_BEGIN_GL is used with the primitive type set to TRIANGLE_STRIP.&lt;br /&gt;
# VERTEX_BUFFER_FIRST with value 0 (indicating the index of the first primitive to render?).&lt;br /&gt;
# VERTEX_BUFFER_COUNT is set to 4, because the Vertex Buffer with the square has 4 vertices.&lt;br /&gt;
# VERTEX_END_GL is used with value 0 (currently unknown what this value means).&lt;br /&gt;
&lt;br /&gt;
== Texture View ==&lt;br /&gt;
&lt;br /&gt;
Texture information such as address, format and size is sent to the GPU through a structure know as Texture View (a.k.a. Texture Image Control, or TIC). Each texture that the game uses needs a separate TIC, and those TICs are written to a table, one after the other. Each [[#TIC_Structure|TIC entry]] has 0x20 bytes, and is composed of 8 32-bits words where the texture information is packed.&lt;br /&gt;
&lt;br /&gt;
The index of the TIC entries that should be used by the shader is sent to the GPU with the CB_POS/CB_DATA (0) methods. Games usually follows the following steps to write the TIC entry indexes:&lt;br /&gt;
&lt;br /&gt;
* Macro 0xe1a is used to set CB_ADDRESS_HIGH/LOW registers to the GPU Virtual Address of the Constant Buffer set on the register 0x982 (the &#039;&#039;Texture Constant Buffer&#039;&#039; index register), and also sets CB_SIZE.&lt;br /&gt;
* CB_POS is used to set the write offset of the Constant Buffer to n * 4, where &#039;&#039;n&#039;&#039; is the index of the &#039;&#039;Handle&#039;&#039; being used on the shader program (this index starts at 8, so CB_POS should be at least 8 * 4 = 0x20).&lt;br /&gt;
* CB_DATA (0) method is used to write the value into the Constant Buffer. The value is a &#039;&#039;Handle&#039;&#039; where the lower 20 bits is the TIC index, and the higher 12 bits is the TSC (Texture Sampler Control) index.&lt;br /&gt;
&lt;br /&gt;
The address of a given TIC entry can be calculates as:&lt;br /&gt;
&lt;br /&gt;
 tic_entry_address = tic_base_address + tic_index * 0x20&lt;br /&gt;
&lt;br /&gt;
Where &#039;&#039;tic_base_address&#039;&#039; is the address written to TIC_ADDRESS_HIGH/LOW (methods 0x1574 and 0x1578), &#039;&#039;tic_index&#039;&#039; is the lower 20 bits of the word written into the Const Buffer with CB_DATA (0), and 0x20 is the size of each TIC entry in bytes.&lt;br /&gt;
&lt;br /&gt;
The texture is accessed on the shader using one of the texture sampling instructions (usually the TEXS instruction). One of the parameters for this instruction is the &#039;&#039;Handle&#039;&#039; index. This index start at 8, so the index 8 will access the handle at 8 * 4 = 0x20 on the &#039;&#039;Texture Constant Buffer&#039;&#039;. Each shader stage has a separate Constant Buffer, so for fragment shaders, this is located at CB_ADDRESS + 4 * CB_SIZE + TEXS_index * 4 (where the first 4 is the index of the fragment shader stage, and the second 4 is the size of a word, 4 bytes).&lt;br /&gt;
&lt;br /&gt;
=== TIC Structure ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Word || Bits || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 6-0 || [[GPU_Texture_Formats#Texture_Formats|Texture Format]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 9-7 || [[#Channel_Data_Type|R Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 12-10 || [[#Channel_Data_Type|G Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 15-13 || [[#Channel_Data_Type|B Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 18-16 || [[#Channel_Data_Type|A Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 31-0 || Lower 32-bits of the Texture GPU Virtual Address&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 15-0 || Higher 16-bits of the Texture GPU Virtual Address&lt;br /&gt;
|-&lt;br /&gt;
| 4 || 15-0 || Texture Width minus 1&lt;br /&gt;
|-&lt;br /&gt;
| 5 || 15-0 || Texture Height minus 1&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Channel Data Type ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Type&lt;br /&gt;
|-&lt;br /&gt;
| 1 || SNORM&lt;br /&gt;
|-&lt;br /&gt;
| 2 || UNORM&lt;br /&gt;
|-&lt;br /&gt;
| 3 || SINT&lt;br /&gt;
|-&lt;br /&gt;
| 4 || UINT&lt;br /&gt;
|-&lt;br /&gt;
| 5 || SNORM_FORCE_FP16&lt;br /&gt;
|-&lt;br /&gt;
| 6 || UNORM_FORCE_FP16&lt;br /&gt;
|-&lt;br /&gt;
| 7 || FLOAT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
FIFO engine overview:&lt;br /&gt;
[https://envytools.readthedocs.io/en/latest/hw/fifo/intro.html]&lt;br /&gt;
&lt;br /&gt;
Method values from the Fermi family GPU (a bit older than the Tegra X1, but values seems to be mostly the same):&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/gf100_3d.xml]&lt;br /&gt;
&lt;br /&gt;
TIC structure used on a Maxwell GPU:&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/gm200_texture.xml]&lt;br /&gt;
&lt;br /&gt;
Values for some types used on the above XML:&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/nv_3ddefs.xml]&lt;br /&gt;
&lt;br /&gt;
Command word packing code used on Mesa3d:&lt;br /&gt;
[https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nvc0/nvc0_winsys.h]&lt;br /&gt;
&lt;br /&gt;
TIC entry pack/write code used on Mesa3d:&lt;br /&gt;
[https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c#n65]&lt;/div&gt;</summary>
		<author><name>Gdkchan</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=GPU&amp;diff=4411</id>
		<title>GPU</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=GPU&amp;diff=4411"/>
		<updated>2018-04-01T19:33:54Z</updated>

		<summary type="html">&lt;p&gt;Gdkchan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Mapping Memory ==&lt;br /&gt;
&lt;br /&gt;
First, to map a memory region on the GPU Address Space, caching needs to be disabled by using [[SVC#svcSetMemoryAttribute|svcSetMemoryAttribute]]. The Address passed is the Virtual Address of the region that will be mapped, the size is the region size, and State0/1 are both set to 8 to disable caching of the memory region. This is done to ensure that the GPU can actually &amp;quot;see&amp;quot; the data written there, and it doesn&#039;t get stuck on some cache.&lt;br /&gt;
&lt;br /&gt;
Then, [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]] is used to create a nvmap object with the desired size. After, [[NV_services#NVMAP_IOC_ALLOC|NVMAP_IOC_ALLOC]] is used to allocate the memory on the GPU Address Space, and map data on the process Address Space into the GPU Address Space, by passing the Virtual Address as the input addr parameter, and also the Handle returned from [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]]. Lastly, the actual mapping is done by using [[NV_services#NVGPU_AS_IOCTL_MAP_BUFFER_EX|NVGPU_AS_IOCTL_MAP_BUFFER_EX]], and the GPU Virtual Address is returned on the offset parameter. It&#039;s also possible to manually set the offset where the mapping should be made on the GPU Address Space, by passing the address on the &amp;quot;offset&amp;quot; parameter, and setting the bit 0 of the flags parameter to 1. However, for this to work, the desired GPU Virtual Address needs to be previously reserved using [[NV_services#NVGPU_AS_IOCTL_ALLOC_SPACE|NVGPU_AS_IOCTL_ALLOC_SPACE]].&lt;br /&gt;
&lt;br /&gt;
The above process is used to map all data that will be used by the GPU, like Textures, Command Lists (a.k.a. Push Buffers), Vertex/Index buffers and Shaders. They usually have their own mapping, but Command Lists can share the same mapping.&lt;br /&gt;
&lt;br /&gt;
== FIFO Commands ==&lt;br /&gt;
&lt;br /&gt;
The GPU implements a variation of Tegra&#039;s push buffer format for it&#039;s PFIFO engine. PFIFO is a special engine responsible for receiving user command lists and routing them to the appropriate engines (2D, 3D, DMA).&lt;br /&gt;
&lt;br /&gt;
Commands are submitted to the GPU&#039;s PFIFO engine through [[NV_services#NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO|NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO]].&lt;br /&gt;
&lt;br /&gt;
This ioctl takes an array of gpfifo entries where each entry points to a FIFO command list. This list is composed of alternating 32-bit words containing FIFO commands and their respective arguments.&lt;br /&gt;
&lt;br /&gt;
=== Command Structure ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Bits&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|12-0&lt;br /&gt;
|Method&lt;br /&gt;
|-&lt;br /&gt;
|15-13&lt;br /&gt;
|Subchannel&lt;br /&gt;
|-&lt;br /&gt;
|27-16&lt;br /&gt;
|Argument count (in 32-bits Words) or inline data (see below)&lt;br /&gt;
|-&lt;br /&gt;
|28?&lt;br /&gt;
|Hmm?&lt;br /&gt;
|-&lt;br /&gt;
|31-29&lt;br /&gt;
|[[#Submission_mode|Submission mode]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note: Methods are treated as 4-byte addressable locations, and hence their numbers are written down multiplied by 4.&lt;br /&gt;
&lt;br /&gt;
Note: The command&#039;s arguments, when present, follow the command word immediately.&lt;br /&gt;
&lt;br /&gt;
==== Submission mode ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Mode&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Offical name&lt;br /&gt;
|-&lt;br /&gt;
|0&lt;br /&gt;
|Increasing mode (old)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Increasing mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039;, while automatically incrementing the &#039;&#039;&#039;method&#039;&#039;&#039; value. This means that each argument will be written to a different method location.&lt;br /&gt;
|INCR&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Non-increasing mode (old)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Non-increasing mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039;. However, all arguments will be written to the same method location.&lt;br /&gt;
|NONINCR&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Inline mode - Tells PFIFO to read &#039;&#039;&#039;inline data&#039;&#039;&#039; from bits 28-16 of the command word, thus eliminating the need to pass additional words for the arguments.&lt;br /&gt;
|IMM&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|Increase-once mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039; and automatically increments the &#039;&#039;&#039;method&#039;&#039;&#039; value once only.&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Command List ===&lt;br /&gt;
&lt;br /&gt;
All methods with values &amp;lt; 0x100 are special and executed by the PFIFO&#039;s DMA puller. The others are forwarded to the engine object currently bound to a given subchannel.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Command || Method || Subchannel || Arg Count || Mode || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001?000 || 0x0000 || Variable || 1 || 1 || [[#BindObject|BindObject]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000040 || 0x40 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA???0045 || 0x45 || 0 || Variable || 5 || SetGraphMacroCode&lt;br /&gt;
|-&lt;br /&gt;
| 0x20020047 || 0x47 || 0 || 2 || 1 || SetGraphMacroEntry&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0049 || 0x49 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20056080 || 0x80 || 3 || Variable || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20016085 || 0x85 || 3 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20026086 || 0x86 || 3 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20026088 || 0x88 || 3 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2004608C || 0x8C || 3 || Variable || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20016091 || 0x91 || 3 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20026092 || 0x92 || 3 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20026094 || 0x94 || 3 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800160B5 || 0xB5 || 3 || 1 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800000BA || 0xBA || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x601000BE || 0xBE || 0 || 16 || 3 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200100BF || 0xBF || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200180C0 || 0xC0 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200400C9 || 0xC9 || 0 || 4 || 1 || SetOuterTessellationLevels&lt;br /&gt;
|-&lt;br /&gt;
| 0x200200CD || 0xCD || 0 || 2 || 1 || SetInnerTessellationLevels&lt;br /&gt;
|-&lt;br /&gt;
| 0x200100DC || 0xDC || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?00DF || 0xDF || 0 || Variable || 4 || SetRasterizerDiscard?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20048100 || 0x100 || 4 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20028102 || 0x102 || 4 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20018104 || 0x104 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20018105 || 0x105 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20018106 || 0x106 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C0 || 0x1C0 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C2 || 0x1C2 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C3 || 0x1C3 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200281C4 || 0x1C4 || 4 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C5 || 0x1C5 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C6 || 0x1C6 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C7 || 0x1C7 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C8 || 0x1C8 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181CA || 0x1CA || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181CB || 0x1CB || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181CC || 0x1CC || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181CD || 0x1CD || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181CF || 0x1CF || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800001D1 || 0x1D1 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200301F0 || 0x1F0 || 0 || 3 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800001F3 || 0x1F3 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200201F8 || 0x1F8 || 0 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200401FA || 0x1FA || 0 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20016223 || 0x223 || 3 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2004622C || 0x22C || 3 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20046230 || 0x230 || 3 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20046234 || 0x234 || 3 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200203?? || 0x3?? Variable || 0 || 2 || 1 || SetScissors?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20040360 || 0x360 || 0 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010364 || 0x364 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0368 || 0x368 || 0 || Variable  || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?036B || 0x36B || 0 || Variable  || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?036C || 0x36C || 0 || Variable  || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001036F || 0x36F || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000370 || 0x370 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000371 || 0x371 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000372 || 0x372 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8???0373 || 0x373 || 0 || Variable || 4 || SetPatchSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000374 || 0x374 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010376 || 0x376 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?03D5 || 0x3D5 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?03D6 || 0x3D6 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?03D7 || 0x3D7 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200103D9 || 0x3D9 || 0 || 1 || 1 || SetTiledCacheTileSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x80?003DE || 0x3DE || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800003E0 || 0x3E0 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200203E7 || 0x3E7 || 0 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800003ED || 0x3ED || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800203EE || 0x3EE || 0 || 2 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200403EF || 0x3EF || 0 || 4 || 1 || SetSampleMask&lt;br /&gt;
|-&lt;br /&gt;
| 0x800003F5 || 0x3F5 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800103F6 || 0x3F6 || 0 || 1 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200503F8 || 0x3F8 || 0 || 5 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200203FD || 0x3FD || 0 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2004040C || 0x40C || 0 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200C0420 || 0x420 || 0 || 12 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000446 || 0x446 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000451 || 0x451 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0452 || 0x452 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20100458 || 0x458 || 0 || 16 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20040478 || 0x478 || 0 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8000047C || 0x47C || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8000047E || 0x47E || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8001047F || 0x47F || 0 || 1 || 4 || ResolveDepthBuffer&lt;br /&gt;
|-&lt;br /&gt;
| 0x2003048A || 0x48A || 0 || 3 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04B3 || 0x4B3 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800104B9 || 0x4B9 || 0 || 1 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04BA || 0x4BA || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800004BB || 0x4BB || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04C3 || 0x4C3 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200104C4 || 0x4C4 || 0 || 1 || 1 || SetAlphaRef&lt;br /&gt;
|-&lt;br /&gt;
| 0x200404C7 || 0x4C7 || 0 || 4 || 1 || SetBlendColor&lt;br /&gt;
|-&lt;br /&gt;
| 0x800004E0 || 0x4E0 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04E5 || 0x4E5 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04E6 || 0x4E6 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04E7 || 0x4E7 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200204EC || 0x4EC || 0 || 2 || 1 || SetLineWidth&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?050D || 0x50D || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000519 || 0x519 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000540 || 0x540 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010546 || 0x546 || 0 || 1 || 1 || SetPointSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001054C || 0x54C || 0 || 1 || 1 || ResetCounter&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?054E || 0x54E || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20030554 || 0x554 || 0 || 3 || 1 || SetRenderEnableConditional&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0556 || 0x556 || 0 || Variable || 4 || SetRenderEnable?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001055B || 0x55B || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001056F || 0x56F || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000572 || 0x572 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0574 || 0x574 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8000057F || 0x57F || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000580 || 0x580 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000591 || 0x591 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010592 || 0x592 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200205F2 || 0x5F2 || 0 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?05F6 || 0x5F6 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001061F || 0x61F || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0620 || 0x620 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80010646 || 0x646 || 0 || 1 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0648 || 0x648 || 0 || Variable  || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001064F || 0x64F || 0 || 1 || 1 || SetDepthClamp&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?066F || 0x66F || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x120020671 || 0x671 || 0 || 2 || 9 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010674 || 0x674 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8000068B || 0x68B || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200406C0 || 0x6C0 || 0 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010703 || 0x703 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200207?? || 0x7?? Variable || 0 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80300830 || 0x830 || 0 || 48 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80400840 || 0x840 || 0 || 64 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80500850 || 0x850 || 0 || 80 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200308E0 || 0x8E0 || 0 || 3 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200308E3 || 0x8E3 || 0 || 3 || 1 || CB_POS(Const buffer position)&lt;br /&gt;
|-&lt;br /&gt;
| 0x200308E4 || 0x8E4 || 0 || 3 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80??0904 || 0x904 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80??090C || 0x90C || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80??0914 || 0x914 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80??091C || 0x91C || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80??0924 || 0x924 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000D1E || 0xD1E || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0D28 || 0xD28 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010D29 || 0xD29 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010D34 || 0xD34 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0020E00 || 0xE00 || 0 || 2 || 5 || BeginTransformFeedback&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010E02 || 0xE02 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80020E04 || 0xE04 || 0 || 2 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010E06 || 0xE06 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0030E0A || 0xE0A || 0 || 3 || 5 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80050E0C || 0xE0C || 0 || 5 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0E0E || 0xE0E || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010E10 || 0xE10 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0040E12 || 0xE12 || 0 || 4 || 5 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010E1A || 0xE1A || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0040E1C || 0xE1C || 0 || 4 || 5 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x81900E1E || 0xE1E || 0 || 400 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000E20 || 0xE20 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000E24 || 0xE24 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0040E2C || 0xE2C || 0 || 4 || 5 || PushDebugGroup&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0020E2E || 0xE2E || 0 || 2 || 5 || PopDebugGroupId&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0030E30 || 0xE30 || 0 || 3 || 5 || DrawArrays&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0050E32 || 0xE32 || 0 || 5 || 5 || DrawArraysIndirect?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0050E34 || 0xE34 || 0 || 5 || 5 || DrawArraysInstanced?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0050E36 || 0xE36 || 0 || 5 || 5 || DrawElements&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0060E38 || 0xE38 || 0 || 6 || 5 || DrawElementsIndirect?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0060E3A || 0xE3A || 0 || 6 || 5 || DrawElementsInstanced?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0050E42 || 0xE42 || 0 || 5 || 5 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0060E44 || 0xE44 || 0 || 6 || 5 || ?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note: These still need to be heavily verified and &#039;&#039;could&#039;&#039; be wrong.&lt;br /&gt;
&lt;br /&gt;
=== BindObject ===&lt;br /&gt;
&lt;br /&gt;
In order to bind an engine object to a specific subchannel, method 0 (BindObject) must be used first. The target subchannel is specified in bits 15-13 of the command word.&lt;br /&gt;
&lt;br /&gt;
After the engine object is bound to the desired subchannel, setting it&#039;s value in bits 15-13 of any subsequent command word will make PFIFO forward the command to the target engine.&lt;br /&gt;
&lt;br /&gt;
This method only takes one argument, an [[#Engine_IDs|engine ID]].&lt;br /&gt;
&lt;br /&gt;
==== Engine IDs ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| ID&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Engine&lt;br /&gt;
|-&lt;br /&gt;
|0x902D&lt;br /&gt;
|FERMI_TWOD_A (2D)&lt;br /&gt;
|-&lt;br /&gt;
|0xB197&lt;br /&gt;
|MAXWELL_B (3D)&lt;br /&gt;
|-&lt;br /&gt;
|0xB1C0&lt;br /&gt;
|MAXWELL_COMPUTE_B&lt;br /&gt;
|-&lt;br /&gt;
|0xA140&lt;br /&gt;
|KEPLER_INLINE_TO_MEMORY_B&lt;br /&gt;
|-&lt;br /&gt;
|0xB0B5&lt;br /&gt;
|MAXWELL_DMA_COPY_A (DMA)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Macro ===&lt;br /&gt;
&lt;br /&gt;
Macros are small programs that can be uploaded to the gpu and are capable of reading and writing to the 3D engine registers on the GPU. The macros also accepts parameters, stored on a FIFO. Macros can be called using methods starting at 0xe00, where the first method triggers the macro execution, and the second one is used to push parameters to the FIFO, that can be read from the macro program using a instruction called &#039;&#039;parm&#039;&#039;. This instruction pops the FIFO and reads the next parameter, while also allowing programs to use a variable number of parameters if desired.&lt;br /&gt;
&lt;br /&gt;
The first parameter is written to 0xe00 + n * 2 (where n is the macro index), and all subsequent parameters should be pushed to the FIFO using 0xe01 + n * 2. The first parameter is placed at the general purpose register R1 in the macro program when execution starts.&lt;br /&gt;
&lt;br /&gt;
Official games uses those macros to conditionally write registers, one example of such uses is the macro at 0xe24, that is used to set shader registers (including shader address and binding the c1 Constant Buffer to the shader). In some cases, it&#039;s also used to set registers unconditionally.&lt;br /&gt;
&lt;br /&gt;
=== Fences ===&lt;br /&gt;
&lt;br /&gt;
Command lists can contain fences to ensure that commands are executed on the correct order, and subsequent commands are only sent when the previously sent commands were already processed by the GPU. Fences uses the QUERY_* commands, and works like this:&lt;br /&gt;
&lt;br /&gt;
* First, QUERY_ADDRESS_HIGH and QUERY_ADDRESS_LOW commands are added to the Command List, with the High/Low 32 bits part of the 64-bits GPU Virtual Address where the fence is located. This GPU Virtual Address needs to be mapped to the process Virtual Address beforehand.&lt;br /&gt;
* Then, QUERY_SEQUENCE is added with a sequential number. This number is basically a incrementing counter, so the first Command List can have QUERY_SEQUENCE = 1, the next one QUERY_SEQUENCE = 2, 3, 4... and so on.&lt;br /&gt;
* Finally, QUERY_GET is added and contains the mode and other unknown data.&lt;br /&gt;
&lt;br /&gt;
The above commands are added using the [[#Submission_mode|increasing mode]], since the Ids for all those 4 registers are sequential.&lt;br /&gt;
&lt;br /&gt;
==== QUERY_GET Structure ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Bits&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|1-0&lt;br /&gt;
|Mode&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Fence&lt;br /&gt;
|-&lt;br /&gt;
|15-12&lt;br /&gt;
|Unit &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== QUERY_GET Mode ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Value&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Mode&lt;br /&gt;
|-&lt;br /&gt;
|0&lt;br /&gt;
|Write&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Sync&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Write ? &lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Write ?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
TODO: Move this to a separate page with all GPU Commands with descriptions. Also figure out what the other values mean.&lt;br /&gt;
&lt;br /&gt;
Some of the other fields are still unknown/unobserved.&lt;br /&gt;
&lt;br /&gt;
Official games will set Mode to 0, Fence to 1 and Unit to 0xF. The QUERY_SEQUENCE value is then written by the GPU to the address pointed to by QUERY_ADDRESS.&lt;br /&gt;
On the CPU side, the game code should wait until the value at the address pointed to by QUERY_ADDRESS is &amp;gt;= to the last written SEQUENCE value. Official code waits for this condition to be true on a loop, and won&#039;t send any further commands before that.&lt;br /&gt;
&lt;br /&gt;
== Vertex Data Submission ==&lt;br /&gt;
&lt;br /&gt;
Note: This is a observation on how the game Puyo Puyo Tetris sends textured squares to the GPU.&lt;br /&gt;
&lt;br /&gt;
# VERTEX_ATTRIB_FORMAT (0-15) are set (only the first 3 are really used, the rest are set float, with Size = 1 and offset at 0).&lt;br /&gt;
# VERTEX_ARRAY_FETCH (0) is set with the lower 12 bits set to 0x1c (Stride) and bit 12 to 1 (Enabled).&lt;br /&gt;
# VERTEX_ARRAY_START_HIGH/LOW (0) are set to the GPU Virtual Address where the Vertex Data is located.&lt;br /&gt;
# VERTEX_ARRAY_LIMIT_HIGH/LOW (0) are set to the GPU Virtual Address where the Vertex Data is located, plus the Vertex Data size in bytes minus 1.&lt;br /&gt;
# VERTEX_BEGIN_GL is used with the primitive type set to TRIANGLE_STRIP.&lt;br /&gt;
# VERTEX_BUFFER_FIRST with value 0 (indicating the index of the first primitive to render?).&lt;br /&gt;
# VERTEX_BUFFER_COUNT is set to 4, because the Vertex Buffer with the square has 4 vertices.&lt;br /&gt;
# VERTEX_END_GL is used with value 0 (currently unknown what this value means).&lt;br /&gt;
&lt;br /&gt;
== Texture View ==&lt;br /&gt;
&lt;br /&gt;
Texture information such as address, format and size is sent to the GPU through a structure know as Texture View (a.k.a. Texture Image Control, or TIC). Each texture that the game uses needs a separate TIC, and those TICs are written to a table, one after the other. Each [[#TIC_Structure|TIC entry]] has 0x20 bytes, and is composed of 8 32-bits words where the texture information is packed.&lt;br /&gt;
&lt;br /&gt;
The index of the TIC entries that should be used by the shader is sent to the GPU with the CB_POS/CB_DATA (0) methods. Games usually follows the following steps to write the TIC entry indexes:&lt;br /&gt;
&lt;br /&gt;
* Macro 0xe1a is used to set CB_ADDRESS_HIGH/LOW registers to the GPU Virtual Address of the Constant Buffer set on the register 0x982 (the &#039;&#039;Texture Constant Buffer&#039;&#039; index register), and also sets CB_SIZE.&lt;br /&gt;
* CB_POS is used to set the write offset of the Constant Buffer to n * 4, where &#039;&#039;n&#039;&#039; is the index of the &#039;&#039;Handle&#039;&#039; being used on the shader program (this index starts at 8, so CB_POS should be at least 8 * 4 = 0x20).&lt;br /&gt;
* CB_DATA (0) method is used to write the value into the Constant Buffer. The value is a &#039;&#039;Handle&#039;&#039; where the lower 20 bits is the TIC index, and the higher 12 bits is the TSC (Texture Sampler Control) index.&lt;br /&gt;
&lt;br /&gt;
The address of a given TIC entry can be calculates as:&lt;br /&gt;
&lt;br /&gt;
 tic_entry_address = tic_base_address + tic_index * 0x20&lt;br /&gt;
&lt;br /&gt;
Where &#039;&#039;tic_base_address&#039;&#039; is the address written to TIC_ADDRESS_HIGH/LOW (methods 0x1574 and 0x1578), &#039;&#039;tic_index&#039;&#039; is the lower 20 bits of the word written into the Const Buffer with CB_DATA (0), and 0x20 is the size of each TIC entry in bytes.&lt;br /&gt;
&lt;br /&gt;
The texture is accessed on the shader using one of the texture sampling instructions (usually the TEXS instruction). One of the parameters for this instruction is the &#039;&#039;Handle&#039;&#039; index. This index start at 8, so the index 8 will access the handle at 8 * 4 = 0x20 on the &#039;&#039;Texture Constant Buffer&#039;&#039;. Each shader stage has a separate Constant Buffer, so for fragment shaders, this is located at CB_ADDRESS + 4 * CB_SIZE + TEXS_index * 4 (where the first 4 is the index of the fragment shader stage, and the second 4 is the size of a word, 4 bytes).&lt;br /&gt;
&lt;br /&gt;
=== TIC Structure ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Word || Bits || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 6-0 || [[GPU_Texture_Formats#Texture_Formats|Texture Format]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 9-7 || [[#Channel_Data_Type|R Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 12-10 || [[#Channel_Data_Type|G Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 15-13 || [[#Channel_Data_Type|B Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 18-16 || [[#Channel_Data_Type|A Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 31-0 || Lower 32-bits of the Texture GPU Virtual Address&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 15-0 || Higher 16-bits of the Texture GPU Virtual Address&lt;br /&gt;
|-&lt;br /&gt;
| 4 || 15-0 || Texture Width minus 1&lt;br /&gt;
|-&lt;br /&gt;
| 5 || 15-0 || Texture Height minus 1&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Channel Data Type ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Type&lt;br /&gt;
|-&lt;br /&gt;
| 1 || SNORM&lt;br /&gt;
|-&lt;br /&gt;
| 2 || UNORM&lt;br /&gt;
|-&lt;br /&gt;
| 3 || SINT&lt;br /&gt;
|-&lt;br /&gt;
| 4 || UINT&lt;br /&gt;
|-&lt;br /&gt;
| 5 || SNORM_FORCE_FP16&lt;br /&gt;
|-&lt;br /&gt;
| 6 || UNORM_FORCE_FP16&lt;br /&gt;
|-&lt;br /&gt;
| 7 || FLOAT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
FIFO engine overview:&lt;br /&gt;
[https://envytools.readthedocs.io/en/latest/hw/fifo/intro.html]&lt;br /&gt;
&lt;br /&gt;
Method values from the Fermi family GPU (a bit older than the Tegra X1, but values seems to be mostly the same):&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/gf100_3d.xml]&lt;br /&gt;
&lt;br /&gt;
TIC structure used on a Maxwell GPU:&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/gm200_texture.xml]&lt;br /&gt;
&lt;br /&gt;
Values for some types used on the above XML:&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/nv_3ddefs.xml]&lt;br /&gt;
&lt;br /&gt;
Command word packing code used on Mesa3d:&lt;br /&gt;
[https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nvc0/nvc0_winsys.h]&lt;br /&gt;
&lt;br /&gt;
TIC entry pack/write code used on Mesa3d:&lt;br /&gt;
[https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c#n65]&lt;/div&gt;</summary>
		<author><name>Gdkchan</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=GPU&amp;diff=4385</id>
		<title>GPU</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=GPU&amp;diff=4385"/>
		<updated>2018-03-30T19:32:39Z</updated>

		<summary type="html">&lt;p&gt;Gdkchan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Mapping Memory ==&lt;br /&gt;
&lt;br /&gt;
First, to map a memory region on the GPU Address Space, caching needs to be disabled by using [[SVC#svcSetMemoryAttribute|svcSetMemoryAttribute]]. The Address passed is the Virtual Address of the region that will be mapped, the size is the region size, and State0/1 are both set to 8 to disable caching of the memory region. This is done to ensure that the GPU can actually &amp;quot;see&amp;quot; the data written there, and it doesn&#039;t get stuck on some cache.&lt;br /&gt;
&lt;br /&gt;
Then, [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]] is used to create a nvmap object with the desired size. After, [[NV_services#NVMAP_IOC_ALLOC|NVMAP_IOC_ALLOC]] is used to allocate the memory on the GPU Address Space, and map data on the process Address Space into the GPU Address Space, by passing the Virtual Address as the input addr parameter, and also the Handle returned from [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]]. Lastly, the actual mapping is done by using [[NV_services#NVGPU_AS_IOCTL_MAP_BUFFER_EX|NVGPU_AS_IOCTL_MAP_BUFFER_EX]], and the GPU Virtual Address is returned on the offset parameter. It&#039;s also possible to manually set the offset where the mapping should be made on the GPU Address Space, by passing the address on the &amp;quot;offset&amp;quot; parameter, and setting the bit 0 of the flags parameter to 1. However, for this to work, the desired GPU Virtual Address needs to be previously reserved using [[NV_services#NVGPU_AS_IOCTL_ALLOC_SPACE|NVGPU_AS_IOCTL_ALLOC_SPACE]].&lt;br /&gt;
&lt;br /&gt;
The above process is used to map all data that will be used by the GPU, like Textures, Command Lists (a.k.a. Push Buffers), Vertex/Index buffers and Shaders. They usually have their own mapping, but Command Lists can share the same mapping.&lt;br /&gt;
&lt;br /&gt;
== FIFO Commands ==&lt;br /&gt;
&lt;br /&gt;
The GPU implements a variation of Tegra&#039;s push buffer format for it&#039;s PFIFO engine. PFIFO is a special engine responsible for receiving user command lists and routing them to the appropriate engines (2D, 3D, DMA).&lt;br /&gt;
&lt;br /&gt;
Commands are submitted to the GPU&#039;s PFIFO engine through [[NV_services#NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO|NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO]].&lt;br /&gt;
&lt;br /&gt;
This ioctl takes an array of gpfifo entries where each entry points to a FIFO command list. This list is composed of alternating 32-bit words containing FIFO commands and their respective arguments.&lt;br /&gt;
&lt;br /&gt;
=== Command Structure ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Bits&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|12-0&lt;br /&gt;
|Method&lt;br /&gt;
|-&lt;br /&gt;
|15-13&lt;br /&gt;
|Subchannel&lt;br /&gt;
|-&lt;br /&gt;
|27-16&lt;br /&gt;
|Argument count (in 32-bits Words) or inline data (see below)&lt;br /&gt;
|-&lt;br /&gt;
|28?&lt;br /&gt;
|Hmm?&lt;br /&gt;
|-&lt;br /&gt;
|31-29&lt;br /&gt;
|[[#Submission_mode|Submission mode]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note: Methods are treated as 4-byte addressable locations, and hence their numbers are written down multiplied by 4.&lt;br /&gt;
&lt;br /&gt;
Note: The command&#039;s arguments, when present, follow the command word immediately.&lt;br /&gt;
&lt;br /&gt;
==== Submission mode ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Mode&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Offical name&lt;br /&gt;
|-&lt;br /&gt;
|0&lt;br /&gt;
|Increasing mode (old)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Increasing mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039;, while automatically incrementing the &#039;&#039;&#039;method&#039;&#039;&#039; value. This means that each argument will be written to a different method location.&lt;br /&gt;
|INCR&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Non-increasing mode (old)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Non-increasing mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039;. However, all arguments will be written to the same method location.&lt;br /&gt;
|NONINCR&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Inline mode - Tells PFIFO to read &#039;&#039;&#039;inline data&#039;&#039;&#039; from bits 28-16 of the command word, thus eliminating the need to pass additional words for the arguments.&lt;br /&gt;
|IMM&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|Increase-once mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039; and automatically increments the &#039;&#039;&#039;method&#039;&#039;&#039; value once only.&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Command List ===&lt;br /&gt;
&lt;br /&gt;
All methods with values &amp;lt; 0x100 are special and executed by the PFIFO&#039;s DMA puller. The others are forwarded to the engine object currently bound to a given subchannel.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Command || Method || Subchannel || Arg Count || Mode || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001?000 || 0x0000 || Variable || 1 || 1 || [[#BindObject|BindObject]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000040 || 0x40 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA???0045 || 0x45 || 0 || Variable || 5 || SetGraphMacroCode&lt;br /&gt;
|-&lt;br /&gt;
| 0x20020047 || 0x47 || 0 || 2 || 1 || SetGraphMacroEntry&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0049 || 0x49 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20056080 || 0x80 || 3 || Variable || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20016085 || 0x85 || 3 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20026086 || 0x86 || 3 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20026088 || 0x88 || 3 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2004608C || 0x8C || 3 || Variable || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20016091 || 0x91 || 3 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20026092 || 0x92 || 3 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20026094 || 0x94 || 3 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800160B5 || 0xB5 || 3 || 1 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800000BA || 0xBA || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x601000BE || 0xBE || 0 || 16 || 3 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200100BF || 0xBF || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200180C0 || 0xC0 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200400C9 || 0xC9 || 0 || 4 || 1 || SetOuterTessellationLevels&lt;br /&gt;
|-&lt;br /&gt;
| 0x200200CD || 0xCD || 0 || 2 || 1 || SetInnerTessellationLevels&lt;br /&gt;
|-&lt;br /&gt;
| 0x200100DC || 0xDC || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?00DF || 0xDF || 0 || Variable || 4 || SetRasterizerDiscard?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20048100 || 0x100 || 4 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20028102 || 0x102 || 4 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20018104 || 0x104 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20018105 || 0x105 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20018106 || 0x106 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C0 || 0x1C0 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C2 || 0x1C2 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C3 || 0x1C3 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200281C4 || 0x1C4 || 4 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C5 || 0x1C5 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C6 || 0x1C6 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C7 || 0x1C7 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C8 || 0x1C8 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181CA || 0x1CA || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181CB || 0x1CB || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181CC || 0x1CC || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181CD || 0x1CD || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181CF || 0x1CF || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800001D1 || 0x1D1 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200301F0 || 0x1F0 || 0 || 3 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800001F3 || 0x1F3 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200201F8 || 0x1F8 || 0 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200401FA || 0x1FA || 0 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20016223 || 0x223 || 3 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2004622C || 0x22C || 3 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20046230 || 0x230 || 3 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20046234 || 0x234 || 3 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200203?? || 0x3?? Variable || 0 || 2 || 1 || SetScissors?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20040360 || 0x360 || 0 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010364 || 0x364 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0368 || 0x368 || 0 || Variable  || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?036B || 0x36B || 0 || Variable  || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?036C || 0x36C || 0 || Variable  || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001036F || 0x36F || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000370 || 0x370 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000371 || 0x371 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000372 || 0x372 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8???0373 || 0x373 || 0 || Variable || 4 || SetPatchSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000374 || 0x374 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010376 || 0x376 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?03D5 || 0x3D5 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?03D6 || 0x3D6 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?03D7 || 0x3D7 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200103D9 || 0x3D9 || 0 || 1 || 1 || SetTiledCacheTileSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x80?003DE || 0x3DE || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800003E0 || 0x3E0 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200203E7 || 0x3E7 || 0 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800003ED || 0x3ED || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800203EE || 0x3EE || 0 || 2 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200403EF || 0x3EF || 0 || 4 || 1 || SetSampleMask&lt;br /&gt;
|-&lt;br /&gt;
| 0x800003F5 || 0x3F5 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800103F6 || 0x3F6 || 0 || 1 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200503F8 || 0x3F8 || 0 || 5 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200203FD || 0x3FD || 0 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2004040C || 0x40C || 0 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200C0420 || 0x420 || 0 || 12 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000446 || 0x446 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000451 || 0x451 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0452 || 0x452 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20100458 || 0x458 || 0 || 16 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20040478 || 0x478 || 0 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8000047C || 0x47C || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8000047E || 0x47E || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8001047F || 0x47F || 0 || 1 || 4 || ResolveDepthBuffer&lt;br /&gt;
|-&lt;br /&gt;
| 0x2003048A || 0x48A || 0 || 3 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04B3 || 0x4B3 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800104B9 || 0x4B9 || 0 || 1 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04BA || 0x4BA || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800004BB || 0x4BB || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04C3 || 0x4C3 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200104C4 || 0x4C4 || 0 || 1 || 1 || SetAlphaRef&lt;br /&gt;
|-&lt;br /&gt;
| 0x200404C7 || 0x4C7 || 0 || 4 || 1 || SetBlendColor&lt;br /&gt;
|-&lt;br /&gt;
| 0x800004E0 || 0x4E0 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04E5 || 0x4E5 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04E6 || 0x4E6 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04E7 || 0x4E7 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200204EC || 0x4EC || 0 || 2 || 1 || SetLineWidth&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?050D || 0x50D || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000519 || 0x519 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000540 || 0x540 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010546 || 0x546 || 0 || 1 || 1 || SetPointSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001054C || 0x54C || 0 || 1 || 1 || ResetCounter&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?054E || 0x54E || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20030554 || 0x554 || 0 || 3 || 1 || SetRenderEnableConditional&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0556 || 0x556 || 0 || Variable || 4 || SetRenderEnable?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001055B || 0x55B || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001056F || 0x56F || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000572 || 0x572 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0574 || 0x574 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8000057F || 0x57F || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000580 || 0x580 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000591 || 0x591 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010592 || 0x592 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200205F2 || 0x5F2 || 0 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?05F6 || 0x5F6 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001061F || 0x61F || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0620 || 0x620 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80010646 || 0x646 || 0 || 1 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0648 || 0x648 || 0 || Variable  || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001064F || 0x64F || 0 || 1 || 1 || SetDepthClamp&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?066F || 0x66F || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x120020671 || 0x671 || 0 || 2 || 9 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010674 || 0x674 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8000068B || 0x68B || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200406C0 || 0x6C0 || 0 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010703 || 0x703 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200207?? || 0x7?? Variable || 0 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80300830 || 0x830 || 0 || 48 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80400840 || 0x840 || 0 || 64 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80500850 || 0x850 || 0 || 80 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200308E0 || 0x8E0 || 0 || 3 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200308E3 || 0x8E3 || 0 || 3 || 1 || CB_POS(Const buffer position)&lt;br /&gt;
|-&lt;br /&gt;
| 0x200308E4 || 0x8E4 || 0 || 3 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80??0904 || 0x904 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80??090C || 0x90C || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80??0914 || 0x914 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80??091C || 0x91C || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80??0924 || 0x924 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000D1E || 0xD1E || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0D28 || 0xD28 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010D29 || 0xD29 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010D34 || 0xD34 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0020E00 || 0xE00 || 0 || 2 || 5 || BeginTransformFeedback&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010E02 || 0xE02 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80020E04 || 0xE04 || 0 || 2 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010E06 || 0xE06 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0030E0A || 0xE0A || 0 || 3 || 5 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80050E0C || 0xE0C || 0 || 5 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0E0E || 0xE0E || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010E10 || 0xE10 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0040E12 || 0xE12 || 0 || 4 || 5 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010E1A || 0xE1A || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0040E1C || 0xE1C || 0 || 4 || 5 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x81900E1E || 0xE1E || 0 || 400 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000E20 || 0xE20 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000E24 || 0xE24 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0040E2C || 0xE2C || 0 || 4 || 5 || PushDebugGroup&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0020E2E || 0xE2E || 0 || 2 || 5 || PopDebugGroupId&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0030E30 || 0xE30 || 0 || 3 || 5 || DrawArrays&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0050E32 || 0xE32 || 0 || 5 || 5 || DrawArraysIndirect?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0050E34 || 0xE34 || 0 || 5 || 5 || DrawArraysInstanced?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0050E36 || 0xE36 || 0 || 5 || 5 || DrawElements&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0060E38 || 0xE38 || 0 || 6 || 5 || DrawElementsIndirect?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0060E3A || 0xE3A || 0 || 6 || 5 || DrawElementsInstanced?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0050E42 || 0xE42 || 0 || 5 || 5 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0060E44 || 0xE44 || 0 || 6 || 5 || ?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note: These still need to be heavily verified and &#039;&#039;could&#039;&#039; be wrong.&lt;br /&gt;
&lt;br /&gt;
=== BindObject ===&lt;br /&gt;
&lt;br /&gt;
In order to bind an engine object to a specific subchannel, method 0 (BindObject) must be used first. The target subchannel is specified in bits 15-13 of the command word.&lt;br /&gt;
&lt;br /&gt;
After the engine object is bound to the desired subchannel, setting it&#039;s value in bits 15-13 of any subsequent command word will make PFIFO forward the command to the target engine.&lt;br /&gt;
&lt;br /&gt;
This method only takes one argument, an [[#Engine_IDs|engine ID]].&lt;br /&gt;
&lt;br /&gt;
==== Engine IDs ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| ID&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Engine&lt;br /&gt;
|-&lt;br /&gt;
|0x902D&lt;br /&gt;
|FERMI_TWOD_A (2D)&lt;br /&gt;
|-&lt;br /&gt;
|0xB197&lt;br /&gt;
|MAXWELL_B (3D)&lt;br /&gt;
|-&lt;br /&gt;
|0xB1C0&lt;br /&gt;
|MAXWELL_COMPUTE_B&lt;br /&gt;
|-&lt;br /&gt;
|0xA140&lt;br /&gt;
|KEPLER_INLINE_TO_MEMORY_B&lt;br /&gt;
|-&lt;br /&gt;
|0xB0B5&lt;br /&gt;
|MAXWELL_DMA_COPY_A (DMA)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Macro ===&lt;br /&gt;
&lt;br /&gt;
Macros are small programs that can be uploaded to the gpu and are capable of reading and writing to the 3D engine registers on the GPU. The macros also accepts parameters, stored on a FIFO. Macros can be called using methods starting at 0xe00, where the first method triggers the macro execution, and the second one is used to push parameters to the FIFO, that can be read from the macro program using a instruction called &#039;&#039;parm&#039;&#039;. This instruction pops the FIFO and reads the next parameter, while also allowing programs to use a variable number of parameters if desired.&lt;br /&gt;
&lt;br /&gt;
The first parameter is written to 0xe00 + n * 2 (where n is the macro index), and all subsequent parameters should be pushed to the FIFO using 0xe01 + n * 2. The first parameter is placed at the general purpose register R1 in the shader program when execution starts.&lt;br /&gt;
&lt;br /&gt;
Official games uses those macros to conditionally write registers, one example of such uses is the macro at 0xe24, that is used to set shader registers (including shader address and binding the c1 Constant Buffer to the shader). In some cases, it&#039;s also used to set registers unconditionally.&lt;br /&gt;
&lt;br /&gt;
=== Fences ===&lt;br /&gt;
&lt;br /&gt;
Command lists can contain fences to ensure that commands are executed on the correct order, and subsequent commands are only sent when the previously sent commands were already processed by the GPU. Fences uses the QUERY_* commands, and works like this:&lt;br /&gt;
&lt;br /&gt;
* First, QUERY_ADDRESS_HIGH and QUERY_ADDRESS_LOW commands are added to the Command List, with the High/Low 32 bits part of the 64-bits GPU Virtual Address where the fence is located. This GPU Virtual Address needs to be mapped to the process Virtual Address beforehand.&lt;br /&gt;
* Then, QUERY_SEQUENCE is added with a sequential number. This number is basically a incrementing counter, so the first Command List can have QUERY_SEQUENCE = 1, the next one QUERY_SEQUENCE = 2, 3, 4... and so on.&lt;br /&gt;
* Finally, QUERY_GET is added and contains the mode and other unknown data.&lt;br /&gt;
&lt;br /&gt;
The above commands are added using the [[#Submission_mode|increasing mode]], since the Ids for all those 4 registers are sequential.&lt;br /&gt;
&lt;br /&gt;
==== QUERY_GET Structure ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Bits&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|1-0&lt;br /&gt;
|Mode&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Fence&lt;br /&gt;
|-&lt;br /&gt;
|15-12&lt;br /&gt;
|Unit &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== QUERY_GET Mode ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Value&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Mode&lt;br /&gt;
|-&lt;br /&gt;
|0&lt;br /&gt;
|Write&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Sync&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Write ? &lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Write ?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
TODO: Move this to a separate page with all GPU Commands with descriptions. Also figure out what the other values mean.&lt;br /&gt;
&lt;br /&gt;
Some of the other fields are still unknown/unobserved.&lt;br /&gt;
&lt;br /&gt;
Official games will set Mode to 0, Fence to 1 and Unit to 0xF. The QUERY_SEQUENCE value is then written by the GPU to the address pointed to by QUERY_ADDRESS.&lt;br /&gt;
On the CPU side, the game code should wait until the value at the address pointed to by QUERY_ADDRESS is &amp;gt;= to the last written SEQUENCE value. Official code waits for this condition to be true on a loop, and won&#039;t send any further commands before that.&lt;br /&gt;
&lt;br /&gt;
== Vertex Data Submission ==&lt;br /&gt;
&lt;br /&gt;
Note: This is a observation on how the game Puyo Puyo Tetris sends textured squares to the GPU.&lt;br /&gt;
&lt;br /&gt;
# VERTEX_ATTRIB_FORMAT (0-15) are set (only the first 3 are really used, the rest are set float, with Size = 1 and offset at 0).&lt;br /&gt;
# VERTEX_ARRAY_FETCH (0) is set with the lower 12 bits set to 0x1c (Stride) and bit 12 to 1 (Enabled).&lt;br /&gt;
# VERTEX_ARRAY_START_HIGH/LOW (0) are set to the GPU Virtual Address where the Vertex Data is located.&lt;br /&gt;
# VERTEX_ARRAY_LIMIT_HIGH/LOW (0) are set to the GPU Virtual Address where the Vertex Data is located, plus the Vertex Data size in bytes minus 1.&lt;br /&gt;
# VERTEX_BEGIN_GL is used with the primitive type set to TRIANGLE_STRIP.&lt;br /&gt;
# VERTEX_BUFFER_FIRST with value 0 (indicating the index of the first primitive to render?).&lt;br /&gt;
# VERTEX_BUFFER_COUNT is set to 4, because the Vertex Buffer with the square has 4 vertices.&lt;br /&gt;
# VERTEX_END_GL is used with value 0 (currently unknown what this value means).&lt;br /&gt;
&lt;br /&gt;
== Texture View ==&lt;br /&gt;
&lt;br /&gt;
Texture information such as address, format and size is sent to the GPU through a structure know as Texture View (a.k.a. Texture Image Control, or TIC). Each texture that the game uses needs a separate TIC, and those TICs are written to a table, one after the other. Each [[#TIC_Structure|TIC entry]] has 0x20 bytes, and is composed of 8 32-bits words where the texture information is packed.&lt;br /&gt;
&lt;br /&gt;
The index of the TIC entries that should be used by the shader is sent to the GPU with the CB_POS/CB_DATA (0) methods. Games usually follows the following steps to write the TIC entry indexes:&lt;br /&gt;
&lt;br /&gt;
* Macro 0xe1a is used to set CB_ADDRESS_HIGH/LOW registers to the GPU Virtual Address of the Constant Buffer set on the register 0x982 (the &#039;&#039;Texture Constant Buffer&#039;&#039; index register), and also sets CB_SIZE.&lt;br /&gt;
* CB_POS is used to set the write offset of the Constant Buffer to 0x20 + n * 4, where &#039;&#039;n&#039;&#039; is the index of the &#039;&#039;Handle&#039;&#039; being used on the shader sampler.&lt;br /&gt;
* CB_DATA (0) method is used to write the value into the Constant Buffer. The value is a &#039;&#039;Handle&#039;&#039; where the lower 20 bits is the TIC index, and the higher 12 bits is the TSC (Texture Sampler Control) index.&lt;br /&gt;
&lt;br /&gt;
The address of a given TIC entry can be calculates as:&lt;br /&gt;
&lt;br /&gt;
 tic_entry_address = tic_base_address + tic_index * 0x20&lt;br /&gt;
&lt;br /&gt;
Where &#039;&#039;tic_base_address&#039;&#039; is the address written to TIC_ADDRESS_HIGH/LOW (methods 0x1574 and 0x1578), &#039;&#039;tic_index&#039;&#039; is the lower 20 bits of the word written into the Const Buffer with CB_DATA (0), and 0x20 is the size of each TIC entry in bytes.&lt;br /&gt;
&lt;br /&gt;
The texture is accessed on the shader using one of the texture sampling instructions (usually the TEXS instruction). One of the parameters for this instruction is the &#039;&#039;Handle&#039;&#039; index. This index start at 8, so the index 8 will access the handle at 8 * 4 = 0x20 on the &#039;&#039;Texture Constant Buffer&#039;&#039;. Each shader stage has a separate Constant Buffer, so for fragment shaders, this is located at CB_ADDRESS + 4 * CB_SIZE + TEXS_index * 4 (where the first 4 is the index of the fragment shader stage, and the second 4 is the size of a word, 4 bytes).&lt;br /&gt;
&lt;br /&gt;
=== TIC Structure ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Word || Bits || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 6-0 || [[GPU_Texture_Formats#Texture_Formats|Texture Format]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 9-7 || [[#Channel_Data_Type|R Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 12-10 || [[#Channel_Data_Type|G Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 15-13 || [[#Channel_Data_Type|B Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 18-16 || [[#Channel_Data_Type|A Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 31-0 || Lower 32-bits of the Texture GPU Virtual Address&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 15-0 || Higher 16-bits of the Texture GPU Virtual Address&lt;br /&gt;
|-&lt;br /&gt;
| 4 || 15-0 || Texture Width minus 1&lt;br /&gt;
|-&lt;br /&gt;
| 5 || 15-0 || Texture Height minus 1&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Channel Data Type ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Type&lt;br /&gt;
|-&lt;br /&gt;
| 1 || SNORM&lt;br /&gt;
|-&lt;br /&gt;
| 2 || UNORM&lt;br /&gt;
|-&lt;br /&gt;
| 3 || SINT&lt;br /&gt;
|-&lt;br /&gt;
| 4 || UINT&lt;br /&gt;
|-&lt;br /&gt;
| 5 || SNORM_FORCE_FP16&lt;br /&gt;
|-&lt;br /&gt;
| 6 || UNORM_FORCE_FP16&lt;br /&gt;
|-&lt;br /&gt;
| 7 || FLOAT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
FIFO engine overview:&lt;br /&gt;
[https://envytools.readthedocs.io/en/latest/hw/fifo/intro.html]&lt;br /&gt;
&lt;br /&gt;
Method values from the Fermi family GPU (a bit older than the Tegra X1, but values seems to be mostly the same):&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/gf100_3d.xml]&lt;br /&gt;
&lt;br /&gt;
TIC structure used on a Maxwell GPU:&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/gm200_texture.xml]&lt;br /&gt;
&lt;br /&gt;
Values for some types used on the above XML:&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/nv_3ddefs.xml]&lt;br /&gt;
&lt;br /&gt;
Command word packing code used on Mesa3d:&lt;br /&gt;
[https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nvc0/nvc0_winsys.h]&lt;br /&gt;
&lt;br /&gt;
TIC entry pack/write code used on Mesa3d:&lt;br /&gt;
[https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c#n65]&lt;/div&gt;</summary>
		<author><name>Gdkchan</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=GPU&amp;diff=4379</id>
		<title>GPU</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=GPU&amp;diff=4379"/>
		<updated>2018-03-30T15:12:50Z</updated>

		<summary type="html">&lt;p&gt;Gdkchan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Mapping Memory ==&lt;br /&gt;
&lt;br /&gt;
First, to map a memory region on the GPU Address Space, caching needs to be disabled by using [[SVC#svcSetMemoryAttribute|svcSetMemoryAttribute]]. The Address passed is the Virtual Address of the region that will be mapped, the size is the region size, and State0/1 are both set to 8 to disable caching of the memory region. This is done to ensure that the GPU can actually &amp;quot;see&amp;quot; the data written there, and it doesn&#039;t get stuck on some cache.&lt;br /&gt;
&lt;br /&gt;
Then, [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]] is used to create a nvmap object with the desired size. After, [[NV_services#NVMAP_IOC_ALLOC|NVMAP_IOC_ALLOC]] is used to allocate the memory on the GPU Address Space, and map data on the process Address Space into the GPU Address Space, by passing the Virtual Address as the input addr parameter, and also the Handle returned from [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]]. Lastly, the actual mapping is done by using [[NV_services#NVGPU_AS_IOCTL_MAP_BUFFER_EX|NVGPU_AS_IOCTL_MAP_BUFFER_EX]], and the GPU Virtual Address is returned on the offset parameter. It&#039;s also possible to manually set the offset where the mapping should be made on the GPU Address Space, by passing the address on the &amp;quot;offset&amp;quot; parameter, and setting the bit 0 of the flags parameter to 1. However, for this to work, the desired GPU Virtual Address needs to be previously reserved using [[NV_services#NVGPU_AS_IOCTL_ALLOC_SPACE|NVGPU_AS_IOCTL_ALLOC_SPACE]].&lt;br /&gt;
&lt;br /&gt;
The above process is used to map all data that will be used by the GPU, like Textures, Command Lists (a.k.a. Push Buffers), Vertex/Index buffers and Shaders. They usually have their own mapping, but Command Lists can share the same mapping.&lt;br /&gt;
&lt;br /&gt;
== FIFO Commands ==&lt;br /&gt;
&lt;br /&gt;
The GPU implements a variation of Tegra&#039;s push buffer format for it&#039;s PFIFO engine. PFIFO is a special engine responsible for receiving user command lists and routing them to the appropriate engines (2D, 3D, DMA).&lt;br /&gt;
&lt;br /&gt;
Commands are submitted to the GPU&#039;s PFIFO engine through [[NV_services#NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO|NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO]].&lt;br /&gt;
&lt;br /&gt;
This ioctl takes an array of gpfifo entries where each entry points to a FIFO command list. This list is composed of alternating 32-bit words containing FIFO commands and their respective arguments.&lt;br /&gt;
&lt;br /&gt;
=== Command Structure ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Bits&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|12-0&lt;br /&gt;
|Method&lt;br /&gt;
|-&lt;br /&gt;
|15-13&lt;br /&gt;
|Subchannel&lt;br /&gt;
|-&lt;br /&gt;
|27-16&lt;br /&gt;
|Argument count (in 32-bits Words) or inline data (see below)&lt;br /&gt;
|-&lt;br /&gt;
|28?&lt;br /&gt;
|Hmm?&lt;br /&gt;
|-&lt;br /&gt;
|31-29&lt;br /&gt;
|[[#Submission_mode|Submission mode]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note: Methods are treated as 4-byte addressable locations, and hence their numbers are written down multiplied by 4.&lt;br /&gt;
&lt;br /&gt;
Note: The command&#039;s arguments, when present, follow the command word immediately.&lt;br /&gt;
&lt;br /&gt;
==== Submission mode ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Mode&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Offical name&lt;br /&gt;
|-&lt;br /&gt;
|0&lt;br /&gt;
|Increasing mode (old)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Increasing mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039;, while automatically incrementing the &#039;&#039;&#039;method&#039;&#039;&#039; value. This means that each argument will be written to a different method location.&lt;br /&gt;
|INCR&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Non-increasing mode (old)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Non-increasing mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039;. However, all arguments will be written to the same method location.&lt;br /&gt;
|NONINCR&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Inline mode - Tells PFIFO to read &#039;&#039;&#039;inline data&#039;&#039;&#039; from bits 28-16 of the command word, thus eliminating the need to pass additional words for the arguments.&lt;br /&gt;
|IMM&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|Increase-once mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039; and automatically increments the &#039;&#039;&#039;method&#039;&#039;&#039; value once only.&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Command List ===&lt;br /&gt;
&lt;br /&gt;
All methods with values &amp;lt; 0x100 are special and executed by the PFIFO&#039;s DMA puller. The others are forwarded to the engine object currently bound to a given subchannel.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Command || Method || Subchannel || Arg Count || Mode || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001?000 || 0x0000 || Variable || 1 || 1 || [[#BindObject|BindObject]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000040 || 0x40 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA???0045 || 0x45 || 0 || Variable || 5 || SetGraphMacroCode&lt;br /&gt;
|-&lt;br /&gt;
| 0x20020047 || 0x47 || 0 || 2 || 1 || SetGraphMacroEntry&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0049 || 0x49 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20056080 || 0x80 || 3 || Variable || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20016085 || 0x85 || 3 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20026086 || 0x86 || 3 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20026088 || 0x88 || 3 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2004608C || 0x8C || 3 || Variable || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20016091 || 0x91 || 3 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20026092 || 0x92 || 3 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20026094 || 0x94 || 3 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800160B5 || 0xB5 || 3 || 1 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800000BA || 0xBA || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x601000BE || 0xBE || 0 || 16 || 3 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200100BF || 0xBF || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200180C0 || 0xC0 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200400C9 || 0xC9 || 0 || 4 || 1 || SetOuterTessellationLevels&lt;br /&gt;
|-&lt;br /&gt;
| 0x200200CD || 0xCD || 0 || 2 || 1 || SetInnerTessellationLevels&lt;br /&gt;
|-&lt;br /&gt;
| 0x200100DC || 0xDC || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?00DF || 0xDF || 0 || Variable || 4 || SetRasterizerDiscard?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20048100 || 0x100 || 4 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20028102 || 0x102 || 4 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20018104 || 0x104 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20018105 || 0x105 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20018106 || 0x106 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C0 || 0x1C0 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C2 || 0x1C2 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C3 || 0x1C3 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200281C4 || 0x1C4 || 4 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C5 || 0x1C5 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C6 || 0x1C6 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C7 || 0x1C7 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C8 || 0x1C8 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181CA || 0x1CA || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181CB || 0x1CB || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181CC || 0x1CC || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181CD || 0x1CD || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181CF || 0x1CF || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800001D1 || 0x1D1 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200301F0 || 0x1F0 || 0 || 3 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800001F3 || 0x1F3 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200201F8 || 0x1F8 || 0 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200401FA || 0x1FA || 0 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20016223 || 0x223 || 3 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2004622C || 0x22C || 3 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20046230 || 0x230 || 3 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20046234 || 0x234 || 3 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200203?? || 0x3?? Variable || 0 || 2 || 1 || SetScissors?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20040360 || 0x360 || 0 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010364 || 0x364 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0368 || 0x368 || 0 || Variable  || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?036B || 0x36B || 0 || Variable  || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?036C || 0x36C || 0 || Variable  || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001036F || 0x36F || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000370 || 0x370 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000371 || 0x371 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000372 || 0x372 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8???0373 || 0x373 || 0 || Variable || 4 || SetPatchSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000374 || 0x374 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010376 || 0x376 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?03D5 || 0x3D5 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?03D6 || 0x3D6 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?03D7 || 0x3D7 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200103D9 || 0x3D9 || 0 || 1 || 1 || SetTiledCacheTileSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x80?003DE || 0x3DE || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800003E0 || 0x3E0 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200203E7 || 0x3E7 || 0 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800003ED || 0x3ED || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800203EE || 0x3EE || 0 || 2 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200403EF || 0x3EF || 0 || 4 || 1 || SetSampleMask&lt;br /&gt;
|-&lt;br /&gt;
| 0x800003F5 || 0x3F5 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800103F6 || 0x3F6 || 0 || 1 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200503F8 || 0x3F8 || 0 || 5 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200203FD || 0x3FD || 0 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2004040C || 0x40C || 0 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200C0420 || 0x420 || 0 || 12 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000446 || 0x446 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000451 || 0x451 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0452 || 0x452 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20100458 || 0x458 || 0 || 16 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20040478 || 0x478 || 0 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8000047C || 0x47C || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8000047E || 0x47E || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8001047F || 0x47F || 0 || 1 || 4 || ResolveDepthBuffer&lt;br /&gt;
|-&lt;br /&gt;
| 0x2003048A || 0x48A || 0 || 3 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04B3 || 0x4B3 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800104B9 || 0x4B9 || 0 || 1 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04BA || 0x4BA || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800004BB || 0x4BB || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04C3 || 0x4C3 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200104C4 || 0x4C4 || 0 || 1 || 1 || SetAlphaRef&lt;br /&gt;
|-&lt;br /&gt;
| 0x200404C7 || 0x4C7 || 0 || 4 || 1 || SetBlendColor&lt;br /&gt;
|-&lt;br /&gt;
| 0x800004E0 || 0x4E0 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04E5 || 0x4E5 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04E6 || 0x4E6 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04E7 || 0x4E7 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200204EC || 0x4EC || 0 || 2 || 1 || SetLineWidth&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?050D || 0x50D || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000519 || 0x519 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000540 || 0x540 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010546 || 0x546 || 0 || 1 || 1 || SetPointSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001054C || 0x54C || 0 || 1 || 1 || ResetCounter&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?054E || 0x54E || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20030554 || 0x554 || 0 || 3 || 1 || SetRenderEnableConditional&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0556 || 0x556 || 0 || Variable || 4 || SetRenderEnable?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001055B || 0x55B || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001056F || 0x56F || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000572 || 0x572 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0574 || 0x574 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8000057F || 0x57F || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000580 || 0x580 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000591 || 0x591 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010592 || 0x592 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200205F2 || 0x5F2 || 0 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?05F6 || 0x5F6 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001061F || 0x61F || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0620 || 0x620 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80010646 || 0x646 || 0 || 1 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0648 || 0x648 || 0 || Variable  || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001064F || 0x64F || 0 || 1 || 1 || SetDepthClamp&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?066F || 0x66F || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x120020671 || 0x671 || 0 || 2 || 9 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010674 || 0x674 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8000068B || 0x68B || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200406C0 || 0x6C0 || 0 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010703 || 0x703 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200207?? || 0x7?? Variable || 0 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80300830 || 0x830 || 0 || 48 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80400840 || 0x840 || 0 || 64 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80500850 || 0x850 || 0 || 80 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200308E0 || 0x8E0 || 0 || 3 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200308E3 || 0x8E3 || 0 || 3 || 1 || CB_POS(Const buffer position)&lt;br /&gt;
|-&lt;br /&gt;
| 0x200308E4 || 0x8E4 || 0 || 3 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80??0904 || 0x904 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80??090C || 0x90C || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80??0914 || 0x914 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80??091C || 0x91C || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80??0924 || 0x924 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000D1E || 0xD1E || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0D28 || 0xD28 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010D29 || 0xD29 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010D34 || 0xD34 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0020E00 || 0xE00 || 0 || 2 || 5 || BeginTransformFeedback&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010E02 || 0xE02 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80020E04 || 0xE04 || 0 || 2 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010E06 || 0xE06 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0030E0A || 0xE0A || 0 || 3 || 5 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80050E0C || 0xE0C || 0 || 5 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0E0E || 0xE0E || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010E10 || 0xE10 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0040E12 || 0xE12 || 0 || 4 || 5 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010E1A || 0xE1A || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0040E1C || 0xE1C || 0 || 4 || 5 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x81900E1E || 0xE1E || 0 || 400 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000E20 || 0xE20 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000E24 || 0xE24 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0040E2C || 0xE2C || 0 || 4 || 5 || PushDebugGroup&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0020E2E || 0xE2E || 0 || 2 || 5 || PopDebugGroupId&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0030E30 || 0xE30 || 0 || 3 || 5 || DrawArrays&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0050E32 || 0xE32 || 0 || 5 || 5 || DrawArraysIndirect?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0050E34 || 0xE34 || 0 || 5 || 5 || DrawArraysInstanced?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0050E36 || 0xE36 || 0 || 5 || 5 || DrawElements&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0060E38 || 0xE38 || 0 || 6 || 5 || DrawElementsIndirect?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0060E3A || 0xE3A || 0 || 6 || 5 || DrawElementsInstanced?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0050E42 || 0xE42 || 0 || 5 || 5 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0060E44 || 0xE44 || 0 || 6 || 5 || ?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note: These still need to be heavily verified and &#039;&#039;could&#039;&#039; be wrong.&lt;br /&gt;
&lt;br /&gt;
=== BindObject ===&lt;br /&gt;
&lt;br /&gt;
In order to bind an engine object to a specific subchannel, method 0 (BindObject) must be used first. The target subchannel is specified in bits 15-13 of the command word.&lt;br /&gt;
&lt;br /&gt;
After the engine object is bound to the desired subchannel, setting it&#039;s value in bits 15-13 of any subsequent command word will make PFIFO forward the command to the target engine.&lt;br /&gt;
&lt;br /&gt;
This method only takes one argument, an [[#Engine_IDs|engine ID]].&lt;br /&gt;
&lt;br /&gt;
==== Engine IDs ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| ID&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Engine&lt;br /&gt;
|-&lt;br /&gt;
|0x902D&lt;br /&gt;
|FERMI_TWOD_A (2D)&lt;br /&gt;
|-&lt;br /&gt;
|0xB197&lt;br /&gt;
|MAXWELL_B (3D)&lt;br /&gt;
|-&lt;br /&gt;
|0xB1C0&lt;br /&gt;
|MAXWELL_COMPUTE_B&lt;br /&gt;
|-&lt;br /&gt;
|0xA140&lt;br /&gt;
|KEPLER_INLINE_TO_MEMORY_B&lt;br /&gt;
|-&lt;br /&gt;
|0xB0B5&lt;br /&gt;
|MAXWELL_DMA_COPY_A (DMA)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Macro ===&lt;br /&gt;
&lt;br /&gt;
Macros are small programs that can be uploaded to the gpu and are capable of reading and writing to the 3D engine registers on the GPU. The macros also accepts parameters, stored on a FIFO. Macros can be called using methods starting at 0xe00, where the first method triggers the macro execution, and the second one is used to push parameters to the FIFO, that can be read from the macro program using a instruction called &#039;&#039;parm&#039;&#039;. This instruction pops the FIFO and reads the next parameter, while also allowing programs to use a variable number of parameters if desired.&lt;br /&gt;
&lt;br /&gt;
The first parameter is written to 0xe00 + n * 2 (where n is the macro index), and all subsequent parameters should be pushed to the FIFO using 0xe01 + n * 2. The first parameter is placed at the general purpose register R1 in the shader program when execution starts.&lt;br /&gt;
&lt;br /&gt;
Official games uses those macros to conditionally write registers, one example of such uses is the macro at 0xe24, that is used to set shader registers (including shader address and binding the c1 Constant Buffer to the shader). In some cases, it&#039;s also used to set registers unconditionally.&lt;br /&gt;
&lt;br /&gt;
=== Fences ===&lt;br /&gt;
&lt;br /&gt;
Command lists can contain fences to ensure that commands are executed on the correct order, and subsequent commands are only sent when the previously sent commands were already processed by the GPU. Fences uses the QUERY_* commands, and works like this:&lt;br /&gt;
&lt;br /&gt;
* First, QUERY_ADDRESS_HIGH and QUERY_ADDRESS_LOW commands are added to the Command List, with the High/Low 32 bits part of the 64-bits GPU Virtual Address where the fence is located. This GPU Virtual Address needs to be mapped to the process Virtual Address beforehand.&lt;br /&gt;
* Then, QUERY_SEQUENCE is added with a sequential number. This number is basically a incrementing counter, so the first Command List can have QUERY_SEQUENCE = 1, the next one QUERY_SEQUENCE = 2, 3, 4... and so on.&lt;br /&gt;
* Finally, QUERY_GET is added and contains the mode and other unknown data.&lt;br /&gt;
&lt;br /&gt;
The above commands are added using the [[#Submission_mode|increasing mode]], since the Ids for all those 4 registers are sequential.&lt;br /&gt;
&lt;br /&gt;
==== QUERY_GET Structure ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Bits&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|1-0&lt;br /&gt;
|Mode&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Fence&lt;br /&gt;
|-&lt;br /&gt;
|15-12&lt;br /&gt;
|Unit &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== QUERY_GET Mode ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Value&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Mode&lt;br /&gt;
|-&lt;br /&gt;
|0&lt;br /&gt;
|Write&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Sync&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Write ? &lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Write ?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
TODO: Move this to a separate page with all GPU Commands with descriptions. Also figure out what the other values mean.&lt;br /&gt;
&lt;br /&gt;
Some of the other fields are still unknown/unobserved.&lt;br /&gt;
&lt;br /&gt;
Official games will set Mode to 0, Fence to 1 and Unit to 0xF. The QUERY_SEQUENCE value is then written by the GPU to the address pointed to by QUERY_ADDRESS.&lt;br /&gt;
On the CPU side, the game code should wait until the value at the address pointed to by QUERY_ADDRESS is &amp;gt;= to the last written SEQUENCE value. Official code waits for this condition to be true on a loop, and won&#039;t send any further commands before that.&lt;br /&gt;
&lt;br /&gt;
== Vertex Data Submission ==&lt;br /&gt;
&lt;br /&gt;
Note: This is a observation on how the game Puyo Puyo Tetris sends textured squares to the GPU.&lt;br /&gt;
&lt;br /&gt;
# VERTEX_ATTRIB_FORMAT (0-15) are set (only the first 3 are really used, the rest are set float, with Size = 1 and offset at 0).&lt;br /&gt;
# VERTEX_ARRAY_FETCH (0) is set with the lower 12 bits set to 0x1c (Stride) and bit 12 to 1 (Enabled).&lt;br /&gt;
# VERTEX_ARRAY_START_HIGH/LOW (0) are set to the GPU Virtual Address where the Vertex Data is located.&lt;br /&gt;
# VERTEX_ARRAY_LIMIT_HIGH/LOW (0) are set to the GPU Virtual Address where the Vertex Data is located, plus the Vertex Data size in bytes minus 1.&lt;br /&gt;
# VERTEX_BEGIN_GL is used with the primitive type set to TRIANGLE_STRIP.&lt;br /&gt;
# VERTEX_BUFFER_FIRST with value 0 (indicating the index of the first primitive to render?).&lt;br /&gt;
# VERTEX_BUFFER_COUNT is set to 4, because the Vertex Buffer with the square has 4 vertices.&lt;br /&gt;
# VERTEX_END_GL is used with value 0 (currently unknown what this value means).&lt;br /&gt;
&lt;br /&gt;
== Texture View ==&lt;br /&gt;
&lt;br /&gt;
Texture information such as address, format and size is sent to the GPU through a structure know as Texture View (a.k.a. Texture Image Control, or TIC). Each texture that the game uses needs a separate TIC, and those TICs are written to a table, one after the other. Each [[#TIC_Structure|TIC entry]] has 0x20 bytes, and is composed of 8 32-bits words where the texture information is packed.&lt;br /&gt;
&lt;br /&gt;
The index of the TIC entries that should be used by the shader is sent to the GPU with the CB_POS/CB_DATA (0) methods. Games usually follows the following steps to write the TIC entry indexes:&lt;br /&gt;
&lt;br /&gt;
* Macro 0xe1a is used to set CB_ADDRESS_HIGH/LOW registers to the GPU Virtual Address of the Constant Buffer set on the register 0x982 (the &#039;&#039;Texture Constant Buffer&#039;&#039; index register), and also sets CB_SIZE.&lt;br /&gt;
* CB_POS is used to set the write offset of the Constant Buffer to 0x20 + n * 4, where &#039;&#039;n&#039;&#039; is the index of the &#039;&#039;Handle&#039;&#039; being used on the shader sampler.&lt;br /&gt;
* CB_DATA (0) method is used to write the value into the Constant Buffer. The value is a &#039;&#039;Handle&#039;&#039; where the lower 20 bits is the TIC index, and the higher 12 bits is the TSC (Texture Sampler Control) index.&lt;br /&gt;
&lt;br /&gt;
The address of a given TIC entry can be calculates as:&lt;br /&gt;
&lt;br /&gt;
 tic_entry_address = tic_base_address + tic_index * 0x20&lt;br /&gt;
&lt;br /&gt;
Where &#039;&#039;tic_base_address&#039;&#039; is the address written to TIC_ADDRESS_HIGH/LOW (methods 0x1574 and 0x1578), &#039;&#039;tic_index&#039;&#039; is the lower 20 bits of the word written into the Const Buffer with CB_DATA (0), and 0x20 is the size of each TIC entry in bytes.&lt;br /&gt;
&lt;br /&gt;
The texture is accessed on the shader using one of the texture sampling instructions (usually the TEXS instruction). One of the parameters for this instruction is the &#039;&#039;Handle&#039;&#039; index. This index start at 8, so the index 8 will access the handle at 8 * 4 = 0x20 on the &#039;&#039;Texture Constant Buffer&#039;&#039;. Each shader stage has a separate Constant Buffer, so for fragment shaders, this is located at CB_ADDRESS + 4 * CB_SIZE + TEXS_index * 4 (where 4 is the index of the fragment shader stage).&lt;br /&gt;
&lt;br /&gt;
=== TIC Structure ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Word || Bits || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 6-0 || [[GPU_Texture_Formats#Texture_Formats|Texture Format]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 9-7 || [[#Channel_Data_Type|R Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 12-10 || [[#Channel_Data_Type|G Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 15-13 || [[#Channel_Data_Type|B Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 18-16 || [[#Channel_Data_Type|A Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 31-0 || Lower 32-bits of the Texture GPU Virtual Address&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 15-0 || Higher 16-bits of the Texture GPU Virtual Address&lt;br /&gt;
|-&lt;br /&gt;
| 4 || 15-0 || Texture Width minus 1&lt;br /&gt;
|-&lt;br /&gt;
| 5 || 15-0 || Texture Height minus 1&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Channel Data Type ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Type&lt;br /&gt;
|-&lt;br /&gt;
| 1 || SNORM&lt;br /&gt;
|-&lt;br /&gt;
| 2 || UNORM&lt;br /&gt;
|-&lt;br /&gt;
| 3 || SINT&lt;br /&gt;
|-&lt;br /&gt;
| 4 || UINT&lt;br /&gt;
|-&lt;br /&gt;
| 5 || SNORM_FORCE_FP16&lt;br /&gt;
|-&lt;br /&gt;
| 6 || UNORM_FORCE_FP16&lt;br /&gt;
|-&lt;br /&gt;
| 7 || FLOAT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
FIFO engine overview:&lt;br /&gt;
[https://envytools.readthedocs.io/en/latest/hw/fifo/intro.html]&lt;br /&gt;
&lt;br /&gt;
Method values from the Fermi family GPU (a bit older than the Tegra X1, but values seems to be mostly the same):&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/gf100_3d.xml]&lt;br /&gt;
&lt;br /&gt;
TIC structure used on a Maxwell GPU:&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/gm200_texture.xml]&lt;br /&gt;
&lt;br /&gt;
Values for some types used on the above XML:&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/nv_3ddefs.xml]&lt;br /&gt;
&lt;br /&gt;
Command word packing code used on Mesa3d:&lt;br /&gt;
[https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nvc0/nvc0_winsys.h]&lt;br /&gt;
&lt;br /&gt;
TIC entry pack/write code used on Mesa3d:&lt;br /&gt;
[https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c#n65]&lt;/div&gt;</summary>
		<author><name>Gdkchan</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=GPU&amp;diff=4378</id>
		<title>GPU</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=GPU&amp;diff=4378"/>
		<updated>2018-03-30T15:05:06Z</updated>

		<summary type="html">&lt;p&gt;Gdkchan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Mapping Memory ==&lt;br /&gt;
&lt;br /&gt;
First, to map a memory region on the GPU Address Space, caching needs to be disabled by using [[SVC#svcSetMemoryAttribute|svcSetMemoryAttribute]]. The Address passed is the Virtual Address of the region that will be mapped, the size is the region size, and State0/1 are both set to 8 to disable caching of the memory region. This is done to ensure that the GPU can actually &amp;quot;see&amp;quot; the data written there, and it doesn&#039;t get stuck on some cache.&lt;br /&gt;
&lt;br /&gt;
Then, [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]] is used to create a nvmap object with the desired size. After, [[NV_services#NVMAP_IOC_ALLOC|NVMAP_IOC_ALLOC]] is used to allocate the memory on the GPU Address Space, and map data on the process Address Space into the GPU Address Space, by passing the Virtual Address as the input addr parameter, and also the Handle returned from [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]]. Lastly, the actual mapping is done by using [[NV_services#NVGPU_AS_IOCTL_MAP_BUFFER_EX|NVGPU_AS_IOCTL_MAP_BUFFER_EX]], and the GPU Virtual Address is returned on the offset parameter. It&#039;s also possible to manually set the offset where the mapping should be made on the GPU Address Space, by passing the address on the &amp;quot;offset&amp;quot; parameter, and setting the bit 0 of the flags parameter to 1. However, for this to work, the desired GPU Virtual Address needs to be previously reserved using [[NV_services#NVGPU_AS_IOCTL_ALLOC_SPACE|NVGPU_AS_IOCTL_ALLOC_SPACE]].&lt;br /&gt;
&lt;br /&gt;
The above process is used to map all data that will be used by the GPU, like Textures, Command Lists (a.k.a. Push Buffers), Vertex/Index buffers and Shaders. They usually have their own mapping, but Command Lists can share the same mapping.&lt;br /&gt;
&lt;br /&gt;
== FIFO Commands ==&lt;br /&gt;
&lt;br /&gt;
The GPU implements a variation of Tegra&#039;s push buffer format for it&#039;s PFIFO engine. PFIFO is a special engine responsible for receiving user command lists and routing them to the appropriate engines (2D, 3D, DMA).&lt;br /&gt;
&lt;br /&gt;
Commands are submitted to the GPU&#039;s PFIFO engine through [[NV_services#NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO|NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO]].&lt;br /&gt;
&lt;br /&gt;
This ioctl takes an array of gpfifo entries where each entry points to a FIFO command list. This list is composed of alternating 32-bit words containing FIFO commands and their respective arguments.&lt;br /&gt;
&lt;br /&gt;
=== Command Structure ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Bits&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|12-0&lt;br /&gt;
|Method&lt;br /&gt;
|-&lt;br /&gt;
|15-13&lt;br /&gt;
|Subchannel&lt;br /&gt;
|-&lt;br /&gt;
|27-16&lt;br /&gt;
|Argument count (in 32-bits Words) or inline data (see below)&lt;br /&gt;
|-&lt;br /&gt;
|28?&lt;br /&gt;
|Hmm?&lt;br /&gt;
|-&lt;br /&gt;
|31-29&lt;br /&gt;
|[[#Submission_mode|Submission mode]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note: Methods are treated as 4-byte addressable locations, and hence their numbers are written down multiplied by 4.&lt;br /&gt;
&lt;br /&gt;
Note: The command&#039;s arguments, when present, follow the command word immediately.&lt;br /&gt;
&lt;br /&gt;
==== Submission mode ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Mode&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Offical name&lt;br /&gt;
|-&lt;br /&gt;
|0&lt;br /&gt;
|Increasing mode (old)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Increasing mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039;, while automatically incrementing the &#039;&#039;&#039;method&#039;&#039;&#039; value. This means that each argument will be written to a different method location.&lt;br /&gt;
|INCR&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Non-increasing mode (old)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Non-increasing mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039;. However, all arguments will be written to the same method location.&lt;br /&gt;
|NONINCR&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Inline mode - Tells PFIFO to read &#039;&#039;&#039;inline data&#039;&#039;&#039; from bits 28-16 of the command word, thus eliminating the need to pass additional words for the arguments.&lt;br /&gt;
|IMM&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|Increase-once mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039; and automatically increments the &#039;&#039;&#039;method&#039;&#039;&#039; value once only.&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Command List ===&lt;br /&gt;
&lt;br /&gt;
All methods with values &amp;lt; 0x100 are special and executed by the PFIFO&#039;s DMA puller. The others are forwarded to the engine object currently bound to a given subchannel.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Command || Method || Subchannel || Arg Count || Mode || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001?000 || 0x0000 || Variable || 1 || 1 || [[#BindObject|BindObject]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000040 || 0x40 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA???0045 || 0x45 || 0 || Variable || 5 || SetGraphMacroCode&lt;br /&gt;
|-&lt;br /&gt;
| 0x20020047 || 0x47 || 0 || 2 || 1 || SetGraphMacroEntry&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0049 || 0x49 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20056080 || 0x80 || 3 || Variable || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20016085 || 0x85 || 3 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20026086 || 0x86 || 3 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20026088 || 0x88 || 3 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2004608C || 0x8C || 3 || Variable || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20016091 || 0x91 || 3 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20026092 || 0x92 || 3 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20026094 || 0x94 || 3 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800160B5 || 0xB5 || 3 || 1 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800000BA || 0xBA || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x601000BE || 0xBE || 0 || 16 || 3 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200100BF || 0xBF || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200180C0 || 0xC0 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200400C9 || 0xC9 || 0 || 4 || 1 || SetOuterTessellationLevels&lt;br /&gt;
|-&lt;br /&gt;
| 0x200200CD || 0xCD || 0 || 2 || 1 || SetInnerTessellationLevels&lt;br /&gt;
|-&lt;br /&gt;
| 0x200100DC || 0xDC || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?00DF || 0xDF || 0 || Variable || 4 || SetRasterizerDiscard?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20048100 || 0x100 || 4 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20028102 || 0x102 || 4 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20018104 || 0x104 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20018105 || 0x105 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20018106 || 0x106 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C0 || 0x1C0 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C2 || 0x1C2 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C3 || 0x1C3 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200281C4 || 0x1C4 || 4 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C5 || 0x1C5 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C6 || 0x1C6 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C7 || 0x1C7 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C8 || 0x1C8 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181CA || 0x1CA || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181CB || 0x1CB || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181CC || 0x1CC || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181CD || 0x1CD || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181CF || 0x1CF || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800001D1 || 0x1D1 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200301F0 || 0x1F0 || 0 || 3 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800001F3 || 0x1F3 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200201F8 || 0x1F8 || 0 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200401FA || 0x1FA || 0 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20016223 || 0x223 || 3 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2004622C || 0x22C || 3 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20046230 || 0x230 || 3 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20046234 || 0x234 || 3 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200203?? || 0x3?? Variable || 0 || 2 || 1 || SetScissors?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20040360 || 0x360 || 0 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010364 || 0x364 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0368 || 0x368 || 0 || Variable  || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?036B || 0x36B || 0 || Variable  || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?036C || 0x36C || 0 || Variable  || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001036F || 0x36F || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000370 || 0x370 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000371 || 0x371 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000372 || 0x372 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8???0373 || 0x373 || 0 || Variable || 4 || SetPatchSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000374 || 0x374 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010376 || 0x376 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?03D5 || 0x3D5 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?03D6 || 0x3D6 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?03D7 || 0x3D7 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200103D9 || 0x3D9 || 0 || 1 || 1 || SetTiledCacheTileSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x80?003DE || 0x3DE || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800003E0 || 0x3E0 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200203E7 || 0x3E7 || 0 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800003ED || 0x3ED || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800203EE || 0x3EE || 0 || 2 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200403EF || 0x3EF || 0 || 4 || 1 || SetSampleMask&lt;br /&gt;
|-&lt;br /&gt;
| 0x800003F5 || 0x3F5 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800103F6 || 0x3F6 || 0 || 1 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200503F8 || 0x3F8 || 0 || 5 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200203FD || 0x3FD || 0 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2004040C || 0x40C || 0 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200C0420 || 0x420 || 0 || 12 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000446 || 0x446 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000451 || 0x451 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0452 || 0x452 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20100458 || 0x458 || 0 || 16 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20040478 || 0x478 || 0 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8000047C || 0x47C || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8000047E || 0x47E || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8001047F || 0x47F || 0 || 1 || 4 || ResolveDepthBuffer&lt;br /&gt;
|-&lt;br /&gt;
| 0x2003048A || 0x48A || 0 || 3 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04B3 || 0x4B3 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800104B9 || 0x4B9 || 0 || 1 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04BA || 0x4BA || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800004BB || 0x4BB || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04C3 || 0x4C3 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200104C4 || 0x4C4 || 0 || 1 || 1 || SetAlphaRef&lt;br /&gt;
|-&lt;br /&gt;
| 0x200404C7 || 0x4C7 || 0 || 4 || 1 || SetBlendColor&lt;br /&gt;
|-&lt;br /&gt;
| 0x800004E0 || 0x4E0 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04E5 || 0x4E5 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04E6 || 0x4E6 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04E7 || 0x4E7 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200204EC || 0x4EC || 0 || 2 || 1 || SetLineWidth&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?050D || 0x50D || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000519 || 0x519 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000540 || 0x540 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010546 || 0x546 || 0 || 1 || 1 || SetPointSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001054C || 0x54C || 0 || 1 || 1 || ResetCounter&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?054E || 0x54E || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20030554 || 0x554 || 0 || 3 || 1 || SetRenderEnableConditional&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0556 || 0x556 || 0 || Variable || 4 || SetRenderEnable?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001055B || 0x55B || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001056F || 0x56F || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000572 || 0x572 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0574 || 0x574 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8000057F || 0x57F || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000580 || 0x580 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000591 || 0x591 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010592 || 0x592 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200205F2 || 0x5F2 || 0 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?05F6 || 0x5F6 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001061F || 0x61F || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0620 || 0x620 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80010646 || 0x646 || 0 || 1 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0648 || 0x648 || 0 || Variable  || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001064F || 0x64F || 0 || 1 || 1 || SetDepthClamp&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?066F || 0x66F || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x120020671 || 0x671 || 0 || 2 || 9 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010674 || 0x674 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8000068B || 0x68B || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200406C0 || 0x6C0 || 0 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010703 || 0x703 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200207?? || 0x7?? Variable || 0 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80300830 || 0x830 || 0 || 48 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80400840 || 0x840 || 0 || 64 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80500850 || 0x850 || 0 || 80 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200308E0 || 0x8E0 || 0 || 3 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200308E3 || 0x8E3 || 0 || 3 || 1 || CB_POS(Const buffer position)&lt;br /&gt;
|-&lt;br /&gt;
| 0x200308E4 || 0x8E4 || 0 || 3 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80??0904 || 0x904 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80??090C || 0x90C || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80??0914 || 0x914 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80??091C || 0x91C || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80??0924 || 0x924 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000D1E || 0xD1E || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0D28 || 0xD28 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010D29 || 0xD29 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010D34 || 0xD34 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0020E00 || 0xE00 || 0 || 2 || 5 || BeginTransformFeedback&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010E02 || 0xE02 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80020E04 || 0xE04 || 0 || 2 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010E06 || 0xE06 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0030E0A || 0xE0A || 0 || 3 || 5 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80050E0C || 0xE0C || 0 || 5 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0E0E || 0xE0E || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010E10 || 0xE10 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0040E12 || 0xE12 || 0 || 4 || 5 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010E1A || 0xE1A || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0040E1C || 0xE1C || 0 || 4 || 5 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x81900E1E || 0xE1E || 0 || 400 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000E20 || 0xE20 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000E24 || 0xE24 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0040E2C || 0xE2C || 0 || 4 || 5 || PushDebugGroup&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0020E2E || 0xE2E || 0 || 2 || 5 || PopDebugGroupId&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0030E30 || 0xE30 || 0 || 3 || 5 || DrawArrays&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0050E32 || 0xE32 || 0 || 5 || 5 || DrawArraysIndirect?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0050E34 || 0xE34 || 0 || 5 || 5 || DrawArraysInstanced?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0050E36 || 0xE36 || 0 || 5 || 5 || DrawElements&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0060E38 || 0xE38 || 0 || 6 || 5 || DrawElementsIndirect?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0060E3A || 0xE3A || 0 || 6 || 5 || DrawElementsInstanced?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0050E42 || 0xE42 || 0 || 5 || 5 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0060E44 || 0xE44 || 0 || 6 || 5 || ?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note: These still need to be heavily verified and &#039;&#039;could&#039;&#039; be wrong.&lt;br /&gt;
&lt;br /&gt;
=== BindObject ===&lt;br /&gt;
&lt;br /&gt;
In order to bind an engine object to a specific subchannel, method 0 (BindObject) must be used first. The target subchannel is specified in bits 15-13 of the command word.&lt;br /&gt;
&lt;br /&gt;
After the engine object is bound to the desired subchannel, setting it&#039;s value in bits 15-13 of any subsequent command word will make PFIFO forward the command to the target engine.&lt;br /&gt;
&lt;br /&gt;
This method only takes one argument, an [[#Engine_IDs|engine ID]].&lt;br /&gt;
&lt;br /&gt;
==== Engine IDs ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| ID&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Engine&lt;br /&gt;
|-&lt;br /&gt;
|0x902D&lt;br /&gt;
|FERMI_TWOD_A (2D)&lt;br /&gt;
|-&lt;br /&gt;
|0xB197&lt;br /&gt;
|MAXWELL_B (3D)&lt;br /&gt;
|-&lt;br /&gt;
|0xB1C0&lt;br /&gt;
|MAXWELL_COMPUTE_B&lt;br /&gt;
|-&lt;br /&gt;
|0xA140&lt;br /&gt;
|KEPLER_INLINE_TO_MEMORY_B&lt;br /&gt;
|-&lt;br /&gt;
|0xB0B5&lt;br /&gt;
|MAXWELL_DMA_COPY_A (DMA)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Macro ===&lt;br /&gt;
&lt;br /&gt;
Macros are small programs that can be uploaded to the gpu and are capable of reading and writing to the 3D engine registers on the GPU. The macros also accepts parameters, stored on a FIFO. Macros can be called using methods starting at 0xe00, where the first method triggers the macro execution, and the second one is used to push parameters to the FIFO, that can be read from the macro program using a instruction called &#039;&#039;parm&#039;&#039;. This instruction pops the FIFO and reads the next parameter, while also allowing programs to use a variable number of parameters if desired.&lt;br /&gt;
&lt;br /&gt;
The first parameter is written to 0xe00 + n * 2 (where n is the macro index), and all subsequent parameters should be pushed to the FIFO using 0xe01 + n * 2. The first parameter is placed the general purpose register R1 in the shader program when execution starts.&lt;br /&gt;
&lt;br /&gt;
Official games uses those macros to conditionally write registers, one example of such uses it the macro at 0xe24, that is used to set shader registers (including shader address and binding the c1 Constant Buffer to the shader). In some cases, it&#039;s also used to set registers unconditionally.&lt;br /&gt;
&lt;br /&gt;
=== Fences ===&lt;br /&gt;
&lt;br /&gt;
Command lists can contain fences to ensure that commands are executed on the correct order, and subsequent commands are only sent when the previously sent commands were already processed by the GPU. Fences uses the QUERY_* commands, and works like this:&lt;br /&gt;
&lt;br /&gt;
* First, QUERY_ADDRESS_HIGH and QUERY_ADDRESS_LOW commands are added to the Command List, with the High/Low 32 bits part of the 64-bits GPU Virtual Address where the fence is located. This GPU Virtual Address needs to be mapped to the process Virtual Address beforehand.&lt;br /&gt;
* Then, QUERY_SEQUENCE is added with a sequential number. This number is basically a incrementing counter, so the first Command List can have QUERY_SEQUENCE = 1, the next one QUERY_SEQUENCE = 2, 3, 4... and so on.&lt;br /&gt;
* Finally, QUERY_GET is added and contains the mode and other unknown data.&lt;br /&gt;
&lt;br /&gt;
The above commands are added using the [[#Submission_mode|increasing mode]], since the Ids for all those 4 registers are sequential.&lt;br /&gt;
&lt;br /&gt;
==== QUERY_GET Structure ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Bits&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|1-0&lt;br /&gt;
|Mode&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Fence&lt;br /&gt;
|-&lt;br /&gt;
|15-12&lt;br /&gt;
|Unit &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== QUERY_GET Mode ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Value&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Mode&lt;br /&gt;
|-&lt;br /&gt;
|0&lt;br /&gt;
|Write&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Sync&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Write ? &lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Write ?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
TODO: Move this to a separate page with all GPU Commands with descriptions. Also figure out what the other values mean.&lt;br /&gt;
&lt;br /&gt;
Some of the other fields are still unknown/unobserved.&lt;br /&gt;
&lt;br /&gt;
Official games will set Mode to 0, Fence to 1 and Unit to 0xF. The QUERY_SEQUENCE value is then written by the GPU to the address pointed to by QUERY_ADDRESS.&lt;br /&gt;
On the CPU side, the game code should wait until the value at the address pointed to by QUERY_ADDRESS is &amp;gt;= to the last written SEQUENCE value. Official code waits for this condition to be true on a loop, and won&#039;t send any further commands before that.&lt;br /&gt;
&lt;br /&gt;
== Vertex Data Submission ==&lt;br /&gt;
&lt;br /&gt;
Note: This is a observation on how the game Puyo Puyo Tetris sends textured squares to the GPU.&lt;br /&gt;
&lt;br /&gt;
# VERTEX_ATTRIB_FORMAT (0-15) are set (only the first 3 are really used, the rest are set float, with Size = 1 and offset at 0).&lt;br /&gt;
# VERTEX_ARRAY_FETCH (0) is set with the lower 12 bits set to 0x1c (Stride) and bit 12 to 1 (Enabled).&lt;br /&gt;
# VERTEX_ARRAY_START_HIGH/LOW (0) are set to the GPU Virtual Address where the Vertex Data is located.&lt;br /&gt;
# VERTEX_ARRAY_LIMIT_HIGH/LOW (0) are set to the GPU Virtual Address where the Vertex Data is located, plus the Vertex Data size in bytes minus 1.&lt;br /&gt;
# VERTEX_BEGIN_GL is used with the primitive type set to TRIANGLE_STRIP.&lt;br /&gt;
# VERTEX_BUFFER_FIRST with value 0 (indicating the index of the first primitive to render?).&lt;br /&gt;
# VERTEX_BUFFER_COUNT is set to 4, because the Vertex Buffer with the square has 4 vertices.&lt;br /&gt;
# VERTEX_END_GL is used with value 0 (currently unknown what this value means).&lt;br /&gt;
&lt;br /&gt;
== Texture View ==&lt;br /&gt;
&lt;br /&gt;
Texture information such as address, format and size is sent to the GPU through a structure know as Texture View (a.k.a. Texture Image Control, or TIC). Each texture that the game uses needs a separate TIC, and those TICs are written to a table, one after the other. Each [[#TIC_Structure|TIC entry]] has 0x20 bytes, and is composed of 8 32-bits words where the texture information is packed.&lt;br /&gt;
&lt;br /&gt;
The index of the TIC entries that should be used by the shader is sent to the GPU with the CB_POS/CB_DATA (0) methods. Games usually follows the following steps to write the TIC entry indexes:&lt;br /&gt;
&lt;br /&gt;
* Macro 0xe1a is used to set CB_ADDRESS_HIGH/LOW registers to the GPU Virtual Address of the Constant Buffer set on the register 0x982 (the &#039;&#039;Texture Constant Buffer&#039;&#039; index register), and also sets CB_SIZE.&lt;br /&gt;
* CB_POS is used to set the write offset of the Constant Buffer to 0x20 + n * 4, where &#039;&#039;n&#039;&#039; is the index of the &#039;&#039;Handle&#039;&#039; being used on the shader sampler.&lt;br /&gt;
* CB_DATA (0) method is used to write the value into the Constant Buffer. The value is a &#039;&#039;Handle&#039;&#039; where the lower 20 bits is the TIC index, and the higher 12 bits is the TSC (Texture Sampler Control) index.&lt;br /&gt;
&lt;br /&gt;
The address of a given TIC entry can be calculates as:&lt;br /&gt;
&lt;br /&gt;
 tic_entry_address = tic_base_address + tic_index * 0x20&lt;br /&gt;
&lt;br /&gt;
Where &#039;&#039;tic_base_address&#039;&#039; is the address written to TIC_ADDRESS_HIGH/LOW (methods 0x1574 and 0x1578), &#039;&#039;tic_index&#039;&#039; is the lower 20 bits of the word written into the Const Buffer with CB_DATA (0), and 0x20 is the size of each TIC entry in bytes.&lt;br /&gt;
&lt;br /&gt;
The texture is accessed on the shader using one of the texture sampling instructions (usually the TEXS instruction). One of the parameters for this instruction is the &#039;&#039;Handle&#039;&#039; index. This index start at 8, so the index 8 will access the handle at 8 * 4 = 0x20 on the &#039;&#039;Texture Constant Buffer&#039;&#039;. Each shader stage has a separate Constant Buffer, so for fragment shaders, this is located at CB_ADDRESS + 4 * CB_SIZE + TEXS_index * 4 (where 4 is the index of the fragment shader stage).&lt;br /&gt;
&lt;br /&gt;
=== TIC Structure ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Word || Bits || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 6-0 || [[GPU_Texture_Formats#Texture_Formats|Texture Format]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 9-7 || [[#Channel_Data_Type|R Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 12-10 || [[#Channel_Data_Type|G Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 15-13 || [[#Channel_Data_Type|B Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 18-16 || [[#Channel_Data_Type|A Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 31-0 || Lower 32-bits of the Texture GPU Virtual Address&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 15-0 || Higher 16-bits of the Texture GPU Virtual Address&lt;br /&gt;
|-&lt;br /&gt;
| 4 || 15-0 || Texture Width minus 1&lt;br /&gt;
|-&lt;br /&gt;
| 5 || 15-0 || Texture Height minus 1&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Channel Data Type ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Type&lt;br /&gt;
|-&lt;br /&gt;
| 1 || SNORM&lt;br /&gt;
|-&lt;br /&gt;
| 2 || UNORM&lt;br /&gt;
|-&lt;br /&gt;
| 3 || SINT&lt;br /&gt;
|-&lt;br /&gt;
| 4 || UINT&lt;br /&gt;
|-&lt;br /&gt;
| 5 || SNORM_FORCE_FP16&lt;br /&gt;
|-&lt;br /&gt;
| 6 || UNORM_FORCE_FP16&lt;br /&gt;
|-&lt;br /&gt;
| 7 || FLOAT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
FIFO engine overview:&lt;br /&gt;
[https://envytools.readthedocs.io/en/latest/hw/fifo/intro.html]&lt;br /&gt;
&lt;br /&gt;
Method values from the Fermi family GPU (a bit older than the Tegra X1, but values seems to be mostly the same):&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/gf100_3d.xml]&lt;br /&gt;
&lt;br /&gt;
TIC structure used on a Maxwell GPU:&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/gm200_texture.xml]&lt;br /&gt;
&lt;br /&gt;
Values for some types used on the above XML:&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/nv_3ddefs.xml]&lt;br /&gt;
&lt;br /&gt;
Command word packing code used on Mesa3d:&lt;br /&gt;
[https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nvc0/nvc0_winsys.h]&lt;br /&gt;
&lt;br /&gt;
TIC entry pack/write code used on Mesa3d:&lt;br /&gt;
[https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c#n65]&lt;/div&gt;</summary>
		<author><name>Gdkchan</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=GPU&amp;diff=4376</id>
		<title>GPU</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=GPU&amp;diff=4376"/>
		<updated>2018-03-30T15:00:46Z</updated>

		<summary type="html">&lt;p&gt;Gdkchan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Mapping Memory ==&lt;br /&gt;
&lt;br /&gt;
First, to map a memory region on the GPU Address Space, caching needs to be disabled by using [[SVC#svcSetMemoryAttribute|svcSetMemoryAttribute]]. The Address passed is the Virtual Address of the region that will be mapped, the size is the region size, and State0/1 are both set to 8 to disable caching of the memory region. This is done to ensure that the GPU can actually &amp;quot;see&amp;quot; the data written there, and it doesn&#039;t get stuck on some cache.&lt;br /&gt;
&lt;br /&gt;
Then, [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]] is used to create a nvmap object with the desired size. After, [[NV_services#NVMAP_IOC_ALLOC|NVMAP_IOC_ALLOC]] is used to allocate the memory on the GPU Address Space, and map data on the process Address Space into the GPU Address Space, by passing the Virtual Address as the input addr parameter, and also the Handle returned from [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]]. Lastly, the actual mapping is done by using [[NV_services#NVGPU_AS_IOCTL_MAP_BUFFER_EX|NVGPU_AS_IOCTL_MAP_BUFFER_EX]], and the GPU Virtual Address is returned on the offset parameter. It&#039;s also possible to manually set the offset where the mapping should be made on the GPU Address Space, by passing the address on the &amp;quot;offset&amp;quot; parameter, and setting the bit 0 of the flags parameter to 1. However, for this to work, the desired GPU Virtual Address needs to be previously reserved using [[NV_services#NVGPU_AS_IOCTL_ALLOC_SPACE|NVGPU_AS_IOCTL_ALLOC_SPACE]].&lt;br /&gt;
&lt;br /&gt;
The above process is used to map all data that will be used by the GPU, like Textures, Command Lists (a.k.a. Push Buffers), Vertex/Index buffers and Shaders. They usually have their own mapping, but Command Lists can share the same mapping.&lt;br /&gt;
&lt;br /&gt;
== FIFO Commands ==&lt;br /&gt;
&lt;br /&gt;
The GPU implements a variation of Tegra&#039;s push buffer format for it&#039;s PFIFO engine. PFIFO is a special engine responsible for receiving user command lists and routing them to the appropriate engines (2D, 3D, DMA).&lt;br /&gt;
&lt;br /&gt;
Commands are submitted to the GPU&#039;s PFIFO engine through [[NV_services#NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO|NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO]].&lt;br /&gt;
&lt;br /&gt;
This ioctl takes an array of gpfifo entries where each entry points to a FIFO command list. This list is composed of alternating 32-bit words containing FIFO commands and their respective arguments.&lt;br /&gt;
&lt;br /&gt;
=== Command Structure ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Bits&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|12-0&lt;br /&gt;
|Method&lt;br /&gt;
|-&lt;br /&gt;
|15-13&lt;br /&gt;
|Subchannel&lt;br /&gt;
|-&lt;br /&gt;
|27-16&lt;br /&gt;
|Argument count (in 32-bits Words) or inline data (see below)&lt;br /&gt;
|-&lt;br /&gt;
|28?&lt;br /&gt;
|Hmm?&lt;br /&gt;
|-&lt;br /&gt;
|31-29&lt;br /&gt;
|[[#Submission_mode|Submission mode]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note: Methods are treated as 4-byte addressable locations, and hence their numbers are written down multiplied by 4.&lt;br /&gt;
&lt;br /&gt;
Note: The command&#039;s arguments, when present, follow the command word immediately.&lt;br /&gt;
&lt;br /&gt;
==== Submission mode ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Mode&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Offical name&lt;br /&gt;
|-&lt;br /&gt;
|0&lt;br /&gt;
|Increasing mode (old)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Increasing mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039;, while automatically incrementing the &#039;&#039;&#039;method&#039;&#039;&#039; value. This means that each argument will be written to a different method location.&lt;br /&gt;
|INCR&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Non-increasing mode (old)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Non-increasing mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039;. However, all arguments will be written to the same method location.&lt;br /&gt;
|NONINCR&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Inline mode - Tells PFIFO to read &#039;&#039;&#039;inline data&#039;&#039;&#039; from bits 28-16 of the command word, thus eliminating the need to pass additional words for the arguments.&lt;br /&gt;
|IMM&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|Increase-once mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039; and automatically increments the &#039;&#039;&#039;method&#039;&#039;&#039; value once only.&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Command List ===&lt;br /&gt;
&lt;br /&gt;
All methods with values &amp;lt; 0x100 are special and executed by the PFIFO&#039;s DMA puller. The others are forwarded to the engine object currently bound to a given subchannel.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Command || Method || Subchannel || Arg Count || Mode || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001?000 || 0x0000 || Variable || 1 || 1 || [[#BindObject|BindObject]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000040 || 0x40 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA???0045 || 0x45 || 0 || Variable || 5 || SetGraphMacroCode&lt;br /&gt;
|-&lt;br /&gt;
| 0x20020047 || 0x47 || 0 || 2 || 1 || SetGraphMacroEntry&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0049 || 0x49 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20056080 || 0x80 || 3 || Variable || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20016085 || 0x85 || 3 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20026086 || 0x86 || 3 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20026088 || 0x88 || 3 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2004608C || 0x8C || 3 || Variable || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20016091 || 0x91 || 3 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20026092 || 0x92 || 3 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20026094 || 0x94 || 3 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800160B5 || 0xB5 || 3 || 1 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800000BA || 0xBA || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x601000BE || 0xBE || 0 || 16 || 3 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200100BF || 0xBF || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200180C0 || 0xC0 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200400C9 || 0xC9 || 0 || 4 || 1 || SetOuterTessellationLevels&lt;br /&gt;
|-&lt;br /&gt;
| 0x200200CD || 0xCD || 0 || 2 || 1 || SetInnerTessellationLevels&lt;br /&gt;
|-&lt;br /&gt;
| 0x200100DC || 0xDC || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?00DF || 0xDF || 0 || Variable || 4 || SetRasterizerDiscard?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20048100 || 0x100 || 4 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20028102 || 0x102 || 4 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20018104 || 0x104 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20018105 || 0x105 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20018106 || 0x106 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C0 || 0x1C0 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C2 || 0x1C2 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C3 || 0x1C3 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200281C4 || 0x1C4 || 4 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C5 || 0x1C5 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C6 || 0x1C6 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C7 || 0x1C7 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181C8 || 0x1C8 || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181CA || 0x1CA || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181CB || 0x1CB || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181CC || 0x1CC || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181CD || 0x1CD || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200181CF || 0x1CF || 4 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800001D1 || 0x1D1 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200301F0 || 0x1F0 || 0 || 3 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800001F3 || 0x1F3 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200201F8 || 0x1F8 || 0 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200401FA || 0x1FA || 0 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20016223 || 0x223 || 3 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2004622C || 0x22C || 3 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20046230 || 0x230 || 3 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20046234 || 0x234 || 3 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200203?? || 0x3?? Variable || 0 || 2 || 1 || SetScissors?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20040360 || 0x360 || 0 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010364 || 0x364 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0368 || 0x368 || 0 || Variable  || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?036B || 0x36B || 0 || Variable  || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?036C || 0x36C || 0 || Variable  || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001036F || 0x36F || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000370 || 0x370 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000371 || 0x371 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000372 || 0x372 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8???0373 || 0x373 || 0 || Variable || 4 || SetPatchSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000374 || 0x374 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010376 || 0x376 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?03D5 || 0x3D5 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?03D6 || 0x3D6 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?03D7 || 0x3D7 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200103D9 || 0x3D9 || 0 || 1 || 1 || SetTiledCacheTileSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x80?003DE || 0x3DE || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800003E0 || 0x3E0 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200203E7 || 0x3E7 || 0 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800003ED || 0x3ED || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800203EE || 0x3EE || 0 || 2 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200403EF || 0x3EF || 0 || 4 || 1 || SetSampleMask&lt;br /&gt;
|-&lt;br /&gt;
| 0x800003F5 || 0x3F5 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800103F6 || 0x3F6 || 0 || 1 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200503F8 || 0x3F8 || 0 || 5 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200203FD || 0x3FD || 0 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2004040C || 0x40C || 0 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200C0420 || 0x420 || 0 || 12 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000446 || 0x446 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000451 || 0x451 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0452 || 0x452 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20100458 || 0x458 || 0 || 16 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20040478 || 0x478 || 0 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8000047C || 0x47C || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8000047E || 0x47E || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8001047F || 0x47F || 0 || 1 || 4 || ResolveDepthBuffer&lt;br /&gt;
|-&lt;br /&gt;
| 0x2003048A || 0x48A || 0 || 3 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04B3 || 0x4B3 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800104B9 || 0x4B9 || 0 || 1 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04BA || 0x4BA || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800004BB || 0x4BB || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04C3 || 0x4C3 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200104C4 || 0x4C4 || 0 || 1 || 1 || SetAlphaRef&lt;br /&gt;
|-&lt;br /&gt;
| 0x200404C7 || 0x4C7 || 0 || 4 || 1 || SetBlendColor&lt;br /&gt;
|-&lt;br /&gt;
| 0x800004E0 || 0x4E0 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04E5 || 0x4E5 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04E6 || 0x4E6 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?04E7 || 0x4E7 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200204EC || 0x4EC || 0 || 2 || 1 || SetLineWidth&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?050D || 0x50D || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000519 || 0x519 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000540 || 0x540 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010546 || 0x546 || 0 || 1 || 1 || SetPointSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001054C || 0x54C || 0 || 1 || 1 || ResetCounter&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?054E || 0x54E || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20030554 || 0x554 || 0 || 3 || 1 || SetRenderEnableConditional&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0556 || 0x556 || 0 || Variable || 4 || SetRenderEnable?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001055B || 0x55B || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001056F || 0x56F || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000572 || 0x572 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0574 || 0x574 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8000057F || 0x57F || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000580 || 0x580 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000591 || 0x591 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010592 || 0x592 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200205F2 || 0x5F2 || 0 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?05F6 || 0x5F6 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001061F || 0x61F || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0620 || 0x620 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80010646 || 0x646 || 0 || 1 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0648 || 0x648 || 0 || Variable  || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001064F || 0x64F || 0 || 1 || 1 || SetDepthClamp&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?066F || 0x66F || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x120020671 || 0x671 || 0 || 2 || 9 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010674 || 0x674 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x8000068B || 0x68B || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200406C0 || 0x6C0 || 0 || 4 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010703 || 0x703 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200207?? || 0x7?? Variable || 0 || 2 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80300830 || 0x830 || 0 || 48 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80400840 || 0x840 || 0 || 64 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80500850 || 0x850 || 0 || 80 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200308E0 || 0x8E0 || 0 || 3 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x200308E3 || 0x8E3 || 0 || 3 || 1 || CB_POS(Const buffer position)&lt;br /&gt;
|-&lt;br /&gt;
| 0x200308E4 || 0x8E4 || 0 || 3 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80??0904 || 0x904 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80??090C || 0x90C || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80??0914 || 0x914 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80??091C || 0x91C || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80??0924 || 0x924 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000D1E || 0xD1E || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0D28 || 0xD28 || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010D29 || 0xD29 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010D34 || 0xD34 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0020E00 || 0xE00 || 0 || 2 || 5 || BeginTransformFeedback&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010E02 || 0xE02 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80020E04 || 0xE04 || 0 || 2 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010E06 || 0xE06 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0030E0A || 0xE0A || 0 || 3 || 5 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80050E0C || 0xE0C || 0 || 5 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x800?0E0E || 0xE0E || 0 || Variable || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010E10 || 0xE10 || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0040E12 || 0xE12 || 0 || 4 || 5 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010E1A || 0xE1A || 0 || 1 || 1 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0040E1C || 0xE1C || 0 || 4 || 5 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x81900E1E || 0xE1E || 0 || 400 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000E20 || 0xE20 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x80000E24 || 0xE24 || 0 || 0 || 4 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0040E2C || 0xE2C || 0 || 4 || 5 || PushDebugGroup&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0020E2E || 0xE2E || 0 || 2 || 5 || PopDebugGroupId&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0030E30 || 0xE30 || 0 || 3 || 5 || DrawArrays&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0050E32 || 0xE32 || 0 || 5 || 5 || DrawArraysIndirect?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0050E34 || 0xE34 || 0 || 5 || 5 || DrawArraysInstanced?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0050E36 || 0xE36 || 0 || 5 || 5 || DrawElements&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0060E38 || 0xE38 || 0 || 6 || 5 || DrawElementsIndirect?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0060E3A || 0xE3A || 0 || 6 || 5 || DrawElementsInstanced?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0050E42 || 0xE42 || 0 || 5 || 5 || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0060E44 || 0xE44 || 0 || 6 || 5 || ?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note: These still need to be heavily verified and &#039;&#039;could&#039;&#039; be wrong.&lt;br /&gt;
&lt;br /&gt;
=== BindObject ===&lt;br /&gt;
&lt;br /&gt;
In order to bind an engine object to a specific subchannel, method 0 (BindObject) must be used first. The target subchannel is specified in bits 15-13 of the command word.&lt;br /&gt;
&lt;br /&gt;
After the engine object is bound to the desired subchannel, setting it&#039;s value in bits 15-13 of any subsequent command word will make PFIFO forward the command to the target engine.&lt;br /&gt;
&lt;br /&gt;
This method only takes one argument, an [[#Engine_IDs|engine ID]].&lt;br /&gt;
&lt;br /&gt;
==== Engine IDs ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| ID&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Engine&lt;br /&gt;
|-&lt;br /&gt;
|0x902D&lt;br /&gt;
|FERMI_TWOD_A (2D)&lt;br /&gt;
|-&lt;br /&gt;
|0xB197&lt;br /&gt;
|MAXWELL_B (3D)&lt;br /&gt;
|-&lt;br /&gt;
|0xB1C0&lt;br /&gt;
|MAXWELL_COMPUTE_B&lt;br /&gt;
|-&lt;br /&gt;
|0xA140&lt;br /&gt;
|KEPLER_INLINE_TO_MEMORY_B&lt;br /&gt;
|-&lt;br /&gt;
|0xB0B5&lt;br /&gt;
|MAXWELL_DMA_COPY_A (DMA)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Macro ===&lt;br /&gt;
&lt;br /&gt;
Macros are small programs that can be uploaded to the gpu and are capable of reading and writing to the 3D engine registers on the GPU. Those macro programs can be executed by calling methods from address 0xe00 onwards on the 3D engine. The macros also accepts parameters, stored on a FIFO that can be read on the macro using a instruction called parm, this instruction pops the FIFO and reads the next parameter. Macros can be called using methods starting at 0xe00, where the first method triggers the macro execution, and the second one is used to push parameters to the FIFO, that can be read from the macro program using parm. This also allows programs to use a variable number of parameters if desired.&lt;br /&gt;
&lt;br /&gt;
The first parameter is written to 0xe00 + n * 2 (where n is the macro index), and all subsequent parameters should be pushed to the FIFO using 0xe01 + n * 2. The first parameter is placed the general purpose register R1 in the shader program when execution starts.&lt;br /&gt;
&lt;br /&gt;
Official games uses those macros to conditionally write registers, one example of such uses it the macro at 0xe24, that is used to set shader registers (including shader address and binding the c1 Constant Buffer to the shader). In some cases, it&#039;s also used to set registers unconditionally.&lt;br /&gt;
&lt;br /&gt;
=== Fences ===&lt;br /&gt;
&lt;br /&gt;
Command lists can contain fences to ensure that commands are executed on the correct order, and subsequent commands are only sent when the previously sent commands were already processed by the GPU. Fences uses the QUERY_* commands, and works like this:&lt;br /&gt;
&lt;br /&gt;
* First, QUERY_ADDRESS_HIGH and QUERY_ADDRESS_LOW commands are added to the Command List, with the High/Low 32 bits part of the 64-bits GPU Virtual Address where the fence is located. This GPU Virtual Address needs to be mapped to the process Virtual Address beforehand.&lt;br /&gt;
* Then, QUERY_SEQUENCE is added with a sequential number. This number is basically a incrementing counter, so the first Command List can have QUERY_SEQUENCE = 1, the next one QUERY_SEQUENCE = 2, 3, 4... and so on.&lt;br /&gt;
* Finally, QUERY_GET is added and contains the mode and other unknown data.&lt;br /&gt;
&lt;br /&gt;
The above commands are added using the [[#Submission_mode|increasing mode]], since the Ids for all those 4 registers are sequential.&lt;br /&gt;
&lt;br /&gt;
==== QUERY_GET Structure ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Bits&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|1-0&lt;br /&gt;
|Mode&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Fence&lt;br /&gt;
|-&lt;br /&gt;
|15-12&lt;br /&gt;
|Unit &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== QUERY_GET Mode ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Value&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Mode&lt;br /&gt;
|-&lt;br /&gt;
|0&lt;br /&gt;
|Write&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Sync&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Write ? &lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Write ?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
TODO: Move this to a separate page with all GPU Commands with descriptions. Also figure out what the other values mean.&lt;br /&gt;
&lt;br /&gt;
Some of the other fields are still unknown/unobserved.&lt;br /&gt;
&lt;br /&gt;
Official games will set Mode to 0, Fence to 1 and Unit to 0xF. The QUERY_SEQUENCE value is then written by the GPU to the address pointed to by QUERY_ADDRESS.&lt;br /&gt;
On the CPU side, the game code should wait until the value at the address pointed to by QUERY_ADDRESS is &amp;gt;= to the last written SEQUENCE value. Official code waits for this condition to be true on a loop, and won&#039;t send any further commands before that.&lt;br /&gt;
&lt;br /&gt;
== Vertex Data Submission ==&lt;br /&gt;
&lt;br /&gt;
Note: This is a observation on how the game Puyo Puyo Tetris sends textured squares to the GPU.&lt;br /&gt;
&lt;br /&gt;
# VERTEX_ATTRIB_FORMAT (0-15) are set (only the first 3 are really used, the rest are set float, with Size = 1 and offset at 0).&lt;br /&gt;
# VERTEX_ARRAY_FETCH (0) is set with the lower 12 bits set to 0x1c (Stride) and bit 12 to 1 (Enabled).&lt;br /&gt;
# VERTEX_ARRAY_START_HIGH/LOW (0) are set to the GPU Virtual Address where the Vertex Data is located.&lt;br /&gt;
# VERTEX_ARRAY_LIMIT_HIGH/LOW (0) are set to the GPU Virtual Address where the Vertex Data is located, plus the Vertex Data size in bytes minus 1.&lt;br /&gt;
# VERTEX_BEGIN_GL is used with the primitive type set to TRIANGLE_STRIP.&lt;br /&gt;
# VERTEX_BUFFER_FIRST with value 0 (indicating the index of the first primitive to render?).&lt;br /&gt;
# VERTEX_BUFFER_COUNT is set to 4, because the Vertex Buffer with the square has 4 vertices.&lt;br /&gt;
# VERTEX_END_GL is used with value 0 (currently unknown what this value means).&lt;br /&gt;
&lt;br /&gt;
== Texture View ==&lt;br /&gt;
&lt;br /&gt;
Texture information such as address, format and size is sent to the GPU through a structure know as Texture View (a.k.a. Texture Image Control, or TIC). Each texture that the game uses needs a separate TIC, and those TICs are written to a table, one after the other. Each [[#TIC_Structure|TIC entry]] has 0x20 bytes, and is composed of 8 32-bits words where the texture information is packed.&lt;br /&gt;
&lt;br /&gt;
The index of the TIC entries that should be used by the shader is sent to the GPU with the CB_POS/CB_DATA (0) methods. Games usually follows the following steps to write the TIC entry indexes:&lt;br /&gt;
&lt;br /&gt;
* Macro 0xe1a is used to set CB_ADDRESS_HIGH/LOW registers to the GPU Virtual Address of the Constant Buffer set on the register 0x982 (the &#039;&#039;Texture Constant Buffer&#039;&#039; index register), and also sets CB_SIZE.&lt;br /&gt;
* CB_POS is used to set the write offset of the Constant Buffer to 0x20 + n * 4, where &#039;&#039;n&#039;&#039; is the index of the handle being used on the shader sampler.&lt;br /&gt;
* CB_DATA (0) method is used to write the value into the Constant Buffer. The value is a &#039;&#039;Handle&#039;&#039; where the lower 20 bits is the TIC index, and the higher 12 bits is the TSC (Texture Sampler Control) index.&lt;br /&gt;
&lt;br /&gt;
The address of a given TIC entry can be calculates as:&lt;br /&gt;
&lt;br /&gt;
 tic_entry_address = tic_base_address + tic_index * 0x20&lt;br /&gt;
&lt;br /&gt;
Where &#039;&#039;tic_base_address&#039;&#039; is the address written to TIC_ADDRESS_HIGH/LOW (methods 0x1574 and 0x1578), &#039;&#039;tic_index&#039;&#039; is the lower 20 bits of the word written into the Const Buffer with CB_DATA (0), and 0x20 is the size of each TIC entry in bytes.&lt;br /&gt;
&lt;br /&gt;
The texture is accessed on the shader using one of the texture sampling instructions (usually the TEXS instruction). One of the parameters for this instruction is the &#039;&#039;Handle&#039;&#039; index. This index start at 8, so the index 8 will access the handle at 8 * 4 = 0x20 on the &#039;&#039;Texture Constant Buffer&#039;&#039;. Each shader stage has a separate Constant Buffer, so for fragment shaders, this is located at CB_ADDRESS + 4 * CB_SIZE + TEXS_index * 4 (where 4 is the index of the fragment shader stage).&lt;br /&gt;
&lt;br /&gt;
=== TIC Structure ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Word || Bits || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 6-0 || [[GPU_Texture_Formats#Texture_Formats|Texture Format]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 9-7 || [[#Channel_Data_Type|R Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 12-10 || [[#Channel_Data_Type|G Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 15-13 || [[#Channel_Data_Type|B Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 18-16 || [[#Channel_Data_Type|A Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 31-0 || Lower 32-bits of the Texture GPU Virtual Address&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 15-0 || Higher 16-bits of the Texture GPU Virtual Address&lt;br /&gt;
|-&lt;br /&gt;
| 4 || 15-0 || Texture Width minus 1&lt;br /&gt;
|-&lt;br /&gt;
| 5 || 15-0 || Texture Height minus 1&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Channel Data Type ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Type&lt;br /&gt;
|-&lt;br /&gt;
| 1 || SNORM&lt;br /&gt;
|-&lt;br /&gt;
| 2 || UNORM&lt;br /&gt;
|-&lt;br /&gt;
| 3 || SINT&lt;br /&gt;
|-&lt;br /&gt;
| 4 || UINT&lt;br /&gt;
|-&lt;br /&gt;
| 5 || SNORM_FORCE_FP16&lt;br /&gt;
|-&lt;br /&gt;
| 6 || UNORM_FORCE_FP16&lt;br /&gt;
|-&lt;br /&gt;
| 7 || FLOAT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
FIFO engine overview:&lt;br /&gt;
[https://envytools.readthedocs.io/en/latest/hw/fifo/intro.html]&lt;br /&gt;
&lt;br /&gt;
Method values from the Fermi family GPU (a bit older than the Tegra X1, but values seems to be mostly the same):&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/gf100_3d.xml]&lt;br /&gt;
&lt;br /&gt;
TIC structure used on a Maxwell GPU:&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/gm200_texture.xml]&lt;br /&gt;
&lt;br /&gt;
Values for some types used on the above XML:&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/nv_3ddefs.xml]&lt;br /&gt;
&lt;br /&gt;
Command word packing code used on Mesa3d:&lt;br /&gt;
[https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nvc0/nvc0_winsys.h]&lt;br /&gt;
&lt;br /&gt;
TIC entry pack/write code used on Mesa3d:&lt;br /&gt;
[https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c#n65]&lt;/div&gt;</summary>
		<author><name>Gdkchan</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=GPU&amp;diff=3621</id>
		<title>GPU</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=GPU&amp;diff=3621"/>
		<updated>2018-02-05T17:37:20Z</updated>

		<summary type="html">&lt;p&gt;Gdkchan: Add missing dot&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Mapping Memory ==&lt;br /&gt;
&lt;br /&gt;
First, to map a memory region on the GPU Address Space, caching needs to be disabled by using [[SVC#svcSetMemoryAttribute|svcSetMemoryAttribute]]. The Address passed is the Virtual Address of the region that will be mapped, the size is the region size, and State0/1 are both set to 8 to disable caching of the memory region. This is done to ensure that the GPU can actually &amp;quot;see&amp;quot; the data written there, and it doesn&#039;t get stuck on some cache.&lt;br /&gt;
&lt;br /&gt;
Then, [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]] is used to create a nvmap object with the desired size. After, [[NV_services#NVMAP_IOC_ALLOC|NVMAP_IOC_ALLOC]] is used to allocate the memory on the GPU Address Space, and map data on the process Address Space into the GPU Address Space, by passing the Virtual Address as the input addr parameter, and also the Handle returned from [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]]. Lastly, the actual mapping is done by using [[NV_services#NVGPU_AS_IOCTL_MAP_BUFFER_EX|NVGPU_AS_IOCTL_MAP_BUFFER_EX]], and the GPU Virtual Address is returned on the offset parameter. It&#039;s also possible to manually set the offset where the mapping should be made on the GPU Address Space, by passing the address on the &amp;quot;offset&amp;quot; parameter, and setting the bit 0 of the flags parameter to 1. However, for this to work, the desired GPU Virtual Address needs to be previously reserved using [[NV_services#NVGPU_AS_IOCTL_ALLOC_SPACE|NVGPU_AS_IOCTL_ALLOC_SPACE]].&lt;br /&gt;
&lt;br /&gt;
The above process is used to map all data that will be used by the GPU, like Textures, Command Lists (a.k.a. Push Buffers), Vertex/Index buffers and Shaders. They usually have their own mapping, but Command Lists can share the same mapping.&lt;br /&gt;
&lt;br /&gt;
== FIFO Commands ==&lt;br /&gt;
&lt;br /&gt;
The GPU implements a variation of Tegra&#039;s push buffer format for it&#039;s PFIFO engine. PFIFO is a special engine responsible for receiving user command lists and routing them to the appropriate engines (2D, 3D, DMA).&lt;br /&gt;
&lt;br /&gt;
Commands are submitted to the GPU&#039;s PFIFO engine through [[NV_services#NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO|NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO]].&lt;br /&gt;
&lt;br /&gt;
This ioctl takes an array of gpfifo entries where each entry points to a FIFO command list. This list is composed of alternating 32-bit words containing FIFO commands and their respective arguments.&lt;br /&gt;
&lt;br /&gt;
=== Command Structure ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Bits&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|12-0&lt;br /&gt;
|Method&lt;br /&gt;
|-&lt;br /&gt;
|15-13&lt;br /&gt;
|Subchannel&lt;br /&gt;
|-&lt;br /&gt;
|28-16&lt;br /&gt;
|Argument count (in 32-bits Words) or inline data (see below)&lt;br /&gt;
|-&lt;br /&gt;
|31-29&lt;br /&gt;
|[[#Submission_mode|Submission mode]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note: Methods are treated as 4-byte addressable locations, and hence their numbers are written down multiplied by 4.&lt;br /&gt;
&lt;br /&gt;
Note: The command&#039;s arguments, when present, follow the command word immediately.&lt;br /&gt;
&lt;br /&gt;
==== Submission mode ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Mode&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Offical name&lt;br /&gt;
|-&lt;br /&gt;
|0&lt;br /&gt;
|Increasing mode (old)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Increasing mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039;, while automatically incrementing the &#039;&#039;&#039;method&#039;&#039;&#039; value. This means that each argument will be written to a different method location.&lt;br /&gt;
|INCR&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Non-increasing mode (old)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Non-increasing mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039;. However, all arguments will be written to the same method location.&lt;br /&gt;
|NONINCR&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Inline mode - Tells PFIFO to read &#039;&#039;&#039;inline data&#039;&#039;&#039; from bits 28-16 of the command word, thus eliminating the need to pass additional words for the arguments.&lt;br /&gt;
|IMM&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|Increase-once mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039; and automatically increments the &#039;&#039;&#039;method&#039;&#039;&#039; value once only.&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Command List ===&lt;br /&gt;
&lt;br /&gt;
All methods with values &amp;lt; 0x100 are special and executed by the PFIFO&#039;s DMA puller. The others are forwarded to the engine object currently bound to a given subchannel.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Command || Method || Subchannel || Arg Count || Mode || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001?000 || 0x0000 || Variable || 1 || 1 || [[#BindObject|BindObject]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0020E00 || 0x3800 || 0 || 2 || 5 || BeginTransformFeedback&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0030E30 || 0x38C0 || 0 || 3 || 5 || DrawArrays&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0050E36 || 0x38D8 || 0 || 5 || 5 || DrawElements&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0020E2E || 0x38B8 || 0 || 2 || 5 || PopDebugGroupId&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0040E2C || 0x38B0 || 0 || 4 || 5 || PushDebugGroup&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001054C || 0x1530 || 0 || 1 || 1 || ResetCounter&lt;br /&gt;
|-&lt;br /&gt;
| 0x8001047F || 0x11FC || 0 || 1 || 4 || ResolveDepthBuffer&lt;br /&gt;
|-&lt;br /&gt;
| 0x200104C4 || 0x1310 || 0 || 1 || 1 || SetAlphaRef&lt;br /&gt;
|-&lt;br /&gt;
| 0x200404C7 || 0x131C || 0 || 4 || 1 || SetBlendColor&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001064F || 0x1BD0 || 0 || 1 || 1 || SetDepthClamp&lt;br /&gt;
|-&lt;br /&gt;
| 0x200200CD || 0x0334 || 0 || 2 || 1 || SetInnerTessellationLevels&lt;br /&gt;
|-&lt;br /&gt;
| 0x200204EC || 0x13B0 || 0 || 2 || 1 || SetLineWidth&lt;br /&gt;
|-&lt;br /&gt;
| 0x200400C9 || 0x0324 || 0 || 4 || 1 || SetOuterTessellationLevels&lt;br /&gt;
|-&lt;br /&gt;
| 0x8???0373 || 0x0DCC || 0 || Variable || 4 || SetPatchSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010546 || 0x1518 || 0 || 1 || 1 || SetPointSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x20030554 || 0x1550 || 0 || 3 || 1 || SetRenderEnableConditional&lt;br /&gt;
|-&lt;br /&gt;
| 0x200403EF || 0x0FBC || 0 || 4 || 1 || SetSampleMask&lt;br /&gt;
|-&lt;br /&gt;
| 0x200103D9 || 0x0F64 || 0 || 1 || 1 || SetTiledCacheTileSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x20020047 || 0x011C || 0 || 2 || 1 || SetGraphMacroEntry&lt;br /&gt;
|-&lt;br /&gt;
| 0xA???0045 || 0x0114 || 0 || Variable || 5 || SetGraphMacroCode&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note: These still need to be heavily verified and &#039;&#039;could&#039;&#039; be wrong.&lt;br /&gt;
&lt;br /&gt;
=== BindObject ===&lt;br /&gt;
&lt;br /&gt;
In order to bind an engine object to a specific subchannel, method 0 (BindObject) must be used first. The target subchannel is specified in bits 15-13 of the command word.&lt;br /&gt;
&lt;br /&gt;
After the engine object is bound to the desired subchannel, setting it&#039;s value in bits 15-13 of any subsequent command word will make PFIFO forward the command to the target engine.&lt;br /&gt;
&lt;br /&gt;
This method only takes one argument, an [[#Engine_IDs|engine ID]].&lt;br /&gt;
&lt;br /&gt;
==== Engine IDs ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| ID&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Engine&lt;br /&gt;
|-&lt;br /&gt;
|0x902D&lt;br /&gt;
|FERMI_TWOD_A (2D)&lt;br /&gt;
|-&lt;br /&gt;
|0xB197&lt;br /&gt;
|MAXWELL_B (3D)&lt;br /&gt;
|-&lt;br /&gt;
|0xB1C0&lt;br /&gt;
|MAXWELL_COMPUTE_B&lt;br /&gt;
|-&lt;br /&gt;
|0xA140&lt;br /&gt;
|KEPLER_INLINE_TO_MEMORY_B&lt;br /&gt;
|-&lt;br /&gt;
|0xB0B5&lt;br /&gt;
|MAXWELL_DMA_COPY_A (DMA)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Fences ===&lt;br /&gt;
&lt;br /&gt;
Command lists can contain fences to ensure that commands are executed on the correct order, and subsequent commands are only sent when the previously sent commands were already processed by the GPU. Fences uses the QUERY_* commands, and works like this:&lt;br /&gt;
&lt;br /&gt;
* First, QUERY_ADDRESS_HIGH and QUERY_ADDRESS_LOW commands are added to the Command List, with the High/Low 32 bits part of the 64-bits GPU Virtual Address where the fence is located. This GPU Virtual Address needs to be mapped to the process Virtual Address beforehand.&lt;br /&gt;
* Then, QUERY_SEQUENCE is added with a sequential number. This number is basically a incrementing counter, so the first Command List can have QUERY_SEQUENCE = 1, the next one QUERY_SEQUENCE = 2, 3, 4... and so on.&lt;br /&gt;
* Finally, QUERY_GET is added and contains the mode and other unknown data.&lt;br /&gt;
&lt;br /&gt;
The above commands are added using the [[#Submission_mode|increasing mode]], since the Ids for all those 4 registers are sequential.&lt;br /&gt;
&lt;br /&gt;
==== QUERY_GET Structure ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Bits&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|1-0&lt;br /&gt;
|Mode&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Fence&lt;br /&gt;
|-&lt;br /&gt;
|15-12&lt;br /&gt;
|Unit &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== QUERY_GET Mode ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Value&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Mode&lt;br /&gt;
|-&lt;br /&gt;
|0&lt;br /&gt;
|Write&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Sync&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Write ? &lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Write ?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
TODO: Move this to a separate page with all GPU Commands with descriptions. Also figure out what the other values mean.&lt;br /&gt;
&lt;br /&gt;
Some of the other fields are still unknown/unobserved.&lt;br /&gt;
&lt;br /&gt;
Official games will set Mode to 0, Fence to 1 and Unit to 0xF. The QUERY_SEQUENCE value is then written by the GPU to the address pointed to by QUERY_ADDRESS.&lt;br /&gt;
On the CPU side, the game code should wait until the value at the address pointed to by QUERY_ADDRESS is &amp;gt;= to the last written SEQUENCE value. Official code waits for this condition to be true on a loop, and won&#039;t send any further commands before that.&lt;br /&gt;
&lt;br /&gt;
== Vertex Data Submission ==&lt;br /&gt;
&lt;br /&gt;
Note: This is a observation on how the game Puyo Puyo Tetris sends textured squares to the GPU.&lt;br /&gt;
&lt;br /&gt;
# VERTEX_ATTRIB_FORMAT (0-15) are set (only the first 3 are really used, the rest are set float, with Size = 1 and offset at 0).&lt;br /&gt;
# VERTEX_ARRAY_FETCH (0) is set with the lower 12 bits set to 0x1c (Stride) and bit 12 to 1 (Enabled).&lt;br /&gt;
# VERTEX_ARRAY_START_HIGH/LOW (0) are set to the GPU Virtual Address where the Vertex Data is located.&lt;br /&gt;
# VERTEX_ARRAY_LIMIT_HIGH/LOW (0) are set to the GPU Virtual Address where the Vertex Data is located, plus the Vertex Data size in bytes minus 1.&lt;br /&gt;
# VERTEX_BEGIN_GL is used with the primitive type set to TRIANGLE_STRIP.&lt;br /&gt;
# VERTEX_BUFFER_FIRST with value 0 (indicating the index of the first primitive to render?).&lt;br /&gt;
# VERTEX_BUFFER_COUNT is set to 4, because the Vertex Buffer with the square has 4 vertices.&lt;br /&gt;
# VERTEX_END_GL is used with value 0 (currently unknown what this value means).&lt;br /&gt;
&lt;br /&gt;
== Texture View ==&lt;br /&gt;
&lt;br /&gt;
Texture information such as address, format and size is sent to the GPU through a structure know as Texture View (a.k.a. Texture Image Control, or TIC). Each texture that the game uses needs a separate TIC, and those TICs are written to a table, one after the other. Each [[#TIC_Structure|TIC entry]] has 0x20 bytes, and is composed of 8 32-bits words where the texture information is packed.&lt;br /&gt;
&lt;br /&gt;
The index of the TIC entries that should be used by the shader is sent to the GPU with the CB_POS/CB_DATA (0) methods. Games usually follows the following steps to write the TIC entry indexes:&lt;br /&gt;
&lt;br /&gt;
* CB_ADDRESS_HIGH/LOW method is used to set the GPU Virtual Address of the Const Buffer.&lt;br /&gt;
* CB_POS is used to set the write offset of the Const Buffer to 0x20 + n * 4, where &#039;&#039;n&#039;&#039; is the is the index of the active texture that will be used by the shader (?).&lt;br /&gt;
* CB_DATA (0) method is used to write the value into the Const Buffer. The value is a word where the lower 20 bits is the TIC index.&lt;br /&gt;
&lt;br /&gt;
The address of a given TIC entry can be calculates as:&lt;br /&gt;
&lt;br /&gt;
 tic_entry_address = tic_base_address + tic_index * 0x20&lt;br /&gt;
&lt;br /&gt;
Where &#039;&#039;tic_base_address&#039;&#039; is the address written to TIC_ADDRESS_HIGH/LOW (methods 0x1574 and 0x1578), &#039;&#039;tic_index&#039;&#039; is the lower 20 bits of the word written into the Const Buffer with CB_DATA (0), and 0x20 is the size of each TIC entry in bytes.&lt;br /&gt;
&lt;br /&gt;
Note: More research still needs to be done on the Const Buffer and how it is used by the shader.&lt;br /&gt;
&lt;br /&gt;
=== TIC Structure ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Word || Bits || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 6-0 || [[GPU_Texture_Formats#Texture_Formats|Texture Format]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 9-7 || [[#Channel_Data_Type|R Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 12-10 || [[#Channel_Data_Type|G Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 15-13 || [[#Channel_Data_Type|B Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 18-16 || [[#Channel_Data_Type|A Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 31-0 || Lower 32-bits of the Texture GPU Virtual Address&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 15-0 || Higher 16-bits of the Texture GPU Virtual Address&lt;br /&gt;
|-&lt;br /&gt;
| 4 || 15-0 || Texture Width minus 1&lt;br /&gt;
|-&lt;br /&gt;
| 5 || 15-0 || Texture Height minus 1&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Channel Data Type ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Type&lt;br /&gt;
|-&lt;br /&gt;
| 1 || SNORM&lt;br /&gt;
|-&lt;br /&gt;
| 2 || UNORM&lt;br /&gt;
|-&lt;br /&gt;
| 3 || SINT&lt;br /&gt;
|-&lt;br /&gt;
| 4 || UINT&lt;br /&gt;
|-&lt;br /&gt;
| 5 || SNORM_FORCE_FP16&lt;br /&gt;
|-&lt;br /&gt;
| 6 || UNORM_FORCE_FP16&lt;br /&gt;
|-&lt;br /&gt;
| 7 || FLOAT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
FIFO engine overview:&lt;br /&gt;
[https://envytools.readthedocs.io/en/latest/hw/fifo/intro.html]&lt;br /&gt;
&lt;br /&gt;
Method values from the Fermi family GPU (a bit older than the Tegra X1, but values seems to be mostly the same):&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/gf100_3d.xml]&lt;br /&gt;
&lt;br /&gt;
TIC structure used on a Maxwell GPU:&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/gm200_texture.xml]&lt;br /&gt;
&lt;br /&gt;
Values for some types used on the above XML:&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/nv_3ddefs.xml]&lt;br /&gt;
&lt;br /&gt;
Command word packing code used on Mesa3d:&lt;br /&gt;
[https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nvc0/nvc0_winsys.h]&lt;br /&gt;
&lt;br /&gt;
TIC entry pack/write code used on Mesa3d:&lt;br /&gt;
[https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c#n65]&lt;/div&gt;</summary>
		<author><name>Gdkchan</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=GPU&amp;diff=3620</id>
		<title>GPU</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=GPU&amp;diff=3620"/>
		<updated>2018-02-05T17:19:36Z</updated>

		<summary type="html">&lt;p&gt;Gdkchan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Mapping Memory ==&lt;br /&gt;
&lt;br /&gt;
First, to map a memory region on the GPU Address Space, caching needs to be disabled by using [[SVC#svcSetMemoryAttribute|svcSetMemoryAttribute]]. The Address passed is the Virtual Address of the region that will be mapped, the size is the region size, and State0/1 are both set to 8 to disable caching of the memory region. This is done to ensure that the GPU can actually &amp;quot;see&amp;quot; the data written there, and it doesn&#039;t get stuck on some cache.&lt;br /&gt;
&lt;br /&gt;
Then, [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]] is used to create a nvmap object with the desired size. After, [[NV_services#NVMAP_IOC_ALLOC|NVMAP_IOC_ALLOC]] is used to allocate the memory on the GPU Address Space, and map data on the process Address Space into the GPU Address Space, by passing the Virtual Address as the input addr parameter, and also the Handle returned from [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]]. Lastly, the actual mapping is done by using [[NV_services#NVGPU_AS_IOCTL_MAP_BUFFER_EX|NVGPU_AS_IOCTL_MAP_BUFFER_EX]], and the GPU Virtual Address is returned on the offset parameter. It&#039;s also possible to manually set the offset where the mapping should be made on the GPU Address Space, by passing the address on the &amp;quot;offset&amp;quot; parameter, and setting the bit 0 of the flags parameter to 1. However, for this to work, the desired GPU Virtual Address needs to be previously reserved using [[NV_services#NVGPU_AS_IOCTL_ALLOC_SPACE|NVGPU_AS_IOCTL_ALLOC_SPACE]].&lt;br /&gt;
&lt;br /&gt;
The above process is used to map all data that will be used by the GPU, like Textures, Command Lists (a.k.a. Push Buffers), Vertex/Index buffers and Shaders. They usually have their own mapping, but Command Lists can share the same mapping.&lt;br /&gt;
&lt;br /&gt;
== FIFO Commands ==&lt;br /&gt;
&lt;br /&gt;
The GPU implements a variation of Tegra&#039;s push buffer format for it&#039;s PFIFO engine. PFIFO is a special engine responsible for receiving user command lists and routing them to the appropriate engines (2D, 3D, DMA).&lt;br /&gt;
&lt;br /&gt;
Commands are submitted to the GPU&#039;s PFIFO engine through [[NV_services#NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO|NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO]].&lt;br /&gt;
&lt;br /&gt;
This ioctl takes an array of gpfifo entries where each entry points to a FIFO command list. This list is composed of alternating 32-bit words containing FIFO commands and their respective arguments.&lt;br /&gt;
&lt;br /&gt;
=== Command Structure ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Bits&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|12-0&lt;br /&gt;
|Method&lt;br /&gt;
|-&lt;br /&gt;
|15-13&lt;br /&gt;
|Subchannel&lt;br /&gt;
|-&lt;br /&gt;
|28-16&lt;br /&gt;
|Argument count (in 32-bits Words) or inline data (see below)&lt;br /&gt;
|-&lt;br /&gt;
|31-29&lt;br /&gt;
|[[#Submission_mode|Submission mode]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note: Methods are treated as 4-byte addressable locations, and hence their numbers are written down multiplied by 4.&lt;br /&gt;
&lt;br /&gt;
Note: The command&#039;s arguments, when present, follow the command word immediately.&lt;br /&gt;
&lt;br /&gt;
==== Submission mode ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Mode&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Offical name&lt;br /&gt;
|-&lt;br /&gt;
|0&lt;br /&gt;
|Increasing mode (old)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Increasing mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039;, while automatically incrementing the &#039;&#039;&#039;method&#039;&#039;&#039; value. This means that each argument will be written to a different method location.&lt;br /&gt;
|INCR&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Non-increasing mode (old)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Non-increasing mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039;. However, all arguments will be written to the same method location.&lt;br /&gt;
|NONINCR&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Inline mode - Tells PFIFO to read &#039;&#039;&#039;inline data&#039;&#039;&#039; from bits 28-16 of the command word, thus eliminating the need to pass additional words for the arguments.&lt;br /&gt;
|IMM&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|Increase-once mode - Tells PFIFO to read as much arguments as specified by &#039;&#039;&#039;argument count&#039;&#039;&#039; and automatically increments the &#039;&#039;&#039;method&#039;&#039;&#039; value once only.&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Command List ===&lt;br /&gt;
&lt;br /&gt;
All methods with values &amp;lt; 0x100 are special and executed by the PFIFO&#039;s DMA puller. The others are forwarded to the engine object currently bound to a given subchannel.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Command || Method || Subchannel || Arg Count || Mode || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001?000 || 0x0000 || Variable || 1 || 1 || [[#BindObject|BindObject]]&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0020E00 || 0x3800 || 0 || 2 || 5 || BeginTransformFeedback&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0030E30 || 0x38C0 || 0 || 3 || 5 || DrawArrays&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0050E36 || 0x38D8 || 0 || 5 || 5 || DrawElements&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0020E2E || 0x38B8 || 0 || 2 || 5 || PopDebugGroupId&lt;br /&gt;
|-&lt;br /&gt;
| 0xA0040E2C || 0x38B0 || 0 || 4 || 5 || PushDebugGroup&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001054C || 0x1530 || 0 || 1 || 1 || ResetCounter&lt;br /&gt;
|-&lt;br /&gt;
| 0x8001047F || 0x11FC || 0 || 1 || 4 || ResolveDepthBuffer&lt;br /&gt;
|-&lt;br /&gt;
| 0x200104C4 || 0x1310 || 0 || 1 || 1 || SetAlphaRef&lt;br /&gt;
|-&lt;br /&gt;
| 0x200404C7 || 0x131C || 0 || 4 || 1 || SetBlendColor&lt;br /&gt;
|-&lt;br /&gt;
| 0x2001064F || 0x1BD0 || 0 || 1 || 1 || SetDepthClamp&lt;br /&gt;
|-&lt;br /&gt;
| 0x200200CD || 0x0334 || 0 || 2 || 1 || SetInnerTessellationLevels&lt;br /&gt;
|-&lt;br /&gt;
| 0x200204EC || 0x13B0 || 0 || 2 || 1 || SetLineWidth&lt;br /&gt;
|-&lt;br /&gt;
| 0x200400C9 || 0x0324 || 0 || 4 || 1 || SetOuterTessellationLevels&lt;br /&gt;
|-&lt;br /&gt;
| 0x8???0373 || 0x0DCC || 0 || Variable || 4 || SetPatchSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x20010546 || 0x1518 || 0 || 1 || 1 || SetPointSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x20030554 || 0x1550 || 0 || 3 || 1 || SetRenderEnableConditional&lt;br /&gt;
|-&lt;br /&gt;
| 0x200403EF || 0x0FBC || 0 || 4 || 1 || SetSampleMask&lt;br /&gt;
|-&lt;br /&gt;
| 0x200103D9 || 0x0F64 || 0 || 1 || 1 || SetTiledCacheTileSize&lt;br /&gt;
|-&lt;br /&gt;
| 0x20020047 || 0x011C || 0 || 2 || 1 || SetGraphMacroEntry&lt;br /&gt;
|-&lt;br /&gt;
| 0xA???0045 || 0x0114 || 0 || Variable || 5 || SetGraphMacroCode&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note: These still need to be heavily verified and &#039;&#039;could&#039;&#039; be wrong.&lt;br /&gt;
&lt;br /&gt;
=== BindObject ===&lt;br /&gt;
&lt;br /&gt;
In order to bind an engine object to a specific subchannel, method 0 (BindObject) must be used first. The target subchannel is specified in bits 15-13 of the command word.&lt;br /&gt;
&lt;br /&gt;
After the engine object is bound to the desired subchannel, setting it&#039;s value in bits 15-13 of any subsequent command word will make PFIFO forward the command to the target engine.&lt;br /&gt;
&lt;br /&gt;
This method only takes one argument, an [[#Engine_IDs|engine ID]].&lt;br /&gt;
&lt;br /&gt;
==== Engine IDs ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| ID&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Engine&lt;br /&gt;
|-&lt;br /&gt;
|0x902D&lt;br /&gt;
|FERMI_TWOD_A (2D)&lt;br /&gt;
|-&lt;br /&gt;
|0xB197&lt;br /&gt;
|MAXWELL_B (3D)&lt;br /&gt;
|-&lt;br /&gt;
|0xB1C0&lt;br /&gt;
|MAXWELL_COMPUTE_B&lt;br /&gt;
|-&lt;br /&gt;
|0xA140&lt;br /&gt;
|KEPLER_INLINE_TO_MEMORY_B&lt;br /&gt;
|-&lt;br /&gt;
|0xB0B5&lt;br /&gt;
|MAXWELL_DMA_COPY_A (DMA)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Fences ===&lt;br /&gt;
&lt;br /&gt;
Command lists can contain fences to ensure that commands are executed on the correct order, and subsequent commands are only sent when the previously sent commands were already processed by the GPU. Fences uses the QUERY_* commands, and works like this:&lt;br /&gt;
&lt;br /&gt;
* First, QUERY_ADDRESS_HIGH and QUERY_ADDRESS_LOW commands are added to the Command List, with the High/Low 32 bits part of the 64-bits GPU Virtual Address where the fence is located. This GPU Virtual Address needs to be mapped to the process Virtual Address beforehand.&lt;br /&gt;
* Then, QUERY_SEQUENCE is added with a sequential number. This number is basically a incrementing counter, so the first Command List can have QUERY_SEQUENCE = 1, the next one QUERY_SEQUENCE = 2, 3, 4... and so on.&lt;br /&gt;
* Finally, QUERY_GET is added and contains the mode and other unknown data.&lt;br /&gt;
&lt;br /&gt;
The above commands are added using the [[#Submission_mode|increasing mode]], since the Ids for all those 4 registers are sequential.&lt;br /&gt;
&lt;br /&gt;
==== QUERY_GET Structure ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Bits&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|1-0&lt;br /&gt;
|Mode&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Fence&lt;br /&gt;
|-&lt;br /&gt;
|15-12&lt;br /&gt;
|Unit &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== QUERY_GET Mode ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Value&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Mode&lt;br /&gt;
|-&lt;br /&gt;
|0&lt;br /&gt;
|Write&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Sync&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Write ? &lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Write ?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
TODO: Move this to a separate page with all GPU Commands with descriptions. Also figure out what the other values mean.&lt;br /&gt;
&lt;br /&gt;
Some of the other fields are still unknown/unobserved.&lt;br /&gt;
&lt;br /&gt;
Official games will set Mode to 0, Fence to 1 and Unit to 0xF. The QUERY_SEQUENCE value is then written by the GPU to the address pointed to by QUERY_ADDRESS.&lt;br /&gt;
On the CPU side, the game code should wait until the value at the address pointed to by QUERY_ADDRESS is &amp;gt;= to the last written SEQUENCE value. Official code waits for this condition to be true on a loop, and won&#039;t send any further commands before that.&lt;br /&gt;
&lt;br /&gt;
== Vertex Data Submission ==&lt;br /&gt;
&lt;br /&gt;
Note: This is a observation on how the game Puyo Puyo Tetris sends textured squares to the GPU.&lt;br /&gt;
&lt;br /&gt;
# VERTEX_ATTRIB_FORMAT (0-15) are set (only the first 3 are really used, the rest are set float, with Size = 1 and offset at 0).&lt;br /&gt;
# VERTEX_ARRAY_FETCH (0) is set with the lower 12 bits set to 0x1c (Stride) and bit 12 to 1 (Enabled).&lt;br /&gt;
# VERTEX_ARRAY_START_HIGH/LOW (0) are set to the GPU Virtual Address where the Vertex Data is located.&lt;br /&gt;
# VERTEX_ARRAY_LIMIT_HIGH/LOW (0) are set to the GPU Virtual Address where the Vertex Data is located, plus the Vertex Data size in bytes minus 1.&lt;br /&gt;
# VERTEX_BEGIN_GL is used with the primitive type set to TRIANGLE_STRIP.&lt;br /&gt;
# VERTEX_BUFFER_FIRST with value 0 (indicating the index of the first primitive to render?).&lt;br /&gt;
# VERTEX_BUFFER_COUNT is set to 4, because the Vertex Buffer with the square has 4 vertices.&lt;br /&gt;
# VERTEX_END_GL is used with value 0 (currently unknown what this value means).&lt;br /&gt;
&lt;br /&gt;
== Texture View ==&lt;br /&gt;
&lt;br /&gt;
Texture information such as address, format and size is sent to the GPU through a structure know as Texture View (a.k.a Texture Image Control, or TIC). Each texture that the game uses needs a separate TIC, and those TICs are written to a table, one after the other. Each [[#TIC_Structure|TIC entry]] has 0x20 bytes, and is composed of 8 32-bits words where the texture information is packed.&lt;br /&gt;
&lt;br /&gt;
The index of the TIC entries that should be used by the shader is sent to the GPU with the CB_POS/CB_DATA (0) methods. Games usually follows the following steps to write the TIC entry indexes:&lt;br /&gt;
&lt;br /&gt;
* CB_ADDRESS_HIGH/LOW method is used to set the GPU Virtual Address of the Const Buffer.&lt;br /&gt;
* CB_POS is used to set the write offset of the Const Buffer to 0x20 + n * 4, where &#039;&#039;n&#039;&#039; is the is the index of the active texture that will be used by the shader (?).&lt;br /&gt;
* CB_DATA (0) method is used to write the value into the Const Buffer. The value is a word where the lower 20 bits is the TIC index.&lt;br /&gt;
&lt;br /&gt;
The address of a given TIC entry can be calculates as:&lt;br /&gt;
&lt;br /&gt;
 tic_entry_address = tic_base_address + tic_index * 0x20&lt;br /&gt;
&lt;br /&gt;
Where &#039;&#039;tic_base_address&#039;&#039; is the address written to TIC_ADDRESS_HIGH/LOW (methods 0x1574 and 0x1578), &#039;&#039;tic_index&#039;&#039; is the lower 20 bits of the word written into the Const Buffer with CB_DATA (0), and 0x20 is the size of each TIC entry in bytes.&lt;br /&gt;
&lt;br /&gt;
Note: More research still needs to be done on the Const Buffer and how it is used by the shader.&lt;br /&gt;
&lt;br /&gt;
=== TIC Structure ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Word || Bits || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 6-0 || [[GPU_Texture_Formats#Texture_Formats|Texture Format]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 9-7 || [[#Channel_Data_Type|R Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 12-10 || [[#Channel_Data_Type|G Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 15-13 || [[#Channel_Data_Type|B Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 18-16 || [[#Channel_Data_Type|A Channel Data Type]]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 31-0 || Lower 32-bits of the Texture GPU Virtual Address&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 15-0 || Higher 16-bits of the Texture GPU Virtual Address&lt;br /&gt;
|-&lt;br /&gt;
| 4 || 15-0 || Texture Width minus 1&lt;br /&gt;
|-&lt;br /&gt;
| 5 || 15-0 || Texture Height minus 1&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Channel Data Type ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Type&lt;br /&gt;
|-&lt;br /&gt;
| 1 || SNORM&lt;br /&gt;
|-&lt;br /&gt;
| 2 || UNORM&lt;br /&gt;
|-&lt;br /&gt;
| 3 || SINT&lt;br /&gt;
|-&lt;br /&gt;
| 4 || UINT&lt;br /&gt;
|-&lt;br /&gt;
| 5 || SNORM_FORCE_FP16&lt;br /&gt;
|-&lt;br /&gt;
| 6 || UNORM_FORCE_FP16&lt;br /&gt;
|-&lt;br /&gt;
| 7 || FLOAT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
FIFO engine overview:&lt;br /&gt;
[https://envytools.readthedocs.io/en/latest/hw/fifo/intro.html]&lt;br /&gt;
&lt;br /&gt;
Method values from the Fermi family GPU (a bit older than the Tegra X1, but values seems to be mostly the same):&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/gf100_3d.xml]&lt;br /&gt;
&lt;br /&gt;
TIC structure used on a Maxwell GPU:&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/gm200_texture.xml]&lt;br /&gt;
&lt;br /&gt;
Values for some types used on the above XML:&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/nv_3ddefs.xml]&lt;br /&gt;
&lt;br /&gt;
Command word packing code used on Mesa3d:&lt;br /&gt;
[https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nvc0/nvc0_winsys.h]&lt;br /&gt;
&lt;br /&gt;
TIC entry pack/write code used on Mesa3d:&lt;br /&gt;
[https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nvc0/nvc0_tex.c#n65]&lt;/div&gt;</summary>
		<author><name>Gdkchan</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=GPU_Texture_Formats&amp;diff=3619</id>
		<title>GPU Texture Formats</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=GPU_Texture_Formats&amp;diff=3619"/>
		<updated>2018-02-05T12:33:59Z</updated>

		<summary type="html">&lt;p&gt;Gdkchan: Created page with &amp;quot;== Texture Formats ==  {| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot; |- ! Value || Format |- | 0x01 || R32_G32_B32_A32 |- | 0x02 || R32_G32_B32 |- | 0x03 || R16_G16_B16_A16 |- | 0x04 || R32...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Texture Formats ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Value || Format&lt;br /&gt;
|-&lt;br /&gt;
| 0x01 || R32_G32_B32_A32&lt;br /&gt;
|-&lt;br /&gt;
| 0x02 || R32_G32_B32&lt;br /&gt;
|-&lt;br /&gt;
| 0x03 || R16_G16_B16_A16&lt;br /&gt;
|-&lt;br /&gt;
| 0x04 || R32_G32&lt;br /&gt;
|-&lt;br /&gt;
| 0x05 || R32_B24G8&lt;br /&gt;
|-&lt;br /&gt;
| 0x06 || ETC2_RGB&lt;br /&gt;
|-&lt;br /&gt;
| 0x07 || X8B8G8R8&lt;br /&gt;
|-&lt;br /&gt;
| 0x08 || A8B8G8R8&lt;br /&gt;
|-&lt;br /&gt;
| 0x09 || A2B10G10R10&lt;br /&gt;
|-&lt;br /&gt;
| 0x0a || ETC2_RGB_PTA&lt;br /&gt;
|-&lt;br /&gt;
| 0x0b || ETC2_RGBA&lt;br /&gt;
|-&lt;br /&gt;
| 0x0c || R16_G16&lt;br /&gt;
|-&lt;br /&gt;
| 0x0d || G8R24&lt;br /&gt;
|-&lt;br /&gt;
| 0x0e || G24R8&lt;br /&gt;
|-&lt;br /&gt;
| 0x0f || R32&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || BC6H_SF16&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || BC6H_UF16&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || A4B4G4R4&lt;br /&gt;
|-&lt;br /&gt;
| 0x13 || A5B5G5R1&lt;br /&gt;
|-&lt;br /&gt;
| 0x14 || A1B5G5R5&lt;br /&gt;
|-&lt;br /&gt;
| 0x15 || B5G6R5&lt;br /&gt;
|-&lt;br /&gt;
| 0x16 || B6G5R5&lt;br /&gt;
|-&lt;br /&gt;
| 0x17 || BC7U&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || G8R8&lt;br /&gt;
|-&lt;br /&gt;
| 0x19 || EAC&lt;br /&gt;
|-&lt;br /&gt;
| 0x1a || EACX2&lt;br /&gt;
|-&lt;br /&gt;
| 0x1b || R16&lt;br /&gt;
|-&lt;br /&gt;
| 0x1c || Y8_VIDEO&lt;br /&gt;
|-&lt;br /&gt;
| 0x1d || R8&lt;br /&gt;
|-&lt;br /&gt;
| 0x1e || G4R4&lt;br /&gt;
|-&lt;br /&gt;
| 0x1f || R1&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || E5B9G9R9_SHAREDEXP&lt;br /&gt;
|-&lt;br /&gt;
| 0x21 || BF10GF11RF11&lt;br /&gt;
|-&lt;br /&gt;
| 0x22 || G8B8G8R8&lt;br /&gt;
|-&lt;br /&gt;
| 0x23 || B8G8R8G8&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || DXT1 (a.k.a. BC1)&lt;br /&gt;
|-&lt;br /&gt;
| 0x25 || DXT23 (a.k.a. BC2)&lt;br /&gt;
|-&lt;br /&gt;
| 0x26 || DXT45 (a.k.a. BC3)&lt;br /&gt;
|-&lt;br /&gt;
| 0x27 || DXN1&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || DXN2&lt;br /&gt;
|-&lt;br /&gt;
| 0x29 || Z24S8&lt;br /&gt;
|-&lt;br /&gt;
| 0x2a || X8Z24&lt;br /&gt;
|-&lt;br /&gt;
| 0x2b || S8Z24&lt;br /&gt;
|-&lt;br /&gt;
| 0x2c || X4V4Z24__COV4R4V&lt;br /&gt;
|-&lt;br /&gt;
| 0x2d || X4V4Z24__COV8R8V&lt;br /&gt;
|-&lt;br /&gt;
| 0x2e || V8Z24__COV4R12V&lt;br /&gt;
|-&lt;br /&gt;
| 0x2f || ZF32&lt;br /&gt;
|-&lt;br /&gt;
| 0x30 || ZF32_X24S8&lt;br /&gt;
|-&lt;br /&gt;
| 0x31 || X8Z24_X20V4S8__COV4R4V&lt;br /&gt;
|-&lt;br /&gt;
| 0x32 || X8Z24_X20V4S8__COV8R8V&lt;br /&gt;
|-&lt;br /&gt;
| 0x33 || ZF32_X20V4X8__COV4R4V&lt;br /&gt;
|-&lt;br /&gt;
| 0x34 || ZF32_X20V4X8__COV8R8V&lt;br /&gt;
|-&lt;br /&gt;
| 0x35 || ZF32_X20V4S8__COV4R4V&lt;br /&gt;
|-&lt;br /&gt;
| 0x36 || ZF32_X20V4S8__COV8R8V&lt;br /&gt;
|-&lt;br /&gt;
| 0x37 || X8Z24_X16V8S8__COV4R12V&lt;br /&gt;
|-&lt;br /&gt;
| 0x38 || ZF32_X16V8X8__COV4R12V&lt;br /&gt;
|-&lt;br /&gt;
| 0x39 || ZF32_X16V8S8__COV4R12V&lt;br /&gt;
|-&lt;br /&gt;
| 0x3a || Z16&lt;br /&gt;
|-&lt;br /&gt;
| 0x3b || V8Z24__COV8R24V&lt;br /&gt;
|-&lt;br /&gt;
| 0x3c || X8Z24_X16V8S8__COV8R24V&lt;br /&gt;
|-&lt;br /&gt;
| 0x3d || ZF32_X16V8X8__COV8R24V&lt;br /&gt;
|-&lt;br /&gt;
| 0x3e || ZF32_X16V8S8__COV8R24V&lt;br /&gt;
|-&lt;br /&gt;
| 0x40 || ASTC_2D_4X4&lt;br /&gt;
|-&lt;br /&gt;
| 0x41 || ASTC_2D_5X5&lt;br /&gt;
|-&lt;br /&gt;
| 0x42 || ASTC_2D_6X6&lt;br /&gt;
|-&lt;br /&gt;
| 0x44 || ASTC_2D_8X8&lt;br /&gt;
|-&lt;br /&gt;
| 0x45 || ASTC_2D_10X10&lt;br /&gt;
|-&lt;br /&gt;
| 0x46 || ASTC_2D_12X12&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || ASTC_2D_5X4&lt;br /&gt;
|-&lt;br /&gt;
| 0x51 || ASTC_2D_6X5&lt;br /&gt;
|-&lt;br /&gt;
| 0x52 || ASTC_2D_8X6&lt;br /&gt;
|-&lt;br /&gt;
| 0x53 || ASTC_2D_10X8&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || ASTC_2D_12X10&lt;br /&gt;
|-&lt;br /&gt;
| 0x55 || ASTC_2D_8X5&lt;br /&gt;
|-&lt;br /&gt;
| 0x56 || ASTC_2D_10X5&lt;br /&gt;
|-&lt;br /&gt;
| 0x57 || ASTC_2D_10X6&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Reference ==&lt;br /&gt;
&lt;br /&gt;
Adapted from EnvyTools documentation:&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/gm200_texture.xml]&lt;/div&gt;</summary>
		<author><name>Gdkchan</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=SVC&amp;diff=3465</id>
		<title>SVC</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=SVC&amp;diff=3465"/>
		<updated>2018-01-18T12:50:18Z</updated>

		<summary type="html">&lt;p&gt;Gdkchan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&lt;br /&gt;
= System calls =&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Id || Name || In || Out&lt;br /&gt;
|-&lt;br /&gt;
|  0x1 || [[#svcSetHeapSize]] || W1=size || W0=result, X1=outaddr&lt;br /&gt;
|-&lt;br /&gt;
|  0x2 || [[#svcSetMemoryPermission]] || X0=addr, X1=size, W2=prot || W0=result&lt;br /&gt;
|-&lt;br /&gt;
|  0x3 || [[#svcSetMemoryAttribute]] || X0=addr, X1=size, W2=state0, W3=state1 || W0=result&lt;br /&gt;
|-&lt;br /&gt;
|  0x4 || [[#svcMapMemory]] || X0=dstaddr, X1=srcaddr, X2=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
|  0x5 || [[#svcUnmapMemory]] || X0=dstaddr, X1=srcaddr, X2=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
|  0x6 || [[#svcQueryMemory]] || X0=MemoryInfo*, X2=addr || W0=result, W1=PageInfo                                                         &lt;br /&gt;
|-&lt;br /&gt;
|  0x7 || [[#svcExitProcess]] || None ||&lt;br /&gt;
|-&lt;br /&gt;
|  0x8 || [[#svcCreateThread]] || X1=entry, X2=thread_context, X3=stacktop, W4=prio, W5=processor_id  || W0=result, W1=handle&lt;br /&gt;
|-&lt;br /&gt;
|  0x9 || [[#svcStartThread]] || W0=thread_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
|  0xA || [[#svcExitThread]] || None ||                                                         &lt;br /&gt;
|-&lt;br /&gt;
|  0xB || [[#svcSleepThread]] || X0=nano || W0=result&lt;br /&gt;
|-&lt;br /&gt;
|  0xC || [[#svcGetThreadPriority]] || W1=thread_handle || W0=result, W1=prio&lt;br /&gt;
|-&lt;br /&gt;
|  0xD || [[#svcSetThreadPriority]] || W0=thread_handle, W1=prio || W0=result&lt;br /&gt;
|-&lt;br /&gt;
|  0xE || [[#svcGetThreadCoreMask]] || W2=thread_handle || W0=result, W1=out, X2=out&lt;br /&gt;
|-&lt;br /&gt;
|  0xF || [[#svcSetThreadCoreMask]] || W0=thread_handle, W1=in, X2=in2 || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || [[#svcGetCurrentProcessorNumber]] || None || W0/X0=cpuid&lt;br /&gt;
|-&lt;br /&gt;
| 0x11 || svcSignalEvent || W0=wevent_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x12 || svcClearEvent || W0=wevent_or_revent_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x13 || [[#svcMapSharedMemory]] || W0=shmem_handle, X1=addr, X2=size, W3=perm || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x14 || svcUnmapSharedMemory || W0=shmem_handle, X1=addr, X2=size || W0=result                                                 &lt;br /&gt;
|-&lt;br /&gt;
| 0x15 || [[#svcCreateTransferMemory]] || X1=addr, X2=size, W3=perm || W0=result, W1=tmem_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x16 || svcCloseHandle || W0=handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x17 || svcResetSignal || W0=revent_or_process_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || [[#svcWaitSynchronization]] || X1=handles_ptr, W2=num_handles. X3=timeout || W0=result, W1=handle_idx&lt;br /&gt;
|-&lt;br /&gt;
| 0x19 || svcCancelSynchronization || W0=thread_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x1A || svcArbitrateLock || W0=cur_thread_handle, X1=ptr, W2=req_thread_handle ||                                     &lt;br /&gt;
|-&lt;br /&gt;
| 0x1B || svcArbitrateUnlock || X0=ptr ||&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || svcWaitProcessWideKeyAtomic || X0=ptr0, X1=ptr, W2=thread_handle, X3=timeout || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x1D || svcSignalProcessWideKey || X0=ptr, W1=value || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x1E || svcGetSystemTick || None || X0={value of cntpct_el0}&lt;br /&gt;
|-&lt;br /&gt;
| 0x1F || svcConnectToNamedPort || X1=port_name_str || W0=result, W1=handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || svcSendSyncRequestLight || W0=light_session_handle, X1=? || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x21 || svcSendSyncRequest || X0=normal_session_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x22 || [[#svcSendSyncRequestWithUserBuffer]] || X0=cmdbufptr, X1=size, X2=handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x23 || svcSendAsyncRequestWithUserBuffer || X1=cmdbufptr, X2=size, X3=handle || W0=result, W1=event_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || svcGetProcessId || W1=thread_or_process_or_debug_handle || W0=result, X1=pid&lt;br /&gt;
|-&lt;br /&gt;
| 0x25 || svcGetThreadId || W0=thread_handle || W0=result, X1=out&lt;br /&gt;
|-&lt;br /&gt;
| 0x26 || svcBreak || X0,X1,X2=info || ?&lt;br /&gt;
|-&lt;br /&gt;
| 0x27 || svcOutputDebugString || X0=str, X1=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || svcReturnFromException || X0=result || &lt;br /&gt;
|-&lt;br /&gt;
| 0x29 || [[#svcGetInfo]] || X1=info_id, X2=handle, X3=info_sub_id || W0=result, X1=out&lt;br /&gt;
|-&lt;br /&gt;
| 0x2A || svcFlushEntireDataCache || None || None&lt;br /&gt;
|-&lt;br /&gt;
| 0x2B || svcFlushDataCache || X0=addr, X1=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C || [3.0.0+] [[#svcMapPhysicalMemory]] || X0=addr, X1=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x2D || [3.0.0+] svcUnmapPhysicalMemory|| X0=addr, X1=size || W0=result&lt;br /&gt;
|- style=&amp;quot;border-top: double&amp;quot;&lt;br /&gt;
| 0x2F || svcGetLastThreadInfo || None || W0=result, W1,W2,W3,W4=unk, W5=truncated_u64, W6=bool&lt;br /&gt;
|-&lt;br /&gt;
| 0x30 || svcGetResourceLimitLimitValue || W1=reslimit_handle, W2=[[#LimitableResource]] || W0=result, X1=value&lt;br /&gt;
|-&lt;br /&gt;
| 0x31 || svcGetResourceLimitCurrentValue || W1=reslimit_handle, W2=[[#LimitableResource]] || W0=result, X1=value&lt;br /&gt;
|-&lt;br /&gt;
| 0x32 || svcSetThreadActivity || W0=thread_handle, W1=bool || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x33 || svcGetThreadContext3 || W0=thread_handle, W1=[[#ThreadContext]]* || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x34 || [4.0.0+] || X0=ptr, W1=type, X2=? X3=timeout ||&lt;br /&gt;
|-&lt;br /&gt;
| 0x35 || [4.0.0+] || X0=ptr, W1=type, X2=? W3=? ||&lt;br /&gt;
|- style=&amp;quot;border-top: double&amp;quot;&lt;br /&gt;
| 0x3C || [[#svcDumpInfo]] || ||&lt;br /&gt;
|-&lt;br /&gt;
| 0x3D || [4.0.0+] svcDumpInfoNew || ||&lt;br /&gt;
|- style=&amp;quot;border-top: double&amp;quot;&lt;br /&gt;
| 0x40 || svcCreateSession || W2=is_light, X3=? || W0=result, W1=server_handle, W2=client_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x41 || [[#svcAcceptSession]] || W1=port_handle || W0=result, W1=session_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x42 || svcReplyAndReceiveLight || W0=light_session_handle || W0=result, W1,W2,W3,W4,W5,W6,W7=out&lt;br /&gt;
|-&lt;br /&gt;
| 0x43 || [[#svcReplyAndReceive]] || X1=ptr_handles, W2=num_handles, X3=replytarget_handle(0=none), X4=timeout || W0=result, W1=handle_idx&lt;br /&gt;
|-&lt;br /&gt;
| 0x44 || svcReplyAndReceiveWithUserBuffer|| X1=buf, X2=sz, X3=ptr_handles, W4=num_handles, X5=replytarget_handle(0=none), X6=timeout || W0=result, W1=handle_idx&lt;br /&gt;
|-&lt;br /&gt;
| 0x45 || svcCreateEvent || None || W0=result, W1=client_handle ?, W2=server_handle ?&lt;br /&gt;
|- style=&amp;quot;border-top: double&amp;quot;&lt;br /&gt;
| 0x4B || [4.0.0+] [[#svcCreateJitMemory]] || X1=addr, X2=size || W0=result, W1=jit_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x4C || [4.0.0+] [[#svcMapJitMemory]] || W0=jit_handle, W1=[[#MapJitOperation]], X2=dstaddr, X3=size, W4=perm || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x4D || svcSleepSystem || None || None&lt;br /&gt;
|-&lt;br /&gt;
| 0x4E || [[#svcReadWriteRegister]] || X1=reg_addr, W2=rw_mask, W3=in_val || W0=result, W1=out_val&lt;br /&gt;
|-&lt;br /&gt;
| 0x4F || svcSetProcessActivity || W0=process_handle, W1=bool || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x50 || [[#svcCreateSharedMemory]] || W1=size, W2=myperm, W3=otherperm || W0=result, W1=shmem_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x51 || [[#svcMapTransferMemory]] || X0=tmem_handle, X1=addr, X2=size, W3=perm || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x52 || [[#svcUnmapTransferMemory]] || W0=tmemhandle, X1=addr, X2=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x53 || svcCreateInterruptEvent || X1=irq_num, W2=flag || W0=result, W1=handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x54 || [[#svcQueryPhysicalAddress]] || X1=addr || W0=result, X1=physaddr, X2=kerneladdr, X3=size&lt;br /&gt;
|-&lt;br /&gt;
| 0x55 || [[#svcQueryIoMapping]] || X1=physaddr, X2=size || W0=result, X1=virtaddr&lt;br /&gt;
|-&lt;br /&gt;
| 0x56 || [[#svcCreateDeviceAddressSpace]] || X1=dev_as_start_addr, X2=dev_as_end_addr || W0=result, W1=dev_as_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x57 || [[#svcAttachDeviceAddressSpace]] || W0=device, X1=dev_as_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x58 || [[#svcDetachDeviceAddressSpace]] || W0=device, X1=dev_as_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x59 || [[#svcMapDeviceAddressSpaceByForce]] || W0=dev_as_handle, W1=proc_handle, X2=dev_map_addr, X3=dev_as_size, X4=dev_as_addr, W5=perm || W0=result &lt;br /&gt;
|-&lt;br /&gt;
| 0x5A || [[#svcMapDeviceAddressSpaceAligned]] || W0=dev_as_handle, W1=proc_handle, X2=dev_map_addr, X3=dev_as_size, X4=dev_as_addr, W5=perm || W0=result &lt;br /&gt;
|-&lt;br /&gt;
| 0x5B || svcMapDeviceAddressSpace || || &lt;br /&gt;
|-&lt;br /&gt;
| 0x5C || [[#svcUnmapDeviceAddressSpace]] || W0=dev_as_handle, W1=proc_handle, X2=dev_map_addr, X3=dev_as_size, X4=dev_as_addr || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x5D || svcInvalidateProcessDataCache || W0=process_handle, X1=addr, X2=size || W0=size&lt;br /&gt;
|-&lt;br /&gt;
| 0x5E || svcStoreProcessDataCache || W0=process_handle, X1=addr, X2=size || W0=size&lt;br /&gt;
|-&lt;br /&gt;
| 0x5F || svcFlushProcessDataCache || W0=process_handle, X1=addr, X2=size || W0=size&lt;br /&gt;
|-&lt;br /&gt;
| 0x60 || svcDebugActiveProcess || X1=pid || W0=result, W1=debug_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x61 || svcBreakDebugProcess || W0=debug_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x62 || svcTerminateDebugProcess || W0=debug_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x63 || svcGetDebugEvent || X0=DebugEventInfo*, W1=debug_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x64 || svcContinueDebugEvent || W0=debug_handle, W1=[[#ContinueDebugFlags]], X2=thread_id || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x65 || svcGetProcessList || X1=pids_out_ptr, W2=max_out || W0=result, W1=num_out &lt;br /&gt;
|-&lt;br /&gt;
| 0x66 || svcGetThreadList || X1=tids_out_ptr, W2=max_out, W3=debug_handle_or_zero || W0=result, X1=num_out&lt;br /&gt;
|-&lt;br /&gt;
| 0x67 || svcGetDebugThreadContext || X0=ThreadContext*, X1=debug_handle, X2=thread_id, W3=[[#ThreadContextFlags]] || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x68 || svcSetDebugThreadContext || W0=debug_handle, W1=[[#ThreadContextFlags]], X2=ThreadContext* || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x69 || svcQueryDebugProcessMemory || X0=[[#MemoryInfo]]*, X2=debug_handle, X3=addr || W0=result, W1=PageInfo&lt;br /&gt;
|-&lt;br /&gt;
| 0x6A || svcReadDebugProcessMemory || X0=buffer*, X1=debug_handle, X2=src_addr, X3=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x6B || svcWriteDebugProcessMemory || X0=debug_handle, X1=buffer*, X2=dst_addr, X3=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x6C || svcSetHardwareBreakPoint || W0=HardwareBreakpointId, X1=watchpoint_flags, X2=watchpoint_value/debug_handle? || &lt;br /&gt;
|-&lt;br /&gt;
| 0x6D || svcGetDebugThreadParam || X2=debug_handle, X3=thread_id, W4=[[#DebugThreadParam]] || W0=result, X1=out0, W2=out1&lt;br /&gt;
|- style=&amp;quot;border-top: double&amp;quot;&lt;br /&gt;
| 0x70 || svcCreatePort || W2=max_sessions, W3=unk_bool, X4=name_ptr || W0=result, W1=clientport_handle, W2=serverport_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x71 || svcManageNamedPort || X1=name_ptr, W2=max_sessions || W0=result, W1=serverport_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x72 || svcConnectToPort || W1=clientport_handle || W0=result, W1=session_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x73 || [[#svcSetProcessMemoryPermission]] || W0=process_handle, X1=addr, X2=size, W3=perm || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x74 || [[#svcMapProcessMemory]] || X0=srcaddr, W1=process_handle, X2=dstaddr, X3=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x75 || [[#svcUnmapProcessMemory]] || W0=process_handle, X1=dstaddr, X2=srcaddr, X3=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x76 || [[#svcQueryProcessMemory]] || X0=meminfo_ptr, W2=process_handle, X3=addr || W0=result, W1=pageinfo&lt;br /&gt;
|-&lt;br /&gt;
| 0x77 || [[#svcMapProcessCodeMemory]] || W0=process_handle, X2=dstaddr, X2=srcaddr, X3=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x78 || [[#svcUnmapProcessCodeMemory]] || W0=process_handle, X1=dstaddr, X2=srcaddr, X3=size || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x79 || [[#svcCreateProcess]] || X1=procinfo_ptr, X2=caps_ptr, W3=cap_num ||  W0=result, W1=process_handle&lt;br /&gt;
|-&lt;br /&gt;
| 0x7A || svcStartProcess || W0=process_handle, W1=main_thread_prio, W2=default_cpuid, W3=main_thread_stacksz || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x7B || svcTerminateProcess || W0=process_handle || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x7C || [[#svcGetProcessInfo]] || W0=process_handle || W0=result, X1=[[#ProcessState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x7D || svcCreateResourceLimit || None || W0=result, W1=reslimit_handle &lt;br /&gt;
|-&lt;br /&gt;
| 0x7E || svcSetResourceLimitLimitValue || W0=reslimit_handle, W1=[[#LimitableResource]], X2=value || W0=result&lt;br /&gt;
|-&lt;br /&gt;
| 0x7F || svcCallSecureMonitor || X0=smc_sub_id, X1,X2,X3,X4,X5,X6,X7=smc_args || X0,X1,X2,X3,X4,X5,X6,X7=result&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== svcSetHeapSize ==&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) X1 || u64 || OutAddr&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Set the process heap to a given Size. It can both extend and shrink the heap.&lt;br /&gt;
&lt;br /&gt;
Size must be a multiple of 0x2000000.&lt;br /&gt;
&lt;br /&gt;
On success, the heap base-address (which is fixed by kernel, aslr&#039;d) is written to OutAddr.&lt;br /&gt;
&lt;br /&gt;
[2.0.0+] Size must be less than 0x18000000.&lt;br /&gt;
&lt;br /&gt;
== svcSetMemoryPermission ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || void* || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || [[#Permission]] || Prot&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Change permission of page-aligned memory region.&lt;br /&gt;
&lt;br /&gt;
Bit2 of permission (exec) is not allowed. Setting write-only is not allowed either (bit1).&lt;br /&gt;
&lt;br /&gt;
This can be used to move back and forth between ---, r-- and rw-.&lt;br /&gt;
&lt;br /&gt;
== svcSetMemoryAttribute ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || void* || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || u32 || State0&lt;br /&gt;
|-&lt;br /&gt;
| (In) W3 || u32 || State1&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Change attribute of page-aligned memory region. &lt;br /&gt;
&lt;br /&gt;
This is used to turn on/off caching for a given memory area. Useful when talking to devices such as the GPU.&lt;br /&gt;
&lt;br /&gt;
What happens &amp;quot;under the hood&amp;quot; is the &amp;quot;Memory Attribute Indirection Register&amp;quot; index is changed from 2 to 3 in the MMU descriptor.&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! State0 || State1 || Action&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 0 || Clear bit3 in [[#MemoryAttribute]].&lt;br /&gt;
|-&lt;br /&gt;
| 8 || 0 || Clear bit3 in [[#MemoryAttribute]].&lt;br /&gt;
|-&lt;br /&gt;
| 8 || 8 || Set bit3 in [[#MemoryAttribute]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== svcMapMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || void* || DstAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || void* || SrcAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Maps a memory range into a different range.&lt;br /&gt;
&lt;br /&gt;
Mainly used for adding guard pages around stack.&lt;br /&gt;
&lt;br /&gt;
Source range gets reprotected to --- (it can no longer be accessed), and bit0 is set in the source [[#MemoryAttribute]].&lt;br /&gt;
&lt;br /&gt;
If dstaddr &amp;gt;= LowerTreshold, the dst-range is enforced to be within the process&#039; &amp;quot;MapRegion&amp;quot;. Code can get the range of this region from [[#svcGetInfo]] id0=2,3.&lt;br /&gt;
&lt;br /&gt;
In this case, the mapped memory will have state 0x5C3C0B.&lt;br /&gt;
&lt;br /&gt;
As long as (dstaddr+size) &amp;lt; LowerThreshold, then you can map anywhere but the mapped memory will have state 0x482907 instead.&lt;br /&gt;
&lt;br /&gt;
LowerTreshold is 0x80000000 for 36-bit address spaces, and 0x40000000 for 32-bit ones.&lt;br /&gt;
&lt;br /&gt;
[2.0.0+] Support for the 0x482907 mappings outside the &amp;quot;MapRegion&amp;quot; were removed.&lt;br /&gt;
&lt;br /&gt;
== svcUnmapMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || void* || DstAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || void* || SrcAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Unmaps a region that was previously mapped with [[#svcMapMemory]].&lt;br /&gt;
&lt;br /&gt;
It&#039;s possible to unmap ranges partially, you don&#039;t need to unmap the entire range &amp;quot;in one go&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The srcaddr/dstaddr must match what was given when the pages were originally mapped.&lt;br /&gt;
&lt;br /&gt;
== svcQueryMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || [[#MemoryInfo]]* || MemInfo&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || void* || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || PageInfo || PageInfo&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Query information about an address. Will always fetch the lowest page-aligned mapping that contains the provided address.&lt;br /&gt;
&lt;br /&gt;
Outputs a [[#MemoryInfo]] struct.&lt;br /&gt;
&lt;br /&gt;
== svcExitProcess ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) None || || &lt;br /&gt;
|-&lt;br /&gt;
| (Out) None || ||&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Exits the current process.&lt;br /&gt;
&lt;br /&gt;
== svcCreateThread ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || void(*)(void*) || Entry&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || void* || ThreadContext&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || void* || StackTop&lt;br /&gt;
|-&lt;br /&gt;
| (In) W4 || u32 || Priority&lt;br /&gt;
|-&lt;br /&gt;
| (In) W5 || u32 || ProcessorId&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || Handle&amp;lt;Thread&amp;gt; || Handle&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Create a thread in the current process.&lt;br /&gt;
&lt;br /&gt;
Processor_id must be 0,1,2,3 or -2, where -2 uses the default cpuid for process.&lt;br /&gt;
&lt;br /&gt;
== svcStartThread ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;Thread&amp;gt; || Handle&lt;br /&gt;
|-&lt;br /&gt;
| (Out) None ||  ||&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Starts the thread for the provided handle.&lt;br /&gt;
&lt;br /&gt;
== svcExitThread ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) None || || &lt;br /&gt;
|-&lt;br /&gt;
| (Out) None || ||&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Exits the current thread.&lt;br /&gt;
&lt;br /&gt;
== svcSleepThread ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || u64 || Nano&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Sleep for a specified amount of time, or yield thread.&lt;br /&gt;
&lt;br /&gt;
Setting nano=0 means &amp;quot;yield thread&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== svcGetThreadPriority ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1|| Handle&amp;lt;Thread&amp;gt; || Handle&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || u64 || Priority&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Get priority of provided thread handle.&lt;br /&gt;
&lt;br /&gt;
== svcSetThreadPriority ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0|| Handle&amp;lt;Thread&amp;gt; || Handle&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1|| u32 || Priority&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Set priority of provided thread handle.&lt;br /&gt;
&lt;br /&gt;
Priority is a number 0-0x3F. Lower value means higher priority.&lt;br /&gt;
&lt;br /&gt;
== svcGetThreadCoreMask ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || Handle&amp;lt;Thread&amp;gt; || Handle&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || u32 || Out0&lt;br /&gt;
|-&lt;br /&gt;
| (Out) X2 || u64 || Out1&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Get affinity mask of provided thread handle.&lt;br /&gt;
&lt;br /&gt;
== svcSetThreadCoreMask ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;Thread&amp;gt; || Handle&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1 || u32 || In0&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || In1&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Set affinity mask of provided thread handle.&lt;br /&gt;
&lt;br /&gt;
== svcGetCurrentProcessorNumber ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) None || || &lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0/X0 || u64 || CpuId&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Get which cpu is executing the current thread.&lt;br /&gt;
&lt;br /&gt;
Cpu-id is an integer in the range 0-3.&lt;br /&gt;
&lt;br /&gt;
== svcMapSharedMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;SharedMemory&amp;gt; || MemHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || void* || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (In) W3 || [[#Permission]] || Permissions&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Maps the block supplied by the handle. The required permissions are different for the process that created the handle and all other processes.&lt;br /&gt;
&lt;br /&gt;
Increases reference count for the KSharedMemory object. Thus in order to release the memory associated with the object, all handles to it must be closed and all mappings must be unmapped.&lt;br /&gt;
&lt;br /&gt;
== svcCreateTransferMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || void* || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (In) W3 || [[#Permission]] || Permissions&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || Handle&amp;lt;TransferMemory&amp;gt; || Handle&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This one reprotects the src block with perms you give it. It also sets bit0 into [[#MemoryAttribute]].&lt;br /&gt;
&lt;br /&gt;
Executable bit perm not allowed.&lt;br /&gt;
&lt;br /&gt;
Closing all handles automatically causes the bit0 in [[#MemoryAttribute]] to clear, and the permission to reset.&lt;br /&gt;
&lt;br /&gt;
== svcWaitSynchronization ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || Handle* || HandlesPtr&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || u64 || HandlesNum&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || Timeout&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || u64 || HandleIndex&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Works with num_handles &amp;lt;= 0x40, error on num_handles == 0.&lt;br /&gt;
&lt;br /&gt;
Does not accept 0xFFFF8001 or 0xFFFF8000 as handles.&lt;br /&gt;
&lt;br /&gt;
=== Object types ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Port:&#039;&#039;&#039; signals when there is an incoming connection waiting to be [[#svcAcceptSession|accepted]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Session (server-side):&#039;&#039;&#039; signals when there is an incoming message waiting to be [[#svcReplyAndReceive|received]] or the pipe is closed.&lt;br /&gt;
&lt;br /&gt;
=== Result codes ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;0x0:&#039;&#039;&#039; Success. One of the objects was signalled before the timeout expired. Handle index is updated to indicate which object signalled.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;0xe401:&#039;&#039;&#039; Invalid handle. Returned when one of the handles passed is invalid. Handle index is not updated.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;0xea01:&#039;&#039;&#039; Timeout. Returned when no objects have been signalled within the timeout. Handle index is not updated.&lt;br /&gt;
&lt;br /&gt;
== svcSendSyncRequestWithUserBuffer ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || void* || CmdPtr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || Handle&amp;lt;Session&amp;gt; || Handle&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Size must be 0x1000-aligned.&lt;br /&gt;
&lt;br /&gt;
== svcBreak ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || u64 ||&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 ||&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || Info&lt;br /&gt;
|-&lt;br /&gt;
| (Out) ? || ? || ?&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When used on retail where inx0 bit31 is clear, the system will throw a [[Error_codes|fatal-error]]. Otherwise when bit31 is set, it will return 0.&lt;br /&gt;
&lt;br /&gt;
== svcGetInfo ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || InfoId&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || Handle || Handle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || InfoSubId&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) X1 || u64 || Out&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Handle type || Id0 || Id1 || Description&lt;br /&gt;
|-&lt;br /&gt;
| Process || 0 || 0 || AllowedCpuIdBitmask&lt;br /&gt;
|-&lt;br /&gt;
| Process || 1 || 0 || AllowedThreadPrioBitmask&lt;br /&gt;
|-&lt;br /&gt;
| Process || 2 || 0 || MapRegionBaseAddr&lt;br /&gt;
|-&lt;br /&gt;
| Process || 3 || 0 || MapRegionSize&lt;br /&gt;
|-&lt;br /&gt;
| Process || 4 || 0 || HeapRegionBaseAddr&lt;br /&gt;
|-&lt;br /&gt;
| Process || 5 || 0 || HeapRegionSize&lt;br /&gt;
|-&lt;br /&gt;
| Process || 6 || 0 || TotalMemoryUsage&lt;br /&gt;
|-&lt;br /&gt;
| Process || 7 || 0 || TotalHeapUsage&lt;br /&gt;
|-&lt;br /&gt;
| Zero    || 8 || 0 || IsCurrentProcessBeingDebugged&lt;br /&gt;
|-&lt;br /&gt;
| Zero    || 9 || 0 || Returns ResourceLimit handle for current process. Used by [[Process_Manager_services|PM]].&lt;br /&gt;
|-&lt;br /&gt;
| Zero    || 10 || -1, {current coreid} || IdleTickCount&lt;br /&gt;
|-&lt;br /&gt;
| Zero    || 11 || 0-3 || RandomEntropy from current process. TRNG. Used to seed usermode PRNGs.&lt;br /&gt;
|-&lt;br /&gt;
| Process || 12 || 0 || [2.0.0+] AddressSpaceBaseAddr&lt;br /&gt;
|-&lt;br /&gt;
| Process || 13 || 0 || [2.0.0+] AddressSpaceSize&lt;br /&gt;
|-&lt;br /&gt;
| Process || 14 || 0 || [2.0.0+] NewMapRegionBaseAddr&lt;br /&gt;
|-&lt;br /&gt;
| Process || 15 || 0 || [2.0.0+] NewMapRegionSize&lt;br /&gt;
|-&lt;br /&gt;
| Process || 16 || 0 || [3.0.0+] IsVirtualAddressMemoryEnabled&lt;br /&gt;
|-&lt;br /&gt;
| Process || 17 || 0 || [3.0.0+] Some size in bytes.&lt;br /&gt;
|-&lt;br /&gt;
| Process || 18 || 0 || [3.0.0+] TitleId&lt;br /&gt;
|-&lt;br /&gt;
| Zero    || 19 || 0 || [4.0.0+] PrivilegedProcessId_LowerBound&lt;br /&gt;
|-&lt;br /&gt;
| Zero    || 19 || 1 || [4.0.0+] PrivilegedProcessId_UpperBound&lt;br /&gt;
|-&lt;br /&gt;
| Thread  || 0xF0000002 || 0 || Performance counter related.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== svcMapPhysicalMemory ==&lt;br /&gt;
This is like svcSetHeapSize except you can allocate heap at any address you&#039;d like.&lt;br /&gt;
&lt;br /&gt;
== svcDumpInfo ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) None || || &lt;br /&gt;
|-&lt;br /&gt;
| (Out) None || ||&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Does nothing, just returns with registers set to all-zero.&lt;br /&gt;
&lt;br /&gt;
== svcAcceptSession ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1 || Handle&amp;lt;Port&amp;gt; || Port&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Result&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || Handle&amp;lt;ServerSession&amp;gt; || Session&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Result codes ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;0xf201:&#039;&#039;&#039; No session waiting to be accepted&lt;br /&gt;
&lt;br /&gt;
== svcReplyAndReceive ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1 || *Handle&amp;lt;Port or ServerSession&amp;gt; || Handles&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || u32 || NumHandles&lt;br /&gt;
|-&lt;br /&gt;
| (In) W3 || Handle&amp;lt;ServerSession&amp;gt; || ReplyTarget&lt;br /&gt;
|-&lt;br /&gt;
| (In) X4 || u64 (nanoseconds) || Timeout&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Result&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || u32 || HandleIndex&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If ReplyTarget is not zero, a reply from the TLS will be sent to that session.&lt;br /&gt;
Then it will wait until either of the passed sessions has an incoming message, is closed, a passed port has an incoming connection, or the timeout expires.&lt;br /&gt;
If there is an incoming message, it is copied to the TLS.&lt;br /&gt;
&lt;br /&gt;
After being validated, passed handles will be enumerated in order; even if a session has been closed, if one that appears earlier in the list has an incoming message, it will take priority and a result code of 0x0 will be returned.&lt;br /&gt;
&lt;br /&gt;
=== Result codes ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;0x0:&#039;&#039;&#039; Success. Either a session has an incoming message or a port has an incoming connection. HandleIndex is set appropriately.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;0xea01:&#039;&#039;&#039; Timeout. No handles were signalled before the timeout expired. HandleIndex is not updated.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;0xf601:&#039;&#039;&#039; Port remote dead. One of the sessions has been closed. HandleIndex is set appropriately.&lt;br /&gt;
&lt;br /&gt;
== svcCreateJitMemory ==&lt;br /&gt;
Takes an address range with backing memory to create the JIT memory object.&lt;br /&gt;
&lt;br /&gt;
The memory is initially memset to 0xFF after being locked.&lt;br /&gt;
&lt;br /&gt;
== svcMapJitMemory ==&lt;br /&gt;
Maps the backing memory for a JIT memory object into the current process.&lt;br /&gt;
&lt;br /&gt;
For [[#MapJitOperation|MapJitOperation_MapOwner]], memory permission must be RW-.&lt;br /&gt;
&lt;br /&gt;
For [[#MapJitOperation|MapJitOperation_MapSlave]], memory permission must be R-- or R-X.&lt;br /&gt;
&lt;br /&gt;
Operations [[#MapJitOperation|MapJitOperation_UnmapOwner/MapJitOperation_UnmapSlave]] unmap memory that was previously mapped this way.&lt;br /&gt;
&lt;br /&gt;
This allows one &amp;quot;secure JIT&amp;quot; process to map the memory as RW-, and the other &amp;quot;slave&amp;quot; process to map it R-X.&lt;br /&gt;
&lt;br /&gt;
== svcReadWriteRegister ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || RegAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || u64 || RwMask&lt;br /&gt;
|-&lt;br /&gt;
| (In) W3 || u64 || InValue&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1|| u64 || OutValue&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Read/write IO registers with a hardcoded whitelist. Input address is physical-address and must be aligned to 4.&lt;br /&gt;
&lt;br /&gt;
rw_mask is 0 for reading and 0xffffffff for writing. You can also write individual bits by using a mask value.&lt;br /&gt;
&lt;br /&gt;
You can only write to registers inside physical pages 0x70019000 (MC), 0x7001C000 (MC0), 0x7001D000 (MC1), and they all share the same whitelist.&lt;br /&gt;
&lt;br /&gt;
The whitelist is same for writing as for reading.&lt;br /&gt;
&lt;br /&gt;
The whitelist is:&lt;br /&gt;
&lt;br /&gt;
0x054, 0x090, 0x094, 0x098, 0x09c, 0x0a0, 0x0a4, 0x0a8, 0x0ac, 0x0b0, 0x0b4, 0x0b8, 0x0bc, 0x0c0, 0x0c4, 0x0c8, 0x0d0, 0x0d4, 0x0d8, 0x0dc, 0x0e0, 0x100, 0x108, 0x10c, 0x118, 0x11c, 0x124, 0x128, 0x12c, 0x130, 0x134, 0x138, 0x13c, 0x158, 0x15c, 0x164, 0x168, 0x16c, 0x170, 0x174, 0x178, 0x17c, 0x200, 0x204, 0x2e4, 0x2e8, 0x2ec, 0x2f4, 0x2f8, 0x310, 0x314, 0x320, 0x328, 0x344, 0x348, 0x370, 0x374, 0x37c, 0x380, 0x390, 0x394, 0x398, 0x3ac, 0x3b8, 0x3bc, 0x3c0, 0x3c4, 0x3d8, 0x3e8, 0x41c, 0x420, 0x424, 0x428, 0x42c, 0x430, 0x44c, 0x47c, 0x480, 0x484, 0x50c, 0x554, 0x558, 0x55c, 0x670, 0x674, 0x690, 0x694, 0x698, 0x69c, 0x6a0, 0x6a4, 0x6c0, 0x6c4, 0x6f0, 0x6f4, 0x960, 0x970, 0x974, 0xa20, 0xa24, 0xb88, 0xb8c, 0xbc4, 0xbc8, 0xbcc, 0xbd0, 0xbd4, 0xbd8, 0xbdc, 0xbe0, 0xbe4, 0xbe8, 0xbec, 0xc00, 0xc5c, 0xcac&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[2.0.0+] Whitelist was extended with 0x4c4, 0x4c8, 0x4cc, 0x584, 0x588, 0x58c.&lt;br /&gt;
&lt;br /&gt;
[2.0.0+] The IO registers in range 0x7000E400 (PMC) size 0xC00 skip the whitelist, and do a TrustZone call using [[SMC]] Id1 0xC3000008(ReadWriteRegister).&lt;br /&gt;
&lt;br /&gt;
Here is the whitelist imposed by that SMC, relative to the start of the PMC registers:&lt;br /&gt;
&lt;br /&gt;
0x000, 0x00c, 0x010, 0x014, 0x01c, 0x020, 0x02c, 0x030, 0x034, 0x038, 0x03c, 0x040, 0x044, 0x048, 0x0dc, 0x0e0, 0x0e4, 0x160, 0x164, 0x168, 0x170, 0x1a8, 0x1b8, 0x1bc, 0x1c0, 0x1c4, 0x1c8, 0x2b4, 0x2d4, 0x440, 0x4d8&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== svcCreateSharedMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || [[#Permission]] || LocalPerm&lt;br /&gt;
|-&lt;br /&gt;
| (In) W3 || [[#Permission]] || RemotePerm&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || Handle&amp;lt;SharedMemory&amp;gt; || MemHandle&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other perm can be used to enforce permission 1, 3, or 0x10000000 if don&#039;t care.&lt;br /&gt;
&lt;br /&gt;
== svcMapTransferMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || Handle&amp;lt;TransferMemory&amp;gt; || MemHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || void* || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (In) W3 || [[#Permission]] || Permissions&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The newly mapped pages will have [[#MemoryState]] type 0xE.&lt;br /&gt;
&lt;br /&gt;
You must pass same size and permissions as given in svcCreateMemoryMirror, otherwise error.&lt;br /&gt;
&lt;br /&gt;
== svcUnmapTransferMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || Handle&amp;lt;TransferMemory&amp;gt; || MemHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || void* || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Size must match size given in map syscall, otherwise there&#039;s an invalid-size error.&lt;br /&gt;
&lt;br /&gt;
== svcQueryPhysicalAddress ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]]|| Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) X1 || u64 || PhysAddr&lt;br /&gt;
|-&lt;br /&gt;
| (Out) X2 || u64 || KernelAddr&lt;br /&gt;
|-&lt;br /&gt;
| (Out) X3 || u64 || Size&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== svcQueryIoMapping ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || PhysAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) X1 || void* || VirtAddr&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Returns a virtual address mapped to a given IO range.&lt;br /&gt;
&lt;br /&gt;
== svcCreateDeviceAddressSpace ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || StartAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || EndAddr&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || Handle&amp;lt;DeviceAddressSpace&amp;gt; || AddressSpaceHandle&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Creates a virtual address space for binding device address spaces and returns a handle.&lt;br /&gt;
&lt;br /&gt;
dev_as_start_addr is normally set to 0 and dev_as_end_addr is normally set to 0xFFFFFFFF.&lt;br /&gt;
&lt;br /&gt;
== svcAttachDeviceAddressSpace ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || [[#DeviceName]] || DeviceId&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || Handle&amp;lt;DeviceAddressSpace&amp;gt; || DeviceAsHandle&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Attaches a device address space to a [[#DeviceName|device]].&lt;br /&gt;
&lt;br /&gt;
== svcDetachDeviceAddressSpace ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || [[#DeviceName]] || DeviceId&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || Handle&amp;lt;DeviceAddressSpace&amp;gt; || DeviceAsHandle&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Detaches a device address space from a [[#DeviceName|device]].&lt;br /&gt;
&lt;br /&gt;
== svcMapDeviceAddressSpaceByForce ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;DeviceAddressSpace&amp;gt; || DeviceAsHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || void* || SrcAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || DeviceAsSize&lt;br /&gt;
|-&lt;br /&gt;
| (In) X4 || u64 || DeviceAsAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) W5 || [[#Permission]] || Permissions&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Maps an attached device address space to an userspace address.&lt;br /&gt;
&lt;br /&gt;
dev_map_addr is the userspace destination address, while dev_as_addr is the source address between dev_as_start_addr and dev_as_end_addr (passed to [[#svcCreateDeviceAddressSpace]]).&lt;br /&gt;
&lt;br /&gt;
The userspace destination address must have the [[SVC#MemoryState|MapDeviceAllowed]] bit set. Bit [[SVC#MemoryAttribute|IsDeviceMapped]] will be set after mapping.&lt;br /&gt;
&lt;br /&gt;
== svcMapDeviceAddressSpaceAligned ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;DeviceAddressSpace&amp;gt; || DeviceAsHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || void* || SrcAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || DeviceAsSize&lt;br /&gt;
|-&lt;br /&gt;
| (In) X4 || u64 || DeviceAsAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) W5 || [[#Permission]] || Permissions&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Maps an attached device address space to an userspace address.&lt;br /&gt;
&lt;br /&gt;
Same as [[#svcMapDeviceAddressSpaceByForce]], but the userspace destination address must have the [[SVC#MemoryState|MapDeviceAlignedAllowed]] bit set instead.&lt;br /&gt;
&lt;br /&gt;
== svcUnmapDeviceAddressSpace ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;DeviceAddressSpace&amp;gt; || DeviceAsHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || void* || SrcAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || DeviceAsSize&lt;br /&gt;
|-&lt;br /&gt;
| (In) X4 || u64 || DeviceAsAddr&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Description:&#039;&#039;&#039; Unmaps an attached device address space from an userspace address.&lt;br /&gt;
&lt;br /&gt;
== svcSetProcessMemoryPermission ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (In) W3 || void* || Perm&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This sets the memory permissions for the specified memory with the supplied process handle.&lt;br /&gt;
&lt;br /&gt;
This throws an error(0xD801) when the input perm is &amp;gt;0x5, hence -WX and RWX are not allowed.&lt;br /&gt;
&lt;br /&gt;
== svcMapProcessMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || u64 || SrcAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) W1 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || void* || DstAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Maps the src address from the supplied process handle into the current process.&lt;br /&gt;
&lt;br /&gt;
This allows mapping code and rodata with RW- permission.&lt;br /&gt;
&lt;br /&gt;
== svcUnmapProcessMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || void* || DstAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || SrcAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Unmaps what was mapped by [[#svcMapProcessMemory]].&lt;br /&gt;
&lt;br /&gt;
== svcQueryProcessMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X0 || [[#MemoryInfo]]* || MemInfoPtr&lt;br /&gt;
|-&lt;br /&gt;
| (In) W2 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || Addr&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || PageInfo || PageInfo&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Equivalent to [[#svcQueryMemory]] except takes a process handle.&lt;br /&gt;
&lt;br /&gt;
== svcMapProcessCodeMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || DstAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || SrcAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Takes a process handle, and maps normal heap in that process as executable code in that process. Used when loading NROs. This does not support using the current-process handle alias.&lt;br /&gt;
&lt;br /&gt;
== svcUnmapProcessCodeMemory ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || u64 || DstAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || SrcAddr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || Size&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Unmaps what was mapped by [[#svcMapProcessCodeMemory]].&lt;br /&gt;
&lt;br /&gt;
== svcCreateProcess ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) X1 || [[#CreateProcessInfo]]* || InfoPtr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X2 || u64 || CapabilitiesPtr&lt;br /&gt;
|-&lt;br /&gt;
| (In) X3 || u64 || CapabilitiesNum&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Takes a [[#CreateProcessInfo]] as input.&lt;br /&gt;
&lt;br /&gt;
== svcGetProcessInfo ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display: inline-block;&amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument || Type || Name&lt;br /&gt;
|-&lt;br /&gt;
| (In) W0 || Handle&amp;lt;Process&amp;gt; || ProcessHandle&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W0 || [[#Result]] || Ret&lt;br /&gt;
|-&lt;br /&gt;
| (Out) W1 || [[#ProcessState]] || State&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Returns an enum with value 0-7.&lt;br /&gt;
&lt;br /&gt;
== Debugging ==&lt;br /&gt;
[2.0.0+] Exactly 6 debug SVCs require that [[SPL_services#GetConfig|IsDebugMode]] is non-zero. Error 0x4201 is returned otherwise.&lt;br /&gt;
* svcBreakDebugProcess&lt;br /&gt;
* svcContinueDebugEvent&lt;br /&gt;
* svcWriteDebugProcessMemory&lt;br /&gt;
* svcSetDebugThreadContext&lt;br /&gt;
* svcTerminateDebugProcess&lt;br /&gt;
* svcSetHardwareBreakPoint&lt;br /&gt;
&lt;br /&gt;
svcDebugActiveProcess stops execution of the target process, the normal method for resuming it requires svcContinueDebugEvent(see above). Closing the debug handle also results in execution being resumed.&lt;br /&gt;
&lt;br /&gt;
= Enum/Structures =&lt;br /&gt;
== ThreadContextRequestFlags ==&lt;br /&gt;
Bitfield of one of more of these:&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Bit || Bitmask || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 1 || NormalContext&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 4 ||&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 8 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== DeviceName ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || DeviceName_AFI&lt;br /&gt;
|-&lt;br /&gt;
| 1 || DeviceName_AVPC&lt;br /&gt;
|-&lt;br /&gt;
| 2 || DeviceName_DC&lt;br /&gt;
|-&lt;br /&gt;
| 3 || DeviceName_DCB&lt;br /&gt;
|-&lt;br /&gt;
| 4 || DeviceName_HC&lt;br /&gt;
|-&lt;br /&gt;
| 5 || DeviceName_HDA&lt;br /&gt;
|-&lt;br /&gt;
| 6 || DeviceName_ISP2&lt;br /&gt;
|-&lt;br /&gt;
| 7 || DeviceName_MSENCNVENC&lt;br /&gt;
|-&lt;br /&gt;
| 8 || DeviceName_NV&lt;br /&gt;
|-&lt;br /&gt;
| 9 || DeviceName_NV2&lt;br /&gt;
|-&lt;br /&gt;
| 10 || DeviceName_PPCS&lt;br /&gt;
|-&lt;br /&gt;
| 11 || DeviceName_SATA&lt;br /&gt;
|-&lt;br /&gt;
| 12 || DeviceName_VI&lt;br /&gt;
|-&lt;br /&gt;
| 13 || DeviceName_VIC&lt;br /&gt;
|-&lt;br /&gt;
| 14 || DeviceName_XUSB_HOST&lt;br /&gt;
|-&lt;br /&gt;
| 15 || DeviceName_XUSB_DEV&lt;br /&gt;
|-&lt;br /&gt;
| 16 || DeviceName_TSEC&lt;br /&gt;
|-&lt;br /&gt;
| 17 || DeviceName_PPCS1&lt;br /&gt;
|-&lt;br /&gt;
| 18 || DeviceName_DC1&lt;br /&gt;
|-&lt;br /&gt;
| 19 || DeviceName_SDMMC1A&lt;br /&gt;
|-&lt;br /&gt;
| 20 || DeviceName_SDMMC2A&lt;br /&gt;
|-&lt;br /&gt;
| 21 || DeviceName_SDMMC3A&lt;br /&gt;
|-&lt;br /&gt;
| 22 || DeviceName_SDMMC4A&lt;br /&gt;
|-&lt;br /&gt;
| 23 || DeviceName_ISP2B&lt;br /&gt;
|-&lt;br /&gt;
| 24 || DeviceName_GPU&lt;br /&gt;
|-&lt;br /&gt;
| 25 || DeviceName_GPUB&lt;br /&gt;
|-&lt;br /&gt;
| 26 || DeviceName_PPCS2&lt;br /&gt;
|-&lt;br /&gt;
| 27 || DeviceName_NVDEC&lt;br /&gt;
|-&lt;br /&gt;
| 28 || DeviceName_APE&lt;br /&gt;
|-&lt;br /&gt;
| 29 || DeviceName_SE&lt;br /&gt;
|-&lt;br /&gt;
| 30 || DeviceName_NVJPG&lt;br /&gt;
|-&lt;br /&gt;
| 31 || DeviceName_HC1&lt;br /&gt;
|-&lt;br /&gt;
| 32 || DeviceName_SE1&lt;br /&gt;
|-&lt;br /&gt;
| 33 || DeviceName_AXIAP&lt;br /&gt;
|-&lt;br /&gt;
| 34 || DeviceName_ETR&lt;br /&gt;
|-&lt;br /&gt;
| 35 || DeviceName_TSECB&lt;br /&gt;
|-&lt;br /&gt;
| 36 || DeviceName_TSEC1&lt;br /&gt;
|-&lt;br /&gt;
| 37 || DeviceName_TSECB1&lt;br /&gt;
|-&lt;br /&gt;
| 38 || DeviceName_NVDEC1&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== MapJitOperation ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || MapJitOperation_MapOwner&lt;br /&gt;
|-&lt;br /&gt;
| 1 || MapJitOperation_MapSlave&lt;br /&gt;
|-&lt;br /&gt;
| 2 || MapJitOperation_UnmapOwner&lt;br /&gt;
|-&lt;br /&gt;
| 3 || MapJitOperation_UnmapSlave&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== LimitableResource ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || LimitableResource_Memory&lt;br /&gt;
|-&lt;br /&gt;
| 1 || LimitableResource_Threads&lt;br /&gt;
|-&lt;br /&gt;
| 2 || LimitableResource_Events&lt;br /&gt;
|-&lt;br /&gt;
| 3 || LimitableResource_TransferMemories&lt;br /&gt;
|-&lt;br /&gt;
| 4 || LimitableResource_Sessions&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== ProcessEvent ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || ProcessEvent_Created&lt;br /&gt;
|-&lt;br /&gt;
| 1 || ProcessEvent_DebugAttached&lt;br /&gt;
|-&lt;br /&gt;
| 2 || ProcessEvent_DebugDetached&lt;br /&gt;
|-&lt;br /&gt;
| 3 || ProcessEvent_Crashed&lt;br /&gt;
|-&lt;br /&gt;
| 4 || ProcessEvent_Running&lt;br /&gt;
|-&lt;br /&gt;
| 5 || ProcessEvent_Exiting&lt;br /&gt;
|-&lt;br /&gt;
| 6 || ProcessEvent_Exited&lt;br /&gt;
|-&lt;br /&gt;
| 7 || ProcessEvent_DebugSuspended&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== DebugThreadParam ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || DebugThreadParam_ActualPriority&lt;br /&gt;
|-&lt;br /&gt;
| 1 ||&lt;br /&gt;
|-&lt;br /&gt;
| 2 || DebugThreadParam_CpuCore&lt;br /&gt;
|-&lt;br /&gt;
| 3 ||&lt;br /&gt;
|-&lt;br /&gt;
| 4 || DebugThreadParam_CoreMask&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== CreateProcessInfo ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Bits || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 12 || || ProcessName (doesn&#039;t have to be null-terminated)&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 8 || || TitleId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 8 || || CodeAddr&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 4 || || CodeNumPages&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 4 || || MmuFlags&lt;br /&gt;
|-&lt;br /&gt;
| || || Bit0 || Is64bit&lt;br /&gt;
|-&lt;br /&gt;
| || || Bit3-1 || [[#AddressSpaceType]]&lt;br /&gt;
|-&lt;br /&gt;
| || || Bit4 ||&lt;br /&gt;
|-&lt;br /&gt;
| || || Bit5 || EnableAslr&lt;br /&gt;
|-&lt;br /&gt;
| || || Bit6 || IsSystem&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || 4 || || ResourceLimitHandle&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C || 4 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== AddressSpaceType ===&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Type || Name || Width || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Normal_32Bit || 32 ||&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Normal_36Bit || 36 ||&lt;br /&gt;
|-&lt;br /&gt;
| 2 || WithoutMap_32Bit || 32 || Appears to be missing map region [?]&lt;br /&gt;
|-&lt;br /&gt;
| 3 || [2.0.0+] Normal_39Bit || 39 ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== MemoryInfo ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 8 || BaseAddress&lt;br /&gt;
|-&lt;br /&gt;
| 8 || 8 || Size&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || 4 || MemoryType: lower 8 bits of [[#MemoryState]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x14 || 4 || [[#MemoryAttribute]]&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || 4 || Permission (bit0: R, bit1: W, bit2: X)&lt;br /&gt;
|-&lt;br /&gt;
| 0x1C || 4 || IpcRefCount&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || 4 || DeviceRefCount&lt;br /&gt;
|-&lt;br /&gt;
| 0x24 || 4 || Padding: always zero&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== MemoryAttribute ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Bits || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || IsBorrowed&lt;br /&gt;
|-&lt;br /&gt;
| 1 || IsIpcMapped: when IpcRefCount &amp;gt; 0.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || IsDeviceMapped: when DeviceRefCount &amp;gt; 0.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || IsUncached&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== MemoryState ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Bits || Description&lt;br /&gt;
|-&lt;br /&gt;
| 7-0 || Type&lt;br /&gt;
|-&lt;br /&gt;
| 8 || [[#svcSetMemoryPermission|PermissionChangeAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 9 || ForceReadWritableByDebugSyscalls&lt;br /&gt;
|-&lt;br /&gt;
| 10 || IpcSendAllowed_Type0&lt;br /&gt;
|-&lt;br /&gt;
| 11 || IpcSendAllowed_Type3&lt;br /&gt;
|-&lt;br /&gt;
| 12 || IpcSendAllowed_Type1&lt;br /&gt;
|-&lt;br /&gt;
| 14 || [[#svcSetProcessMemoryPermission|ProcessPermissionChangeAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 15 || [[#svcMapMemory|MapAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 16 || [[#svcUnmapProcessCodeMemory|UnmapProcessCodeMemoryAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 17 || [[#svcCreateTransferMemory|TransferMemoryAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 18 || [[#svcQueryPhysicalAddress|QueryPhysicalAddressAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 19 || MapDeviceAllowed ([[#svcMapDeviceAddressSpace]] and [[#svcMapDeviceAddressSpaceByForce]])&lt;br /&gt;
|-&lt;br /&gt;
| 20 || [[#svcMapDeviceAddressSpaceAligned|MapDeviceAlignedAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 21 || [[#svcSendSyncRequestWithUserBuffer|IpcBufferAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 22 || IsPoolAllocated/IsReferenceCounted&lt;br /&gt;
|-&lt;br /&gt;
| 23 || [[#svcMapProcessMemory|MapProcessAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 24 || [[#svcSetMemoryAttribute|AttributeChangeAllowed]]&lt;br /&gt;
|-&lt;br /&gt;
| 25 || [4.0.0+] JitMemoryAllowed&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Type || Meaning&lt;br /&gt;
|-&lt;br /&gt;
| 0x00000000 || MemoryType_Unmapped ||&lt;br /&gt;
|-&lt;br /&gt;
| 0x00002001 || MemoryType_Io || Mapped by kernel capability parsing in [[#svcCreateProcess]]. &lt;br /&gt;
|-&lt;br /&gt;
| 0x00042002 || MemoryType_Normal || Mapped by kernel capability parsing in [[#svcCreateProcess]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x00DC7E03 || MemoryType_CodeStatic || Mapped during [[#svcCreateProcess]].&lt;br /&gt;
|-&lt;br /&gt;
| [1.0.0+]&lt;br /&gt;
&lt;br /&gt;
0x01FEBD04&lt;br /&gt;
&lt;br /&gt;
[4.0.0+]&lt;br /&gt;
&lt;br /&gt;
0x03FEBD04&lt;br /&gt;
|| MemoryType_CodeMutable || Transition from 0xDC7E03 performed by [[#svcSetProcessMemoryPermission]].&lt;br /&gt;
|-&lt;br /&gt;
| [1.0.0+]&lt;br /&gt;
0x017EBD05&lt;br /&gt;
&lt;br /&gt;
[4.0.0+]&lt;br /&gt;
&lt;br /&gt;
0x037EBD05&lt;br /&gt;
|| MemoryType_Heap || Mapped using [[#svcSetHeapSize]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x00402006 || MemoryType_SharedMemory || Mapped using [[#svcMapSharedMemory]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x00482907 || [1.0.0] MemoryType_WeirdSharedMemory || Mapped using [[#svcMapMemory]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x00DD7E08 || MemoryType_ModuleCodeStatic || Mapped using [[#svcMapProcessCodeMemory]].&lt;br /&gt;
|-&lt;br /&gt;
| [1.0.0+]&lt;br /&gt;
&lt;br /&gt;
0x01FFBD09&lt;br /&gt;
&lt;br /&gt;
[4.0.0+]&lt;br /&gt;
&lt;br /&gt;
0x03FFBD09&lt;br /&gt;
|| MemoryType_ModuleCodeMutable || Transition from 0xDD7E08 performed by [[#svcSetProcessMemoryPermission]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x005C3C0A || [[IPC_Marshalling|MemoryType_IpcBuffer0]] || IPC buffers with descriptor flags=0.&lt;br /&gt;
|-&lt;br /&gt;
| 0x005C3C0B || MemoryType_MappedMemory || Mapped using [[#svcMapMemory]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x0040200C || [[Thread Local Storage|MemoryType_ThreadLocal]] || Mapped during [[#svcCreateThread]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x015C3C0D || MemoryType_TransferMemoryIsolated || Mapped using [[#svcMapTransferMemory]] when the owning process has perm=0.&lt;br /&gt;
|-&lt;br /&gt;
| 0x005C380E || MemoryType_TransferMemory || Mapped using [[#svcMapTransferMemory]] when the owning process has perm!=0.&lt;br /&gt;
|-&lt;br /&gt;
| 0x0040380F || MemoryType_ProcessMemory || Mapped using [[#svcMapProcessMemory]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x00000010 || MemoryType_Reserved ||&lt;br /&gt;
|-&lt;br /&gt;
| 0x005C3811 || [[IPC_Marshalling|MemoryType_IpcBuffer1]] || IPC buffers with descriptor flags=1.&lt;br /&gt;
|-&lt;br /&gt;
| 0x004C2812 || [[IPC_Marshalling|MemoryType_IpcBuffer3]] || IPC buffers with descriptor flags=3.&lt;br /&gt;
|-&lt;br /&gt;
| 0x00002013 || MemoryType_KernelStack || Mapped in kernel during [[#svcCreateThread]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x00402214 || [4.0.0+] MemoryType_JitReadOnly || Mapped in kernel during [[#svcMapJitMemory]].&lt;br /&gt;
|-&lt;br /&gt;
| 0x00402015 || [4.0.0+] MemoryType_JitWritable || Mapped in kernel during [[#svcMapJitMemory]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== ContinueDebugFlags ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Bit || Bitmask || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 1 || SwallowException&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 2 ||&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 4 || ResumeAllThreads&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== DebugEventInfo ==&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || u32 || EventType&lt;br /&gt;
|-&lt;br /&gt;
| 4 || u32 || Flags (bit0: NeedsContinue)&lt;br /&gt;
|-&lt;br /&gt;
| 8 || u64 || ThreadId&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || || PerTypeSpecifics&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
AttachProcess specific:&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || u64 || TitleId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || u64 || ProcessId&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || char[12] || ProcessName&lt;br /&gt;
|-&lt;br /&gt;
| 0x2C || u32 || MmuFlags&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
AttachThread specific:&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || u64 || ThreadId&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || u64 || TlsPtr&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || u64 || Entrypoint&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Exit specific:&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || u64 || Type (0=PausedThread, 1=RunningThread, 2=TerminatedProcess)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Exception specific:&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x10 || u64 || ExceptionType&lt;br /&gt;
|-&lt;br /&gt;
| 0x18 || u64 || FaultRegister&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || || PerExceptionSpecifics&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== DebugEventType ===&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || DebugEvent_AttachProcess&lt;br /&gt;
|-&lt;br /&gt;
| 1 || DebugEvent_AttachThread&lt;br /&gt;
|-&lt;br /&gt;
| 2 ||&lt;br /&gt;
|-&lt;br /&gt;
| 3 || DebugEvent_Exit&lt;br /&gt;
|-&lt;br /&gt;
| 4 || DebugEvent_Exception&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== DebugExceptionType ===&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Value || Name&lt;br /&gt;
|-&lt;br /&gt;
| 0 || Exception_UndefinedInstruction&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Exception_InstructionAbort&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Exception_DataAbortMisc&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Exception_PcSpAlignmentFault&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Exception_DebuggerAttached&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Exception_BreakPoint&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Exception_UserBreak&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Exception_DebuggerBreak&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Exception_BadSvcId&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
UndefinedInstruction specifics:&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || u32 || Opcode&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
BreakPoint specifics:&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || u32 || IsWatchpoint&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
UserBreak specifics:&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || u32 || Info0&lt;br /&gt;
|-&lt;br /&gt;
| 0x28 || u64 || Info1&lt;br /&gt;
|-&lt;br /&gt;
| 0x30 || u64 || Info2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
BadSvcId specifics:&lt;br /&gt;
{| class=wikitable&lt;br /&gt;
! Offset || Length || Description&lt;br /&gt;
|-&lt;br /&gt;
| 0x20 || u32 || SvcId&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Exception handling =&lt;br /&gt;
There is userland code for handling exceptions, however this doesn&#039;t seem to be executed on retail mode.&lt;br /&gt;
&lt;br /&gt;
When a usermode exception occurs, it jumps to the main code binary entrypoint (main_binary_address + 0 == &#039;&#039;&#039;_start&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
During normal boot &#039;&#039;&#039;_start&#039;&#039;&#039; is invoked with X0=0 and X1=main_thread_handle (triggering normal crt0 setup).&lt;br /&gt;
During an usermode exception &#039;&#039;&#039;_start&#039;&#039;&#039; is invoked with X0=exception_info0_ptr and X1=exception_info1_ptr instead.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;_start&#039;&#039;&#039; method determines whether to boot normally or handle an exception if X0 is set to 0 or not.&lt;/div&gt;</summary>
		<author><name>Gdkchan</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=Switch_System_Flaws&amp;diff=3464</id>
		<title>Switch System Flaws</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=Switch_System_Flaws&amp;diff=3464"/>
		<updated>2018-01-18T12:49:09Z</updated>

		<summary type="html">&lt;p&gt;Gdkchan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
System Flaws are used to execute unofficial code (homebrew) on the Nintendo Switch. This page is a list of known and public Switch System Flaws.&lt;br /&gt;
&lt;br /&gt;
=List of Switch System Flaws=&lt;br /&gt;
&lt;br /&gt;
== Hardware == &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
!  Summary&lt;br /&gt;
!  Description&lt;br /&gt;
!  Fixed with hardware model/revision&lt;br /&gt;
!  Newest hardware model/revision this flaw was checked for&lt;br /&gt;
!  Timeframe this was discovered&lt;br /&gt;
!  Public disclosure timeframe&lt;br /&gt;
!  Discovered by&lt;br /&gt;
|-&lt;br /&gt;
| GMMU DMA attack&lt;br /&gt;
| The Switch&#039;s GPU includes a separate MMU (GMMU) that is allowed to bypass the system&#039;s IOMMU (SMMU). By accessing the GPU&#039;s MMIO region and manipulating the page table entries in the GMMU, an attacker can read/write any portion of the DRAM (except memory carveouts).&lt;br /&gt;
| None&lt;br /&gt;
| HAC-001&lt;br /&gt;
| Summer 2017&lt;br /&gt;
| December 28, 2017&lt;br /&gt;
| [[User:hexkyz|hexkyz]], [[User:SciresM|SciresM]] and [[User:qlutoo|qlutoo]]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== System software ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Stage 1 Bootloader ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Summary&lt;br /&gt;
!  Description&lt;br /&gt;
!  Successful exploitation result&lt;br /&gt;
!  Fixed in system version&lt;br /&gt;
!  Last system version this flaw was checked for&lt;br /&gt;
!  Timeframe this was discovered&lt;br /&gt;
!  Public disclosure timeframe&lt;br /&gt;
!  Discovered by&lt;br /&gt;
|-&lt;br /&gt;
|  Null-dereference in panic()&lt;br /&gt;
|  The Switch&#039;s stage 1 bootloader, on panic(), clears the stack and then attempts to clear the Security Engine. However, it does so by dereferencing a pointer to the SE in .bss (initially NULL), and this pointer doesn&#039;t get initialized until partway into the bootloader&#039;s main() after several functions that might panic() are called. Thus, a panic() caused prior to SE initialization would result in the SE pointer still being NULL when dereferenced. This would cause a data abort, causing the bootloader to clear the stack and then try to clear the security engine...dereferencing NULL again, over and over in a loop.&lt;br /&gt;
&lt;br /&gt;
In 3.0.0, this was fixed by moving the security engine initialization earlier in main(), before the first function that could potentially panic().&lt;br /&gt;
|  Infinite clear-the-stack-then-data-abort loop very early in boot, before SBK/other keyslots are cleared. Probably useless for anything more interesting.&lt;br /&gt;
|  [[3.0.0]]&lt;br /&gt;
|  [[3.0.0]]&lt;br /&gt;
|  Early July, 2017&lt;br /&gt;
|  July 30, 2017&lt;br /&gt;
|  Everyone who diff&#039;d 2.3.0 and 3.0.0 Package1&lt;br /&gt;
|-&lt;br /&gt;
|  FUSE_DIS_PGM not written by package1 &lt;br /&gt;
|  The switch&#039;s hardware fuse driver contains a write-once bit in a register called &amp;quot;FUSE_DIS_PGM&amp;quot;, which disables burning fuses until the next reboot. While Nintendo&#039;s bootloader code for waking up from sleep writes this on all firmware, the actual package1 initial bootloader forgets to write to it on cold reboot. &lt;br /&gt;
&lt;br /&gt;
This isn&#039;t too big of a problem because another fuse is burnt on retail devices (production mode), which prevents burning *all* fuses other than ODM_RESERVED ones in hardware.&lt;br /&gt;
&lt;br /&gt;
This was fixed in 3.0.0 by writing to the register on cold boot (although the write happens in TZ instead of package1 where it should take place, possibly to obfuscate the fact that they made this mistake).&lt;br /&gt;
|  Burning arbitrary ODM reserved fuses with TZ code execution, which should never be possible for non-bootloader code.&lt;br /&gt;
&lt;br /&gt;
Warning: one could irreparably brick one&#039;s console by playing with this.&lt;br /&gt;
|  [[3.0.0]]&lt;br /&gt;
|  [[3.0.0]]&lt;br /&gt;
|  late summer/early fall 2017&lt;br /&gt;
|  December 31, 2017&lt;br /&gt;
|  SciresM, Motezazer&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== TrustZone ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Summary&lt;br /&gt;
!  Description&lt;br /&gt;
!  Successful exploitation result&lt;br /&gt;
!  Fixed in system version&lt;br /&gt;
!  Last system version this flaw was checked for&lt;br /&gt;
!  Timeframe this was discovered&lt;br /&gt;
!  Public disclosure timeframe&lt;br /&gt;
!  Discovered by&lt;br /&gt;
|-&lt;br /&gt;
|  Non-atomic mutexes&lt;br /&gt;
|  When an [[SMC]] is called, TrustZone sets a global variable to mark that an SMC is in progress, so that two SMCs using shared resources (like the security engine) do not trample on one another. On 1.0.0, this global variable was written using non-atomic writes, and thus a race condition is possible.&lt;br /&gt;
&lt;br /&gt;
However, the SMC handler enforces that all SMCs must be called from core #3, unless the top-level handler ID is 1 (SMCs internal to the kernel). Thus, the only SMCs that can be run side-by-side are [any userland smc] and smcGetRandomBytesForKernel, and this turns out to not really be abusable.&lt;br /&gt;
| Mostly useless. Maybe some oob-write into unused (and thus useless) memory if running smcGetRandomBytesForKernel and smcGetRandomBytesForUser at the same time.&lt;br /&gt;
| [[2.0.0]]&lt;br /&gt;
| [[2.0.0]]&lt;br /&gt;
| December 2017 (Probably earlier by others)&lt;br /&gt;
| January 18, 2018&lt;br /&gt;
| SciresM, probably others.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Kernel ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Summary&lt;br /&gt;
!  Description&lt;br /&gt;
!  Successful exploitation result&lt;br /&gt;
!  Fixed in system version&lt;br /&gt;
!  Last system version this flaw was checked for&lt;br /&gt;
!  Timeframe this was discovered&lt;br /&gt;
!  Public disclosure timeframe&lt;br /&gt;
!  Discovered by&lt;br /&gt;
|-&lt;br /&gt;
| Syscall Infoleaks&lt;br /&gt;
| Many syscalls leaked kernel pointers on sad paths (for example svcSetHeapSize and svcQueryMemory), until they landed a bunch of fixes in 2.0.0.&lt;br /&gt;
| Nothing really.&lt;br /&gt;
| Unfixed&lt;br /&gt;
| 2.0.0&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| GetLastThreadInfo UAF&lt;br /&gt;
| GetLastThreadInfo syscall gets last-scheduled-KThread pointer from KScheduler object. This pointer is not reference counted, and can be pointing to a freed KThread.&lt;br /&gt;
| Nothing. There is a theoretical race that might leak from a KThread from a different process, but it&#039;s impossible to trigger practically.&lt;br /&gt;
| Unfixed&lt;br /&gt;
| &lt;br /&gt;
| 15 October&lt;br /&gt;
| 17 October&lt;br /&gt;
| [[User:qlutoo|qlutoo]]&lt;br /&gt;
|-&lt;br /&gt;
| Bad irq_id check in CreateInterruptEvent&lt;br /&gt;
| CreateInterruptEvent syscall is designed to work only for irq_id &amp;gt;= 32. All irq_ids &amp;lt; 32 are &amp;quot;per-core&amp;quot; and reserved for kernel use (watchdog/scheduling/core communications).&lt;br /&gt;
On 1.0.0 you could supply irq_id &amp;lt; 32 and it would write outside the SharedIrqs table.&lt;br /&gt;
| You can register irq&#039;s in the Core3Irqs table, and thus register per-core irqs for core3, that are normally reserved for kernel. Useless.&lt;br /&gt;
| 2.0.0&lt;br /&gt;
| 2.0.0&lt;br /&gt;
| ~October&lt;br /&gt;
| 17 October&lt;br /&gt;
| [[User:qlutoo|qlutoo]]&lt;br /&gt;
|-&lt;br /&gt;
| Kernel .text mapped executable in usermode&lt;br /&gt;
| Prior to [[3.0.2]] the kernel .text was [[Memory_layout|mapped]] in usermode as executable. This can be used for usermode ROP for bypassing ASLR, but SVCs/IPC are not usable by running kernel .text in usermode.&lt;br /&gt;
| Executing kernel .text in usermode&lt;br /&gt;
| [[3.0.2]]&lt;br /&gt;
| [[3.0.2]]&lt;br /&gt;
| &lt;br /&gt;
| 34c3 (December 28, 2017)&lt;br /&gt;
| [[User:qlutoo|qlutoo]]&lt;br /&gt;
|-&lt;br /&gt;
| Memory Controller not properly secured&lt;br /&gt;
| The Switch OS originally had the memory controller not set to be accessible only by the secure-world, which was problematic because insecure access can compromise the kernel.&lt;br /&gt;
&lt;br /&gt;
This was fixed partially in [[2.0.0]] by blacklisting the memory controller from being mapped by user-processes, and was fixed entirely in [[4.0.0]] by making the memory controller TZ-only and making all kernel accesses go through [[SMC|smcReadWriteRegister]].&lt;br /&gt;
| With some way to access the memory controller MMIO, arbitrary kernel code execution.&lt;br /&gt;
| [[4.0.0]]&lt;br /&gt;
| [[4.0.0]]&lt;br /&gt;
| January 2018&lt;br /&gt;
| January 2018&lt;br /&gt;
| SciresM, yellows8&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== FIRM-package System Modules ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Summary&lt;br /&gt;
!  Description&lt;br /&gt;
!  Successful exploitation result&lt;br /&gt;
!  Fixed in system version&lt;br /&gt;
!  Last system version this flaw was checked for&lt;br /&gt;
!  Timeframe this was discovered&lt;br /&gt;
!  Public disclosure timeframe&lt;br /&gt;
!  Discovered by&lt;br /&gt;
|-&lt;br /&gt;
| Service access control bypass (sm:h, smhax, probably other names)&lt;br /&gt;
| Prior to [[3.0.1]], the &#039;&#039;service manager&#039;&#039; (sm) built-in system module treats a user as though it has full permissions if the user creates a new &amp;quot;sm:&amp;quot; port session but bypasses [[Services_API#Initialize|initialization]]. This is due to the other sm commands skipping the service ACL check for Pids &amp;lt;= 7 (i.e. all kernel bundled modules) and that skipping the initialization command leaves the Pid field uninitialized.&lt;br /&gt;
In [[3.0.1]], sm returns error code 0x415 if [[Services_API#Initialize|Initialize]] has not been called yet.&lt;br /&gt;
| Acquiring, registering, and unregistering arbitrary services&lt;br /&gt;
| [[3.0.1]]&lt;br /&gt;
| [[3.0.1]]&lt;br /&gt;
| May 2017&lt;br /&gt;
| August 17, 2017&lt;br /&gt;
| Everyone&lt;br /&gt;
|-&lt;br /&gt;
| Overly permissive SPL service&lt;br /&gt;
| The concept behind the switch&#039;s [[SMC|Secure Monitor]] is that all cryptographic keydata is located in userspace, but stored as &amp;quot;access keys&amp;quot; encrypted with &amp;quot;keks&amp;quot; that never leave TrustZone. The [[SPL services|spl]] (&amp;quot;security processor liaison&amp;quot;?) service serves as an interface between the rest of the system and the secure monitor. Prior to [[4.0.0]], spl exposed only a single service &amp;quot;spl:&amp;quot;, which provided all TrustZone wrapper functions to all sysmodules with access to it. Thus anyone with access to the spl: service (via smhax or by pwning a sysmodule with access) could do crypto with any access keys they knew. &lt;br /&gt;
&lt;br /&gt;
This was fixed in [[4.0.0]] by splitting spl: into spl:, spl:mig, spl:ssl, spl:es, and spl:fs.&lt;br /&gt;
| Arbitrary spl: crypto with any access keys one knows. For example, one could use the SSL module&#039;s access keys to decrypt their console&#039;s SSL certificate private key without having to pwn the SSL sysmodule.&lt;br /&gt;
| [[4.0.0]]&lt;br /&gt;
| [[4.0.0]]&lt;br /&gt;
| Summer 2017 (after smhax was discovered).&lt;br /&gt;
| December 23, 2017&lt;br /&gt;
| Everyone&lt;br /&gt;
|-&lt;br /&gt;
| Single session services not really single session&lt;br /&gt;
| Several &amp;quot;critical&amp;quot; services (like fsp-ldr, fsp-pr, sm:m, etc) are meant to only ever hold a single session with a specific sysmodule. However, when a sysmodule dies, all its service session handles are released -- and thus killing the holder of a single session handle would allow one (via sm:hax etc) to get access to that service. &lt;br /&gt;
&lt;br /&gt;
This was fixed in [[4.0.0]] by adding a semaphore to these critical single-session services, so that even if one gets access to them an error code will be returned when attempting to use any of their commands.&lt;br /&gt;
| With some way to access these services and kill their session holders: dumping sysmodule code, arbitrary service access, elevated filesystem permissions, etc.&lt;br /&gt;
| [[4.0.0]]&lt;br /&gt;
| [[4.0.0]]&lt;br /&gt;
| May/June 2017 (basically immediately after smhax was discovered)&lt;br /&gt;
| December 30, 2017&lt;br /&gt;
| Everyone&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== System Modules ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Summary&lt;br /&gt;
!  Description&lt;br /&gt;
!  Successful exploitation result&lt;br /&gt;
!  Fixed in system version&lt;br /&gt;
!  Last system version this flaw was checked for&lt;br /&gt;
!  Timeframe this was discovered&lt;br /&gt;
!  Public disclosure timeframe&lt;br /&gt;
!  Discovered by&lt;br /&gt;
|-&lt;br /&gt;
| Out-of-bounds array read for [[BCAT_Content_Container]] secret-data index&lt;br /&gt;
| The [[BCAT_Content_Container]] secret-data index is not validated at all. This is handled before the RSA-signature(?) is ever used. Since the field is an u8, a total of 0x800-bytes relative to the array start can be accessed.&lt;br /&gt;
This is not useful since the string loaded from this array is only involved with key-generation.&lt;br /&gt;
| &lt;br /&gt;
| Unknown&lt;br /&gt;
| [[2.0.0]]&lt;br /&gt;
| August 4, 2017&lt;br /&gt;
| August 6, 2017&lt;br /&gt;
| [[User: shinyquagsire23|Shiny Quagsire]], [[User:Yellows8|Yellows8]] (independently)&lt;br /&gt;
|-&lt;br /&gt;
|  OOB Read in NS system module (pl:utoohax, pl:utonium, maybe other names)&lt;br /&gt;
|  Prior to [[3.0.0]], pl:u (Shared Font services implemented in the NS sysmodule) service commands 1,2,3 took in a signed 32-bit index and returned that index of an array but did not check that index at all. This allowed for an arbitrary read within a 34-bit range (33-bit signed) from NS .bss. In [[3.0.0]], sending out of range indexes causes error code 0x60A to be returned.&lt;br /&gt;
|  Dumping full NS .text, .rodata and .data, infoleak, etc&lt;br /&gt;
|  [[3.0.0]]&lt;br /&gt;
|  [[3.0.0]]&lt;br /&gt;
|  April 2017&lt;br /&gt;
|  On exploit&#039;s fix in [[3.0.0]]&lt;br /&gt;
|  [[User:qlutoo|qlutoo]], Reswitched team (independently)&lt;br /&gt;
|-&lt;br /&gt;
| Unchecked domain ID in common IPC code&lt;br /&gt;
| Prior to [[2.0.0]], object IDs in [[IPC_Marshalling#Domain_message|domain messages]] are not bounds checked. This out-of-bounds read could be exploited to brute-force ASLR and get PC control in some services that support domain messages.&lt;br /&gt;
|&lt;br /&gt;
| 2.0.0&lt;br /&gt;
| 2.0.0&lt;br /&gt;
| ~July 2017&lt;br /&gt;
| 20 July 2017‎&lt;br /&gt;
| [[User:hthh|hthh]]&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Gdkchan</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=GPU&amp;diff=3430</id>
		<title>GPU</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=GPU&amp;diff=3430"/>
		<updated>2018-01-15T00:37:23Z</updated>

		<summary type="html">&lt;p&gt;Gdkchan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Mapping Memory==&lt;br /&gt;
&lt;br /&gt;
First, to map a memory region on the GPU Address Space, caching needs to be disabled by using [[SVC#svcSetMemoryAttribute|svcSetMemoryAttribute]]. The Address passed is the Virtual Address of the region that will be mapped, the size is the region size, and State0/1 are both set to 8 to disable caching of the memory region. This is done to ensure that the GPU can actually &amp;quot;see&amp;quot; the data written there, and it doesn&#039;t get stuck on some cache.&lt;br /&gt;
&lt;br /&gt;
Then, [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]] is used to create a nvmap object with the desired size. After, [[NV_services#NVMAP_IOC_ALLOC|NVMAP_IOC_ALLOC]] is used to allocate the memory on the GPU Address Space, and map data on the process Address Space into the GPU Address Space, by passing the Virtual Address as the input addr parameter, and also the Handle returned from [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]]. Lastly, the actual mapping is done by using [[NV_services#NVGPU_AS_IOCTL_MAP_BUFFER_EX|NVGPU_AS_IOCTL_MAP_BUFFER_EX]], and the GPU Virtual Address is returned on the offset parameter. It&#039;s also possible to manually set the offset where the mapping should be made on the GPU Address Space, by passing the address on the &amp;quot;offset&amp;quot; parameter, and setting the bit 0 of the flags parameter to 1. However, for this to work, the desired GPU Virtual Address needs to be previously reserved using [[NV_services#NVGPU_AS_IOCTL_ALLOC_SPACE|NVGPU_AS_IOCTL_ALLOC_SPACE]].&lt;br /&gt;
&lt;br /&gt;
The above process is used to map all data that will be used by the GPU, like Textures, Command Lists (a.k.a. Push Buffers), Vertex/Index buffers and Shaders. They usually have their own mapping, but Command Lists can share the same mapping.&lt;br /&gt;
&lt;br /&gt;
==Commands Submission==&lt;br /&gt;
&lt;br /&gt;
Commands are sent to the GPU through [[NV_services#NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO|NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO]]. This IoCtl command accepts various GpFifo entries, and each GpFifo entry points to a Command List. The GPU Command List is composed of 32-bits words, which usually are Command/Argument pairs.&lt;br /&gt;
&lt;br /&gt;
====Command Word Structure====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Bits&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|12-0&lt;br /&gt;
|Command/Register Id&lt;br /&gt;
|-&lt;br /&gt;
|15-13&lt;br /&gt;
|Sub Channel&lt;br /&gt;
|-&lt;br /&gt;
|28-16&lt;br /&gt;
|Arguments Count (in 32-bits Words) or Inline Data (see below)&lt;br /&gt;
|-&lt;br /&gt;
|31-29&lt;br /&gt;
|Mode&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Command Mode====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Mode&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Sequential Mode - Reads &amp;quot;Argument Count&amp;quot; arguments, while automatically incrementing the Register Id. So, each argument is written to a different register.&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Normal Mode - This is a Command with multiple arguments. Reads &amp;quot;Argument Count&amp;quot; arguments, all belonging to the same Command.&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Inline Mode - Bits 28-16 of the Command Word (where Inline Data is located) contains the Value of the argument written to the register. The next Word is another Command.&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|Unobserved, but is valid too.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
TODO: Find a better name for the &amp;quot;Normal Mode&amp;quot; and figure out what mode 5 is.&lt;br /&gt;
&lt;br /&gt;
Other mode values are unobserved.&lt;br /&gt;
&lt;br /&gt;
Note: All Commands/Register Id values are multiples of 4, so they are divided by 4 when packing, and multiplied by 4 when unpacking.&lt;br /&gt;
&lt;br /&gt;
==Sub Channel binding==&lt;br /&gt;
&lt;br /&gt;
All Command Id values &amp;lt; 0x100 are special and aren&#039;t fowarded to the engines. The command 0 is used to bind engines to Sub Channels, and needs to be used before commands are submited to the engines.&lt;br /&gt;
&lt;br /&gt;
The command 0 only has one argument, the Engine Id.&lt;br /&gt;
&lt;br /&gt;
====Engine Ids====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Id&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Engine&lt;br /&gt;
|-&lt;br /&gt;
|0x902d&lt;br /&gt;
|2D&lt;br /&gt;
|-&lt;br /&gt;
|0xb197&lt;br /&gt;
|3D&lt;br /&gt;
|-&lt;br /&gt;
|0xb1c0&lt;br /&gt;
|Compute&lt;br /&gt;
|-&lt;br /&gt;
|0xa140&lt;br /&gt;
|Kepler&lt;br /&gt;
|-&lt;br /&gt;
|0xb0b5 &lt;br /&gt;
|DMA&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The bits 15-13 of the Command Word contains the Sub Channel index that should be bound.&lt;br /&gt;
&lt;br /&gt;
After binding the required Sub Channels, then the respective values can be used on the &amp;quot;Sub Channel&amp;quot; field of the Command Word to talk with the respective Engines.&lt;br /&gt;
&lt;br /&gt;
==Fences==&lt;br /&gt;
&lt;br /&gt;
Command Lists can contain fences to ensure that commands are executed on the correct order, and subsequent commands are only sent when the previously sent commands were already processed by the GPU. Fences uses the QUERY_* commands, and works like this:&lt;br /&gt;
&lt;br /&gt;
* First, QUERY_ADDRESS_HIGH and QUERY_ADDRESS_LOW commands are added to the Command List, with the High/Low 32 bits part of the 64-bits GPU Virtual Address where the fence is located. This GPU Virtual Address needs to be mapped to the process Virtual Address beforehand.&lt;br /&gt;
* Then, QUERY_SEQUENCE is added with a sequential number. This number is basically a incrementing counter, so the first Command List can have QUERY_SEQUENCE = 1, the next one QUERY_SEQUENCE = 2, 3, 4... and so on.&lt;br /&gt;
* Finally, QUERY_GET is added and contains the mode and other unknown data.&lt;br /&gt;
&lt;br /&gt;
The above commands are added using the Sequential Mode, since the Ids for all those 4 registers are sequential.&lt;br /&gt;
&lt;br /&gt;
====QUERY_GET Structure====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Bits&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|1-0&lt;br /&gt;
|Mode&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Fence&lt;br /&gt;
|-&lt;br /&gt;
|15-12&lt;br /&gt;
|Unit &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====QUERY_GET Mode====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Value&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Mode&lt;br /&gt;
|-&lt;br /&gt;
|0&lt;br /&gt;
|Write&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Sync&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Write ? &lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Write ?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
TODO: Move this to a separate page with all GPU Commands with descriptions. Also figure out what the other values mean.&lt;br /&gt;
&lt;br /&gt;
Some of the other fields are still unknown/unobserved.&lt;br /&gt;
&lt;br /&gt;
Official games will set Mode to 0, Fence to 1 and Unit to 0xF. The QUERY_SEQUENCE value is then written by the GPU to the address pointed to by QUERY_ADDRESS.&lt;br /&gt;
On the CPU side, the game code should wait until the value at the address pointed to by QUERY_ADDRESS is &amp;gt;= to the last written SEQUENCE value. Official code waits for this condition to be true on a loop, and won&#039;t send any further commands before that.&lt;br /&gt;
&lt;br /&gt;
==Vertex Data Submission==&lt;br /&gt;
&lt;br /&gt;
Note: This is a observation on how the game Puyo Puyo Tetris sends textured squares to the GPU.&lt;br /&gt;
&lt;br /&gt;
# VERTEX_ATTRIB_FORMAT (0-15) are set (only the first 3 are really used, the rest are set float, with Size = 1 and offset at 0).&lt;br /&gt;
# VERTEX_ARRAY_FETCH (0) is set with the lower 12 bits set to 0x1c (Stride) and bit 12 to 1 (Enabled).&lt;br /&gt;
# VERTEX_ARRAY_START_HIGH/LOW (0) are set to the GPU Virtual Address where the Vertex Data is located.&lt;br /&gt;
# VERTEX_ARRAY_LIMIT_HIGH/LOW (0) are set to the GPU Virtual Address where the Vertex Data is located, plus the Vertex Data size in bytes minus 1.&lt;br /&gt;
# VERTEX_BEGIN_GL is used with the primitive type set to TRIANGLE_STRIP.&lt;br /&gt;
# VERTEX_BUFFER_FIRST with value 0 (indicating the index of the first primitive to render?).&lt;br /&gt;
# VERTEX_BUFFER_COUNT is set to 4, because the Vertex Buffer with the square has 4 vertices.&lt;br /&gt;
# VERTEX_END_GL is used with value 0 (currently unknown what this value means).&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
Check out those pages for more useful data.&lt;br /&gt;
&lt;br /&gt;
Register Id values from the Fermi family GPU (a bit older than the Tegra X1, but values seems to be mostly the same):&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/gf100_3d.xml]&lt;br /&gt;
&lt;br /&gt;
Values for some types used on the above XML:&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/nv_3ddefs.xml]&lt;br /&gt;
&lt;br /&gt;
Command Word packing code used on Mesa3d:&lt;br /&gt;
[https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nvc0/nvc0_winsys.h]&lt;/div&gt;</summary>
		<author><name>Gdkchan</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=GPU&amp;diff=3428</id>
		<title>GPU</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=GPU&amp;diff=3428"/>
		<updated>2018-01-15T00:02:16Z</updated>

		<summary type="html">&lt;p&gt;Gdkchan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Mapping Memory==&lt;br /&gt;
&lt;br /&gt;
First, to map a memory region on the GPU Address Space, caching needs to be disabled by using [[SVC#svcSetMemoryAttribute|svcSetMemoryAttribute]]. The Address passed is the Virtual Address of the region that will be mapped, the size is the region size, and State0/1 are both set to 8 to disable caching of the memory region. This is done to ensure that the GPU can actually &amp;quot;see&amp;quot; the data written there, and it doesn&#039;t get stuck on some cache.&lt;br /&gt;
&lt;br /&gt;
Then, [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]] is used to create a nvmap object with the desired size. After, [[NV_services#NVMAP_IOC_ALLOC|NVMAP_IOC_ALLOC]] is used to allocate the memory on the GPU Address Space, and map data on the process Address Space into the GPU Address Space, by passing the virtual address as the input addr parameter, and also the Handle returned from [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]]. Lastly, the actual mapping is done by using [[NV_services#NVGPU_AS_IOCTL_MAP_BUFFER_EX|NVGPU_AS_IOCTL_MAP_BUFFER_EX]], and the GPU Virtual Address is returned on the offset parameter. It&#039;s also possible to manually set the offset where the mapping should be made on the GPU Address Space, by passing the address on the &amp;quot;offset&amp;quot; parameter, and setting the bit 0 of the flags parameter to 1. However, for this to work, the desired GPU Virtual Address needs to be previously reserved using [[NV_services#NVGPU_AS_IOCTL_ALLOC_SPACE|NVGPU_AS_IOCTL_ALLOC_SPACE]].&lt;br /&gt;
&lt;br /&gt;
The above process is used to map all data that needs to be sent to the GPU, like Textures, Command Lists (a.k.a. Push Buffers), Vertex/Index buffers and Shaders. They usually have their own mapping, but Command Lists can share the same mapping.&lt;br /&gt;
&lt;br /&gt;
==Commands Submission==&lt;br /&gt;
&lt;br /&gt;
Commands are sent to the GPU through [[NV_services#NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO|NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO]]. This IoCtl command accepts various GpFifo entries, and each GpFifo entry points to a Command List. The GPU Command List is composed of 32-bits words, which usually are Command/Argument pairs.&lt;br /&gt;
&lt;br /&gt;
====Command Word Structure====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Bits&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|12-0&lt;br /&gt;
|Command/Register Id&lt;br /&gt;
|-&lt;br /&gt;
|15-13&lt;br /&gt;
|Sub Channel&lt;br /&gt;
|-&lt;br /&gt;
|28-16&lt;br /&gt;
|Arguments Count (in 32-bits Words) or Inline Data (see below)&lt;br /&gt;
|-&lt;br /&gt;
|31-29&lt;br /&gt;
|Mode&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Command Mode====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Mode&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Sequential Mode - Reads &amp;quot;Argument Count&amp;quot; arguments, while automatically incrementing the Register Id. So, each argument is written to a different register.&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Normal Mode - This is a Command with multiple arguments. Reads &amp;quot;Argument Count&amp;quot; arguments, all belonging to the same Command.&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Inline Mode - Bits 28-16 of the Command Word (where Inline Data is located) contains the Value of the argument written to the register. The next Word is another Command.&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|Unobserved, but is valid too.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
TODO: Find a better name for the &amp;quot;Normal Mode&amp;quot; and figure out what mode 5 is.&lt;br /&gt;
&lt;br /&gt;
Ohter mode values are unobserved.&lt;br /&gt;
&lt;br /&gt;
Note: All Commands/Register Id values are multiples of 4, so they are divided by 4 when packing, and multiplied by 4 when unpacking.&lt;br /&gt;
&lt;br /&gt;
==Sub Channel binding==&lt;br /&gt;
&lt;br /&gt;
All Command Id values &amp;lt; 0x100 are special and aren&#039;t fowarded to the engines. The command 0 is used to bind engines to Sub Channels, and needs to be used before commands are submited to the engines.&lt;br /&gt;
&lt;br /&gt;
The command 0 only has one argument, the Engine Id.&lt;br /&gt;
&lt;br /&gt;
====Engine Ids====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Id&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Engine&lt;br /&gt;
|-&lt;br /&gt;
|0x902d&lt;br /&gt;
|2D&lt;br /&gt;
|-&lt;br /&gt;
|0xb197&lt;br /&gt;
|3D&lt;br /&gt;
|-&lt;br /&gt;
|0xb1c0&lt;br /&gt;
|Compute&lt;br /&gt;
|-&lt;br /&gt;
|0xa140&lt;br /&gt;
|Kepler&lt;br /&gt;
|-&lt;br /&gt;
|0xb0b5 &lt;br /&gt;
|DMA&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The bits 15-13 of the Command Word contains the Sub Channel index that should be bound.&lt;br /&gt;
&lt;br /&gt;
After binding the required Sub Channels, then the respective values can be used on the &amp;quot;Sub Channel&amp;quot; field of the Command Word to talk with the respective Engines.&lt;br /&gt;
&lt;br /&gt;
==Fences==&lt;br /&gt;
&lt;br /&gt;
Command Lists can contain fences to ensure that commands are executed on the correct order, and subsequent commands are only sent when the previously sent commands were already processed by the GPU. Fences uses the QUERY_* commands, and works like this:&lt;br /&gt;
&lt;br /&gt;
* First, QUERY_ADDRESS_HIGH and QUERY_ADDRESS_LOW commands are added to the Command List, with the High/Low 32 bits part of the 64-bits GPU Virtual Address where the fence is located. This GPU Virtual Address needs to be mapped to the process Virtual Address beforehand.&lt;br /&gt;
* Then, QUERY_SEQUENCE is added with a sequential number. This number is basically a incrementing counter, so the first Command List can have QUERY_SEQUENCE = 1, the next one QUERY_SEQUENCE = 2, 3, 4... and so on.&lt;br /&gt;
* Finally, QUERY_GET is added and contains the mode and other unknown data.&lt;br /&gt;
&lt;br /&gt;
The above commands are added using the Sequential Mode, since the Ids for all those 4 registers are sequential.&lt;br /&gt;
&lt;br /&gt;
====QUERY_GET Structure====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Bits&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|1-0&lt;br /&gt;
|Mode&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Fence&lt;br /&gt;
|-&lt;br /&gt;
|15-12&lt;br /&gt;
|Unit &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====QUERY_GET Mode====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Value&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Mode&lt;br /&gt;
|-&lt;br /&gt;
|0&lt;br /&gt;
|Write&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Sync&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Write ? &lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Write ?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
TODO: Move this to a separate page with all GPU Commands with descriptions. Also figure out what the other values mean.&lt;br /&gt;
&lt;br /&gt;
Some of the other fields are still unknown/unobserved.&lt;br /&gt;
&lt;br /&gt;
Official games will set Mode to 0, Fence to 1 and Unit to 0xF. The QUERY_SEQUENCE value is then written by the GPU to the address pointed to by QUERY_ADDRESS.&lt;br /&gt;
On the CPU side, the game code should wait until the value at the address pointed to by QUERY_ADDRESS is &amp;gt;= to the last written SEQUENCE value. Official code waits for this condition to be true on a loop, and won&#039;t send any further commands before that.&lt;br /&gt;
&lt;br /&gt;
==Vertex Data Submission==&lt;br /&gt;
&lt;br /&gt;
Note: This is a observation on how the game Puyo Puyo Tetris sends textured squares to the GPU.&lt;br /&gt;
&lt;br /&gt;
# VERTEX_ATTRIB_FORMAT (0-15) are set (only the first 3 are really used, the rest are set float, with Size = 1 and offset at 0).&lt;br /&gt;
# VERTEX_ARRAY_FETCH (0) is set with the lower 12 bits set to 0x1c (Stride) and bit 12 to 1 (Enabled).&lt;br /&gt;
# VERTEX_ARRAY_START_HIGH/LOW (0) are set to the GPU Virtual Address where the Vertex Data is located.&lt;br /&gt;
# VERTEX_ARRAY_LIMIT_HIGH/LOW (0) are set to the GPU Virtual Address where the Vertex Data is located, plus the Vertex Data size in bytes minus 1.&lt;br /&gt;
# VERTEX_BEGIN_GL is used with the primitive type set to TRIANGLE_STRIP.&lt;br /&gt;
# VERTEX_BUFFER_FIRST with value 0 (indicating the index of the first primitive to render?).&lt;br /&gt;
# VERTEX_BUFFER_COUNT is set to 4, because the Vertex Buffer with the square has 4 vertices.&lt;br /&gt;
# VERTEX_END_GL is used with value 0 (currently unknown what this value means).&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
Check out those pages for more useful data.&lt;br /&gt;
&lt;br /&gt;
Register Id values from the Fermi family GPU (a bit older than the Tegra X1, but values seems to be mostly the same):&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/gf100_3d.xml]&lt;br /&gt;
&lt;br /&gt;
Values for some types used on the above XML:&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/nv_3ddefs.xml]&lt;br /&gt;
&lt;br /&gt;
Command Word packing code used on Mesa3d:&lt;br /&gt;
[https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nvc0/nvc0_winsys.h]&lt;/div&gt;</summary>
		<author><name>Gdkchan</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=GPU&amp;diff=3427</id>
		<title>GPU</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=GPU&amp;diff=3427"/>
		<updated>2018-01-14T23:34:17Z</updated>

		<summary type="html">&lt;p&gt;Gdkchan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Mapping Memory==&lt;br /&gt;
&lt;br /&gt;
First, to map a memory region on the GPU Address Space, caching needs to be disabled by using [[SVC#svcSetMemoryAttribute|svcSetMemoryAttribute]]. The Address passed is the Virtual Address of the region that will be mapped, the size is the region size, and State0/1 are both set to 8 to disable caching of the memory region. This is done to ensure that the GPU can actually &amp;quot;see&amp;quot; the data written there, and it doesn&#039;t get stuck on some cache.&lt;br /&gt;
&lt;br /&gt;
Then, [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]] is used to create a nvmap object with the desired size. After, [[NV_services#NVMAP_IOC_ALLOC|NVMAP_IOC_ALLOC]] is used to allocate the memory on the GPU Address Space, and map data on the process Address Space into the GPU Address Space, by passing the virtual address as the input addr parameter, and also the Handle returned from [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]]. Lastly, the actual mapping is done by using [[NV_services#NVGPU_AS_IOCTL_MAP_BUFFER_EX|NVGPU_AS_IOCTL_MAP_BUFFER_EX]], and the GPU Virtual Address is returned on the offset parameter. It&#039;s also possible to manually set the offset where the mapping should be made on the GPU Address Space, by passing the address on the &amp;quot;offset&amp;quot; parameter, and setting the bit 0 of the flags parameter to 1. However, for this to work, the desired GPU Virtual Address needs to be previously reserved using [[NV_services#NVGPU_AS_IOCTL_ALLOC_SPACE|NVGPU_AS_IOCTL_ALLOC_SPACE]].&lt;br /&gt;
&lt;br /&gt;
The above process is used to map all data that needs to be sent to the GPU, like Textures, Command Lists (a.k.a. Push Buffers), Vertex/Index buffers and Shaders. They usually have their own mapping, but Command Lists can share the same mapping.&lt;br /&gt;
&lt;br /&gt;
==Commands Submission==&lt;br /&gt;
&lt;br /&gt;
Commands are sent to the GPU through [[NV_services#NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO|NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO]]. This IoCtl command accepts various GpFifo entries, and each GpFifo entry points to a Command List. The GPU Command List is composed of 32-bits words, which usually are Command/Argument pairs.&lt;br /&gt;
&lt;br /&gt;
====Command Word Structure====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Bits&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|12-0&lt;br /&gt;
|Command/Register Id&lt;br /&gt;
|-&lt;br /&gt;
|15-13&lt;br /&gt;
|Sub Channel&lt;br /&gt;
|-&lt;br /&gt;
|28-16&lt;br /&gt;
|Arguments Count (in 32-bits Words) or Inline Data (see below)&lt;br /&gt;
|-&lt;br /&gt;
|31-29&lt;br /&gt;
|Mode&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Command Mode====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Mode&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Sequential Mode - Reads &amp;quot;Argument Count&amp;quot; arguments, while automatically incrementing the Register Id. So, each argument is written to a different register.&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Normal Mode - This is a Command with multiple arguments. Reads &amp;quot;Argument Count&amp;quot; arguments, all belonging to the same Command.&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Inline Mode - Bits 28-16 of the Command Word (where Inline Data is located) contains the Value of the argument written to the register. The next Word is another Command.&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|Unobserved, but is valid too.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
TODO: Find a better name for the &amp;quot;Normal Mode&amp;quot; and figure out what mode 5 is.&lt;br /&gt;
&lt;br /&gt;
Ohter mode values are unobserved.&lt;br /&gt;
&lt;br /&gt;
Note: All Commands/Register Id values are multiples of 4, so they are divided by 4 when packing, and multiplied by 4 when unpacking.&lt;br /&gt;
&lt;br /&gt;
==Sub Channel binding==&lt;br /&gt;
&lt;br /&gt;
All Command Id values &amp;lt; 0x100 are special and aren&#039;t fowarded to the engines. The command 0 is used to bind engines to Sub Channels, and needs to be used before commands are submited to the engines.&lt;br /&gt;
&lt;br /&gt;
The command 0 only has one argument, the Engine Id.&lt;br /&gt;
&lt;br /&gt;
====Engine Ids====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Id&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Engine&lt;br /&gt;
|-&lt;br /&gt;
|0x902d&lt;br /&gt;
|2D&lt;br /&gt;
|-&lt;br /&gt;
|0xb197&lt;br /&gt;
|3D&lt;br /&gt;
|-&lt;br /&gt;
|0xb1c0&lt;br /&gt;
|Compute&lt;br /&gt;
|-&lt;br /&gt;
|0xa140&lt;br /&gt;
|Kepler&lt;br /&gt;
|-&lt;br /&gt;
|0xb0b5 &lt;br /&gt;
|DMA&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The bits 15-13 of the Command Word contains the Sub Channel index that should be bound.&lt;br /&gt;
&lt;br /&gt;
After binding the required Sub Channels, then the respective values can be used on the &amp;quot;Sub Channel&amp;quot; field of the Command Word to talk with the respective Engines.&lt;br /&gt;
&lt;br /&gt;
==Fences==&lt;br /&gt;
&lt;br /&gt;
Command Lists can contain fences to ensure that commands are executed on the correct order, and subsequent commands are only sent when the previously sent commands were already processed by the GPU. Fences uses the QUERY_* commands, and works like this:&lt;br /&gt;
&lt;br /&gt;
* First, QUERY_ADDRESS_HIGH and QUERY_ADDRESS_LOW commands are added to the Command List, with the High/Low 32 bits part of the 64-bits GPU Virtual Address where the fence is located. This GPU Virtual Address needs to be mapped to the process Virtual Address beforehand.&lt;br /&gt;
* Then, QUERY_SEQUENCE is added with a sequential number. This number is basically a incrementing counter, so the first Command List can have QUERY_SEQUENCE = 1, the next one QUERY_SEQUENCE = 2, 3, 4... and so on.&lt;br /&gt;
* Finally, QUERY_GET is added and contains the mode and other unknown data.&lt;br /&gt;
&lt;br /&gt;
The above commands are added using the Sequential Mode, since the Ids for all those 4 registers are sequential.&lt;br /&gt;
&lt;br /&gt;
====QUERY_GET Structure====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Bits&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|1-0&lt;br /&gt;
|Mode&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Fence&lt;br /&gt;
|-&lt;br /&gt;
|15-12&lt;br /&gt;
|Unit &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====QUERY_GET Mode====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Value&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Mode&lt;br /&gt;
|-&lt;br /&gt;
|0&lt;br /&gt;
|Write&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Sync&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Write ? &lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Write ?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
TODO: Move this to a separate page with all GPU Commands with descriptions. Also figure out what the other values mean.&lt;br /&gt;
&lt;br /&gt;
Some of the other fields are still unknown/unobserved.&lt;br /&gt;
&lt;br /&gt;
Official games will set Mode to 0, Fence to 1 and Unit to 0xF. The QUERY_SEQUENCE value is then written by the GPU to the address pointed to by QUERY_ADDRESS.&lt;br /&gt;
On the CPU side, the game code should wait until the value at the address pointed to by QUERY_ADDRESS is &amp;gt;= to the last written SEQUENCE value. Official code waits for this condition to be true on a loop, and won&#039;t send any further commands before that.&lt;br /&gt;
&lt;br /&gt;
==Vertex Data Submission==&lt;br /&gt;
&lt;br /&gt;
Note: This is a observation on how the game Puyo Puyo Tetris sends textured squares to the GPU.&lt;br /&gt;
&lt;br /&gt;
# VERTEX_ATTRIB_FORMAT (0-15) are set (only the first 3 are really used, the rest are set float, with Size = 1 and offset at 0).&lt;br /&gt;
# VERTEX_ARRAY_FETCH (0) is set with the lower 12 bits set to 0x1c (Stride) and bit 12 to 1 (Enabled).&lt;br /&gt;
# VERTEX_ARRAY_START_HIGH/LOW are set to the GPU Virtual Address where the Vertex Data is located.&lt;br /&gt;
# VERTEX_ARRAY_LIMIT_HIGH/LOW are set to the GPU Virtual Address where the Vertex Data is located, plus the Vertex Data size in bytes minus 1.&lt;br /&gt;
# VERTEX_BEGIN_GL is used with the primitive type set to TRIANGLE_STRIP.&lt;br /&gt;
# VERTEX_BUFFER_FIRST with value 0 (indicating the index of the first primitive to render?).&lt;br /&gt;
# VERTEX_BUFFER_COUNT is set to 4, because the Vertex Buffer with the square has 4 vertices.&lt;br /&gt;
# VERTEX_END_GL is used with value 0 (currently unknown what this value means).&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
Check out those pages for more useful data.&lt;br /&gt;
&lt;br /&gt;
Register Id values from the Fermi family GPU (a bit older than the Tegra X1, but values seems to be mostly the same):&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/gf100_3d.xml]&lt;br /&gt;
&lt;br /&gt;
Values for some types used on the above XML:&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/nv_3ddefs.xml]&lt;br /&gt;
&lt;br /&gt;
Command Word packing code used on Mesa3d:&lt;br /&gt;
[https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nvc0/nvc0_winsys.h]&lt;/div&gt;</summary>
		<author><name>Gdkchan</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=GPU&amp;diff=3426</id>
		<title>GPU</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=GPU&amp;diff=3426"/>
		<updated>2018-01-14T23:27:42Z</updated>

		<summary type="html">&lt;p&gt;Gdkchan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Mapping Memory==&lt;br /&gt;
&lt;br /&gt;
First, to map a memory region on the GPU Address Space, caching needs to be disabled by using [[SVC#svcSetMemoryAttribute|svcSetMemoryAttribute]]. The Address passed is the Virtual Address of the region that will be mapped, the size is the region size, and State0/1 are both set to 8 to disable caching of the memory region. This is done to ensure that the GPU can actually &amp;quot;see&amp;quot; the data written there, and it doesn&#039;t get stuck on some cache.&lt;br /&gt;
&lt;br /&gt;
Then, [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]] is used to create a nvmap object with the desired size. After, [[NV_services#NVMAP_IOC_ALLOC|NVMAP_IOC_ALLOC]] is used to allocate the memory on the GPU Address Space, and map data on the process Address Space into the GPU Address Space, by passing the virtual address as the input addr parameter, and also the Handle returned from [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]]. Lastly, the actual mapping is done by using [[NV_services#NVGPU_AS_IOCTL_MAP_BUFFER_EX|NVGPU_AS_IOCTL_MAP_BUFFER_EX]], and the GPU Virtual Address is returned on the offset parameter. It&#039;s also possible to manually set the offset where the mapping should be made on the GPU Address Space, by passing the address on the &amp;quot;offset&amp;quot; parameter, and setting the bit 0 of the flags parameter to 1. However, for this to work, the desired GPU Virtual Address needs to be previously reserved using [[NV_services#NVGPU_AS_IOCTL_ALLOC_SPACE|NVGPU_AS_IOCTL_ALLOC_SPACE]].&lt;br /&gt;
&lt;br /&gt;
The above process is used to map all data that needs to be sent to the GPU, like Textures, Command Lists (a.k.a. Push Buffers), Vertex/Index buffers and Shaders. They usually have their own mapping, but Command Lists can share the same mapping.&lt;br /&gt;
&lt;br /&gt;
==Commands Submission==&lt;br /&gt;
&lt;br /&gt;
Commands are sent to the GPU through [[NV_services#NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO|NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO]]. This IoCtl command accepts various GpFifo entries, and each GpFifo entry points to a Command List. The GPU Command List is composed of 32-bits words, which usually are Command/Argument pairs.&lt;br /&gt;
&lt;br /&gt;
====Command Word Structure====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Bits&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|12-0&lt;br /&gt;
|Command/Register Id&lt;br /&gt;
|-&lt;br /&gt;
|15-13&lt;br /&gt;
|Sub Channel&lt;br /&gt;
|-&lt;br /&gt;
|28-16&lt;br /&gt;
|Arguments Count (in 32-bits Words) or Inline Data (see below)&lt;br /&gt;
|-&lt;br /&gt;
|31-29&lt;br /&gt;
|Mode&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Command Mode====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Mode&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Sequential Mode - Reads &amp;quot;Argument Count&amp;quot; arguments, while automatically incrementing the Register Id. So, each argument is written to a different register.&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Normal Mode - This is a Command with multiple arguments. Reads &amp;quot;Argument Count&amp;quot; arguments, all belonging to the same Command.&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Inline Mode - Bits 16:28 of the Command Word (where Inline Data is located) contains the Value of the argument written to the register. The next Word is another Command.&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|Unobserved, but is valid too.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
TODO: Find a better name for the &amp;quot;Normal Mode&amp;quot; and figure out what mode 5 is.&lt;br /&gt;
&lt;br /&gt;
Ohter mode values are unobserved.&lt;br /&gt;
&lt;br /&gt;
Note: All Commands/Register Id values are multiples of 4, so they are divided by 4 when packing, and multiplied by 4 when unpacking.&lt;br /&gt;
&lt;br /&gt;
==Sub Channel binding==&lt;br /&gt;
&lt;br /&gt;
All Command Id values &amp;lt; 0x100 are special and aren&#039;t fowarded to the engines. The command 0 is used to bind engines to Sub Channels, and needs to be used before commands are submited to the engines.&lt;br /&gt;
&lt;br /&gt;
The command 0 only has one argument, the Engine Id.&lt;br /&gt;
&lt;br /&gt;
====Engine Ids====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Id&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Engine&lt;br /&gt;
|-&lt;br /&gt;
|0x902d&lt;br /&gt;
|2D&lt;br /&gt;
|-&lt;br /&gt;
|0xb197&lt;br /&gt;
|3D&lt;br /&gt;
|-&lt;br /&gt;
|0xb1c0&lt;br /&gt;
|Compute&lt;br /&gt;
|-&lt;br /&gt;
|0xa140&lt;br /&gt;
|Kepler&lt;br /&gt;
|-&lt;br /&gt;
|0xb0b5 &lt;br /&gt;
|DMA&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The bits 15-13 of the Command Word contains the Sub Channel index that should be bound.&lt;br /&gt;
&lt;br /&gt;
After binding the required Sub Channels, then the respective values can be used on the &amp;quot;Sub Channel&amp;quot; field of the Command Word to talk with the respective Engines.&lt;br /&gt;
&lt;br /&gt;
==Fences==&lt;br /&gt;
&lt;br /&gt;
Command Lists can contain fences to ensure that commands are executed on the correct order, and subsequent commands are only sent when the previously sent commands were already processed by the GPU. Fences uses the QUERY_* commands, and works like this:&lt;br /&gt;
&lt;br /&gt;
* First, QUERY_ADDRESS_HIGH and QUERY_ADDRESS_LOW commands are added to the Command List, with the High/Low 32 bits part of the 64-bits GPU Virtual Address where the fence is located. This GPU Virtual Address needs to be mapped to the process Virtual Address beforehand.&lt;br /&gt;
* Then, QUERY_SEQUENCE is added with a sequential number. This number is basically a incrementing counter, so the first Command List can have QUERY_SEQUENCE = 1, the next one QUERY_SEQUENCE = 2, 3, 4... and so on.&lt;br /&gt;
* Finally, QUERY_GET is added and contains the mode and other unknown data.&lt;br /&gt;
&lt;br /&gt;
The above commands are added using the Sequential Mode, since the Ids for all those 4 registers are sequential.&lt;br /&gt;
&lt;br /&gt;
====QUERY_GET Structure====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Bits&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|1-0&lt;br /&gt;
|Mode&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Fence&lt;br /&gt;
|-&lt;br /&gt;
|15-12&lt;br /&gt;
|Unit &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====QUERY_GET Mode====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Value&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Mode&lt;br /&gt;
|-&lt;br /&gt;
|0&lt;br /&gt;
|Write&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Sync&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Write ? &lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Write ?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
TODO: Move this to a separate page with all GPU Commands with descriptions. Also figure out what the other values mean.&lt;br /&gt;
&lt;br /&gt;
Some of the other fields are still unknown/unobserved.&lt;br /&gt;
&lt;br /&gt;
Official games will set Mode to 0, Fence to 1 and Unit to 0xF. The QUERY_SEQUENCE value is then written by the GPU to the address pointed to by QUERY_ADDRESS.&lt;br /&gt;
On the CPU side, the game code should wait until the value at the address pointed to by QUERY_ADDRESS is &amp;gt;= to the last written SEQUENCE value. Official code waits for this condition to be true on a loop, and won&#039;t send any further commands before that.&lt;br /&gt;
&lt;br /&gt;
==Vertex Data Submission==&lt;br /&gt;
&lt;br /&gt;
Note: This is a observation on how the game Puyo Puyo Tetris sends textured squares to the GPU.&lt;br /&gt;
&lt;br /&gt;
# VERTEX_ATTRIB_FORMAT (0-15) are set (only the first 3 are really used, the rest are set float, with Size = 1 and offset at 0).&lt;br /&gt;
# VERTEX_ARRAY_FETCH (0) is set with the lower 12 bits set to 0x1c (Stride) and bit 12 to 1 (Enabled).&lt;br /&gt;
# VERTEX_ARRAY_START_HIGH/LOW are set to the GPU Virtual Address where the Vertex Data is located.&lt;br /&gt;
# VERTEX_ARRAY_LIMIT_HIGH/LOW are set to the GPU Virtual Address where the Vertex Data is located, plus the Vertex Data size in bytes minus 1.&lt;br /&gt;
# VERTEX_BEGIN_GL is used with the primitive type set to TRIANGLE_STRIP.&lt;br /&gt;
# VERTEX_BUFFER_FIRST with value 0 (indicating the index of the first primitive to render?).&lt;br /&gt;
# VERTEX_BUFFER_COUNT is set to 4, because the Vertex Buffer with the square has 4 vertices.&lt;br /&gt;
# VERTEX_END_GL is used with value 0 (currently unknown what this value means).&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
Check out those pages for more useful data.&lt;br /&gt;
&lt;br /&gt;
Register Id values from the Fermi family GPU (a bit older than the Tegra X1, but values seems to be mostly the same):&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/gf100_3d.xml]&lt;br /&gt;
&lt;br /&gt;
Values for some types used on the above XML:&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/nv_3ddefs.xml]&lt;br /&gt;
&lt;br /&gt;
Command Word packing code used on Mesa3d:&lt;br /&gt;
[https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nvc0/nvc0_winsys.h]&lt;/div&gt;</summary>
		<author><name>Gdkchan</name></author>
	</entry>
	<entry>
		<id>https://switchbrew.org/w/index.php?title=GPU&amp;diff=3425</id>
		<title>GPU</title>
		<link rel="alternate" type="text/html" href="https://switchbrew.org/w/index.php?title=GPU&amp;diff=3425"/>
		<updated>2018-01-14T23:21:49Z</updated>

		<summary type="html">&lt;p&gt;Gdkchan: Created page with &amp;quot;==Mapping Memory==  First, to map a memory region on the GPU Address Space, caching needs to be disabled by using svcSetMemoryAttribute. The Addr...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Mapping Memory==&lt;br /&gt;
&lt;br /&gt;
First, to map a memory region on the GPU Address Space, caching needs to be disabled by using [[SVC#svcSetMemoryAttribute|svcSetMemoryAttribute]]. The Address passed is the Virtual Address of the region that will be mapped, the size is the region size, and State0/1 are both set to 8 to disable caching of the memory region. This is done to ensure that the GPU can actually &amp;quot;see&amp;quot; the data written there, and it doesn&#039;t get stuck on some cache.&lt;br /&gt;
&lt;br /&gt;
Then, [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]] is used to create a nvmap object with the desired size. After, [[NV_services#NVMAP_IOC_ALLOC|NVMAP_IOC_ALLOC]] is used to allocate the memory on the GPU Address Space, and map data on the process Address Space into the GPU Address Space, by passing the virtual address as the input addr parameter, and also the Handle returned from [[NV_services#NVMAP_IOC_CREATE|NVMAP_IOC_CREATE]]. Lastly, the actual mapping is done by using [[NV_services#NVGPU_AS_IOCTL_MAP_BUFFER_EX|NVGPU_AS_IOCTL_MAP_BUFFER_EX]], and the GPU Virtual Address is returned on the offset parameter. It&#039;s also possible to manually set the offset where the mapping should be made on the GPU Address Space, by passing the address on the &amp;quot;offset&amp;quot; parameter, and setting the bit 0 of the flags parameter to 1. However, for this to work, the desired GPU Virtual Address needs to be previously reserved using [[NV_services#NVGPU_AS_IOCTL_ALLOC_SPACE|NVGPU_AS_IOCTL_ALLOC_SPACE]].&lt;br /&gt;
&lt;br /&gt;
The above process is used to map all data that needs to be sent to the GPU, like Textures, Command Lists (a.k.a. Push Buffers), Vertex/Index buffers and Shaders. They usually have their own mapping, but Command Lists can share the same mapping.&lt;br /&gt;
&lt;br /&gt;
==Commands Submission==&lt;br /&gt;
&lt;br /&gt;
Commands are sent to the GPU through [[NV_services#NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO|NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO]]. This IoCtl command accepts various GpFifo entries, and each GpFifo entry points to a Command List. The GPU Command List is composed of 32-bits words, which usually are Command/Argument pairs.&lt;br /&gt;
&lt;br /&gt;
====Command Word Structure====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Bits&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|12-0&lt;br /&gt;
|Command/Register Id&lt;br /&gt;
|-&lt;br /&gt;
|15-13&lt;br /&gt;
|Sub Channel&lt;br /&gt;
|-&lt;br /&gt;
|28-16&lt;br /&gt;
|Arguments Count (in 32-bits Words) or Inline Data (see below)&lt;br /&gt;
|-&lt;br /&gt;
|31-29&lt;br /&gt;
|Mode&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====Command Mode====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Mode&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Sequential Mode - Reads &amp;quot;Argument Count&amp;quot; arguments, while automatically incrementing the Register Id. So, each argument is written to a different register.&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Normal Mode - This is a Command with multiple arguments. Reads &amp;quot;Argument Count&amp;quot; arguments, all belonging to the same Command.&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Inline Mode - Bits 16:28 of the Command Word (where Inline Data is located) contains the Value of the argument written to the register. The next Word is another Command.&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|Unobserved, but is valid too.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
TODO: Find a better name for the &amp;quot;Normal Mode&amp;quot; and figure out what mode 5 is.&lt;br /&gt;
&lt;br /&gt;
Ohter mode values are unobserved.&lt;br /&gt;
&lt;br /&gt;
Note: All Commands/Register Id values are multiples of 4, so they are divided by 4 when packing, and multiplied by 4 when unpacking.&lt;br /&gt;
&lt;br /&gt;
==Sub Channel binding==&lt;br /&gt;
&lt;br /&gt;
All Command Id values &amp;lt; 0x100 are special and aren&#039;t fowarded to the engines. The command 0 is used to bind engines to Sub Channels, and needs to be used before commands are submited to the engines.&lt;br /&gt;
&lt;br /&gt;
The command 0 only has one argument, the Engine Id.&lt;br /&gt;
&lt;br /&gt;
====Engine Ids====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Id&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Engine&lt;br /&gt;
|-&lt;br /&gt;
|0x902d&lt;br /&gt;
|2D&lt;br /&gt;
|-&lt;br /&gt;
|0xb197&lt;br /&gt;
|3D&lt;br /&gt;
|-&lt;br /&gt;
|0xb1c0&lt;br /&gt;
|Compute&lt;br /&gt;
|-&lt;br /&gt;
|0xa140&lt;br /&gt;
|Kepler&lt;br /&gt;
|-&lt;br /&gt;
|0xb0b5 &lt;br /&gt;
|DMA&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The bits 15-13 of the Command Word contains the Sub Channel index that should be bound.&lt;br /&gt;
&lt;br /&gt;
After binding the required Sub Channels, then the respective values can be used on the &amp;quot;Sub Channel&amp;quot; field of the Command Word to talk with the respective Engines.&lt;br /&gt;
&lt;br /&gt;
==Fences==&lt;br /&gt;
&lt;br /&gt;
Command Lists can contain fences to ensure that commands are executed on the correct order, and subsequent commands are only sent when the previously sent commands were already processed by the GPU. Fences uses the QUERY_* commands, and works like this:&lt;br /&gt;
&lt;br /&gt;
* First, QUERY_ADDRESS_HIGH and QUERY_ADDRESS_LOW commands are added to the Command List, with the High/Low 32 bits part of the 64-bits GPU Virtual Address where the fence is located. This GPU Virtual Address needs to be mapped to the process Virtual Address beforehand.&lt;br /&gt;
* Then, QUERY_SEQUENCE is added with a sequential number. This number is basically a incrementing counter, so the first Command List can have QUERY_SEQUENCE = 1, the next one QUERY_SEQUENCE = 2, 3, 4... and so on.&lt;br /&gt;
* Finally, QUERY_GET is added and contains the mode and other unknown data.&lt;br /&gt;
&lt;br /&gt;
====QUERY_GET Structure====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Bits&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
|1-0&lt;br /&gt;
|Mode&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|Fence&lt;br /&gt;
|-&lt;br /&gt;
|15-12&lt;br /&gt;
|Unit &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====QUERY_GET Mode====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Value&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Mode&lt;br /&gt;
|-&lt;br /&gt;
|0&lt;br /&gt;
|Write&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Sync&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Write ? &lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|Write ?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
TODO: Move this to a separate page with all GPU Commands with descriptions. Also figure out what the other values mean.&lt;br /&gt;
&lt;br /&gt;
Some of the other fields are still unknown/unobserved.&lt;br /&gt;
&lt;br /&gt;
Official games will set Mode to 0, Fence to 1 and Unit to 0xF. The QUERY_SEQUENCE value is then written to the address pointed to by QUERY_ADDRESS.&lt;br /&gt;
On the CPU side, the game code should wait until the value at the address pointed to by QUERY_ADDRESS is &amp;gt;= to the last written SEQUENCE value. Official code waits for this condition to be true on a loop, and won&#039;t send any further commands before that.&lt;br /&gt;
&lt;br /&gt;
==Vertex Data Submission==&lt;br /&gt;
&lt;br /&gt;
Note: This is a observation on how the game Puyo Puyo Tetris sends textured squares to the GPU.&lt;br /&gt;
&lt;br /&gt;
# VERTEX_ATTRIB_FORMAT (0-15) are set (only the first 3 are really used, the rest are set float, with Size = 1 and offset at 0).&lt;br /&gt;
# VERTEX_ARRAY_FETCH (0) is set with the lower 12 bits set to 0x1c (Stride) and bit 12 to 1 (Enabled).&lt;br /&gt;
# VERTEX_ARRAY_START_HIGH/LOW are set to the GPU Virtual Address where the Vertex Data is located.&lt;br /&gt;
# VERTEX_ARRAY_LIMIT_HIGH/LOW are set to the GPU Virtual Address where the Vertex Data is located, plus the Vertex Data size in bytes minus 1.&lt;br /&gt;
# VERTEX_BEGIN_GL is used with the primitive type set to TRIANGLE_STRIP.&lt;br /&gt;
# VERTEX_BUFFER_FIRST with value 0 (indicating the index of the first primitive to render?).&lt;br /&gt;
# VERTEX_BUFFER_COUNT is set to 4, because the Vertex Buffer with the square has 4 vertices.&lt;br /&gt;
# VERTEX_END_GL is used with value 0 (currently unknown what this value means).&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
Check out those pages for more useful data.&lt;br /&gt;
&lt;br /&gt;
Register Id values from the Fermi family GPU (a bit older than the Tegra X1, but values seems to be mostly the same):&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/gf100_3d.xml]&lt;br /&gt;
&lt;br /&gt;
Values for some types used on the above XML:&lt;br /&gt;
[https://github.com/envytools/envytools/blob/master/rnndb/graph/nv_3ddefs.xml]&lt;br /&gt;
&lt;br /&gt;
Command Word packing code used on Mesa3d:&lt;br /&gt;
[https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nvc0/nvc0_winsys.h]&lt;/div&gt;</summary>
		<author><name>Gdkchan</name></author>
	</entry>
</feed>