coco/TSM: Host-side Arm CCA IDE setup via connect/disconnect callbacks
Subsystems (10)
Aneesh Kumar K.V (Arm)
maintainerv5 cover coco/TSM: Host-side Arm CCA IDE setup via connect/disconnect callbacks
This patch series implements the TSM ->connect() and ->disconnect() callbacks required for the Arm CCA IDE setup as per the RMM 2.0bet3 specification [1].
This patchset includes the host-side flow needed by connect/disconnect, including:
- DA feature detection helpers
- host TSM callback wiring and IDE stream allocation support
- creation/registration of RMM pdev descriptors
- RMM pdev communication helpers
- pdev stop and teardown helpers for disconnect
- pdev instantiation from the connect path
- public key registration with RMM
To support public-key handling from the device certificate chain, the series also includes the required X.509 parser updates.
Testing / Usage
To initiate the IDE setup:
echo tsm0 > /sys/bus/pci/devices/$DEVICE/tsm/connect
To disconnect:
echo tsm0 > /sys/bus/pci/devices/$DEVICE/tsm/disconnect
The series is based on:
- https://lore.kernel.org/all/[email protected]
- https://lore.kernel.org/all/[email protected]
Changes from v4:
https://lore.kernel.org/all/[email protected]
* Update rmi_set_pub_key() based on the latest specification.
* Rename structure members to match the specification.
* Rebase on top of the latest dependent series.
Changes from v3:
https://lore.kernel.org/all/[email protected]
* updated the patches to follow the RMM 2.0bet1 specification
* reworked the host-side pdev lifecycle to better match the RMM 2.0bet1 flow, including common pdev state, root-port pdev support, and non-coherent stream setup and teardown
* split PF0 setup into identity collection and conditional public-key installation, and gate DA enablement on RMI_FEATURE_REGISTER_2_DA
* added coordinated handling for RMI_DEV_COMM_EXIT_STREAM_WAIT, along with stream connect/disconnect and stream key refresh/purge support during vdev teardown
Changes from v2:
rfc-v2 https://lore.kernel.org/all/[email protected]
* rebase to latest kernel and core TSM changes
* Address review feedback.
v1:
rfc-v1 https://lore.kernel.org/all/[email protected]
[1] https://developer.arm.com/documentation/den0137/2-0bet3/
[2] https://lore.kernel.org/all/[email protected]
[3] https://lore.kernel.org/all/[email protected]
[4] https://gitlab.arm.com/linux-arm/linux-cca.git cca/topics/cca-tdisp-upstream-rfc-v4
Aneesh Kumar K.V (Arm) (12):
coco: host: arm64: Prepare host TSM plumbing for IDE streams
coco: host: arm64: Create RMM pdev objects for PCI endpoints
coco: host: arm64: Add RMM pdev communication plumbing
coco: host: arm64: Add RMM pdev stop and destroy helper
coco: host: arm64: Register device public key with RMM
coco: host: arm64: Initialize RMM pdev state for TDISP IDE connect
coco: host: arm64: Coordinate peer stream waits during pdev
communication
coco: host: arm64: Connect RMM pdev streams for IDE devices
coco: host: arm64: Refcount root-port pdevs used by IDE streams PCI/TSM: Move CMA DOE mailbox discovery out of
pci_tsm_pf0_constructor()
coco: host: arm64: Add NCOH_SYS stream support for RC endpoints
coco: host: arm64: Enable PCI TSM connect callbacks
Lukas Wunner (3):
X.509: Make certificate parser public
X.509: Parse Subject Alternative Name in certificates X.509: Move certificate length retrieval into new helper
crypto/asymmetric_keys/x509_cert_parser.c | 9 + crypto/asymmetric_keys/x509_loader.c | 38 +- crypto/asymmetric_keys/x509_parser.h | 42 +- drivers/crypto/ccp/sev-dev-tsm.c | 13 + drivers/firmware/arm_rmm/rmi.c | 4 +- drivers/firmware/smccc/smccc.c | 6 + drivers/pci/tsm.c | 13 +- drivers/virt/coco/Kconfig | 2 + drivers/virt/coco/Makefile | 1 + drivers/virt/coco/arm-cca-host/Kconfig | 26 + drivers/virt/coco/arm-cca-host/Makefile | 5 + drivers/virt/coco/arm-cca-host/main.c | 461 ++++++++++++ drivers/virt/coco/arm-cca-host/rmi-da.c | 859 ++++++++++++++++++++++ drivers/virt/coco/arm-cca-host/rmi-da.h | 217 ++++++ include/keys/asymmetric-type.h | 2 + include/keys/x509-parser.h | 57 ++ include/linux/arm-rmi-cmds.h | 85 +++ include/linux/arm-smccc-rmi.h | 161 ++++ 18 files changed, 1940 insertions(+), 61 deletions(-) create mode 100644 drivers/virt/coco/arm-cca-host/Kconfig create mode 100644 drivers/virt/coco/arm-cca-host/Makefile create mode 100644 drivers/virt/coco/arm-cca-host/main.c create mode 100644 drivers/virt/coco/arm-cca-host/rmi-da.c create mode 100644 drivers/virt/coco/arm-cca-host/rmi-da.h create mode 100644 include/keys/x509-parser.h
Signature · 1 line
2.43.0
Aneesh Kumar K.V (Arm)
maintainerPATCH v5 1/15 coco: host: arm64: Prepare host TSM plumbing for IDE streams
Add the initial Arm CCA host driver plumbing needed for device assignment support. Register the RMI SMCCC device, add the host TSM driver, and hook up the PCI TSM probe/remove callbacks when RMM reports Device Assignment support.
This patch only establishes the driver and per-device PCI TSM state needed by later patches. The RMM-facing pdev lifecycle, device communication, key setup, peer stream coordination, IDE stream setup, and connect/disconnect callbacks are added later in the series.
This keeps the patch as preparatory groundwork; complete enablement happens once the follow-up patches wire these pieces into the RMM stream lifecycle.
--- drivers/firmware/arm_rmm/rmi.c | 4 +- drivers/firmware/smccc/smccc.c | 6 + drivers/virt/coco/Kconfig | 2 + drivers/virt/coco/Makefile | 1 + drivers/virt/coco/arm-cca-host/Kconfig | 19 +++ drivers/virt/coco/arm-cca-host/Makefile | 5 + drivers/virt/coco/arm-cca-host/main.c | 192 ++++++++++++++++++++++++ drivers/virt/coco/arm-cca-host/rmi-da.h | 46 ++++++ 8 files changed, 273 insertions(+), 2 deletions(-) create mode 100644 drivers/virt/coco/arm-cca-host/Kconfig create mode 100644 drivers/virt/coco/arm-cca-host/Makefile create mode 100644 drivers/virt/coco/arm-cca-host/main.c create mode 100644 drivers/virt/coco/arm-cca-host/rmi-da.h
drivers/firmware/arm_rmm/rmi.c +2 -2
@@ -15,8 +15,8 @@static bool arm64_rmi_is_available; -/* Currently only the first 2 registers are used by Linux */ -#define RMI_FEAT_REG_COUNT 2 +/* Currently only the first 3 registers are used by Linux */ +#define RMI_FEAT_REG_COUNT 3static __ro_after_init unsigned long rmi_feat_reg_cache[RMI_FEAT_REG_COUNT ];unsigned long rmi_feat_reg (unsigned long id)
drivers/firmware/smccc/smccc.c +6 -0
@@ -11,6 +11,7 @@#include <linux/kernel.h> #include <linux/arm-smccc-bus.h> #include <linux/arm-smccc-rsi.h> +#include <linux/arm-smccc-rmi.h> #include <asm/archrandom.h>
@@ -100,6 +101,11 @@ static const struct smccc_device_info smccc_devices[] __initconst = { .requires_smc = true, .device_name = "arm-rsi", }, + { + .func_id = SMC_RMI_VERSION, + .requires_smc = true, + .device_name = "arm-rmi", + }, };static bool __init smccc_probe_smccc_device (const struct smccc_device_info *smccc_dev)
drivers/virt/coco/Kconfig +2 -0
@@ -19,5 +19,7 @@ endif source "drivers/virt/coco/tdx-host/Kconfig" +source "drivers/virt/coco/arm-cca-host/Kconfig" + config TSM bool
drivers/virt/coco/Makefile +1 -0
@@ -10,3 +10,4 @@ obj-$(CONFIG_INTEL_TDX_HOST) += tdx-host/ obj-$(CONFIG_ARM_CCA_GUEST) += arm-cca-guest/ obj-$(CONFIG_TSM) += tsm-core.o obj-$(CONFIG_TSM_GUEST) += guest/ +obj-$(CONFIG_ARM_CCA_HOST) += arm-cca-host/
drivers/virt/coco/arm-cca-host/Kconfig new file +19 -0
@@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# TSM (TEE Security Manager) host drivers +# +config ARM_CCA_HOST + tristate "Arm CCA Host driver" + depends on ARM64 + depends on PCI + depends on ARM_RMM_RMI + depends on HAVE_ARM_SMCCC_DISCOVERY + select PCI_TSM + + help + ARM CCA RMM firmware is the trusted runtime that enforces memory + isolation and security for confidential computing on ARM. This driver + provides the interface for communicating with RMM to support secure + device assignment. + + If you choose 'M' here, this module will be called arm-cca-host.
drivers/virt/coco/arm-cca-host/Makefile new file +5 -0
@@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +obj-$(CONFIG_ARM_CCA_HOST) += arm-cca-host.o + +arm-cca-host-y += main.o
drivers/virt/coco/arm-cca-host/main.c new file +192 -0
192 lines not on this page · raw message
drivers/virt/coco/arm-cca-host/rmi-da.h new file +46 -0
46 lines not on this page · raw message
Signature · 1 line
2.43.0
Aneesh Kumar K.V (Arm)
maintainerPATCH v5 2/15 coco: host: arm64: Create RMM pdev objects for PCI endpoints
In reply to Aneesh Kumar K.V (Arm)Add the RMI definitions needed for pdev management, including the pdev state enum, parameter layout, and helpers for RMI_PDEV_CREATE and RMI_PDEV_GET_STATE.
Introduce a host-side pdev descriptor and cca_pdev_create() to allocate and delegate the backing granule, populate the pdev parameters from the PCI endpoint, and issue RMI_PDEV_CREATE to the RMM.
The new helper stores the created RMM pdev handle in the PF0 endpoint descriptor preparing the device for later IDE/TDISP setup.
--- drivers/virt/coco/arm-cca-host/Makefile | 2 +- drivers/virt/coco/arm-cca-host/rmi-da.c | 146 ++++++++++++++++++++++++ drivers/virt/coco/arm-cca-host/rmi-da.h | 26 +++++ include/linux/arm-rmi-cmds.h | 11 ++ include/linux/arm-smccc-rmi.h | 43 +++++++ 5 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 drivers/virt/coco/arm-cca-host/rmi-da.c
drivers/virt/coco/arm-cca-host/Makefile +1 -1
@@ -2,4 +2,4 @@ # obj-$(CONFIG_ARM_CCA_HOST) += arm-cca-host.o -arm-cca-host-y += main.o +arm-cca-host-y += main.o rmi-da.o
drivers/virt/coco/arm-cca-host/rmi-da.c new file +146 -0
146 lines not on this page · raw message
drivers/virt/coco/arm-cca-host/rmi-da.h +26 -0
@@ -12,13 +12,26 @@#include <linux/pci-ide.h> #include <linux/pci-tsm.h> +/** +* struct cca_host_pdev_dsc - Common RMM pdev context +* @rmm_pdev: Delegated page backing the RMM pdev object +* @object_lock: Serializes access to the RMM pdev object and PF0/TDI caches +*/ +struct cca_host_pdev_dsc { +void *rmm_pdev; +/* lock kept here to simplify the generic lock/unlock paths. */ +struct mutex object_lock; +}; +/** * struct cca_host_pf0_ep_dsc - PF0 endpoint device security context. * @pci: Physical Function 0 TDISP link context +* @pdev: pdev communication context * @sel_stream: Selective IDE Stream descriptor */ struct cca_host_pf0_ep_dsc {struct pci_tsm_pf0 pci; +struct cca_host_pdev_dsc pdev;struct pci_ide *sel_stream; };
@@ -43,4 +56,17 @@ static inline struct cca_host_fn_dsc *to_cca_fn_dsc(struct pci_dev *pdev) return container_of(tsm, struct cca_host_fn_dsc, pci); } +static inline struct cca_host_pdev_dsc *to_cca_pdev_dsc (struct pci_dev *pdev) +{ +struct cca_host_pf0_ep_dsc *pf0_ep_dsc; + + pf0_ep_dsc =to_cca_pf0_ep_dsc (pdev); +if (pf0_ep_dsc) +return &pf0_ep_dsc->pdev; + +return NULL ; +} + +int cca_pdev_create (struct pci_dev *pdev); +#endif
include/linux/arm-rmi-cmds.h +11 -0
@@ -8,6 +8,7 @@#include <linux/arm-smccc-rmi.h> #include <linux/bug.h> +#include <linux/gfp_types.h> #include <linux/types.h> #define RMI_MAX_ADDR_LIST 256
@@ -675,4 +676,14 @@ static inline long rmi_rtt_unprot_unmap(unsigned long rd, return ret; } +static inline unsigned long rmi_pdev_get_state (unsigned long pdev_phys,enum rmi_pdev_state *state) +{ +struct arm_smccc_res res; + +arm_smccc_1_1_invoke (SMC_RMI_PDEV_GET_STATE , pdev_phys, &res); + + *state = res.a1; +return res.a0; +} +#endif
include/linux/arm-smccc-rmi.h +43 -0
47 lines not on this page · raw message
Signature · 1 line
2.43.0
Aneesh Kumar K.V (Arm)
maintainerPATCH v5 3/15 coco: host: arm64: Add RMM pdev communication plumbing
In reply to Aneesh Kumar K.V (Arm)RMM pdev state transitions and SPDM exchanges are driven through RMI_PDEV_COMMUNICATE after the pdev object has been created. Add the host-side communication infrastructure needed to service those requests.
Define the RMI device communication ABI, add the PDEV_COMMUNICATE and PDEV_ABORT SMCCC wrappers, and allocate the per-PF0 communication pages and ordered workqueue. Add helpers that submit communication requests to RMM, perform the requested DOE SPDM/Secure SPDM transfers, cache multi-part device data such as VCA and certificate-chain objects, and wait for target RMM pdev states under the pdev object lock.
This only adds the shared communication machinery. Later patches use it for public-key registration, pdev initialization, stream setup, and the final connect/disconnect callbacks.
--- drivers/virt/coco/arm-cca-host/main.c | 50 +++++ drivers/virt/coco/arm-cca-host/rmi-da.c | 276 ++++++++++++++++++++++++ drivers/virt/coco/arm-cca-host/rmi-da.h | 65 ++++++ include/linux/arm-rmi-cmds.h | 20 ++ include/linux/arm-smccc-rmi.h | 62 ++++++ 5 files changed, 473 insertions(+)
drivers/virt/coco/arm-cca-host/main.c +50 -0
@@ -44,6 +44,7 @@ static struct pci_tsm *cca_tsm_pci_probe(struct tsm_dev *tsm_dev, struct pci_dev ret =pci_tsm_pf0_constructor (pdev, &pf0_ep_dsc->pci, tsm_dev);if (ret)return NULL ; +mutex_init (&pf0_ep_dsc->pdev.object_lock);pci_dbg (pdev,"tsm enabled\n" );return &no_free_ptr (pf0_ep_dsc)->pci.base_tsm;
@@ -63,6 +64,55 @@ static void cca_tsm_pci_remove(struct pci_tsm *tsm) } } +static __maybe_unused int init_dev_communication_buffers (struct pci_dev *pdev, +struct cca_host_comm_data *comm_data) +{ +int ret = -ENOMEM ; + + comm_data->io_params = (struct rmi_dev_comm_data *)get_zeroed_page (GFP_KERNEL ); +if (!comm_data->io_params) + goto err_out; + + comm_data->rsp_buff = (void *)__get_free_page (GFP_KERNEL ); +if (!comm_data->rsp_buff) + goto err_res_buff; + + comm_data->req_buff = (void *)__get_free_page (GFP_KERNEL ); +if (!comm_data->req_buff) + goto err_req_buff; + + comm_data->work_queue =alloc_ordered_workqueue ("%s %s DEV_COMM" ,0 , +dev_bus_name (&pdev->dev), +pci_name (pdev)); +if (!comm_data->work_queue) + goto err_work_queue; + + comm_data->io_params->enter.status =RMI_DEV_COMM_NONE ; + comm_data->io_params->enter.resp_addr =virt_to_phys (comm_data->rsp_buff); + comm_data->io_params->enter.req_addr =virt_to_phys (comm_data->req_buff); + comm_data->io_params->enter.resp_len =0 ; + +return 0 ; + +err_work_queue: +free_page ((unsigned long )comm_data->req_buff); +err_req_buff: +free_page ((unsigned long )comm_data->rsp_buff); +err_res_buff: +free_page ((unsigned long )comm_data->io_params); +err_out: +return ret; +} + +static inline void free_dev_communication_buffers (struct cca_host_comm_data *comm_data) +{ +destroy_workqueue (comm_data->work_queue); + +free_page ((unsigned long )comm_data->req_buff); +free_page ((unsigned long )comm_data->rsp_buff); +free_page ((unsigned long )comm_data->io_params); +} +static inline bool cca_pdev_need_sel_ide_streams (struct pci_dev *pdev) {return pci_pcie_type (pdev) ==PCI_EXP_TYPE_ENDPOINT ;
drivers/virt/coco/arm-cca-host/rmi-da.c +276 -0
285 lines not on this page · raw message
drivers/virt/coco/arm-cca-host/rmi-da.h +65 -0
101 lines not on this page · raw message
include/linux/arm-rmi-cmds.h +20 -0
@@ -686,4 +686,24 @@ static inline unsigned long rmi_pdev_get_state(unsigned long pdev_phys, enum rmi return res.a0; } +static inline unsigned long rmi_pdev_communicate (unsigned long pdev_phys, +unsigned long pdev_comm_data_phys) +{ +struct arm_smccc_res res; + +arm_smccc_1_1_invoke (SMC_RMI_PDEV_COMMUNICATE , + pdev_phys, pdev_comm_data_phys, &res); + +return res.a0; +} + +static inline unsigned long rmi_pdev_abort (unsigned long pdev_phys) +{ +struct arm_smccc_res res; + +arm_smccc_1_1_invoke (SMC_RMI_PDEV_ABORT , pdev_phys, &res); + +return res.a0; +} +#endif
include/linux/arm-smccc-rmi.h +62 -0
66 lines not on this page · raw message
Signature · 1 line
2.43.0
Aneesh Kumar K.V (Arm)
maintainerPATCH v5 4/15 coco: host: arm64: Add RMM pdev stop and destroy helper
In reply to Aneesh Kumar K.V (Arm)Add the host-side helper needed to tear down an RMM pdev object once later disconnect and error paths are wired up.
Describe RMI_PDEV_STOP and RMI_PDEV_DESTROY, add the PDEV_STOP SMCCC wrapper, and issue PDEV_DESTROY through the SRO helper. The new teardown helper stops the pdev, drives device communication until RMM reports RMI_PDEV_STOPPED, destroys the RMM object, releases cached PF0 device-communication state, and undelegates the backing granule.
No caller is added here; this prepares the teardown side of the RMM pdev lifecycle for the follow-up patches that connect it to IDE stream disconnect.
--- drivers/virt/coco/arm-cca-host/rmi-da.c | 47 ++++++++++++++++++++++++- drivers/virt/coco/arm-cca-host/rmi-da.h | 1 + include/linux/arm-rmi-cmds.h | 9 +++++ 3 files changed, 56 insertions(+), 1 deletion(-)
drivers/virt/coco/arm-cca-host/rmi-da.c +46 -1
@@ -394,7 +394,7 @@ static void pdev_state_transition_workfn(struct work_struct *work)WARN_ON (state != setup_work->target_state); } -static int __maybe_unused submit_pdev_state_transition_work (struct pci_dev *pdev, +static int submit_pdev_state_transition_work (struct pci_dev *pdev,enum rmi_pdev_state target_state) {enum rmi_pdev_state state;
@@ -420,3 +420,48 @@ static int __maybe_unused submit_pdev_state_transition_work(struct pci_dev *pdevreturn -1 ;return 0 ; } + +static inline int rmi_pdev_destroy (unsigned long pdev_phys, +unsigned long *rmi_ret) +{ + struct rmi_sro_state *sro __free(kfree) = kmalloc_obj(*sro); +if (!sro) +return -ENOMEM ; + + *rmi_ret =rmi_sro_memxfer_cmd (sro,GFP_KERNEL , +SMC_RMI_PDEV_DESTROY , pdev_phys); + +return 0 ; +} + +void cca_pdev_stop_and_destroy (struct pci_dev *pdev) +{ +int ret; +unsigned long rmi_ret; +struct cca_host_pdev_dsc *pdev_dsc =to_cca_pdev_dsc (pdev); +struct cca_host_pf0_ep_dsc *pf0_ep_dsc =to_cca_pf0_ep_dsc (pdev); +phys_addr_t rmm_pdev_phys =virt_to_phys (pdev_dsc->rmm_pdev); + +if (WARN_ON (rmi_pdev_stop (rmm_pdev_phys))) +return ; + + ret =submit_pdev_state_transition_work (pdev,RMI_PDEV_STOPPED ); +if (ret) +return ; + + ret =rmi_pdev_destroy (rmm_pdev_phys, &rmi_ret); +if (WARN_ON (ret || rmi_ret)) +return ; + +if (pf0_ep_dsc) { +kfree (pf0_ep_dsc->cert_chain.public_key); +kvfree (pf0_ep_dsc->cert_chain.cache); +kvfree (pf0_ep_dsc->vca); + pf0_ep_dsc->cert_chain.cache =NULL ; + pf0_ep_dsc->vca =NULL ; + } + +if (!rmi_undelegate_page (rmm_pdev_phys)) +free_page ((unsigned long )pdev_dsc->rmm_pdev); + pdev_dsc->rmm_pdev =NULL ; +}
drivers/virt/coco/arm-cca-host/rmi-da.h +1 -0
@@ -133,5 +133,6 @@ static inline struct cca_host_comm_data *to_cca_comm_data(struct pci_dev *pdev) }int cca_pdev_create (struct pci_dev *pdev); +void cca_pdev_stop_and_destroy (struct pci_dev *pdev);#endif
include/linux/arm-rmi-cmds.h +9 -0
@@ -706,4 +706,13 @@ static inline unsigned long rmi_pdev_abort(unsigned long pdev_phys) return res.a0; } +static inline unsigned long rmi_pdev_stop (unsigned long pdev_phys) +{ +struct arm_smccc_res res; + +arm_smccc_1_1_invoke (SMC_RMI_PDEV_STOP , pdev_phys, &res); + +return res.a0; +} +#endif
Signature · 1 line
2.43.0
Aneesh Kumar K.V (Arm)
maintainerPATCH v5 5/15 X.509: Make certificate parser public
In reply to Aneesh Kumar K.V (Arm)From: Lukas Wunner <[email protected]>
The upcoming support for PCI device authentication with CMA-SPDM (PCIe r6.1 sec 6.31) requires validating the Subject Alternative Name in X.509 certificates.
High-level functions for X.509 parsing such as key_create_or_update() throw away the internal, low-level struct x509_certificate after extracting the struct public_key and public_key_signature from it. The Subject Alternative Name is thus inaccessible when using those functions.
Afford CMA-SPDM access to the Subject Alternative Name by making struct x509_certificate public, together with the functions for parsing an X.509 certificate into such a struct and freeing such a struct.
The private header file x509_parser.h previously included <linux/time.h> for the definition of time64_t. That definition was since moved to <linux/time64.h> by commit 361a3bf00582 ("time64: Add time64.h header and define struct timespec64"), so adjust the #include directive as part of the move to the new public header file <keys/x509-parser.h>.
No functional change intended.
--- crypto/asymmetric_keys/x509_parser.h | 42 +-------------------- include/keys/x509-parser.h | 55 ++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 41 deletions(-) create mode 100644 include/keys/x509-parser.h
crypto/asymmetric_keys/x509_parser.h +1 -41
@@ -5,51 +5,11 @@* Written by David Howells ([email protected]) */ -#include <linux/cleanup.h> -#include <linux/time.h> -#include <crypto/public_key.h> -#include <keys/asymmetric-type.h> -#include <crypto/sha2.h> - -struct x509_certificate { -struct x509_certificate *next; -struct x509_certificate *signer;/* Certificate that signed this one */ -struct public_key *pub;/* Public key details */ -struct public_key_signature *sig;/* Signature parameters */ -u8 sha256[SHA256_DIGEST_SIZE ];/* Hash for blacklist purposes */ -char *issuer;/* Name of certificate issuer */ -char *subject;/* Name of certificate subject */ -struct asymmetric_key_id *id;/* Issuer + Serial number */ -struct asymmetric_key_id *skid;/* Subject + subjectKeyId (optional) */ -time64_t valid_from; -time64_t valid_to; -const void *tbs;/* Signed data */ -unsigned tbs_size;/* Size of signed data */ -unsigned raw_sig_size;/* Size of signature */ -const void *raw_sig;/* Signature data */ -const void *raw_serial;/* Raw serial number in ASN.1 */ -unsigned raw_serial_size; -unsigned raw_issuer_size; -const void *raw_issuer;/* Raw issuer name in ASN.1 */ -const void *raw_subject;/* Raw subject name in ASN.1 */ -unsigned raw_subject_size; -unsigned raw_skid_size; -const void *raw_skid;/* Raw subjectKeyId in ASN.1 */ -unsigned index; -bool seen;/* Infinite recursion prevention */ -bool verified; -bool self_signed;/* T if self-signed (check unsupported_sig too) */ -bool unsupported_sig;/* T if signature uses unsupported crypto */ -bool blacklisted; -}; +#include <keys/x509-parser.h> /* * x509_cert_parser.c */ -extern void x509_free_certificate (struct x509_certificate *cert); -DEFINE_FREE(x509_free_certificate, struct x509_certificate *, - if (!IS_ERR(_T)) x509_free_certificate(_T)) -extern struct x509_certificate *x509_cert_parse (const void *data,size_t datalen);extern int x509_decode_time (time64_t *_t,size_t hdrlen,unsigned char tag,const unsigned char *value,size_t vlen);
include/keys/x509-parser.h new file +55 -0
55 lines not on this page · raw message
Signature · 1 line
2.43.0
Aneesh Kumar K.V (Arm)
maintainerPATCH v5 6/15 X.509: Parse Subject Alternative Name in certificates
In reply to Aneesh Kumar K.V (Arm)From: Lukas Wunner <[email protected]>
The upcoming support for PCI device authentication with CMA-SPDM (PCIe r6.1 sec 6.31) requires validating the Subject Alternative Name in X.509 certificates.
Store a pointer to the Subject Alternative Name upon parsing for consumption by CMA-SPDM.
--- crypto/asymmetric_keys/x509_cert_parser.c | 9 +++++++++ include/keys/x509-parser.h | 2 ++ 2 files changed, 11 insertions(+)
crypto/asymmetric_keys/x509_cert_parser.c +9 -0
@@ -596,6 +596,15 @@ int x509_process_extension(void *context, size_t hdrlen,return 0 ; } +if (ctx->last_oid == OID_subjectAltName) { +if (ctx->cert->raw_san) +return -EBADMSG ; + + ctx->cert->raw_san = v; + ctx->cert->raw_san_size = vlen; +return 0 ; + } +if (ctx->last_oid == OID_keyUsage) {/* * Get hold of the keyUsage bit string
include/keys/x509-parser.h +2 -0
@@ -38,6 +38,8 @@ struct x509_certificate {unsigned raw_subject_size;unsigned raw_skid_size;const void *raw_skid;/* Raw subjectKeyId in ASN.1 */ +const void *raw_san;/* Raw subjectAltName in ASN.1 */ +unsigned raw_san_size;unsigned index;bool seen;/* Infinite recursion prevention */ bool verified;
Signature · 1 line
2.43.0
Aneesh Kumar K.V (Arm)
maintainerPATCH v5 7/15 X.509: Move certificate length retrieval into new helper
In reply to Aneesh Kumar K.V (Arm)From: Lukas Wunner <[email protected]>
The upcoming in-kernel SPDM library (Security Protocol and Data Model,
https://www.dmtf.org/dsp/DSP0274) needs to retrieve the length from ASN.1 DER-encoded X.509 certificates.
Such code already exists in x509_load_certificate_list(), so move it into a new helper for reuse by SPDM.
Export the helper so that SPDM can be tristate. (Some upcoming users of the SPDM libray may be modular, such as SCSI and ATA.)
No functional change intended.
--- crypto/asymmetric_keys/x509_loader.c | 38 +++++++++++++++++++--------- include/keys/asymmetric-type.h | 2 ++ 2 files changed, 28 insertions(+), 12 deletions(-)
crypto/asymmetric_keys/x509_loader.c +26 -12
@@ -4,28 +4,42 @@#include <linux/key.h> #include <keys/asymmetric-type.h> +ssize_t x509_get_certificate_length (const u8 *p,unsigned long buflen) +{ +ssize_t plen; + +/* Each cert begins with an ASN.1 SEQUENCE tag and must be more +* than 256 bytes in size. +*/ +if (buflen <4 ) +return -EINVAL ; + +if (p[0 ] !=0x30 || + p[1 ] !=0x82 ) +return -EINVAL ; + + plen = (p[2 ] <<8 ) | p[3 ]; + plen +=4 ; +if (plen > buflen) +return -EINVAL ; + +return plen; +} +EXPORT_SYMBOL_GPL (x509_get_certificate_length); +int x509_load_certificate_list (const u8 cert_list[],const unsigned long list_size,const struct key *keyring) {key_ref_t key;const u8 *p, *end; -size_t plen; +ssize_t plen; p = cert_list; end = p + list_size;while (p < end) { -/* Each cert begins with an ASN.1 SEQUENCE tag and must be more -* than 256 bytes in size. -*/ -if (end - p <4 ) - goto dodgy_cert; -if (p[0 ] !=0x30 || - p[1 ] !=0x82 ) - goto dodgy_cert; - plen = (p[2 ] <<8 ) | p[3 ]; - plen +=4 ; -if (plen > end - p) + plen =x509_get_certificate_length (p, end - p); +if (plen <0 ) goto dodgy_cert; key = key_create_or_update(make_key_ref(keyring, 1),
include/keys/asymmetric-type.h +2 -0
@@ -84,6 +84,8 @@ extern struct key *find_asymmetric_key(struct key *keyring,const struct asymmetric_key_id *id_2, bool partial); +ssize_t x509_get_certificate_length (const u8 *p,unsigned long buflen); +int x509_load_certificate_list (const u8 cert_list[],const unsigned long list_size,const struct key *keyring);
Signature · 1 line
2.43.0
Aneesh Kumar K.V (Arm)
maintainerPATCH v5 8/15 coco: host: arm64: Register device public key with RMM
In reply to Aneesh Kumar K.V (Arm)- Introduce the SMC_RMI_PDEV_SET_PUBKEY helper and the associated struct rmi_public_key_params so the host can hand the device’s public key to the RMM.
- Parse the certificate chain cached during SPDM session setup, extract the final certificate’s public key, and recognise RSA-3072, ECDSA-P256, and ECDSA-P384 keys before calling into the RMM.
--- drivers/virt/coco/arm-cca-host/Kconfig | 7 ++ drivers/virt/coco/arm-cca-host/rmi-da.c | 152 ++++++++++++++++++++++++ drivers/virt/coco/arm-cca-host/rmi-da.h | 2 + include/linux/arm-rmi-cmds.h | 9 ++ include/linux/arm-smccc-rmi.h | 18 +++ 5 files changed, 188 insertions(+)
drivers/virt/coco/arm-cca-host/Kconfig +7 -0
@@ -9,6 +9,13 @@ config ARM_CCA_HOST depends on ARM_RMM_RMI depends on HAVE_ARM_SMCCC_DISCOVERY select PCI_TSM + select KEYS + select ASYMMETRIC_KEY_TYPE + select ASYMMETRIC_PUBLIC_KEY_SUBTYPE + select CRYPTO + select X509_CERTIFICATE_PARSER + select CRYPTO_ECDSA + select CRYPTO_RSA help ARM CCA RMM firmware is the trusted runtime that enforces memory
drivers/virt/coco/arm-cca-host/rmi-da.c +152 -0
170 lines not on this page · raw message
drivers/virt/coco/arm-cca-host/rmi-da.h +2 -0
@@ -59,6 +59,7 @@ struct cca_host_pdev_dsc {* @pci: Physical Function 0 TDISP link context * @pdev: pdev communication context * @sel_stream: Selective IDE Stream descriptor +* @rmi_signature_algorithm: Signature algorithm used for public key * @cert_chain: cetrificate chain * @vca: SPDM's Version-Capabilities-Algorithms cache object */
@@ -67,6 +68,7 @@ struct cca_host_pf0_ep_dsc {struct cca_host_pdev_dsc pdev;struct pci_ide *sel_stream; +char *rmi_signature_algorithm;struct {struct cache_object *cache;
include/linux/arm-rmi-cmds.h +9 -0
@@ -715,4 +715,13 @@ static inline unsigned long rmi_pdev_stop(unsigned long pdev_phys) return res.a0; } +static inline unsigned long rmi_pdev_set_pubkey (unsigned long pdev_phys,unsigned long key_phys) +{ +struct arm_smccc_res res; + +arm_smccc_1_1_invoke (SMC_RMI_PDEV_SET_PUBKEY , pdev_phys, key_phys, &res); + +return res.a0; +} +#endif
include/linux/arm-smccc-rmi.h +18 -0
@@ -596,4 +596,22 @@ struct rmi_dev_comm_data { }; }; +struct rmi_public_key_params { +union { +struct { +union {/* 0x0 */ +u64 key_addr; +u8 padding0[0x400 ]; + }; +union {/* 0x400 */ +u64 metadata_addr; +u8 padding1[0x400 ]; + }; +u64 key_len; +u64 metadata_len; + }; +u8 padding[0x1000 ]; + }; +}; +#endif /* __LINUX_ARM_SMCCC_RMI_H_ */
Signature · 1 line
2.43.0
Aneesh Kumar K.V (Arm)
maintainerPATCH v5 9/15 coco: host: arm64: Initialize RMM pdev state for TDISP IDE connect
In reply to Aneesh Kumar K.V (Arm)Update connect() to:
- allocate device-communication buffers,
- create the RMM pdev object,
- perform initial device communication to collect identity, and
- set the device public key when the pdev enters NEEDS_KEY.
--- drivers/virt/coco/arm-cca-host/main.c | 47 ++++++++++--- drivers/virt/coco/arm-cca-host/rmi-da.c | 90 ++++++++++++++++++++++++- drivers/virt/coco/arm-cca-host/rmi-da.h | 3 + 3 files changed, 130 insertions(+), 10 deletions(-)
drivers/virt/coco/arm-cca-host/main.c +39 -8
@@ -64,7 +64,7 @@ static void cca_tsm_pci_remove(struct pci_tsm *tsm) } } -static __maybe_unused int init_dev_communication_buffers (struct pci_dev *pdev, +static int init_dev_communication_buffers (struct pci_dev *pdev,struct cca_host_comm_data *comm_data) {int ret = -ENOMEM ;
@@ -158,15 +158,43 @@ static int __maybe_unused cca_tsm_connect(struct pci_dev *pdev) ide->partner[PCI_IDE_EP ].default_stream =1 ;pci_ide_stream_setup (pdev, ide);pci_ide_stream_setup (rp, ide); + } -/* -* Once ide is setup, enable the stream at the endpoint -* Root port will be done by RMM -*/ -pci_ide_stream_enable (pdev, ide); + ret =init_dev_communication_buffers (pdev, &pf0_ep_dsc->pdev.comm_data); +if (ret) + goto err_comm_buff; + ret =cca_pdev_create (pdev); +if (ret) + goto err_pdev_create; + + ret =cca_pdev_collect_identity (pdev); +if (ret) + goto pdev_destroy; + +if (cca_pdev_needs_key (pdev)) { + ret =cca_pdev_set_public_key (pdev); +if (ret) + goto pdev_destroy; } +/* +* Once ide is setup, enable the stream at the endpoint +* Root port will be done by RMM +*/ +if (cca_pdev_need_sel_ide_streams (pdev)) +pci_ide_stream_enable (pdev, ide); +return 0 ; +pdev_destroy: +cca_pdev_stop_and_destroy (pdev); +err_pdev_create: +free_dev_communication_buffers (&pf0_ep_dsc->pdev.comm_data); +err_comm_buff: +if (cca_pdev_need_sel_ide_streams (pdev)) { +pci_ide_stream_teardown (rp, ide); +pci_ide_stream_teardown (pdev, ide); +pci_ide_stream_unregister (ide); + } err_stream:if (cca_pdev_need_sel_ide_streams (pdev))pci_ide_stream_free (ide);
@@ -185,13 +213,16 @@ static void __maybe_unused cca_tsm_disconnect(struct pci_dev *pdev)if (!pf0_ep_dsc)return ; -if (cca_pdev_need_sel_ide_streams (pdev)) { +if (cca_pdev_need_sel_ide_streams (pdev)) ide = pf0_ep_dsc->sel_stream; +cca_pdev_stop_and_destroy (pdev); +free_dev_communication_buffers (&pf0_ep_dsc->pdev.comm_data); + +if (cca_pdev_need_sel_ide_streams (pdev)) {pci_ide_stream_release (ide); pf0_ep_dsc->sel_stream =NULL ; } - }static struct pci_tsm_ops cca_link_pci_ops = {
drivers/virt/coco/arm-cca-host/rmi-da.c +88 -2
108 lines not on this page · raw message
drivers/virt/coco/arm-cca-host/rmi-da.h +3 -0
@@ -135,6 +135,9 @@ static inline struct cca_host_comm_data *to_cca_comm_data(struct pci_dev *pdev) }int cca_pdev_create (struct pci_dev *pdev); +int cca_pdev_collect_identity (struct pci_dev *pdev); +bool cca_pdev_needs_key (struct pci_dev *pdev); +int cca_pdev_set_public_key (struct pci_dev *pdev);void cca_pdev_stop_and_destroy (struct pci_dev *pdev);#endif
Signature · 1 line
2.43.0
Aneesh Kumar K.V (Arm)
maintainerPATCH v5 10/15 coco: host: arm64: Coordinate peer stream waits during pdev communication
In reply to Aneesh Kumar K.V (Arm)RMM stream operations can return RMI_DEV_COMM_EXIT_STREAM_WAIT while one side waits for the peer stream to reach the matching point in the protocol.
Teach arm-cca host device communication to detect STREAM_WAIT and add a helper that runs pdev communication for both sides in parallel until each side has made enough progress, then issue rmi_pdev_stream_complete().
This provides the synchronization needed for stream connect, disconnect, key refresh, and key purge operations.
--- drivers/virt/coco/arm-cca-host/rmi-da.c | 116 +++++++++++++++++++++++- drivers/virt/coco/arm-cca-host/rmi-da.h | 13 +++ include/linux/arm-smccc-rmi.h | 1 + 3 files changed, 125 insertions(+), 5 deletions(-)
drivers/virt/coco/arm-cca-host/rmi-da.c +111 -5
@@ -192,7 +192,7 @@ static inline gfp_t cache_obj_id_to_gfp_flags(u8 cache_obj_id)return GFP_KERNEL_ACCOUNT ; } -static int _do_dev_communicate (enum dev_comm_type type,struct pci_tsm *tsm) +static int _do_dev_communicate (enum dev_comm_type type,struct pci_tsm *tsm,int *stream_wait) {unsigned long rmi_ret;gfp_t cache_alloc_flags;
@@ -324,11 +324,17 @@ static int _do_dev_communicate(enum dev_comm_type type, struct pci_tsm *tsm)if (pending_dev_communicate (io_exit)) goto redo_communicate; +if (io_exit->flags &RMI_DEV_COMM_EXIT_STREAM_WAIT ) { +if (stream_wait) + *stream_wait =1 ; +else +WARN (1 ,"Unexpected Stream wait status\n" ); + }return 0 ; }static int do_dev_communicate (enum dev_comm_type type, -struct pci_tsm *tsm,unsigned long error_state) +struct pci_tsm *tsm,unsigned long error_state,int *stream_wait) {int ret, state = error_state;struct rmi_dev_comm_enter *io_enter;
@@ -337,8 +343,10 @@ static int do_dev_communicate(enum dev_comm_type type, io_enter = &pdev_dsc->comm_data.io_params->enter; io_enter->resp_len =0 ; io_enter->status =RMI_DEV_COMM_NONE ; +if (stream_wait) + *stream_wait =0 ; - ret =_do_dev_communicate (type, tsm); + ret =_do_dev_communicate (type, tsm, stream_wait);if (ret) {if (type ==PDEV_COMMUNICATE )rmi_pdev_abort (virt_to_phys (pdev_dsc->rmm_pdev));
@@ -366,7 +374,7 @@ static int wait_for_dev_state(enum dev_comm_type type, struct pci_tsm *tsm,int state; do { - state = do_dev_communicate(type, tsm, error_state); + state = do_dev_communicate(type, tsm, error_state, NULL); if (state == target_state || state == error_state) return state;
@@ -584,7 +592,7 @@ static void pdev_collect_identity_workfn(struct work_struct *work)guard (mutex)(&pdev_dsc->object_lock); -do_dev_communicate (PDEV_COMMUNICATE , tsm,RMI_PDEV_ERROR ); +do_dev_communicate (PDEV_COMMUNICATE , tsm,RMI_PDEV_ERROR ,NULL );/* * Don't worry about communication error. The caller will look at
@@ -703,3 +711,101 @@ void cca_pdev_stop_and_destroy(struct pci_dev *pdev)free_page ((unsigned long )pdev_dsc->rmm_pdev); pdev_dsc->rmm_pdev =NULL ; } + +static void stream_connect_workfn (struct work_struct *work) +{ +int state; +int peer_wait =0 ; +struct pci_tsm *tsm; +int my_index, peer_index, target; +struct stream_connect_work *stream_work; +struct cca_host_pdev_dsc *pdev_dsc; + + stream_work = container_of(work, struct stream_connect_work, work); + tsm = stream_work->tsm; + pdev_dsc =to_cca_pdev_dsc (tsm->dsm_dev); + + my_index = stream_work->my_index; + peer_index = my_index ^0x1 ; + +redo_communicate: +mutex_lock (&pdev_dsc->object_lock); + + state =do_dev_communicate (PDEV_COMMUNICATE , tsm,RMI_PDEV_ERROR , &peer_wait); +if (state !=RMI_PDEV_ERROR && peer_wait) { + +if (!stream_work->has_peer) { +WARN (1 ,"Unexpected STREAM_WAIT without peer stream\n" ); +mutex_unlock (&pdev_dsc->object_lock); +return ; + } +/* +* Record a fresh target val for this side, then wait until +* peer reaches at least the same target. +*/ + target =atomic_inc_return (&stream_work->sync->val[my_index]); + +wake_up_all (&stream_work->sync->wq); + +mutex_unlock (&pdev_dsc->object_lock); + +/* Wait for peer to make matching progress */ +wait_event (stream_work->sync->wq, +atomic_read (&stream_work->sync->val[peer_index]) >= target); + goto redo_communicate; + } + +/* Signal peer if it is waiting on me */ +atomic_inc_return (&stream_work->sync->val[my_index]); +wake_up_all (&stream_work->sync->wq); + +mutex_unlock (&pdev_dsc->object_lock); +} + +static int __maybe_unused submit_stream_work (struct pci_dev *pdev1,struct pci_dev *pdev2, +unsigned long stream_handle) +{ +phys_addr_t rmm_pdev1_phys, rmm_pdev2_phys =0 ; +struct cca_host_comm_data *comm_data_pdev1, *comm_data_pdev2; +struct cca_host_pdev_dsc *pdev_dsc1, *pdev_dsc2 =NULL ; +struct stream_sync sync; +struct stream_connect_work stream_work_pdev1, stream_work_pdev2; + + comm_data_pdev1 =to_cca_comm_data (pdev1); +init_waitqueue_head (&sync.wq); +atomic_set (&sync.val[0 ],0 ); +atomic_set (&sync.val[1 ],0 ); + + pdev_dsc1 =to_cca_pdev_dsc (pdev1); +INIT_WORK_ONSTACK (&stream_work_pdev1.work, stream_connect_workfn); + stream_work_pdev1.tsm = pdev1->tsm; + stream_work_pdev1.sync = &sync; + stream_work_pdev1.my_index =0 ; + stream_work_pdev1.has_peer = !!pdev2; +queue_work (comm_data_pdev1->work_queue, &stream_work_pdev1.work); + +if (pdev2) { + comm_data_pdev2 =to_cca_comm_data (pdev2); + pdev_dsc2 =to_cca_pdev_dsc (pdev2); +INIT_WORK_ONSTACK (&stream_work_pdev2.work, stream_connect_workfn); + stream_work_pdev2.tsm = pdev2->tsm; + stream_work_pdev2.sync = &sync; + stream_work_pdev2.my_index =1 ; + stream_work_pdev2.has_peer = true; +queue_work (comm_data_pdev2->work_queue, &stream_work_pdev2.work); + } + +flush_work (&stream_work_pdev1.work); +if (pdev2) { +flush_work (&stream_work_pdev2.work); +destroy_work_on_stack (&stream_work_pdev2.work); + } + +destroy_work_on_stack (&stream_work_pdev1.work); + + rmm_pdev1_phys =virt_to_phys (pdev_dsc1->rmm_pdev); +if (pdev2) + rmm_pdev2_phys =virt_to_phys (pdev_dsc2->rmm_pdev); + +return 0 ; +}
drivers/virt/coco/arm-cca-host/rmi-da.h +13 -0
@@ -27,6 +27,19 @@ struct dev_comm_work {struct work_struct work; }; +struct stream_sync { +wait_queue_head_t wq; +atomic_t val[2 ]; +}; + +struct stream_connect_work { +struct pci_tsm *tsm; +struct work_struct work; +struct stream_sync *sync; +u8 my_index; +bool has_peer; +}; +struct cca_host_comm_data {void *rsp_buff;void *req_buff;
include/linux/arm-smccc-rmi.h +1 -0
@@ -540,6 +540,7 @@ struct rmi_pdev_params {#define RMI_DEV_COMM_EXIT_WAIT BIT(3)#define RMI_DEV_COMM_EXIT_RSP_RESET BIT(4)#define RMI_DEV_COMM_EXIT_MULTI BIT(5) +#define RMI_DEV_COMM_EXIT_STREAM_WAIT BIT(6)#define RMI_DEV_COMM_NONE 0#define RMI_DEV_COMM_RESPONSE 1
Signature · 1 line
2.43.0
Aneesh Kumar K.V (Arm)
maintainerPATCH v5 11/15 coco: host: arm64: Connect RMM pdev streams for IDE devices
In reply to Aneesh Kumar K.V (Arm)Add the RMI definitions for pdev stream management, including the stream parameter layout and helpers for RMI_PDEV_STREAM_CONNECT, RMI_PDEV_STREAM_COMPLETE, and RMI_PDEV_STREAM_DISCONNECT.
Create an RMM pdev for the endpoint's root port when needed, build the non-coherent stream parameters from the endpoint/root-port pdevs, IDE stream ID, and bridge address windows, and issue the RMM stream connect before enabling IDE on the endpoint.
Store the returned stream handle in the PF0 descriptor
--- drivers/virt/coco/arm-cca-host/main.c | 124 ++++++++++++++++++++++++ drivers/virt/coco/arm-cca-host/rmi-da.c | 40 +++++++- drivers/virt/coco/arm-cca-host/rmi-da.h | 57 +++++++++++ include/linux/arm-rmi-cmds.h | 36 +++++++ include/linux/arm-smccc-rmi.h | 37 +++++++ 5 files changed, 293 insertions(+), 1 deletion(-)
drivers/virt/coco/arm-cca-host/main.c +124 -0
@@ -113,6 +113,123 @@ static inline void free_dev_communication_buffers(struct cca_host_comm_data *comfree_page ((unsigned long )comm_data->io_params); } +static int cca_root_port_pdev_create (struct pci_dev *rp,struct tsm_dev *tsm_dev) +{ +int ret; +struct cca_host_rp_dsc *rp_dsc; + + rp_dsc =kzalloc_obj (*rp_dsc); +if (!rp_dsc) +return -ENOMEM ; + +/* we expect this to be asigned early */ + rp->tsm = &rp_dsc->pci; + rp->tsm->dsm_dev = rp; + rp->tsm->pdev = rp; + rp->tsm->tsm_dev = tsm_dev; +mutex_init (&rp_dsc->pdev.object_lock); + + ret =init_dev_communication_buffers (rp, &rp_dsc->pdev.comm_data); +if (ret) + goto err_comm_buff; + + ret =cca_pdev_create (rp); +if (ret) + goto err_pdev_create; + +/* +* device communication is still required even though +* there is not identity collection +*/ + ret =cca_pdev_collect_identity (rp); +if (ret) + goto pdev_destroy; + +return 0 ; + +pdev_destroy: +cca_pdev_stop_and_destroy (rp); +err_pdev_create: +free_dev_communication_buffers (&rp_dsc->pdev.comm_data); +err_comm_buff: +kfree (rp_dsc); + rp->tsm =NULL ; +return ret; +} + +static int pci_dev_addr_range (struct pci_dev *pdev,struct rmi_addr_range *pdev_addr) +{ +int naddr =0 ; +struct pci_dev *br; +struct resource *mem, *pref; + + br =pci_upstream_bridge (pdev); +if (!br) +return 0 ; + + mem =pci_resource_n (br,PCI_BRIDGE_MEM_WINDOW ); + pref =pci_resource_n (br,PCI_BRIDGE_PREF_MEM_WINDOW ); +if (resource_assigned (mem)) + naddr =insert_addr_range_sorted (pdev_addr, naddr, + mem->start, mem->end +1 ); +if (resource_assigned (pref)) + naddr =insert_addr_range_sorted (pdev_addr, naddr, + pref->start, pref->end +1 ); + +return naddr; +} + +static int cca_pdev_create_ncoh_stream (struct pci_dev *pdev,unsigned long stream_id) +{ +int ret; +long stream_handle; +struct cca_host_rp_dsc *rp_dsc; +struct rmi_pdev_stream_params *params; +struct pci_dev *rp =pcie_find_root_port (pdev); +struct cca_host_pf0_ep_dsc *pf0_ep_dsc =to_cca_pf0_ep_dsc (pdev); + +if (!rp->tsm) { + ret =cca_root_port_pdev_create (rp, pf0_ep_dsc->pci.base_tsm.tsm_dev); +if (ret) +return ret; + rp_dsc =to_cca_rp_dsc (rp); + }else { + rp_dsc =to_cca_rp_dsc (rp); +/* Make sure they use the same TSM */ +if (rp->tsm->tsm_dev != pf0_ep_dsc->pci.base_tsm.tsm_dev) +return -EINVAL ; + } + + + params = (struct rmi_pdev_stream_params *)get_zeroed_page (GFP_KERNEL ); +if (!params) +return -ENOMEM ; + + params->flags =0 ; + params->stream_type =RMI_PDEV_STREAM_NCOH ; + params->pdev_1 =virt_to_phys (pf0_ep_dsc->pdev.rmm_pdev); + params->pdev_2 =virt_to_phys (rp_dsc->pdev.rmm_pdev); + params->ide_sid = stream_id; + params->num_addr_range =pci_dev_addr_range (pdev, params->addr_range); + + ret =cca_pdev_stream_connect (pdev, rp, params, &stream_handle); +if (!ret) + pf0_ep_dsc->stream_handle = stream_handle; + +free_page ((unsigned long )params); +return ret; +} + +static int cca_pdev_create_streams (struct pci_dev *pdev,unsigned long stream_id) +{ +switch (pci_pcie_type (pdev)) { +case PCI_EXP_TYPE_ENDPOINT : +return cca_pdev_create_ncoh_stream (pdev, stream_id); +default : +return -EINVAL ; + } +} +static inline bool cca_pdev_need_sel_ide_streams (struct pci_dev *pdev) {return pci_pcie_type (pdev) ==PCI_EXP_TYPE_ENDPOINT ;
@@ -176,6 +293,10 @@ static int __maybe_unused cca_tsm_connect(struct pci_dev *pdev)if (ret) goto pdev_destroy; } +/* Create IDE streams */ + ret =cca_pdev_create_streams (pdev, stream_id); +if (ret) + goto pdev_destroy;/* * Once ide is setup, enable the stream at the endpoint * Root port will be done by RMM
@@ -208,6 +329,7 @@ static void __maybe_unused cca_tsm_disconnect(struct pci_dev *pdev) {struct pci_ide *ide;struct cca_host_pf0_ep_dsc *pf0_ep_dsc; +struct pci_dev *rp =pcie_find_root_port (pdev); pf0_ep_dsc =to_cca_pf0_ep_dsc (pdev);if (!pf0_ep_dsc)
@@ -216,6 +338,8 @@ static void __maybe_unused cca_tsm_disconnect(struct pci_dev *pdev)if (cca_pdev_need_sel_ide_streams (pdev)) ide = pf0_ep_dsc->sel_stream; +cca_pdev_disconnect_stream (pdev, rp, pf0_ep_dsc->stream_handle); +cca_pdev_stop_and_destroy (pdev);free_dev_communication_buffers (&pf0_ep_dsc->pdev.comm_data);
drivers/virt/coco/arm-cca-host/rmi-da.c +39 -1
@@ -62,6 +62,10 @@ static int init_pdev_params(struct pci_dev *pdev, struct rmi_pdev_params *params category =RMI_PDEV_FLAGS_CATEGORY_OFF_CHIP_EP ;break ; } +case PCI_EXP_TYPE_ROOT_PORT : { + category =RMI_PDEV_FLAGS_CATEGORY_ROOT_PORT ; +break ; + }default :return -EINVAL ; }
@@ -762,7 +766,7 @@ static void stream_connect_workfn(struct work_struct *work)mutex_unlock (&pdev_dsc->object_lock); } -static int __maybe_unused submit_stream_work (struct pci_dev *pdev1,struct pci_dev *pdev2, +static int submit_stream_work (struct pci_dev *pdev1,struct pci_dev *pdev2,unsigned long stream_handle) {phys_addr_t rmm_pdev1_phys, rmm_pdev2_phys =0 ;
@@ -806,6 +810,40 @@ static int __maybe_unused submit_stream_work(struct pci_dev *pdev1, struct pci_d rmm_pdev1_phys =virt_to_phys (pdev_dsc1->rmm_pdev);if (pdev2) rmm_pdev2_phys =virt_to_phys (pdev_dsc2->rmm_pdev); +/* +* If we had device communication error, this will error out. +*/ +if (rmi_pdev_stream_complete (rmm_pdev1_phys, rmm_pdev2_phys, stream_handle)) +return -EIO ;return 0 ; } + +int cca_pdev_stream_connect (struct pci_dev *pdev1,struct pci_dev *pdev2, +struct rmi_pdev_stream_params *stream_params, +unsigned long *stream_handle) +{ +phys_addr_t stream_params_phys =virt_to_phys (stream_params); + +if (rmi_pdev_stream_connect (stream_params_phys, stream_handle)) +return -EIO ; + +return submit_stream_work (pdev1, pdev2, *stream_handle); +} + +int cca_pdev_disconnect_stream (struct pci_dev *pdev1, +struct pci_dev *pdev2,unsigned long stream_handle) +{ + +phys_addr_t rmm_pdev2_phys =0 ; +struct cca_host_pdev_dsc *pdev_dsc1 =to_cca_pdev_dsc (pdev1); + +if (pdev2) + rmm_pdev2_phys =virt_to_phys (to_cca_pdev_dsc (pdev2)->rmm_pdev); + +if (rmi_pdev_stream_disconnect (virt_to_phys (pdev_dsc1->rmm_pdev), + rmm_pdev2_phys, stream_handle)) +return -EIO ; + +return submit_stream_work (pdev1, pdev2, stream_handle); +}
drivers/virt/coco/arm-cca-host/rmi-da.h +57 -0
100 lines not on this page · raw message
include/linux/arm-rmi-cmds.h +36 -0
@@ -724,4 +724,40 @@ static inline unsigned long rmi_pdev_set_pubkey(unsigned long pdev_phys, unsignereturn res.a0; } +static inline unsigned long rmi_pdev_stream_connect (unsigned long stream_params_phys, +unsigned long *stream_handle) +{ + +struct arm_smccc_res res; + +arm_smccc_1_1_invoke (SMC_RMI_PDEV_STREAM_CONNECT , stream_params_phys, &res); + + *stream_handle = res.a1; +return res.a0; +} + +static inline unsigned long rmi_pdev_stream_complete (unsigned long pdev1_phys, +unsigned long pdev2_phys,unsigned long stream_handle) +{ + +struct arm_smccc_res res; + +arm_smccc_1_1_invoke (SMC_RMI_PDEV_STREAM_COMPLETE , pdev1_phys, + pdev2_phys, stream_handle, &res); + +return res.a0; +} + +static inline unsigned long rmi_pdev_stream_disconnect (unsigned long pdev1_phys, +unsigned long pdev2_phys,unsigned long stream_handle) +{ + +struct arm_smccc_res res; + +arm_smccc_1_1_invoke (SMC_RMI_PDEV_STREAM_DISCONNECT , pdev1_phys, + pdev2_phys, stream_handle, &res); + +return res.a0; +} +#endif
include/linux/arm-smccc-rmi.h +37 -0
@@ -615,4 +615,41 @@ struct rmi_public_key_params { }; }; +#define MAX_STREAM_ADDR_RANGE 16 + +enum rmi_pdev_stream_type { +RMI_PDEV_STREAM_NON_TEE , +RMI_PDEV_STREAM_NCOH , +RMI_PDEV_STREAM_COH , +RMI_PDEV_STREAM_NCOH_SYS , +RMI_PDEV_STREAM_COH_SYS , +}; + +struct rmi_addr_range { +u64 base;/* inclusive */ +u64 top;/* exclusive */ +}; + +struct rmi_pdev_stream_params { +union { +struct { +u64 flags; +union { +u8 stream_type; +u8 padding0[8 ]; + }; +u64 pdev_1; +u64 pdev_2; +u64 ide_sid; +u64 num_addr_range; + }; +u8 padding1[0x100 ]; + }; + +union {/* 0x100 */ +struct rmi_addr_range addr_range[MAX_STREAM_ADDR_RANGE ]; +u8 padding2[0xF00 ]; + }; +}; +#endif /* __LINUX_ARM_SMCCC_RMI_H_ */
Signature · 1 line
2.43.0
Re: [PATCH v5 11/15] coco: host: arm64: Connect RMM pdev streams for IDE devices
Hi Aneesh
As I read it, the address ranges handed to RMM in this patch are captured once and at the point cca_tsm_connect() runs. That becomes the address range RMM has on record for the pdev/stream going forward.
So a couple of questions on that..
1. Is connect -> {driver probe / vfio-pci bind } the intended sequence or is that ordering left entirely to userspace/VMM policy?
2. Are the resources/BARs captured at connect time assumed to be fixed for the lifetime of the PDEV? If a PCI rescan (or resource reassignment such as pci=realloc, a hotplug re-enumeration happens after connect, is that expected to be rejected/blocked?
Thanks
Aneesh Kumar K.V
maintainerRe: [PATCH v5 11/15] coco: host: arm64: Connect RMM pdev streams for IDE devices
Quoted 10 lines · Ankit Agrawal
Hi Aneesh
As I read it, the address ranges handed to RMM in this patch are captured once and at the point
cca_tsm_connect()runs. That becomes the address range RMM has on record for the pdev/stream going forward.So a couple of questions on that..
1. Is connect -> {driver probe / vfio-pci bind } the intended sequence or is that ordering left entirely to userspace/VMM policy?
We can tsm connect the device even while its driver is bound.
Quoted 4 lines
2. Are the resources/BARs captured at connect time assumed to be fixed for the lifetime of the PDEV? If a PCI rescan (or resource reassignment such as pci=realloc, a hotplug re-enumeration happens after connect, is that expected to be rejected/blocked?
IIUC, a normal rescan neither rereads nor relocates an already known and assigned BAR? To discover an externally changed BAR, the device would normally need to be removed before rescanning. Device removal reaches pci_destroy_dev(), which calls pci_tsm_destroy() -> pci_tsm_disconnect()
-aneesh
Re: [PATCH v5 11/15] coco: host: arm64: Connect RMM pdev streams for IDE devices
In reply to Aneesh Kumar K.V (Arm)Hi Aneesh
It isn't clear to me why does pci_dev_addr_range() derive addr_range from the upstream bridge PCI_BRIDGE_MEM_WINDOW / PCI_BRIDGE_PREF_MEM_WINDOW rather than from pdev's own regions? Should it be filled up with device regions instead?
IIUC, there may be a couple of issues with the current approach:
1. The bridge's window can be wider than what pdev actually owns due to alignment padding.
2. If the bridge has multiple downstream devices (are there any?), the window spans address space belonging to sibling devices too and not just this pdev. So RMM would get a range that isn't exclusive to the pdev/stream being connected.
Aneesh Kumar K.V (Arm)
maintainerPATCH v5 12/15 coco: host: arm64: Refcount root-port pdevs used by IDE streams
In reply to Aneesh Kumar K.V (Arm)Keep the root-port RMM pdev alive while endpoint IDE streams are attached to it.
Add a kref to the root-port descriptor, take a reference when reusing an existing root-port pdev for stream setup, and drop it when the endpoint disconnects. Release the root-port pdev once the final reference is dropped, tearing down the RMM object and its communication buffers at that point.
--- drivers/virt/coco/arm-cca-host/main.c | 31 ++++++++++++++++++++++--- drivers/virt/coco/arm-cca-host/rmi-da.h | 4 ++++ 2 files changed, 32 insertions(+), 3 deletions(-)
drivers/virt/coco/arm-cca-host/main.c +28 -3
@@ -113,6 +113,23 @@ static inline void free_dev_communication_buffers(struct cca_host_comm_data *comfree_page ((unsigned long )comm_data->io_params); } +static void cca_root_port_pdev_release (struct kref *kref) +{ + struct cca_host_rp_dsc *rp_dsc = container_of(kref, struct cca_host_rp_dsc, + tsm_ref); +struct pci_dev *rp = rp_dsc->pci.pdev; + +cca_pdev_stop_and_destroy (rp); +free_dev_communication_buffers (&rp_dsc->pdev.comm_data); + rp->tsm =NULL ; +kfree (rp_dsc); +} + +static inline void cca_root_port_pdev_put (struct cca_host_rp_dsc *rp_dsc) +{ +kref_put (&rp_dsc->tsm_ref, cca_root_port_pdev_release); +} +static int cca_root_port_pdev_create (struct pci_dev *rp,struct tsm_dev *tsm_dev) {int ret;
@@ -127,6 +144,7 @@ static int cca_root_port_pdev_create(struct pci_dev *rp, struct tsm_dev *tsm_dev rp->tsm->dsm_dev = rp; rp->tsm->pdev = rp; rp->tsm->tsm_dev = tsm_dev; +kref_init (&rp_dsc->tsm_ref);mutex_init (&rp_dsc->pdev.object_lock); ret =init_dev_communication_buffers (rp, &rp_dsc->pdev.comm_data);
@@ -198,12 +216,15 @@ static int cca_pdev_create_ncoh_stream(struct pci_dev *pdev, unsigned long strea/* Make sure they use the same TSM */ if (rp->tsm->tsm_dev != pf0_ep_dsc->pci.base_tsm.tsm_dev)return -EINVAL ; - } +kref_get (&rp_dsc->tsm_ref); + } params = (struct rmi_pdev_stream_params *)get_zeroed_page (GFP_KERNEL ); -if (!params) +if (!params) { +cca_root_port_pdev_put (rp_dsc);return -ENOMEM ; + } params->flags =0 ; params->stream_type =RMI_PDEV_STREAM_NCOH ;
@@ -213,7 +234,9 @@ static int cca_pdev_create_ncoh_stream(struct pci_dev *pdev, unsigned long strea params->num_addr_range =pci_dev_addr_range (pdev, params->addr_range); ret =cca_pdev_stream_connect (pdev, rp, params, &stream_handle); -if (!ret) +if (ret) +cca_root_port_pdev_put (rp_dsc); +else pf0_ep_dsc->stream_handle = stream_handle;free_page ((unsigned long )params);
@@ -339,6 +362,8 @@ static void __maybe_unused cca_tsm_disconnect(struct pci_dev *pdev) ide = pf0_ep_dsc->sel_stream;cca_pdev_disconnect_stream (pdev, rp, pf0_ep_dsc->stream_handle); +if (rp) +cca_root_port_pdev_put (to_cca_rp_dsc (rp));cca_pdev_stop_and_destroy (pdev);free_dev_communication_buffers (&pf0_ep_dsc->pdev.comm_data);
drivers/virt/coco/arm-cca-host/rmi-da.h +4 -0
@@ -12,6 +12,9 @@#include <linux/pci-ide.h> #include <linux/pci-tsm.h> #include <linux/sizes.h> +#include <linux/atomic.h> +#include <linux/kref.h> +#include <linux/wait.h> #define MAX_CACHE_OBJ_SIZE SZ_16M#define CACHE_CHUNK_SIZE SZ_4K
@@ -104,6 +107,7 @@ struct cca_host_pf0_ep_dsc {struct cca_host_rp_dsc {struct pci_tsm pci;struct cca_host_pdev_dsc pdev; +struct kref tsm_ref; };struct cca_host_fn_dsc {
Signature · 1 line
2.43.0
Aneesh Kumar K.V (Arm)
maintainerPATCH v5 13/15 PCI/TSM: Move CMA DOE mailbox discovery out of pci_tsm_pf0_constructor()
In reply to Aneesh Kumar K.V (Arm)pci_tsm_pf0_constructor() currently looks up a CMA DOE mailbox and fails PF0 initialization when one is not present. That is too strict for all link TSM drivers.
Move CMA DOE mailbox discovery into the low-level PF0 probe callbacks so each driver can decide whether a mailbox is mandatory.
Keep SEV-TIO and TDX requiring a CMA mailbox, while allowing the arm-cca host path to proceed on PF0 devices that do not support IDE and therefore have no DOE-based SPDM path.
--- drivers/crypto/ccp/sev-dev-tsm.c | 13 +++++++++++++ drivers/pci/tsm.c | 13 +++++++------ drivers/virt/coco/arm-cca-host/main.c | 15 ++++++++++++--- 3 files changed, 32 insertions(+), 9 deletions(-)
drivers/crypto/ccp/sev-dev-tsm.c +13 -0
@@ -217,6 +217,19 @@ static struct pci_tsm *tio_pf0_probe(struct pci_dev *pdev, struct sev_device *seif (rc)return NULL ; +/* if device have ide cap, setup doe mailbox */ +if (pdev->ide_cap) { +struct pci_doe_mb *doe_mb; + + doe_mb =pci_find_doe_mailbox (pdev,PCI_VENDOR_ID_PCI_SIG , +PCI_DOE_FEATURE_CMA ); +if (!doe_mb) +return NULL ; + dsm->tsm.doe_mb = doe_mb; + }else { +return NULL ; + } +pci_dbg (pdev,"TSM enabled\n" ); dsm->sev = sev;return &no_free_ptr (dsm)->tsm.base_tsm;
drivers/pci/tsm.c +7 -6
@@ -744,12 +744,13 @@ int pci_tsm_pf0_constructor(struct pci_dev *pdev, struct pci_tsm_pf0 *tsm, struct tsm_dev *tsm_dev) {mutex_init (&tsm->lock); - tsm->doe_mb =pci_find_doe_mailbox (pdev,PCI_VENDOR_ID_PCI_SIG , -PCI_DOE_FEATURE_CMA ); -if (!tsm->doe_mb) { -pci_warn (pdev,"TSM init failure, no CMA mailbox\n" ); -return -ENODEV ; - } +/* +* Note, low-level TSM driver responsible for determining if it wants to +* proceed with a device that has no DOE mailbox. TSM may have an +* alternate method for coordinating TDISP. +*/ +if (!tsm->doe_mb) +pci_dbg (pdev,"No CMA mailbox\n" );return pci_tsm_link_constructor (pdev, &tsm->base_tsm, tsm_dev); }
drivers/virt/coco/arm-cca-host/main.c +12 -3
@@ -12,6 +12,7 @@#include <linux/tsm.h> #include <linux/vmalloc.h> #include <linux/cleanup.h> +#include <linux/pci-doe.h> #include "rmi-da.h"
@@ -33,14 +34,22 @@ static struct pci_tsm *cca_tsm_pci_probe(struct tsm_dev *tsm_dev, struct pci_devreturn &no_free_ptr (fn_dsc)->pci; } -if (!pdev->ide_cap) -return NULL ; - struct cca_host_pf0_ep_dsc *pf0_ep_dsc __free(kfree) =kzalloc (sizeof (*pf0_ep_dsc),GFP_KERNEL );if (!pf0_ep_dsc)return NULL ; +/* if device have ide cap, setup doe mailbox */ +if (pdev->ide_cap) { +struct pci_doe_mb *doe_mb; + + doe_mb =pci_find_doe_mailbox (pdev,PCI_VENDOR_ID_PCI_SIG , +PCI_DOE_FEATURE_CMA ); +if (!doe_mb) +return NULL ; + pf0_ep_dsc->pci.doe_mb = doe_mb; + } + ret =pci_tsm_pf0_constructor (pdev, &pf0_ep_dsc->pci, tsm_dev);if (ret)return NULL ;
Signature · 1 line
2.43.0
Aneesh Kumar K.V (Arm)
maintainerPATCH v5 14/15 coco: host: arm64: Add NCOH_SYS stream support for RC endpoints
In reply to Aneesh Kumar K.V (Arm)Teach the host CCA pdev setup to handle PCI_EXP_TYPE_RC_END devices.
Classify RC integrated endpoints as RMI_PDEV_FLAGS_CATEGORY_ON_CHIP_EP when building the RMM pdev parameters, and only advertise SPDM support when a DOE mailbox is present.
Also add the stream setup path for these devices by creating an RMI_PDEV_STREAM_NCOH_SYS stream using the endpoint pdev and its bridge address windows. This allows RC endpoints to participate in the TDISP flow without requiring a separate root-port pdev.
--- drivers/virt/coco/arm-cca-host/main.c | 28 +++++++++++++++++++++++++ drivers/virt/coco/arm-cca-host/rmi-da.c | 10 +++++++++ 2 files changed, 38 insertions(+)
drivers/virt/coco/arm-cca-host/main.c +28 -0
@@ -252,11 +252,39 @@ static int cca_pdev_create_ncoh_stream(struct pci_dev *pdev, unsigned long streareturn ret; } +static int cca_pdev_create_ncoh_sys_stream (struct pci_dev *pdev) +{ +int ret; +long stream_handle; +struct rmi_pdev_stream_params *params; +struct cca_host_pf0_ep_dsc *pf0_ep_dsc =to_cca_pf0_ep_dsc (pdev); + + params = (struct rmi_pdev_stream_params *)get_zeroed_page (GFP_KERNEL ); +if (!params) +return -ENOMEM ; + + params->flags =0 ; + params->stream_type =RMI_PDEV_STREAM_NCOH_SYS ; + params->pdev_1 =virt_to_phys (pf0_ep_dsc->pdev.rmm_pdev); + params->pdev_2 =0 ;/* ignored */ + params->ide_sid =0 ;/* ignored */ + params->num_addr_range =pci_dev_addr_range (pdev, params->addr_range); + + ret =cca_pdev_stream_connect (pdev,NULL , params, &stream_handle); +if (!ret) + pf0_ep_dsc->stream_handle = stream_handle; + +free_page ((unsigned long )params); +return ret; +} +static int cca_pdev_create_streams (struct pci_dev *pdev,unsigned long stream_id) {switch (pci_pcie_type (pdev)) {case PCI_EXP_TYPE_ENDPOINT :return cca_pdev_create_ncoh_stream (pdev, stream_id); +case PCI_EXP_TYPE_RC_END : +return cca_pdev_create_ncoh_sys_stream (pdev);default :return -EINVAL ; }
drivers/virt/coco/arm-cca-host/rmi-da.c +10 -0
@@ -66,6 +66,16 @@ static int init_pdev_params(struct pci_dev *pdev, struct rmi_pdev_params *params category =RMI_PDEV_FLAGS_CATEGORY_ROOT_PORT ;break ; } +case PCI_EXP_TYPE_RC_END : { +struct cca_host_pf0_ep_dsc *pf0_ep_dsc =to_cca_pf0_ep_dsc (pdev); + +/* Use SPDM if present */ +if (pf0_ep_dsc->pci.doe_mb) + params->flags =RMI_PDEV_FLAGS_SPDM ; + + category =RMI_PDEV_FLAGS_CATEGORY_ON_CHIP_EP ; +break ; + }default :return -EINVAL ; }
Signature · 1 line
2.43.0
Aneesh Kumar K.V (Arm)
maintainerPATCH v5 15/15 coco: host: arm64: Enable PCI TSM connect callbacks
In reply to Aneesh Kumar K.V (Arm)The previous patches build up the Arm CCA host device-assignment flow: RMM pdev creation and teardown, device communication, public-key setup, peer stream coordination, RMM stream connect/disconnect, and support for both endpoint and RC endpoint stream types.
Now that the connect and disconnect paths contain the complete setup and teardown sequence, register them in pci_tsm_ops and drop the __maybe_unused annotations.
--- drivers/virt/coco/arm-cca-host/main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/virt/coco/arm-cca-host/main.c +4 -2
@@ -295,7 +295,7 @@ static inline bool cca_pdev_need_sel_ide_streams(struct pci_dev *pdev)return pci_pcie_type (pdev) ==PCI_EXP_TYPE_ENDPOINT ; } -static int __maybe_unused cca_tsm_connect (struct pci_dev *pdev) +static int cca_tsm_connect (struct pci_dev *pdev) {struct pci_dev *rp =pcie_find_root_port (pdev);struct cca_host_pf0_ep_dsc *pf0_ep_dsc;
@@ -385,7 +385,7 @@ static int __maybe_unused cca_tsm_connect(struct pci_dev *pdev)return ret; } -static void __maybe_unused cca_tsm_disconnect (struct pci_dev *pdev) +static void cca_tsm_disconnect (struct pci_dev *pdev) {struct pci_ide *ide;struct cca_host_pf0_ep_dsc *pf0_ep_dsc;
@@ -414,6 +414,8 @@ static void __maybe_unused cca_tsm_disconnect(struct pci_dev *pdev)static struct pci_tsm_ops cca_link_pci_ops = { .probe = cca_tsm_pci_probe, .remove = cca_tsm_pci_remove, + .connect = cca_tsm_connect, + .disconnect = cca_tsm_disconnect, };static void cca_link_tsm_remove (void *tsm_dev)
Signature · 1 line
2.43.0