linux/drivers/virt/nitro_enclaves/ne_pci_dev.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2/*
   3 * Copyright 2020 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 / NE_RECV_DATA_SIZE - 240 bytes for send / recv buffer.
  88 */
  89#define NE_SEND_DATA_SIZE       (240)
  90#define NE_RECV_DATA_SIZE       (240)
  91
  92/**
  93 * DOC: MSI-X interrupt vectors
  94 */
  95
  96/**
  97 * NE_VEC_REPLY - MSI-X vector used for command reply notification.
  98 */
  99#define NE_VEC_REPLY            (0)
 100
 101/**
 102 * NE_VEC_EVENT - MSI-X vector used for out-of-band events e.g. enclave crash.
 103 */
 104#define NE_VEC_EVENT            (1)
 105
 106/**
 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.
 121 */
 122enum ne_pci_dev_cmd_type {
 123        INVALID_CMD             = 0,
 124        ENCLAVE_START           = 1,
 125        ENCLAVE_GET_SLOT        = 2,
 126        ENCLAVE_STOP            = 3,
 127        SLOT_ALLOC              = 4,
 128        SLOT_FREE               = 5,
 129        SLOT_ADD_MEM            = 6,
 130        SLOT_ADD_VCPU           = 7,
 131        SLOT_COUNT              = 8,
 132        NEXT_SLOT               = 9,
 133        SLOT_INFO               = 10,
 134        SLOT_ADD_BULK_VCPUS     = 11,
 135        MAX_CMD,
 136};
 137
 138/**
 139 * DOC: Device commands - payload structure for requests and replies.
 140 */
 141
 142/**
 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).
 148 */
 149struct enclave_start_req {
 150        u64     slot_uid;
 151        u64     enclave_cid;
 152        u64     flags;
 153};
 154
 155/**
 156 * struct enclave_get_slot_req - ENCLAVE_GET_SLOT request.
 157 * @enclave_cid:        Context ID (CID) for the enclave vsock device.
 158 */
 159struct enclave_get_slot_req {
 160        u64     enclave_cid;
 161};
 162
 163/**
 164 * struct enclave_stop_req - ENCLAVE_STOP request.
 165 * @slot_uid:   Slot unique id mapped to the enclave to stop.
 166 */
 167struct enclave_stop_req {
 168        u64     slot_uid;
 169};
 170
 171/**
 172 * struct slot_alloc_req - SLOT_ALLOC request.
 173 * @unused:     In order to avoid weird sizeof edge cases.
 174 */
 175struct slot_alloc_req {
 176        u8      unused;
 177};
 178
 179/**
 180 * struct slot_free_req - SLOT_FREE request.
 181 * @slot_uid:   Slot unique id mapped to the slot to free.
 182 */
 183struct slot_free_req {
 184        u64     slot_uid;
 185};
 186
 187/* TODO: Add flags field to the request to add memory region. */
 188/**
 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.
 193 */
 194struct slot_add_mem_req {
 195        u64     slot_uid;
 196        u64     paddr;
 197        u64     size;
 198};
 199
 200/**
 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.
 205 */
 206struct slot_add_vcpu_req {
 207        u64     slot_uid;
 208        u32     vcpu_id;
 209        u8      padding[4];
 210};
 211
 212/**
 213 * struct slot_count_req - SLOT_COUNT request.
 214 * @unused:     In order to avoid weird sizeof edge cases.
 215 */
 216struct slot_count_req {
 217        u8      unused;
 218};
 219
 220/**
 221 * struct next_slot_req - NEXT_SLOT request.
 222 * @slot_uid:   Slot unique id of the next slot in the iteration.
 223 */
 224struct next_slot_req {
 225        u64     slot_uid;
 226};
 227
 228/**
 229 * struct slot_info_req - SLOT_INFO request.
 230 * @slot_uid:   Slot unique id mapped to the slot to get information about.
 231 */
 232struct slot_info_req {
 233        u64     slot_uid;
 234};
 235
 236/**
 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.
 240 */
 241struct slot_add_bulk_vcpus_req {
 242        u64     slot_uid;
 243        u64     nr_vcpus;
 244};
 245
 246/**
 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.
 259 */
 260struct ne_pci_dev_cmd_reply {
 261        s32     rc;
 262        u8      padding0[4];
 263        u64     slot_uid;
 264        u64     enclave_cid;
 265        u64     slot_count;
 266        u64     mem_regions;
 267        u64     mem_size;
 268        u64     nr_vcpus;
 269        u64     flags;
 270        u16     state;
 271        u8      padding1[6];
 272};
 273
 274/**
 275 * struct ne_pci_dev - Nitro Enclaves (NE) PCI device.
 276 * @cmd_reply_avail:            Variable set if a reply has been sent by the
 277 *                              PCI device.
 278 * @cmd_reply_wait_q:           Wait queue for handling command reply from the
 279 *                              PCI device.
 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
 285 *                              enclave process.
 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.
 290 */
 291struct ne_pci_dev {
 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;
 301};
 302
 303/**
 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.
 312 *
 313 * Context: Process context. This function uses the ne_pci_dev mutex to handle
 314 *          one command at a time.
 315 * Return:
 316 * * 0 on success.
 317 * * Negative return value on failure.
 318 */
 319int 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);
 323
 324/* Nitro Enclaves (NE) PCI device driver */
 325extern struct pci_driver ne_pci_driver;
 326
 327#endif /* _NE_PCI_DEV_H_ */
 328