2020-09-21 15:17:16 +03:00
/* SPDX-License-Identifier: GPL-2.0 */
/*
2021-08-27 18:49:26 +03:00
* Copyright 2020 - 2021 Amazon . com , Inc . or its affiliates . All Rights Reserved .
2020-09-21 15:17:16 +03:00
*/
# 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>
/**
* DOC : Nitro Enclaves ( NE ) PCI device
*/
/**
* PCI_DEVICE_ID_NE - Nitro Enclaves PCI device id .
*/
# define PCI_DEVICE_ID_NE (0xe4c1)
/**
* PCI_BAR_NE - Nitro Enclaves PCI device MMIO BAR .
*/
# define PCI_BAR_NE (0x03)
/**
* DOC : Device registers in the NE PCI device MMIO BAR
*/
/**
* NE_ENABLE - ( 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)
/**
* NE_VERSION - ( 2 bytes ) Register to select the device run - time version
* ( Read / Write ) .
*/
# define NE_VERSION (0x0002)
# define NE_VERSION_MAX (0x0001)
/**
* NE_COMMAND - ( 4 bytes ) Register to notify the device what command was
* requested ( Write - Only ) .
*/
# define NE_COMMAND (0x0004)
/**
* NE_EVTCNT - ( 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 )
/**
* NE_SEND_DATA - ( 240 bytes ) Buffer for sending the command request payload
* ( Read / Write ) .
*/
# define NE_SEND_DATA (0x0010)
/**
* NE_RECV_DATA - ( 240 bytes ) Buffer for receiving the command reply payload
* ( Read - Only ) .
*/
# define NE_RECV_DATA (0x0100)
/**
* DOC : Device MMIO buffer sizes
*/
/**
2021-08-27 18:49:26 +03:00
* NE_SEND_DATA_SIZE - Size of the send buffer , in bytes .
2020-09-21 15:17:16 +03:00
*/
# define NE_SEND_DATA_SIZE (240)
2021-08-27 18:49:26 +03:00
/**
* NE_RECV_DATA_SIZE - Size of the receive buffer , in bytes .
*/
2020-09-21 15:17:16 +03:00
# define NE_RECV_DATA_SIZE (240)
/**
* DOC : MSI - X interrupt vectors
*/
/**
* NE_VEC_REPLY - MSI - X vector used for command reply notification .
*/
# define NE_VEC_REPLY (0)
/**
* NE_VEC_EVENT - MSI - X vector used for out - of - band events e . g . enclave crash .
*/
# define NE_VEC_EVENT (1)
/**
* enum ne_pci_dev_cmd_type - Device command types .
* @ INVALID_CMD : Invalid command .
* @ ENCLAVE_START : Start an enclave , after setting its resources .
* @ ENCLAVE_GET_SLOT : Get the slot uid of an enclave .
* @ ENCLAVE_STOP : Terminate an enclave .
* @ SLOT_ALLOC : Allocate a slot for an enclave .
* @ SLOT_FREE : Free the slot allocated for an enclave
* @ SLOT_ADD_MEM : Add a memory region to an enclave slot .
* @ SLOT_ADD_VCPU : Add a vCPU to an enclave slot .
* @ SLOT_COUNT : Get the number of allocated slots .
* @ NEXT_SLOT : Get the next slot in the list of allocated slots .
* @ SLOT_INFO : Get the info for a slot e . g . slot uid , vCPUs count .
* @ SLOT_ADD_BULK_VCPUS : Add a number of vCPUs , not providing CPU ids .
* @ MAX_CMD : A gatekeeper for max possible command type .
*/
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 ,
} ;
/**
* DOC : Device commands - payload structure for requests and replies .
*/
/**
* struct enclave_start_req - ENCLAVE_START request .
* @ slot_uid : Slot unique id mapped to the enclave to start .
* @ enclave_cid : Context ID ( CID ) for the enclave vsock device .
* If 0 , CID is autogenerated .
* @ flags : Flags for the enclave to start with ( e . g . debug mode ) .
*/
struct enclave_start_req {
u64 slot_uid ;
u64 enclave_cid ;
u64 flags ;
} ;
/**
* struct enclave_get_slot_req - ENCLAVE_GET_SLOT request .
* @ enclave_cid : Context ID ( CID ) for the enclave vsock device .
*/
struct enclave_get_slot_req {
u64 enclave_cid ;
} ;
/**
* struct enclave_stop_req - ENCLAVE_STOP request .
* @ slot_uid : Slot unique id mapped to the enclave to stop .
*/
struct enclave_stop_req {
u64 slot_uid ;
} ;
/**
* struct slot_alloc_req - SLOT_ALLOC request .
* @ unused : In order to avoid weird sizeof edge cases .
*/
struct slot_alloc_req {
u8 unused ;
} ;
/**
* struct slot_free_req - SLOT_FREE request .
* @ slot_uid : Slot unique id mapped to the slot to free .
*/
struct slot_free_req {
u64 slot_uid ;
} ;
/* TODO: Add flags field to the request to add memory region. */
/**
* struct slot_add_mem_req - SLOT_ADD_MEM request .
* @ slot_uid : Slot unique id mapped to the slot to add the memory region to .
* @ paddr : Physical address of the memory region to add to the slot .
* @ size : Memory size , in bytes , of the memory region to add to the slot .
*/
struct slot_add_mem_req {
u64 slot_uid ;
u64 paddr ;
u64 size ;
} ;
/**
* struct slot_add_vcpu_req - SLOT_ADD_VCPU request .
* @ slot_uid : Slot unique id mapped to the slot to add the vCPU to .
* @ vcpu_id : vCPU ID of the CPU to add to the enclave .
* @ padding : Padding for the overall data structure .
*/
struct slot_add_vcpu_req {
u64 slot_uid ;
u32 vcpu_id ;
u8 padding [ 4 ] ;
} ;
/**
* struct slot_count_req - SLOT_COUNT request .
* @ unused : In order to avoid weird sizeof edge cases .
*/
struct slot_count_req {
u8 unused ;
} ;
/**
* struct next_slot_req - NEXT_SLOT request .
* @ slot_uid : Slot unique id of the next slot in the iteration .
*/
struct next_slot_req {
u64 slot_uid ;
} ;
/**
* struct slot_info_req - SLOT_INFO request .
* @ slot_uid : Slot unique id mapped to the slot to get information about .
*/
struct slot_info_req {
u64 slot_uid ;
} ;
/**
* struct slot_add_bulk_vcpus_req - SLOT_ADD_BULK_VCPUS request .
* @ slot_uid : Slot unique id mapped to the slot to add vCPUs to .
* @ nr_vcpus : Number of vCPUs to add to the slot .
*/
struct slot_add_bulk_vcpus_req {
u64 slot_uid ;
u64 nr_vcpus ;
} ;
/**
* struct ne_pci_dev_cmd_reply - NE PCI device command reply .
* @ rc : Return code of the logic that processed the request .
* @ padding0 : Padding for the overall data structure .
* @ slot_uid : Valid for all commands except SLOT_COUNT .
* @ enclave_cid : Valid for ENCLAVE_START command .
* @ slot_count : Valid for SLOT_COUNT command .
* @ mem_regions : Valid for SLOT_ALLOC and SLOT_INFO commands .
* @ mem_size : Valid for SLOT_INFO command .
* @ nr_vcpus : Valid for SLOT_INFO command .
* @ flags : Valid for SLOT_INFO command .
* @ state : Valid for SLOT_INFO command .
* @ padding1 : Padding for the overall data structure .
*/
struct ne_pci_dev_cmd_reply {
s32 rc ;
u8 padding0 [ 4 ] ;
u64 slot_uid ;
u64 enclave_cid ;
u64 slot_count ;
u64 mem_regions ;
u64 mem_size ;
u64 nr_vcpus ;
u64 flags ;
u16 state ;
u8 padding1 [ 6 ] ;
} ;
/**
* struct ne_pci_dev - Nitro Enclaves ( NE ) PCI device .
* @ cmd_reply_avail : Variable set if a reply has been sent by the
* PCI device .
* @ cmd_reply_wait_q : Wait queue for handling command reply from the
* PCI device .
* @ enclaves_list : List of the enclaves managed by the PCI device .
* @ enclaves_list_mutex : Mutex for accessing the list of enclaves .
* @ event_wq : Work queue for handling out - of - band events
* triggered by the Nitro Hypervisor which require
* enclave state scanning and propagation to the
* enclave process .
* @ iomem_base : MMIO region of the PCI device .
* @ notify_work : Work item for every received out - of - band event .
* @ pci_dev_mutex : Mutex for accessing the PCI device MMIO space .
* @ pdev : PCI device data structure .
*/
struct ne_pci_dev {
atomic_t cmd_reply_avail ;
wait_queue_head_t cmd_reply_wait_q ;
struct list_head enclaves_list ;
struct mutex enclaves_list_mutex ;
struct workqueue_struct * event_wq ;
void __iomem * iomem_base ;
struct work_struct notify_work ;
struct mutex pci_dev_mutex ;
struct pci_dev * pdev ;
} ;
/**
* ne_do_request ( ) - Submit command request to the PCI device based on the command
* type and retrieve the associated reply .
* @ 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 .
*
* Context : Process context . This function uses the ne_pci_dev mutex to handle
* one command at a time .
* Return :
* * 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_ */