summaryrefslogtreecommitdiffstats
path: root/wiki/RPC-Message-Format.md
blob: baec760b124a3a6d4f5b3410f9775cbb88eda6ad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
# GSP RPC Message Format Specification

> **Historical document — superseded.** This page describes the legacy BAR0
> mailbox RPC model: the 64-byte `GSPR` magic header and the 12-type model
> below are **not** the path the guest driver uses. The live GSP-RM path is a
> message queue in guest system memory with 4 KB queue elements and a 32-byte
> RPC header (signature `0x43505256`, header version `0x03000000`); functions
> are a flat enum (`SET_GUEST_SYSTEM_INFO` 1, `FREE` 10,
> `GET_GSP_STATIC_INFO` 65, `GSP_RM_CONTROL` 76, `GSP_RM_ALLOC` 103, ...).
> Canonical documentation:
> [`../docs/03-architecture/03-gsp-and-gsp-rm.md`](../docs/03-architecture/03-gsp-and-gsp-rm.md)
> and [`../docs/03-architecture/06-host-module-and-hybrid-model.md`](../docs/03-architecture/06-host-module-and-hybrid-model.md).

## 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:
```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;
```

**Example: Subcmd 3 (0x057A1BCC)**
```c
// Returns ID = 0x10
*out_subcmd_id = 0x10;
*out_a = flags_b;
*out_b = flags_a;
*out_c = flags_c;
return 0;
```

**Example: Subcmd 0 (0x057A1DB4)**
```c
// Returns ID = 0x40
*out_subcmd_id = 0x40;
*out_a = flags_b;
*out_b = flags_a;
*out_c = flags_c;
return 0;
```

## Secondary Dispatcher Call Convention

### Entry Point
```
FUN_ram_04ed39dc(rpc_message_t *msg) -> int64_t
```

### Message Structure (Inferred)
```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;
```

### Branch-Based Dispatch
Secondary dispatcher uses `bgeu`/`bltu` branches on `rpc_type` register:
```assembly
# 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
```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;
```

### MAP (0x03) - Handlers 0x05766AB7 / 0x05778A37
```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;
```

### PIN (0x05) - Handler 0x04ED34B8
```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;
```

### SCHEDULE (0x07) - Via 0x051EFBF4 / 0x05767F37
```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;
```

### BAR_TRAP (0x0A) - Handler 0x04CB8188
```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;
```

### MIGRATE (0x0B) - Dual Jump Tables
```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;
```

## 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)
```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;
```

### Complete Message
```
+------------------+
| rpc_header_t     |  64 bytes
+------------------+
| payload (varies) |  payload_size bytes
+------------------+
| padding to 256B  |  (alignment)
+------------------+
```

## Response Format

### Synchronous Response
```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;
```

### 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
```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));
}
```

### Doorbell Mechanism
```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);
}
```

## Async Completion

### Notification Mechanism
```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
```

---

## Reference
- Primary Dispatcher: 0x057A1AC0
- Secondary Dispatcher: 0x04ED39DC
- Jump Table: 0x057A3AD8 (32 entries)
- RPC Type Jump Table: 0x059BFEB0 (12 types)