File Index
Files and directories
Sign in
FILE

pci-tsm.h

File preview with syntax highlighting.

linux-6.19.14/include/linux/pci-tsm.h C
  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 */
~/ Read-only file preview.