From nobody Thu Jun 11 03:18:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 6A85F3264FA; Mon, 27 Apr 2026 06:51:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777272701; cv=none; b=jSqClZuWw1Y6C/u3VoeDFMRqqycFsqyUNr3aNId2Q4OvMZTQe3LQ+kyEv30r04ffq4JWS30og2kCgtMn1WBK5MRjCDVq3d+F6C3rezWlJ/1ooE0W73ylxEggdmbgBO+Ma225rj7CJpCWgnpvchte+GDuMQEsW88tyTkm90A/FIg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777272701; c=relaxed/simple; bh=DItmN7CZJj9mPjedXacvO6++q0aZQyxMF5Mr5JCA8i8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FEgELuALJ3XTB2AuihzyePMdnBq73a+76/19D5CZ7r2ouhyx29rII7kXUqw8egVWItTBzLwNump1M22KhP5EJOdfImQE/prKxdOImahxe6FpS5x+lNHXcSxXKsP9S3e6mKpaJE6/IdHJOryqTRRQaoL6vGwW9n77Cm/UWCLPJsI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=dh1wPQPp; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="dh1wPQPp" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 607F5C19425; Mon, 27 Apr 2026 06:51:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777272701; bh=DItmN7CZJj9mPjedXacvO6++q0aZQyxMF5Mr5JCA8i8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=dh1wPQPpsfz4oPsUXrvorOw5GifxbivRYT8lRBBE0Pz0WDLXkgZg6TBuVk+w1hiAU R1jvr8W5O6FyXQv0tGTd4U9tflsQAedWKpFCG3iwjZ4keFt8HWqx9bISg8B2YIt3ZE GNERJYyTQkROaxWGTOhOa9F9+h81Zdn7WNf0xjRFY/J8HXpWyoiRCeTsPqq+a7Zn29 GTrm/MP3UCMBqvneEAaUb4ANO+kCj+6MJPbwqyKsvFaUZsJBQXfeql42vdwYNV77k6 Vv7gOtfBr4oOWdwXcMfPUqfFiQ0T7l/K1Be3L0ld7diV9HbxOvZaj1krPUTf9dqnK9 bZPE4/z0xKROg== 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: [RFC PATCH v4 01/14] coco: host: arm64: Add host TSM callback and IDE stream allocation support Date: Mon, 27 Apr 2026 12:21:08 +0530 Message-ID: <20260427065121.916615-2-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260427065121.916615-1-aneesh.kumar@kernel.org> References: <20260427065121.916615-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" Register the TSM callback when the DA feature is supported by KVM. This driver handles IDE stream setup for both the root port and PCIe endpoints. Root port IDE stream enablement itself is managed by RMM. In addition, the driver registers pci_tsm_ops with the TSM subsystem. Signed-off-by: Aneesh Kumar K.V (Arm) --- arch/arm64/include/asm/rmi_smc.h | 2 + drivers/firmware/smccc/rmm.c | 12 ++ drivers/firmware/smccc/rmm.h | 8 + drivers/firmware/smccc/smccc.c | 1 + 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/arm-cca.c | 225 +++++++++++++++++++++++ drivers/virt/coco/arm-cca-host/rmi-da.h | 46 +++++ 10 files changed, 321 insertions(+) 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/arm-cca.c create mode 100644 drivers/virt/coco/arm-cca-host/rmi-da.h diff --git a/arch/arm64/include/asm/rmi_smc.h b/arch/arm64/include/asm/rmi_= smc.h index fa23818e1b4c..109d6cc6ef37 100644 --- a/arch/arm64/include/asm/rmi_smc.h +++ b/arch/arm64/include/asm/rmi_smc.h @@ -12,6 +12,8 @@ =20 #include =20 +#define RMI_DEV_NAME "arm-rmi-dev" + #define SMC_RMI_CALL(func) \ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ ARM_SMCCC_SMC_64, \ diff --git a/drivers/firmware/smccc/rmm.c b/drivers/firmware/smccc/rmm.c index 2a6187df3285..7444cc3a588c 100644 --- a/drivers/firmware/smccc/rmm.c +++ b/drivers/firmware/smccc/rmm.c @@ -21,3 +21,15 @@ void __init register_rsi_device(struct platform_device *= pdev) __devm_auxiliary_device_create(&pdev->dev, "arm_cca_guest", RSI_DEV_NAME, NULL, 0); } + +void __init register_rmi_device(struct platform_device *pdev) +{ + struct arm_smccc_res res; + unsigned long host_version =3D RMI_ABI_VERSION(RMI_ABI_MAJOR_VERSION, + RMI_ABI_MINOR_VERSION); + + arm_smccc_1_1_invoke(SMC_RMI_VERSION, host_version, &res); + if (res.a0 =3D=3D RMI_SUCCESS) + __devm_auxiliary_device_create(&pdev->dev, + "arm_cca_host", RMI_DEV_NAME, NULL, 0); +} diff --git a/drivers/firmware/smccc/rmm.h b/drivers/firmware/smccc/rmm.h index a47a650d4f51..37d0d95a099e 100644 --- a/drivers/firmware/smccc/rmm.h +++ b/drivers/firmware/smccc/rmm.h @@ -6,12 +6,20 @@ =20 #ifdef CONFIG_ARM64 #include +#include + void __init register_rsi_device(struct platform_device *pdev); +void __init register_rmi_device(struct platform_device *pdev); #else =20 static void __init register_rsi_device(struct platform_device *pdev) { =20 +} + +static void __init register_rmi_device(struct platform_device *pdev) +{ + } #endif #endif diff --git a/drivers/firmware/smccc/smccc.c b/drivers/firmware/smccc/smccc.c index fc9b44b7c687..2bf2d59e686d 100644 --- a/drivers/firmware/smccc/smccc.c +++ b/drivers/firmware/smccc/smccc.c @@ -97,6 +97,7 @@ static int __init smccc_devices_init(void) * the required SMCCC function IDs at a supported revision. */ register_rsi_device(pdev); + register_rmi_device(pdev); } =20 if (smccc_trng_available) { 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..efe40d61d5d8 --- /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 KVM + select PCI_TSM + select AUXILIARY_BUS + + 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..c236827f002c --- /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 arm-cca.o diff --git a/drivers/virt/coco/arm-cca-host/arm-cca.c b/drivers/virt/coco/a= rm-cca-host/arm-cca.c new file mode 100644 index 000000000000..67f7e80106e8 --- /dev/null +++ b/drivers/virt/coco/arm-cca-host/arm-cca.c @@ -0,0 +1,225 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2026 ARM Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rmi-da.h" + +/* Total number of stream id supported at root port level */ +#define MAX_STREAM_ID 256 + +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)); + } +} + +/* For now global for simplicity. Protected by pci_tsm_rwsem */ +static DECLARE_BITMAP(cca_stream_ids, MAX_STREAM_ID); +static int alloc_stream_id(struct pci_host_bridge *hb) +{ + int stream_id; + +redo_alloc: + stream_id =3D find_first_zero_bit(cca_stream_ids, MAX_STREAM_ID); + if (stream_id =3D=3D MAX_STREAM_ID) + return stream_id; + + if (ida_exists(&hb->ide_stream_ids_ida, stream_id)) { + /* mark the stream allocated in the global bitmap. */ + set_bit(stream_id, cca_stream_ids); + goto redo_alloc; + } + return stream_id; +} + +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 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)) { + /* Allocate stream id */ + stream_id =3D alloc_stream_id(pci_find_host_bridge(pdev->bus)); + if (stream_id =3D=3D MAX_STREAM_ID) + return -EBUSY; + set_bit(stream_id, cca_stream_ids); + + ide =3D pci_ide_stream_alloc(pdev); + if (!ide) { + ret =3D -ENOMEM; + goto err_stream_alloc; + } + + pf0_ep_dsc->sel_stream =3D ide; + 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); + + ret =3D tsm_ide_stream_register(ide); + if (ret) + goto err_tsm; + + /* + * 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_tsm: + 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); + pf0_ep_dsc->sel_stream =3D NULL; +err_stream_alloc: + clear_bit(stream_id, cca_stream_ids); + + return ret; +} + +static void cca_tsm_disconnect(struct pci_dev *pdev) +{ + int stream_id; + 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; + stream_id =3D ide->stream_id; + + pci_ide_stream_release(ide); + pf0_ep_dsc->sel_stream =3D NULL; + clear_bit(stream_id, cca_stream_ids); + } + +} + +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, +}; + +static void cca_link_tsm_remove(void *tsm_dev) +{ + tsm_unregister(tsm_dev); +} + +static int cca_link_tsm_probe(struct auxiliary_device *adev, + const struct auxiliary_device_id *id) +{ + struct tsm_dev *tsm_dev; + + if (!rmm_has_reg2_feature(RMI_FEATURE_REGISTER_2_DA)) + return -ENODEV; + + tsm_dev =3D tsm_register(&adev->dev, &cca_link_pci_ops); + if (IS_ERR(tsm_dev)) + return PTR_ERR(tsm_dev); + + return devm_add_action_or_reset(&adev->dev, cca_link_tsm_remove, + tsm_dev); +} + +static const struct auxiliary_device_id cca_link_tsm_id_table[] =3D { + { .name =3D KBUILD_MODNAME "." RMI_DEV_NAME }, + {} +}; +MODULE_DEVICE_TABLE(auxiliary, cca_link_tsm_id_table); + +static struct auxiliary_driver cca_link_tsm_driver =3D { + .probe =3D cca_link_tsm_probe, + .id_table =3D cca_link_tsm_id_table, +}; +module_auxiliary_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..4abc7ad159e5 --- /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 Thu Jun 11 03:18:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 EFE8D3890F9; Mon, 27 Apr 2026 06:51:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777272707; cv=none; b=fpuW0/rS3MNJvJWFC9vAVBgkee1zJsMZPk1GOhxK3HEnJ5CJImt/+XH2UXHeMSubz3QJQ0iiW2LhbFQSWdN83kDdhdorfcGAZxXUIthJmJJPCvjyCMnDoj6bQoclgh2LDrSFqkSzSAwqmy8xL3wb6McUG4Ggjce045oTGTczsMY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777272707; c=relaxed/simple; bh=dXVSkfXFOX78UgFW20dAcjZ+t2/MgDkcG0mnxyEG+AU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tGfyQAI1BkdjaDPAezlKiaYt2aNpYjp4b8Q1tvMbhKJt/lYiJitG3D4b7TJMXM3HDXch2rbpZ45QWp7eXft0HJzrF5K3by0xX1iEynVm9uR9vCqsPG/A53W9snmpjeI2wj0E4BVQ9Po0MdTsPMGfls8CeYeMAboRMywuBFD0viU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=mFMorngm; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="mFMorngm" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E5B94C19425; Mon, 27 Apr 2026 06:51:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777272706; bh=dXVSkfXFOX78UgFW20dAcjZ+t2/MgDkcG0mnxyEG+AU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mFMorngmP4n5ZNy59e3IGxRAEDoS87uDWsQmaaz5+/VD+zWcsl4HMCvZ7Th6x8GJB GRmg23kXm7dLPZbtGEe41W+f0Qcd5o+OoJeaEYqDKzRB+a8YAVwTqD6HSd/4iknAQR GqDBUIgwKqpaL19dOiR5KuztnLN7wslU2QjDqr93RdWFpcSaFrh47SssUI42eusN45 mp4rLdqz8lno314NIGzq0CZ1j2xeN4CDnsJl8EgBTUsnwiT4vDlssxotLGKFnnz5Qo qlWZLb8ijM5TtYw8WvFamxtsAaqR72iaJEjDij2hKXvRYq3PwfJISqq1CSxr4OnnZP 57PTXkN8WYQ+w== 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: [RFC PATCH v4 02/14] coco: host: arm64: Create RMM pdev objects for PCI endpoints Date: Mon, 27 Apr 2026 12:21:09 +0530 Message-ID: <20260427065121.916615-3-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260427065121.916615-1-aneesh.kumar@kernel.org> References: <20260427065121.916615-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) --- arch/arm64/include/asm/rmi_cmds.h | 10 ++ arch/arm64/include/asm/rmi_smc.h | 49 ++++++++ drivers/virt/coco/arm-cca-host/Makefile | 2 +- drivers/virt/coco/arm-cca-host/rmi-da.c | 151 ++++++++++++++++++++++++ drivers/virt/coco/arm-cca-host/rmi-da.h | 26 ++++ 5 files changed, 237 insertions(+), 1 deletion(-) create mode 100644 drivers/virt/coco/arm-cca-host/rmi-da.c diff --git a/arch/arm64/include/asm/rmi_cmds.h b/arch/arm64/include/asm/rmi= _cmds.h index 2901fc84d245..d23a0590c7ee 100644 --- a/arch/arm64/include/asm/rmi_cmds.h +++ b/arch/arm64/include/asm/rmi_cmds.h @@ -726,4 +726,14 @@ static inline int rmi_rtt_unmap_unprotected(unsigned l= ong rd, return res.a0; } =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 /* __ASM_RMI_CMDS_H */ diff --git a/arch/arm64/include/asm/rmi_smc.h b/arch/arm64/include/asm/rmi_= smc.h index 109d6cc6ef37..94bcaf3e7e68 100644 --- a/arch/arm64/include/asm/rmi_smc.h +++ b/arch/arm64/include/asm/rmi_smc.h @@ -429,4 +429,53 @@ struct rec_run { struct rec_exit exit; }; =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 +#define RMI_PDEV_FLAGS_CATEGORY_CMEM 0x3 + +#define RMI_HASH_SHA_256 0x0 +#define RMI_HASH_SHA_512 0x1 +#define RMI_HASH_SHA_384 0x2 + +struct rmi_pdev_params { + union { + struct { + u64 flags; + u64 pdev_id; + //u64 rc_id; + u64 routing_id; + u64 id_index; + union { + u16 rid_base; + u8 padding1[8]; + }; + union { + u16 rid_top; + u8 padding2[8]; + }; + union { + u8 hash_algo; + u8 padding3[8]; + }; + u64 max_vdevs_order; + }; + u8 padding5[0x1000]; + }; +}; + #endif /* __ASM_RMI_SMC_H */ diff --git a/drivers/virt/coco/arm-cca-host/Makefile b/drivers/virt/coco/ar= m-cca-host/Makefile index c236827f002c..d48e8940af46 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 arm-cca.o +arm-cca-host-y +=3D arm-cca.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..8fb5d286fd82 --- /dev/null +++ b/drivers/virt/coco/arm-cca-host/rmi-da.c @@ -0,0 +1,151 @@ +// 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_DEVFN(slot, fn); + 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 cfg->res.start | rid; + // ecam window base FIXME!! + //params->pdev_id =3D rid; + //params->rc_id =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; + // FIXME!! what is this? + params->max_vdevs_order =3D 10; + 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(sro) =3D + rmi_sro_init(SMC_RMI_PDEV_CREATE, pdev_phys, pdev_params_phys); + if (!sro) + return -ENOMEM; + + *rmi_ret =3D rmi_sro_execute(sro); + + 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 4abc7ad159e5..de67f10ce20e 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 --=20 2.43.0 From nobody Thu Jun 11 03:18:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 951E33806AA; Mon, 27 Apr 2026 06:51:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777272712; cv=none; b=Q35rHbuIrlJuabryo0jRsEyHs/ADa/owh5LsM03967or+QERAFiRYljyajhT/TsKmIaWg3baizRBGBJ/IXDzVBn5S5h7rZUu4NgYWeJExiNOyj0hmLcpaOcL5paiqhUXi181WQx+h/3+37hn6eBCD8sSeFZlAXL0u8f54tIF3CU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777272712; c=relaxed/simple; bh=JEURRF8GZKIh10CUwhrIZZfreX6x48a7h1EP+1wGiTo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rnH36T0Aw/1+jtZxB8UBpTzeACyEhA32s6Xg8wjBEpyavCk//qB40aB7+mBBkJu/hdEyDw5B6NtgXb2F+xvUO0s5JE19Zodzj30nk9UWUEX2sn4ZZTgZHwACjsX5yLwut2WgYHULj9NlKSBoPha7AMTe0PQuJY6CvNVVn8qfi8s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=kJYWSelh; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="kJYWSelh" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 421D1C2BCB6; Mon, 27 Apr 2026 06:51:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777272712; bh=JEURRF8GZKIh10CUwhrIZZfreX6x48a7h1EP+1wGiTo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=kJYWSelhMVGWJ4Jy6S/tRHcq9m6xFCQLoDQViaAP/Z6tF+/r9GTuXPHv9hzSOHKZ/ XGS+I1gyIr8uXphoZqQ9W1f4HZ93kzZfMRUkXere0R7bYHQcMn9z2wHiJDSztl2Xge 19O7MyCO7T7lXlt+H19acqo3SaviZXgAuMME/pU/HvpEkdARivYWroz5Rl7HSLYiBs 04+qz9jZtAydWo+sM/7tytNB/ZBIv5hxB51XyrHLo3Qr8UEmdJbYTXgAzUFET9Mqtt 8Ru9nvdoFiWdhsyHzHl63SxR6pBgdxgYoV72DKTmJVnGxhShVstyEDdcVai+NQPsDA BokRiJpW4LISw== 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: [RFC PATCH v4 03/14] coco: host: arm64: Add RMM device communication helpers Date: Mon, 27 Apr 2026 12:21:10 +0530 Message-ID: <20260427065121.916615-4-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260427065121.916615-1-aneesh.kumar@kernel.org> References: <20260427065121.916615-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 SMCCC IDs/wrappers for RMI_PDEV_COMMUNICATE/RMI_PDEV_ABORT - describe the RMM device-communication ABI (struct rmi_dev_comm_*, cache flags, protocol/object IDs, busy error code) - track per-PF0 communication state (buffers, workqueue, cache metadata) and serialize access behind object_lock - plumb a DOE/SPDM worker plus shared helpers that submit the SMCCC call, cache multi-part responses, and handle retries/abort Signed-off-by: Aneesh Kumar K.V (Arm) --- arch/arm64/include/asm/rmi_cmds.h | 20 ++ arch/arm64/include/asm/rmi_smc.h | 60 +++++ drivers/virt/coco/arm-cca-host/arm-cca.c | 50 ++++ drivers/virt/coco/arm-cca-host/rmi-da.c | 276 +++++++++++++++++++++++ drivers/virt/coco/arm-cca-host/rmi-da.h | 65 ++++++ 5 files changed, 471 insertions(+) diff --git a/arch/arm64/include/asm/rmi_cmds.h b/arch/arm64/include/asm/rmi= _cmds.h index d23a0590c7ee..6664c439173f 100644 --- a/arch/arm64/include/asm/rmi_cmds.h +++ b/arch/arm64/include/asm/rmi_cmds.h @@ -736,4 +736,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 /* __ASM_RMI_CMDS_H */ diff --git a/arch/arm64/include/asm/rmi_smc.h b/arch/arm64/include/asm/rmi_= smc.h index 94bcaf3e7e68..9056a7639667 100644 --- a/arch/arm64/include/asm/rmi_smc.h +++ b/arch/arm64/include/asm/rmi_smc.h @@ -478,4 +478,64 @@ 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; +}; + +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_obj_id; + u64 padding0; + }; + + union { + u8 protocol; + u64 padding1; + }; + u64 req_delay; + u64 req_len; + u64 rsp_timeout; +}; + +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 /* __ASM_RMI_SMC_H */ diff --git a/drivers/virt/coco/arm-cca-host/arm-cca.c b/drivers/virt/coco/a= rm-cca-host/arm-cca.c index 67f7e80106e8..3c854aab95cc 100644 --- a/drivers/virt/coco/arm-cca-host/arm-cca.c +++ b/drivers/virt/coco/arm-cca-host/arm-cca.c @@ -46,6 +46,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; @@ -65,6 +66,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); +} + /* For now global for simplicity. Protected by pci_tsm_rwsem */ static DECLARE_BITMAP(cca_stream_ids, MAX_STREAM_ID); static int alloc_stream_id(struct pci_host_bridge *hb) diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.c b/drivers/virt/coco/ar= m-cca-host/rmi-da.c index 8fb5d286fd82..dc159d9f2c24 100644 --- a/drivers/virt/coco/arm-cca-host/rmi-da.c +++ b/drivers/virt/coco/arm-cca-host/rmi-da.c @@ -5,6 +5,8 @@ =20 #include #include +#include +#include #include =20 #include "rmi-da.h" @@ -149,3 +151,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_obj_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_obj_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 de67f10ce20e..9f72ff8f28bf 100644 --- a/drivers/virt/coco/arm-cca-host/rmi-da.h +++ b/drivers/virt/coco/arm-cca-host/rmi-da.h @@ -9,15 +9,46 @@ #include #include #include +#include #include #include =20 +#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; +}; + /** * 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 --=20 2.43.0 From nobody Thu Jun 11 03:18:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 F1DD13890F9; Mon, 27 Apr 2026 06:51:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777272718; cv=none; b=n3eEqohOhTpKocJKYYi+F0D9PLY/GAhYzaO4O4oxbGavCISlYqsXeOjflJp+qHRhQDnm0zYlhp1LBaaqeYTLHp5z27alCaL9MgMad4sVNm9v6VzmEyRkAYrUTj6ySOxPHRGY2VavrggSSSlGGsK+ZOrYBUHLv7QS/0ZJRpzgEYM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777272718; c=relaxed/simple; bh=VdMmOEU+WLMyu9cmy2MbebMhWXlrd9XagLeJX1bJz2k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=J8KcjtQ6BQUXjmxymUp2IvI6KoQwCTsTY+oWx8+YV7CjHETlITJ2KC1bk0WhaDT8CWwKAvmUyaxZgGzsMFQRHSHcRIo6SFNbSBy6jMgGu2syEDlCKHSey5IaV9h7u5M5kCPYJO1bGmlgycsREaGPj+WzRwTT8oQJn21kVMK3krQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=mHDcAh0M; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="mHDcAh0M" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D439AC2BCB6; Mon, 27 Apr 2026 06:51:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777272717; bh=VdMmOEU+WLMyu9cmy2MbebMhWXlrd9XagLeJX1bJz2k=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mHDcAh0MjFFeCWsaT8LYI3QxIrELTsBuhydteOCg89CSXExibrFJGp9JHQD0mro0A gvfeLdJ3KCcsVRL7u6phEJL50TC0CnBxBDiVcG8yddDXuHW/UrehMu0dF7dB0RY7ci dwJnorCauY+KnLrstUcajhrgnmkKVfahoJmwIWpgYv3Kh+ti/CFM6pn4dYWB2JioEl yITWmUYSAubJYKkDqs6xen8abOLlyi04nf+pys2kjNiGkI0wiaP6AZ/e840rZYzKZU nBkVmq+KrA6uNSONIXOuoe0LgHCtJkO0cU1RWja2cz8W437/e7KylIz7FvReSf4VCf k3zMy3wvToIWQ== 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: [RFC PATCH v4 04/14] coco: host: arm64: Add helper to stop and tear down an RMM pdev Date: Mon, 27 Apr 2026 12:21:11 +0530 Message-ID: <20260427065121.916615-5-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260427065121.916615-1-aneesh.kumar@kernel.org> References: <20260427065121.916615-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 helper to stop and tear down an RMM pdev - describe the RMI_PDEV_STOP/RMI_PDEV_DESTROY SMC IDs and provide wrappers in rmi_cmds.h - implement pdev_stop_and_destroy() so the host driver stops the pdev, waits for it to reach RMI_PDEV_STOPPED and destroys it Signed-off-by: Aneesh Kumar K.V (Arm) --- arch/arm64/include/asm/rmi_cmds.h | 9 +++++ drivers/virt/coco/arm-cca-host/rmi-da.c | 47 ++++++++++++++++++++++++- drivers/virt/coco/arm-cca-host/rmi-da.h | 1 + 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/rmi_cmds.h b/arch/arm64/include/asm/rmi= _cmds.h index 6664c439173f..8024e9d89e55 100644 --- a/arch/arm64/include/asm/rmi_cmds.h +++ b/arch/arm64/include/asm/rmi_cmds.h @@ -756,4 +756,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 /* __ASM_RMI_CMDS_H */ diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.c b/drivers/virt/coco/ar= m-cca-host/rmi-da.c index dc159d9f2c24..8a43a1f1c036 100644 --- a/drivers/virt/coco/arm-cca-host/rmi-da.c +++ b/drivers/virt/coco/arm-cca-host/rmi-da.c @@ -399,7 +399,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; @@ -425,3 +425,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(sro) =3D + rmi_sro_init(SMC_RMI_PDEV_DESTROY, pdev_phys); + if (!sro) + return -ENOMEM; + + *rmi_ret =3D rmi_sro_execute(sro); + + 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 9f72ff8f28bf..784eb1fff95d 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 --=20 2.43.0 From nobody Thu Jun 11 03:18:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 CD2B62E2850; Mon, 27 Apr 2026 06:52:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777272723; cv=none; b=Xo9Zf/IF7RQCWfMZuZn6oeoyCYUEa8gmgSBr4ufmsmn3skYEQGn56teOgnr6u/R+zJrtUz91TomAHtSZbWh9EcBkdN3Fnh+o7KP2i2CRqiUHFLLl5YjgWOhuTiro/G6XwBhSn0ztDKU16X2fIDol1pPhQVlH89OcnIz3ZsMG16A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777272723; c=relaxed/simple; bh=iT902Kks+8Y5KbHMSujhzXpOT2Flu5+M48nmim2dfB8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=sfvHJ8zOgV28JTmX2RS2ecZzV1yAsMAb54hqeAYOrSsHu1OdKToU7Kj2EV0CWhSy61dV+e42L/rGnTmm9ErcW0tNAjmrLY91ofC2FRmZSZzB64uNAfNN7v1aCTLW2Qh8iuOxUpuCP3XKVV06vpxirEimW0iwSb5UZnl2MfZ90wc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=gh2im7to; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="gh2im7to" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2E12AC2BCB6; Mon, 27 Apr 2026 06:51:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777272723; bh=iT902Kks+8Y5KbHMSujhzXpOT2Flu5+M48nmim2dfB8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gh2im7toqr3/e66zB/sju0y9xVNNDvr0LZl3e/zrwn97kxM0Fs2YOwKOycs/EXcij 8ABG6FXVVvzrwW5qT1TdeIigXXsyIjtpK5o6EiKlfyNjUaY6NDGAgmZOqbs+RObw5I mOwtPpWeiu14B3vlDLSC3MfzXVqGPVWk0nlZMrvWkXM/DP+nZ3RfDg7tTX/9Suagf7 kAIifO8mk14eS1SU1RCw+izfQcfRjzo7J6J6mISeNmB6QZZWf0w351hc18A0G3rQn3 BdBqYdlgqpglzFrDd+SRFmh5CfASZQac4Pypoaqa5HWCLzfYTAIsDRNWLNUhWQmFYC irNI7D7fq/F5g== 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: [RFC PATCH v4 05/14] X.509: Make certificate parser public Date: Mon, 27 Apr 2026 12:21:12 +0530 Message-ID: <20260427065121.916615-6-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260427065121.916615-1-aneesh.kumar@kernel.org> References: <20260427065121.916615-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 Thu Jun 11 03:18:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 6C1513815E7; Mon, 27 Apr 2026 06:52:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777272730; cv=none; b=YijK4CIcE/9utkyx5AiZJmPVAQIPfpS8iXn1oKqA00rLTWhLiYy14ZMFzPoewD2HdIQhVsvG3kYQteU3ekUluM5iytJC6iNGZZ8Z6qMBPSJAnQESuL9kgjc7MCTEGJooja38wn0ho2Sxj0pANlI1pC67Vg5kEg/hrPy/cYc5RQk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777272730; c=relaxed/simple; bh=rj2gZrREi98L5OW7DVFeQ4A3D6mJm8/gxjqIgpOv8+4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=BTJ1a6HezkBhgl1zGgTs824x/UDHCLGAHFav4ZGCCwlkzIt0JCggtRmU9O0Ck0WSMIThEjK7B/9RqJlSZhoA8eS8Y4zGbRTmvouhfdC7/0yZh+Zl8dSCJkjE5mrpGxZCa5OHbYSUC0/xz6cvQlqOyBSxOcYDlczzjKTCmzB2u1U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bFJUaGtk; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="bFJUaGtk" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 462D8C2BCF4; Mon, 27 Apr 2026 06:52:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777272730; bh=rj2gZrREi98L5OW7DVFeQ4A3D6mJm8/gxjqIgpOv8+4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bFJUaGtkSDKRTJn0s95vHYtgPBOZQJp+FgE/V8/RpViupAsg2NyZBF4GqZd1U3upp bfjr2M1p2y7Me0vmTz+wIWxBaQf6EbaOLrESfg7MB3EL3kY7c4dXG2Irb2HGi6wj5u Od512jDVj0LAbOKIebViKfGL+seKnzHgzha6ObdQnsNMdwVkS8vPv4XBCXehV/wI3I KkhePzLOVbLq4Rv9gcShzwhF1rsnUDhBQXSZu8X6C29Dt2bP6PV5RgRFdTANPVXMpQ uvPopa6fTBjNGwJZqyv2eTfWWAkOUg0MQDbgK5+AZ3Zf/Epk2TjZVIWXs2tkjs/s3L 862inefcNPsjw== 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: [RFC PATCH v4 06/14] X.509: Parse Subject Alternative Name in certificates Date: Mon, 27 Apr 2026 12:21:13 +0530 Message-ID: <20260427065121.916615-7-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260427065121.916615-1-aneesh.kumar@kernel.org> References: <20260427065121.916615-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 37e4fb9da106..d81b7de4236c 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 Thu Jun 11 03:18:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 316D53815E7; Mon, 27 Apr 2026 06:52:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777272736; cv=none; b=U+KiC9sa5aaCmw+7nGwRXNscGYc7mWWu0RjDgPqFvwDWHqwNE4k/tCknRkK+M2dthhbCJ/izZxabmJiPbe15AV9OaMXnzuYYAvHw1Itn4N6bUgiTEbQH5DvvdPhEMZBd5pglXAtcNLKN9OnuM5O5wppuYVADfasMhXPlDNFVaw4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777272736; c=relaxed/simple; bh=ffDcIy1rll5TndwARYJlNX/u1R7dPKivglLlkq9yNX4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=u4kpKJflIJlfQ+j3CUP1ePbTG0hjQZnez+GLmTQz250sqnoFsQ+bFnI0m1cx6PSXC29xUDGgFN1H/TBNE06QzaIPXGJJ3kXLkcU52Fjiv1A1s/smBgFEVQ5cIdLH+xz98hpHdDhyu3IckCbAcQsG+JSbRzzn4NATcwNsNH8PqPc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=MCW5NXvx; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="MCW5NXvx" Received: by smtp.kernel.org (Postfix) with ESMTPSA id AA69EC19425; Mon, 27 Apr 2026 06:52:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777272735; bh=ffDcIy1rll5TndwARYJlNX/u1R7dPKivglLlkq9yNX4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MCW5NXvxJk16MxGp7/OTMROKXi8o0yo0goiPrw+TyupAXECNmntB17dxSvROsCCFm JPF/mjcd/HIJ9uDxwi3s6SNJCQs0Xa+mtWJzPhdM1ToCUaZipzW/MUiWke17YwuptA ES8xhQYPYm8AQtc4FJV6a9tvX/ko8nYGZTezbGWc6L5/b56aq+0kdsXLhuroOFvmF2 58JFowJXJQaQcaQ6UvIwBtINU6k6mPTcBRGcM59c/zRz/Wj2HIxromBk7l5bHYI0XL lIBrZActVuJvL6zC8zyDtnHMNOUKLebzDjdLyZNCNio93qUy7NadgaeFVHkmtPSKhT ORdHETSiAC6yA== 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: [RFC PATCH v4 07/14] X.509: Move certificate length retrieval into new helper Date: Mon, 27 Apr 2026 12:21:14 +0530 Message-ID: <20260427065121.916615-8-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260427065121.916615-1-aneesh.kumar@kernel.org> References: <20260427065121.916615-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 a41741326998..25ff027fad1d 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 Thu Jun 11 03:18:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 93B80386C12; Mon, 27 Apr 2026 06:52:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777272741; cv=none; b=uFUU7b9bqwGWiFp2KfW4yYqZaCUWSWXY0q4E+108GrvbEz2sLCEnLLEGE2WSG+PUXszU844pYlHDSEiBJlywlQ2drlPl2D14czL+qgChJaskqe6j8G9N+lsYzBP1ZA4zJHMB9mV2TdborCHHiS3Ltv0RGeUmHxb4Mj/9vzp5uEw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777272741; c=relaxed/simple; bh=8p8XrF54svUmqa/FbWkb2wAIIOl++3NsWo5wZGvA1c8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=onRV8qEv5JgnyZaDqI1s8RKlZAEIjsUgFGJRKxT0E8Y1YSvTI8LOyMcjEUa2AgZrvftQayM/hFQ00iKvWSOZLTibJb5xlkK6kRh9g3sLd1vH19OkyowoeZ/bfxMera2sRYT+eRLFuav1zdtE1inx2qqoU8HQ/Ek5xJrz40utG+0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=sg37gUfh; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="sg37gUfh" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7B232C2BCB8; Mon, 27 Apr 2026 06:52:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777272741; bh=8p8XrF54svUmqa/FbWkb2wAIIOl++3NsWo5wZGvA1c8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=sg37gUfhb/ZDeXMT0+OWQwVpkDHoLz2Uv7klAyb01XOEDt3MjNZa/syXzY/+U5MXK hHCCxciBkznRX11dahJV4GoWClyQqAoQoknIR9IpetNxdHX1VSDHm2PqoDHEzSh5dt V8p/RnYMb5mPcesmqicUCU6wpwDbt6+X2BH6u2SrA4nNcSRZCMZtvg+nUQgn5kqCAo /rO8Swm6Y0NWZGvLM/zSP/Q2uM4JF1zCmrKb4arClzdIIg8NmXHLfXB3cXMmBFvPSi wr/WYlYix1GbF/VNqVa561+CJXn85pY2q5rwrtD9kdF13p6xGRwr9rh17bYSzjrf5b ftEXDXzzlaSpA== 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: [RFC PATCH v4 08/14] coco: host: arm64: Register device public key with RMM Date: Mon, 27 Apr 2026 12:21:15 +0530 Message-ID: <20260427065121.916615-9-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260427065121.916615-1-aneesh.kumar@kernel.org> References: <20260427065121.916615-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) --- arch/arm64/include/asm/rmi_cmds.h | 9 ++ arch/arm64/include/asm/rmi_smc.h | 17 +++ drivers/virt/coco/arm-cca-host/Kconfig | 4 + drivers/virt/coco/arm-cca-host/rmi-da.c | 155 ++++++++++++++++++++++++ drivers/virt/coco/arm-cca-host/rmi-da.h | 2 + 5 files changed, 187 insertions(+) diff --git a/arch/arm64/include/asm/rmi_cmds.h b/arch/arm64/include/asm/rmi= _cmds.h index 8024e9d89e55..00e0a08e17a6 100644 --- a/arch/arm64/include/asm/rmi_cmds.h +++ b/arch/arm64/include/asm/rmi_cmds.h @@ -765,4 +765,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 /* __ASM_RMI_CMDS_H */ diff --git a/arch/arm64/include/asm/rmi_smc.h b/arch/arm64/include/asm/rmi_= smc.h index 9056a7639667..7a5d57a8be7a 100644 --- a/arch/arm64/include/asm/rmi_smc.h +++ b/arch/arm64/include/asm/rmi_smc.h @@ -538,4 +538,21 @@ struct rmi_dev_comm_data { }; }; =20 +#define RMI_SIG_RSASSA_3072 0 +#define RMI_SIG_ECDSA_P256 1 +#define RMI_SIG_ECDSA_P384 2 + +struct rmi_public_key_params { + union { + struct { + u8 public_key[1024]; + u8 metadata[1024]; + u64 public_key_len; + u64 metadata_len; + u8 rmi_signature_algorithm; + }; + u8 padding[0x1000]; + }; +}; + #endif /* __ASM_RMI_SMC_H */ diff --git a/drivers/virt/coco/arm-cca-host/Kconfig b/drivers/virt/coco/arm= -cca-host/Kconfig index efe40d61d5d8..c5076e2b4eb5 100644 --- a/drivers/virt/coco/arm-cca-host/Kconfig +++ b/drivers/virt/coco/arm-cca-host/Kconfig @@ -8,7 +8,11 @@ config ARM_CCA_HOST depends on PCI depends on KVM select PCI_TSM + select KEYS + select X509_CERTIFICATE_PARSER select AUXILIARY_BUS + 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 8a43a1f1c036..996979dba709 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 @@ -383,6 +386,158 @@ 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) { + void *public_key __free(kfree) =3D + kzalloc(cert->pub->keylen, GFP_KERNEL); + + if (!public_key) + return -ENOMEM; + + if (!strcmp("ecdsa-nist-p256", cert->pub->pkey_algo)) { + pf0_ep_dsc->rmi_signature_algorithm =3D RMI_SIG_ECDSA_P256; + } else if (!strcmp("ecdsa-nist-p384", cert->pub->pkey_algo)) { + pf0_ep_dsc->rmi_signature_algorithm =3D RMI_SIG_ECDSA_P384; + } else 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; + + pf0_ep_dsc->rmi_signature_algorithm =3D RMI_SIG_RSASSA_3072; + } else { + return -EINVAL; + } + + memcpy(public_key, cert->pub->key, cert->pub->keylen); + 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; + + 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) + return -ENOMEM; + + key_params->rmi_signature_algorithm =3D pf0_ep_dsc->rmi_signature_algorit= hm; + + switch (key_params->rmi_signature_algorithm) { + case RMI_SIG_ECDSA_P384: + case RMI_SIG_ECDSA_P256: + { + key_params->public_key_len =3D pf0_ep_dsc->cert_chain.public_key_size; + memcpy(key_params->public_key, + pf0_ep_dsc->cert_chain.public_key, + pf0_ep_dsc->cert_chain.public_key_size); + key_params->metadata_len =3D 0; + break; + } + case RMI_SIG_RSASSA_3072: + { + 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->public_key_len =3D copy_key_part(key_params->public_key, + rsa_key.n, rsa_key.n_sz); + key_params->metadata_len =3D copy_key_part(key_params->metadata, + rsa_key.e, rsa_key.e_sz); + break; + } + default: + return -EINVAL; + } + + 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; diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.h b/drivers/virt/coco/ar= m-cca-host/rmi-da.h index 784eb1fff95d..7d38e548b659 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 + uint8_t rmi_signature_algorithm; struct { struct cache_object *cache; =20 --=20 2.43.0 From nobody Thu Jun 11 03:18:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 E22E93890F9; Mon, 27 Apr 2026 06:52:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777272747; cv=none; b=fyVlHCK/FCQ1t713joXfpifXhFuZ4TxibZK67gKfXgLOMMu+MEMPZzm7xtYWc+Jgj5J6gmTrU+sZxS8hEkPNRqpBzUjaBBrf7+cw833ZAEhysjCEdOdi9bzJRFS6gr29JnsqeMRZjmtsJ4zBGSA/8nkaM47fO7brsKu8f7eV2fU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777272747; c=relaxed/simple; bh=c/swTFYXP2qdXTxfLvAWfMN1SMlHP5XuNC+j5JT3jV4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=N4wpHk6YCrVv9sJVh1c7oWkJRP1Hq2NpdJC2+JzIBkeXY8q/sPBvamHd/nRqCFllJdzEtG4y1nOFsFE9HtWWnTx9n7QG/+muoymGUmbQdP8rWLZ05zQFyovHrLsSovYJl0fpDWBnJarifTESE2TDEddjRsaAe5RtcP5GWQ7x7yM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FoKtPFr+; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="FoKtPFr+" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CF739C19425; Mon, 27 Apr 2026 06:52:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777272746; bh=c/swTFYXP2qdXTxfLvAWfMN1SMlHP5XuNC+j5JT3jV4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FoKtPFr+3ScWKwc6SzA0v/siEGUsjOevvKFwVDKE1gQyi8VHELmD9aHvocV7Thplp XZ5iwO/wljdRJEqz+ZzpUi7i9xV+DhSKOf8UrFhv4ctVK/S4JiIWKPhb1+AX0losIK 1tnkSXXrtwKzvK8KDNYOVPIXsAoPMRd7NqxGAbVEcsLZGMptGJ/0uUbhtkE2Rt2Y9K f2gchITpsR5HMzsB49XOel9wcX7i13tKHlB7EPzma4wIMpfyeS1ZjUFTzFSM4GI7ny TcUTzvUOLiX0KVmZC100zJRj+Hzrf878O+NJiKMmMPBOgEfrPHDb+NavuGaQ0G47PT UrXGR0+Q/8IAg== 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: [RFC PATCH v4 09/14] coco: host: arm64: Initialize RMM pdev state for TDISP IDE connect Date: Mon, 27 Apr 2026 12:21:16 +0530 Message-ID: <20260427065121.916615-10-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260427065121.916615-1-aneesh.kumar@kernel.org> References: <20260427065121.916615-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/arm-cca.c | 43 +++++++++-- drivers/virt/coco/arm-cca-host/rmi-da.c | 92 +++++++++++++++++++++++- drivers/virt/coco/arm-cca-host/rmi-da.h | 3 + 3 files changed, 128 insertions(+), 10 deletions(-) diff --git a/drivers/virt/coco/arm-cca-host/arm-cca.c b/drivers/virt/coco/a= rm-cca-host/arm-cca.c index 3c854aab95cc..f0aa4e46e96c 100644 --- a/drivers/virt/coco/arm-cca-host/arm-cca.c +++ b/drivers/virt/coco/arm-cca-host/arm-cca.c @@ -66,7 +66,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; @@ -184,15 +184,40 @@ static int cca_tsm_connect(struct pci_dev *pdev) ret =3D tsm_ide_stream_register(ide); if (ret) goto err_tsm; + } =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)) + tsm_ide_stream_unregister(ide); err_tsm: if (cca_pdev_need_sel_ide_streams(pdev)) { pci_ide_stream_teardown(rp, ide); @@ -222,12 +247,16 @@ static void cca_tsm_disconnect(struct pci_dev *pdev) if (cca_pdev_need_sel_ide_streams(pdev)) { ide =3D pf0_ep_dsc->sel_stream; stream_id =3D ide->stream_id; + } + + cca_pdev_stop_and_destroy(pdev); + free_dev_communication_buffers(&pf0_ep_dsc->pdev.comm_data); =20 + if (cca_pdev_need_sel_ide_streams(pdev)) { pci_ide_stream_release(ide); pf0_ep_dsc->sel_stream =3D NULL; clear_bit(stream_id, cca_stream_ids); } - } =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 996979dba709..cb654d1b2eb3 100644 --- a/drivers/virt/coco/arm-cca-host/rmi-da.c +++ b/drivers/virt/coco/arm-cca-host/rmi-da.c @@ -386,7 +386,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; @@ -484,7 +484,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 @@ -581,8 +581,94 @@ 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) + unsigned long *rmi_ret) { struct rmi_sro_state *sro __free(sro) =3D rmi_sro_init(SMC_RMI_PDEV_DESTROY, pdev_phys); diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.h b/drivers/virt/coco/ar= m-cca-host/rmi-da.h index 7d38e548b659..240b2993ae53 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 Thu Jun 11 03:18:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 326B52E2850; Mon, 27 Apr 2026 06:52:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777272752; cv=none; b=g5HKBZGNWh+o6xAPxUT2vvAWUJHsO0WU/CX9nd1blKm1Dsu3YU2qVXrgDoF6UCRyNq2sUXzhl1Q8cb+q2MrT28bQfcVwhPc2Br7qzl4kUCNfVNWylZuLoEcvElHnrO1TvOin6Sv877uvrXBEXBfuJ2AHlQpK3sYAWdM9wzsbLE0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777272752; c=relaxed/simple; bh=6Sw133FYh53nGQovcs9D8dmPUc0HpnR58dh4gpbmiQs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lRRUB/Cl3sydPc9m6NWJVw0L18nybmYUJBKCOnI3kg1LVCnidUgPYkMX16BkL5ATdgYECbbGyZy5SMmrcH5fT5vm0X3wZF8CmK4SKnSZqw6K41Y+733V3M5ouj86L7Pkdp9qIKNn8zfCTIg3iqF2S6g31HkNZNx+5lHruyDtEeY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=noOqHOyX; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="noOqHOyX" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 21BDBC19425; Mon, 27 Apr 2026 06:52:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777272751; bh=6Sw133FYh53nGQovcs9D8dmPUc0HpnR58dh4gpbmiQs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=noOqHOyXTbTN+psr4aaXatkYLw1cGUbB2hBh0g9du2NZGYAio1C1KdP/NY5MKcWKH RdSLwYfrCd6PJNjBSj1gM7xYIyY41+vNLOGmblrWR6GLBSwqBwf1iKmqVgVJ/Hafr0 5bVgmhSMAT4Me22LcOALIMRPkxJAwGKBEw7Jh3VNSFzjv0L8+U2Otm+zeptdtqo8gP udXt5++O/JNiYem/bQUo29ZorcpEl29LruigypoddqJebf1SeDF9yHrOAy91fccPDA NSFKAKtt5uRp5nBusFEoffzjzEum9/nTwvJ0k/8PXZHU2VveKurIuFS86g9YSQFQN1 WiGTuqFwFc3qg== 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: [RFC PATCH v4 10/14] coco: host: arm64: Coordinate peer stream waits during pdev communication Date: Mon, 27 Apr 2026 12:21:17 +0530 Message-ID: <20260427065121.916615-11-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260427065121.916615-1-aneesh.kumar@kernel.org> References: <20260427065121.916615-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) --- arch/arm64/include/asm/rmi_smc.h | 1 + drivers/virt/coco/arm-cca-host/rmi-da.c | 116 +++++++++++++++++++++++- drivers/virt/coco/arm-cca-host/rmi-da.h | 13 +++ 3 files changed, 125 insertions(+), 5 deletions(-) diff --git a/arch/arm64/include/asm/rmi_smc.h b/arch/arm64/include/asm/rmi_= smc.h index 7a5d57a8be7a..e9437d56996a 100644 --- a/arch/arm64/include/asm/rmi_smc.h +++ b/arch/arm64/include/asm/rmi_smc.h @@ -484,6 +484,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 diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.c b/drivers/virt/coco/ar= m-cca-host/rmi-da.c index cb654d1b2eb3..28f450e2db27 100644 --- a/drivers/virt/coco/arm-cca-host/rmi-da.c +++ b/drivers/virt/coco/arm-cca-host/rmi-da.c @@ -197,7 +197,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; @@ -329,11 +329,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; @@ -342,8 +348,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)); @@ -371,7 +379,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; @@ -593,7 +601,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 @@ -711,3 +719,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 240b2993ae53..5b0f43493485 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; --=20 2.43.0 From nobody Thu Jun 11 03:18:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 7EA6A3890F9; Mon, 27 Apr 2026 06:52:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777272757; cv=none; b=Uhap6aNs/cCxkdWZgY7rYs37SeEVJ1IrUjM1BWJbd6Eir7FHtjxBz+hFB+RYcdHvloPwcqCCI1G+TukMT2ZK5/K+2ZuM4DaZZ8Fvyg0A5pYtDbfVBcguppnmXLQm57mfTDdIpWiv/MQ9XhxQEP8Mn8KIXLnEl+dNsRq3Ccelp4Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777272757; c=relaxed/simple; bh=sHgmPkt+ZMIm9QVi6ISjsSY+hW0JjlGh+/3Y1MgSYYY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ra63NQOSEf4xPdsghXtIRNpr2VHyv63Urzt6yU6/M+lYQKUY+86zaYemIGFQ9MgHl3K9vUlm4wNbIhZPignIbTEBGgjUOoe8LNyl3PPGphR3xSuokxlQzAqqic8hU6DIWul8D2I5tuhMLB/Ysz1k/ZD1ajEHykpnBPsjYUkf/v8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=WFLBpYzb; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="WFLBpYzb" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6A2B8C19425; Mon, 27 Apr 2026 06:52:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777272757; bh=sHgmPkt+ZMIm9QVi6ISjsSY+hW0JjlGh+/3Y1MgSYYY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WFLBpYzbZkmib/2ByFRj9MNGPT57k2TSMgyA679dJlvIrHzzBsxNJuUJPr1FpwHzH u4ScNaIoAZ5hr3K64s5Vxm5CtdG6oAZfH6+GIk2HkvaLVOyPobMi/XbzUem4QtURw7 9HgjeAz91aHlTC+V5KLC6BZcrxKu5tVG8yeJXbe5AL4Cb04/qLBeuy30syfBhABPxH KZRlRmK9SKky/MY75SXJNy1GeG3wjXA5GKgYIqdZyu9zYbwbuIhJLdzu/n+7pmm/+a P0R8z3XWfdSIeTqfyHA/InRdkbdlOM3Dxh0SM3h/GqeRTpChSfqr9veDBD9ltqsvhZ zsz2raXN9LkUg== 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: [RFC PATCH v4 11/14] coco: host: arm64: Connect RMM pdev streams for IDE devices Date: Mon, 27 Apr 2026 12:21:18 +0530 Message-ID: <20260427065121.916615-12-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260427065121.916615-1-aneesh.kumar@kernel.org> References: <20260427065121.916615-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) --- arch/arm64/include/asm/rmi_cmds.h | 37 +++++++ arch/arm64/include/asm/rmi_smc.h | 39 +++++++ drivers/virt/coco/arm-cca-host/arm-cca.c | 127 +++++++++++++++++++++++ drivers/virt/coco/arm-cca-host/rmi-da.c | 40 ++++++- drivers/virt/coco/arm-cca-host/rmi-da.h | 57 ++++++++++ 5 files changed, 299 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/rmi_cmds.h b/arch/arm64/include/asm/rmi= _cmds.h index 00e0a08e17a6..c82d4d9cbc06 100644 --- a/arch/arm64/include/asm/rmi_cmds.h +++ b/arch/arm64/include/asm/rmi_cmds.h @@ -774,4 +774,41 @@ 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 /* __ASM_RMI_CMDS_H */ diff --git a/arch/arm64/include/asm/rmi_smc.h b/arch/arm64/include/asm/rmi_= smc.h index e9437d56996a..7b16f1540a0e 100644 --- a/arch/arm64/include/asm/rmi_smc.h +++ b/arch/arm64/include/asm/rmi_smc.h @@ -556,4 +556,43 @@ 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, + RMI_PDEV_STREAM_NCOH_P2P, + RMI_PDEV_STREAM_COH_CMEM, +}; + +struct rmi_addr_range { + u64 base; /* inclusive */ + u64 top; /* exclusive */ +}; + +struct rmi_pdev_stream_params { + union { + struct { + u64 flags; + union { + u8 type; + u8 padding1[8]; + }; + u64 pdev_1; + u64 pdev_2; + u64 ide_sid; + u64 num_addr_range; + }; + u8 padding2[0x100]; + }; + + union { /* 0x100 */ + struct rmi_addr_range addr_range[MAX_STREAM_ADDR_RANGE]; + u8 padding3[0xF00]; + }; +}; + #endif /* __ASM_RMI_SMC_H */ diff --git a/drivers/virt/coco/arm-cca-host/arm-cca.c b/drivers/virt/coco/a= rm-cca-host/arm-cca.c index f0aa4e46e96c..de7a2e156549 100644 --- a/drivers/virt/coco/arm-cca-host/arm-cca.c +++ b/drivers/virt/coco/arm-cca-host/arm-cca.c @@ -134,6 +134,126 @@ static int alloc_stream_id(struct pci_host_bridge *hb) return stream_id; } =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; + + /* We are under pci_tsm_rwsem. */ + lockdep_assert_held_write(&pci_tsm_rwsem); + + 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->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; @@ -202,6 +322,10 @@ static int cca_tsm_connect(struct pci_dev *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 @@ -239,6 +363,7 @@ static void cca_tsm_disconnect(struct pci_dev *pdev) int stream_id; 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) @@ -249,6 +374,8 @@ static void cca_tsm_disconnect(struct pci_dev *pdev) stream_id =3D ide->stream_id; } =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 28f450e2db27..a10ac6ff03d1 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; } @@ -770,7 +774,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; @@ -814,6 +818,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 5b0f43493485..ea5f7df3541f 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 uint8_t 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 --=20 2.43.0 From nobody Thu Jun 11 03:18:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 7E8FB3264FA; Mon, 27 Apr 2026 06:52:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777272762; cv=none; b=u2FYawRbaSW3myvvgTGanCEkCLPmwIN/RiF3FCeOsGNsR7LhhF+0jNqWunu0Py9ulmT+64XlTpqJXErA6Hi2BvM5ttxz8kfhHQ0tM4bm83bFBVVakAg7sU9WcIQxf8uUet8TB3wBl1ny06hMF/650mHndO0PIuKnRbkHoa5Hbhc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777272762; c=relaxed/simple; bh=Lgmbk9xMIpHvR05nzEfVzoIynoOoPTPEvkqEGSPDfJo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cJmkRIyw6uhqvXY7nkEqUyfu5InSjsFQy8vcdhcNO0ORfc25sUAQqShSr6OV2EipxqSxgtSXu7Twi/gyy1v1eqHYAV3E6oL9dCHMuioJ9Z5vaway8MTb35CUZwhvFUrkUOiX8af/0KaqaoQId2Tr2dwtgX0zc/h5ehFpKhQ8xgE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=BJHUouHR; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="BJHUouHR" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B2A31C19425; Mon, 27 Apr 2026 06:52:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777272762; bh=Lgmbk9xMIpHvR05nzEfVzoIynoOoPTPEvkqEGSPDfJo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BJHUouHRSkmYTywbg9zws+4kV6xqUuhelqXjP+HvFWKQTtaWZB3KY4x2DO0M8T3ch EBhGzDyiKKYgXnZLScnZ8eXFbi0WIkFZMcMOF4H6F7A4Cm54wExxYkdJEwiVa0ZjZ3 PgKpu/nB3UTf2R5wTmqrvp0JUjbfj4hFzkbku5ABJTI4MlspkV98vV7jCDW2qThHeE yK7qBfI2NNwO+uhtU8kYkhHm62poGTRsLzD7c4N/ZOYqhzs8mltEvj/mN1dS10wKi0 RI3N9JilK7PoxhGdA+AxzFFdMHMhg67xZw05lCdCfDF9WQDflK+tY45dJtz6ZnbNKB kd4vd263wK6Bw== 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: [RFC PATCH v4 12/14] coco: host: arm64: Refcount root-port pdevs used by IDE streams Date: Mon, 27 Apr 2026 12:21:19 +0530 Message-ID: <20260427065121.916615-13-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260427065121.916615-1-aneesh.kumar@kernel.org> References: <20260427065121.916615-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/arm-cca.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/arm-cca.c b/drivers/virt/coco/a= rm-cca-host/arm-cca.c index de7a2e156549..0b1200f591ab 100644 --- a/drivers/virt/coco/arm-cca-host/arm-cca.c +++ b/drivers/virt/coco/arm-cca-host/arm-cca.c @@ -134,6 +134,23 @@ static int alloc_stream_id(struct pci_host_bridge *hb) return stream_id; } =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; @@ -151,6 +168,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); @@ -222,12 +240,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->type =3D RMI_PDEV_STREAM_NCOH; @@ -237,7 +258,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); @@ -375,6 +398,8 @@ static void cca_tsm_disconnect(struct pci_dev *pdev) } =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 ea5f7df3541f..798a8ed7505f 100644 --- a/drivers/virt/coco/arm-cca-host/rmi-da.h +++ b/drivers/virt/coco/arm-cca-host/rmi-da.h @@ -10,6 +10,9 @@ #include #include #include +#include +#include +#include #include #include =20 @@ -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 Thu Jun 11 03:18:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 24B793264FA; Mon, 27 Apr 2026 06:52:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777272768; cv=none; b=HdIjSlW8+1REhp4h/shtGaFJSefZymS22I6rQQWQ2gXM6+QeeONjj/qQxTuJaTM1DW2ktdDCyvg03NnZHUTaLxXNJ/Jvr+q1V1YwDVbgNO7b4Fq0Psi7vqQ1PiT5IYcpo3nESpxzCfzXNOk+6XK6IxnhWQfs9b6Zp8mlTkS/S6M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777272768; c=relaxed/simple; bh=437kH86jrTn4c1Epnw3resuWckEvIYjsHBmw7fIP+EI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=s5qRGNfPTTtWp7eZy4N0yFIls6wg1BqyoD7CtdkPz6OUgLjhha9W0vYCMV9UnjXKJBE9LhFFDg8sQxkJjWBMN0Fet1XlcB9cGM6y4U/zOAvjhVoGZhl+Zbk3GsZ3S/dcr/FT0XG66BqTlMoXFYvwwswo8yZqL29wiSTioQgakl0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=VsTz+yqz; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="VsTz+yqz" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 05037C2BCC4; Mon, 27 Apr 2026 06:52:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777272767; bh=437kH86jrTn4c1Epnw3resuWckEvIYjsHBmw7fIP+EI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VsTz+yqzRX5JWFXZZf9VJOF0bKQiZOVuDoPji4g1OmLkdzebLsB7i4cbYXSfeRtx5 OvMcZDNbo6zJY/e2lIT01+Bq+26mBgFksiGi8UW5EOedPKDFI91fFD7iaz4icdS5+G ZpcA79VuLeFLsJ38vg5yj29PUrrMYXmVYk8dQUqDt4UwvojIoCZT7Q+6pDc6w7n6wz v4STTOPn8lwri6ZSGF3vcDKCEaEYx2hg2GSCjn79CvQR7ueHMn9Ho7H86liZ0QGP9D aqz/pQ5iYC7EngUQpuaUrOpKeS7Wt417IWVlBkqqJATaz1pd0FTczxlP79EkIgqfZ2 Uf6XsOqxcIqXg== 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: [RFC PATCH v4 13/14] PCI/TSM: Move CMA DOE mailbox discovery out of pci_tsm_pf0_constructor() Date: Mon, 27 Apr 2026 12:21:20 +0530 Message-ID: <20260427065121.916615-14-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260427065121.916615-1-aneesh.kumar@kernel.org> References: <20260427065121.916615-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/core.c | 14 ++++++++------ drivers/virt/coco/arm-cca-host/arm-cca.c | 16 +++++++++++++--- drivers/virt/coco/tdx-host/tdx-host.c | 13 +++++++++++++ 4 files changed, 47 insertions(+), 9 deletions(-) diff --git a/drivers/crypto/ccp/sev-dev-tsm.c b/drivers/crypto/ccp/sev-dev-= tsm.c index b07ae529b591..a7506cbbe392 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/core.c b/drivers/pci/tsm/core.c index bb440135b8f7..900306a43161 100644 --- a/drivers/pci/tsm/core.c +++ b/drivers/pci/tsm/core.c @@ -1236,12 +1236,14 @@ int pci_tsm_pf0_constructor(struct pci_dev *pdev, s= truct 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/arm-cca.c b/drivers/virt/coco/a= rm-cca-host/arm-cca.c index 0b1200f591ab..265aa0cb612a 100644 --- a/drivers/virt/coco/arm-cca-host/arm-cca.c +++ b/drivers/virt/coco/arm-cca-host/arm-cca.c @@ -11,6 +11,8 @@ #include #include #include +#include + =20 #include "rmi-da.h" =20 @@ -35,14 +37,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; diff --git a/drivers/virt/coco/tdx-host/tdx-host.c b/drivers/virt/coco/tdx-= host/tdx-host.c index ea7c2167660f..4947b9bc2359 100644 --- a/drivers/virt/coco/tdx-host/tdx-host.c +++ b/drivers/virt/coco/tdx-host/tdx-host.c @@ -634,6 +634,19 @@ static struct pci_tsm *tdx_link_pf0_probe(struct tsm_d= ev *tsm_dev, spdm_conf->vmm_spdm_cap =3D SPDM_CAP_KEY_UPD; spdm_conf->certificate_slot_mask =3D 0xff; =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; + tlink->pci.doe_mb =3D doe_mb; + } else { + return NULL; + } + tlink->in_msg =3D no_free_ptr(in_msg); tlink->out_msg =3D no_free_ptr(out_msg); tlink->spdm_conf =3D no_free_ptr(spdm_conf); --=20 2.43.0 From nobody Thu Jun 11 03:18:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 7A3552E2850; Mon, 27 Apr 2026 06:52:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777272773; cv=none; b=djq3jhEeCGhr+df6VprjEpToS2vf+AhZog7JDSaKd1xqy7Y2FXqvfbnYW+yLgBVYbW46ITJCvoNNdNRgBic5cATLybxOMzIIHBnJITVYl9z14sOmKDpQr7ca5pMtkGHU2+9Oz7izSHtFYq/iCTjZDt5+P0jM4agz3nziHbzjrVg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777272773; c=relaxed/simple; bh=TKihfP1sVP9MoGos7O6yEjkbJNsJ70AjwacVZf82tOU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jb6efkaXL+1iP8MaPqc3VjLd559qS/4HtP4YFYDF4C5lppmmOYRtf7WHvn6gVTS+Lvcd8z+TA1sG+9mQsn5kPpQfggyYloylJOE2hHXOScovxBM3yrSQuxdJErI+1QeBWoe0lIpWeXgtm5F3omwBW6VmeTfWAAEimu33JPAWU50= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Jb1GNe7o; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Jb1GNe7o" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5D30BC4AF0B; Mon, 27 Apr 2026 06:52:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777272773; bh=TKihfP1sVP9MoGos7O6yEjkbJNsJ70AjwacVZf82tOU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Jb1GNe7oJiWmum8eE+T3ZUHoLT6j/OA0ZwpbjHuWebCbYAIuZ5FoqY15tUhTJx2LK WrPejaCgrTcjFQhm1tLf1LCclzLc98EreGo2TbtiXili1SBXxQKmvUbddoIW3dgwg0 ZZBY37PV8tL/nS/NnKgMmneG9MNHBfsGz14rTMiNTL6zxzXQV9twoTmkVFytCTfGlt m8piyK1TPe0UrBE8Bq8wUHvsKD9mB9ZU32UlrJu7lGedIKeN2n7IF6XW9dHuCtOfvl OhV2qrdcw2+V+TDF7OfyqUv4VT1Rztktxc2ez54IHSTLpZRIb1uXMnFyhKLLsW+ej8 V32UcleUrrZHA== 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: [RFC PATCH v4 14/14] coco: host: arm64: Add NCOH_SYS stream support for RC endpoints Date: Mon, 27 Apr 2026 12:21:21 +0530 Message-ID: <20260427065121.916615-15-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260427065121.916615-1-aneesh.kumar@kernel.org> References: <20260427065121.916615-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/arm-cca.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/arm-cca.c b/drivers/virt/coco/a= rm-cca-host/arm-cca.c index 265aa0cb612a..8b1182620872 100644 --- a/drivers/virt/coco/arm-cca-host/arm-cca.c +++ b/drivers/virt/coco/arm-cca-host/arm-cca.c @@ -277,11 +277,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->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 a10ac6ff03d1..33a2551fd09f 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