1 /* SPDX-License-Identifier: GPL-2.0 */
3 * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
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>
17 * DOC: Nitro Enclaves (NE) PCI device
21 * PCI_DEVICE_ID_NE - Nitro Enclaves PCI device id.
23 #define PCI_DEVICE_ID_NE (0xe4c1)
25 * PCI_BAR_NE - Nitro Enclaves PCI device MMIO BAR.
27 #define PCI_BAR_NE (0x03)
30 * DOC: Device registers in the NE PCI device MMIO BAR
34 * NE_ENABLE - (1 byte) Register to notify the device that the driver is using
37 #define NE_ENABLE (0x0000)
38 #define NE_ENABLE_OFF (0x00)
39 #define NE_ENABLE_ON (0x01)
42 * NE_VERSION - (2 bytes) Register to select the device run-time version
45 #define NE_VERSION (0x0002)
46 #define NE_VERSION_MAX (0x0001)
49 * NE_COMMAND - (4 bytes) Register to notify the device what command was
50 * requested (Write-Only).
52 #define NE_COMMAND (0x0004)
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
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)
71 * NE_SEND_DATA - (240 bytes) Buffer for sending the command request payload
74 #define NE_SEND_DATA (0x0010)
77 * NE_RECV_DATA - (240 bytes) Buffer for receiving the command reply payload
80 #define NE_RECV_DATA (0x0100)
83 * DOC: Device MMIO buffer sizes
87 * NE_SEND_DATA_SIZE / NE_RECV_DATA_SIZE - 240 bytes for send / recv buffer.
89 #define NE_SEND_DATA_SIZE (240)
90 #define NE_RECV_DATA_SIZE (240)
93 * DOC: MSI-X interrupt vectors
97 * NE_VEC_REPLY - MSI-X vector used for command reply notification.
99 #define NE_VEC_REPLY (0)
102 * NE_VEC_EVENT - MSI-X vector used for out-of-band events e.g. enclave crash.
104 #define NE_VEC_EVENT (1)
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.
122 enum ne_pci_dev_cmd_type
{
125 ENCLAVE_GET_SLOT
= 2,
134 SLOT_ADD_BULK_VCPUS
= 11,
139 * DOC: Device commands - payload structure for requests and replies.
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).
149 struct enclave_start_req
{
156 * struct enclave_get_slot_req - ENCLAVE_GET_SLOT request.
157 * @enclave_cid: Context ID (CID) for the enclave vsock device.
159 struct enclave_get_slot_req
{
164 * struct enclave_stop_req - ENCLAVE_STOP request.
165 * @slot_uid: Slot unique id mapped to the enclave to stop.
167 struct enclave_stop_req
{
172 * struct slot_alloc_req - SLOT_ALLOC request.
173 * @unused: In order to avoid weird sizeof edge cases.
175 struct slot_alloc_req
{
180 * struct slot_free_req - SLOT_FREE request.
181 * @slot_uid: Slot unique id mapped to the slot to free.
183 struct slot_free_req
{
187 /* TODO: Add flags field to the request to add memory region. */
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.
194 struct slot_add_mem_req
{
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.
206 struct slot_add_vcpu_req
{
213 * struct slot_count_req - SLOT_COUNT request.
214 * @unused: In order to avoid weird sizeof edge cases.
216 struct slot_count_req
{
221 * struct next_slot_req - NEXT_SLOT request.
222 * @slot_uid: Slot unique id of the next slot in the iteration.
224 struct next_slot_req
{
229 * struct slot_info_req - SLOT_INFO request.
230 * @slot_uid: Slot unique id mapped to the slot to get information about.
232 struct slot_info_req
{
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.
241 struct slot_add_bulk_vcpus_req
{
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.
260 struct ne_pci_dev_cmd_reply
{
275 * struct ne_pci_dev - Nitro Enclaves (NE) PCI device.
276 * @cmd_reply_avail: Variable set if a reply has been sent by the
278 * @cmd_reply_wait_q: Wait queue for handling command reply from the
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
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.
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
;
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.
313 * Context: Process context. This function uses the ne_pci_dev mutex to handle
314 * one command at a time.
317 * * Negative return value on failure.
319 int 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
);
324 /* Nitro Enclaves (NE) PCI device driver */
325 extern struct pci_driver ne_pci_driver
;
327 #endif /* _NE_PCI_DEV_H_ */