1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Copyright 2020-2021 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 - Size of the send buffer, in bytes. 88 */ 89 #define NE_SEND_DATA_SIZE (240) 90 91 /** 92 * NE_RECV_DATA_SIZE - Size of the receive buffer, in bytes. 93 */ 94 #define NE_RECV_DATA_SIZE (240) 95 96 /** 97 * DOC: MSI-X interrupt vectors 98 */ 99 100 /** 101 * NE_VEC_REPLY - MSI-X vector used for command reply notification. 102 */ 103 #define NE_VEC_REPLY (0) 104 105 /** 106 * NE_VEC_EVENT - MSI-X vector used for out-of-band events e.g. enclave crash. 107 */ 108 #define NE_VEC_EVENT (1) 109 110 /** 111 * enum ne_pci_dev_cmd_type - Device command types. 112 * @INVALID_CMD: Invalid command. 113 * @ENCLAVE_START: Start an enclave, after setting its resources. 114 * @ENCLAVE_GET_SLOT: Get the slot uid of an enclave. 115 * @ENCLAVE_STOP: Terminate an enclave. 116 * @SLOT_ALLOC : Allocate a slot for an enclave. 117 * @SLOT_FREE: Free the slot allocated for an enclave 118 * @SLOT_ADD_MEM: Add a memory region to an enclave slot. 119 * @SLOT_ADD_VCPU: Add a vCPU to an enclave slot. 120 * @SLOT_COUNT : Get the number of allocated slots. 121 * @NEXT_SLOT: Get the next slot in the list of allocated slots. 122 * @SLOT_INFO: Get the info for a slot e.g. slot uid, vCPUs count. 123 * @SLOT_ADD_BULK_VCPUS: Add a number of vCPUs, not providing CPU ids. 124 * @MAX_CMD: A gatekeeper for max possible command type. 125 */ 126 enum ne_pci_dev_cmd_type { 127 INVALID_CMD = 0, 128 ENCLAVE_START = 1, 129 ENCLAVE_GET_SLOT = 2, 130 ENCLAVE_STOP = 3, 131 SLOT_ALLOC = 4, 132 SLOT_FREE = 5, 133 SLOT_ADD_MEM = 6, 134 SLOT_ADD_VCPU = 7, 135 SLOT_COUNT = 8, 136 NEXT_SLOT = 9, 137 SLOT_INFO = 10, 138 SLOT_ADD_BULK_VCPUS = 11, 139 MAX_CMD, 140 }; 141 142 /** 143 * DOC: Device commands - payload structure for requests and replies. 144 */ 145 146 /** 147 * struct enclave_start_req - ENCLAVE_START request. 148 * @slot_uid: Slot unique id mapped to the enclave to start. 149 * @enclave_cid: Context ID (CID) for the enclave vsock device. 150 * If 0, CID is autogenerated. 151 * @flags: Flags for the enclave to start with (e.g. debug mode). 152 */ 153 struct enclave_start_req { 154 u64 slot_uid; 155 u64 enclave_cid; 156 u64 flags; 157 }; 158 159 /** 160 * struct enclave_get_slot_req - ENCLAVE_GET_SLOT request. 161 * @enclave_cid: Context ID (CID) for the enclave vsock device. 162 */ 163 struct enclave_get_slot_req { 164 u64 enclave_cid; 165 }; 166 167 /** 168 * struct enclave_stop_req - ENCLAVE_STOP request. 169 * @slot_uid: Slot unique id mapped to the enclave to stop. 170 */ 171 struct enclave_stop_req { 172 u64 slot_uid; 173 }; 174 175 /** 176 * struct slot_alloc_req - SLOT_ALLOC request. 177 * @unused: In order to avoid weird sizeof edge cases. 178 */ 179 struct slot_alloc_req { 180 u8 unused; 181 }; 182 183 /** 184 * struct slot_free_req - SLOT_FREE request. 185 * @slot_uid: Slot unique id mapped to the slot to free. 186 */ 187 struct slot_free_req { 188 u64 slot_uid; 189 }; 190 191 /* TODO: Add flags field to the request to add memory region. */ 192 /** 193 * struct slot_add_mem_req - SLOT_ADD_MEM request. 194 * @slot_uid: Slot unique id mapped to the slot to add the memory region to. 195 * @paddr: Physical address of the memory region to add to the slot. 196 * @size: Memory size, in bytes, of the memory region to add to the slot. 197 */ 198 struct slot_add_mem_req { 199 u64 slot_uid; 200 u64 paddr; 201 u64 size; 202 }; 203 204 /** 205 * struct slot_add_vcpu_req - SLOT_ADD_VCPU request. 206 * @slot_uid: Slot unique id mapped to the slot to add the vCPU to. 207 * @vcpu_id: vCPU ID of the CPU to add to the enclave. 208 * @padding: Padding for the overall data structure. 209 */ 210 struct slot_add_vcpu_req { 211 u64 slot_uid; 212 u32 vcpu_id; 213 u8 padding[4]; 214 }; 215 216 /** 217 * struct slot_count_req - SLOT_COUNT request. 218 * @unused: In order to avoid weird sizeof edge cases. 219 */ 220 struct slot_count_req { 221 u8 unused; 222 }; 223 224 /** 225 * struct next_slot_req - NEXT_SLOT request. 226 * @slot_uid: Slot unique id of the next slot in the iteration. 227 */ 228 struct next_slot_req { 229 u64 slot_uid; 230 }; 231 232 /** 233 * struct slot_info_req - SLOT_INFO request. 234 * @slot_uid: Slot unique id mapped to the slot to get information about. 235 */ 236 struct slot_info_req { 237 u64 slot_uid; 238 }; 239 240 /** 241 * struct slot_add_bulk_vcpus_req - SLOT_ADD_BULK_VCPUS request. 242 * @slot_uid: Slot unique id mapped to the slot to add vCPUs to. 243 * @nr_vcpus: Number of vCPUs to add to the slot. 244 */ 245 struct slot_add_bulk_vcpus_req { 246 u64 slot_uid; 247 u64 nr_vcpus; 248 }; 249 250 /** 251 * struct ne_pci_dev_cmd_reply - NE PCI device command reply. 252 * @rc : Return code of the logic that processed the request. 253 * @padding0: Padding for the overall data structure. 254 * @slot_uid: Valid for all commands except SLOT_COUNT. 255 * @enclave_cid: Valid for ENCLAVE_START command. 256 * @slot_count : Valid for SLOT_COUNT command. 257 * @mem_regions: Valid for SLOT_ALLOC and SLOT_INFO commands. 258 * @mem_size: Valid for SLOT_INFO command. 259 * @nr_vcpus: Valid for SLOT_INFO command. 260 * @flags: Valid for SLOT_INFO command. 261 * @state: Valid for SLOT_INFO command. 262 * @padding1: Padding for the overall data structure. 263 */ 264 struct ne_pci_dev_cmd_reply { 265 s32 rc; 266 u8 padding0[4]; 267 u64 slot_uid; 268 u64 enclave_cid; 269 u64 slot_count; 270 u64 mem_regions; 271 u64 mem_size; 272 u64 nr_vcpus; 273 u64 flags; 274 u16 state; 275 u8 padding1[6]; 276 }; 277 278 /** 279 * struct ne_pci_dev - Nitro Enclaves (NE) PCI device. 280 * @cmd_reply_avail: Variable set if a reply has been sent by the 281 * PCI device. 282 * @cmd_reply_wait_q: Wait queue for handling command reply from the 283 * PCI device. 284 * @enclaves_list: List of the enclaves managed by the PCI device. 285 * @enclaves_list_mutex: Mutex for accessing the list of enclaves. 286 * @event_wq: Work queue for handling out-of-band events 287 * triggered by the Nitro Hypervisor which require 288 * enclave state scanning and propagation to the 289 * enclave process. 290 * @iomem_base : MMIO region of the PCI device. 291 * @notify_work: Work item for every received out-of-band event. 292 * @pci_dev_mutex: Mutex for accessing the PCI device MMIO space. 293 * @pdev: PCI device data structure. 294 */ 295 struct ne_pci_dev { 296 atomic_t cmd_reply_avail; 297 wait_queue_head_t cmd_reply_wait_q; 298 struct list_head enclaves_list; 299 struct mutex enclaves_list_mutex; 300 struct workqueue_struct *event_wq; 301 void __iomem *iomem_base; 302 struct work_struct notify_work; 303 struct mutex pci_dev_mutex; 304 struct pci_dev *pdev; 305 }; 306 307 /** 308 * ne_do_request() - Submit command request to the PCI device based on the command 309 * type and retrieve the associated reply. 310 * @pdev: PCI device to send the command to and receive the reply from. 311 * @cmd_type: Command type of the request sent to the PCI device. 312 * @cmd_request: Command request payload. 313 * @cmd_request_size: Size of the command request payload. 314 * @cmd_reply: Command reply payload. 315 * @cmd_reply_size: Size of the command reply payload. 316 * 317 * Context: Process context. This function uses the ne_pci_dev mutex to handle 318 * one command at a time. 319 * Return: 320 * * 0 on success. 321 * * Negative return value on failure. 322 */ 323 int ne_do_request(struct pci_dev *pdev, enum ne_pci_dev_cmd_type cmd_type, 324 void *cmd_request, size_t cmd_request_size, 325 struct ne_pci_dev_cmd_reply *cmd_reply, 326 size_t cmd_reply_size); 327 328 /* Nitro Enclaves (NE) PCI device driver */ 329 extern struct pci_driver ne_pci_driver; 330 331 #endif /* _NE_PCI_DEV_H_ */ 332