blob: 7329c0b8f9e441446ed45c2a56ee910750152e1e (
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
|
/*
* GSP-RM Emulation (physical-path) for Host-Side vGPU
*
* Emulates the GSP-RM firmware's msgq-based RPC channel for a guest driver
* that believes it is driving a real physical GPU. The guest driver:
* - boots the "GSP" (falcon stages emulated in gsp_emulation.c)
* - programs libos init args address into GSP MAILBOX0/1
* - expects GSP-RM to msgqInit the status queue in *guest system memory*
* (shared command/status queue buffer described by GSP_ARGUMENTS_CACHED)
* - polls the status queue for NV_VGPU_MSG_EVENT_GSP_INIT_DONE and then
* issues the RM RPC sequence on the command queue.
*
* Since there is no real GSP engine, this module performs the "virtual DMA"
* on behalf of the device using vfio_dma_rw() (CPU copies through the VFIO
* container's IOMMU mappings, IOVA == guest physical address).
*/
#ifndef _GSP_RM_EMULATION_H_
#define _GSP_RM_EMULATION_H_
#include <linux/types.h>
#include "nvidia-vgpu-vfio.h"
struct gsp_emu_context;
/* Wire constants (from NVIDIA OpenRM 570.144 msgq/rpc headers - the guest
* driver is the 570.144 stock runfile, whose GSP_MSG_QUEUE_ELEMENT has NO
* MCTP/NVDM transport headers: authTag[16]+aad[16]+checkSum+seqNum+elemCount
* +rpc@0x30). */
#define GSPRM_MSGQ_VERSION 0
#define GSPRM_MSGQ_FLAGS_SWAP_RX 1
#define GSPRM_RPC_SIGNATURE 0x43505256 /* NV_VGPU_MSG_SIGNATURE_VALID */
#define GSPRM_RPC_HEADER_VERSION 0x03000000 /* MAJOR_TOT(3)<<24|MINOR_TOT(0)<<16 */
/* RPC function/event numbers (rpc_global_enums.h) */
#define GSPRM_RPC_FUNC_SET_GUEST_SYSTEM_INFO 1
#define GSPRM_RPC_FUNC_ALLOC_ROOT 2
#define GSPRM_RPC_FUNC_GET_GSP_STATIC_INFO 65
#define GSPRM_RPC_FUNC_GSP_SET_SYSTEM_INFO 72
#define GSPRM_RPC_FUNC_SET_REGISTRY 73
#define GSPRM_RPC_FUNC_CONTINUATION_RECORD 71
#define GSPRM_RPC_FUNC_GSP_RM_CONTROL 76
#define GSPRM_RPC_FUNC_FREE 10
#define GSPRM_RPC_EVENT_GSP_INIT_DONE 0x1001
/* rpc_set_guest_system_info_v03_00: version fields the driver reads back
* from the reply to negotiate the RPC interface version (ipVersion). */
#define GSPRM_SET_GUEST_INFO_SIZE 0x324
#define GSPRM_VGX_VERSION_MAJOR 0x29
#define GSPRM_VGX_VERSION_MINOR 0x0C
/* "RMARGS" packed big-endian into u64 by _kgspGenerateInitArgId() */
#define GSPRM_LIBOS_ID_RMARGS 0x524D41524753ULL
#define GSPRM_MAX_LIBOS_REGIONS 32
#define GSPRM_QUEUE_ELEMENT_SIZE 0x1000
#define GSPRM_STATUS_QUEUE_SIZE 0x40000
/* msgqTxHeader (msgq_priv.h) */
struct gsprm_msgq_tx_header {
u32 version;
u32 size;
u32 msgSize;
u32 msgCount;
u32 writePtr;
u32 flags;
u32 rxHdrOff;
u32 entryOff;
};
/* rpc_message_header_v03_00 (g_rpc-message-header.h) */
struct gsprm_rpc_header {
u32 header_version;
u32 signature;
u32 length;
u32 function;
u32 rpc_result;
u32 rpc_result_private;
u32 sequence;
u32 spare; /* rpc_message_rpc_union_field_v (spare/cpuRmGfid) */
};
/* LibosMemoryRegionInitArgument (libos_init_args.h) - natural alignment, 32B */
struct gsprm_libos_region {
u64 id8;
u64 pa;
u64 size;
u8 kind;
u8 loc;
u8 pad[6];
};
/* MESSAGE_QUEUE_INIT_ARGUMENTS (gsp_init_args.h), x86_64 NvLength=u64 */
struct gsprm_mq_init_args {
u64 sharedMemPhysAddr;
u32 pageTableEntryCount;
u32 pad0;
u64 cmdQueueOffset;
u64 statQueueOffset;
u64 queueElementHdrSize;
u64 queueElementSizeMin;
u64 queueElementSizeMax;
u32 queueHeaderAlign;
u32 queueElementAlign;
};
struct gsp_rm_emu {
struct nv_vgpu_device *vgpu;
bool parsed; /* queue chain parsed + status queue linked */
bool active;
unsigned long last_parse_retry; /* jiffies of last on_booter_done retry */
u64 libos_args_gpa; /* from GSP MAILBOX0/1 */
u64 gsp_args_gpa; /* RMARGS region pa */
/* queue buffer description (from GSP_ARGUMENTS_CACHED) */
struct gsprm_mq_init_args mq;
u64 *ptes; /* pageTableEntryCount guest-phys addrs */
/* computed queue geometry. cmd_off/stat_off are offsets into the shared
* buffer (linear); GPAs must be computed per-access via the page table
* (buffer is NV_MEMORY_NONCONTIGUOUS). */
u64 cmd_off;
u64 stat_off;
u64 cmd_gpa; /* GPA of command queue base (diagnostic) */
u64 stat_gpa; /* GPA of status queue base (diagnostic) */
u32 cmd_size; /* bytes */
u32 stat_size; /* bytes */
u32 cmd_msgcount;
u32 stat_msgcount;
u32 entry_off; /* 0x1000 (msgq entryOff, both queues) */
/* GSP-side cursors */
u32 cmd_read; /* elements consumed from command queue */
u32 stat_write; /* elements written to status queue */
u32 stat_seq; /* status record sequence numbers */
bool init_done_sent;
/* stats */
u64 rpcs_seen;
u64 rpcs_replied;
u64 unknown_rpcs;
};
int gsp_rm_emu_init(struct nv_vgpu_device *vgpu, struct gsp_emu_context *ctx);
void gsp_rm_emu_fini(struct gsp_emu_context *ctx);
void gsp_rm_emu_reset(struct gsp_emu_context *ctx);
void gsp_rm_emu_on_booter_done(struct gsp_emu_context *ctx);
void gsp_rm_emu_poll(struct gsp_emu_context *ctx);
#endif /* _GSP_RM_EMULATION_H_ */
|