new file mode 100644
@@ -0,0 +1,264 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ */
+
+#ifndef _NE_PCI_DEV_H_
+#define _NE_PCI_DEV_H_
+
+#include <linux/atomic.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/wait.h>
+
+/* Nitro Enclaves (NE) PCI device identifier */
+
+#define PCI_DEVICE_ID_NE (0xe4c1)
+#define PCI_BAR_NE (0x03)
+
+/* Device registers */
+
+/**
+ * (1 byte) Register to notify the device that the driver is using it
+ * (Read/Write).
+ */
+#define NE_ENABLE (0x0000)
+#define NE_ENABLE_OFF (0x00)
+#define NE_ENABLE_ON (0x01)
+
+/* (2 bytes) Register to select the device run-time version (Read/Write). */
+#define NE_VERSION (0x0002)
+#define NE_VERSION_MAX (0x0001)
+
+/**
+ * (4 bytes) Register to notify the device what command was requested
+ * (Write-Only).
+ */
+#define NE_COMMAND (0x0004)
+
+/**
+ * (4 bytes) Register to notify the driver that a reply or a device event
+ * is available (Read-Only):
+ * - Lower half - command reply counter
+ * - Higher half - out-of-band device event counter
+ */
+#define NE_EVTCNT (0x000c)
+#define NE_EVTCNT_REPLY_SHIFT (0)
+#define NE_EVTCNT_REPLY_MASK (0x0000ffff)
+#define NE_EVTCNT_REPLY(cnt) (((cnt) & NE_EVTCNT_REPLY_MASK) >> \
+ NE_EVTCNT_REPLY_SHIFT)
+#define NE_EVTCNT_EVENT_SHIFT (16)
+#define NE_EVTCNT_EVENT_MASK (0xffff0000)
+#define NE_EVTCNT_EVENT(cnt) (((cnt) & NE_EVTCNT_EVENT_MASK) >> \
+ NE_EVTCNT_EVENT_SHIFT)
+
+/* (240 bytes) Buffer for sending the command request payload (Read/Write). */
+#define NE_SEND_DATA (0x0010)
+
+/* (240 bytes) Buffer for receiving the command reply payload (Read-Only). */
+#define NE_RECV_DATA (0x0100)
+
+/* Device MMIO buffer sizes */
+
+/* 240 bytes for send / recv buffer. */
+#define NE_SEND_DATA_SIZE (240)
+#define NE_RECV_DATA_SIZE (240)
+
+/* MSI-X interrupt vectors */
+
+/* MSI-X vector used for command reply notification. */
+#define NE_VEC_REPLY (0)
+
+/* MSI-X vector used for out-of-band events e.g. enclave crash. */
+#define NE_VEC_EVENT (1)
+
+/* Device command types. */
+enum ne_pci_dev_cmd_type {
+ INVALID_CMD = 0,
+ ENCLAVE_START = 1,
+ ENCLAVE_GET_SLOT = 2,
+ ENCLAVE_STOP = 3,
+ SLOT_ALLOC = 4,
+ SLOT_FREE = 5,
+ SLOT_ADD_MEM = 6,
+ SLOT_ADD_VCPU = 7,
+ SLOT_COUNT = 8,
+ NEXT_SLOT = 9,
+ SLOT_INFO = 10,
+ SLOT_ADD_BULK_VCPUS = 11,
+ MAX_CMD,
+};
+
+/* Device commands - payload structure for requests and replies. */
+
+struct enclave_start_req {
+ /* Slot unique id mapped to the enclave to start. */
+ u64 slot_uid;
+
+ /**
+ * Context ID (CID) for the enclave vsock device.
+ * If 0, CID is autogenerated.
+ */
+ u64 enclave_cid;
+
+ /* Flags for the enclave to start with (e.g. debug mode). */
+ u64 flags;
+};
+
+struct enclave_get_slot_req {
+ /* Context ID (CID) for the enclave vsock device. */
+ u64 enclave_cid;
+};
+
+struct enclave_stop_req {
+ /* Slot unique id mapped to the enclave to stop. */
+ u64 slot_uid;
+};
+
+struct slot_alloc_req {
+ /* In order to avoid weird sizeof edge cases. */
+ u8 unused;
+};
+
+struct slot_free_req {
+ /* Slot unique id mapped to the slot to free. */
+ u64 slot_uid;
+};
+
+struct slot_add_mem_req {
+ /* Slot unique id mapped to the slot to add the memory region to. */
+ u64 slot_uid;
+
+ /* Physical address of the memory region to add to the slot. */
+ u64 paddr;
+
+ /* Memory size, in bytes, of the memory region to add to the slot. */
+ u64 size;
+};
+
+struct slot_add_vcpu_req {
+ /* Slot unique id mapped to the slot to add the vCPU to. */
+ u64 slot_uid;
+
+ /* vCPU ID of the CPU to add to the enclave. */
+ u32 vcpu_id;
+
+ u8 padding[4];
+};
+
+struct slot_count_req {
+ /* In order to avoid weird sizeof edge cases. */
+ u8 unused;
+};
+
+struct next_slot_req {
+ /* Slot unique id of the next slot in the iteration. */
+ u64 slot_uid;
+};
+
+struct slot_info_req {
+ /* Slot unique id mapped to the slot to get information about. */
+ u64 slot_uid;
+};
+
+struct slot_add_bulk_vcpus_req {
+ /* Slot unique id mapped to the slot to add vCPUs to. */
+ u64 slot_uid;
+
+ /* Number of vCPUs to add to the slot. */
+ u64 nr_vcpus;
+};
+
+struct ne_pci_dev_cmd_reply {
+ /* Return code of the functionality that processed the request. */
+ s32 rc;
+
+ u8 padding0[4];
+
+ /* Valid for all commands except SLOT_COUNT. */
+ u64 slot_uid;
+
+ /* Valid for ENCLAVE_START command. */
+ u64 enclave_cid;
+
+ /* Valid for SLOT_COUNT command. */
+ u64 slot_count;
+
+ /* Valid for SLOT_ALLOC and SLOT_INFO commands. */
+ u64 mem_regions;
+
+ /* Valid for SLOT_INFO command. */
+ u64 mem_size;
+
+ /* Valid for SLOT_INFO command. */
+ u64 nr_vcpus;
+
+ /* Valid for SLOT_INFO command. */
+ u64 flags;
+
+ /* Valid for SLOT_INFO command. */
+ u16 state;
+
+ u8 padding1[6];
+};
+
+/* Nitro Enclaves (NE) PCI device. */
+struct ne_pci_dev {
+ /* Variable set if a reply has been sent by the PCI device. */
+ atomic_t cmd_reply_avail;
+
+ /* Wait queue for handling command reply from the PCI device. */
+ wait_queue_head_t cmd_reply_wait_q;
+
+ /* List of the enclaves managed by the PCI device. */
+ struct list_head enclaves_list;
+
+ /* Mutex for accessing the list of enclaves. */
+ struct mutex enclaves_list_mutex;
+
+ /**
+ * Work queue for handling out-of-band events triggered by the Nitro
+ * Hypervisor which require enclave state scanning and propagation to
+ * the enclave process.
+ */
+ struct workqueue_struct *event_wq;
+
+ /* MMIO region of the PCI device. */
+ void __iomem *iomem_base;
+
+ /* Work item for every received out-of-band event. */
+ struct work_struct notify_work;
+
+ /* Mutex for accessing the PCI device MMIO space. */
+ struct mutex pci_dev_mutex;
+
+ /* PCI device data structure. */
+ struct pci_dev *pdev;
+};
+
+/**
+ * ne_do_request - Submit command request to the PCI device based on the command
+ * type and retrieve the associated reply.
+ *
+ * This function uses the ne_pci_dev mutex to handle one command at a time.
+ *
+ * @pdev: PCI device to send the command to and receive the reply from.
+ * @cmd_type: command type of the request sent to the PCI device.
+ * @cmd_request: command request payload.
+ * @cmd_request_size: size of the command request payload.
+ * @cmd_reply: command reply payload.
+ * @cmd_reply_size: size of the command reply payload.
+ *
+ * @returns: 0 on success, negative return value on failure.
+ */
+int ne_do_request(struct pci_dev *pdev, enum ne_pci_dev_cmd_type cmd_type,
+ void *cmd_request, size_t cmd_request_size,
+ struct ne_pci_dev_cmd_reply *cmd_reply,
+ size_t cmd_reply_size);
+
+/* Nitro Enclaves (NE) PCI device driver */
+extern struct pci_driver ne_pci_driver;
+
+#endif /* _NE_PCI_DEV_H_ */