The Switch uses a customized NVIDIA driver.

nvdrv, nvdrv:a, nvdrv:s, nvdrv:t

This is "nns::nvdrv::INvDrvServices".

Main NVIDIA driver service.

Each service is used by:

  • "nvdrv": regular applications
  • "nvdrv:a": applets
  • "nvdrv:s": sysmodules
  • "nvdrv:t": factory titles
Cmd Name
0 #Open
1 #Ioctl
2 #Close
3 #Initialize
4 #QueryEvent
5 #MapSharedMem
6 #GetStatus
7 #SetAruid
8 #SetAruidByPID
9 #DumpGraphicsMemoryInfo
10 [3.0.0+] #InitializeDevtools
11 [3.0.0+] #Ioctl2
12 [3.0.0+] #Ioctl3
13 [3.0.0+] #FinishInitialize

Open

Takes a type-0x5 input buffer for the device-path. Returns the output 32bit fd and the u32 error_code.

Ioctl

Takes a 32bit fd, an u32 ioctl_cmd, a type-0x21 input buffer, and a type-0x22 output buffer. Returns an output u32 (error_code).

The addr/size for send/recv buffers are only set when the associated direction bit is set in the ioctl cmd (addr/size = 0 otherwise).

Close

Takes a 32bit fd. Returns an output u32 (error_code).

Initialize

Takes two copy-handles (current_process and transfer_memory) and an input u32 (transfer_memory_size). Returns an output u32 (error_code).

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

QueryEvent

Takes two input u32s (fd and event_id), with the second word immediately after the first one. Returns an output u32 (error_code) and a copy-handle (event_handle).

QueryEvent is only supported on (and implemented differently on):

  • /dev/nvhost-gpu
    • 1: SmException_BptIntReport
    • 2: SmException_BptPauseReport
    • 3: ErrorNotifierEvent
  • /dev/nvhost-ctrl: Used to get events for SyncPts.
    • If bit31-28 is 1, then lower 16-bits contain event_slot, bit27-16 contain syncpt_number.
    • If bit31-28 is 0, then lower 4-bits contain event_slot, bit31-4 contains syncpt_number.
  • /dev/nvhost-ctrl-gpu
    • 1: Returns error_event_handle.
    • 2: Returns unknown event.
  • /dev/nvhost-dbg-gpu
    • Ignores event_id.

MapSharedMem

Takes a copy-handle (transfer_memory) and two input u32s (fd and nvmap_handle). Returns an output u32 (error_code).

GetStatus

Takes no input. Returns 0x10-bytes and an output u32 (error_code).

SetAruid

Takes an input u64 which must match the user-process PID (AppletResourceUserId). Returns an output u32 (error_code).

SetAruidByPID

Takes a PID-descriptor and an u64 which must match the user-process PID (AppletResourceUserId). Returns an output u32 (error_code).

DumpGraphicsMemoryInfo

No input or output. Does nothing.

InitializeDevtools

Takes a copy-handle and an input u32. Returns an output u32 (error_code).

Ioctl2

Takes a type-0x21 buffer, a type-0x22 buffer, a type-0x21 buffer, and two input u32s. Returns an output u32 (error_code).

Ioctl3

Takes a type-0x21 buffer, a type-0x22 buffer, another type-0x22 buffer, and two input u32s. Returns an output u32 (error_code). Cmdhdr_word1 is 0x100B instead of 0xC0B.

FinishInitialize

Takes an input u64. No output.

This sets a boolean value based on the input u64 and the value of the "nv!nv_graphics_firmware_memory_margin" system configuration, but only for "nvdrv" (the other services default to false).

Official user-processes starting with 3.0.0 now use this at the end of nvdrv service init with value 0x1.

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 #NVHOST_IOCTL_CTRL_MODULE_REGRDWR
0xC0100019 Inout 16 #NVHOST_IOCTL_CTRL_SYNCPT_WAITEX
0xC008001A Inout 8 #NVHOST_IOCTL_CTRL_SYNCPT_READ_MAX
0xC183001B Inout 387 #NVHOST_IOCTL_CTRL_GET_CONFIG
0xC004001C Inout 4 #NVHOST_IOCTL_CTRL_EVENT_SIGNAL
0xC010001D Inout 16 #NVHOST_IOCTL_CTRL_EVENT_WAIT
0xC010001E Inout 16 #NVHOST_IOCTL_CTRL_EVENT_WAIT_ASYNC
0xC004001F Inout 4 #NVHOST_IOCTL_CTRL_EVENT_REGISTER
0xC0040020 Inout 4 #NVHOST_IOCTL_CTRL_EVENT_UNREGISTER
0x40080021 In 8 #NVHOST_IOCTL_CTRL_EVENT_KILL

NVHOST_IOCTL_CTRL_SYNCPT_READ

Identical to Linux driver.

 struct {
   __in  u32 id;
   __out u32 value;
 };

NVHOST_IOCTL_CTRL_SYNCPT_INCR

Identical to Linux driver.

 struct {
   __in u32 id;
 };

NVHOST_IOCTL_CTRL_SYNCPT_WAIT

Identical to Linux driver.

 struct {
   __in u32 id;
   __in u32 thresh;
   __in s32 timeout;
 };

NVHOST_IOCTL_CTRL_MODULE_MUTEX

Identical to Linux driver.

 struct {
   __in u32 id;
   __in u32 lock;        // (0==unlock; 1==lock)
 };

NVHOST_IOCTL_CTRL_MODULE_REGRDWR

Identical to Linux driver. Uses 32-bit version and doesn't work.

 struct {
   __in u32 id;
   __in u32 num_offsets;
   __in u32 block_size;
   __in u32 offsets;
   __in u32 values;
   __in u32 write;
 };

NVHOST_IOCTL_CTRL_SYNCPT_WAITEX

Identical to Linux driver.

 struct {
   __in  u32 id;
   __in  u32 thresh;
   __in  s32 timeout;
   __out u32 value;
 };

NVHOST_IOCTL_CTRL_SYNCPT_READ_MAX

Identical to Linux driver.

 struct {
   __in  u32 id;
   __out u32 value;
 };

NVHOST_IOCTL_CTRL_GET_CONFIG

Gets configured settings. Not available in production mode.

 struct {
   __in char domain_str[0x41];       // "nv"
   __in char param_str[0x41];
   __out char config_str[0x101];
 };

NVHOST_IOCTL_CTRL_EVENT_SIGNAL

Signals an user event. Exclusive to the Switch.

 struct {
   __in u32 user_event_id;      // ranges from 0x00 to 0x3F
 };

NVHOST_IOCTL_CTRL_EVENT_WAIT

Waits on an event. If waiting fails, returns error code 0x05 (Timeout) and sets value to ((syncpt_id << 0x10) | 0x10000000).

Depending on threshold, an user_event_id may be returned for using with other event ioctls.

 struct {
   __in    u32 syncpt_id;
   __in    u32 threshold;
   __in    s32 timeout;
   __inout u32 value;           // in=user_event_id (ignored); out=syncpt_value or user_event_id
 };

NVHOST_IOCTL_CTRL_EVENT_WAIT_ASYNC

Waits on an event (async version). If waiting fails, returns error code 0x0B (BadValue).

Depending on threshold, an user_event_id may be returned for using with other event ioctls.

 struct {
   __in    u32 syncpt_id;
   __in    u32 threshold;
   __in    u32 timeout;
   __inout u32 value;           // in=user_event_id (ignored); out=syncpt_value or user_event_id
 };

NVHOST_IOCTL_CTRL_EVENT_REGISTER

Registers an user event. Exclusive to the Switch.

 struct {
   __in u32 user_event_id;      // ranges from 0x00 to 0x3F
 };

NVHOST_IOCTL_CTRL_EVENT_UNREGISTER

Unregisters an user event. Exclusive to the Switch.

 struct {
   __in u32 user_event_id;      // ranges from 0x00 to 0x3F
 };

NVHOST_IOCTL_CTRL_EVENT_KILL

Kills user events. Exclusive to the Switch.

 struct {
   __in u64 user_events;       // 64-bit bitfield where each bit represents one event
 };

/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
0x40100112 In 16 NVMAP_IOC_EXPORT_FOR_ARUID
0x40100113 In 16 NVMAP_IOC_IS_OWNED_BY_ARUID
0x40100114 In 16 NVMAP_IOC_REMOVE_EXPORT_FOR_ARUID

NVMAP_IOC_CREATE

Creates an nvmap object. Identical to Linux driver.

 struct {
   __in  u32 size;
   __out u32 handle;
 };

NVMAP_IOC_FROM_ID

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

 struct {
   __in  u32 id;
   __out u32 handle;
 };

NVMAP_IOC_ALLOC

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

 struct {
   __in u32 handle;
   __in u32 heapmask;
   __in u32 flags;    // (0=read-only, 1=read-write)
   __in u32 align;
   __in u8  kind;
   u8       pad[7];
   __inout u64 addr;
 };

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 {
   __in  u32 handle;
   u32       pad;
   __out u64 refcount;
   __out u32 size;
   __out u32 flags;    // 1=NOT_FREED_YET
 };

NVMAP_IOC_PARAM

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

 struct {
   __in  u32 handle;
   __in  u32 param;  // 1=SIZE, 2=ALIGNMENT, 3=BASE (returns error), 4=HEAP (always 0x40000000), 5=KIND, 6=COMPR (unused)
   __out u32 result;
 };

NVMAP_IOC_GET_ID

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

 struct {
   __out u32 id; //~0 indicates error
   __in  u32 handle;
 };

/dev/nvdisp-ctrl

Value Direction Size Description Notes
0x80040212 Out 4 TEGRA_DC_EXT_CONTROL_GET_NUM_OUTPUTS
0xC0140213 Inout 20 TEGRA_DC_EXT_CONTROL_GET_OUTPUT_PROPERTIES
0xC1100214 Inout 272 TEGRA_DC_EXT_CONTROL_GET_OUTPUT_EDID
0xC0040216 Inout 4 TEGRA_DC_EXT_CONTROL_GET_EXT_HPD_IN_EVENT
0xC0040217 Inout 4 TEGRA_DC_EXT_CONTROL_GET_EXT_HPD_OUT_EVENT
0xC0100218 Inout 16 TEGRA_DC_EXT_CONTROL_GET_VBLANK_HEAD0_EVENT
0xC0100219 Inout 16 TEGRA_DC_EXT_CONTROL_GET_VBLANK_HEAD1_EVENT
0xC0040220 Inout 4 TEGRA_DC_EXT_CONTROL_GET_UNK_EVENT

/dev/nvdisp-disp0, /dev/nvdisp-disp1

Value Direction Size Description Notes
0x40040201 In 4 TEGRA_DC_EXT_GET_WINDOW
0x40040202 In 4 TEGRA_DC_EXT_PUT_WINDOW
0xC4C80203 In 1224 TEGRA_DC_EXT_FLIP
0x80380204 Out 56 TEGRA_DC_EXT_GET_MODE
0x40380205 Out 56 TEGRA_DC_EXT_SET_MODE
0x430C0206 In 780 TEGRA_DC_EXT_SET_LUT
0x40010207 In 1 TEGRA_DC_EXT_ENABLE_DISABLE_CRC
0x80040208 Out 4 TEGRA_DC_EXT_GET_CRC
0x80040209 Out 4 TEGRA_DC_EXT_GET_HEAD_STATUS
0xC038020A Inout 56 TEGRA_DC_EXT_VALIDATE_MODE
0x4018020B In 24 TEGRA_DC_EXT_SET_CSC
0xC004020C Inout 4 TEGRA_DC_EXT_GET_VBLANK_SYNCPT
0x8040020D Out 64 TEGRA_DC_EXT_GET_UNDERFLOWS
0xC99A020E Inout 2458 TEGRA_DC_EXT_SET_CMU
0xC004020F Inout 4 TEGRA_DC_EXT_DPMS
0x80600210 Out 96 TEGRA_DC_EXT_GET_AVI_INFOFRAME
0x40600211 In 96 TEGRA_DC_EXT_SET_AVI_INFOFRAME
0xEBFC0215 Inout 11260 TEGRA_DC_EXT_GET_MODE_DB
0xC003021A Inout 3 TEGRA_DC_EXT_PANEL_GET_VENDOR_ID
0x803C021B Out 60 TEGRA_DC_EXT_GET_MODE2
0x403C021C In 60 TEGRA_DC_EXT_SET_MODE2
0xC03C021D Inout 60 TEGRA_DC_EXT_VALIDATE_MODE2
0xEF20021E Inout 12064 TEGRA_DC_EXT_GET_MODE_DB2
0xC004021F Inout 4 TEGRA_DC_EXT_GET_WINMASK

/dev/nvcec-ctrl

Value Direction Size Description Notes
0x40010300 In 1
0x40010301 In 1 NVCEC_CTRL_ENABLE
0x804C0302 Out 76 NVCEC_CTRL_GET_PADDR
0x40040303 In 4 NVCEC_CTRL_SET_LADDR
0xC04C0304 Inout 76 NVCEC_CTRL_WRITE
0xC04C0305 Inout 76 NVCEC_CTRL_READ
0x804C0306 Out 76 NVCEC_CTRL_GET_CONNECTION_STATUS
0x804C0307 Out 76 NVCEC_CTRL_GET_WRITE_STATUS

/dev/nvhdcp_up-ctrl

Value Direction Size Description Notes
0xC4880401 Inout 1160 TEGRAIO_NVHDCP_READ_M
0xC4880402 Inout 1160 TEGRAIO_NVHDCP_READ_S
0x40010403 In 1 TEGRAIO_NVHDCP_ON_OFF

/dev/nvdcutil-disp0, /dev/nvdcutil-disp1

Value Direction Size Description Notes
0x40010501 In 1 NVDCUTIL_SW_HOTPLUG_IN_OUT
0x40010502 In 1 NVDCUTIL_VIRTUAL_EDID_ON_OFF
0x42040503 In 1056 NVDCUTIL_VIRTUAL_EDID_SET_DATA
0x803C0504 Out 60 NVDCUTIL_GET_MODE
0x40010505 In 1 NVDCUTIL_TELEMETRY_TEST_ON_OFF

/dev/nvsched-ctrl

This is a customized scheduler device.

The way this device is exposed and configured is exclusive to the Switch, since other sources don't have an actual interface for the scheduler.

Value Direction Size Description Notes
0x00000601 - 0 #NVSCHED_CTRL_ENABLE
0x00000602 - 0 #NVSCHED_CTRL_DISABLE
0x40180603 In 24 #NVSCHED_CTRL_ADD_APPLICATION
0x40180604 In 24 #NVSCHED_CTRL_UPDATE_APPLICATION
0x40080605 In 8 #NVSCHED_CTRL_REMOVE_APPLICATION
0x80080606 Out 8 #NVSCHED_CTRL_GET_ID
0x80080607 Out 8 #NVSCHED_CTRL_ADD_RUNLIST
0x40180608 In 24 #NVSCHED_CTRL_UPDATE_RUNLIST
0x40100609 In 16 #NVSCHED_CTRL_LINK_RUNLIST
0x4010060A In 16 #NVSCHED_CTRL_UNLINK_RUNLIST
0x4008060B In 8 #NVSCHED_CTRL_REMOVE_RUNLIST
0x8001060C Out 1 #NVSCHED_CTRL_HAS_OVERRUN_EVENT
0x8010060D Out 16 #NVSCHED_CTRL_GET_NEXT_OVERRUN_EVENT
0x400C060E In 12 #NVSCHED_CTRL_PUT_CONDUCTOR_FLIP_FENCE
0x4008060F In 8 #NVSCHED_CTRL_DETACH_APPLICATION
0x40100610 In 16
0x40100611 In 16

NVSCHED_CTRL_ENABLE

Enables the scheduler.

NVSCHED_CTRL_DISABLE

Disables the scheduler.

NVSCHED_CTRL_ADD_APPLICATION

Adds a new application to the scheduler.

 struct {
   __in u64 application_id;
   __in u64 priority;
   __in u64 timeslice;
 };

NVSCHED_CTRL_UPDATE_APPLICATION

Updates the application parameters in the scheduler.

 struct {
   __in u64 application_id;
   __in u64 priority;
   __in u64 timeslice;
 };

NVSCHED_CTRL_REMOVE_APPLICATION

Removes the application from the scheduler.

 struct {
   __in u64 application_id;
 };

NVSCHED_CTRL_GET_ID

Returns the ID of the last scheduled object.

 struct {
   __out u64 id;
 };

NVSCHED_CTRL_ADD_RUNLIST

Creates a new runlist and returns it's ID.

 struct {
   __out u64 runlist_id;
 };

NVSCHED_CTRL_UPDATE_RUNLIST

Updates the runlist parameters in the scheduler.

 struct {
   __in u64 runlist_id;
   __in u64 priority;
   __in u64 timeslice;
 };

NVSCHED_CTRL_LINK_RUNLIST

Links a runlist to a given application in the scheduler.

 struct {
   __in u64 runlist_id;
   __in u64 application_id;
 };

NVSCHED_CTRL_UNLINK_RUNLIST

Unlinks a runlist from a given application in the scheduler.

 struct {
   __in u64 runlist_id;
   __in u64 application_id;
 };

NVSCHED_CTRL_REMOVE_RUNLIST

Removes the runlist from the scheduler.

 struct {
   __in u64 runlist_id;
 };

NVSCHED_CTRL_HAS_OVERRUN_EVENT

Returns a boolean to tell if the scheduler has an overrun event or not.

 struct {
   __out u8 has_overrun;
 };

NVSCHED_CTRL_GET_NEXT_OVERRUN_EVENT

Returns the overrun event's data from the scheduler.

 struct {
   __out u64 runlist_id;
   __out u64 debt;
 };

NVSCHED_CTRL_PUT_CONDUCTOR_FLIP_FENCE

Installs a fence swap event?

 struct {
   __in u32 fence_id;
   __in u32 fence_value;
   __in u32 swap_interval;
 };

NVSCHED_CTRL_DETACH_APPLICATION

Places the given application in detached state.

 struct {
   __in u64 application_id;
 };

/dev/nverpt-ctrl

Added in firmware version 3.0.0.

Value Direction Size Description Notes
0xC1280701 Inout 296 NVERPT_TELEMETRY_SUBMIT_DATA
0xCF580702 Inout 3928 NVERPT_TELEMETRY_SUBMIT_DATA_EX

/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).

Value Direction Size Description Notes
0x40044101 In 4 #NVGPU_AS_IOCTL_BIND_CHANNEL
0xC0184102 Inout 24 #NVGPU_AS_IOCTL_ALLOC_SPACE
0xC0104103 Inout 16 #NVGPU_AS_IOCTL_FREE_SPACE
0xC0184104 Inout 24 #NVGPU_AS_IOCTL_MAP_BUFFER
0xC0084105 Inout 8 #NVGPU_AS_IOCTL_UNMAP_BUFFER
0xC0284106 Inout 40 #NVGPU_AS_IOCTL_MAP_BUFFER_EX
0x40104107 In 16 #NVGPU_AS_IOCTL_INITIALIZE
0xC0404108 Inout 64 #NVGPU_AS_IOCTL_GET_VA_REGIONS
0x40284109 In 40 #NVGPU_AS_IOCTL_INITIALIZE_EX
0xC0??4114 Inout Variable #NVGPU_AS_IOCTL_REMAP

NVGPU_AS_IOCTL_BIND_CHANNEL

Identical to Linux driver.

 struct {
   __in u32 fd;
 };

NVGPU_AS_IOCTL_ALLOC_SPACE

This one reserves pages in the device address space.

 struct {
   __in u32 pages;
   __in u32 page_size;
   __in u32 flags;
   u32      pad;
   union {
     __out u64 offset;
     __in  u64 align;
   };
 };

NVGPU_AS_IOCTL_FREE_SPACE

This one frees pages from the device address space.

 struct {
   __in u64 offset;
   __in u32 pages;
   __in u32 page_size;
 };

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 {
   __in    u32 flags;        // bit0: fixed_offset, bit2: cacheable
   u32         pad;
   __in    u32 nvmap_handle;
   __inout u32 page_size;    // 0 means don't care
   union {
     __out u64 offset;
     __in  u64 align;
   };
 };

NVGPU_AS_IOCTL_MAP_BUFFER_EX

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

Unaligned size will cause a #Panic.

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

 struct {
   __in    u32 flags;          // bit0: fixed_offset, bit2: cacheable
   __in    u32 kind;           // -1 is default
   __in    u32 nvmap_handle;
   __inout u32 page_size;      // 0 means don't care
   __in    u64 buffer_offset;
   __in    u64 mapping_size;
   __inout   u64 offset;
 };

NVGPU_AS_IOCTL_UNMAP_BUFFER

Unmap a memory region from the device address space.

struct {
   __in u64 offset;
 };

NVGPU_AS_IOCTL_INITIALIZE

Nintendo's custom implementation of NVGPU_GPU_IOCTL_ALLOC_AS (unavailable).

 struct {
   __in u32 big_page_size;   // depends on GPU's available_big_page_sizes; 0=default
   __in s32 as_fd;           // ignored; passes 0
   __in u32 flags;           // ignored; passes 0
   __in u32 reserved;        // ignored; passes 0
 };

NVGPU_AS_IOCTL_GET_VA_REGIONS

Nintendo modified to get rid of pointer in struct.

 struct va_region {
   u64 offset;
   u32 page_size;
   u32 pad;
   u64 pages;
 };
 
 struct {
   u64         not_used;   // (contained output user ptr on linux, ignored)
   __inout u32 bufsize;    // forced to 2*sizeof(struct va_region)
   u32         pad;
   __out struct va_region regions[2];
 };

NVGPU_AS_IOCTL_INITIALIZE_EX

Nintendo's custom implementation of NVGPU_GPU_IOCTL_ALLOC_AS (unavailable) with extra params.

 struct {
   __in u32 big_page_size;   // depends on GPU's available_big_page_sizes; 0=default
   __in s32 as_fd;           // ignored; passes 0
   __in u32 flags;           // passes 0
   __in u32 reserved;        // ignored; passes 0
   __in u64 unk0;
   __in u64 unk1;
   __in u64 unk2;
 };

NVGPU_AS_IOCTL_REMAP

Nintendo's custom implementation of address space remapping.

 struct remap_entry {
   __in u16 flags;        // 0 or 4
   __in u16 kind;           
   __in u32 nvmap_handle;
   __in u32 padding;
   __in u32 offset;       // (alloc_space_offset >> 0x10)
   __in u32 pages;        // alloc_space_pages
 };

struct {
   __in struct remap_entry entries[];
};

/dev/nvhost-dbg-gpu

Returns NotSupported on Open unless nn::settings::detail::GetDebugModeFlag is set.

Value Direction Size Description Notes
0x40084401 In 8 NVGPU_DBG_GPU_IOCTL_BIND_CHANNEL
0xC0??4402 Inout Variable NVGPU_DBG_GPU_IOCTL_REG_OPS
0x40084403 In 8 NVGPU_DBG_GPU_IOCTL_EVENTS_CTRL
0x40044404 In 4 NVGPU_DBG_GPU_IOCTL_POWERGATE
0x40044405 In 4 NVGPU_DBG_GPU_IOCTL_SMPC_CTXSW_MODE
0x40044406 In 4 NVGPU_DBG_GPU_IOCTL_SUSPEND_RESUME_SM
0xC0184407 Inout 24 NVGPU_DBG_GPU_IOCTL_PERFBUF_MAP
0x40084408 In 8 NVGPU_DBG_GPU_IOCTL_PERFBUF_UNMAP
0x40084409 In 8 NVGPU_DBG_GPU_IOCTL_PC_SAMPLING
0x4008440A In 8 NVGPU_DBG_GPU_IOCTL_TIMEOUT
0x8008440B Out 8 NVGPU_DBG_GPU_IOCTL_GET_TIMEOUT
0x8004440C Out 4 NVGPU_DBG_GPU_IOCTL_GET_GR_CONTEXT_SIZE
0x0000440D None 0 NVGPU_DBG_GPU_IOCTL_GET_GR_CONTEXT Uses Ioctl3.

/dev/nvhost-prof-gpu

Returns NotSupported on Open unless nn::settings::detail::GetDebugModeFlag is set.

This device is identical to /dev/nvhost-dbg-gpu.

/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_FLUSH_L2
0x4008470D In 8 NVGPU_GPU_IOCTL_INVAL_ICACHE
0x4008470E In 8 NVGPU_GPU_IOCTL_SET_MMUDEBUG_MODE
0x4010470F In 16 NVGPU_GPU_IOCTL_SET_SM_DEBUG_MODE
0xC0084710 Inout 8 NVGPU_GPU_IOCTL_WAIT_FOR_PAUSE
0x80084711 Out 8 NVGPU_GPU_IOCTL_GET_TPC_EXCEPTION_EN_STATUS
0x80084712 Out 8 NVGPU_GPU_IOCTL_NUM_VSMS
0xC0044713 Inout 4 NVGPU_GPU_IOCTL_VSMS_MAPPING
0x80084714 Out 8 #NVGPU_GPU_IOCTL_ZBC_GET_ACTIVE_SLOT_MASK
0x80044715 Out 4
0x8018471A Out 24
0xC008471B Inout 8 NVGPU_GPU_IOCTL_GET_ERROR_CHANNEL_USER_DATA
0xC010471C Inout 16 NVGPU_GPU_IOCTL_GET_GPU_TIME
0xC108471D Inout 264 NVGPU_GPU_IOCTL_GET_CPU_TIME_CORRELATION_INFO

NVGPU_GPU_IOCTL_ZCULL_GET_CTX_SIZE

Returns the GPU's ZCULL context size. Identical to Linux driver.

struct {
   __out u32 size;
 };

NVGPU_GPU_IOCTL_ZCULL_GET_INFO

Returns GPU's ZCULL information. Identical to Linux driver.

struct {
   __out u32 width_align_pixels;
   __out u32 height_align_pixels;
   __out u32 pixel_squares_by_aliquots;
   __out u32 aliquot_total;
   __out u32 region_byte_multiplier;
   __out u32 region_header_size;
   __out u32 subregion_header_size;
   __out u32 subregion_width_align_pixels;
   __out u32 subregion_height_align_pixels;
   __out u32 subregion_count;
 };

NVGPU_GPU_IOCTL_ZBC_SET_TABLE

Sets the active ZBC table. Identical to Linux driver.

struct {
   __in u32 color_ds[4];
   __in u32 color_l2[4];
   __in u32 depth;
   __in u32 format;
   __in u32 type;         // 1=color, 2=depth
 };

NVGPU_GPU_IOCTL_ZBC_QUERY_TABLE

Queries the active ZBC table. Identical to Linux driver.

struct {
   __out u32 color_ds[4];
   __out u32 color_l2[4];
   __out u32 depth;
   __out u32 ref_cnt;
   __out u32 format;
   __out u32 type;
   __inout u32 index_size;
 };

NVGPU_GPU_IOCTL_GET_CHARACTERISTICS

Returns the GPU characteristics. Modified to return inline data instead of using a pointer.

 struct gpu_characteristics {
   u32 arch;                           // 0x120 (NVGPU_GPU_ARCH_GM200)
   u32 impl;                           // 0xB (NVGPU_GPU_IMPL_GM20B)
   u32 rev;                            // 0xA1 (Revision A1)
   u32 num_gpc;                        // 0x1
   u64 l2_cache_size;                  // 0x40000
   u64 on_board_video_memory_size;     // 0x0 (not used)
   u32 num_tpc_per_gpc;                // 0x2
   u32 bus_type;                       // 0x20 (NVGPU_GPU_BUS_TYPE_AXI)
   u32 big_page_size;                  // 0x20000
   u32 compression_page_size;          // 0x20000
   u32 pde_coverage_bit_count;         // 0x1B
   u32 available_big_page_sizes;       // 0x30000
   u32 gpc_mask;                       // 0x1
   u32 sm_arch_sm_version;             // 0x503 (Maxwell Generation 5.0.3?)
   u32 sm_arch_spa_version;            // 0x503 (Maxwell Generation 5.0.3?)
   u32 sm_arch_warp_count;             // 0x80
   u32 gpu_va_bit_count;               // 0x28
   u32 reserved;                       // NULL
   u64 flags;                          // 0x55
   u32 twod_class;                     // 0x902D (FERMI_TWOD_A)
   u32 threed_class;                   // 0xB197 (MAXWELL_B)
   u32 compute_class;                  // 0xB1C0 (MAXWELL_COMPUTE_B)
   u32 gpfifo_class;                   // 0xB06F (MAXWELL_CHANNEL_GPFIFO_A)
   u32 inline_to_memory_class;         // 0xA140 (KEPLER_INLINE_TO_MEMORY_B)
   u32 dma_copy_class;                 // 0xB0B5 (MAXWELL_DMA_COPY_A)
   u32 max_fbps_count;                 // 0x1
   u32 fbp_en_mask;                    // 0x0 (disabled)
   u32 max_ltc_per_fbp;                // 0x2
   u32 max_lts_per_ltc;                // 0x1
   u32 max_tex_per_tpc;                // 0x0 (not supported)
   u32 max_gpc_count;                  // 0x1
   u32 rop_l2_en_mask_0;               // 0x21D70 (fuse_status_opt_rop_l2_fbp_r)
   u32 rop_l2_en_mask_1;               // 0x0
   u64 chipname;                       // 0x6230326D67 ("gm20b")
   u64 gr_compbit_store_base_hw;       // 0x0 (not supported)
 };

 struct {
   __inout u64 gpu_characteristics_buf_size;   // must not be NULL, but gets overwritten with 0xA0=max_size
   __in    u64 gpu_characteristics_buf_addr;   // ignored, but must not be NULL
   __out struct gpu_characteristics gc;
 };

NVGPU_GPU_IOCTL_FLUSH_L2

Flushes the GPU L2 cache.

 struct {
   __in u32 flush;          // l2_flush | l2_invalidate << 1 | fb_flush << 2
   u32      reserved;
 };

NVGPU_GPU_IOCTL_ZBC_GET_ACTIVE_SLOT_MASK

Returns the mask value for a ZBC slot.

 struct {
   __out u32 slot;       // always 0x07
   __out u32 mask;
 };

Channels

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

Path Name
/dev/nvhost-gpu
/dev/nvhost-vic Video Image Compositor
/dev/nvhost-nvdec Video Decoder
/dev/nvhost-nvjpg JPEG Decoder

Channel Ioctls

Value Size Description Notes
0xC0??0001 Variable NVHOST_IOCTL_CHANNEL_SUBMIT Seen on 1.0.0.
0xC0080002 8 NVHOST_IOCTL_CHANNEL_GET_SYNCPOINT Seen on 1.0.0.
0xC0080003 8 NVHOST_IOCTL_CHANNEL_GET_WAITBASE Seen on 1.0.0.
0xC0080004 8 NVHOST_IOCTL_CHANNEL_SET_TIMEOUT_EX Seen on 1.0.0. Stubbed; does a debug print and returns 0.
0x40040007 4 NVHOST_IOCTL_CHANNEL_SET_SUBMIT_TIMEOUT Seen on 1.0.0.
0x40080008 8 NVHOST_IOCTL_CHANNEL_SET_CLK_RATE Seen on 1.0.0.
0xC0??0009 Variable NVHOST_IOCTL_CHANNEL_MAP_CMD_BUFFER Seen on 1.0.0.
0xC0??000A Variable NVHOST_IOCTL_CHANNEL_UNMAP_CMD_BUFFER Seen on 1.0.0.
0x00000013 0 Seen on 1.0.0. This one sets a u32, and bool based on input.
0xC0080014 NVHOST_IOCTL_CHANNEL_GET_CLK_RATE Seen on 1.0.0.
0x40044801 4 #NVGPU_IOCTL_CHANNEL_SET_NVMAP_FD Seen on 1.0.0.
0x40044803 4 NVGPU_IOCTL_CHANNEL_SET_TIMEOUT Seen on 1.0.0.
0x40084805 8 #NVGPU_IOCTL_CHANNEL_ALLOC_GPFIFO Seen on 1.0.0.
0x40184806 NVGPU_IOCTL_CHANNEL_WAIT Seen on 1.0.0.
0xC0044807 4 NVGPU_IOCTL_CHANNEL_CYCLE_STATS Seen on 1.0.0.
0xC0??4808 Variable #NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO Seen on 1.0.0.
0xC0104809 16 #NVGPU_IOCTL_CHANNEL_ALLOC_OBJ_CTX Seen on 1.0.0.
0x4008480A NVHOST_IOCTL_CHANNEL_FREE_OBJ_CTX Seen on 1.0.0.
0xC010480B 16 #NVGPU_IOCTL_CHANNEL_ZCULL_BIND Seen on 1.0.0.
0xC018480C 24 #NVGPU_IOCTL_CHANNEL_SET_ERROR_NOTIFIER Seen on 1.0.0.
0x4004480D 4 #NVGPU_IOCTL_CHANNEL_SET_PRIORITY Seen on 1.0.0.
0x0000480E 0 #NVGPU_IOCTL_CHANNEL_ENABLE Seen on 1.0.0.
0x0000480F 0 #NVGPU_IOCTL_CHANNEL_DISABLE Seen on 1.0.0.
0x00004810 0 #NVGPU_IOCTL_CHANNEL_PREEMPT Seen on 1.0.0.
0x00004811 0 #NVGPU_IOCTL_CHANNEL_FORCE_RESET Seen on 1.0.0.
0x40084812 8 #NVGPU_IOCTL_CHANNEL_EVENT_ID_CONTROL Seen on 1.0.0.
0xC0104813 16 NVGPU_IOCTL_CHANNEL_CYCLE_STATS_SNAPSHOT Seen on 1.0.0.
0x80804816 128 NVGPU_IOCTL_CHANNEL_GET_ERROR_INFO Seen on 1.0.0.
0xC0104817 16 #NVGPU_IOCTL_CHANNEL_GET_ERROR_NOTIFICATION Seen on 1.0.0.
0x40204818 32 #NVGPU_IOCTL_CHANNEL_ALLOC_GPFIFO_EX Seen on 1.0.0.
0xC0??4819 Variable #NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO_RETRY Seen on 1.0.0.
0xC020481A 32 #NVGPU_IOCTL_CHANNEL_ALLOC_GPFIFO_EX2 Seen on 1.0.0.
0xC018481B 24 Uses Ioctl2.
0xC018481C 24 Uses Ioctl2.
0x40084714 8 NVGPU_IOCTL_CHANNEL_SET_USER_DATA Sets an unknown user context address. Seen on 1.0.0.
0x80084715 8 NVGPU_IOCTL_CHANNEL_GET_USER_DATA Gets an unknown user context address. Seen on 1.0.0.

NVGPU_IOCTL_CHANNEL_SET_NVMAP_FD

Binds a nvmap object to this channel. Identical to Linux driver.

This ioctl is a no-op in the Linux driver, not sure about Switch?

 struct {
   __in u32 nvmap_fd;
 };

NVGPU_IOCTL_CHANNEL_ALLOC_GPFIFO

Allocates gpfifo entries. Identical to Linux driver.

 struct {
   __in u32 num_entries;
   __in u32 flags;
 };

NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO

Submits a gpfifo object. Modified to take inline entry objects instead of a pointer.

 struct fence {
   u32 syncpt_id;
   u32 syncpt_value;
 };
 
 struct gpfifo_entry {
   u64 entry;                            // gpu_iova | (unk_2bits << 40) | (size << 42) | (unk_flag << 63)
 };
 
 struct {
   __in    u64 gpfifo;                      // (ignored) pointer to gpfifo fence structs
   __in    u32 num_entries;                 // number of fence objects being submitted
   __in    u32 flags;
   __inout struct fence fence_out;         // returned new fence object for others to wait on
   __in    struct gpfifo_entry entries[];  // depends on num_entries
 };

NVGPU_IOCTL_CHANNEL_ALLOC_OBJ_CTX

Allocates a graphics context object. Modified to ignore object's ID.

You can only have one object context allocated at a time. You must have bound an address space before using this.

 struct {
   __in  u32 class_num;    // 0x902D=2d, 0xB197=3d, 0xB1C0=compute, 0xA140=kepler, 0xB0B5=DMA, 0xB06F=channel_gpfifo
   __in  u32 flags;        // bit0: LOCKBOOST_ZERO
   __out u64 obj_id;       // (ignored) used for FREE_OBJ_CTX ioctl, which is not supported
 };

NVGPU_IOCTL_CHANNEL_ZCULL_BIND

Binds a ZCULL context to the channel. Identical to Linux driver.

struct {
   __in u64 gpu_va;
   __in u32 mode;         // 0=global, 1=no_ctxsw, 2=separate_buffer, 3=part_of_regular_buf
   __in u32 padding;
 };

NVGPU_IOCTL_CHANNEL_SET_ERROR_NOTIFIER

Initializes the error notifier for this channel. Unlike for the Linux kernel, the Switch driver cannot write to an arbitrary userspace buffer. Thus new ioctls have been introduced to fetch the error information rather than using a shared memory buffer.

 struct {
   __in u64 offset;  // ignored
   __in u64 size;    // ignored
   __in u32 mem;     // must be non-zero to initialize, zero to de-initialize
   __in u32 padding; // ignored
 };

NVGPU_IOCTL_CHANNEL_SET_PRIORITY

Change channel's priority. Identical to Linux driver.

 struct {
   __in u32 priority;    // 0x32 is low, 0x64 is medium and 0x96 is high
 };

NVGPU_IOCTL_CHANNEL_ENABLE

Enables the current channel. Identical to Linux driver.

NVGPU_IOCTL_CHANNEL_DISABLE

Disables the current channel. Identical to Linux driver.

NVGPU_IOCTL_CHANNEL_PREEMPT

Clears the FIFO pipe for this channel. Identical to Linux driver.

NVGPU_IOCTL_CHANNEL_FORCE_RESET

Forces the channel to reset. Identical to Linux driver.

NVGPU_IOCTL_CHANNEL_EVENT_ID_CONTROL

Controls event notifications.

 struct {
   __in u32 cmd;    // 0=disable, 1=enable, 2=clear
   __in u32 id;     // same id's as for #QueryEvent
 };

NVGPU_IOCTL_CHANNEL_GET_ERROR_NOTIFICATION

Returns the current error notification caught by the error notifier. Exclusive to the Switch.

Despite being marked as inout this is all output.

 struct {
   __out u64 timestamp;    // fetched straight from armGetSystemTick
   __out u32 info32;       // error code
   __out u16 info16;       // additional error info
   __out u16 status;       // always 0xFFFF
 };

NVGPU_IOCTL_CHANNEL_ALLOC_GPFIFO_EX

Allocates gpfifo entries with additional parameters. Exclusive to the Switch.

 struct {
   __in u32 num_entries;
   __in u32 flags;
   __in u32 unk0;            // 1 works
   __in u32 unk1;
   __in u32 unk2;
   __in u32 unk3;
   __in u32 unk4;
   __in u32 unk5;
 };

NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO_RETRY

Submits a gpfifo object (async version). Exclusive to the Switch.

 struct {
   u64 __gpfifo;                     // in (pointer to gpfifo fence structs; ignored)
   u32 __num_entries;                // in (number of fence objects being submitted)
   u32 __flags;                      // in
   struct fence        __fence_out;  // out (returned new fence object for others to wait on)
   struct gpfifo_entry __entries[];  // in (depends on __num_entries)
 };

NVGPU_IOCTL_CHANNEL_ALLOC_GPFIFO_EX2

Allocates gpfifo entries with additional parameters and returns a fence. Exclusive to the Switch.

 struct {
   u32 __num_entries;         // in
   u32 __flags;               // in
   u32 __unk0;                // in (1 works)
   struct fence __fence_out;  // out
   u32 __unk1;                // in
   u32 __unk2;                // in
   u32 __unk3;                // in
 };

nvmemp

NVIDIA memory profiler (this service is not available on retail units). /dev/nvhost-ctrl sends the ioctl NVHOST_IOCTL_CTRL_GET_CONFIG to check the config "nv!NV_MEMORY_PROFILER". If config_str returns "1", the applications attempts to talk to use nvmemp.

Cmd Name
0 Open
1 GetPid

nvdrvdbg

This is "nns::nvdrv::INvDrvDebugFSServices".

Cmd Name
0 #OpenLog
1 #CloseLog
2 #ReadLog
3
4

OpenLog

Takes process handle. Returns an fd.

CloseLog

Takes fd and closes it.

ReadLog

Takes fd and reads log into a type-6 buffer.

nvgem:c

This is "nv::gemcontrol::INvGemControl".

Cmd Name
0
1
2
3
4
[?-4.1.0] 5
6
7 [3.0.0+]

nvgem:cd

This is "nv::gemcoredump::INvGemCoreDump".

Cmd Name
0
1
2
3 [8.0.0+]
4 [8.0.0+]

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
0x30003 FileOperationFailed
0x30004 DirOperationFailed
0x3000F IoctlFailed
0x30010 AccessDenied
0x30013 FileNotFound
0xA000E ModuleNotPresent

Panic

In some cases, a panic may occur. NV forces a crash by doing:

(void *)0 = 0xCAFE;

End result is that the system hangs with a white-screen.

Gpfifo Panic

When the gpfifo data in the gpu_va buffers specified by the submitted gpfifo entries is invalid(?), eventually the user-process will be force-terminated after using the submit-gpfifo ioctl. It's unknown how exactly this is done.