at master 8.5 kB view raw
1/* SPDX-License-Identifier: GPL-2.0 */ 2#ifndef __PCI_TSM_H 3#define __PCI_TSM_H 4#include <linux/mutex.h> 5#include <linux/pci.h> 6#include <linux/sockptr.h> 7 8struct pci_tsm; 9struct tsm_dev; 10struct kvm; 11enum pci_tsm_req_scope; 12 13/* 14 * struct pci_tsm_ops - manage confidential links and security state 15 * @link_ops: Coordinate PCIe SPDM and IDE establishment via a platform TSM. 16 * Provide a secure session transport for TDISP state management 17 * (typically bare metal physical function operations). 18 * @devsec_ops: Lock, unlock, and interrogate the security state of the 19 * function via the platform TSM (typically virtual function 20 * operations). 21 * 22 * This operations are mutually exclusive either a tsm_dev instance 23 * manages physical link properties or it manages function security 24 * states like TDISP lock/unlock. 25 */ 26struct pci_tsm_ops { 27 /* 28 * struct pci_tsm_link_ops - Manage physical link and the TSM/DSM session 29 * @probe: establish context with the TSM (allocate / wrap 'struct 30 * pci_tsm') for follow-on link operations 31 * @remove: destroy link operations context 32 * @connect: establish / validate a secure connection (e.g. IDE) 33 * with the device 34 * @disconnect: teardown the secure link 35 * @bind: bind a TDI in preparation for it to be accepted by a TVM 36 * @unbind: remove a TDI from secure operation with a TVM 37 * @guest_req: marshal TVM information and state change requests 38 * 39 * Context: @probe, @remove, @connect, and @disconnect run under 40 * pci_tsm_rwsem held for write to sync with TSM unregistration and 41 * mutual exclusion of @connect and @disconnect. @connect and 42 * @disconnect additionally run under the DSM lock (struct 43 * pci_tsm_pf0::lock) as well as @probe and @remove of the subfunctions. 44 * @bind, @unbind, and @guest_req run under pci_tsm_rwsem held for read 45 * and the DSM lock. 46 */ 47 struct_group_tagged(pci_tsm_link_ops, link_ops, 48 struct pci_tsm *(*probe)(struct tsm_dev *tsm_dev, 49 struct pci_dev *pdev); 50 void (*remove)(struct pci_tsm *tsm); 51 int (*connect)(struct pci_dev *pdev); 52 void (*disconnect)(struct pci_dev *pdev); 53 struct pci_tdi *(*bind)(struct pci_dev *pdev, 54 struct kvm *kvm, u32 tdi_id); 55 void (*unbind)(struct pci_tdi *tdi); 56 ssize_t (*guest_req)(struct pci_tdi *tdi, 57 enum pci_tsm_req_scope scope, 58 sockptr_t req_in, size_t in_len, 59 sockptr_t req_out, size_t out_len, 60 u64 *tsm_code); 61 ); 62 63 /* 64 * struct pci_tsm_devsec_ops - Manage the security state of the function 65 * @lock: establish context with the TSM (allocate / wrap 'struct 66 * pci_tsm') for follow-on security state transitions from the 67 * LOCKED state 68 * @unlock: destroy TSM context and return device to UNLOCKED state 69 * 70 * Context: @lock and @unlock run under pci_tsm_rwsem held for write to 71 * sync with TSM unregistration and each other 72 */ 73 struct_group_tagged(pci_tsm_devsec_ops, devsec_ops, 74 struct pci_tsm *(*lock)(struct tsm_dev *tsm_dev, 75 struct pci_dev *pdev); 76 void (*unlock)(struct pci_tsm *tsm); 77 ); 78}; 79 80/** 81 * struct pci_tdi - Core TEE I/O Device Interface (TDI) context 82 * @pdev: host side representation of guest-side TDI 83 * @kvm: TEE VM context of bound TDI 84 * @tdi_id: Identifier (virtual BDF) for the TDI as referenced by the TSM and DSM 85 */ 86struct pci_tdi { 87 struct pci_dev *pdev; 88 struct kvm *kvm; 89 u32 tdi_id; 90}; 91 92/** 93 * struct pci_tsm - Core TSM context for a given PCIe endpoint 94 * @pdev: Back ref to device function, distinguishes type of pci_tsm context 95 * @dsm_dev: PCI Device Security Manager for link operations on @pdev 96 * @tsm_dev: PCI TEE Security Manager device for Link Confidentiality or Device 97 * Function Security operations 98 * @tdi: TDI context established by the @bind link operation 99 * 100 * This structure is wrapped by low level TSM driver data and returned by 101 * probe()/lock(), it is freed by the corresponding remove()/unlock(). 102 * 103 * For link operations it serves to cache the association between a Device 104 * Security Manager (DSM) and the functions that manager can assign to a TVM. 105 * That can be "self", for assigning function0 of a TEE I/O device, a 106 * sub-function (SR-IOV virtual function, or non-function0 107 * multifunction-device), or a downstream endpoint (PCIe upstream switch-port as 108 * DSM). 109 */ 110struct pci_tsm { 111 struct pci_dev *pdev; 112 struct pci_dev *dsm_dev; 113 struct tsm_dev *tsm_dev; 114 struct pci_tdi *tdi; 115}; 116 117/** 118 * struct pci_tsm_pf0 - Physical Function 0 TDISP link context 119 * @base_tsm: generic core "tsm" context 120 * @lock: mutual exclustion for pci_tsm_ops invocation 121 * @doe_mb: PCIe Data Object Exchange mailbox 122 */ 123struct pci_tsm_pf0 { 124 struct pci_tsm base_tsm; 125 struct mutex lock; 126 struct pci_doe_mb *doe_mb; 127}; 128 129/* physical function0 and capable of 'connect' */ 130static inline bool is_pci_tsm_pf0(struct pci_dev *pdev) 131{ 132 if (!pdev) 133 return false; 134 135 if (!pci_is_pcie(pdev)) 136 return false; 137 138 if (pdev->is_virtfn) 139 return false; 140 141 /* 142 * Allow for a Device Security Manager (DSM) associated with function0 143 * of an Endpoint to coordinate TDISP requests for other functions 144 * (physical or virtual) of the device, or allow for an Upstream Port 145 * DSM to accept TDISP requests for the Endpoints downstream of the 146 * switch. 147 */ 148 switch (pci_pcie_type(pdev)) { 149 case PCI_EXP_TYPE_ENDPOINT: 150 case PCI_EXP_TYPE_UPSTREAM: 151 case PCI_EXP_TYPE_RC_END: 152 if (pdev->ide_cap || (pdev->devcap & PCI_EXP_DEVCAP_TEE)) 153 break; 154 fallthrough; 155 default: 156 return false; 157 } 158 159 return PCI_FUNC(pdev->devfn) == 0; 160} 161 162/** 163 * enum pci_tsm_req_scope - Scope of guest requests to be validated by TSM 164 * 165 * Guest requests are a transport for a TVM to communicate with a TSM + DSM for 166 * a given TDI. A TSM driver is responsible for maintaining the kernel security 167 * model and limit commands that may affect the host, or are otherwise outside 168 * the typical TDISP operational model. 169 */ 170enum pci_tsm_req_scope { 171 /** 172 * @PCI_TSM_REQ_INFO: Read-only, without side effects, request for 173 * typical TDISP collateral information like Device Interface Reports. 174 * No device secrets are permitted, and no device state is changed. 175 */ 176 PCI_TSM_REQ_INFO = 0, 177 /** 178 * @PCI_TSM_REQ_STATE_CHANGE: Request to change the TDISP state from 179 * UNLOCKED->LOCKED, LOCKED->RUN, or other architecture specific state 180 * changes to support those transitions for a TDI. No other (unrelated 181 * to TDISP) device / host state, configuration, or data change is 182 * permitted. 183 */ 184 PCI_TSM_REQ_STATE_CHANGE = 1, 185 /** 186 * @PCI_TSM_REQ_DEBUG_READ: Read-only request for debug information 187 * 188 * A method to facilitate TVM information retrieval outside of typical 189 * TDISP operational requirements. No device secrets are permitted. 190 */ 191 PCI_TSM_REQ_DEBUG_READ = 2, 192 /** 193 * @PCI_TSM_REQ_DEBUG_WRITE: Device state changes for debug purposes 194 * 195 * The request may affect the operational state of the device outside of 196 * the TDISP operational model. If allowed, requires CAP_SYS_RAW_IO, and 197 * will taint the kernel. 198 */ 199 PCI_TSM_REQ_DEBUG_WRITE = 3, 200}; 201 202#ifdef CONFIG_PCI_TSM 203int pci_tsm_register(struct tsm_dev *tsm_dev); 204void pci_tsm_unregister(struct tsm_dev *tsm_dev); 205int pci_tsm_link_constructor(struct pci_dev *pdev, struct pci_tsm *tsm, 206 struct tsm_dev *tsm_dev); 207int pci_tsm_pf0_constructor(struct pci_dev *pdev, struct pci_tsm_pf0 *tsm, 208 struct tsm_dev *tsm_dev); 209void pci_tsm_pf0_destructor(struct pci_tsm_pf0 *tsm); 210int pci_tsm_doe_transfer(struct pci_dev *pdev, u8 type, const void *req, 211 size_t req_sz, void *resp, size_t resp_sz); 212int pci_tsm_bind(struct pci_dev *pdev, struct kvm *kvm, u32 tdi_id); 213void pci_tsm_unbind(struct pci_dev *pdev); 214void pci_tsm_tdi_constructor(struct pci_dev *pdev, struct pci_tdi *tdi, 215 struct kvm *kvm, u32 tdi_id); 216ssize_t pci_tsm_guest_req(struct pci_dev *pdev, enum pci_tsm_req_scope scope, 217 sockptr_t req_in, size_t in_len, sockptr_t req_out, 218 size_t out_len, u64 *tsm_code); 219#else 220static inline int pci_tsm_register(struct tsm_dev *tsm_dev) 221{ 222 return 0; 223} 224static inline void pci_tsm_unregister(struct tsm_dev *tsm_dev) 225{ 226} 227static inline int pci_tsm_bind(struct pci_dev *pdev, struct kvm *kvm, u64 tdi_id) 228{ 229 return -ENXIO; 230} 231static inline void pci_tsm_unbind(struct pci_dev *pdev) 232{ 233} 234static inline ssize_t pci_tsm_guest_req(struct pci_dev *pdev, 235 enum pci_tsm_req_scope scope, 236 sockptr_t req_in, size_t in_len, 237 sockptr_t req_out, size_t out_len, 238 u64 *tsm_code) 239{ 240 return -ENXIO; 241} 242#endif 243#endif /*__PCI_TSM_H */