Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  * Copyright 2020-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
0004  */
0005 
0006 #ifndef _NE_PCI_DEV_H_
0007 #define _NE_PCI_DEV_H_
0008 
0009 #include <linux/atomic.h>
0010 #include <linux/list.h>
0011 #include <linux/mutex.h>
0012 #include <linux/pci.h>
0013 #include <linux/pci_ids.h>
0014 #include <linux/wait.h>
0015 
0016 /**
0017  * DOC: Nitro Enclaves (NE) PCI device
0018  */
0019 
0020 /**
0021  * PCI_DEVICE_ID_NE - Nitro Enclaves PCI device id.
0022  */
0023 #define PCI_DEVICE_ID_NE    (0xe4c1)
0024 /**
0025  * PCI_BAR_NE - Nitro Enclaves PCI device MMIO BAR.
0026  */
0027 #define PCI_BAR_NE      (0x03)
0028 
0029 /**
0030  * DOC: Device registers in the NE PCI device MMIO BAR
0031  */
0032 
0033 /**
0034  * NE_ENABLE - (1 byte) Register to notify the device that the driver is using
0035  *         it (Read/Write).
0036  */
0037 #define NE_ENABLE       (0x0000)
0038 #define NE_ENABLE_OFF       (0x00)
0039 #define NE_ENABLE_ON        (0x01)
0040 
0041 /**
0042  * NE_VERSION - (2 bytes) Register to select the device run-time version
0043  *      (Read/Write).
0044  */
0045 #define NE_VERSION      (0x0002)
0046 #define NE_VERSION_MAX      (0x0001)
0047 
0048 /**
0049  * NE_COMMAND - (4 bytes) Register to notify the device what command was
0050  *      requested (Write-Only).
0051  */
0052 #define NE_COMMAND      (0x0004)
0053 
0054 /**
0055  * NE_EVTCNT - (4 bytes) Register to notify the driver that a reply or a device
0056  *         event is available (Read-Only):
0057  *         - Lower half  - command reply counter
0058  *         - Higher half - out-of-band device event counter
0059  */
0060 #define NE_EVTCNT       (0x000c)
0061 #define NE_EVTCNT_REPLY_SHIFT   (0)
0062 #define NE_EVTCNT_REPLY_MASK    (0x0000ffff)
0063 #define NE_EVTCNT_REPLY(cnt)    (((cnt) & NE_EVTCNT_REPLY_MASK) >> \
0064                 NE_EVTCNT_REPLY_SHIFT)
0065 #define NE_EVTCNT_EVENT_SHIFT   (16)
0066 #define NE_EVTCNT_EVENT_MASK    (0xffff0000)
0067 #define NE_EVTCNT_EVENT(cnt)    (((cnt) & NE_EVTCNT_EVENT_MASK) >> \
0068                 NE_EVTCNT_EVENT_SHIFT)
0069 
0070 /**
0071  * NE_SEND_DATA - (240 bytes) Buffer for sending the command request payload
0072  *        (Read/Write).
0073  */
0074 #define NE_SEND_DATA        (0x0010)
0075 
0076 /**
0077  * NE_RECV_DATA - (240 bytes) Buffer for receiving the command reply payload
0078  *        (Read-Only).
0079  */
0080 #define NE_RECV_DATA        (0x0100)
0081 
0082 /**
0083  * DOC: Device MMIO buffer sizes
0084  */
0085 
0086 /**
0087  * NE_SEND_DATA_SIZE - Size of the send buffer, in bytes.
0088  */
0089 #define NE_SEND_DATA_SIZE   (240)
0090 
0091 /**
0092  * NE_RECV_DATA_SIZE - Size of the receive buffer, in bytes.
0093  */
0094 #define NE_RECV_DATA_SIZE   (240)
0095 
0096 /**
0097  * DOC: MSI-X interrupt vectors
0098  */
0099 
0100 /**
0101  * NE_VEC_REPLY - MSI-X vector used for command reply notification.
0102  */
0103 #define NE_VEC_REPLY        (0)
0104 
0105 /**
0106  * NE_VEC_EVENT - MSI-X vector used for out-of-band events e.g. enclave crash.
0107  */
0108 #define NE_VEC_EVENT        (1)
0109 
0110 /**
0111  * enum ne_pci_dev_cmd_type - Device command types.
0112  * @INVALID_CMD:        Invalid command.
0113  * @ENCLAVE_START:      Start an enclave, after setting its resources.
0114  * @ENCLAVE_GET_SLOT:       Get the slot uid of an enclave.
0115  * @ENCLAVE_STOP:       Terminate an enclave.
0116  * @SLOT_ALLOC :        Allocate a slot for an enclave.
0117  * @SLOT_FREE:          Free the slot allocated for an enclave
0118  * @SLOT_ADD_MEM:       Add a memory region to an enclave slot.
0119  * @SLOT_ADD_VCPU:      Add a vCPU to an enclave slot.
0120  * @SLOT_COUNT :        Get the number of allocated slots.
0121  * @NEXT_SLOT:          Get the next slot in the list of allocated slots.
0122  * @SLOT_INFO:          Get the info for a slot e.g. slot uid, vCPUs count.
0123  * @SLOT_ADD_BULK_VCPUS:    Add a number of vCPUs, not providing CPU ids.
0124  * @MAX_CMD:            A gatekeeper for max possible command type.
0125  */
0126 enum ne_pci_dev_cmd_type {
0127     INVALID_CMD     = 0,
0128     ENCLAVE_START       = 1,
0129     ENCLAVE_GET_SLOT    = 2,
0130     ENCLAVE_STOP        = 3,
0131     SLOT_ALLOC      = 4,
0132     SLOT_FREE       = 5,
0133     SLOT_ADD_MEM        = 6,
0134     SLOT_ADD_VCPU       = 7,
0135     SLOT_COUNT      = 8,
0136     NEXT_SLOT       = 9,
0137     SLOT_INFO       = 10,
0138     SLOT_ADD_BULK_VCPUS = 11,
0139     MAX_CMD,
0140 };
0141 
0142 /**
0143  * DOC: Device commands - payload structure for requests and replies.
0144  */
0145 
0146 /**
0147  * struct enclave_start_req - ENCLAVE_START request.
0148  * @slot_uid:       Slot unique id mapped to the enclave to start.
0149  * @enclave_cid:    Context ID (CID) for the enclave vsock device.
0150  *          If 0, CID is autogenerated.
0151  * @flags:      Flags for the enclave to start with (e.g. debug mode).
0152  */
0153 struct enclave_start_req {
0154     u64 slot_uid;
0155     u64 enclave_cid;
0156     u64 flags;
0157 };
0158 
0159 /**
0160  * struct enclave_get_slot_req - ENCLAVE_GET_SLOT request.
0161  * @enclave_cid:    Context ID (CID) for the enclave vsock device.
0162  */
0163 struct enclave_get_slot_req {
0164     u64 enclave_cid;
0165 };
0166 
0167 /**
0168  * struct enclave_stop_req - ENCLAVE_STOP request.
0169  * @slot_uid:   Slot unique id mapped to the enclave to stop.
0170  */
0171 struct enclave_stop_req {
0172     u64 slot_uid;
0173 };
0174 
0175 /**
0176  * struct slot_alloc_req - SLOT_ALLOC request.
0177  * @unused: In order to avoid weird sizeof edge cases.
0178  */
0179 struct slot_alloc_req {
0180     u8  unused;
0181 };
0182 
0183 /**
0184  * struct slot_free_req - SLOT_FREE request.
0185  * @slot_uid:   Slot unique id mapped to the slot to free.
0186  */
0187 struct slot_free_req {
0188     u64 slot_uid;
0189 };
0190 
0191 /* TODO: Add flags field to the request to add memory region. */
0192 /**
0193  * struct slot_add_mem_req - SLOT_ADD_MEM request.
0194  * @slot_uid:   Slot unique id mapped to the slot to add the memory region to.
0195  * @paddr:  Physical address of the memory region to add to the slot.
0196  * @size:   Memory size, in bytes, of the memory region to add to the slot.
0197  */
0198 struct slot_add_mem_req {
0199     u64 slot_uid;
0200     u64 paddr;
0201     u64 size;
0202 };
0203 
0204 /**
0205  * struct slot_add_vcpu_req - SLOT_ADD_VCPU request.
0206  * @slot_uid:   Slot unique id mapped to the slot to add the vCPU to.
0207  * @vcpu_id:    vCPU ID of the CPU to add to the enclave.
0208  * @padding:    Padding for the overall data structure.
0209  */
0210 struct slot_add_vcpu_req {
0211     u64 slot_uid;
0212     u32 vcpu_id;
0213     u8  padding[4];
0214 };
0215 
0216 /**
0217  * struct slot_count_req - SLOT_COUNT request.
0218  * @unused: In order to avoid weird sizeof edge cases.
0219  */
0220 struct slot_count_req {
0221     u8  unused;
0222 };
0223 
0224 /**
0225  * struct next_slot_req - NEXT_SLOT request.
0226  * @slot_uid:   Slot unique id of the next slot in the iteration.
0227  */
0228 struct next_slot_req {
0229     u64 slot_uid;
0230 };
0231 
0232 /**
0233  * struct slot_info_req - SLOT_INFO request.
0234  * @slot_uid:   Slot unique id mapped to the slot to get information about.
0235  */
0236 struct slot_info_req {
0237     u64 slot_uid;
0238 };
0239 
0240 /**
0241  * struct slot_add_bulk_vcpus_req - SLOT_ADD_BULK_VCPUS request.
0242  * @slot_uid:   Slot unique id mapped to the slot to add vCPUs to.
0243  * @nr_vcpus:   Number of vCPUs to add to the slot.
0244  */
0245 struct slot_add_bulk_vcpus_req {
0246     u64 slot_uid;
0247     u64 nr_vcpus;
0248 };
0249 
0250 /**
0251  * struct ne_pci_dev_cmd_reply - NE PCI device command reply.
0252  * @rc :        Return code of the logic that processed the request.
0253  * @padding0:       Padding for the overall data structure.
0254  * @slot_uid:       Valid for all commands except SLOT_COUNT.
0255  * @enclave_cid:    Valid for ENCLAVE_START command.
0256  * @slot_count :    Valid for SLOT_COUNT command.
0257  * @mem_regions:    Valid for SLOT_ALLOC and SLOT_INFO commands.
0258  * @mem_size:       Valid for SLOT_INFO command.
0259  * @nr_vcpus:       Valid for SLOT_INFO command.
0260  * @flags:      Valid for SLOT_INFO command.
0261  * @state:      Valid for SLOT_INFO command.
0262  * @padding1:       Padding for the overall data structure.
0263  */
0264 struct ne_pci_dev_cmd_reply {
0265     s32 rc;
0266     u8  padding0[4];
0267     u64 slot_uid;
0268     u64 enclave_cid;
0269     u64 slot_count;
0270     u64 mem_regions;
0271     u64 mem_size;
0272     u64 nr_vcpus;
0273     u64 flags;
0274     u16 state;
0275     u8  padding1[6];
0276 };
0277 
0278 /**
0279  * struct ne_pci_dev - Nitro Enclaves (NE) PCI device.
0280  * @cmd_reply_avail:        Variable set if a reply has been sent by the
0281  *              PCI device.
0282  * @cmd_reply_wait_q:       Wait queue for handling command reply from the
0283  *              PCI device.
0284  * @enclaves_list:      List of the enclaves managed by the PCI device.
0285  * @enclaves_list_mutex:    Mutex for accessing the list of enclaves.
0286  * @event_wq:           Work queue for handling out-of-band events
0287  *              triggered by the Nitro Hypervisor which require
0288  *              enclave state scanning and propagation to the
0289  *              enclave process.
0290  * @iomem_base :        MMIO region of the PCI device.
0291  * @notify_work:        Work item for every received out-of-band event.
0292  * @pci_dev_mutex:      Mutex for accessing the PCI device MMIO space.
0293  * @pdev:           PCI device data structure.
0294  */
0295 struct ne_pci_dev {
0296     atomic_t        cmd_reply_avail;
0297     wait_queue_head_t   cmd_reply_wait_q;
0298     struct list_head    enclaves_list;
0299     struct mutex        enclaves_list_mutex;
0300     struct workqueue_struct *event_wq;
0301     void __iomem        *iomem_base;
0302     struct work_struct  notify_work;
0303     struct mutex        pci_dev_mutex;
0304     struct pci_dev      *pdev;
0305 };
0306 
0307 /**
0308  * ne_do_request() - Submit command request to the PCI device based on the command
0309  *           type and retrieve the associated reply.
0310  * @pdev:       PCI device to send the command to and receive the reply from.
0311  * @cmd_type:       Command type of the request sent to the PCI device.
0312  * @cmd_request:    Command request payload.
0313  * @cmd_request_size:   Size of the command request payload.
0314  * @cmd_reply:      Command reply payload.
0315  * @cmd_reply_size: Size of the command reply payload.
0316  *
0317  * Context: Process context. This function uses the ne_pci_dev mutex to handle
0318  *      one command at a time.
0319  * Return:
0320  * * 0 on success.
0321  * * Negative return value on failure.
0322  */
0323 int ne_do_request(struct pci_dev *pdev, enum ne_pci_dev_cmd_type cmd_type,
0324           void *cmd_request, size_t cmd_request_size,
0325           struct ne_pci_dev_cmd_reply *cmd_reply,
0326           size_t cmd_reply_size);
0327 
0328 /* Nitro Enclaves (NE) PCI device driver */
0329 extern struct pci_driver ne_pci_driver;
0330 
0331 #endif /* _NE_PCI_DEV_H_ */