xref: /linux/include/linux/pci-tsm.h (revision 249872f53d64441690927853e9d3af36394802d5)
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 
8 struct pci_tsm;
9 struct tsm_dev;
10 struct kvm;
11 enum 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  */
26 struct 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  */
86 struct 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  */
110 struct 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  */
123 struct 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' */
is_pci_tsm_pf0(struct pci_dev * pdev)130 static 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  */
170 enum 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
203 int pci_tsm_register(struct tsm_dev *tsm_dev);
204 void pci_tsm_unregister(struct tsm_dev *tsm_dev);
205 int pci_tsm_link_constructor(struct pci_dev *pdev, struct pci_tsm *tsm,
206 			     struct tsm_dev *tsm_dev);
207 int pci_tsm_pf0_constructor(struct pci_dev *pdev, struct pci_tsm_pf0 *tsm,
208 			    struct tsm_dev *tsm_dev);
209 void pci_tsm_pf0_destructor(struct pci_tsm_pf0 *tsm);
210 int pci_tsm_doe_transfer(struct pci_dev *pdev, u8 type, const void *req,
211 			 size_t req_sz, void *resp, size_t resp_sz);
212 int pci_tsm_bind(struct pci_dev *pdev, struct kvm *kvm, u32 tdi_id);
213 void pci_tsm_unbind(struct pci_dev *pdev);
214 void pci_tsm_tdi_constructor(struct pci_dev *pdev, struct pci_tdi *tdi,
215 			     struct kvm *kvm, u32 tdi_id);
216 ssize_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
pci_tsm_register(struct tsm_dev * tsm_dev)220 static inline int pci_tsm_register(struct tsm_dev *tsm_dev)
221 {
222 	return 0;
223 }
pci_tsm_unregister(struct tsm_dev * tsm_dev)224 static inline void pci_tsm_unregister(struct tsm_dev *tsm_dev)
225 {
226 }
pci_tsm_bind(struct pci_dev * pdev,struct kvm * kvm,u64 tdi_id)227 static inline int pci_tsm_bind(struct pci_dev *pdev, struct kvm *kvm, u64 tdi_id)
228 {
229 	return -ENXIO;
230 }
pci_tsm_unbind(struct pci_dev * pdev)231 static inline void pci_tsm_unbind(struct pci_dev *pdev)
232 {
233 }
pci_tsm_guest_req(struct pci_dev * pdev,enum pci_tsm_req_scope scope,sockptr_t req_in,size_t in_len,sockptr_t req_out,size_t out_len,u64 * tsm_code)234 static 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 */
244