1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 */
5
6#ifndef _NE_PCI_DEV_H_
7#define _NE_PCI_DEV_H_
8
9#include <linux/atomic.h>
10#include <linux/list.h>
11#include <linux/mutex.h>
12#include <linux/pci.h>
13#include <linux/pci_ids.h>
14#include <linux/wait.h>
15
16/**
17 * DOC: Nitro Enclaves (NE) PCI device
18 */
19
20/**
21 * PCI_DEVICE_ID_NE - Nitro Enclaves PCI device id.
22 */
23#define PCI_DEVICE_ID_NE	(0xe4c1)
24/**
25 * PCI_BAR_NE - Nitro Enclaves PCI device MMIO BAR.
26 */
27#define PCI_BAR_NE		(0x03)
28
29/**
30 * DOC: Device registers in the NE PCI device MMIO BAR
31 */
32
33/**
34 * NE_ENABLE - (1 byte) Register to notify the device that the driver is using
35 *	       it (Read/Write).
36 */
37#define NE_ENABLE		(0x0000)
38#define NE_ENABLE_OFF		(0x00)
39#define NE_ENABLE_ON		(0x01)
40
41/**
42 * NE_VERSION - (2 bytes) Register to select the device run-time version
43 *		(Read/Write).
44 */
45#define NE_VERSION		(0x0002)
46#define NE_VERSION_MAX		(0x0001)
47
48/**
49 * NE_COMMAND - (4 bytes) Register to notify the device what command was
50 *		requested (Write-Only).
51 */
52#define NE_COMMAND		(0x0004)
53
54/**
55 * NE_EVTCNT - (4 bytes) Register to notify the driver that a reply or a device
56 *	       event is available (Read-Only):
57 *	       - Lower half  - command reply counter
58 *	       - Higher half - out-of-band device event counter
59 */
60#define NE_EVTCNT		(0x000c)
61#define NE_EVTCNT_REPLY_SHIFT	(0)
62#define NE_EVTCNT_REPLY_MASK	(0x0000ffff)
63#define NE_EVTCNT_REPLY(cnt)	(((cnt) & NE_EVTCNT_REPLY_MASK) >> \
64				NE_EVTCNT_REPLY_SHIFT)
65#define NE_EVTCNT_EVENT_SHIFT	(16)
66#define NE_EVTCNT_EVENT_MASK	(0xffff0000)
67#define NE_EVTCNT_EVENT(cnt)	(((cnt) & NE_EVTCNT_EVENT_MASK) >> \
68				NE_EVTCNT_EVENT_SHIFT)
69
70/**
71 * NE_SEND_DATA - (240 bytes) Buffer for sending the command request payload
72 *		  (Read/Write).
73 */
74#define NE_SEND_DATA		(0x0010)
75
76/**
77 * NE_RECV_DATA - (240 bytes) Buffer for receiving the command reply payload
78 *		  (Read-Only).
79 */
80#define NE_RECV_DATA		(0x0100)
81
82/**
83 * DOC: Device MMIO buffer sizes
84 */
85
86/**
87 * NE_SEND_DATA_SIZE / NE_RECV_DATA_SIZE - 240 bytes for send / recv buffer.
88 */
89#define NE_SEND_DATA_SIZE	(240)
90#define NE_RECV_DATA_SIZE	(240)
91
92/**
93 * DOC: MSI-X interrupt vectors
94 */
95
96/**
97 * NE_VEC_REPLY - MSI-X vector used for command reply notification.
98 */
99#define NE_VEC_REPLY		(0)
100
101/**
102 * NE_VEC_EVENT - MSI-X vector used for out-of-band events e.g. enclave crash.
103 */
104#define NE_VEC_EVENT		(1)
105
106/**
107 * enum ne_pci_dev_cmd_type - Device command types.
108 * @INVALID_CMD:		Invalid command.
109 * @ENCLAVE_START:		Start an enclave, after setting its resources.
110 * @ENCLAVE_GET_SLOT:		Get the slot uid of an enclave.
111 * @ENCLAVE_STOP:		Terminate an enclave.
112 * @SLOT_ALLOC :		Allocate a slot for an enclave.
113 * @SLOT_FREE:			Free the slot allocated for an enclave
114 * @SLOT_ADD_MEM:		Add a memory region to an enclave slot.
115 * @SLOT_ADD_VCPU:		Add a vCPU to an enclave slot.
116 * @SLOT_COUNT :		Get the number of allocated slots.
117 * @NEXT_SLOT:			Get the next slot in the list of allocated slots.
118 * @SLOT_INFO:			Get the info for a slot e.g. slot uid, vCPUs count.
119 * @SLOT_ADD_BULK_VCPUS:	Add a number of vCPUs, not providing CPU ids.
120 * @MAX_CMD:			A gatekeeper for max possible command type.
121 */
122enum ne_pci_dev_cmd_type {
123	INVALID_CMD		= 0,
124	ENCLAVE_START		= 1,
125	ENCLAVE_GET_SLOT	= 2,
126	ENCLAVE_STOP		= 3,
127	SLOT_ALLOC		= 4,
128	SLOT_FREE		= 5,
129	SLOT_ADD_MEM		= 6,
130	SLOT_ADD_VCPU		= 7,
131	SLOT_COUNT		= 8,
132	NEXT_SLOT		= 9,
133	SLOT_INFO		= 10,
134	SLOT_ADD_BULK_VCPUS	= 11,
135	MAX_CMD,
136};
137
138/**
139 * DOC: Device commands - payload structure for requests and replies.
140 */
141
142/**
143 * struct enclave_start_req - ENCLAVE_START request.
144 * @slot_uid:		Slot unique id mapped to the enclave to start.
145 * @enclave_cid:	Context ID (CID) for the enclave vsock device.
146 *			If 0, CID is autogenerated.
147 * @flags:		Flags for the enclave to start with (e.g. debug mode).
148 */
149struct enclave_start_req {
150	u64	slot_uid;
151	u64	enclave_cid;
152	u64	flags;
153};
154
155/**
156 * struct enclave_get_slot_req - ENCLAVE_GET_SLOT request.
157 * @enclave_cid:	Context ID (CID) for the enclave vsock device.
158 */
159struct enclave_get_slot_req {
160	u64	enclave_cid;
161};
162
163/**
164 * struct enclave_stop_req - ENCLAVE_STOP request.
165 * @slot_uid:	Slot unique id mapped to the enclave to stop.
166 */
167struct enclave_stop_req {
168	u64	slot_uid;
169};
170
171/**
172 * struct slot_alloc_req - SLOT_ALLOC request.
173 * @unused:	In order to avoid weird sizeof edge cases.
174 */
175struct slot_alloc_req {
176	u8	unused;
177};
178
179/**
180 * struct slot_free_req - SLOT_FREE request.
181 * @slot_uid:	Slot unique id mapped to the slot to free.
182 */
183struct slot_free_req {
184	u64	slot_uid;
185};
186
187/* TODO: Add flags field to the request to add memory region. */
188/**
189 * struct slot_add_mem_req - SLOT_ADD_MEM request.
190 * @slot_uid:	Slot unique id mapped to the slot to add the memory region to.
191 * @paddr:	Physical address of the memory region to add to the slot.
192 * @size:	Memory size, in bytes, of the memory region to add to the slot.
193 */
194struct slot_add_mem_req {
195	u64	slot_uid;
196	u64	paddr;
197	u64	size;
198};
199
200/**
201 * struct slot_add_vcpu_req - SLOT_ADD_VCPU request.
202 * @slot_uid:	Slot unique id mapped to the slot to add the vCPU to.
203 * @vcpu_id:	vCPU ID of the CPU to add to the enclave.
204 * @padding:	Padding for the overall data structure.
205 */
206struct slot_add_vcpu_req {
207	u64	slot_uid;
208	u32	vcpu_id;
209	u8	padding[4];
210};
211
212/**
213 * struct slot_count_req - SLOT_COUNT request.
214 * @unused:	In order to avoid weird sizeof edge cases.
215 */
216struct slot_count_req {
217	u8	unused;
218};
219
220/**
221 * struct next_slot_req - NEXT_SLOT request.
222 * @slot_uid:	Slot unique id of the next slot in the iteration.
223 */
224struct next_slot_req {
225	u64	slot_uid;
226};
227
228/**
229 * struct slot_info_req - SLOT_INFO request.
230 * @slot_uid:	Slot unique id mapped to the slot to get information about.
231 */
232struct slot_info_req {
233	u64	slot_uid;
234};
235
236/**
237 * struct slot_add_bulk_vcpus_req - SLOT_ADD_BULK_VCPUS request.
238 * @slot_uid:	Slot unique id mapped to the slot to add vCPUs to.
239 * @nr_vcpus:	Number of vCPUs to add to the slot.
240 */
241struct slot_add_bulk_vcpus_req {
242	u64	slot_uid;
243	u64	nr_vcpus;
244};
245
246/**
247 * struct ne_pci_dev_cmd_reply - NE PCI device command reply.
248 * @rc :		Return code of the logic that processed the request.
249 * @padding0:		Padding for the overall data structure.
250 * @slot_uid:		Valid for all commands except SLOT_COUNT.
251 * @enclave_cid:	Valid for ENCLAVE_START command.
252 * @slot_count :	Valid for SLOT_COUNT command.
253 * @mem_regions:	Valid for SLOT_ALLOC and SLOT_INFO commands.
254 * @mem_size:		Valid for SLOT_INFO command.
255 * @nr_vcpus:		Valid for SLOT_INFO command.
256 * @flags:		Valid for SLOT_INFO command.
257 * @state:		Valid for SLOT_INFO command.
258 * @padding1:		Padding for the overall data structure.
259 */
260struct ne_pci_dev_cmd_reply {
261	s32	rc;
262	u8	padding0[4];
263	u64	slot_uid;
264	u64	enclave_cid;
265	u64	slot_count;
266	u64	mem_regions;
267	u64	mem_size;
268	u64	nr_vcpus;
269	u64	flags;
270	u16	state;
271	u8	padding1[6];
272};
273
274/**
275 * struct ne_pci_dev - Nitro Enclaves (NE) PCI device.
276 * @cmd_reply_avail:		Variable set if a reply has been sent by the
277 *				PCI device.
278 * @cmd_reply_wait_q:		Wait queue for handling command reply from the
279 *				PCI device.
280 * @enclaves_list:		List of the enclaves managed by the PCI device.
281 * @enclaves_list_mutex:	Mutex for accessing the list of enclaves.
282 * @event_wq:			Work queue for handling out-of-band events
283 *				triggered by the Nitro Hypervisor which require
284 *				enclave state scanning and propagation to the
285 *				enclave process.
286 * @iomem_base :		MMIO region of the PCI device.
287 * @notify_work:		Work item for every received out-of-band event.
288 * @pci_dev_mutex:		Mutex for accessing the PCI device MMIO space.
289 * @pdev:			PCI device data structure.
290 */
291struct ne_pci_dev {
292	atomic_t		cmd_reply_avail;
293	wait_queue_head_t	cmd_reply_wait_q;
294	struct list_head	enclaves_list;
295	struct mutex		enclaves_list_mutex;
296	struct workqueue_struct	*event_wq;
297	void __iomem		*iomem_base;
298	struct work_struct	notify_work;
299	struct mutex		pci_dev_mutex;
300	struct pci_dev		*pdev;
301};
302
303/**
304 * ne_do_request() - Submit command request to the PCI device based on the command
305 *		     type and retrieve the associated reply.
306 * @pdev:		PCI device to send the command to and receive the reply from.
307 * @cmd_type:		Command type of the request sent to the PCI device.
308 * @cmd_request:	Command request payload.
309 * @cmd_request_size:	Size of the command request payload.
310 * @cmd_reply:		Command reply payload.
311 * @cmd_reply_size:	Size of the command reply payload.
312 *
313 * Context: Process context. This function uses the ne_pci_dev mutex to handle
314 *	    one command at a time.
315 * Return:
316 * * 0 on success.
317 * * Negative return value on failure.
318 */
319int ne_do_request(struct pci_dev *pdev, enum ne_pci_dev_cmd_type cmd_type,
320		  void *cmd_request, size_t cmd_request_size,
321		  struct ne_pci_dev_cmd_reply *cmd_reply,
322		  size_t cmd_reply_size);
323
324/* Nitro Enclaves (NE) PCI device driver */
325extern struct pci_driver ne_pci_driver;
326
327#endif /* _NE_PCI_DEV_H_ */
328