RPC Message Format
GSP RPC Message Format Specification
Overview
The GSP firmware uses a dispatcher-based RPC system with two dispatchers:
- Primary (0x057A1AC0): ALLOC, FREE, MAP, UNMAP, PIN, UNPIN, SCHEDULE, YIELD, NOTIFY, BAR_TRAP, MIGRATE, DEBUG
- Secondary (0x04ED39DC): Branch-based dispatch for all 11 types
Primary Dispatcher Call Convention
Entry Point
FUN_ram_057a1ac0(
uint32_t rpc_type, // param_1: RPC type (0x01-0x0C)
uint8_t flags_a, // param_2
uint8_t flags_b, // param_3
uint8_t flags_c, // param_4
uint32_t *out_subcmd_id,// param_5: Returns sub-command ID
uint8_t *out_a, // param_6: Echoes flags_b
uint8_t *out_b, // param_7: Echoes flags_a
uint8_t *out_c // param_8: Echoes flags_c
) -> int64_t
RPC Type to Sub-Command Mapping
The primary dispatcher validates RPC type, then indexes into the 32-entry jump table at 0x057A3AD8.
| RPC Type | Name | Subcmd Range | Notes |
|---|---|---|---|
| 0x01 | ALLOC | 0-31 | Uses 0x057E94EC main |
| 0x02 | FREE | 0-31 | |
| 0x03 | MAP | — | Uses secondary dispatcher |
| 0x04 | UNMAP | 0-31 | Primary + secondary |
| 0x05 | PIN | — | Uses secondary dispatcher |
| 0x06 | UNPIN | — | Uses secondary dispatcher |
| 0x07 | SCHEDULE | 0-31 | Uses 0x051EFBF4 main |
| 0x08 | YIELD | — | Uses secondary dispatcher |
| 0x09 | NOTIFY | — | Uses secondary dispatcher |
| 0x0A | BAR_TRAP | — | Uses 0x04CB8188 |
| 0x0B | MIGRATE | 0-15 x2 | Dual jump tables |
| 0x0C | DEBUG | — | Unimplemented |
Sub-Command Descriptor (Returned by Jump Table Handlers)
Each sub-command handler at the jump table returns:
<syntaxhighlight lang="c">typedef struct {
uint32_t subcmd_id; // Constant ID (e.g., 0x10, 0x14, 0x40) uint8_t echo_flags_b; // Copy of input flags_b uint8_t echo_flags_a; // Copy of input flags_a uint8_t echo_flags_c; // Copy of input flags_c
} __attribute__((packed)) subcmd_descriptor_t;</syntaxhighlight> Example: Subcmd 3 (0x057A1BCC)
<syntaxhighlight lang="c">// Returns ID = 0x10
- out_subcmd_id = 0x10;
- out_a = flags_b;
- out_b = flags_a;
- out_c = flags_c;
return 0;</syntaxhighlight> Example: Subcmd 0 (0x057A1DB4)
<syntaxhighlight lang="c">// Returns ID = 0x40
- out_subcmd_id = 0x40;
- out_a = flags_b;
- out_b = flags_a;
- out_c = flags_c;
return 0;</syntaxhighlight>
Secondary Dispatcher Call Convention
Entry Point
FUN_ram_04ed39dc(rpc_message_t *msg) -> int64_t
Message Structure (Inferred)
<syntaxhighlight lang="c">typedef struct {
uint32_t rpc_type; // 0x01-0x0B uint32_t sub_type; // Sub-operation code uint64_t payload_ptr; // Pointer to RPC-specific payload uint32_t payload_size; // Size of payload uint32_t flags; // Control flags uint64_t context; // Opaque context uint32_t sequence; // Sequence number uint32_t reserved;
} __attribute__((packed)) rpc_message_t;</syntaxhighlight>
Branch-Based Dispatch
Secondary dispatcher uses bgeu/bltu branches on rpc_type register:
# Pseudocode if (rpc_type >= 0x0C) goto error; switch(rpc_type): case 0x03: call MAP_handler_A; case 0x04: call UNMAP_handler_A; case 0x05: call PIN_handler_A (0x04ED34B8); case 0x06: call UNPIN_handler_A; case 0x07: call SCHEDULE_handler_A; case 0x08: call YIELD_handler_A; case 0x09: call NOTIFY_handler_A; case 0x0A: call BAR_TRAP_handler (0x057675B7);
RPC-Specific Payloads
ALLOC (0x01) - Via 0x057E94EC
<syntaxhighlight lang="c">typedef struct {
uint64_t size; // Allocation size in bytes uint32_t type; // Memory type (VRAM, sysmem, etc.) uint32_t alignment; // Alignment requirement uint64_t va_hint; // Virtual address hint uint32_t flags; // CACHE_COHERENT, UNCACHED, etc. uint32_t pid; // Process ID uint32_t vf_id; // VF ID (for vGPU) uint32_t reserved; uint64_t *out_handle; // Output: allocation handle uint64_t *out_va; // Output: mapped virtual address uint64_t *out_pa; // Output: physical address
} alloc_payload_t;</syntaxhighlight>
MAP (0x03) - Handlers 0x05766AB7 / 0x05778A37
<syntaxhighlight lang="c">typedef struct {
uint64_t handle; // Allocation handle from ALLOC uint64_t va; // Target virtual address uint64_t size; // Map size uint32_t prot; // PROT_READ|PROT_WRITE|PROT_EXEC uint32_t flags; // MAP_FIXED, MAP_SHARED, etc. uint32_t vf_id; // Target VF uint32_t reserved;
} map_payload_t;</syntaxhighlight>
PIN (0x05) - Handler 0x04ED34B8
<syntaxhighlight lang="c">typedef struct {
uint64_t handle; // Allocation handle uint64_t offset; // Offset within allocation uint64_t size; // Size to pin uint32_t vf_id; // Target VF uint32_t flags; // PIN_WRITE, PIN_READ, PIN_LONGTERM uint64_t *out_dma_addr; // Output: DMA address for device
} pin_payload_t;</syntaxhighlight>
SCHEDULE (0x07) - Via 0x051EFBF4 / 0x05767F37
<syntaxhighlight lang="c">typedef struct {
uint32_t vf_id; // VF to schedule uint32_t priority; // Scheduling priority uint64_t time_slice_ns; // Time slice in nanoseconds uint32_t flags; // PREEMPTIBLE, REALTIME, etc. uint32_t reserved;
} schedule_payload_t;</syntaxhighlight>
BAR_TRAP (0x0A) - Handler 0x04CB8188
<syntaxhighlight lang="c">typedef struct {
uint32_t bar_index; // BAR number (0-5) uint32_t trap_type; // READ, WRITE, ATOMIC uint64_t offset; // Offset within BAR uint64_t value; // Value for writes uint32_t size; // Access size (1,2,4,8) uint32_t vf_id; // Trapping VF uint64_t *out_value; // Output: read value
} bar_trap_payload_t;</syntaxhighlight>
MIGRATE (0x0B) - Dual Jump Tables
<syntaxhighlight lang="c">typedef struct {
uint32_t phase; // 0=prepare, 1=transfer, 2=commit, 3=cleanup uint32_t subcmd; // Sub-command index (0-15 for each table) uint64_t src_vf; // Source VF uint64_t dst_vf; // Destination VF uint64_t data_ptr; // Migration data buffer uint64_t data_size; // Buffer size uint32_t flags; // LIVE, POSTCOPY, etc. uint32_t reserved;
} migrate_payload_t;</syntaxhighlight>
Wire Format (Host → GSP)
Legacy BAR0 mailbox format — not used by the guest driver. The current msgq header/element facts are in the note at the top of this page.
Message Header (64 bytes)
<syntaxhighlight lang="c">typedef struct {
uint32_t magic; // 0x47535052 ("GSPR")
uint32_t version; // Protocol version (1)
uint32_t rpc_type; // 0x01-0x0C
uint32_t sequence; // Monotonic sequence
uint64_t timestamp_ns; // Submission timestamp
uint32_t payload_size; // Size of payload
uint32_t flags; // MSG_SYNC, MSG_ASYNC, MSG_NOREPLY
uint64_t correlation_id;// For async matching
uint64_t reserved[3]; // Padding to 64 bytes
} __attribute__((packed)) rpc_header_t;</syntaxhighlight>
Complete Message
+------------------+ | rpc_header_t | 64 bytes +------------------+ | payload (varies) | payload_size bytes +------------------+ | padding to 256B | (alignment) +------------------+
Response Format
Synchronous Response
<syntaxhighlight lang="c">typedef struct {
int64_t status; // 0 = success, negative = error uint32_t rpc_type; // Echo of request uint32_t sequence; // Echo of request uint64_t timestamp_ns; // Completion timestamp uint32_t payload_size; // Response payload size uint32_t reserved;
} __attribute__((packed)) rpc_response_header_t;</syntaxhighlight>
Error Codes
| Code | Name | Description |
|---|---|---|
| 0 | OK | Success |
| -1 (0xFFFF) | EPERM | Permission denied |
| -2 (0xFFFE) | ENOENT | Not found |
| -3 (0xFFFD) | EINVAL | Invalid argument |
| -6 (0xFFFA) | ENODEV | No such device |
| -12 (0xFFF4) | ENOMEM | Out of memory |
| -16 (0xFFEE) | EBUSY | Resource busy |
| -22 (0xFFEA) | EINVAL | Invalid argument |
| -28 (0xFFE4) | ENOSPC | No space left |
| -37 (0xFFDB) | ENOLCK | No locks available |
| -56 (0xFFC8) | EBADMSG | Bad message |
| -84 (0xFFAC) | EOVERFLOW | Value too large |
| -90 (0xFFA6) | ENOSTR | Not a stream |
| -91 (0xFFA5) | ENODATA | No data available |
| -94 (0xFFA2) | ENOSR | Out of streams resources |
| -97 (0xFF9F) | EPROTO | Protocol error |
| -111 (0xFF91) | ETIMEDOUT | Connection timed out |
Kernel Client Implementation
Message Builder
<syntaxhighlight lang="c">static int gsp_rpc_send(gsp_client_t *client, uint32_t rpc_type,
void *payload, size_t payload_size,
void *response, size_t *response_size) {
rpc_header_t hdr = {.magic = 0x47535052,.version = 1,.rpc_type = rpc_type,.sequence = atomic_inc(&client->seq),.timestamp_ns = ktime_get_ns,.payload_size = payload_size,.flags = MSG_SYNC,
};
// Build complete message
uint8_t msg[256];
memcpy(msg, &hdr, sizeof(hdr));
memcpy(msg + 64, payload, payload_size);
// Submit to GSP doorbell
return gsp_doorbell_ring(client->gsp, msg, sizeof(msg));
}</syntaxhighlight>
Doorbell Mechanism
<syntaxhighlight lang="c">// GSP doorbell register (PCIe BAR0 + offset)
- define GSP_DOORBELL_OFFSET 0x1000
static void gsp_doorbell_ring(gsp_device_t *gsp, void *msg, size_t len) {
// Copy message to shared memory ring // Ring GSP doorbell writel(1, gsp->bar0 + GSP_DOORBELL_OFFSET);
}</syntaxhighlight>
Async Completion
Notification Mechanism
<syntaxhighlight lang="c">typedef struct {
uint32_t rpc_type; uint32_t sequence; int64_t status; uint64_t timestamp_ns; uint32_t payload_size; uint32_t reserved;
} async_completion_t;
// Delivered via MSI-X or GSP notification queue</syntaxhighlight>
Reference
- Primary Dispatcher: 0x057A1AC0
- Secondary Dispatcher: 0x04ED39DC
- Jump Table: 0x057A3AD8 (32 entries)
- RPC Type Jump Table: 0x059BFEB0 (12 types)