From nobody Fri Sep 25 16:01:36 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6198949891A; Thu, 10 Sep 2026 14:05:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049128; cv=none; b=rxhR3ia8hWyCpCRv0AaIfzWLO+4hbRDWxCddlFJnqneMRDtmvi0xvXzPHZVw+eTjJfr2+hE4RmyHmIDL6yC+s8/w0/C63qytIc6yJlJxJkrohA6usrp7OTZ2n/5/suV6/bqDUHWBOdSxDgebMnStjf3jM0QaesArHsH17jY0bmw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049128; c=relaxed/simple; bh=s23VfKMMmRNZNIU0pGAjcGNAwSkq9eHIXgc68aPcObw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DKl5rE0pzQtwavESVC6L6eCsX+2UeAdEk419k3rfA84f/bY89z0BKS9os0+cpJvj16gVmr2vIMfE78muBnytAqCMGfpo2qvgIOI+VXS2qSGTUEKGlDmK60eUz9GhShVDF8J8x16wuKABxJqstMbQn+YI6m/nI11REAGI/OPJfhw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=DJ7iqDZc; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="DJ7iqDZc" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1FB2C1F00893; Thu, 10 Sep 2026 14:05:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1789049126; bh=NDk08jf8/gCHIxn5wFUM9weoXOz0O1oU/9eJvj/KxnE=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=DJ7iqDZc5FDTJsXTAmrZcFigCdnq9KpTS+iZyvI0kdfK3OTHME+NTn6Ljkl1fFkrL lr9VY5qMOx/xlAk3xJJYPnsCh0vRssbu0FDBdhppLVbM7Iio5XlH+WjO+bdSA5wvSH qDAGeYWrr0MJClNV6jRzhgtbq01r1o+Ll3XC9fyTsTsSDqu5bwKiD//NnQnWpEm1lA 4QDDycN7unF8iu18G6koGT3AgOAh87mZdPxTHDdQYxPG+K1zofbkyrUDIA7SbayCOY pWrPJHncPbdV1CK/+OKf2dgmHLI7XThE224VMEGPXRfuJgohGmHw0MXjHm56BII6kL PL0WNbcI2QMwQ== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Alexey Kardashevskiy , Catalin Marinas , Dan Williams , Jason Gunthorpe , Jonathan Cameron , Marc Zyngier , Samuel Ortiz , Steven Price , Suzuki K Poulose , Will Deacon , Xu Yilun Subject: [PATCH v5 01/15] coco: host: arm64: Prepare host TSM plumbing for IDE streams Date: Thu, 10 Sep 2026 19:34:54 +0530 Message-ID: <20260910140509.868402-2-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260910140509.868402-1-aneesh.kumar@kernel.org> References: <20260910140509.868402-1-aneesh.kumar@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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. Signed-off-by: Aneesh Kumar K.V (Arm) --- 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 diff --git a/drivers/firmware/arm_rmm/rmi.c b/drivers/firmware/arm_rmm/rmi.c index 34058e34188d..ba415b66991b 100644 --- a/drivers/firmware/arm_rmm/rmi.c +++ b/drivers/firmware/arm_rmm/rmi.c @@ -15,8 +15,8 @@ =20 static bool arm64_rmi_is_available; =20 -/* 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 3 static __ro_after_init unsigned long rmi_feat_reg_cache[RMI_FEAT_REG_COUNT= ]; =20 unsigned long rmi_feat_reg(unsigned long id) diff --git a/drivers/firmware/smccc/smccc.c b/drivers/firmware/smccc/smccc.c index 854276a3cd57..90b87a622a6b 100644 --- a/drivers/firmware/smccc/smccc.c +++ b/drivers/firmware/smccc/smccc.c @@ -11,6 +11,7 @@ #include #include #include +#include =20 #include =20 @@ -100,6 +101,11 @@ static const struct smccc_device_info smccc_devices[] = __initconst =3D { .requires_smc =3D true, .device_name =3D "arm-rsi", }, + { + .func_id =3D SMC_RMI_VERSION, + .requires_smc =3D true, + .device_name =3D "arm-rmi", + }, }; =20 static bool __init smccc_probe_smccc_device(const struct smccc_device_info= *smccc_dev) diff --git a/drivers/virt/coco/Kconfig b/drivers/virt/coco/Kconfig index f7691f64fbe3..1cbc2134f9ea 100644 --- a/drivers/virt/coco/Kconfig +++ b/drivers/virt/coco/Kconfig @@ -19,5 +19,7 @@ endif =20 source "drivers/virt/coco/tdx-host/Kconfig" =20 +source "drivers/virt/coco/arm-cca-host/Kconfig" + config TSM bool diff --git a/drivers/virt/coco/Makefile b/drivers/virt/coco/Makefile index b323b0ae4f82..f2310c34daf9 100644 --- a/drivers/virt/coco/Makefile +++ b/drivers/virt/coco/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_INTEL_TDX_HOST) +=3D tdx-host/ obj-$(CONFIG_ARM_CCA_GUEST) +=3D arm-cca-guest/ obj-$(CONFIG_TSM) +=3D tsm-core.o obj-$(CONFIG_TSM_GUEST) +=3D guest/ +obj-$(CONFIG_ARM_CCA_HOST) +=3D arm-cca-host/ diff --git a/drivers/virt/coco/arm-cca-host/Kconfig b/drivers/virt/coco/arm= -cca-host/Kconfig new file mode 100644 index 000000000000..d2bf44f9776a --- /dev/null +++ b/drivers/virt/coco/arm-cca-host/Kconfig @@ -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. diff --git a/drivers/virt/coco/arm-cca-host/Makefile b/drivers/virt/coco/ar= m-cca-host/Makefile new file mode 100644 index 000000000000..7a4c2e0e5d26 --- /dev/null +++ b/drivers/virt/coco/arm-cca-host/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +obj-$(CONFIG_ARM_CCA_HOST) +=3D arm-cca-host.o + +arm-cca-host-y +=3D main.o diff --git a/drivers/virt/coco/arm-cca-host/main.c b/drivers/virt/coco/arm-= cca-host/main.c new file mode 100644 index 000000000000..df2cc761f68b --- /dev/null +++ b/drivers/virt/coco/arm-cca-host/main.c @@ -0,0 +1,192 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2026 ARM Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rmi-da.h" + +static struct pci_tsm *cca_tsm_pci_probe(struct tsm_dev *tsm_dev, struct p= ci_dev *pdev) +{ + int ret; + + if (!is_pci_tsm_pf0(pdev)) { + struct cca_host_fn_dsc *fn_dsc __free(kfree) =3D + kzalloc(sizeof(*fn_dsc), GFP_KERNEL); + + if (!fn_dsc) + return NULL; + + ret =3D pci_tsm_link_constructor(pdev, &fn_dsc->pci, tsm_dev); + if (ret) + return NULL; + + return &no_free_ptr(fn_dsc)->pci; + } + + if (!pdev->ide_cap) + return NULL; + + struct cca_host_pf0_ep_dsc *pf0_ep_dsc __free(kfree) =3D + kzalloc(sizeof(*pf0_ep_dsc), GFP_KERNEL); + if (!pf0_ep_dsc) + return NULL; + + ret =3D pci_tsm_pf0_constructor(pdev, &pf0_ep_dsc->pci, tsm_dev); + if (ret) + return NULL; + + pci_dbg(pdev, "tsm enabled\n"); + return &no_free_ptr(pf0_ep_dsc)->pci.base_tsm; +} + +static void cca_tsm_pci_remove(struct pci_tsm *tsm) +{ + struct pci_dev *pdev =3D tsm->pdev; + + if (is_pci_tsm_pf0(pdev)) { + struct cca_host_pf0_ep_dsc *pf0_ep_dsc =3D to_cca_pf0_ep_dsc(pdev); + + pci_tsm_pf0_destructor(&pf0_ep_dsc->pci); + kfree(pf0_ep_dsc); + } else { + kfree(to_cca_fn_dsc(pdev)); + } +} + +static inline bool cca_pdev_need_sel_ide_streams(struct pci_dev *pdev) +{ + return pci_pcie_type(pdev) =3D=3D PCI_EXP_TYPE_ENDPOINT; +} + +static int __maybe_unused cca_tsm_connect(struct pci_dev *pdev) +{ + struct pci_dev *rp =3D pcie_find_root_port(pdev); + struct cca_host_pf0_ep_dsc *pf0_ep_dsc; + struct pci_ide *ide; + int ret, stream_id =3D 0; + + /* Only function 0 supports connect in host */ + if (WARN_ON(!is_pci_tsm_pf0(pdev))) + return -EIO; + + pf0_ep_dsc =3D to_cca_pf0_ep_dsc(pdev); + if (cca_pdev_need_sel_ide_streams(pdev)) { + + ide =3D pci_ide_stream_alloc(pdev); + if (!ide) { + ret =3D -ENOMEM; + goto err_stream_alloc; + } + + pf0_ep_dsc->sel_stream =3D ide; + /* + * keep the stream id simple by using the host-bridge id + */ + stream_id =3D ide->host_bridge_stream; + ide->stream_id =3D stream_id; + ret =3D pci_ide_stream_register(ide); + if (ret) + goto err_stream; + /* + * Configure IDE capability for target device + * + * Some test devices work only with DEFAULT_STREAM enabled. + * For simplicity, enable DEFAULT_STREAM for all devices. A + * future decent solution may be to have a quirk table to + * specify which devices need DEFAULT_STREAM. + */ + ide->partner[PCI_IDE_EP].default_stream =3D 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); + } + return 0; + +err_stream: + if (cca_pdev_need_sel_ide_streams(pdev)) + pci_ide_stream_free(ide); + pf0_ep_dsc->sel_stream =3D NULL; +err_stream_alloc: + + return ret; +} + +static void __maybe_unused cca_tsm_disconnect(struct pci_dev *pdev) +{ + struct pci_ide *ide; + struct cca_host_pf0_ep_dsc *pf0_ep_dsc; + + pf0_ep_dsc =3D to_cca_pf0_ep_dsc(pdev); + if (!pf0_ep_dsc) + return; + + if (cca_pdev_need_sel_ide_streams(pdev)) { + ide =3D pf0_ep_dsc->sel_stream; + + pci_ide_stream_release(ide); + pf0_ep_dsc->sel_stream =3D NULL; + } + +} + +static struct pci_tsm_ops cca_link_pci_ops =3D { + .probe =3D cca_tsm_pci_probe, + .remove =3D cca_tsm_pci_remove, +}; + +static void cca_link_tsm_remove(void *tsm_dev) +{ + tsm_unregister(tsm_dev); +} + +static bool rmi_has_reg2_feature(unsigned long feature) +{ + return !!u64_get_bits(rmi_feat_reg(2), feature); +} + +static int cca_link_tsm_probe(struct arm_smccc_device *sdev) +{ + struct tsm_dev *tsm_dev; + + if (!rmi_has_reg2_feature(RMI_FEATURE_REGISTER_2_DA)) + return -ENODEV; + + tsm_dev =3D tsm_register(&sdev->dev, &cca_link_pci_ops); + if (IS_ERR(tsm_dev)) + return PTR_ERR(tsm_dev); + + return devm_add_action_or_reset(&sdev->dev, cca_link_tsm_remove, + tsm_dev); +} + +static const struct arm_smccc_device_id cca_link_tsm_id_table[] =3D { + { .func_id =3D SMC_RMI_VERSION }, + {} +}; +MODULE_DEVICE_TABLE(arm_smccc, cca_link_tsm_id_table); + +static struct arm_smccc_driver cca_link_tsm_driver =3D { + .name =3D KBUILD_MODNAME, + .probe =3D cca_link_tsm_probe, + .id_table =3D cca_link_tsm_id_table, +}; +module_arm_smccc_driver(cca_link_tsm_driver); +MODULE_IMPORT_NS("PCI_IDE"); +MODULE_AUTHOR("Aneesh Kumar "); +MODULE_DESCRIPTION("ARM CCA Host TSM driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.h b/drivers/virt/coco/ar= m-cca-host/rmi-da.h new file mode 100644 index 000000000000..c5a568cb5674 --- /dev/null +++ b/drivers/virt/coco/arm-cca-host/rmi-da.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2026 ARM Ltd. + */ + +#ifndef _VIRT_COCO_RMM_DA_H_ +#define _VIRT_COCO_RMM_DA_H_ + +#include +#include +#include +#include +#include + +/** + * struct cca_host_pf0_ep_dsc - PF0 endpoint device security context. + * @pci: Physical Function 0 TDISP link context + * @sel_stream: Selective IDE Stream descriptor + */ +struct cca_host_pf0_ep_dsc { + struct pci_tsm_pf0 pci; + struct pci_ide *sel_stream; +}; + +struct cca_host_fn_dsc { + struct pci_tsm pci; +}; + +static inline struct cca_host_pf0_ep_dsc *to_cca_pf0_ep_dsc(struct pci_dev= *pdev) +{ + struct pci_tsm *tsm =3D pdev->tsm; + + if (!tsm || !is_pci_tsm_pf0(pdev)) + return NULL; + + return container_of(tsm, struct cca_host_pf0_ep_dsc, pci.base_tsm); +} + +static inline struct cca_host_fn_dsc *to_cca_fn_dsc(struct pci_dev *pdev) +{ + struct pci_tsm *tsm =3D pdev->tsm; + + return container_of(tsm, struct cca_host_fn_dsc, pci); +} + +#endif --=20 2.43.0 From nobody Fri Sep 25 16:01:36 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7718749BD88; Thu, 10 Sep 2026 14:05:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049135; cv=none; b=hB5T9e8bAIQkfX5nTZJYQIlH4XsoL/QxsTKvyTkpm4lrWf2PyLmprkJIWoW3NteNI4R8GK8+iqHr1wx4N/Lig19Z6KkR4K+JqMmZYp3ysJ3JJSR4g1I6EDaGfqYFEwXHAjRfZO5rX7Dn0K8GOO+qSnwPJGZuwOOBOCFDKO0YZbw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049135; c=relaxed/simple; bh=D2thJi9YqnarZ9ESCZo3JVYhDCvRjNmOTLyItJJmI1E=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uzfIALp6LcmoC+xd87N8EB7Ig7WMsy5rmJ2iLt8eFoRICuQwg6dIcCEBThvEZfd63e8SK7TAUp2dFxJW/fQmIIJMZqb+5epZzuO0/1GYCgrf6k8zsxVd0s3YgdDuXWrNbauGShhzMCrlO5YY/lbIpHiq1Y4wkOVgBcy9SDBBSVU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LVRMEBsg; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="LVRMEBsg" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BFCE81F000FF; Thu, 10 Sep 2026 14:05:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1789049132; bh=gZCTlQJpIBSERmsxN06CrBINuFB1nOoFSPT8yuNke68=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=LVRMEBsg94Rd36kfVrF+woZhxkxn2Sle/Mdyj4e0L8Xz3kpXTl9tfvsiXTPHJX3+j bdbAKrBaNL9qYL9H9tUPKJqkOHz5WfZJGVCN0fsshUB3Yw5+zLZbpUYMGRgVA2jSDz dCnwuDecWWl2aQkoTfRe9eYjtHJ5VFIl8bb2bakUzF0pIWZZ492iLijqww1NKGl28t OCfGgAzgePGrzg9PlihIt5+nFyxwj3i7H+LCO18OH4yTO99JWK2c0cy42CQPXr2OP7 1OZSpTGrC0LhRrxnb4NaOxR8tI6oCxQaJQR5f+gdtOnKJKanUH+5QcmVp7aMa7Hs1H PvyaR6WiWv+uQ== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Alexey Kardashevskiy , Catalin Marinas , Dan Williams , Jason Gunthorpe , Jonathan Cameron , Marc Zyngier , Samuel Ortiz , Steven Price , Suzuki K Poulose , Will Deacon , Xu Yilun Subject: [PATCH v5 02/15] coco: host: arm64: Create RMM pdev objects for PCI endpoints Date: Thu, 10 Sep 2026 19:34:55 +0530 Message-ID: <20260910140509.868402-3-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260910140509.868402-1-aneesh.kumar@kernel.org> References: <20260910140509.868402-1-aneesh.kumar@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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. Signed-off-by: Aneesh Kumar K.V (Arm) --- 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 diff --git a/drivers/virt/coco/arm-cca-host/Makefile b/drivers/virt/coco/ar= m-cca-host/Makefile index 7a4c2e0e5d26..cdbe85d072ae 100644 --- a/drivers/virt/coco/arm-cca-host/Makefile +++ b/drivers/virt/coco/arm-cca-host/Makefile @@ -2,4 +2,4 @@ # obj-$(CONFIG_ARM_CCA_HOST) +=3D arm-cca-host.o =20 -arm-cca-host-y +=3D main.o +arm-cca-host-y +=3D main.o rmi-da.o diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.c b/drivers/virt/coco/ar= m-cca-host/rmi-da.c new file mode 100644 index 000000000000..863bb425e5c9 --- /dev/null +++ b/drivers/virt/coco/arm-cca-host/rmi-da.c @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2026 ARM Ltd. + */ + +#include +#include +#include + +#include "rmi-da.h" + +static int pci_ide_segment(struct pci_dev *pdev) +{ + if (pdev->fm_enabled) + return pci_domain_nr(pdev->bus); + return 0; +} + +static unsigned int pci_get_max_rid(struct pci_dev *pdev) +{ + int fn; + int max_rid; + int slot =3D PCI_SLOT(pdev->devfn); + + for (fn =3D 0; fn < 8; fn++) { + struct pci_dev *fn_dev; + + fn_dev =3D pci_get_slot(pdev->bus, PCI_DEVFN(slot, fn)); + if (!fn_dev) + continue; + + max_rid =3D pci_dev_id(fn_dev); + pci_dev_put(fn_dev); + } + return max_rid; +} + +static int init_pdev_params(struct pci_dev *pdev, struct rmi_pdev_params *= params) +{ + int rid; + unsigned long category; + struct pci_config_window *cfg =3D pdev->bus->sysdata; + + /* check we are ECAM compliant */ + if (!pdev->bus->ops->map_bus) + return -EINVAL; + + switch (pci_pcie_type(pdev)) { + case PCI_EXP_TYPE_ENDPOINT: { + struct cca_host_pf0_ep_dsc *pf0_ep_dsc =3D to_cca_pf0_ep_dsc(pdev); + + /* Endpoint needs DOE mailbox */ + if (!pf0_ep_dsc->pci.doe_mb) + return -EINVAL; + + params->flags =3D RMI_PDEV_FLAGS_SPDM; + category =3D RMI_PDEV_FLAGS_CATEGORY_OFF_CHIP_EP; + break; + } + default: + return -EINVAL; + } + + params->flags |=3D (category << RMI_PDEV_FLAGS_CATEGORY_SHIFT); + /* assign the ep device with RMM */ + rid =3D pci_dev_id(pdev); + params->pdev_id =3D rid; + params->hb_base =3D cfg->res.start; + params->routing_id =3D pci_ide_segment(pdev); + /* slot number for certificate chain default to zero */ + params->id_index =3D 0; + params->hash_algo =3D RMI_HASH_SHA_256; + /* no multi function device here. */ + params->rid_base =3D rid; + params->rid_top =3D pci_get_max_rid(pdev) + 1; + return 0; +} + +static inline int rmi_pdev_create(unsigned long pdev_phys, + unsigned long pdev_params_phys, unsigned long *rmi_ret) +{ + struct rmi_sro_state *sro __free(kfree) =3D kmalloc_obj(*sro); + if (!sro) + return -ENOMEM; + + *rmi_ret =3D rmi_sro_memxfer_cmd(sro, GFP_KERNEL, SMC_RMI_PDEV_CREATE, + pdev_phys, pdev_params_phys); + + return 0; +} + +int cca_pdev_create(struct pci_dev *pci_dev) +{ + int ret; + void *rmm_pdev; + bool should_free =3D true; + phys_addr_t rmm_pdev_phys; + struct rmi_pdev_params *params; + struct cca_host_pdev_dsc *pdev_dsc =3D to_cca_pdev_dsc(pci_dev); + + rmm_pdev =3D (void *)get_zeroed_page(GFP_KERNEL); + if (!rmm_pdev) + return -ENOMEM; + + rmm_pdev_phys =3D virt_to_phys(rmm_pdev); + if (rmi_delegate_page(rmm_pdev_phys)) { + ret =3D -EIO; + goto err_granule_delegate; + } + + params =3D (struct rmi_pdev_params *)get_zeroed_page(GFP_KERNEL); + if (!params) { + ret =3D -ENOMEM; + goto err_param_alloc; + } + + ret =3D init_pdev_params(pci_dev, params); + if (ret) + goto err_init_pdev_params; + + { + unsigned long rmi_ret; + + ret =3D rmi_pdev_create(rmm_pdev_phys, virt_to_phys(params), + &rmi_ret); + if (ret || rmi_ret) { + if (!ret) + ret =3D -EIO; + goto err_init_pdev_params; + } + } + + pdev_dsc->rmm_pdev =3D rmm_pdev; + free_page((unsigned long)params); + return 0; + +err_init_pdev_params: + free_page((unsigned long)params); +err_param_alloc: + if (rmi_undelegate_page(rmm_pdev_phys)) + should_free =3D false; +err_granule_delegate: + if (should_free) + free_page((unsigned long)rmm_pdev); + return ret; +} diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.h b/drivers/virt/coco/ar= m-cca-host/rmi-da.h index c5a568cb5674..f1580308777b 100644 --- a/drivers/virt/coco/arm-cca-host/rmi-da.h +++ b/drivers/virt/coco/arm-cca-host/rmi-da.h @@ -12,13 +12,26 @@ #include #include =20 +/** + * 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 cach= es + */ +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; }; =20 @@ -43,4 +56,17 @@ static inline struct cca_host_fn_dsc *to_cca_fn_dsc(stru= ct pci_dev *pdev) return container_of(tsm, struct cca_host_fn_dsc, pci); } =20 +static inline struct cca_host_pdev_dsc *to_cca_pdev_dsc(struct pci_dev *pd= ev) +{ + struct cca_host_pf0_ep_dsc *pf0_ep_dsc; + + pf0_ep_dsc =3D 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 diff --git a/include/linux/arm-rmi-cmds.h b/include/linux/arm-rmi-cmds.h index 746257d77dd6..850ac8e230e2 100644 --- a/include/linux/arm-rmi-cmds.h +++ b/include/linux/arm-rmi-cmds.h @@ -8,6 +8,7 @@ =20 #include #include +#include #include =20 #define RMI_MAX_ADDR_LIST 256 @@ -675,4 +676,14 @@ static inline long rmi_rtt_unprot_unmap(unsigned long = rd, return ret; } =20 +static inline unsigned long rmi_pdev_get_state(unsigned long pdev_phys, en= um rmi_pdev_state *state) +{ + struct arm_smccc_res res; + + arm_smccc_1_1_invoke(SMC_RMI_PDEV_GET_STATE, pdev_phys, &res); + + *state =3D res.a1; + return res.a0; +} + #endif diff --git a/include/linux/arm-smccc-rmi.h b/include/linux/arm-smccc-rmi.h index 3eb88caf4096..7241da55c753 100644 --- a/include/linux/arm-smccc-rmi.h +++ b/include/linux/arm-smccc-rmi.h @@ -491,4 +491,47 @@ static_assert(sizeof(struct rec_run) =3D=3D SZ_4K); #define RMI_S2AP_DIRECT_WRITE BIT(0) #define RMI_S2AP_DIRECT_READ BIT(1) =20 +enum rmi_pdev_state { + RMI_PDEV_NEW, + RMI_PDEV_NEEDS_KEY, + RMI_PDEV_HAS_KEY, + RMI_PDEV_READY, + RMI_PDEV_STOPPED, + RMI_PDEV_ERROR, +}; + +#define RMI_PDEV_FLAGS_SPDM BIT(0) +#define RMI_PDEV_FLAGS_CATEGORY_MASK GENMASK(2, 1) +#define RMI_PDEV_FLAGS_CATEGORY_SHIFT 1 +#define RMI_PDEV_FLAGS_P2P BIT(3) + +#define RMI_PDEV_FLAGS_CATEGORY_ROOT_PORT 0x0 +#define RMI_PDEV_FLAGS_CATEGORY_OFF_CHIP_EP 0x1 +#define RMI_PDEV_FLAGS_CATEGORY_ON_CHIP_EP 0x2 + +struct rmi_pdev_params { + union { + struct { + u64 flags; + u64 hb_base; + u64 pdev_id; + u64 routing_id; + u64 id_index; + union { + u32 rid_base; + u8 padding0[8]; + }; + union { + u32 rid_top; + u8 padding1[8]; + }; + union { + u8 hash_algo; + u8 padding2[8]; + }; + }; + u8 padding3[0x1000]; + }; +}; + #endif /* __LINUX_ARM_SMCCC_RMI_H_ */ --=20 2.43.0 From nobody Fri Sep 25 16:01:36 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F3E3449B1EE; Thu, 10 Sep 2026 14:05:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049142; cv=none; b=pTUrftqLkr9UFNMsLykurLJadmT73YtAOBxMbreX8EUJmgbOL71yeqOh6wECdA/7roc0E7uAetACsG2W8zjl0Q9z9kOSEAyx4hyGKF7NAYX1wZmKu9b0QCcRJvqeeVcNP0yRIO8bYu6zp/WOeKDDoJoI7B73FE10EkkmPhEBbWU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049142; c=relaxed/simple; bh=7mPuM/AZRJSXKP7wuU+io+gr1+VytF+OXT2cLGSx4fA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=iMHvEM4JW/6JuTFs5okvxeWuAtMcI6NHVsZANF4D2bU3d+ZnQXGaYs+KoFFLyZh2toa9eI4CAJleWd9PP6mLVZh2Yf4kfC/yneXc5WzDVrDu9rfjle/Nn6A5WqySUgNxHPwwEK68jEZ0weJlNFoYoHjN5mLRLCxNocK5p7VCUWY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=nUvZB22J; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="nUvZB22J" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3A1F71F00893; Thu, 10 Sep 2026 14:05:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1789049139; bh=UHHL5Xy41RFnE2N8BFozRzMEXVLR7j90JEEQ4uUfGlE=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=nUvZB22J+8U8Vtlshl0vdKHsFiyxB4LitKDQLFAc1j3p+LfmL5UbS6izofLwXSQ8I Jn/FmJxCIppaRv/R1yiyQzNehyUn11GHf5IyTnuUhqharYaleH6mnExfwCEOyBLsyY MuSM33tJx+jIzDo0/pVVfgwxZ8dS/CW3yFHwjp8ZwapWMy7VShBsVl+WtZtXhSnaz1 eWdT18ahpFg4JqcIKxhvGRqnkczNYQS40pDUqD8K9Ortazp7AggJvNiHfQTecMqbLG Ggn28djz173LLEyp+eGmnrvTWZmJcCQk43vk757i7ijGDyIWqeHUZlXBHpGRQEI7Km FM+YloDpS8Oqw== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Alexey Kardashevskiy , Catalin Marinas , Dan Williams , Jason Gunthorpe , Jonathan Cameron , Marc Zyngier , Samuel Ortiz , Steven Price , Suzuki K Poulose , Will Deacon , Xu Yilun Subject: [PATCH v5 03/15] coco: host: arm64: Add RMM pdev communication plumbing Date: Thu, 10 Sep 2026 19:34:56 +0530 Message-ID: <20260910140509.868402-4-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260910140509.868402-1-aneesh.kumar@kernel.org> References: <20260910140509.868402-1-aneesh.kumar@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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. Signed-off-by: Aneesh Kumar K.V (Arm) --- 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(+) diff --git a/drivers/virt/coco/arm-cca-host/main.c b/drivers/virt/coco/arm-= cca-host/main.c index df2cc761f68b..ce16ce108db7 100644 --- a/drivers/virt/coco/arm-cca-host/main.c +++ b/drivers/virt/coco/arm-cca-host/main.c @@ -44,6 +44,7 @@ static struct pci_tsm *cca_tsm_pci_probe(struct tsm_dev *= tsm_dev, struct pci_dev ret =3D pci_tsm_pf0_constructor(pdev, &pf0_ep_dsc->pci, tsm_dev); if (ret) return NULL; + mutex_init(&pf0_ep_dsc->pdev.object_lock); =20 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) } } =20 +static __maybe_unused int init_dev_communication_buffers(struct pci_dev *p= dev, + struct cca_host_comm_data *comm_data) +{ + int ret =3D -ENOMEM; + + comm_data->io_params =3D (struct rmi_dev_comm_data *)get_zeroed_page(GFP_= KERNEL); + if (!comm_data->io_params) + goto err_out; + + comm_data->rsp_buff =3D (void *)__get_free_page(GFP_KERNEL); + if (!comm_data->rsp_buff) + goto err_res_buff; + + comm_data->req_buff =3D (void *)__get_free_page(GFP_KERNEL); + if (!comm_data->req_buff) + goto err_req_buff; + + comm_data->work_queue =3D 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 =3D RMI_DEV_COMM_NONE; + comm_data->io_params->enter.resp_addr =3D virt_to_phys(comm_data->rsp_buf= f); + comm_data->io_params->enter.req_addr =3D virt_to_phys(comm_data->req_buf= f); + comm_data->io_params->enter.resp_len =3D 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_dat= a *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) =3D=3D PCI_EXP_TYPE_ENDPOINT; diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.c b/drivers/virt/coco/ar= m-cca-host/rmi-da.c index 863bb425e5c9..495a3bd2798f 100644 --- a/drivers/virt/coco/arm-cca-host/rmi-da.c +++ b/drivers/virt/coco/arm-cca-host/rmi-da.c @@ -6,6 +6,8 @@ #include #include #include +#include +#include =20 #include "rmi-da.h" =20 @@ -144,3 +146,277 @@ int cca_pdev_create(struct pci_dev *pci_dev) free_page((unsigned long)rmm_pdev); return ret; } + +static int doe_send_req_resp(struct pci_tsm *tsm) +{ + int data_obj_type; + struct cca_host_comm_data *comm_data =3D to_cca_comm_data(tsm->pdev); + struct rmi_dev_comm_exit *io_exit =3D &comm_data->io_params->exit; + u8 protocol =3D io_exit->protocol; + + if (protocol =3D=3D RMI_PROTOCOL_SPDM) + data_obj_type =3D PCI_DOE_FEATURE_CMA; + else if (protocol =3D=3D RMI_PROTOCOL_SECURE_SPDM) + data_obj_type =3D PCI_DOE_FEATURE_SSESSION; + else + return -EINVAL; + + /* delay the send */ + if (io_exit->req_delay) + fsleep(io_exit->req_delay); + + return pci_tsm_doe_transfer(tsm->dsm_dev, data_obj_type, + comm_data->req_buff, io_exit->req_len, + comm_data->rsp_buff, PAGE_SIZE); +} + +static inline bool pending_dev_communicate(struct rmi_dev_comm_exit *io_ex= it) +{ + bool pending =3D io_exit->flags & (RMI_DEV_COMM_EXIT_CACHE_REQ | + RMI_DEV_COMM_EXIT_CACHE_RSP | + RMI_DEV_COMM_EXIT_SEND | + RMI_DEV_COMM_EXIT_WAIT | + RMI_DEV_COMM_EXIT_MULTI); + return pending; +} + +static inline gfp_t cache_obj_id_to_gfp_flags(u8 cache_obj_id) +{ + /* These two cache objects are system objects. */ + if (cache_obj_id =3D=3D RMI_DEV_VCA || cache_obj_id =3D=3D RMI_DEV_CERTIF= ICATE) + return GFP_KERNEL; + /* rest are per TDI which is associated to a VM */ + return GFP_KERNEL_ACCOUNT; +} + +static int _do_dev_communicate(enum dev_comm_type type, struct pci_tsm *ts= m) +{ + unsigned long rmi_ret; + gfp_t cache_alloc_flags; + int nbytes, cp_len; + struct cache_object **cache_objp, *cache_obj; + struct cca_host_pdev_dsc *pdev_dsc =3D to_cca_pdev_dsc(tsm->dsm_dev); + struct cca_host_comm_data *comm_data =3D to_cca_comm_data(tsm->pdev); + struct rmi_dev_comm_enter *io_enter =3D &comm_data->io_params->enter; + struct rmi_dev_comm_exit *io_exit =3D &comm_data->io_params->exit; + +redo_communicate: + + if (type =3D=3D PDEV_COMMUNICATE) + rmi_ret =3D rmi_pdev_communicate(virt_to_phys(pdev_dsc->rmm_pdev), + virt_to_phys(comm_data->io_params)); + else + rmi_ret =3D RMI_ERROR_INPUT; + if (rmi_ret !=3D RMI_SUCCESS) { + if (rmi_ret =3D=3D RMI_BUSY) + return -EBUSY; + return -EIO; + } + + if (io_exit->flags & RMI_DEV_COMM_EXIT_CACHE_REQ || + io_exit->flags & RMI_DEV_COMM_EXIT_CACHE_RSP) { + struct cca_host_pf0_ep_dsc *pf0_ep_dsc =3D to_cca_pf0_ep_dsc(tsm->dsm_de= v); + + if (!pf0_ep_dsc) { + WARN(1, + "Device communication got cache request on wrong device\n"); + return -EINVAL; + } + + switch (io_exit->cache_object_id) { + case RMI_DEV_VCA: + cache_objp =3D &pf0_ep_dsc->vca; + break; + case RMI_DEV_CERTIFICATE: + cache_objp =3D &pf0_ep_dsc->cert_chain.cache; + break; + default: + return -EINVAL; + } + cache_obj =3D *cache_objp; + cache_alloc_flags =3D cache_obj_id_to_gfp_flags(io_exit->cache_object_id= ); + int cache_remaining; + + if (io_exit->flags & RMI_DEV_COMM_EXIT_CACHE_REQ) + cp_len =3D io_exit->req_cache_len; + else + cp_len =3D io_exit->rsp_cache_len; + + /* response and request len should be <=3D SZ_4k */ + if (cp_len > CACHE_CHUNK_SIZE) + return -EINVAL; + + /* new allocation */ + if (!cache_obj) { + int obj_size =3D struct_size(cache_obj, buf, + CACHE_CHUNK_SIZE); + + cache_obj =3D kvmalloc(obj_size, cache_alloc_flags); + if (!cache_obj) + return -ENOMEM; + + cache_obj->size =3D CACHE_CHUNK_SIZE; + cache_obj->offset =3D 0; + *cache_objp =3D cache_obj; + } + + cache_remaining =3D cache_obj->size - cache_obj->offset; + if (cp_len > cache_remaining) { + struct cache_object *new_obj; + int new_size =3D struct_size(cache_obj, buf, + cache_obj->size + + CACHE_CHUNK_SIZE); + + if (cache_obj->size + CACHE_CHUNK_SIZE > MAX_CACHE_OBJ_SIZE) + return -EINVAL; + + new_obj =3D kvrealloc(cache_obj, new_size, cache_alloc_flags); + if (!new_obj) + return -ENOMEM; + new_obj->size =3D cache_obj->size + CACHE_CHUNK_SIZE; + *cache_objp =3D new_obj; + } + + /* cache object can change above. */ + cache_obj =3D *cache_objp; + } + + + if (io_exit->flags & RMI_DEV_COMM_EXIT_CACHE_REQ) { + memcpy(cache_obj->buf + cache_obj->offset, + (comm_data->req_buff + io_exit->req_cache_offset), io_exit->req_c= ache_len); + cache_obj->offset +=3D io_exit->req_cache_len; + } + + if (io_exit->flags & RMI_DEV_COMM_EXIT_CACHE_RSP) { + memcpy(cache_obj->buf + cache_obj->offset, + (comm_data->rsp_buff + io_exit->rsp_cache_offset), io_exit->rsp_c= ache_len); + cache_obj->offset +=3D io_exit->rsp_cache_len; + } + + /* + * wait for last packet request from RMM. + * We should not find this because our device communication is synchronous + */ + if (io_exit->flags & RMI_DEV_COMM_EXIT_WAIT) + return -EIO; + + /* next packet to send */ + if (io_exit->flags & RMI_DEV_COMM_EXIT_SEND) { + nbytes =3D doe_send_req_resp(tsm); + if (nbytes < 0) { + /* report error back to RMM */ + io_enter->status =3D RMI_DEV_COMM_ERROR; + } else { + /* send response back to RMM */ + io_enter->resp_len =3D nbytes; + io_enter->status =3D RMI_DEV_COMM_RESPONSE; + } + } else { + /* no data transmitted =3D> no data received */ + io_enter->resp_len =3D 0; + io_enter->status =3D RMI_DEV_COMM_NONE; + } + + if (pending_dev_communicate(io_exit)) + goto redo_communicate; + + return 0; +} + +static int do_dev_communicate(enum dev_comm_type type, + struct pci_tsm *tsm, unsigned long error_state) +{ + int ret, state =3D error_state; + struct rmi_dev_comm_enter *io_enter; + struct cca_host_pdev_dsc *pdev_dsc =3D to_cca_pdev_dsc(tsm->dsm_dev); + + io_enter =3D &pdev_dsc->comm_data.io_params->enter; + io_enter->resp_len =3D 0; + io_enter->status =3D RMI_DEV_COMM_NONE; + + ret =3D _do_dev_communicate(type, tsm); + if (ret) { + if (type =3D=3D PDEV_COMMUNICATE) + rmi_pdev_abort(virt_to_phys(pdev_dsc->rmm_pdev)); + } else { + /* + * Some device communication error will transition the + * device to error state. Report that. + */ + if (type =3D=3D PDEV_COMMUNICATE) { + if (rmi_pdev_get_state(virt_to_phys(pdev_dsc->rmm_pdev), + (enum rmi_pdev_state *)&state)) + state =3D error_state; + } + } + + if (state =3D=3D error_state) + pci_err(tsm->pdev, "device communication error\n"); + + return state; +} + +static int wait_for_dev_state(enum dev_comm_type type, struct pci_tsm *tsm, + unsigned long target_state, unsigned long error_state) +{ + int state; + + do { + state =3D do_dev_communicate(type, tsm, error_state); + + if (state =3D=3D target_state || state =3D=3D error_state) + return state; + } while (1); + + /* can't reach */ + return error_state; +} + +static int wait_for_pdev_state(struct pci_tsm *tsm, enum rmi_pdev_state ta= rget_state) +{ + return wait_for_dev_state(PDEV_COMMUNICATE, tsm, target_state, RMI_PDEV_E= RROR); +} + +static void pdev_state_transition_workfn(struct work_struct *work) +{ + unsigned long state; + struct pci_tsm *tsm; + struct dev_comm_work *setup_work; + struct cca_host_pdev_dsc *pdev_dsc; + + setup_work =3D container_of(work, struct dev_comm_work, work); + tsm =3D setup_work->tsm; + pdev_dsc =3D to_cca_pdev_dsc(tsm->dsm_dev); + + guard(mutex)(&pdev_dsc->object_lock); + state =3D wait_for_pdev_state(tsm, setup_work->target_state); + WARN_ON(state !=3D setup_work->target_state); +} + +static int __maybe_unused submit_pdev_state_transition_work(struct pci_dev= *pdev, + enum rmi_pdev_state target_state) +{ + enum rmi_pdev_state state; + struct dev_comm_work comm_work; + struct cca_host_pdev_dsc *pdev_dsc =3D to_cca_pdev_dsc(pdev); + struct cca_host_comm_data *comm_data =3D to_cca_comm_data(pdev); + + INIT_WORK_ONSTACK(&comm_work.work, pdev_state_transition_workfn); + comm_work.tsm =3D pdev->tsm; + comm_work.target_state =3D target_state; + + queue_work(comm_data->work_queue, &comm_work.work); + + flush_work(&comm_work.work); + destroy_work_on_stack(&comm_work.work); + + /* check if we reached target state */ + if (rmi_pdev_get_state(virt_to_phys(pdev_dsc->rmm_pdev), &state)) + return -EIO; + + if (state !=3D target_state) + /* no specific error for this */ + return -1; + return 0; +} diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.h b/drivers/virt/coco/ar= m-cca-host/rmi-da.h index f1580308777b..07034b034b53 100644 --- a/drivers/virt/coco/arm-cca-host/rmi-da.h +++ b/drivers/virt/coco/arm-cca-host/rmi-da.h @@ -11,13 +11,44 @@ #include #include #include +#include + +#define MAX_CACHE_OBJ_SIZE SZ_16M +#define CACHE_CHUNK_SIZE SZ_4K +struct cache_object { + int size; + int offset; + u8 buf[] __counted_by(size); +}; + +struct dev_comm_work { + struct pci_tsm *tsm; + int target_state; + struct work_struct work; +}; + +struct cca_host_comm_data { + void *rsp_buff; + void *req_buff; + struct rmi_dev_comm_data *io_params; + /* + * Only one device communication request can be active at + * a time. This limitation comes from using the DOE mailbox + * at the pdev level. Requests such as get_measurements may + * span multiple mailbox messages, which must not be + * interleaved with other SPDM requests. + */ + struct workqueue_struct *work_queue; +}; =20 /** * struct cca_host_pdev_dsc - Common RMM pdev context + * @comm_data: Shared device communication state for the DSM-owned pdev * @rmm_pdev: Delegated page backing the RMM pdev object * @object_lock: Serializes access to the RMM pdev object and PF0/TDI cach= es */ struct cca_host_pdev_dsc { + struct cca_host_comm_data comm_data; void *rmm_pdev; /* lock kept here to simplify the generic lock/unlock paths. */ struct mutex object_lock; @@ -28,17 +59,33 @@ struct cca_host_pdev_dsc { * @pci: Physical Function 0 TDISP link context * @pdev: pdev communication context * @sel_stream: Selective IDE Stream descriptor + * @cert_chain: cetrificate chain + * @vca: SPDM's Version-Capabilities-Algorithms cache object */ struct cca_host_pf0_ep_dsc { struct pci_tsm_pf0 pci; struct cca_host_pdev_dsc pdev; struct pci_ide *sel_stream; + + struct { + struct cache_object *cache; + + void *public_key; + size_t public_key_size; + + bool valid; + } cert_chain; + struct cache_object *vca; }; =20 struct cca_host_fn_dsc { struct pci_tsm pci; }; =20 +enum dev_comm_type { + PDEV_COMMUNICATE =3D 0x1, +}; + static inline struct cca_host_pf0_ep_dsc *to_cca_pf0_ep_dsc(struct pci_dev= *pdev) { struct pci_tsm *tsm =3D pdev->tsm; @@ -67,6 +114,24 @@ static inline struct cca_host_pdev_dsc *to_cca_pdev_dsc= (struct pci_dev *pdev) return NULL; } =20 +static inline struct cca_host_comm_data *to_cca_comm_data(struct pci_dev *= pdev) +{ + struct cca_host_pdev_dsc *pdev_dsc; + + pdev_dsc =3D to_cca_pdev_dsc(pdev); + if (pdev_dsc) + return &pdev_dsc->comm_data; + + if (!pdev->tsm || !pdev->tsm->dsm_dev) + return NULL; + + pdev_dsc =3D to_cca_pdev_dsc(pdev->tsm->dsm_dev); + if (pdev_dsc) + return &pdev_dsc->comm_data; + + return NULL; +} + int cca_pdev_create(struct pci_dev *pdev); =20 #endif diff --git a/include/linux/arm-rmi-cmds.h b/include/linux/arm-rmi-cmds.h index 850ac8e230e2..c2fc80dd19cc 100644 --- a/include/linux/arm-rmi-cmds.h +++ b/include/linux/arm-rmi-cmds.h @@ -686,4 +686,24 @@ static inline unsigned long rmi_pdev_get_state(unsigne= d long pdev_phys, enum rmi return res.a0; } =20 +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 diff --git a/include/linux/arm-smccc-rmi.h b/include/linux/arm-smccc-rmi.h index 7241da55c753..3133b34354ce 100644 --- a/include/linux/arm-smccc-rmi.h +++ b/include/linux/arm-smccc-rmi.h @@ -534,4 +534,66 @@ struct rmi_pdev_params { }; }; =20 +#define RMI_DEV_COMM_EXIT_CACHE_REQ BIT(0) +#define RMI_DEV_COMM_EXIT_CACHE_RSP BIT(1) +#define RMI_DEV_COMM_EXIT_SEND BIT(2) +#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_NONE 0 +#define RMI_DEV_COMM_RESPONSE 1 +#define RMI_DEV_COMM_ERROR 2 + +#define RMI_PROTOCOL_SPDM 0 +#define RMI_PROTOCOL_SECURE_SPDM 1 + +#define RMI_DEV_VCA 0 +#define RMI_DEV_CERTIFICATE 1 +#define RMI_DEV_MEASUREMENTS 2 +#define RMI_DEV_INTERFACE_REPORT 3 + +struct rmi_dev_comm_enter { + union { + u8 status; + u64 padding0; + }; + u64 req_addr; + u64 resp_addr; + u64 resp_len; + u8 padding1[0xe0]; +}; + +struct rmi_dev_comm_exit { + u64 flags; + u64 req_cache_offset; + u64 req_cache_len; + u64 rsp_cache_offset; + u64 rsp_cache_len; + union { + u8 cache_object_id; + u8 padding0[0x8]; + }; + + union { + u8 protocol; + u8 padding1[0x8]; + }; + u64 req_delay; + u64 req_len; + u64 rsp_timeout; + u8 padding2[0xb0]; +}; + +struct rmi_dev_comm_data { + union { /* 0x0 */ + struct rmi_dev_comm_enter enter; + u8 padding0[0x800]; + }; + union { /* 0x800 */ + struct rmi_dev_comm_exit exit; + u8 padding1[0x800]; + }; +}; + #endif /* __LINUX_ARM_SMCCC_RMI_H_ */ --=20 2.43.0 From nobody Fri Sep 25 16:01:36 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C03E649DB8B; Thu, 10 Sep 2026 14:05:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049148; cv=none; b=ZjRoMxAV28a7U0RNq6vAB7La2JNJ8gPm9v+n624wOc85TyFFprRJ1y8LS6nv1ItfargKnHr+3FFkHPcOJodOajoYqNbVzQ/5T5cs5MV0yv4n9Od5i7FhPFy8w/G22m4DHak//pCiZDl0topjzsZ2lJsOgTrCc3+904y7PXxY8P4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049148; c=relaxed/simple; bh=j2vpmR9myFwAcMjs58RSG+Vi3DV7VWhNBTVrLRXGffI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FU5rj/JK5b5UdLbKRd/LAeGb3glt9a7gNdC0mIn83/AnHLA8QB01/L1em/dXVQX+hOsR2i+Bghmns4pAqCgwxpGO1oulKDgKYYwYL+bnpAzh6ohdJunPWE9WvnUFt2B7vCaSUiNV/qa2p43ZTzlpdXFwkNZ9C0NctD9CHPTMfPQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=JXqZJQPN; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="JXqZJQPN" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6310D1F000FF; Thu, 10 Sep 2026 14:05:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1789049146; bh=luXs/S+Jd2KjBu4OQ9brsQHU+FfslBl2cNL4bNycYLc=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=JXqZJQPNFlO9/UykM96CLppxtOFbk0Ol3RL7i4VXURo6OoPYE7Hio1SE7ITiM4wGD bJV9HBk/AGRRnoLBB1u8cVw4BU/btRgxNwlPzPDvBhVSzWUWd5SZv62qc0MWtVn1hq seBdwbFLXvofdWfGxSy2ip3TAEOlzCqRebgE9uDAamx14h+JunJCfRxd9yX6fz6cw+ H7kXv3GdUeQmkdapzX7nwbN7oJ3WscH+1eBdPZk1WRoyVOPjvA1OkuI76LDUtid1V0 ZARQhoAx9SFuWFVe8IKoftnCGjaJnrF5ZXG6pX+yi3EQaY+k+zLrsqs8i/3qBvqwB+ jVvNbOcKCvT4Q== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Alexey Kardashevskiy , Catalin Marinas , Dan Williams , Jason Gunthorpe , Jonathan Cameron , Marc Zyngier , Samuel Ortiz , Steven Price , Suzuki K Poulose , Will Deacon , Xu Yilun Subject: [PATCH v5 04/15] coco: host: arm64: Add RMM pdev stop and destroy helper Date: Thu, 10 Sep 2026 19:34:57 +0530 Message-ID: <20260910140509.868402-5-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260910140509.868402-1-aneesh.kumar@kernel.org> References: <20260910140509.868402-1-aneesh.kumar@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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. Signed-off-by: Aneesh Kumar K.V (Arm) --- 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(-) diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.c b/drivers/virt/coco/ar= m-cca-host/rmi-da.c index 495a3bd2798f..7a72e8eead90 100644 --- a/drivers/virt/coco/arm-cca-host/rmi-da.c +++ b/drivers/virt/coco/arm-cca-host/rmi-da.c @@ -394,7 +394,7 @@ static void pdev_state_transition_workfn(struct work_st= ruct *work) WARN_ON(state !=3D setup_work->target_state); } =20 -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 *pdev return -1; return 0; } + +static inline int rmi_pdev_destroy(unsigned long pdev_phys, + unsigned long *rmi_ret) +{ + struct rmi_sro_state *sro __free(kfree) =3D kmalloc_obj(*sro); + if (!sro) + return -ENOMEM; + + *rmi_ret =3D 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 =3D to_cca_pdev_dsc(pdev); + struct cca_host_pf0_ep_dsc *pf0_ep_dsc =3D to_cca_pf0_ep_dsc(pdev); + phys_addr_t rmm_pdev_phys =3D virt_to_phys(pdev_dsc->rmm_pdev); + + if (WARN_ON(rmi_pdev_stop(rmm_pdev_phys))) + return; + + ret =3D submit_pdev_state_transition_work(pdev, RMI_PDEV_STOPPED); + if (ret) + return; + + ret =3D 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 =3D NULL; + pf0_ep_dsc->vca =3D NULL; + } + + if (!rmi_undelegate_page(rmm_pdev_phys)) + free_page((unsigned long)pdev_dsc->rmm_pdev); + pdev_dsc->rmm_pdev =3D NULL; +} diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.h b/drivers/virt/coco/ar= m-cca-host/rmi-da.h index 07034b034b53..f3bd106c8a54 100644 --- a/drivers/virt/coco/arm-cca-host/rmi-da.h +++ b/drivers/virt/coco/arm-cca-host/rmi-da.h @@ -133,5 +133,6 @@ static inline struct cca_host_comm_data *to_cca_comm_da= ta(struct pci_dev *pdev) } =20 int cca_pdev_create(struct pci_dev *pdev); +void cca_pdev_stop_and_destroy(struct pci_dev *pdev); =20 #endif diff --git a/include/linux/arm-rmi-cmds.h b/include/linux/arm-rmi-cmds.h index c2fc80dd19cc..f947b2f4909a 100644 --- a/include/linux/arm-rmi-cmds.h +++ b/include/linux/arm-rmi-cmds.h @@ -706,4 +706,13 @@ static inline unsigned long rmi_pdev_abort(unsigned lo= ng pdev_phys) return res.a0; } =20 +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 --=20 2.43.0 From nobody Fri Sep 25 16:01:36 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0A92A49DBB8; Thu, 10 Sep 2026 14:05:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049155; cv=none; b=FjjWyJVwIEi0f9FpnqVwliPAAaAt9r97UUsIiUkezxSLZWxRUR4rew+obRQO/lvOiHvp0qM7sNH8XfspeRyOqeNGcokFLrhLfwVmUBFrKz+G+KJvCjhVArgVaDA11ad9zELeiw+vpeSrtpNIcznqsJZYsR01xOgtSSdGMOWnw1I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049155; c=relaxed/simple; bh=iT902Kks+8Y5KbHMSujhzXpOT2Flu5+M48nmim2dfB8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=jBH4VXzuzrOtVZotpvb++HPxMK1fN2OCtkDIAeT5a3gBQegFs8/v14nv7Id75GyUhj/AuKxd3IKdmeaDzXKHzLOPsGLbErbo4YLsr40OVKuYVztI3a+9RmwZi1h2bgfAR3+lr8VP05vaYzeOpx31m3hievsOeP7QibK5IzPStlE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=meHwmQsT; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="meHwmQsT" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0F0851F00899; Thu, 10 Sep 2026 14:05:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1789049153; bh=YKwzMF4Jues8v9L8adOzb6dNb4/nlEvbqWvzaKf2xQ4=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=meHwmQsTXmZ05vkNeXF3/aBPPJOYI5II87m4CzDGg3ZM8G2u7YZdtkT8Lazw8Vb7j eobdlAaWRYC+SeeEAkWXwfu1zzXQfuwV+4mFL9tbO5kfr+0iSPb3A3VQLMYFMpL8Ez twV67ErqpDrS8uCS0wR3+guCphvz1qZZ0nyvChQg83KsMRTO3V5ErE30mjsi9iJvro +uhnMLJjVtSXglxLWrx2LLRaTwmgaMNsJI6VYdJOQ3/HbwSa6FGMbFBQ4VifYrxqFn RGnBnnMzZUDRYJuMw915aIQSQ54OoxC0PdXUG1U9mBgU8VcX1EGeCBYONckW1NZH/m J26Og/ZLqLvOA== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Alexey Kardashevskiy , Catalin Marinas , Dan Williams , Jason Gunthorpe , Jonathan Cameron , Marc Zyngier , Samuel Ortiz , Steven Price , Suzuki K Poulose , Will Deacon , Xu Yilun , Lukas Wunner , =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= , Jonathan Cameron Subject: [PATCH v5 05/15] X.509: Make certificate parser public Date: Thu, 10 Sep 2026 19:34:58 +0530 Message-ID: <20260910140509.868402-6-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260910140509.868402-1-aneesh.kumar@kernel.org> References: <20260910140509.868402-1-aneesh.kumar@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Lukas Wunner 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 for the definition of time64_t. That definition was since moved to 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 . No functional change intended. Signed-off-by: Lukas Wunner Reviewed-by: Dan Williams Reviewed-by: Ilpo J=C3=A4rvinen Reviewed-by: Jonathan Cameron Signed-off-by: Aneesh Kumar K.V (Arm) --- 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 diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/= x509_parser.h index b7aeebdddb36..39f1521b773d 100644 --- a/crypto/asymmetric_keys/x509_parser.h +++ b/crypto/asymmetric_keys/x509_parser.h @@ -5,51 +5,11 @@ * Written by David Howells (dhowells@redhat.com) */ =20 -#include -#include -#include -#include -#include - -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 =20 /* * 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 d= atalen); extern int x509_decode_time(time64_t *_t, size_t hdrlen, unsigned char tag, const unsigned char *value, size_t vlen); diff --git a/include/keys/x509-parser.h b/include/keys/x509-parser.h new file mode 100644 index 000000000000..8b68e720693a --- /dev/null +++ b/include/keys/x509-parser.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* X.509 certificate parser + * + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +#ifndef _KEYS_X509_PARSER_H +#define _KEYS_X509_PARSER_H + +#include +#include +#include +#include +#include + +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; +}; + +struct x509_certificate *x509_cert_parse(const void *data, size_t datalen); +void x509_free_certificate(struct x509_certificate *cert); + +DEFINE_FREE(x509_free_certificate, struct x509_certificate *, + if (!IS_ERR(_T)) x509_free_certificate(_T)) + +#endif /* _KEYS_X509_PARSER_H */ --=20 2.43.0 From nobody Fri Sep 25 16:01:36 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DE920489FD0; Thu, 10 Sep 2026 14:06:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049163; cv=none; b=fQ5qUIvNLc/UCaY4uGWntvt7x9x5OxID1YmCXFd7ZR38Iw0Um/s4w+L3kLm9Ni4tXvLLaO+COVT12wWy2i4T1RQ+qcaWsNbDnpLV2H7p9BRmyn2TDo31KQcOn+Ot1EcaClnqFqnwLPDqbOxZw/evbbdM2nbW+tbau7YQHhM17lY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049163; c=relaxed/simple; bh=6BCszsXk8d+Z0XLNFAG78fBDmY5OsPZxWRGyTYS9Amk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=P2DvJ/UbvfMSYX48vjE/u4PJwHBE4wdgMdaVSuhLqzc8K194oiLITRYm23iycGZNqX1oz+JTyc1iiECsXWhrplYFi20p9sjP09dKe3pmwB5RcX3BIzYiufJx8KfFWuKHVfUJ39ng0pxJguZ5ePmWbgb0k0nekxq++BnxjQTuHPM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=aEhHkPMI; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="aEhHkPMI" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5100A1F000FF; Thu, 10 Sep 2026 14:05:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1789049161; bh=MJXs8QEQplpsD7TykCLygoPyjsSjXkWAK/IQrvHJzTM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=aEhHkPMI95R2HMm7OcFqIIp2t363j7h16Mbj3iZUXL1gUTYX4eK36EBuNlWmB9rr4 C0ACD2I851UWas5dLSimqai2XK2vDX2mn+lnfWeTk+BNdT2AAwhEvflzqLISHLY+2Z OInh+vVW6Ouh2lNlKcxn8+qkjiVf3/CPl4lBF25HZCXCq5H++sCi+GD+T1O0IZZ0TN qncCi9d8rpaToAvbm88rVOTyP8F+xSDUQu5t+PW1B3TLczcJq+LFZLQsky7HuLOdgL lLHPA8S2I5Bj7XijlAp2cnZRR2npvrXlYDHOeKqzsg6Iv97b8XpEMwoeYR4DFS5N0a Ddwh6iMGNxwFg== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Alexey Kardashevskiy , Catalin Marinas , Dan Williams , Jason Gunthorpe , Jonathan Cameron , Marc Zyngier , Samuel Ortiz , Steven Price , Suzuki K Poulose , Will Deacon , Xu Yilun , Lukas Wunner , Wilfred Mallawa , =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= , Jonathan Cameron Subject: [PATCH v5 06/15] X.509: Parse Subject Alternative Name in certificates Date: Thu, 10 Sep 2026 19:34:59 +0530 Message-ID: <20260910140509.868402-7-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260910140509.868402-1-aneesh.kumar@kernel.org> References: <20260910140509.868402-1-aneesh.kumar@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Lukas Wunner 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. Signed-off-by: Lukas Wunner Reviewed-by: Wilfred Mallawa Reviewed-by: Ilpo J=C3=A4rvinen Reviewed-by: Jonathan Cameron Acked-by: Dan Williams Signed-off-by: Aneesh Kumar K.V (Arm) --- crypto/asymmetric_keys/x509_cert_parser.c | 9 +++++++++ include/keys/x509-parser.h | 2 ++ 2 files changed, 11 insertions(+) diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_= keys/x509_cert_parser.c index bfd10f0195e0..c3ec2846695a 100644 --- a/crypto/asymmetric_keys/x509_cert_parser.c +++ b/crypto/asymmetric_keys/x509_cert_parser.c @@ -596,6 +596,15 @@ int x509_process_extension(void *context, size_t hdrle= n, return 0; } =20 + if (ctx->last_oid =3D=3D OID_subjectAltName) { + if (ctx->cert->raw_san) + return -EBADMSG; + + ctx->cert->raw_san =3D v; + ctx->cert->raw_san_size =3D vlen; + return 0; + } + if (ctx->last_oid =3D=3D OID_keyUsage) { /* * Get hold of the keyUsage bit string diff --git a/include/keys/x509-parser.h b/include/keys/x509-parser.h index 8b68e720693a..4e6a05a8c7a6 100644 --- a/include/keys/x509-parser.h +++ b/include/keys/x509-parser.h @@ -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; --=20 2.43.0 From nobody Fri Sep 25 16:01:36 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D67EB47DFA0; Thu, 10 Sep 2026 14:06:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049170; cv=none; b=XGP8pncE9M11lGW72YK6L0Z/RLmwy9aFOQ09DmV6HwFIlvNxQOhFwlnwqzQeqCPGqAoSJMyJul6yNc9st91KQBr18IaIdvkBGRqnz1PhZFkFtbmOU2xZFlcay+nakKrcbokve1wEYCtfXIawESbIZYKMAEMtZ65HDzNhIs+3EJY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049170; c=relaxed/simple; bh=ZekddyUAupgcV4cqOlYACPyOcsZqNYPA+Vwwi1mz3PI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Et9RFACoMVg+AdGypLAx3PTefgLbbl6M+x60vNlFVSFlEFXwEYn5quRUBUdkMUz98KW+04twxOT08xFTu8EX/G2Oi8MtRXd7OQADUIVYQNWqPUoDuvbMf1Vk7gTmVMby8wIm56HS8mpSF92WH5Na8CK97JE9a71KGMhaeD88QYU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=W+Yfr3B2; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="W+Yfr3B2" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1BE221F00898; Thu, 10 Sep 2026 14:06:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1789049168; bh=bQxF5xPnidokpY8b4H+spdca0SQOWphTNH0IC+8rD8s=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=W+Yfr3B2cmI6WXnzmhxjcrdlIzZGAK6ctIf/QDzgV8LB4GtNmkmB1H2OQDYxE2sYX zV1kQvoT9kMMY1gV0DxuXGK9Xo4ZSjwVcNFgltva8RL06rSL8d/soQj0JO1EjPYKwO Ax1i6cg9/VeyxEu90tA8kgY7nFRAbN0Bu1CvaFAGYLLu2Z1y4hKO78/QpZzqpMsjmj BTHnc+4ma5K4dEnVU3zPMIYIa3hRqWPUqeozaMNiQSgNTQleAHHz+ZSEFGkINZGaFX ljiihOMYN/PWCcnYhkzlqyISwBxo+YYYUuRG+OapSt2AVK9Z0UWRypn5Qq4Kk2JCo9 BYeIQPs5mluYg== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Alexey Kardashevskiy , Catalin Marinas , Dan Williams , Jason Gunthorpe , Jonathan Cameron , Marc Zyngier , Samuel Ortiz , Steven Price , Suzuki K Poulose , Will Deacon , Xu Yilun , Lukas Wunner , Jonathan Cameron Subject: [PATCH v5 07/15] X.509: Move certificate length retrieval into new helper Date: Thu, 10 Sep 2026 19:35:00 +0530 Message-ID: <20260910140509.868402-8-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260910140509.868402-1-aneesh.kumar@kernel.org> References: <20260910140509.868402-1-aneesh.kumar@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Lukas Wunner 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. Signed-off-by: Lukas Wunner Reviewed-by: Dan Williams Reviewed-by: Jonathan Cameron Signed-off-by: Aneesh Kumar K.V (Arm) --- crypto/asymmetric_keys/x509_loader.c | 38 +++++++++++++++++++--------- include/keys/asymmetric-type.h | 2 ++ 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/crypto/asymmetric_keys/x509_loader.c b/crypto/asymmetric_keys/= x509_loader.c index 0d516c77cc26..174451b93eda 100644 --- a/crypto/asymmetric_keys/x509_loader.c +++ b/crypto/asymmetric_keys/x509_loader.c @@ -4,28 +4,42 @@ #include #include =20 +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] !=3D 0x30 || + p[1] !=3D 0x82) + return -EINVAL; + + plen =3D (p[2] << 8) | p[3]; + plen +=3D 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; =20 p =3D cert_list; end =3D 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] !=3D 0x30 || - p[1] !=3D 0x82) - goto dodgy_cert; - plen =3D (p[2] << 8) | p[3]; - plen +=3D 4; - if (plen > end - p) + plen =3D x509_get_certificate_length(p, end - p); + if (plen < 0) goto dodgy_cert; =20 key =3D key_create_or_update(make_key_ref(keyring, 1), diff --git a/include/keys/asymmetric-type.h b/include/keys/asymmetric-type.h index 1b91c8f98688..301efa952e26 100644 --- a/include/keys/asymmetric-type.h +++ b/include/keys/asymmetric-type.h @@ -84,6 +84,8 @@ extern struct key *find_asymmetric_key(struct key *keyrin= g, const struct asymmetric_key_id *id_2, bool partial); =20 +ssize_t x509_get_certificate_length(const u8 *p, unsigned long buflen); + int x509_load_certificate_list(const u8 cert_list[], const unsigned long l= ist_size, const struct key *keyring); =20 --=20 2.43.0 From nobody Fri Sep 25 16:01:36 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 078A349C4DE; Thu, 10 Sep 2026 14:06:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049177; cv=none; b=dFM9Ut7nZRtTfILFWFk0GhDrfE3NyPm3o6cDbBmx2HcRuDsZCng7UXg6g22Om/r3thhR1iPSLVtIErbQfSacS1X4n5yYdnVrLdIBo68ugUEqhLRUtkP0btV6q0zqGWGZjSbdqCMAOd/F9KgWhTwzlEi2cdO2JUJqQh2M3ajabKQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049177; c=relaxed/simple; bh=MMAtey+9IMba7dZkmuYNGjCD59kI8+2TWL769qvRkcA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=GXPHL3s3oGBBIqwD/lbwl0wSibCvvCD61tEn4YsGMrUXY+rN3cI2DsGZJxg3Uh/tHgidoPqP8/2amexRKUOpAfI+FY0fTNET+OQXIcEhWkSRhbgBxExHClc+Is1U/VU/oCS358dh6Mrz+uH0Mc5vjF5FOSNEW+tVf95R4/TDFXc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=JTsc+wSR; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="JTsc+wSR" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 77D361F000FF; Thu, 10 Sep 2026 14:06:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1789049175; bh=CB6ghbgDfVwHgjqO9k99YiMcwetqo8QudA9rXLeQUJM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=JTsc+wSRMF2u/wDOvehp/0qBJt2b6pliIpB8D0gu6ByMP1AzSUdEGLw5HWf1KnB9g 46Sj9Lo7ZwCUzaCiIh8Zj8qGO7o+uAAzdZKISao/KO8Knla8Y1V05ehrDquUYMx9rS sFPZoxPvnSglk5FTTgo+T4whprCq9pyZjIjFMOZsZVSQgnfJTjLqK5rx82+3TEHagT 5U08vrubQAvdJDlxQ7Wi92o34oPdA+PePTbnmJ+Q3gZNAzrrF3yrlxIIumelh0DtU+ 4FfF3e78Iez2KQlGEzqg0eg+bzV1Tv7OOlrCzGI7AItzHbJphftQKNvZyfOW519LB8 1wLMQty+M4MlQ== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Alexey Kardashevskiy , Catalin Marinas , Dan Williams , Jason Gunthorpe , Jonathan Cameron , Marc Zyngier , Samuel Ortiz , Steven Price , Suzuki K Poulose , Will Deacon , Xu Yilun Subject: [PATCH v5 08/15] coco: host: arm64: Register device public key with RMM Date: Thu, 10 Sep 2026 19:35:01 +0530 Message-ID: <20260910140509.868402-9-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260910140509.868402-1-aneesh.kumar@kernel.org> References: <20260910140509.868402-1-aneesh.kumar@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable - Introduce the SMC_RMI_PDEV_SET_PUBKEY helper and the associated struct rmi_public_key_params so the host can hand the device=E2=80=99s public key = to the RMM. - Parse the certificate chain cached during SPDM session setup, extract the final certificate=E2=80=99s public key, and recognise RSA-3072, ECDSA-P256,= and ECDSA-P384 keys before calling into the RMM. Signed-off-by: Aneesh Kumar K.V (Arm) --- 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(+) diff --git a/drivers/virt/coco/arm-cca-host/Kconfig b/drivers/virt/coco/arm= -cca-host/Kconfig index d2bf44f9776a..43f0f0228e0c 100644 --- a/drivers/virt/coco/arm-cca-host/Kconfig +++ b/drivers/virt/coco/arm-cca-host/Kconfig @@ -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 =20 help ARM CCA RMM firmware is the trusted runtime that enforces memory diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.c b/drivers/virt/coco/ar= m-cca-host/rmi-da.c index 7a72e8eead90..394b6a87f2d3 100644 --- a/drivers/virt/coco/arm-cca-host/rmi-da.c +++ b/drivers/virt/coco/arm-cca-host/rmi-da.c @@ -8,6 +8,9 @@ #include #include #include +#include +#include +#include =20 #include "rmi-da.h" =20 @@ -378,6 +381,154 @@ static int wait_for_pdev_state(struct pci_tsm *tsm, e= num rmi_pdev_state target_s return wait_for_dev_state(PDEV_COMMUNICATE, tsm, target_state, RMI_PDEV_E= RROR); } =20 +static int __maybe_unused parse_certificate_chain(struct pci_tsm *tsm) +{ + struct cca_host_pf0_ep_dsc *pf0_ep_dsc; + unsigned int chain_size; + unsigned int offset =3D 0; + u8 *chain_data; + + pf0_ep_dsc =3D to_cca_pf0_ep_dsc(tsm->pdev); + + /* If device communication didn't results in certificate caching. */ + if (!pf0_ep_dsc->cert_chain.cache || !pf0_ep_dsc->cert_chain.cache->offse= t) + return -EINVAL; + + chain_size =3D pf0_ep_dsc->cert_chain.cache->offset; + chain_data =3D pf0_ep_dsc->cert_chain.cache->buf; + + while (offset < chain_size) { + ssize_t cert_len =3D + x509_get_certificate_length(chain_data + offset, + chain_size - offset); + if (cert_len < 0) + return cert_len; + + struct x509_certificate *cert __free(x509_free_certificate) =3D + x509_cert_parse(chain_data + offset, cert_len); + + if (IS_ERR(cert)) { + pci_warn(tsm->pdev, "parsing of certificate chain not successful\n"); + return PTR_ERR(cert); + } + + /* The key in the last cert in the chain is used */ + if (offset + cert_len =3D=3D chain_size) { + char *signature_algorithm __free(kfree) =3D NULL; + void *public_key __free(kfree) =3D + kzalloc(cert->pub->keylen, GFP_KERNEL); + + if (!public_key) + return -ENOMEM; + + if (!strcmp("rsa", cert->pub->pkey_algo)) { + struct rsa_key rsa_key =3D {0}; + size_t skip =3D 0; + int ret; + + ret =3D rsa_parse_pub_key(&rsa_key, cert->pub->key, + cert->pub->keylen); + if (ret) + return ret; + + while (skip < rsa_key.n_sz && !rsa_key.n[skip]) + skip++; + + /* check we have 3072 bits len */ + if ((rsa_key.n_sz - skip) !=3D (3072 >> 3)) + return -EINVAL; + } else if (strcmp("ecdsa-nist-p256", cert->pub->pkey_algo) && + strcmp("ecdsa-nist-p384", cert->pub->pkey_algo)) { + return -EINVAL; + } + + signature_algorithm =3D kstrdup(cert->pub->pkey_algo, GFP_KERNEL); + if (!signature_algorithm) + return -ENOMEM; + + memcpy(public_key, cert->pub->key, cert->pub->keylen); + pf0_ep_dsc->rmi_signature_algorithm =3D + no_free_ptr(signature_algorithm); + pf0_ep_dsc->cert_chain.public_key =3D no_free_ptr(public_key); + pf0_ep_dsc->cert_chain.public_key_size =3D cert->pub->keylen; + pf0_ep_dsc->cert_chain.valid =3D true; + return 0; + } + + offset +=3D cert_len; + } + + /* something wrong with chain size and parsing. */ + return -EINVAL; +} + +static inline void key_param_free(struct rmi_public_key_params *param) +{ + return free_page((unsigned long)param); +} + +static inline int copy_key_part(u8 *buf, const u8 *key_buf, size_t sz) +{ + int skip; + + /* skip leading zero in asn.1 */ + for (skip =3D 0; skip < sz; skip++) + if (key_buf[skip]) + break; + + memcpy(buf, key_buf + skip, sz - skip); + return sz - skip; +} + +DEFINE_FREE(key_param_free, struct rmi_public_key_params *, if (_T) key_pa= ram_free(_T)) +static int __maybe_unused pdev_set_public_key(struct pci_tsm *tsm) +{ + struct cca_host_pf0_ep_dsc *pf0_ep_dsc; + + pf0_ep_dsc =3D to_cca_pf0_ep_dsc(tsm->pdev); + /* Check that all the necessary information was captured from communicati= on */ + if (!pf0_ep_dsc->cert_chain.valid) + return -EINVAL; + + u8 *key __free(free_page) =3D (u8 *)get_zeroed_page(GFP_KERNEL); + u8 *metadata __free(free_page) =3D (u8 *)get_zeroed_page(GFP_KERNEL); + struct rmi_public_key_params *key_params __free(key_param_free) =3D + (struct rmi_public_key_params *)get_zeroed_page(GFP_KERNEL); + if (!key_params || !key || !metadata) + return -ENOMEM; + + if (!strcmp("ecdsa-nist-p384", pf0_ep_dsc->rmi_signature_algorithm) || + !strcmp("ecdsa-nist-p256", pf0_ep_dsc->rmi_signature_algorithm)) { + key_params->key_len =3D pf0_ep_dsc->cert_chain.public_key_size; + memcpy(key, pf0_ep_dsc->cert_chain.public_key, + pf0_ep_dsc->cert_chain.public_key_size); + key_params->metadata_len =3D 0; + } else if (!strcmp("rsa", pf0_ep_dsc->rmi_signature_algorithm)) { + int ret; + struct rsa_key rsa_key =3D {0}; + + ret =3D rsa_parse_pub_key(&rsa_key, + pf0_ep_dsc->cert_chain.public_key, + pf0_ep_dsc->cert_chain.public_key_size); + if (ret) + return ret; + + key_params->key_len =3D copy_key_part(key, rsa_key.n, rsa_key.n_sz); + key_params->metadata_len =3D copy_key_part(metadata, + rsa_key.e, rsa_key.e_sz); + } else { + return -EINVAL; + } + + key_params->key_addr =3D virt_to_phys(key); + key_params->metadata_addr =3D virt_to_phys(metadata); + + if (rmi_pdev_set_pubkey(virt_to_phys(pf0_ep_dsc->pdev.rmm_pdev), + virt_to_phys(key_params))) + return -ENXIO; + return 0; +} + static void pdev_state_transition_workfn(struct work_struct *work) { unsigned long state; @@ -454,6 +605,7 @@ void cca_pdev_stop_and_destroy(struct pci_dev *pdev) return; =20 if (pf0_ep_dsc) { + kfree(pf0_ep_dsc->rmi_signature_algorithm); kfree(pf0_ep_dsc->cert_chain.public_key); kvfree(pf0_ep_dsc->cert_chain.cache); kvfree(pf0_ep_dsc->vca); diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.h b/drivers/virt/coco/ar= m-cca-host/rmi-da.h index f3bd106c8a54..92bcd9571cb8 100644 --- a/drivers/virt/coco/arm-cca-host/rmi-da.h +++ b/drivers/virt/coco/arm-cca-host/rmi-da.h @@ -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; =20 + char *rmi_signature_algorithm; struct { struct cache_object *cache; =20 diff --git a/include/linux/arm-rmi-cmds.h b/include/linux/arm-rmi-cmds.h index f947b2f4909a..1f1dc771a8ff 100644 --- a/include/linux/arm-rmi-cmds.h +++ b/include/linux/arm-rmi-cmds.h @@ -715,4 +715,13 @@ static inline unsigned long rmi_pdev_stop(unsigned lon= g pdev_phys) return res.a0; } =20 +static inline unsigned long rmi_pdev_set_pubkey(unsigned long pdev_phys, u= nsigned 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 diff --git a/include/linux/arm-smccc-rmi.h b/include/linux/arm-smccc-rmi.h index 3133b34354ce..fdc830379060 100644 --- a/include/linux/arm-smccc-rmi.h +++ b/include/linux/arm-smccc-rmi.h @@ -596,4 +596,22 @@ struct rmi_dev_comm_data { }; }; =20 +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_ */ --=20 2.43.0 From nobody Fri Sep 25 16:01:36 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F3D044A090E; Thu, 10 Sep 2026 14:06:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049183; cv=none; b=fArSkN0PQKD5KeCh5oHGMfvOGxpc1Df2a/Rq4FSSt/iFJapV78qQvWhIA+MyybIa+V7x0OwhbH1IxQ9YXu6f/4lKqziT9ZUlWezlFiXdXILjmT3GoZvbpJ0X5YhNkQ7y0kVJiYJHMdX0YLR6iKTmvw/8y80WDGVPmqM3wdBStRU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049183; c=relaxed/simple; bh=bO5ZxRUTplC78RMoKS01ZkNJgF3nE7/LqS/iuXurVS4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NMtc1TD72ELJguAcbuNISun8+YQ4FsIbNAFKtIpQ5XCdJUYux0YJ1EvUkMOUAISiXR34/F66JtjGaW/sc16I0MXCIdBuF08FWJ/crdEYLwgHOR4X794at1wZMR1WmrNuFVqZhXtMJ5i/8gBIXi5FOBdbeUaHJWRsAQikPnrVNU0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=PjzpqKPH; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="PjzpqKPH" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5749C1F00893; Thu, 10 Sep 2026 14:06:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1789049181; bh=IiIVREUxf6Ua6VFPmuswL/Ps0omblFjMc6DSuW760z0=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=PjzpqKPHFvzO05/QxbvZ2IFnK2A1E4t7tiqS/xY/7O53ICZyAOUyJTbgcy3Cx0FAt bshLtmA9+9vAcS+IROJguNAgIkMnxvW977zPKWBttXpllQdR2HEPq2xxmWoDHwtPSk 7s917CHvror+NMFSGnb66kP1wAc7vGr0H6g+vygjqTLnoU4PcwrjZdkPz/sz22qmIm cIMBZyigMnrdP0QDbiz/kecD2ODAOZO0/4sJoJAm3FTtUIMkL6m/E93b/ySITHvXcX /7TgICEnvfc4fVJaN0CoGmro4TnX5HAnu2g2nLKVGhMEq8gGCwjjBucKOcjK6PBC3F reKcTrjAt5GIw== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Alexey Kardashevskiy , Catalin Marinas , Dan Williams , Jason Gunthorpe , Jonathan Cameron , Marc Zyngier , Samuel Ortiz , Steven Price , Suzuki K Poulose , Will Deacon , Xu Yilun Subject: [PATCH v5 09/15] coco: host: arm64: Initialize RMM pdev state for TDISP IDE connect Date: Thu, 10 Sep 2026 19:35:02 +0530 Message-ID: <20260910140509.868402-10-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260910140509.868402-1-aneesh.kumar@kernel.org> References: <20260910140509.868402-1-aneesh.kumar@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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. Signed-off-by: Aneesh Kumar K.V (Arm) --- 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(-) diff --git a/drivers/virt/coco/arm-cca-host/main.c b/drivers/virt/coco/arm-= cca-host/main.c index ce16ce108db7..318967bab8ca 100644 --- a/drivers/virt/coco/arm-cca-host/main.c +++ b/drivers/virt/coco/arm-cca-host/main.c @@ -64,7 +64,7 @@ static void cca_tsm_pci_remove(struct pci_tsm *tsm) } } =20 -static __maybe_unused int init_dev_communication_buffers(struct pci_dev *p= dev, +static int init_dev_communication_buffers(struct pci_dev *pdev, struct cca_host_comm_data *comm_data) { int ret =3D -ENOMEM; @@ -158,15 +158,43 @@ static int __maybe_unused cca_tsm_connect(struct pci_= dev *pdev) ide->partner[PCI_IDE_EP].default_stream =3D 1; pci_ide_stream_setup(pdev, ide); pci_ide_stream_setup(rp, ide); + } =20 - /* - * Once ide is setup, enable the stream at the endpoint - * Root port will be done by RMM - */ - pci_ide_stream_enable(pdev, ide); + ret =3D init_dev_communication_buffers(pdev, &pf0_ep_dsc->pdev.comm_data); + if (ret) + goto err_comm_buff; + ret =3D cca_pdev_create(pdev); + if (ret) + goto err_pdev_create; + + ret =3D cca_pdev_collect_identity(pdev); + if (ret) + goto pdev_destroy; + + if (cca_pdev_needs_key(pdev)) { + ret =3D 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; =20 +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; =20 - if (cca_pdev_need_sel_ide_streams(pdev)) { + if (cca_pdev_need_sel_ide_streams(pdev)) ide =3D pf0_ep_dsc->sel_stream; =20 + 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 =3D NULL; } - } =20 static struct pci_tsm_ops cca_link_pci_ops =3D { diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.c b/drivers/virt/coco/ar= m-cca-host/rmi-da.c index 394b6a87f2d3..a046edb6be86 100644 --- a/drivers/virt/coco/arm-cca-host/rmi-da.c +++ b/drivers/virt/coco/arm-cca-host/rmi-da.c @@ -381,7 +381,7 @@ static int wait_for_pdev_state(struct pci_tsm *tsm, enu= m rmi_pdev_state target_s return wait_for_dev_state(PDEV_COMMUNICATE, tsm, target_state, RMI_PDEV_E= RROR); } =20 -static int __maybe_unused parse_certificate_chain(struct pci_tsm *tsm) +static int parse_certificate_chain(struct pci_tsm *tsm) { struct cca_host_pf0_ep_dsc *pf0_ep_dsc; unsigned int chain_size; @@ -481,7 +481,7 @@ static inline int copy_key_part(u8 *buf, const u8 *key_= buf, size_t sz) } =20 DEFINE_FREE(key_param_free, struct rmi_public_key_params *, if (_T) key_pa= ram_free(_T)) -static int __maybe_unused pdev_set_public_key(struct pci_tsm *tsm) +static int pdev_set_public_key(struct pci_tsm *tsm) { struct cca_host_pf0_ep_dsc *pf0_ep_dsc; =20 @@ -572,6 +572,92 @@ static int submit_pdev_state_transition_work(struct pc= i_dev *pdev, return 0; } =20 +static void pdev_collect_identity_workfn(struct work_struct *work) +{ + struct pci_tsm *tsm; + struct dev_comm_work *setup_work; + struct cca_host_pdev_dsc *pdev_dsc; + + setup_work =3D container_of(work, struct dev_comm_work, work); + tsm =3D setup_work->tsm; + pdev_dsc =3D to_cca_pdev_dsc(tsm->dsm_dev); + + guard(mutex)(&pdev_dsc->object_lock); + + do_dev_communicate(PDEV_COMMUNICATE, tsm, RMI_PDEV_ERROR); + + /* + * Don't worry about communication error. The caller will look at + * device state to find more about error + */ +} + +int cca_pdev_collect_identity(struct pci_dev *pdev) +{ + enum rmi_pdev_state state; + struct dev_comm_work comm_work; + struct cca_host_pdev_dsc *pdev_dsc =3D to_cca_pdev_dsc(pdev); + struct cca_host_comm_data *comm_data =3D to_cca_comm_data(pdev); + + /* + * Device identity is collected by doing a device communication + * after a pdev_create + */ + INIT_WORK_ONSTACK(&comm_work.work, pdev_collect_identity_workfn); + comm_work.tsm =3D pdev->tsm; + + queue_work(comm_data->work_queue, &comm_work.work); + + flush_work(&comm_work.work); + destroy_work_on_stack(&comm_work.work); + + /* check for device communication error*/ + if (rmi_pdev_get_state(virt_to_phys(pdev_dsc->rmm_pdev), &state)) + return -EIO; + + if (state =3D=3D RMI_PDEV_ERROR) + return -EPROTO; + + return 0; +} + +bool cca_pdev_needs_key(struct pci_dev *pdev) +{ + enum rmi_pdev_state state; + struct cca_host_pdev_dsc *pdev_dsc =3D to_cca_pdev_dsc(pdev); + + /* + * Consider pdev_get_state failure as need key transition + * and that will result in device communication failure, which + * will handle this error. + */ + if (rmi_pdev_get_state(virt_to_phys(pdev_dsc->rmm_pdev), &state)) + return true; + + if (state =3D=3D RMI_PDEV_NEEDS_KEY) + return true; + return false; +} + +int cca_pdev_set_public_key(struct pci_dev *pdev) +{ + int ret; + + /* + * we now have certificate chain in dsm->cert_chain. Parse that and set + * the pubkey. + */ + ret =3D parse_certificate_chain(pdev->tsm); + if (ret) + return ret; + + ret =3D pdev_set_public_key(pdev->tsm); + if (ret) + return ret; + + return submit_pdev_state_transition_work(pdev, RMI_PDEV_READY); +} + static inline int rmi_pdev_destroy(unsigned long pdev_phys, unsigned long *rmi_ret) { diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.h b/drivers/virt/coco/ar= m-cca-host/rmi-da.h index 92bcd9571cb8..dc5dc4246591 100644 --- a/drivers/virt/coco/arm-cca-host/rmi-da.h +++ b/drivers/virt/coco/arm-cca-host/rmi-da.h @@ -135,6 +135,9 @@ static inline struct cca_host_comm_data *to_cca_comm_da= ta(struct pci_dev *pdev) } =20 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); =20 #endif --=20 2.43.0 From nobody Fri Sep 25 16:01:36 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AF6044A091E; Thu, 10 Sep 2026 14:06:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049190; cv=none; b=S0NmhfqLmUEPlkoRVRcB7zp6+6osPFEfREvzrAzJtzMOsyZPjMcfScI9o9U6kXlXn6H+gKpTP6foWbhElPG82qR7pyByyaRK/o/Qb6W/gkW8oYcJq7isbxGyuJdqNtFdrUbO9wo6Grwhia9lGrZ7NGanIqjU6QgT5Zl3lZX42t8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049190; c=relaxed/simple; bh=taXXnEltMXc9aNtgN/w1xijUJ7aoLs7yN+b1YTkYWG8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CV2oi0fVjj4iChCyxT9XLNFh5Q9zC786mv11rVlN1JRfEkQkP73pfofqijntT6Qx4iM5RwLaRIZ0Rahoe+5VEQsb4oI0wVm5FQhYx+Z8x+F1tAgMQGrdFhJYiky/84iGczwRjEu6PupaVnkcPGB5oTrsKu4OVf4stCae4dFKgCk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=A1dpld/G; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="A1dpld/G" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9152B1F0089A; Thu, 10 Sep 2026 14:06:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1789049188; bh=6ePdmdhx3YlI4NyqTdkO5yb3MhPJf9n4y0d3TQqzJF0=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=A1dpld/GBSZOH1TNTJr5kYxNV+DfGgq1JfY0b/u8mLoNLtS4flgJVU6Bvtk1QtMyI GTSEHrqDBT45BuF3S54rAEWELGzutsIt1kpflUDwBOvnaf4rX9p3NwEggafQ4+ezvS e3V7OLrG3VI5Hw1yrLCLhIOl82bnkKp4RYn20NrC9oZ8wzMWWGHyKWqBVAmyMu+rvF UQfxnw2jDlwIV8U8JW+ut2xnyWRCtJXLDeCdt3GLfdCvDmYkYqwVESouicyLZ1VaOI VTqmvoWMcyhecCDktcegZAe2s6cmiWthxXuzjKrth76WvntMnCQLRg8PFsrO5oaVMI b3jOGouQAbnlg== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Alexey Kardashevskiy , Catalin Marinas , Dan Williams , Jason Gunthorpe , Jonathan Cameron , Marc Zyngier , Samuel Ortiz , Steven Price , Suzuki K Poulose , Will Deacon , Xu Yilun Subject: [PATCH v5 10/15] coco: host: arm64: Coordinate peer stream waits during pdev communication Date: Thu, 10 Sep 2026 19:35:03 +0530 Message-ID: <20260910140509.868402-11-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260910140509.868402-1-aneesh.kumar@kernel.org> References: <20260910140509.868402-1-aneesh.kumar@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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. Signed-off-by: Aneesh Kumar K.V (Arm) --- 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(-) diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.c b/drivers/virt/coco/ar= m-cca-host/rmi-da.c index a046edb6be86..784572116064 100644 --- a/drivers/virt/coco/arm-cca-host/rmi-da.c +++ b/drivers/virt/coco/arm-cca-host/rmi-da.c @@ -192,7 +192,7 @@ static inline gfp_t cache_obj_id_to_gfp_flags(u8 cache_= obj_id) return GFP_KERNEL_ACCOUNT; } =20 -static int _do_dev_communicate(enum dev_comm_type type, struct pci_tsm *ts= m) +static int _do_dev_communicate(enum dev_comm_type type, struct pci_tsm *ts= m, 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 typ= e, struct pci_tsm *tsm) if (pending_dev_communicate(io_exit)) goto redo_communicate; =20 + if (io_exit->flags & RMI_DEV_COMM_EXIT_STREAM_WAIT) { + if (stream_wait) + *stream_wait =3D 1; + else + WARN(1, "Unexpected Stream wait status\n"); + } return 0; } =20 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 =3D 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 =3D &pdev_dsc->comm_data.io_params->enter; io_enter->resp_len =3D 0; io_enter->status =3D RMI_DEV_COMM_NONE; + if (stream_wait) + *stream_wait =3D 0; =20 - ret =3D _do_dev_communicate(type, tsm); + ret =3D _do_dev_communicate(type, tsm, stream_wait); if (ret) { if (type =3D=3D 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; =20 do { - state =3D do_dev_communicate(type, tsm, error_state); + state =3D do_dev_communicate(type, tsm, error_state, NULL); =20 if (state =3D=3D target_state || state =3D=3D error_state) return state; @@ -584,7 +592,7 @@ static void pdev_collect_identity_workfn(struct work_st= ruct *work) =20 guard(mutex)(&pdev_dsc->object_lock); =20 - do_dev_communicate(PDEV_COMMUNICATE, tsm, RMI_PDEV_ERROR); + do_dev_communicate(PDEV_COMMUNICATE, tsm, RMI_PDEV_ERROR, NULL); =20 /* * 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 =3D NULL; } + +static void stream_connect_workfn(struct work_struct *work) +{ + int state; + int peer_wait =3D 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 =3D container_of(work, struct stream_connect_work, work); + tsm =3D stream_work->tsm; + pdev_dsc =3D to_cca_pdev_dsc(tsm->dsm_dev); + + my_index =3D stream_work->my_index; + peer_index =3D my_index ^ 0x1; + +redo_communicate: + mutex_lock(&pdev_dsc->object_lock); + + state =3D do_dev_communicate(PDEV_COMMUNICATE, tsm, RMI_PDEV_ERROR, &peer= _wait); + if (state !=3D 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 =3D 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]) >=3D 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 =3D 0; + struct cca_host_comm_data *comm_data_pdev1, *comm_data_pdev2; + struct cca_host_pdev_dsc *pdev_dsc1, *pdev_dsc2 =3D NULL; + struct stream_sync sync; + struct stream_connect_work stream_work_pdev1, stream_work_pdev2; + + comm_data_pdev1 =3D to_cca_comm_data(pdev1); + init_waitqueue_head(&sync.wq); + atomic_set(&sync.val[0], 0); + atomic_set(&sync.val[1], 0); + + pdev_dsc1 =3D to_cca_pdev_dsc(pdev1); + INIT_WORK_ONSTACK(&stream_work_pdev1.work, stream_connect_workfn); + stream_work_pdev1.tsm =3D pdev1->tsm; + stream_work_pdev1.sync =3D &sync; + stream_work_pdev1.my_index =3D 0; + stream_work_pdev1.has_peer =3D !!pdev2; + queue_work(comm_data_pdev1->work_queue, &stream_work_pdev1.work); + + if (pdev2) { + comm_data_pdev2 =3D to_cca_comm_data(pdev2); + pdev_dsc2 =3D to_cca_pdev_dsc(pdev2); + INIT_WORK_ONSTACK(&stream_work_pdev2.work, stream_connect_workfn); + stream_work_pdev2.tsm =3D pdev2->tsm; + stream_work_pdev2.sync =3D &sync; + stream_work_pdev2.my_index =3D 1; + stream_work_pdev2.has_peer =3D 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 =3D virt_to_phys(pdev_dsc1->rmm_pdev); + if (pdev2) + rmm_pdev2_phys =3D virt_to_phys(pdev_dsc2->rmm_pdev); + + return 0; +} diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.h b/drivers/virt/coco/ar= m-cca-host/rmi-da.h index dc5dc4246591..7b8fe0de7b90 100644 --- a/drivers/virt/coco/arm-cca-host/rmi-da.h +++ b/drivers/virt/coco/arm-cca-host/rmi-da.h @@ -27,6 +27,19 @@ struct dev_comm_work { struct work_struct work; }; =20 +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; diff --git a/include/linux/arm-smccc-rmi.h b/include/linux/arm-smccc-rmi.h index fdc830379060..1640f2f43344 100644 --- a/include/linux/arm-smccc-rmi.h +++ b/include/linux/arm-smccc-rmi.h @@ -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) =20 #define RMI_DEV_COMM_NONE 0 #define RMI_DEV_COMM_RESPONSE 1 --=20 2.43.0 From nobody Fri Sep 25 16:01:36 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8D94A49EC41; Thu, 10 Sep 2026 14:06:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049197; cv=none; b=rMb9+LIPve7TrWEIEchra4MHrcsqVIAoSwWa1xSaAP2LuqR7BYM37i1oBo11Fjw2rlknBQictrCNaSOKyRVrdmmHV9VFtZHzSGO9NDvOJPxCIaePEZD8R4OUP5AdW6JR1o6c611NnpzAhS1UCgIrfxTd+cehA/ayt4aNQhS7xPU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049197; c=relaxed/simple; bh=H+pz1Sh6MKgJy+I7oWVTcVb5ItNSWIicN86E0iNf1zs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lkGHsrtcacnalB+/E530YAYJtk3dU7k/h9PeRLn5wn3zpkuG70C1/pXrcoO+p3w0eD71+j3sryXzOw765ajL14+y+VgTbwayJmfanrcROuu9Z0Ys/ERB0VKXvqf6tGhx4nNP5T6392VSt59y+kqQ08cta00I+exApULRL/c5dO4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Xuepawku; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Xuepawku" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3D0DD1F00893; Thu, 10 Sep 2026 14:06:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1789049194; bh=j7ECvB77nd0rYPlOXbmTHEjVbrbUTnBGowHFwbt3IqQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=XuepawkuBlXa63fLJhPaCsLlqvfSKAyTABnsqXC1rj7lCwJpXOnQtas/RRRC38/qB v7QQuSvWeFnOK2mV5/1uW8jmWCkJEAKIINXw9OO01/vV3wSMLjJoldpWSQirTvQrpB juqSr3IyJf2A35/nbwHe1fjF0C5WZ+hdTJyTl/P0/k2RSkffOXaK+Zez2B9iHn6rZx osxLM+vdQ7Iutu9qqFbJWrVGL/AcluWzsIjEqROxmdtpvRzGHv/t/AR6d6Zsly50P0 2bXRTom4GA9A47ti53AvchtkVoH1C4yDv1Vqopxcyor/EYoaJGP4+BMMGeRNBKbSZI gkMs4/hihXbrQ== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Alexey Kardashevskiy , Catalin Marinas , Dan Williams , Jason Gunthorpe , Jonathan Cameron , Marc Zyngier , Samuel Ortiz , Steven Price , Suzuki K Poulose , Will Deacon , Xu Yilun Subject: [PATCH v5 11/15] coco: host: arm64: Connect RMM pdev streams for IDE devices Date: Thu, 10 Sep 2026 19:35:04 +0530 Message-ID: <20260910140509.868402-12-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260910140509.868402-1-aneesh.kumar@kernel.org> References: <20260910140509.868402-1-aneesh.kumar@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 Signed-off-by: Aneesh Kumar K.V (Arm) --- 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(-) diff --git a/drivers/virt/coco/arm-cca-host/main.c b/drivers/virt/coco/arm-= cca-host/main.c index 318967bab8ca..d357bad14325 100644 --- a/drivers/virt/coco/arm-cca-host/main.c +++ b/drivers/virt/coco/arm-cca-host/main.c @@ -113,6 +113,123 @@ static inline void free_dev_communication_buffers(str= uct cca_host_comm_data *com free_page((unsigned long)comm_data->io_params); } =20 +static int cca_root_port_pdev_create(struct pci_dev *rp, struct tsm_dev *t= sm_dev) +{ + int ret; + struct cca_host_rp_dsc *rp_dsc; + + rp_dsc =3D kzalloc_obj(*rp_dsc); + if (!rp_dsc) + return -ENOMEM; + + /* we expect this to be asigned early */ + rp->tsm =3D &rp_dsc->pci; + rp->tsm->dsm_dev =3D rp; + rp->tsm->pdev =3D rp; + rp->tsm->tsm_dev =3D tsm_dev; + mutex_init(&rp_dsc->pdev.object_lock); + + ret =3D init_dev_communication_buffers(rp, &rp_dsc->pdev.comm_data); + if (ret) + goto err_comm_buff; + + ret =3D cca_pdev_create(rp); + if (ret) + goto err_pdev_create; + + /* + * device communication is still required even though + * there is not identity collection + */ + ret =3D 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 =3D NULL; + return ret; +} + +static int pci_dev_addr_range(struct pci_dev *pdev, struct rmi_addr_range = *pdev_addr) +{ + int naddr =3D 0; + struct pci_dev *br; + struct resource *mem, *pref; + + br =3D pci_upstream_bridge(pdev); + if (!br) + return 0; + + mem =3D pci_resource_n(br, PCI_BRIDGE_MEM_WINDOW); + pref =3D pci_resource_n(br, PCI_BRIDGE_PREF_MEM_WINDOW); + if (resource_assigned(mem)) + naddr =3D insert_addr_range_sorted(pdev_addr, naddr, + mem->start, mem->end + 1); + if (resource_assigned(pref)) + naddr =3D 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 =3D pcie_find_root_port(pdev); + struct cca_host_pf0_ep_dsc *pf0_ep_dsc =3D to_cca_pf0_ep_dsc(pdev); + + if (!rp->tsm) { + ret =3D cca_root_port_pdev_create(rp, pf0_ep_dsc->pci.base_tsm.tsm_dev); + if (ret) + return ret; + rp_dsc =3D to_cca_rp_dsc(rp); + } else { + rp_dsc =3D to_cca_rp_dsc(rp); + /* Make sure they use the same TSM */ + if (rp->tsm->tsm_dev !=3D pf0_ep_dsc->pci.base_tsm.tsm_dev) + return -EINVAL; + } + + + params =3D (struct rmi_pdev_stream_params *)get_zeroed_page(GFP_KERNEL); + if (!params) + return -ENOMEM; + + params->flags =3D 0; + params->stream_type =3D RMI_PDEV_STREAM_NCOH; + params->pdev_1 =3D virt_to_phys(pf0_ep_dsc->pdev.rmm_pdev); + params->pdev_2 =3D virt_to_phys(rp_dsc->pdev.rmm_pdev); + params->ide_sid =3D stream_id; + params->num_addr_range =3D pci_dev_addr_range(pdev, params->addr_range); + + ret =3D cca_pdev_stream_connect(pdev, rp, params, &stream_handle); + if (!ret) + pf0_ep_dsc->stream_handle =3D stream_handle; + + free_page((unsigned long)params); + return ret; +} + +static int cca_pdev_create_streams(struct pci_dev *pdev, unsigned long str= eam_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) =3D=3D PCI_EXP_TYPE_ENDPOINT; @@ -176,6 +293,10 @@ static int __maybe_unused cca_tsm_connect(struct pci_d= ev *pdev) if (ret) goto pdev_destroy; } + /* Create IDE streams */ + ret =3D 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 pc= i_dev *pdev) { struct pci_ide *ide; struct cca_host_pf0_ep_dsc *pf0_ep_dsc; + struct pci_dev *rp =3D pcie_find_root_port(pdev); =20 pf0_ep_dsc =3D to_cca_pf0_ep_dsc(pdev); if (!pf0_ep_dsc) @@ -216,6 +338,8 @@ static void __maybe_unused cca_tsm_disconnect(struct pc= i_dev *pdev) if (cca_pdev_need_sel_ide_streams(pdev)) ide =3D pf0_ep_dsc->sel_stream; =20 + 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); =20 diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.c b/drivers/virt/coco/ar= m-cca-host/rmi-da.c index 784572116064..fcca9f73b5fb 100644 --- a/drivers/virt/coco/arm-cca-host/rmi-da.c +++ b/drivers/virt/coco/arm-cca-host/rmi-da.c @@ -62,6 +62,10 @@ static int init_pdev_params(struct pci_dev *pdev, struct= rmi_pdev_params *params category =3D RMI_PDEV_FLAGS_CATEGORY_OFF_CHIP_EP; break; } + case PCI_EXP_TYPE_ROOT_PORT: { + category =3D RMI_PDEV_FLAGS_CATEGORY_ROOT_PORT; + break; + } default: return -EINVAL; } @@ -762,7 +766,7 @@ static void stream_connect_workfn(struct work_struct *w= ork) mutex_unlock(&pdev_dsc->object_lock); } =20 -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 =3D 0; @@ -806,6 +810,40 @@ static int __maybe_unused submit_stream_work(struct pc= i_dev *pdev1, struct pci_d rmm_pdev1_phys =3D virt_to_phys(pdev_dsc1->rmm_pdev); if (pdev2) rmm_pdev2_phys =3D 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_handl= e)) + return -EIO; =20 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 =3D 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 =3D 0; + struct cca_host_pdev_dsc *pdev_dsc1 =3D to_cca_pdev_dsc(pdev1); + + if (pdev2) + rmm_pdev2_phys =3D 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); +} diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.h b/drivers/virt/coco/ar= m-cca-host/rmi-da.h index 7b8fe0de7b90..ed5d3a58096d 100644 --- a/drivers/virt/coco/arm-cca-host/rmi-da.h +++ b/drivers/virt/coco/arm-cca-host/rmi-da.h @@ -72,6 +72,7 @@ struct cca_host_pdev_dsc { * @pci: Physical Function 0 TDISP link context * @pdev: pdev communication context * @sel_stream: Selective IDE Stream descriptor + * @stream_handle: Stream handle returned by stream connect * @rmi_signature_algorithm: Signature algorithm used for public key * @cert_chain: cetrificate chain * @vca: SPDM's Version-Capabilities-Algorithms cache object @@ -80,6 +81,7 @@ struct cca_host_pf0_ep_dsc { struct pci_tsm_pf0 pci; struct cca_host_pdev_dsc pdev; struct pci_ide *sel_stream; + unsigned long stream_handle; =20 char *rmi_signature_algorithm; struct { @@ -93,6 +95,17 @@ struct cca_host_pf0_ep_dsc { struct cache_object *vca; }; =20 +/** + * struct cca_host_rp_dsc - Root-port pdev context for stream coordination. + * @pci: Root-port TSM link context + * @pdev: Common pdev communication context + * @tsm_ref: Reference count held by connected endpoint streams + */ +struct cca_host_rp_dsc { + struct pci_tsm pci; + struct cca_host_pdev_dsc pdev; +}; + struct cca_host_fn_dsc { struct pci_tsm pci; }; @@ -101,6 +114,30 @@ enum dev_comm_type { PDEV_COMMUNICATE =3D 0x1, }; =20 +static inline int insert_addr_range_sorted(struct rmi_addr_range *addr_ran= ge, + int nr_addr_range, resource_size_t start, resource_size_t top) +{ + int index =3D nr_addr_range; + + while (index > 0) { + struct rmi_addr_range *prev =3D &addr_range[index - 1]; + + if (prev->base < start) + break; + + if (prev->base =3D=3D start && prev->top <=3D top) + break; + + addr_range[index] =3D *prev; + index--; + } + + addr_range[index].base =3D start; + addr_range[index].top =3D top; + + return nr_addr_range + 1; +} + static inline struct cca_host_pf0_ep_dsc *to_cca_pf0_ep_dsc(struct pci_dev= *pdev) { struct pci_tsm *tsm =3D pdev->tsm; @@ -118,14 +155,29 @@ static inline struct cca_host_fn_dsc *to_cca_fn_dsc(s= truct pci_dev *pdev) return container_of(tsm, struct cca_host_fn_dsc, pci); } =20 +static inline struct cca_host_rp_dsc *to_cca_rp_dsc(struct pci_dev *pdev) +{ + struct pci_tsm *tsm =3D pdev->tsm; + + if (!tsm || pci_pcie_type(pdev) !=3D PCI_EXP_TYPE_ROOT_PORT) + return NULL; + + return container_of(tsm, struct cca_host_rp_dsc, pci); +} + static inline struct cca_host_pdev_dsc *to_cca_pdev_dsc(struct pci_dev *pd= ev) { struct cca_host_pf0_ep_dsc *pf0_ep_dsc; + struct cca_host_rp_dsc *rp_dsc; =20 pf0_ep_dsc =3D to_cca_pf0_ep_dsc(pdev); if (pf0_ep_dsc) return &pf0_ep_dsc->pdev; =20 + rp_dsc =3D to_cca_rp_dsc(pdev); + if (rp_dsc) + return &rp_dsc->pdev; + return NULL; } =20 @@ -152,5 +204,10 @@ 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); +int cca_pdev_stream_connect(struct pci_dev *pdev1, struct pci_dev *pdev2, + struct rmi_pdev_stream_params *stream_params, + unsigned long *stream_handle); +int cca_pdev_disconnect_stream(struct pci_dev *pdev1, + struct pci_dev *pdev2, unsigned long stream_handle); =20 #endif diff --git a/include/linux/arm-rmi-cmds.h b/include/linux/arm-rmi-cmds.h index 1f1dc771a8ff..8db92447dc61 100644 --- a/include/linux/arm-rmi-cmds.h +++ b/include/linux/arm-rmi-cmds.h @@ -724,4 +724,40 @@ static inline unsigned long rmi_pdev_set_pubkey(unsign= ed long pdev_phys, unsigne return res.a0; } =20 +static inline unsigned long rmi_pdev_stream_connect(unsigned long stream_p= arams_phys, + unsigned long *stream_handle) +{ + + struct arm_smccc_res res; + + arm_smccc_1_1_invoke(SMC_RMI_PDEV_STREAM_CONNECT, stream_params_phys, &re= s); + + *stream_handle =3D res.a1; + return res.a0; +} + +static inline unsigned long rmi_pdev_stream_complete(unsigned long pdev1_p= hys, + 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 diff --git a/include/linux/arm-smccc-rmi.h b/include/linux/arm-smccc-rmi.h index 1640f2f43344..f9dd919b696a 100644 --- a/include/linux/arm-smccc-rmi.h +++ b/include/linux/arm-smccc-rmi.h @@ -615,4 +615,41 @@ struct rmi_public_key_params { }; }; =20 +#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_ */ --=20 2.43.0 From nobody Fri Sep 25 16:01:36 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2E88449BD93; Thu, 10 Sep 2026 14:06:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049204; cv=none; b=dzxEgq80eDQ/m/9BOJNivAQctRZs5tt8IJMKq6LltgKUvura+x4X4fhsRtswC0UAUawUgQCASb/OzKoPobjpaS5e1pMIdVlQ96Sz58rVbkcfzIJCFOyGBIQNEFWZ0ukTaCHkogeZ94QCf07ExxFNqQknD4RAb25cLlDfNoJT0AY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049204; c=relaxed/simple; bh=WTY08XsToLDsIhZRuFf85W24Ek1Sy7sZ+oJpkuL/lbI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YnBznplQ9i0OIvxh2joJRWsMjCWIwF74HwzNLQGJp/q8Lt6mhsAkJ4LOfx94A4bXVrmwfA2KWnOj1pBXeNlBxbqThI4FEgIFUA7L/+AlzhJgr9GkoVoIx6tPrOEv2fdeOc3M4Yhav9qVR9eYhT5jFvlhFpDH+ULBDrK5OkdJ22Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=mqh0EZzx; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="mqh0EZzx" Received: by smtp.kernel.org (Postfix) with ESMTPSA id AB9841F000FF; Thu, 10 Sep 2026 14:06:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1789049201; bh=iX8SSvkP0TRGmeqvD2oG6hiYGm+9zRzWtG9NpyIedjc=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=mqh0EZzxseos9g49gSpPyaDSDP5fp4uJNWI8WD3DmpUAhySxNIDdub8DwxX7JS1MY OFcPexKHHMz+mcZu2x29KuhaokyCG42H3Nq7ApOk0qP4BLWTHpGrnsjysSgjtqLTjp OwbfD6Vn9XrH8UOrFUGbqdy1RvCWhJjjp7/GxgRvL2gWHMPSJ7rRyTjUMLf7xieWxv MQfJw++DEPr/ywU9RirDxo/9CXhOMoVB3JYSSIbdCLWyKdSn9POChncwl6iFZ6Qu9e 4UDqBBOuFfKw6Yky6O8B58cQsOIquQw8T4RbS7c1mlQzSNrmp0Kt6T7+lnbg8doAQZ pWGDwku8uJ3uw== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Alexey Kardashevskiy , Catalin Marinas , Dan Williams , Jason Gunthorpe , Jonathan Cameron , Marc Zyngier , Samuel Ortiz , Steven Price , Suzuki K Poulose , Will Deacon , Xu Yilun Subject: [PATCH v5 12/15] coco: host: arm64: Refcount root-port pdevs used by IDE streams Date: Thu, 10 Sep 2026 19:35:05 +0530 Message-ID: <20260910140509.868402-13-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260910140509.868402-1-aneesh.kumar@kernel.org> References: <20260910140509.868402-1-aneesh.kumar@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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. Signed-off-by: Aneesh Kumar K.V (Arm) --- 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(-) diff --git a/drivers/virt/coco/arm-cca-host/main.c b/drivers/virt/coco/arm-= cca-host/main.c index d357bad14325..b74fe1fb14fd 100644 --- a/drivers/virt/coco/arm-cca-host/main.c +++ b/drivers/virt/coco/arm-cca-host/main.c @@ -113,6 +113,23 @@ static inline void free_dev_communication_buffers(stru= ct cca_host_comm_data *com free_page((unsigned long)comm_data->io_params); } =20 +static void cca_root_port_pdev_release(struct kref *kref) +{ + struct cca_host_rp_dsc *rp_dsc =3D container_of(kref, struct cca_host_rp_= dsc, + tsm_ref); + struct pci_dev *rp =3D rp_dsc->pci.pdev; + + cca_pdev_stop_and_destroy(rp); + free_dev_communication_buffers(&rp_dsc->pdev.comm_data); + rp->tsm =3D 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 *t= sm_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 =3D rp; rp->tsm->pdev =3D rp; rp->tsm->tsm_dev =3D tsm_dev; + kref_init(&rp_dsc->tsm_ref); mutex_init(&rp_dsc->pdev.object_lock); =20 ret =3D 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 !=3D pf0_ep_dsc->pci.base_tsm.tsm_dev) return -EINVAL; - } =20 + kref_get(&rp_dsc->tsm_ref); + } =20 params =3D (struct rmi_pdev_stream_params *)get_zeroed_page(GFP_KERNEL); - if (!params) + if (!params) { + cca_root_port_pdev_put(rp_dsc); return -ENOMEM; + } =20 params->flags =3D 0; params->stream_type =3D 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 =3D pci_dev_addr_range(pdev, params->addr_range); =20 ret =3D 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 =3D stream_handle; =20 free_page((unsigned long)params); @@ -339,6 +362,8 @@ static void __maybe_unused cca_tsm_disconnect(struct pc= i_dev *pdev) ide =3D pf0_ep_dsc->sel_stream; =20 cca_pdev_disconnect_stream(pdev, rp, pf0_ep_dsc->stream_handle); + if (rp) + cca_root_port_pdev_put(to_cca_rp_dsc(rp)); =20 cca_pdev_stop_and_destroy(pdev); free_dev_communication_buffers(&pf0_ep_dsc->pdev.comm_data); diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.h b/drivers/virt/coco/ar= m-cca-host/rmi-da.h index ed5d3a58096d..b76cb4af8436 100644 --- a/drivers/virt/coco/arm-cca-host/rmi-da.h +++ b/drivers/virt/coco/arm-cca-host/rmi-da.h @@ -12,6 +12,9 @@ #include #include #include +#include +#include +#include =20 #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; }; =20 struct cca_host_fn_dsc { --=20 2.43.0 From nobody Fri Sep 25 16:01:36 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 901CB340DB8; Thu, 10 Sep 2026 14:06:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049210; cv=none; b=EMy2Bdmc8RWYMeKXx2J0YoRORDvh+OWFAFfWwPA9+hlSUbyw2EGRUyGrx2RJdOFk+3WvBup2ABrCdqqt3r/mqQ+9HAoB5jiGSc09xSaby0bM6OF0Bj0AtdzBkKDk1FbOwwellruPBWWDCMSJGroRkvjdou3kYhfoHPvQZZGWcSY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049210; c=relaxed/simple; bh=9y6ofKb3CBBnvWD+XTFAP396QOIyR9mesB2l9nFChzY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=INpxFu6i7LRYPQZqOyLPm3Nsb4zS6hYxkDleJG2gbs9SA6LjP9a7Yh+xQ9A5n9WveCZ4viCJFRo4ycDl1+/Y6lKRzNpfqlexsl7H0c+q6IRWvLpj5/IDEjFIRoc8XmO8uqy/geky6fnCPmCxpRrY8jyA3KHcrKZ97ljlTuaG4VU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=aW3wpbY0; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="aW3wpbY0" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8DD071F00893; Thu, 10 Sep 2026 14:06:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1789049208; bh=8e//6G86LJaRiE5M1GpEgb21G8bE9NJI6seWzHEhfuI=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=aW3wpbY0PM7OcZjDE1nbBr0vGfPf7IFR0Qp27bMXeU8oMPZr63E6tj1BXROkMDg0a opgzzg1Gh0sGIMesLRT0+m8aaT8PzFsnfAKUDn/bPodv3kdeRM9zT0nA3RSXW6LThj KRsz2AEiHMTwErtBO2ozWkwV0Toi6DaYcj6m9ufsXHsY08lT4BSI/397OvV9Sc7Rrs mbWv9bri20OlsIKwkm57YDUOcFVyplavzltFuYgINahgBzD4tb6uliiMG7FpzdvomL DXS9VWWhMU8zDo8sXPrrozdOhX+L22aGby9qF/InfPWJxjvz9ssqwzlYAU2kOKFqk2 IrwzkH5OVTmWw== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Alexey Kardashevskiy , Catalin Marinas , Dan Williams , Jason Gunthorpe , Jonathan Cameron , Marc Zyngier , Samuel Ortiz , Steven Price , Suzuki K Poulose , Will Deacon , Xu Yilun Subject: [PATCH v5 13/15] PCI/TSM: Move CMA DOE mailbox discovery out of pci_tsm_pf0_constructor() Date: Thu, 10 Sep 2026 19:35:06 +0530 Message-ID: <20260910140509.868402-14-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260910140509.868402-1-aneesh.kumar@kernel.org> References: <20260910140509.868402-1-aneesh.kumar@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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. Signed-off-by: Aneesh Kumar K.V (Arm) --- 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(-) diff --git a/drivers/crypto/ccp/sev-dev-tsm.c b/drivers/crypto/ccp/sev-dev-= tsm.c index 46f2539d2d5a..e55eaca16998 100644 --- a/drivers/crypto/ccp/sev-dev-tsm.c +++ b/drivers/crypto/ccp/sev-dev-tsm.c @@ -217,6 +217,19 @@ static struct pci_tsm *tio_pf0_probe(struct pci_dev *p= dev, struct sev_device *se if (rc) return NULL; =20 + /* if device have ide cap, setup doe mailbox */ + if (pdev->ide_cap) { + struct pci_doe_mb *doe_mb; + + doe_mb =3D pci_find_doe_mailbox(pdev, PCI_VENDOR_ID_PCI_SIG, + PCI_DOE_FEATURE_CMA); + if (!doe_mb) + return NULL; + dsm->tsm.doe_mb =3D doe_mb; + } else { + return NULL; + } + pci_dbg(pdev, "TSM enabled\n"); dsm->sev =3D sev; return &no_free_ptr(dsm)->tsm.base_tsm; diff --git a/drivers/pci/tsm.c b/drivers/pci/tsm.c index 5fdcd7f2e820..34805b7ba7a0 100644 --- a/drivers/pci/tsm.c +++ b/drivers/pci/tsm.c @@ -744,12 +744,13 @@ int pci_tsm_pf0_constructor(struct pci_dev *pdev, str= uct pci_tsm_pf0 *tsm, struct tsm_dev *tsm_dev) { mutex_init(&tsm->lock); - tsm->doe_mb =3D 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"); =20 return pci_tsm_link_constructor(pdev, &tsm->base_tsm, tsm_dev); } diff --git a/drivers/virt/coco/arm-cca-host/main.c b/drivers/virt/coco/arm-= cca-host/main.c index b74fe1fb14fd..70cbff181561 100644 --- a/drivers/virt/coco/arm-cca-host/main.c +++ b/drivers/virt/coco/arm-cca-host/main.c @@ -12,6 +12,7 @@ #include #include #include +#include =20 #include "rmi-da.h" =20 @@ -33,14 +34,22 @@ static struct pci_tsm *cca_tsm_pci_probe(struct tsm_dev= *tsm_dev, struct pci_dev return &no_free_ptr(fn_dsc)->pci; } =20 - if (!pdev->ide_cap) - return NULL; - struct cca_host_pf0_ep_dsc *pf0_ep_dsc __free(kfree) =3D kzalloc(sizeof(*pf0_ep_dsc), GFP_KERNEL); if (!pf0_ep_dsc) return NULL; =20 + /* if device have ide cap, setup doe mailbox */ + if (pdev->ide_cap) { + struct pci_doe_mb *doe_mb; + + doe_mb =3D 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 =3D doe_mb; + } + ret =3D pci_tsm_pf0_constructor(pdev, &pf0_ep_dsc->pci, tsm_dev); if (ret) return NULL; --=20 2.43.0 From nobody Fri Sep 25 16:01:36 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F35214A3F3A; Thu, 10 Sep 2026 14:06:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049216; cv=none; b=dFnvsoulJpXqtAnpS8ppCYHI04QWoy/rS/7PgiQOOsBw7vwq9scDMtua53S0BtZFYEcqvC5ebegrTQNaZz1Gv20o8/q8hPdYXoYK6wR4Wgg4VTbzkyaGHh7zreQD5utvKAir8OBDK3kEFDLaFky6MUry3h0swjw4gF31N3BNl3Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049216; c=relaxed/simple; bh=c5lfmiCJYlY+UhANXT9srmqmEWUJIiCKECCxpceAQII=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NgdqUnfNE5TSjppgS/zyBYpDgMCrw2Z9zdMyVg1SMUvmvyryxFncAuwN/0bblHG/Zvxc+tmtEZeWOEUqqxikz6NubOt4g6iDkqYpNUmT2Fkjljqckr/eTo0V2E3TgpGHSloyCddb0JQmRtUoVlVIdj2NAgqnPMlOpcpDMPfRwwY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=g16gXhhx; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="g16gXhhx" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 039471F00898; Thu, 10 Sep 2026 14:06:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1789049214; bh=HfACVSTqqZWVHHMsfW9j7D8zjVuyoIFAMlGVkuERVwY=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=g16gXhhxkVq5S5oxzfWsaWCw3urd025JZW1sxsu9eBUu1CdJDqpISr68hktAo/CHr 2F2O/QCunWoL+37JccgSRDvuhWzbmLGW4J0X2PhPFNGRVwApRS5XmPH5Lf0Ylg4PPa YbhNeDsiLtUHHK83QQtbLdaJ3I9v5IhzjCI5tAM3J049vv7Atw+WEUIhjtbQvwAAf4 dDzmBw1Y1FPRD6I1J8/MaZjYuBAMNfvOZl1N2XddNvNnW4w4BWdXCZSt6NfMABdXqd KBVRcFCrHkdq0LMLI22NTuK2daML6fj7B3HFs5psQJtkawQQmgXk/MYUp4/fhuY4nP mtTkAoj8KrYTA== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Alexey Kardashevskiy , Catalin Marinas , Dan Williams , Jason Gunthorpe , Jonathan Cameron , Marc Zyngier , Samuel Ortiz , Steven Price , Suzuki K Poulose , Will Deacon , Xu Yilun Subject: [PATCH v5 14/15] coco: host: arm64: Add NCOH_SYS stream support for RC endpoints Date: Thu, 10 Sep 2026 19:35:07 +0530 Message-ID: <20260910140509.868402-15-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260910140509.868402-1-aneesh.kumar@kernel.org> References: <20260910140509.868402-1-aneesh.kumar@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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. Signed-off-by: Aneesh Kumar K.V (Arm) --- drivers/virt/coco/arm-cca-host/main.c | 28 +++++++++++++++++++++++++ drivers/virt/coco/arm-cca-host/rmi-da.c | 10 +++++++++ 2 files changed, 38 insertions(+) diff --git a/drivers/virt/coco/arm-cca-host/main.c b/drivers/virt/coco/arm-= cca-host/main.c index 70cbff181561..b7b0cc0a016c 100644 --- a/drivers/virt/coco/arm-cca-host/main.c +++ b/drivers/virt/coco/arm-cca-host/main.c @@ -252,11 +252,39 @@ static int cca_pdev_create_ncoh_stream(struct pci_dev= *pdev, unsigned long strea return ret; } =20 +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 =3D to_cca_pf0_ep_dsc(pdev); + + params =3D (struct rmi_pdev_stream_params *)get_zeroed_page(GFP_KERNEL); + if (!params) + return -ENOMEM; + + params->flags =3D 0; + params->stream_type =3D RMI_PDEV_STREAM_NCOH_SYS; + params->pdev_1 =3D virt_to_phys(pf0_ep_dsc->pdev.rmm_pdev); + params->pdev_2 =3D 0; /* ignored */ + params->ide_sid =3D 0; /* ignored */ + params->num_addr_range =3D pci_dev_addr_range(pdev, params->addr_range); + + ret =3D cca_pdev_stream_connect(pdev, NULL, params, &stream_handle); + if (!ret) + pf0_ep_dsc->stream_handle =3D stream_handle; + + free_page((unsigned long)params); + return ret; +} + static int cca_pdev_create_streams(struct pci_dev *pdev, unsigned long str= eam_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; } diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.c b/drivers/virt/coco/ar= m-cca-host/rmi-da.c index fcca9f73b5fb..794385f818ce 100644 --- a/drivers/virt/coco/arm-cca-host/rmi-da.c +++ b/drivers/virt/coco/arm-cca-host/rmi-da.c @@ -66,6 +66,16 @@ static int init_pdev_params(struct pci_dev *pdev, struct= rmi_pdev_params *params category =3D RMI_PDEV_FLAGS_CATEGORY_ROOT_PORT; break; } + case PCI_EXP_TYPE_RC_END: { + struct cca_host_pf0_ep_dsc *pf0_ep_dsc =3D to_cca_pf0_ep_dsc(pdev); + + /* Use SPDM if present */ + if (pf0_ep_dsc->pci.doe_mb) + params->flags =3D RMI_PDEV_FLAGS_SPDM; + + category =3D RMI_PDEV_FLAGS_CATEGORY_ON_CHIP_EP; + break; + } default: return -EINVAL; } --=20 2.43.0 From nobody Fri Sep 25 16:01:36 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 74AD24A8A17; Thu, 10 Sep 2026 14:07:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049223; cv=none; b=lpqrjm/hdyRIgtAO+ZhaYWKYQwbkUNQZhA6nfC6fljMztemhrLJuQzeQV8ziHGE0ZPLPJZ6iq6AORK7HxCkLntJDTpIH6i6u9elwcWdZR1qjnc1nSPhsFTSmeiRZqrsG4KKB1Yn5pObuqpxYWcxwdXpdyYtQzSxxCgAeugDoFac= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789049223; c=relaxed/simple; bh=kko8o+2yLViA7AjY6vne36W8QZaUMTzZtOffEn/gjKw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HZHuiOvTOtTbyCP9bsVweuiE1ja+TTljT9kMTvZaTNBfjPXdFVOkriJmSQGcw3mUlWG9elUyQRfhPUR6bMQV1fWdxBTCwocXC4Y61roMYU48qbI0eyBeFBqXd7s7q8xYGc0otpooc5572LViOiNkn6/v8Ghd1+Q63JtI90RCchw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=SyQiX9GX; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="SyQiX9GX" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A3A321F0089B; Thu, 10 Sep 2026 14:06:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1789049222; bh=7scpEVVr4UU62YzdzYFb4j0SlzJSeqGX0ORVVeED+nw=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=SyQiX9GXEjjt2r/KKPAuTr18MSFEFjkQhuO1GnsboRPFfeyD6Vfrcj5zGP342Hpcn Vb9DMA+iGTmteG3jFNDRH2l/EJlnb7w9Hy/yttWSz9uzW2rwPVtknfqtBuvjfzjJKP TNOQA8tqDfddmWhmP4g/rp93U+cZpQ5I6LckzJmB++30zG2B4KZ6GqF0CUvwzPkSR3 r4vyeDVLTiiq+iRX9RlWZoX2dn2GsyXC8q0dYKBf0I5fGH31YVxakjb3JI+J0BYMqm VdRhoA7nstQFRxjZ+/ttRSpn38JZw6zYnRzRL0yy7yvADDdiXxnXdSCcZ0ffScjXnz u95B0wYR8BwYw== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Alexey Kardashevskiy , Catalin Marinas , Dan Williams , Jason Gunthorpe , Jonathan Cameron , Marc Zyngier , Samuel Ortiz , Steven Price , Suzuki K Poulose , Will Deacon , Xu Yilun Subject: [PATCH v5 15/15] coco: host: arm64: Enable PCI TSM connect callbacks Date: Thu, 10 Sep 2026 19:35:08 +0530 Message-ID: <20260910140509.868402-16-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260910140509.868402-1-aneesh.kumar@kernel.org> References: <20260910140509.868402-1-aneesh.kumar@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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. Signed-off-by: Aneesh Kumar K.V (Arm) --- drivers/virt/coco/arm-cca-host/main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/virt/coco/arm-cca-host/main.c b/drivers/virt/coco/arm-= cca-host/main.c index b7b0cc0a016c..e8afd54c23f6 100644 --- a/drivers/virt/coco/arm-cca-host/main.c +++ b/drivers/virt/coco/arm-cca-host/main.c @@ -295,7 +295,7 @@ static inline bool cca_pdev_need_sel_ide_streams(struct= pci_dev *pdev) return pci_pcie_type(pdev) =3D=3D PCI_EXP_TYPE_ENDPOINT; } =20 -static int __maybe_unused cca_tsm_connect(struct pci_dev *pdev) +static int cca_tsm_connect(struct pci_dev *pdev) { struct pci_dev *rp =3D 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_de= v *pdev) return ret; } =20 -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 pc= i_dev *pdev) static struct pci_tsm_ops cca_link_pci_ops =3D { .probe =3D cca_tsm_pci_probe, .remove =3D cca_tsm_pci_remove, + .connect =3D cca_tsm_connect, + .disconnect =3D cca_tsm_disconnect, }; =20 static void cca_link_tsm_remove(void *tsm_dev) --=20 2.43.0