332 lines · c
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 device18 */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 BAR31 */32 33/**34 * NE_ENABLE - (1 byte) Register to notify the device that the driver is using35 * 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 version43 * (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 was50 * 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 device56 * event is available (Read-Only):57 * - Lower half - command reply counter58 * - Higher half - out-of-band device event counter59 */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 payload72 * (Read/Write).73 */74#define NE_SEND_DATA (0x0010)75 76/**77 * NE_RECV_DATA - (240 bytes) Buffer for receiving the command reply payload78 * (Read-Only).79 */80#define NE_RECV_DATA (0x0100)81 82/**83 * DOC: Device MMIO buffer sizes84 */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 vectors98 */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 enclave118 * @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 */126enum 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 */153struct 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 */163struct 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 */171struct 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 */179struct 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 */187struct 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 */198struct 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 */210struct 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 */220struct 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 */228struct 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 */236struct 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 */245struct 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 */264struct 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 the281 * PCI device.282 * @cmd_reply_wait_q: Wait queue for handling command reply from the283 * 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 events287 * triggered by the Nitro Hypervisor which require288 * enclave state scanning and propagation to the289 * 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 */295struct 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 command309 * 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 handle318 * one command at a time.319 * Return:320 * * 0 on success.321 * * Negative return value on failure.322 */323int 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 */329extern struct pci_driver ne_pci_driver;330 331#endif /* _NE_PCI_DEV_H_ */332