From nobody Tue Apr 7 18:00:32 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 3B5A327470; Thu, 12 Mar 2026 08:01:59 +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=1773302519; cv=none; b=Q5pSIOiClWCGMYzQ3AiZu+IaYIErBfHN+6VdXjtwQYi3/Sy14DGLzSMQcqaCwj0UO9S1onLhvDl45WNo+XA+2j0NXkRLB2ZTfzA2krXfi0b1Mq7Q0OwKu7hcKP7GA8IJw8Tjq5BnJ868JkkMRmFgD46ik+oREqzdGtkF+6tliKY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773302519; c=relaxed/simple; bh=u+K2YX0UiSGjqu/03TsV46CS2J8/TdkIpbUuur3YNrI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=P4OMKhj41NyBgB1s73oDm4cx0c6N6XrhE81ZhgSTEhfbJqWd2mhGYkfPe/KIIt8zFWvjj9GYGN58B4RzLKRiRTTmpgSrmFJ164TaSyjvEOLREvYxo5tZnyYgovF60/Hew76Aev2W1ar4ewLA85BhbXtzjNZfz0QjP74LVm7RYsI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Vb82oAZQ; 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="Vb82oAZQ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id AD661C116C6; Thu, 12 Mar 2026 08:01:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773302518; bh=u+K2YX0UiSGjqu/03TsV46CS2J8/TdkIpbUuur3YNrI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Vb82oAZQB5riuIp6fPLoLpOePoCwPydEF1xFAVupqMWfuEQP0NvsxQIC6ZS3hIulO 827rgOsl/s4E5/l49GFccCO/LlvHivBjgkq3zgfnYCgpuSQiu7aVceFaw9YY+VD6Zb KW50EqulVzvveWrVjPO90feb+l1eV2A3/7ZITBV4zngj5bkspJqqimawN4jkMM1GZ7 OtLo2/R7vept85hSX5SaGWjXzILwV/Uyr031CLBZkMLn8vYTvudhYe400Nfutj+jYd zfQ48riBOWQHt+4T8W0o1DnEJsyvq/unfEzR8JtMhPeanEQeWDFMR3XeNdgY1NUGv2 HtfMWnQmXHPXA== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org, "Aneesh Kumar K.V (Arm)" , Marc Zyngier , Catalin Marinas , Will Deacon , Jonathan Cameron , Jason Gunthorpe , Dan Williams , Alexey Kardashevskiy , Samuel Ortiz , Xu Yilun , Suzuki K Poulose , Steven Price Subject: [RFC PATCH v3 01/10] KVM: arm64: RMI: Add and export kvm_has_da_feature helper Date: Thu, 12 Mar 2026 13:31:20 +0530 Message-ID: <20260312080129.3483585-2-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260312080129.3483585-1-aneesh.kumar@kernel.org> References: <20260312080129.3483585-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 kvm_has_da_feature() helper for use in later patches. Update reserved fields based on Alp17 spec. Cc: Marc Zyngier Cc: Catalin Marinas Cc: Will Deacon Cc: Jonathan Cameron Cc: Jason Gunthorpe Cc: Dan Williams Cc: Alexey Kardashevskiy Cc: Samuel Ortiz Cc: Xu Yilun Cc: Suzuki K Poulose Cc: Steven Price Signed-off-by: Aneesh Kumar K.V (Arm) --- arch/arm64/include/asm/kvm_rmi.h | 1 + arch/arm64/include/asm/rmi_smc.h | 3 ++- arch/arm64/kvm/rmi.c | 6 ++++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/kvm_rmi.h b/arch/arm64/include/asm/kvm_= rmi.h index 1b2cdaac6c50..a967061af6ed 100644 --- a/arch/arm64/include/asm/kvm_rmi.h +++ b/arch/arm64/include/asm/kvm_rmi.h @@ -90,6 +90,7 @@ u32 kvm_realm_ipa_limit(void); u32 kvm_realm_vgic_nr_lr(void); u8 kvm_realm_max_pmu_counters(void); unsigned int kvm_realm_sve_max_vl(void); +bool kvm_has_da_feature(void); =20 u64 kvm_realm_reset_id_aa64dfr0_el1(const struct kvm_vcpu *vcpu, u64 val); =20 diff --git a/arch/arm64/include/asm/rmi_smc.h b/arch/arm64/include/asm/rmi_= smc.h index 1000368f1bca..f6f786bfb9c9 100644 --- a/arch/arm64/include/asm/rmi_smc.h +++ b/arch/arm64/include/asm/rmi_smc.h @@ -86,7 +86,8 @@ enum rmi_ripas { #define RMI_FEATURE_REGISTER_0_HASH_SHA_512 BIT(33) #define RMI_FEATURE_REGISTER_0_GICV3_NUM_LRS GENMASK(37, 34) #define RMI_FEATURE_REGISTER_0_MAX_RECS_ORDER GENMASK(41, 38) -#define RMI_FEATURE_REGISTER_0_Reserved GENMASK(63, 42) +#define RMI_FEATURE_REGISTER_0_DA BIT(42) +#define RMI_FEATURE_REGISTER_0_Reserved GENMASK(63, 61) =20 #define RMI_REALM_PARAM_FLAG_LPA2 BIT(0) #define RMI_REALM_PARAM_FLAG_SVE BIT(1) diff --git a/arch/arm64/kvm/rmi.c b/arch/arm64/kvm/rmi.c index 478a73e0b35a..08f3d2362dfd 100644 --- a/arch/arm64/kvm/rmi.c +++ b/arch/arm64/kvm/rmi.c @@ -1738,6 +1738,12 @@ int kvm_init_realm_vm(struct kvm *kvm) return 0; } =20 +bool kvm_has_da_feature(void) +{ + return rmi_has_feature(RMI_FEATURE_REGISTER_0_DA); +} +EXPORT_SYMBOL_GPL(kvm_has_da_feature); + void kvm_init_rmi(void) { /* Only 4k page size on the host is supported */ --=20 2.43.0 From nobody Tue Apr 7 18:00:32 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 C212B2D949F; Thu, 12 Mar 2026 08:02:06 +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=1773302526; cv=none; b=BcmailVYzhoc6FtZklqWBlYiRSrvDbLMzbDGMGelWHhQHhV/dkUgUEH7DH83ilXTQHq3oZdvWYKf3cI9TzIzT1TkJC2uwS4g6Ifq/7vToqtS/whJRI+BIBGocqr+GZ7RlmOB067ApvRmmFjEJmJcMX0S9CBDyWny7qPOwxtKA/o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773302526; c=relaxed/simple; bh=eWlGJ1mq0uFiFfzJb+fYY2WYTV1JrcFFXW4P04yrmR4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dCQVLjwQN2JtjmwUH50I5MxEOzEw3zoZ15mXxxHJ/XbcGjW+ZSb0m6Meqnk1zSHIeZb5PC8NW/QOAHMKN34ppbeYgzXEI+T8qzb60wDl2k6eRdfazgxjB0ymfcsT7BET7Th3/Tu1lQepO/PVyfqNsSG/GyUjlAjy/STZfnyOr/s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=sYxk00+3; 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="sYxk00+3" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A85E8C116C6; Thu, 12 Mar 2026 08:01:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773302526; bh=eWlGJ1mq0uFiFfzJb+fYY2WYTV1JrcFFXW4P04yrmR4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=sYxk00+3L2os3MAfNJKAbiE7LZpbj2O10PFrY9REUQuQTcLjHUmQBmvTugGrbX11N RQE8Uli1HHrYCqBFThEQaBu/QybxLHHl675SRiDOGfNq64dScTzAkRuQEYV5ekAElM NLjzBiY1oafLdVMXAxpImQfOjj8UyG1QghXdvP6uxetdm/2UMN3/aa3eSbDaaiZzPv rfLoc9yOp/epU74Mnxjn82nz8m/EbpmhzoPIJ4aziaU6K7Lfg/gkd7iNuIqfKhxekq dSayP8ICVpdLyBtuiEA+/7VmRHOeHrACHUrtlZvlwghkLDAXnlD0WctUgGlk+gpBb0 uagp2pwifyCWA== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org, "Aneesh Kumar K.V (Arm)" , Marc Zyngier , Catalin Marinas , Will Deacon , Jonathan Cameron , Jason Gunthorpe , Dan Williams , Alexey Kardashevskiy , Samuel Ortiz , Xu Yilun , Suzuki K Poulose , Steven Price Subject: [RFC PATCH v3 02/10] coco: host: arm64: Add host TSM callback and IDE stream allocation support Date: Thu, 12 Mar 2026 13:31:21 +0530 Message-ID: <20260312080129.3483585-3-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260312080129.3483585-1-aneesh.kumar@kernel.org> References: <20260312080129.3483585-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. Cc: Marc Zyngier Cc: Catalin Marinas Cc: Will Deacon Cc: Jonathan Cameron Cc: Jason Gunthorpe Cc: Dan Williams Cc: Alexey Kardashevskiy Cc: Samuel Ortiz Cc: Xu Yilun Cc: Suzuki K Poulose Cc: Steven Price 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 | 205 +++++++++++++++++++++++ drivers/virt/coco/arm-cca-host/rmi-da.h | 45 +++++ 10 files changed, 300 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 f6f786bfb9c9..9f8b6aa5ea06 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 03496330630f..7435996dcb90 100644 --- a/drivers/firmware/smccc/rmm.c +++ b/drivers/firmware/smccc/rmm.c @@ -23,3 +23,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..639ebd82978a --- /dev/null +++ b/drivers/virt/coco/arm-cca-host/arm-cca.c @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2026 ARM Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rmi-da.h" + +/* 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 rc; + + 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; + + rc =3D pci_tsm_link_constructor(pdev, &fn_dsc->pci, tsm_dev); + if (rc) + return NULL; + + return &no_free_ptr(fn_dsc)->pci; + } + + if (!pdev->ide_cap) + return NULL; + + struct cca_host_pf0_dsc *pf0_dsc __free(kfree) =3D + kzalloc(sizeof(*pf0_dsc), GFP_KERNEL); + if (!pf0_dsc) + return NULL; + + rc =3D pci_tsm_pf0_constructor(pdev, &pf0_dsc->pci, tsm_dev); + if (rc) + return NULL; + + pci_dbg(pdev, "tsm enabled\n"); + return &no_free_ptr(pf0_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_dsc *pf0_dsc =3D to_cca_pf0_dsc(pdev); + + pci_tsm_pf0_destructor(&pf0_dsc->pci); + kfree(pf0_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 int cca_tsm_connect(struct pci_dev *pdev) +{ + struct pci_dev *rp =3D pcie_find_root_port(pdev); + struct cca_host_pf0_dsc *pf0_dsc; + struct pci_ide *ide; + int rc, stream_id; + + /* Only function 0 supports connect in host */ + if (WARN_ON(!is_pci_tsm_pf0(pdev))) + return -EIO; + + pf0_dsc =3D to_cca_pf0_dsc(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) { + rc =3D -ENOMEM; + goto err_stream_alloc; + } + + pf0_dsc->sel_stream =3D ide; + ide->stream_id =3D stream_id; + rc =3D pci_ide_stream_register(ide); + if (rc) + goto err_stream; + + pci_ide_stream_setup(pdev, ide); + pci_ide_stream_setup(rp, ide); + + rc =3D tsm_ide_stream_register(ide); + if (rc) + 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: + pci_ide_stream_teardown(rp, ide); + pci_ide_stream_teardown(pdev, ide); + pci_ide_stream_unregister(ide); +err_stream: + pci_ide_stream_free(ide); + pf0_dsc->sel_stream =3D NULL; +err_stream_alloc: + clear_bit(stream_id, cca_stream_ids); + + return rc; +} + +static void cca_tsm_disconnect(struct pci_dev *pdev) +{ + int stream_id; + struct pci_ide *ide; + struct cca_host_pf0_dsc *pf0_dsc; + + pf0_dsc =3D to_cca_pf0_dsc(pdev); + if (!pf0_dsc) + return; + + ide =3D pf0_dsc->sel_stream; + stream_id =3D ide->stream_id; + + pci_ide_stream_release(ide); + pf0_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 (!kvm_has_da_feature()) + 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..a23955f84e4f --- /dev/null +++ b/drivers/virt/coco/arm-cca-host/rmi-da.h @@ -0,0 +1,45 @@ +/* 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 + +/** + * struct cca_host_pf0_dsc - Device Security Context for physical function= 0. + * @pci: Physical Function 0 TDISP link context + * @sel_stream: Selective IDE Stream descriptor + */ +struct cca_host_pf0_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_dsc *to_cca_pf0_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_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 Tue Apr 7 18:00:32 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 66E162D949F; Thu, 12 Mar 2026 08:02:13 +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=1773302533; cv=none; b=nzoiSabZkzGlGhUtrAglpWD4e82VsU06JtogJSx06a7aFgVyUcWMJsuieKX4HY9vmNA4VXyLxzEhjKchYOft4kuBI2mJsB8PiVklCpVDLf8G5us50n80VcMGAYQ32IC6q5ui09+BkXi0I6oT/psyzfpeB5e1VeUDpee70dEWz9A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773302533; c=relaxed/simple; bh=OyePJXIGmU9NZm7ifAgf6slvGQOVTPSVDx7SSqyYN24=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Mk7mdJpgRUkL+aitOm/gahxla1yq9DcsFeSjYNj3JtQiwekqkNycdu9aBLY6iZaNWWszpd0l6JCulcyV+GtAvmaL/u/g7RBoFYs72L/9H4yH1XeokGLBeIOQnxHKGCAfnUPsLkzJwewxhVKYtom+oMq27PI4wj+8d6798PZ8x/M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=er/G/rtt; 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="er/G/rtt" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 452A7C2BC87; Thu, 12 Mar 2026 08:02:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773302533; bh=OyePJXIGmU9NZm7ifAgf6slvGQOVTPSVDx7SSqyYN24=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=er/G/rttM2NUdbMTDk8RmgeqamR5oNe/GBlF2hFiWPY1ORMHN3n6u4v98wj1Qu1CH gRUa0NA4pEKjdcLu7xl35uNwVGwdS+D5eC+TKM3cCMALEmWCVZDcye/TxSoFhKclOB NR033IUQ0X61kf6A/dXien2pN6smixuK+gBkcPiFGxMsl1XEpPJTs6+tE38AKLbjyX 0KFwYSP0zt0G07Kgqz+bBOruzcs4UaJkDUi2cdhQXMA1IBvNp1x8foL2d21ZMg9jVn aEbFoZzOxoxnsqsflJgWMPPDgelLFkT63mWWfWwbSgTBgB60nUyY/smEIN2vfA/Wc0 8oIXz8HQXg3iQ== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org, "Aneesh Kumar K.V (Arm)" , Marc Zyngier , Catalin Marinas , Will Deacon , Jonathan Cameron , Jason Gunthorpe , Dan Williams , Alexey Kardashevskiy , Samuel Ortiz , Xu Yilun , Suzuki K Poulose , Steven Price Subject: [RFC PATCH v3 03/10] coco: host: arm64: Build and register RMM pdev descriptors Date: Thu, 12 Mar 2026 13:31:22 +0530 Message-ID: <20260312080129.3483585-4-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260312080129.3483585-1-aneesh.kumar@kernel.org> References: <20260312080129.3483585-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 SMCCC plumbing for RMI_PDEV_AUX_COUNT, RMI_PDEV_CREATE, and RMI_PDEV_GET_STATE, describe the pdev state enum/flags in rmi_smc.h, and extend the PF0 descriptor so we can hold the RMM-side pdev handle plus its auxiliary granules. Implement pdev_create() to delegate backing pages, populate the pdev parameters from the device's RID, ECAM window, IDE stream, and non-coherent address ranges, and invoke RMI_PDEV_CREATE. The helper keeps track of the allocated/assigned granules and unwinds them on failure, so the host driver can reliably establish the pdev channel before kicking off further IDE/TSM setup. Cc: Marc Zyngier Cc: Catalin Marinas Cc: Will Deacon Cc: Jonathan Cameron Cc: Jason Gunthorpe Cc: Dan Williams Cc: Alexey Kardashevskiy Cc: Samuel Ortiz Cc: Xu Yilun Cc: Suzuki K Poulose Cc: Steven Price Signed-off-by: Aneesh Kumar K.V (Arm) --- arch/arm64/include/asm/rmi_cmds.h | 31 +++++ arch/arm64/include/asm/rmi_smc.h | 95 ++++++++++++++- drivers/virt/coco/arm-cca-host/Makefile | 2 +- drivers/virt/coco/arm-cca-host/rmi-da.c | 156 ++++++++++++++++++++++++ drivers/virt/coco/arm-cca-host/rmi-da.h | 8 ++ 5 files changed, 290 insertions(+), 2 deletions(-) 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 ef53147c1984..4547ce0901a6 100644 --- a/arch/arm64/include/asm/rmi_cmds.h +++ b/arch/arm64/include/asm/rmi_cmds.h @@ -505,4 +505,35 @@ static inline int rmi_rtt_unmap_unprotected(unsigned l= ong rd, return res.a0; } =20 +static inline unsigned long rmi_pdev_aux_count(unsigned long flags, u64 *a= ux_count) +{ + struct arm_smccc_res res; + + arm_smccc_1_1_invoke(SMC_RMI_PDEV_AUX_COUNT, flags, &res); + + *aux_count =3D res.a1; + return res.a0; +} + +static inline unsigned long rmi_pdev_create(unsigned long pdev_phys, + unsigned long pdev_params_phys) +{ + struct arm_smccc_res res; + + arm_smccc_1_1_invoke(SMC_RMI_PDEV_CREATE, + pdev_phys, pdev_params_phys, &res); + + return res.a0; +} + +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 9f8b6aa5ea06..58106740c1f7 100644 --- a/arch/arm64/include/asm/rmi_smc.h +++ b/arch/arm64/include/asm/rmi_smc.h @@ -26,7 +26,7 @@ #define SMC_RMI_DATA_CREATE SMC_RMI_CALL(0x0153) #define SMC_RMI_DATA_CREATE_UNKNOWN SMC_RMI_CALL(0x0154) #define SMC_RMI_DATA_DESTROY SMC_RMI_CALL(0x0155) - +#define SMC_RMI_PDEV_AUX_COUNT SMC_RMI_CALL(0x0156) #define SMC_RMI_REALM_ACTIVATE SMC_RMI_CALL(0x0157) #define SMC_RMI_REALM_CREATE SMC_RMI_CALL(0x0158) #define SMC_RMI_REALM_DESTROY SMC_RMI_CALL(0x0159) @@ -47,6 +47,9 @@ #define SMC_RMI_RTT_INIT_RIPAS SMC_RMI_CALL(0x0168) #define SMC_RMI_RTT_SET_RIPAS SMC_RMI_CALL(0x0169) =20 +#define SMC_RMI_PDEV_CREATE SMC_RMI_CALL(0x0176) +#define SMC_RMI_PDEV_GET_STATE SMC_RMI_CALL(0x0178) + #define RMI_ABI_MAJOR_VERSION 1 #define RMI_ABI_MINOR_VERSION 0 =20 @@ -269,4 +272,94 @@ 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_IDE_RESETTING, + RMI_PDEV_COMMUNICATING, + RMI_PDEV_STOPPING, + RMI_PDEV_STOPPED, + RMI_PDEV_ERROR, +}; + +#define MAX_PDEV_AUX_GRANULES 32 +#define MAX_IOCOH_ADDR_RANGE 16 +#define MAX_FCOH_ADDR_RANGE 4 + +#define RMI_PDEV_FLAGS_SPDM BIT(0) +#define RMI_PDEV_FLAGS_NCOH_IDE BIT(1) +#define RMI_PDEV_FLAGS_NCOH_ADDR BIT(2) +#define RMI_PDEV_FLAGS_COH_IDE BIT(3) +#define RMI_PDEV_FLAGS_COH_ADDR BIT(4) +#define RMI_PDEV_FLAGS_P2P BIT(5) +#define RMI_PDEV_FLAGS_COMP_TRUST BIT(6) +#define RMI_PDEV_FLAGS_CATEGORY_MASK GENMASK(8, 7) +#define RMI_PDEV_FLAGS_CATEGORY_SHIFT 7 + +#define RMI_PDEV_FLAGS_CATEGORY_CMEM_CXL 0x1 + +#define RMI_HASH_SHA_256 0 +#define RMI_HASH_SHA_512 1 + +struct rmi_pdev_addr_range { + u64 base; + u64 top; +}; + +struct rmi_pdev_params { + union { + struct { + u64 flags; + u64 pdev_id; + union { + u8 segment_id; + u64 padding0; + }; + u64 ecam_addr; + union { + u16 root_id; + u64 padding1; + }; + u64 cert_id; + union { + u16 rid_base; + u64 padding2; + }; + union { + u16 rid_top; + u64 padding3; + }; + union { + u8 hash_algo; + u64 padding4; + }; + u64 num_aux; + u64 ncoh_ide_sid; + u64 ncoh_num_addr_range; + u64 coh_num_addr_range; + }; + u8 padding5[0x100]; + }; + + union { /* 0x100 */ + u64 aux_granule[MAX_PDEV_AUX_GRANULES]; + u8 padding6[0x100]; + }; + + union { /* 0x200 */ + struct { + struct rmi_pdev_addr_range ncoh_addr_range[MAX_IOCOH_ADDR_RANGE]; + }; + u8 padding7[0x100]; + }; + union { /* 0x300 */ + struct { + struct rmi_pdev_addr_range coh_addr_range[MAX_FCOH_ADDR_RANGE]; + }; + u8 padding8[0x100]; + }; +}; + #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..89b61ad5bc00 --- /dev/null +++ b/drivers/virt/coco/arm-cca-host/rmi-da.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2026 ARM Ltd. + */ + +#include +#include +#include + +#include "rmi-da.h" + +static int pci_dev_addr_range(struct pci_dev *pdev, + struct rmi_pdev_addr_range *pdev_addr, + struct pci_ide_partner *partner) +{ + 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)) { + pdev_addr[naddr].base =3D mem->start; + pdev_addr[naddr].top =3D mem->end + 1; + naddr++; + } + if (resource_assigned(pref)) { + pdev_addr[naddr].base =3D pref->start; + pdev_addr[naddr].top =3D pref->end + 1; + naddr++; + } + return naddr; +} + +static void free_aux_pages(int cnt, void *aux[]) +{ + int ret; + + while (cnt--) { + ret =3D rmi_granule_undelegate(virt_to_phys(aux[cnt])); + if (!ret) + free_page((unsigned long)aux[cnt]); + } +} + +static int init_pdev_params(struct pci_dev *pdev, struct rmi_pdev_params *= params) +{ + int rid, ret, i; + phys_addr_t aux_phys; + struct pci_config_window *cfg =3D pdev->bus->sysdata; + struct cca_host_pf0_dsc *pf0_dsc =3D to_cca_pf0_dsc(pdev); + struct pci_ide *ide =3D pf0_dsc->sel_stream; + + /* assign the ep device with RMM */ + rid =3D pci_dev_id(pdev); + params->pdev_id =3D rid; + /* slot number for certificate chain */ + params->cert_id =3D 0; + /* io coherent spdm/ide and non p2p */ + params->flags =3D RMI_PDEV_FLAGS_SPDM | RMI_PDEV_FLAGS_NCOH_IDE | + RMI_PDEV_FLAGS_NCOH_ADDR; + params->ncoh_ide_sid =3D ide->stream_id; + params->hash_algo =3D RMI_HASH_SHA_256; + /* use the rid and MMIO resources of the end point pdev */ + params->rid_base =3D rid; + params->rid_top =3D params->rid_base + 1; + params->ecam_addr =3D cfg->res.start; + params->root_id =3D pci_dev_id(pcie_find_root_port(pdev)); + + params->ncoh_num_addr_range =3D pci_dev_addr_range(pdev, + params->ncoh_addr_range, + &ide->partner[PCI_IDE_RP]); + + ret =3D rmi_pdev_aux_count(params->flags, ¶ms->num_aux); + if (ret) + return -EIO; + + pf0_dsc->num_aux =3D params->num_aux; + for (i =3D 0; i < params->num_aux; i++) { + void *aux =3D (void *)__get_free_page(GFP_KERNEL); + + if (!aux) { + ret =3D -ENOMEM; + goto err_free_aux; + } + + aux_phys =3D virt_to_phys(aux); + if (rmi_granule_delegate(aux_phys)) { + ret =3D -EIO; + free_page((unsigned long)aux); + goto err_free_aux; + } + params->aux_granule[i] =3D aux_phys; + pf0_dsc->aux[i] =3D aux; + } + return 0; + +err_free_aux: + free_aux_pages(i, pf0_dsc->aux); + return ret; +} + +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_pf0_dsc *pf0_dsc =3D to_cca_pf0_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_granule_delegate(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; + + if (rmi_pdev_create(rmm_pdev_phys, virt_to_phys(params))) { + ret =3D -EIO; + goto err_pdev_create; + } + + pf0_dsc->rmm_pdev =3D rmm_pdev; + free_page((unsigned long)params); + return 0; + +err_pdev_create: + free_aux_pages(pf0_dsc->num_aux, pf0_dsc->aux); +err_init_pdev_params: + free_page((unsigned long)params); +err_param_alloc: + if (rmi_granule_undelegate(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 a23955f84e4f..229f3ff6dc6f 100644 --- a/drivers/virt/coco/arm-cca-host/rmi-da.h +++ b/drivers/virt/coco/arm-cca-host/rmi-da.h @@ -15,10 +15,17 @@ * struct cca_host_pf0_dsc - Device Security Context for physical function= 0. * @pci: Physical Function 0 TDISP link context * @sel_stream: Selective IDE Stream descriptor + * @rmm_pdev: Delegated granule address of rmm pdev object + * @num_ax: Number of auxiliary granules allocated for pdev + * @aux: Delegated auxiliary granules */ struct cca_host_pf0_dsc { struct pci_tsm_pf0 pci; struct pci_ide *sel_stream; + + void *rmm_pdev; + int num_aux; + void *aux[MAX_PDEV_AUX_GRANULES]; }; =20 struct cca_host_fn_dsc { @@ -42,4 +49,5 @@ static inline struct cca_host_fn_dsc *to_cca_fn_dsc(struc= t pci_dev *pdev) return container_of(tsm, struct cca_host_fn_dsc, pci); } =20 +int cca_pdev_create(struct pci_dev *pdev); #endif --=20 2.43.0 From nobody Tue Apr 7 18:00:32 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 A84432DEA95; Thu, 12 Mar 2026 08:02:20 +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=1773302540; cv=none; b=KVF5HwM33yOrdrr5WsuNZ5dcgYsODMbjvMg6cbHXq0p5vCv+pR10/OzA0ij+M735qRZFw6FcOubFXK5X+WVW/KVgbjm2C2JadSHIjo4VJuyjJJqE2Vr2zxQLkE2CsTlDbvRkfwrb4pk6JP+3ztex0bLhftZBgILyFFMJp4dYhOE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773302540; c=relaxed/simple; bh=llKUZdAoO4jq/d/aGskWdbEbWUrP11igcL2ngjZcRiA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=i9/g/yqGXDiBiGwnEEHYb8mBdNG/o1LT0RKA+S9ppzhwzkyfxx9T+56GyhViMisNVmQ6GUzczCav3r5tTXnAc2h9IqOIIuITV2BUwGx8lLeCZOZZxTtJNHFtX7ro1sK14L9+b4IyWjoNRgymkTVOeZFo32wrZWAO+SQYipMIxxE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=glH9iZyF; 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="glH9iZyF" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C93F7C19424; Thu, 12 Mar 2026 08:02:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773302540; bh=llKUZdAoO4jq/d/aGskWdbEbWUrP11igcL2ngjZcRiA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=glH9iZyFRc1vaUf1OEFBvq6hmMj304/2ZCIqHbtDoRTWHnr05yYwuiyvEpdIdOgNY Q5SHqcAneLx9gWB5uDjoo8275vww6/BesiLjVOOmHUMx1uCXHmqJrLW+CHgDvIy9Ww qx6zjD186085kY58laUYx/XN+2AjL7IFCdPN/gme3XPuPJj0n8yDcCxtZs9w3DDd4l ofQ7UX1AaHSOWnSxgeeC+hRC3mplO1aet/NMzdKmOdyQJcSSGP1uBsymCOHPel834R h1Bcor1o2a+xQkfKZsFDUgdDWl5SHw/XViF4b43xQFKcKvUMPD8fueQWAHXBbqDm7s vzkPm4ZmZoX/Q== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org, "Aneesh Kumar K.V (Arm)" , Marc Zyngier , Catalin Marinas , Will Deacon , Jonathan Cameron , Jason Gunthorpe , Dan Williams , Alexey Kardashevskiy , Samuel Ortiz , Xu Yilun , Suzuki K Poulose , Steven Price Subject: [RFC PATCH v3 04/10] coco: host: arm64: Add RMM device communication helpers Date: Thu, 12 Mar 2026 13:31:23 +0530 Message-ID: <20260312080129.3483585-5-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260312080129.3483585-1-aneesh.kumar@kernel.org> References: <20260312080129.3483585-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 (pdev_communicate_work) plus shared helpers that submit the SMCCC call, cache multi-part responses, and handle retries/abo= rt - hook the new helpers into the physical function connect path so IDE setup can drive the device to the expected state Cc: Marc Zyngier Cc: Catalin Marinas Cc: Will Deacon Cc: Jonathan Cameron Cc: Jason Gunthorpe Cc: Dan Williams Cc: Alexey Kardashevskiy Cc: Samuel Ortiz Cc: Xu Yilun Cc: Suzuki K Poulose Cc: Steven Price Signed-off-by: Aneesh Kumar K.V (Arm) --- arch/arm64/include/asm/rmi_cmds.h | 20 ++ arch/arm64/include/asm/rmi_smc.h | 63 +++++ drivers/virt/coco/arm-cca-host/arm-cca.c | 50 ++++ drivers/virt/coco/arm-cca-host/rmi-da.c | 281 +++++++++++++++++++++++ drivers/virt/coco/arm-cca-host/rmi-da.h | 66 ++++++ 5 files changed, 480 insertions(+) diff --git a/arch/arm64/include/asm/rmi_cmds.h b/arch/arm64/include/asm/rmi= _cmds.h index 4547ce0901a6..b86bf15afcda 100644 --- a/arch/arm64/include/asm/rmi_cmds.h +++ b/arch/arm64/include/asm/rmi_cmds.h @@ -536,4 +536,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 58106740c1f7..c91cd0e389a9 100644 --- a/arch/arm64/include/asm/rmi_smc.h +++ b/arch/arm64/include/asm/rmi_smc.h @@ -47,6 +47,8 @@ #define SMC_RMI_RTT_INIT_RIPAS SMC_RMI_CALL(0x0168) #define SMC_RMI_RTT_SET_RIPAS SMC_RMI_CALL(0x0169) =20 +#define SMC_RMI_PDEV_ABORT SMC_RMI_CALL(0x0174) +#define SMC_RMI_PDEV_COMMUNICATE SMC_RMI_CALL(0x0175) #define SMC_RMI_PDEV_CREATE SMC_RMI_CALL(0x0176) #define SMC_RMI_PDEV_GET_STATE SMC_RMI_CALL(0x0178) =20 @@ -69,6 +71,7 @@ #define RMI_ERROR_REALM 2 #define RMI_ERROR_REC 3 #define RMI_ERROR_RTT 4 +#define RMI_BUSY 10 =20 enum rmi_ripas { RMI_EMPTY =3D 0, @@ -362,4 +365,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 639ebd82978a..4ed5e8ec9e91 100644 --- a/drivers/virt/coco/arm-cca-host/arm-cca.c +++ b/drivers/virt/coco/arm-cca-host/arm-cca.c @@ -47,6 +47,7 @@ static struct pci_tsm *cca_tsm_pci_probe(struct tsm_dev *= tsm_dev, struct pci_dev rc =3D pci_tsm_pf0_constructor(pdev, &pf0_dsc->pci, tsm_dev); if (rc) return NULL; + mutex_init(&pf0_dsc->object_lock); =20 pci_dbg(pdev, "tsm enabled\n"); return &no_free_ptr(pf0_dsc)->pci.base_tsm; @@ -66,6 +67,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 89b61ad5bc00..93512f7e73d5 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" @@ -154,3 +156,282 @@ 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_pf0_dsc *pf0_dsc =3D to_cca_pf0_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(pf0_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) { + + switch (io_exit->cache_obj_id) { + case RMI_DEV_VCA: + cache_objp =3D &pf0_dsc->vca; + break; + case RMI_DEV_CERTIFICATE: + cache_objp =3D &pf0_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); + } + + 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; + + if (io_exit->flags & RMI_DEV_COMM_EXIT_CACHE_REQ || + io_exit->flags & RMI_DEV_COMM_EXIT_CACHE_RSP) { + int cache_remaining; + + /* 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_pf0_dsc *pf0_dsc =3D to_cca_pf0_dsc(tsm->dsm_dev); + + io_enter =3D &pf0_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(pf0_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(pf0_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_pf0_dsc *pf0_dsc; + + setup_work =3D container_of(work, struct dev_comm_work, work); + tsm =3D setup_work->tsm; + pf0_dsc =3D to_cca_pf0_dsc(tsm->dsm_dev); + + guard(mutex)(&pf0_dsc->object_lock); + state =3D wait_for_pdev_state(tsm, setup_work->target_state); + WARN_ON(state !=3D setup_work->target_state); + + complete(&setup_work->complete); +} + +static int submit_pdev_state_transition_work(struct pci_dev *pdev, int tar= get_state) +{ + enum rmi_pdev_state state; + struct dev_comm_work comm_work; + struct cca_host_pf0_dsc *pf0_dsc =3D to_cca_pf0_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); + init_completion(&comm_work.complete); + comm_work.tsm =3D pdev->tsm; + comm_work.target_state =3D target_state; + + queue_work(comm_data->work_queue, &comm_work.work); + + wait_for_completion(&comm_work.complete); + destroy_work_on_stack(&comm_work.work); + + /* check if we reached target state */ + if (rmi_pdev_get_state(virt_to_phys(pf0_dsc->rmm_pdev), &state)) + return -EIO; + + if (state !=3D target_state) + /* no specific error for this */ + return -1; + return 0; +} + +int cca_pdev_ide_setup(struct pci_dev *pdev) +{ + return submit_pdev_state_transition_work(pdev, RMI_PDEV_NEEDS_KEY); +} diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.h b/drivers/virt/coco/ar= m-cca-host/rmi-da.h index 229f3ff6dc6f..db4bf893f596 100644 --- a/drivers/virt/coco/arm-cca-host/rmi-da.h +++ b/drivers/virt/coco/arm-cca-host/rmi-da.h @@ -9,29 +9,79 @@ #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 completion complete; +}; + +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_pf0_dsc - Device Security Context for physical function= 0. + * @comm_data: Device communication context * @pci: Physical Function 0 TDISP link context * @sel_stream: Selective IDE Stream descriptor * @rmm_pdev: Delegated granule address of rmm pdev object * @num_ax: Number of auxiliary granules allocated for pdev * @aux: Delegated auxiliary granules + * @object_lock: lock used to protect access to cached obects in PF0 and T= DIs + * @cert_chain: cetrificate chain + * @vca: SPDM's Version-Capabilities-Algorithms cache object */ struct cca_host_pf0_dsc { + struct cca_host_comm_data comm_data; struct pci_tsm_pf0 pci; struct pci_ide *sel_stream; =20 void *rmm_pdev; int num_aux; void *aux[MAX_PDEV_AUX_GRANULES]; + + struct mutex object_lock; + 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_dsc *to_cca_pf0_dsc(struct pci_dev *pdev) { struct pci_tsm *tsm =3D pdev->tsm; @@ -49,5 +99,21 @@ 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_comm_data *to_cca_comm_data(struct pci_dev *= pdev) +{ + struct cca_host_pf0_dsc *pf0_dsc; + + pf0_dsc =3D to_cca_pf0_dsc(pdev); + if (pf0_dsc) + return &pf0_dsc->comm_data; + + pf0_dsc =3D to_cca_pf0_dsc(pdev->tsm->dsm_dev); + if (pf0_dsc) + return &pf0_dsc->comm_data; + + return NULL; +} + int cca_pdev_create(struct pci_dev *pdev); +int cca_pdev_ide_setup(struct pci_dev *pdev); #endif --=20 2.43.0 From nobody Tue Apr 7 18:00:32 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 2FBA92E88BB; Thu, 12 Mar 2026 08:02:27 +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=1773302548; cv=none; b=c9ZQM9pqkrfimlrcowFVzkW9JkQPulhl6Jf/lzlpsWdSgnNvt7MEPTvfPXGmsD9uZPoNHm0vld2a6tzffH9nHncaxmyim6VDaMNtCmssmXT74h4z+L59JIISJrGf6Qf/XQuA6yfSvQWY22VnC4zlnsxU1oR8CfikyY3zNG6bIR8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773302548; c=relaxed/simple; bh=Gzj/qINUbsAKyM46DkOxoWyoR/eowsPritJzhjgn8qw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gfBKGuoOFsC98u2Q7b0Iouept/ZVggX23y8gEoEgFLjWTEEed9jF/hQA3jgmGGRE50RI1qXoyp4z7dAiezmT8429FrVt9LhI6ofar1hSnyIkPg8mqh9rd9g/mEfEgITjayPERgRpWqJbTvOwpDTSNMFAsLhH0iEwf3yYPV69W2M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Rwthk/kk; 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="Rwthk/kk" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 016F4C116C6; Thu, 12 Mar 2026 08:02:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773302547; bh=Gzj/qINUbsAKyM46DkOxoWyoR/eowsPritJzhjgn8qw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Rwthk/kkaJXkDR6/kz9Vay9yZpdMCZPU201cnMwjmbpLQEftZgLG3x8wAvgQAnqAf hTsWrWlJ9weeH8lSWTFf8Xhy87+XauV8JFUfAjpvGY3iAKV6upYE/iLCf0oQuMSeMS SJ3P+mViJcniQLKFxBJ8qjMVHDVvQn1vhLHKol8Vz3MyTg2AcsmO1PbyuN2bShxaua 8H+m6DQnFoNpyTNQkNqucJInlAxk6hJyGtxZ+RrVtvAuOrJJ6H2737hrTHd86Y+4v0 GtR348dZJgW4ULzKSVSN2JzaGONW7n19Iyo6nvJzt+P0gKRB1wUaS/kuHYrEQWCVEv pXC6Nvp8E16gg== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org, "Aneesh Kumar K.V (Arm)" , Marc Zyngier , Catalin Marinas , Will Deacon , Jonathan Cameron , Jason Gunthorpe , Dan Williams , Alexey Kardashevskiy , Samuel Ortiz , Xu Yilun , Suzuki K Poulose , Steven Price , Jonathan Cameron Subject: [RFC PATCH v3 05/10] coco: host: arm64: Add helper to stop and tear down an RMM pdev Date: Thu, 12 Mar 2026 13:31:24 +0530 Message-ID: <20260312080129.3483585-6-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260312080129.3483585-1-aneesh.kumar@kernel.org> References: <20260312080129.3483585-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, destroys it, frees auxiliary granules, and drops the delegated page Cc: Marc Zyngier Cc: Catalin Marinas Cc: Will Deacon Cc: Jonathan Cameron Cc: Jason Gunthorpe Cc: Dan Williams Cc: Alexey Kardashevskiy Cc: Samuel Ortiz Cc: Xu Yilun Cc: Suzuki K Poulose Cc: Steven Price Reviewed-by: Jonathan Cameron Signed-off-by: Aneesh Kumar K.V (Arm) --- arch/arm64/include/asm/rmi_cmds.h | 18 +++++++++++++++ arch/arm64/include/asm/rmi_smc.h | 2 ++ drivers/virt/coco/arm-cca-host/rmi-da.c | 30 +++++++++++++++++++++++++ drivers/virt/coco/arm-cca-host/rmi-da.h | 1 + 4 files changed, 51 insertions(+) diff --git a/arch/arm64/include/asm/rmi_cmds.h b/arch/arm64/include/asm/rmi= _cmds.h index b86bf15afcda..f10a0dcaa308 100644 --- a/arch/arm64/include/asm/rmi_cmds.h +++ b/arch/arm64/include/asm/rmi_cmds.h @@ -556,4 +556,22 @@ 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; +} + +static inline unsigned long rmi_pdev_destroy(unsigned long pdev_phys) +{ + struct arm_smccc_res res; + + arm_smccc_1_1_invoke(SMC_RMI_PDEV_DESTROY, 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 c91cd0e389a9..3a57c7245029 100644 --- a/arch/arm64/include/asm/rmi_smc.h +++ b/arch/arm64/include/asm/rmi_smc.h @@ -50,7 +50,9 @@ #define SMC_RMI_PDEV_ABORT SMC_RMI_CALL(0x0174) #define SMC_RMI_PDEV_COMMUNICATE SMC_RMI_CALL(0x0175) #define SMC_RMI_PDEV_CREATE SMC_RMI_CALL(0x0176) +#define SMC_RMI_PDEV_DESTROY SMC_RMI_CALL(0x0177) #define SMC_RMI_PDEV_GET_STATE SMC_RMI_CALL(0x0178) +#define SMC_RMI_PDEV_STOP SMC_RMI_CALL(0x017c) =20 #define RMI_ABI_MAJOR_VERSION 1 #define RMI_ABI_MINOR_VERSION 0 diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.c b/drivers/virt/coco/ar= m-cca-host/rmi-da.c index 93512f7e73d5..ba6d67e5f54e 100644 --- a/drivers/virt/coco/arm-cca-host/rmi-da.c +++ b/drivers/virt/coco/arm-cca-host/rmi-da.c @@ -435,3 +435,33 @@ int cca_pdev_ide_setup(struct pci_dev *pdev) { return submit_pdev_state_transition_work(pdev, RMI_PDEV_NEEDS_KEY); } + +void cca_pdev_stop_and_destroy(struct pci_dev *pdev) +{ + int ret; + struct cca_host_pf0_dsc *pf0_dsc =3D to_cca_pf0_dsc(pdev); + phys_addr_t rmm_pdev_phys =3D virt_to_phys(pf0_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; + + if (WARN_ON(rmi_pdev_destroy(rmm_pdev_phys))) + return; + + kfree(pf0_dsc->cert_chain.public_key); + kvfree(pf0_dsc->cert_chain.cache); + kvfree(pf0_dsc->vca); + pf0_dsc->cert_chain.cache =3D NULL; + pf0_dsc->vca =3D NULL; + + /* Free the aux granules */ + free_aux_pages(pf0_dsc->num_aux, pf0_dsc->aux); + pf0_dsc->num_aux =3D 0; + if (!rmi_granule_undelegate(rmm_pdev_phys)) + free_page((unsigned long)pf0_dsc->rmm_pdev); + pf0_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 db4bf893f596..fbfbcd40beb4 100644 --- a/drivers/virt/coco/arm-cca-host/rmi-da.h +++ b/drivers/virt/coco/arm-cca-host/rmi-da.h @@ -116,4 +116,5 @@ 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_ide_setup(struct pci_dev *pdev); +void cca_pdev_stop_and_destroy(struct pci_dev *pdev); #endif --=20 2.43.0 From nobody Tue Apr 7 18:00:32 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 5A91C2E88BB; Thu, 12 Mar 2026 08:02:35 +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=1773302555; cv=none; b=a0sl3b6e4c7Sd32xNBAu/KQms+8G7GORLNy1Yo1x3D1d2dDqT9aQOp1kENlzqQk6HUNnHfenlSwrOfx9FrfnHDRzw4n4q8FRsKgXRVEt7ZdbO3uJ9S8GbKaBPzQ4etN5AU/I+ee3gPcaP94n/DMuEDR64JAhDXuDFeWp+kEuqhU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773302555; c=relaxed/simple; bh=za/IJI/M4boNse0krvOPCedzdOn+suKa0F46ZZO+gZg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ifIY+5mSjiVsQowLtwkVe23vUWJRxgrDy+biPv6j9YOYttLsYNtTL7yV2qkmOjAiHjlCElgKpg9rOU6Lpwu+7i1NL28lNtW2ZtARkPq+TsRpTVVf/lsvkQ0zH32xlA4gtXvnuz8ZneEGFYwRyc7xYwXomr/buITdqbbuXHDF2hM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RI+nA7uk; 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="RI+nA7uk" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A27E6C2BCB0; Thu, 12 Mar 2026 08:02:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773302555; bh=za/IJI/M4boNse0krvOPCedzdOn+suKa0F46ZZO+gZg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RI+nA7ukMybNnkm3lH6oVEgqiYcpyFBnzTFL2NOQgUdbOm74tb7wEhZUC/D/XXy4r +4cOwBl14c/GXbc4AtgSZpsLAhoEMvkVKLvlFz9ROvUyWhAaSnUhdhHQXcYjq7M78W Av0vAr7sM9UvyMb9lFS79sYWoDMUd6NLqRoa+YyjVuf+jMmVGR1ojevgW5QXjSRNrG CbbiQOggMSfgBdEaMxXQq6/uPscz4Ad8mxTS/+5+dYVemLKkDPhXZdq7WIcYXPYw4D dblKI6MXASVTOqJvhlmyOwyP2MQkwDstJZm4wvBSzxNHs3Oqf7H76ozgOHcPIrafMr u0jbUW/HX0chw== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org, "Aneesh Kumar K.V (Arm)" , Marc Zyngier , Catalin Marinas , Will Deacon , Jonathan Cameron , Jason Gunthorpe , Dan Williams , Alexey Kardashevskiy , Samuel Ortiz , Xu Yilun , Suzuki K Poulose , Steven Price , Jonathan Cameron Subject: [RFC PATCH v3 06/10] coco: host: arm64: Instantiate RMM pdev during device connect Date: Thu, 12 Mar 2026 13:31:25 +0530 Message-ID: <20260312080129.3483585-7-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260312080129.3483585-1-aneesh.kumar@kernel.org> References: <20260312080129.3483585-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" An RMM pdev object represents a communication channel between the RMM and a physical device, for example a PCIe device. With the required helpers now in place, update the connect callback to create an RMM pdev object. Cc: Marc Zyngier Cc: Catalin Marinas Cc: Will Deacon Cc: Jonathan Cameron Cc: Jason Gunthorpe Cc: Dan Williams Cc: Alexey Kardashevskiy Cc: Samuel Ortiz Cc: Xu Yilun Cc: Suzuki K Poulose Cc: Steven Price Reviewed-by: Jonathan Cameron Signed-off-by: Aneesh Kumar K.V (Arm) --- drivers/virt/coco/arm-cca-host/arm-cca.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 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 4ed5e8ec9e91..987c1be566ba 100644 --- a/drivers/virt/coco/arm-cca-host/arm-cca.c +++ b/drivers/virt/coco/arm-cca-host/arm-cca.c @@ -67,8 +67,8 @@ 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) +static int init_dev_communication_buffers(struct pci_dev *pdev, + struct cca_host_comm_data *comm_data) { int ret =3D -ENOMEM; =20 @@ -172,6 +172,16 @@ static int cca_tsm_connect(struct pci_dev *pdev) if (rc) goto err_tsm; =20 + rc =3D init_dev_communication_buffers(pdev, &pf0_dsc->comm_data); + if (rc) + goto err_comm_buff; + rc =3D cca_pdev_create(pdev); + if (rc) + goto err_pdev_create; + + rc =3D cca_pdev_ide_setup(pdev); + if (rc) + goto err_ide_setup; /* * Once ide is setup, enable the stream at the endpoint * Root port will be done by RMM @@ -179,6 +189,12 @@ static int cca_tsm_connect(struct pci_dev *pdev) pci_ide_stream_enable(pdev, ide); return 0; =20 +err_ide_setup: + cca_pdev_stop_and_destroy(pdev); +err_pdev_create: + free_dev_communication_buffers(&pf0_dsc->comm_data); +err_comm_buff: + tsm_ide_stream_unregister(ide); err_tsm: pci_ide_stream_teardown(rp, ide); pci_ide_stream_teardown(pdev, ide); @@ -205,6 +221,9 @@ static void cca_tsm_disconnect(struct pci_dev *pdev) ide =3D pf0_dsc->sel_stream; stream_id =3D ide->stream_id; =20 + cca_pdev_stop_and_destroy(pdev); + free_dev_communication_buffers(&pf0_dsc->comm_data); + pci_ide_stream_release(ide); pf0_dsc->sel_stream =3D NULL; clear_bit(stream_id, cca_stream_ids); --=20 2.43.0 From nobody Tue Apr 7 18:00:32 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 114E12E718B; Thu, 12 Mar 2026 08:02:39 +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=1773302560; cv=none; b=JiW4/OKpqxL/OXE4++G6QPs46LYOz68FXxz9m4K1DDPYIQxknFQ8sl8jPk2n6ppYORhP/aoW/D4GlQG2xerUp0l3drcXz0tOjTC+7W415pblb+5XcZy7lF4hmXi4OmEw5CFD3mTGkJYjhmu9Lcr+G+BvrmFgDHdWT4WtQ19C2/c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773302560; c=relaxed/simple; bh=iT902Kks+8Y5KbHMSujhzXpOT2Flu5+M48nmim2dfB8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=fJTXHL+CK0RVqJsib4qQvPz7UoSlCLWKMJIXOQQi/kkn7SF1HUWXWWn42gG18F+9S3AOcpmIAXCYWXwO5t1B7Q0rj2rGz+MJenDSlKHUg7v/Volmleg517moCwBL6Jesyydxl4lUrk8CtqH/uqQoj5wMl8WOFNUgIixawtI7UNU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hWMkA/Ea; 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="hWMkA/Ea" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D1EEBC116C6; Thu, 12 Mar 2026 08:02:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773302559; bh=iT902Kks+8Y5KbHMSujhzXpOT2Flu5+M48nmim2dfB8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hWMkA/Ea6OIu1WDUL3C9QpZJXw7J8zW7YEFh882hbWj+cjUngEws4TWpm7wBMVZXy gQlSXscA3R/6QHuPORiOV9FeOsXJdEip7kIYZ5KTHHP4mX6hTcev+KRZvdIboruDLI MAw0Wf2LYk0ysQm2nhKhA+EIU4tZSBJaDvMRkl4MoXgb+/gpK64cvrkod9868J4YSq wQ1c3msyKg2GKa6grQSTN9b1t5KC8c4y5ZeDGLHwMLFB4F/6rOIkCZ30IokcrUgkus lc/jd7UglBbDtzg/A4Fo3Z5/xlXPBav4wkK5ok828dr2zUrFIDksEEVv8m+xnhLd00 zOMp9nNLqF4pQ== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org, Lukas Wunner , Dan Williams , =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= , Jonathan Cameron , "Aneesh Kumar K . V" Subject: [RFC PATCH v3 07/10] X.509: Make certificate parser public Date: Thu, 12 Mar 2026 13:31:26 +0530 Message-ID: <20260312080129.3483585-8-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260312080129.3483585-1-aneesh.kumar@kernel.org> References: <20260312080129.3483585-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 Tue Apr 7 18:00:32 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 B02792E718B; Thu, 12 Mar 2026 08:02:44 +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=1773302564; cv=none; b=YCpYB0bKyXWt+NUzmzn9iQ+tuNlcVjXUaXu4WEQzFbNREknRtu97m9oPns9s6MJq4YZLMmqf4qsl7fMD2qCTWiWRMXH9l60v1X0IhpRBK0f6XxbiSYNRFliUEMo+qNDAaDK9tfZZf9FFSfdS0+CuXAGC7DnAB3ebi/DlQCxr4hY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773302564; c=relaxed/simple; bh=rj2gZrREi98L5OW7DVFeQ4A3D6mJm8/gxjqIgpOv8+4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=SOUceDfQvq0HDCTjVM04/a4p3z+2uV9iqsE2rkrWkStYCvnEUDPxAEx149+8ePXpFuw73SQyAZid/aTHOGu8GSbp37+Al5phA5qQ8zBRbhw+R91GVnsuK+ux4duADMFrsXMW6hFqrQ1C/sugGKOUrQ4Ra31iEROOJNHiVaD1Wwk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=mCCgYEnN; 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="mCCgYEnN" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8D6D1C2BCAF; Thu, 12 Mar 2026 08:02:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773302564; bh=rj2gZrREi98L5OW7DVFeQ4A3D6mJm8/gxjqIgpOv8+4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mCCgYEnN4wxBqbiELTtD0Q7L1zRqUtOHaqxSGbRTDlja+it7z4nj/jPPjtfiMM8eR R4DEFYXR/85OcR9uN7U+KqmlyCklYGLl7+CIIhvgKw+DCRZyk0iOSMxS8XtTPm7AiJ XwCe99MN8IJpYfX2fZTrwZCxTx9huehSdWR/+aXUHcp0RyNSuYPhRfj9GU8/BhQCTV ImvN2W2g717TVK8WERXJjklq/kDQImPCeUkjYPD4KnOPtbnRDmE9G+6MWgdLNWOuTT IBzBQhrM/4B8Cea52U+5+vwPGLb4yvF2SEElhw5e5fND6VS5NvvNivulu4XoeFd+IY IMKHWjgQHWuxA== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org, Lukas Wunner , Wilfred Mallawa , =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= , Jonathan Cameron , Dan Williams , "Aneesh Kumar K . V" Subject: [RFC PATCH v3 08/10] X.509: Parse Subject Alternative Name in certificates Date: Thu, 12 Mar 2026 13:31:27 +0530 Message-ID: <20260312080129.3483585-9-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260312080129.3483585-1-aneesh.kumar@kernel.org> References: <20260312080129.3483585-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 Tue Apr 7 18:00:32 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 02DFC2D949F; Thu, 12 Mar 2026 08:02:49 +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=1773302569; cv=none; b=pOTelvka2nIhgbI6+kpl3VU+5OxJ6q0CayWjYDfQe3xL19U8HYc69VU4tOx1q+DBAUXhd6Qyfds+WAQFV5TiBTIQ8vtZ+lybn6FWZtvfJSJqaS060yEXFCmMZ/0wZ8wa9mwuA7xxJ/JB6QicBaS2Jl13expKDRYTOJFdKOR5Uqk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773302569; c=relaxed/simple; bh=ffDcIy1rll5TndwARYJlNX/u1R7dPKivglLlkq9yNX4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TI2zd3UPxQltj2TPZYnvBvqTHDC5GjDR3UiRYdWuobhOGFBoJIdFQL4JobqqhmhmmvxwnSprydZlEEnPvag91jlA6SLx5YV42JHRXHDOddhyzzcqPz5TfVG+bphB9yUYTcDrzzZFZQRxB3rf3Ap0Pa8uFXXjYWkX+Rs+j7kUw2Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=AuZK/d6n; 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="AuZK/d6n" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 740BDC2BC87; Thu, 12 Mar 2026 08:02:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773302568; bh=ffDcIy1rll5TndwARYJlNX/u1R7dPKivglLlkq9yNX4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=AuZK/d6nV1QqYVL/mEjm7FM/y2cM5OYjevf2ZE9HjLYN1A+Wq3Zzne/EQbNlknEnh 8MDc66yB+VK/ViUmJKV7K/oitN6hX2LZI5IGMHgnLVGek4L1oO65hspoTUR01N++hX rCCvaYXFB+3pmCUsj7gfaOb4o/QwJWbdDvcrpQXgVWIOitCcOkfP7hKi3hSpDcFqSL wZmtrvDILniubCUvdo2SrbtpvKSYXRzjBZ9WnQHJLC6L+Kd97QND4oi63+Ztj/KJl6 x1rqQv2JCRHcz9N3p5qhXNIiGkvkMc4yV2vGCipi+VWb8zMeKN5LLkeVLJrwlurLCP jByWmuAqWa2Jg== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org, Lukas Wunner , Dan Williams , Jonathan Cameron , "Aneesh Kumar K . V" Subject: [RFC PATCH v3 09/10] X.509: Move certificate length retrieval into new helper Date: Thu, 12 Mar 2026 13:31:28 +0530 Message-ID: <20260312080129.3483585-10-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260312080129.3483585-1-aneesh.kumar@kernel.org> References: <20260312080129.3483585-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 Tue Apr 7 18:00:32 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 E3DF82F6911; Thu, 12 Mar 2026 08:02:56 +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=1773302577; cv=none; b=o6L4PSlxml4qTLZiWarTxyIhhFNJ58twU4O+KTDc5KVQzi9FuG8P5AdWM0JjN0Ctmj9xoGPLO+l/uK6eJ9tcdy0Qi6+bBkaVxuc9IFR2TvLpZjG18E6NJmHu1PRzuL3Gt2d1x6smxX5u7zX4Oc1+dnk8TnfvzxCnoR2D4mesmUU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773302577; c=relaxed/simple; bh=VUOalaLBOiIjNU7HAVFo9dX7mrBFsxxsTy0R3pqsmiE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=INw8qYrAE2PSlA4uyg5VL938LoOJmupwl+GSW2Zt//N00BFYz9plrjdHWhmjx5BsxCwcl+4JqdqCOBlE54b9hSGDqjdfjQeY3fBQ1blgUOWYR0NW7+vAjcLGLmPLZWXfcB7pa0hkJuSeNqmjrqUVSsax1DwNaCMRhRtXnZGiS1s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=c8yyNa4V; 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="c8yyNa4V" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C0403C116C6; Thu, 12 Mar 2026 08:02:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773302576; bh=VUOalaLBOiIjNU7HAVFo9dX7mrBFsxxsTy0R3pqsmiE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=c8yyNa4VyLTf0tyCFwWp0S3qHwqgkTAfm0cRv9O1syDi+2BWEl29J9apIZpUqM0+5 ow9zb4swvsbprvRm/6ho2KsDLbsWQX2+DCN3dUgjIntvDOO+5jmrJVqFTexgwqYi2A F+BTW+NWJu0gRno013nGvUk1Mp6pgxYMPNiJBQqmPEfG/Bd4nChFPz9qeXjDE0syIv se6ksweIXnnulu8JqHhSkO6AK9jAluigEWpFUbXe93E3U59e5l57Pq6cq6NMSAA4wK G9U361IcRaWarYkkcSV8KxCFUcuPDTZ+5Th2cDX8Z+UW95Qq8UrArqeAHbcO6H4o+A 4jAGYHtoNWDrg== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org, "Aneesh Kumar K.V (Arm)" , Marc Zyngier , Catalin Marinas , Will Deacon , Jonathan Cameron , Jason Gunthorpe , Dan Williams , Alexey Kardashevskiy , Samuel Ortiz , Xu Yilun , Suzuki K Poulose , Steven Price Subject: [RFC PATCH v3 10/10] coco: host: arm64: Register device public key with RMM Date: Thu, 12 Mar 2026 13:31:29 +0530 Message-ID: <20260312080129.3483585-11-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260312080129.3483585-1-aneesh.kumar@kernel.org> References: <20260312080129.3483585-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 IDE 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. Cc: Marc Zyngier Cc: Catalin Marinas Cc: Will Deacon Cc: Jonathan Cameron Cc: Jason Gunthorpe Cc: Dan Williams Cc: Alexey Kardashevskiy Cc: Samuel Ortiz Cc: Xu Yilun Cc: Suzuki K Poulose Cc: Steven Price Signed-off-by: Aneesh Kumar K.V (Arm) --- arch/arm64/include/asm/rmi_cmds.h | 9 ++ arch/arm64/include/asm/rmi_smc.h | 18 +++ drivers/virt/coco/arm-cca-host/Kconfig | 4 + drivers/virt/coco/arm-cca-host/rmi-da.c | 174 +++++++++++++++++++++++- drivers/virt/coco/arm-cca-host/rmi-da.h | 2 + 5 files changed, 206 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/rmi_cmds.h b/arch/arm64/include/asm/rmi= _cmds.h index f10a0dcaa308..339bea517760 100644 --- a/arch/arm64/include/asm/rmi_cmds.h +++ b/arch/arm64/include/asm/rmi_cmds.h @@ -574,4 +574,13 @@ static inline unsigned long rmi_pdev_destroy(unsigned = long 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 3a57c7245029..907e00f4855a 100644 --- a/arch/arm64/include/asm/rmi_smc.h +++ b/arch/arm64/include/asm/rmi_smc.h @@ -52,6 +52,7 @@ #define SMC_RMI_PDEV_CREATE SMC_RMI_CALL(0x0176) #define SMC_RMI_PDEV_DESTROY SMC_RMI_CALL(0x0177) #define SMC_RMI_PDEV_GET_STATE SMC_RMI_CALL(0x0178) +#define SMC_RMI_PDEV_SET_PUBKEY SMC_RMI_CALL(0x017b) #define SMC_RMI_PDEV_STOP SMC_RMI_CALL(0x017c) =20 #define RMI_ABI_MAJOR_VERSION 1 @@ -427,4 +428,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; + } __packed; + 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 ba6d67e5f54e..029758ada136 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 @@ -386,6 +389,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 parse_certificate_chain(struct pci_tsm *tsm) +{ + struct cca_host_pf0_dsc *pf0_dsc; + unsigned int chain_size; + unsigned int offset =3D 0; + u8 *chain_data; + + pf0_dsc =3D to_cca_pf0_dsc(tsm->pdev); + + /* If device communication didn't results in certificate caching. */ + if (!pf0_dsc->cert_chain.cache || !pf0_dsc->cert_chain.cache->offset) + return -EINVAL; + + chain_size =3D pf0_dsc->cert_chain.cache->offset; + chain_data =3D pf0_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_dsc->rmi_signature_algorithm =3D RMI_SIG_ECDSA_P256; + } else if (!strcmp("ecdsa-nist-p384", cert->pub->pkey_algo)) { + pf0_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_dsc->rmi_signature_algorithm =3D RMI_SIG_RSASSA_3072; + } else { + return -EINVAL; + } + + memcpy(public_key, cert->pub->key, cert->pub->keylen); + pf0_dsc->cert_chain.public_key =3D no_free_ptr(public_key); + pf0_dsc->cert_chain.public_key_size =3D cert->pub->keylen; + pf0_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 pdev_set_public_key(struct pci_tsm *tsm) +{ + struct cca_host_pf0_dsc *pf0_dsc; + + pf0_dsc =3D to_cca_pf0_dsc(tsm->pdev); + /* Check that all the necessary information was captured from communicati= on */ + if (!pf0_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_dsc->rmi_signature_algorithm; + + switch (key_params->rmi_signature_algorithm) { + case RMI_SIG_ECDSA_P384: + case RMI_SIG_ECDSA_P256: + { + key_params->public_key_len =3D pf0_dsc->cert_chain.public_key_size; + memcpy(key_params->public_key, + pf0_dsc->cert_chain.public_key, + pf0_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_dsc->cert_chain.public_key, + pf0_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_dsc->rmm_pdev), + virt_to_phys(key_params))) + return -ENXIO; + return 0; +} + static void pdev_state_transition_workfn(struct work_struct *work) { unsigned long state; @@ -433,7 +588,24 @@ static int submit_pdev_state_transition_work(struct pc= i_dev *pdev, int target_st =20 int cca_pdev_ide_setup(struct pci_dev *pdev) { - return submit_pdev_state_transition_work(pdev, RMI_PDEV_NEEDS_KEY); + int ret; + + ret =3D submit_pdev_state_transition_work(pdev, RMI_PDEV_NEEDS_KEY); + if (ret) + return 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); } =20 void cca_pdev_stop_and_destroy(struct pci_dev *pdev) diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.h b/drivers/virt/coco/ar= m-cca-host/rmi-da.h index fbfbcd40beb4..38550103c2a5 100644 --- a/drivers/virt/coco/arm-cca-host/rmi-da.h +++ b/drivers/virt/coco/arm-cca-host/rmi-da.h @@ -49,6 +49,7 @@ struct cca_host_comm_data { * @rmm_pdev: Delegated granule address of rmm pdev object * @num_ax: Number of auxiliary granules allocated for pdev * @aux: Delegated auxiliary granules + * @rmi_signature_algorithm: Signature algorithm used for public key * @object_lock: lock used to protect access to cached obects in PF0 and T= DIs * @cert_chain: cetrificate chain * @vca: SPDM's Version-Capabilities-Algorithms cache object @@ -62,6 +63,7 @@ struct cca_host_pf0_dsc { int num_aux; void *aux[MAX_PDEV_AUX_GRANULES]; =20 + uint8_t rmi_signature_algorithm; struct mutex object_lock; struct { struct cache_object *cache; --=20 2.43.0