NV services

From Nintendo Switch Brew
Jump to navigation Jump to search

The Switch makes use of a customized NVIDIA driver.

nvdrv:a

Main NVIDIA driver service.

Cmd Name
0 #Open
1 #Ioctl
2 #Close
3 #Initialize
4 QueryEvent
5 MapSharedMem
6 ?
7 ?
8 BindDisplayService
9 ?

Open

Word Value
0 0x00100004
1 0x00000008
2-4 Type 5 descriptor: Device path
0-1 "SFCI"
2-3 Cmd id (0)

Ioctl

Word Value
0 0x11100004
1 0x00000C0B
? Type 0x21 descriptor: Input buffer
? Type 0x22 descriptor: Output buffer
0-1 "SFCI"
2-3 Cmd id (1)
4 Device fd
5 Ioctl Cmd

Close

Word Value
0 0x00000004
1 0x00000009
0-1 "SFCI"
2-3 Cmd id (2)
4 Device fd

Initialize

Word Value
0 0x00000004
1 0x80000009
? Handle descriptor: Current process
? Handle descriptor: Shared memory mirror
0-1 "SFCI"
2-3 Cmd id (3)
4 Shared memory size

Webkit applet creates the shared memory with perm = 0 and size 0x300000.

Ioctls

The ioctl number is generated with the following primitive (see Linux kernel):

#define _IOC(inout, group, num, len) \
   (inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num))

The following table contains known ioctls.

/dev/nvhost-ctrl

Value Direction Size Description Notes
0xC0080014 Inout 8 NVHOST_IOCTL_CTRL_SYNCPT_READ
0x40040015 In 4 NVHOST_IOCTL_CTRL_SYNCPT_INCR
0xC00C0016 Inout 12 NVHOST_IOCTL_CTRL_SYNCPT_WAIT
0x40080017 In 8 NVHOST_IOCTL_CTRL_MODULE_MUTEX
0xC0180018 Inout 24 NVHOST32_IOCTL_CTRL_MODULE_REGRDWR
0xC0100019 Inout 16 NVHOST_IOCTL_CTRL_SYNCPT_WAITEX
0xC008001A Inout 8 NVHOST_IOCTL_CTRL_SYNCPT_READ_MAX
0xC004001C Inout 4
0xC010001D Inout 16 NvRmSyncWaitEvent (wait on event?)
0xC010001E Inout 16 NvRmSyncWaitEvent (wait on event?)
0xC004001F Inout 4 NvRmSyncWaitEvent (signal event?)
0xC0040020 Inout 4 NvRmSyncWaitEvent (signal event?)
0x40080021 In 8 cancel_wait_event Cancels all events

/dev/nvhost-as-gpu

Each fd opened to this device creates an address space. An address space is then later bound with a channel.

Once a nvgpu channel has been bound to an address space it cannot be unbound. There is no support for allowing an nvgpu channel to change from one address space to another (or from one to none).

Device Direction Size Value Description Notes
/dev/nvhost-as-gpu In 4 0x40044101 #NVGPU_AS_IOCTL_BIND_CHANNEL
/dev/nvhost-as-gpu Inout 24 0xC0184102 #NVGPU_AS_IOCTL_ALLOC_SPACE
/dev/nvhost-as-gpu Inout 16 0xC0104103 #NVGPU_AS_IOCTL_FREE_SPACE
/dev/nvhost-as-gpu Inout 24 0xC0184104 #NVGPU_AS_IOCTL_MAP_BUFFER
/dev/nvhost-as-gpu Inout 8 0xC0084105 NVGPU_AS_IOCTL_UNMAP_BUFFER
/dev/nvhost-as-gpu Inout 40 0xC0284106 NVGPU_AS_IOCTL_MAP_BUFFER_EX
/dev/nvhost-as-gpu In 16 0x40104107 #NVGPU_AS_IOCTL_INITIALIZE
/dev/nvhost-as-gpu Inout 64 0xC0404108 NVGPU_AS_IOCTL_GET_VA_REGIONS?
/dev/nvhost-as-gpu In 40 0x40284109 #NVGPU_AS_IOCTL_INITIALIZE_EX
/dev/nvhost-as-gpu Inout 20 0xC0144114

NVGPU_AS_IOCTL_BIND_CHANNEL

Identical to Linux driver.

 struct {
   u32 __fd; // in
 };

NVGPU_AS_IOCTL_ALLOC_SPACE

This one reserves pages in the device address space.

 struct {
   u32 __pages;     // in
   u32 __page_size; // in
   u32 __flags;     // in
   u32 __pad;
   union {
     u64 __offset;  // out
     u64 __align;   // in
   };
 };

NVGPU_AS_IOCTL_FREE_SPACE

 struct {
   u64 __offset;    // in
   u32 __pages;     // in
   u32 __page_size; // in
 };

NVGPU_AS_IOCTL_MAP_BUFFER

Map a memory region in the device address space. Identical to Linux driver pretty much.

On success, the mapped memory region is locked by having SVC#MemoryState bit34 set.

 struct {
   u32 __flags;        // in, 4 works
   u32 __reserved;
   u32 __nvmap_handle; // in
   u32 __page_size;    // inout, 0 means don't care
   union {
     u64 __offset;     // out
     u64 __align;      // in
   };
 };

NVGPU_AS_IOCTL_INITIALIZE

Nintendo custom.

 struct {
   u32 __unk;       // in, 0 works
   u32 __zeroes[3]; // in
 };

NVGPU_AS_IOCTL_INITIALIZE_EX

 struct {
   u32 __unk0; // in
   u32 __pad0;
   u32 __unk1; // in
   u32 __pad1;
   u64 __unk2; // in
   u64 __unk3; // in
   u64 __unk4; // in
 };

/dev/nvmap

Value Direction Size Description Notes
0xC0080101 Inout 8 #NVMAP_IOC_CREATE
0x00000102 - 0 NVMAP_IOC_CLAIM Returns NotSupported
0xC0080103 Inout 8 #NVMAP_IOC_FROM_ID
0xC0200104 Inout 32 #NVMAP_IOC_ALLOC
0xC0180105 Inout 24 #NVMAP_IOC_FREE
0xC0280106 Inout 40 NVMAP_IOC_MMAP Returns NotSupported
0xC0280107 Inout 40 NVMAP_IOC_WRITE Returns NotSupported
0xC0280108 Inout 40 NVMAP_IOC_READ Returns NotSupported
0xC00C0109 Inout 12 #NVMAP_IOC_PARAM
0xC010010A Inout 16 NVMAP_IOC_PIN_MULT Returns NotSupported
0xC010010B Inout 16 NVMAP_IOC_UNPIN_MULT Returns NotSupported
0xC008010C Inout 8 NVMAP_IOC_CACHE Returns NotSupported
0xC004010D Inout 4 Returns NotSupported
0xC008010E Inout 8 #NVMAP_IOC_GET_ID
0xC004010F Inout 4 Returns NotSupported
0x40040110 In 4 Returns NotSupported
0x00000111 - 0 Returns NotSupported

NVMAP_IOC_CREATE

Creates an nvmap object. Identical to Linux driver.

 struct {
   u32 __size;   // in
   u32 __handle; // out
 };

NVMAP_IOC_FROM_ID

Get handle to an existing nvmap object. Identical to Linux driver.

 struct {
   u32 __id;     // in
   u32 __handle; // out
 };

NVMAP_IOC_ALLOC

Allocate memory for the nvmap object. Nintendo extended this one with 16 bytes, and changed it from in to inout.

 struct {
   u32 __handle;   // in
   u32 __heapmask; // in
   u32 __flags;    // in (0=read-only, 1=read-write)
   u32 __align;    // in
   u8  __unk0;     // in
   u8  __pad[7];
   u64 __addr;     // in
 };

NVMAP_IOC_FREE

This one is completely custom. Partly because the Linux driver passed the handle as the ioctl "arg-ptr", and HIPC can't handle that voodoo.

 struct {
   u32 __handle;   // in
   u32 __pad;
   u64 __refcount; // out
   u32 __size;     // out
   u32 __flags;    // out
 };

NVMAP_IOC_PARAM

Returns info about a nvmap object. Identical to Linux driver, but extended with further params.

 struct {
   u32 __handle; // in
   u32 __param;  // in, 1=SIZE, 2=ALIGNMENT, 3=?, 4=?, 5=UNK0, 6=?
   u32 __result; // out
 };

NVMAP_IOC_GET_ID

Returns an id for a nvmap object. Identical to Linux driver.

 struct {
   u32 __id;     // out
   u32 __handle; // in
 };

/dev/nvhost-ctrl-gpu

This device is for global (context independent) operations on the gpu.

Value Direction Size Description Notes
0x80044701 Out 4 NVGPU_GPU_IOCTL_ZCULL_GET_CTX_SIZE
0x80284702 Out 40 NVGPU_GPU_IOCTL_ZCULL_GET_INFO
0x402C4703 In 44 NVGPU_GPU_IOCTL_ZBC_SET_TABLE
0xC0344704 Inout 52 NVGPU_GPU_IOCTL_ZBC_QUERY_TABLE
0xC0B04705 Inout 176 NVGPU_GPU_IOCTL_GET_CHARACTERISTICS
0xC0184706 Inout 24 NVGPU_GPU_IOCTL_GET_TPC_MASKS
0x40084707 In 8 NVGPU_GPU_IOCTL_OPEN_CHANNEL
0x4008470E In 8
0x4010470F In 16
0xC0084710 Inout 8
0x80084711 Out 8
0x80084712 Out 8
0xC0044713 Inout 4
0x80084714 Out 8
0x80044715 Out 4
0x8018471A Out 24
0xC008471B Inout 8
0xC010471C Inout 16

Channels

Channels are a concept for NVIDIA hardware blocks that share a common interface.

Path Name
/dev/nvhost-gpu
/dev/nvhost-vic
/dev/nvhost-nvdec
/dev/nvhost-nvjpg

Channel Ioctls

Value Size Description Notes
0xC0??0001 Variable NVHOST_IOCTL_CHANNEL_SUBMIT
0xC0080002 8 NVHOST_IOCTL_CHANNEL_GET_SYNCPOINT
0xC0080003 8 NVHOST_IOCTL_CHANNEL_GET_WAITBASE
0xC0080004 8 NVHOST_IOCTL_CHANNEL_SET_TIMEOUT_EX
0x40040007 4
0xC0??0009 Variable NVHOST_IOCTL_CHANNEL_MAP_BUFFER
0xC0??000A Variable NVHOST_IOCTL_CHANNEL_UNMAP_BUFFER
0x00000013 0
0x40044801 4 NVGPU_IOCTL_CHANNEL_SET_NVMAP_FD
0x40044803 4 NVGPU_IOCTL_CHANNEL_SET_PRIORITY
0x40084805 8 NVGPU_IOCTL_CHANNEL_ALLOC_GPFIFO
0xC0044807 4 NVGPU_IOCTL_CHANNEL_CYCLE_STATS
0xC0184808 24 NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO
0xC0104809 16 NVGPU_IOCTL_CHANNEL_ALLOC_OBJ_CTX
0x4008480A 8 NVGPU_IOCTL_CHANNEL_FREE_OBJ_CTX
0xC010480B 16 NVGPU_IOCTL_CHANNEL_ZCULL_BIND
0xC018480C 24 NVGPU_IOCTL_CHANNEL_SET_ERROR_NOTIFIER
0x4004480D 4 NVGPU_IOCTL_CHANNEL_OPEN
0x0000480E 0 NVGPU_IOCTL_CHANNEL_ENABLE
0x0000480F 0 NVGPU_IOCTL_CHANNEL_DISABLE
0x00004810 0 NVGPU_IOCTL_CHANNEL_PREEMPT
0x00004811 0 NVGPU_IOCTL_CHANNEL_FORCE_RESET
0x40084812 8 NVGPU_IOCTL_CHANNEL_EVENTS_CTRL
0xC0104813 16 NVGPU_IOCTL_CHANNEL_CYCLE_STATS_SNAPSHOT
0x80804816 128
0xC0104817 16
0x40204818 32 NVGPU_IOCTL_CHANNEL_ALLOC_GPFIFO_EX
0xC0484819 72
0xC020481A 32 NVGPU_IOCTL_CHANNEL_ALLOC_GPFIFO_EX2
0x40084714 8 set_user_address
0x80084715 8 get_user_address

Remaining Ioctls

Value Size Description Notes
/dev/nvhost-dbg-gpu 0x40084401 NVGPU_DBG_GPU_IOCTL_BIND_CHANNEL
/dev/nvhost-dbg-gpu 0xC0??4402 NVGPU_DBG_GPU_IOCTL_REG_OPS ?? == size is unknown
/dev/nvhost-dbg-gpu 0x40084403 NVGPU_DBG_GPU_IOCTL_EVENTS_CTRL
/dev/nvhost-dbg-gpu 0x40044404 NVGPU_DBG_GPU_IOCTL_POWERGATE
/dev/nvhost-dbg-gpu 0x40044405 NVGPU_DBG_GPU_IOCTL_SMPC_CTXSW_MODE
/dev/nvhost-dbg-gpu 0xC0184407 NVGPU_DBG_GPU_IOCTL_PERFBUF_MAP
/dev/nvhost-dbg-gpu 0x40084408 NVGPU_DBG_GPU_IOCTL_PERFBUF_UNMAP
/dev/nvhost-dbg-gpu 0x40084409 NVGPU_DBG_GPU_IOCTL_PC_SAMPLING

nvmemp

NVIDIA memory profiler (this service is not available on retail units).

mm:u

NVIDIA multimedia (NvMM) platform service.

Cmd Name
0 ?
1 ?
2 ?
3 ?
4 module_init_clk
5 module_deinit_clk
6 module_set_clk_rate
7 module_get_clk_rate

Errors

Most nvidia driver commands return an error code apart from the normal return code.

Cmd Name
0 Success
1 NotImplemented
2 NotSupported
3 NotInitialized
4 BadParameter
5 Timeout
6 InsufficientMemory
7 ReadOnlyAttribute
8 InvalidState
9 InvalidAddress
0xA InvalidSize
0xB BadValue
0xD AlreadyAllocated
0xE Busy
0xF ResourceError
0x10 CountMismatch
0x1000 SharedMemoryTooSmall
0x3000F IoctlFailed