From nobody Thu Jun 11 03:18:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2EA613976A7; Mon, 27 Apr 2026 08:28:19 +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=1777278499; cv=none; b=qp6uyo/1XzWkYXmXoSNRoH0DrFVKO0/Y0c/L52VKUHUCf+8u2r0h76wJ2ydN/lsrqhl2usRjLwMEQxVMSkOtE01qlUbK1pSh56XqR8ZubOEvguVaQ+U3P6A3y+Njk6JNe+R5N+mkrecypknzDs78FAxonGsQUY+mVmOxcq/vJV4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777278499; c=relaxed/simple; bh=lybotH1aprjln0PLII4oso8/TTzjYe9+EWScaClR5DE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lGxmXDdtI0AL+BtKyTsfUNiPtIGxGxt73O/Iz7Z9936ew73vg/3ZSgLaNQxe0LejaLvLxaBxlUTguagQ2ncHEqRiQO466cT/GtzJ44sA+slIrBnjIJlU/PVaDYlc/UhhxHXzifb9U62vZ8H5OMlwYccDbVTTngULmxRYcJCD3qI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=gCMJTZ3T; 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="gCMJTZ3T" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6A6E4C19425; Mon, 27 Apr 2026 08:28:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777278499; bh=lybotH1aprjln0PLII4oso8/TTzjYe9+EWScaClR5DE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gCMJTZ3TQERWQUjQsDMdBEVxy2QmSCgZ1Bl9vYWTEHDOVB3aUEgwAUHIFg4BBG1wx Sl0y92uqSbGpQnuFRBtt+lJ0o66xN67YrE0w2OE8f6TnH/5wpOvjns7TXDm8nlHGR1 T1gs/rZK6sPpq5oQjQoVZg9/ZGfTrh6jG5VutKuUlBd49sTRJWnh4mZB6tUoLHaCMh jl8s2GBHuPmcxThc/jXdZJf1in7Ydx6s0aS/6a9MHG/Qpq3l2LCsh5ctql9xrrEb1w A8hKYWBv7MRDr77R6nl4RcnzxgANJVBGXbfccyrPgXde4B4DnMr1lF97Ed9ljuneG+ XvAyETZstrtLA== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Alexey Kardashevskiy , Catalin Marinas , Dan Williams , Jason Gunthorpe , Jonathan Cameron , Marc Zyngier , Samuel Ortiz , Steven Price , Suzuki K Poulose , Will Deacon , Xu Yilun Subject: [RFC PATCH v4 01/11] coco: guest: arm64: Guest TSM callback and realm device lock support Date: Mon, 27 Apr 2026 13:57:55 +0530 Message-ID: <20260427082805.931832-2-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260427082805.931832-1-aneesh.kumar@kernel.org> References: <20260427082805.931832-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 RSI. The build order is also adjusted so that the TSM class is created before the arm-cca-guest driver is initialized. In addition, add support for the TDISP lock sequence. Writing a TSM (TEE Security Manager) device name from `/sys/class/tsm` into `tsm/lock` triggers the realm device lock operation. Signed-off-by: Aneesh Kumar K.V (Arm) --- arch/arm64/include/asm/rsi.h | 1 + arch/arm64/include/asm/rsi_cmds.h | 17 +++++++ arch/arm64/include/asm/rsi_smc.h | 1 + arch/arm64/kernel/rsi.c | 10 ++++ drivers/virt/coco/Makefile | 2 +- drivers/virt/coco/arm-cca-guest/Kconfig | 5 ++ drivers/virt/coco/arm-cca-guest/arm-cca.c | 60 ++++++++++++++++++++++- drivers/virt/coco/arm-cca-guest/rsi-da.h | 35 +++++++++++++ 8 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 drivers/virt/coco/arm-cca-guest/rsi-da.h diff --git a/arch/arm64/include/asm/rsi.h b/arch/arm64/include/asm/rsi.h index 34c8f649fe48..f5288551ae77 100644 --- a/arch/arm64/include/asm/rsi.h +++ b/arch/arm64/include/asm/rsi.h @@ -68,5 +68,6 @@ static inline int rsi_set_memory_range_shared(phys_addr_t= start, RSI_CHANGE_DESTROYED); } =20 +bool rsi_has_da_feature(void); unsigned long realm_get_hyp_pagesize(void); #endif /* __ASM_RSI_H_ */ diff --git a/arch/arm64/include/asm/rsi_cmds.h b/arch/arm64/include/asm/rsi= _cmds.h index a341ce0eeda1..596bdc356f1a 100644 --- a/arch/arm64/include/asm/rsi_cmds.h +++ b/arch/arm64/include/asm/rsi_cmds.h @@ -169,4 +169,21 @@ static inline unsigned long rsi_host_call(struct rsi_h= ost_call *rhi_call) return res.a0; } =20 +/** + * rsi_features() - Read feature register + * @index: Feature register index + * @out: Feature register value is written to this pointer + * + * Return: RSI return code + */ +static inline unsigned long rsi_features(unsigned long index, u64 *out) +{ + struct arm_smccc_res res; + + arm_smccc_1_1_invoke(SMC_RSI_FEATURES, index, &res); + + *out =3D res.a1; + return res.a0; +} + #endif /* __ASM_RSI_CMDS_H */ diff --git a/arch/arm64/include/asm/rsi_smc.h b/arch/arm64/include/asm/rsi_= smc.h index 9ee8b5c7612e..4af4638fdd49 100644 --- a/arch/arm64/include/asm/rsi_smc.h +++ b/arch/arm64/include/asm/rsi_smc.h @@ -53,6 +53,7 @@ */ #define SMC_RSI_ABI_VERSION SMC_RSI_FID(0x190) =20 +#define RSI_FEATURE_REGISTER_0_DA BIT(0) /* * Read feature register. * diff --git a/arch/arm64/kernel/rsi.c b/arch/arm64/kernel/rsi.c index e49318469632..a3cd27bf82e8 100644 --- a/arch/arm64/kernel/rsi.c +++ b/arch/arm64/kernel/rsi.c @@ -17,6 +17,7 @@ #include =20 static struct realm_config config; +static u64 rsi_feat_reg0; static unsigned long ipa_change_alignment =3D PAGE_SIZE; =20 unsigned long prot_ns_shared; @@ -25,6 +26,12 @@ EXPORT_SYMBOL(prot_ns_shared); DEFINE_STATIC_KEY_FALSE_RO(rsi_present); EXPORT_SYMBOL(rsi_present); =20 +bool rsi_has_da_feature(void) +{ + return u64_get_bits(rsi_feat_reg0, RSI_FEATURE_REGISTER_0_DA); +} +EXPORT_SYMBOL_GPL(rsi_has_da_feature); + bool cc_platform_has(enum cc_attr attr) { switch (attr) { @@ -160,6 +167,9 @@ void __init arm64_rsi_init(void) if (!ipa_change_alignment) return; =20 + if (WARN_ON(rsi_features(0, &rsi_feat_reg0))) + return; + prot_ns_shared =3D __phys_to_pte_val(BIT(config.ipa_bits - 1)); =20 if (arm64_ioremap_prot_hook_register(realm_ioremap_hook)) diff --git a/drivers/virt/coco/Makefile b/drivers/virt/coco/Makefile index b323b0ae4f82..4f7e30f5aeb8 100644 --- a/drivers/virt/coco/Makefile +++ b/drivers/virt/coco/Makefile @@ -7,6 +7,6 @@ obj-$(CONFIG_ARM_PKVM_GUEST) +=3D pkvm-guest/ obj-$(CONFIG_SEV_GUEST) +=3D sev-guest/ obj-$(CONFIG_INTEL_TDX_GUEST) +=3D tdx-guest/ 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_GUEST) +=3D arm-cca-guest/ diff --git a/drivers/virt/coco/arm-cca-guest/Kconfig b/drivers/virt/coco/ar= m-cca-guest/Kconfig index a42359a90558..5f7f284dae1a 100644 --- a/drivers/virt/coco/arm-cca-guest/Kconfig +++ b/drivers/virt/coco/arm-cca-guest/Kconfig @@ -1,11 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0-only +# + config ARM_CCA_GUEST tristate "Arm CCA Guest driver" depends on ARM64 + select PCI_TSM if PCI select TSM_REPORTS select AUXILIARY_BUS help The driver provides userspace interface to request and attestation report from the Realm Management Monitor(RMM). + If the DA feature is supported, it also register with TSM framework. =20 If you choose 'M' here, this module will be called arm-cca-guest. diff --git a/drivers/virt/coco/arm-cca-guest/arm-cca.c b/drivers/virt/coco/= arm-cca-guest/arm-cca.c index 7daada072cc0..6f13c54fab73 100644 --- a/drivers/virt/coco/arm-cca-guest/arm-cca.c +++ b/drivers/virt/coco/arm-cca-guest/arm-cca.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2023 ARM Ltd. + * Copyright (C) 2023-2026 ARM Ltd. */ =20 #include @@ -15,6 +15,10 @@ =20 #include =20 +#ifdef CONFIG_PCI_TSM +#include "rsi-da.h" +#endif + /** * struct arm_cca_token_info - a descriptor for the token buffer. * @challenge: Pointer to the challenge data @@ -192,6 +196,53 @@ static void unregister_cca_tsm_report(void *data) tsm_report_unregister(&arm_cca_tsm_report_ops); } =20 +#ifdef CONFIG_PCI_TSM +static struct pci_tsm *cca_tsm_lock(struct tsm_dev *tsm_dev, struct pci_de= v *pdev) +{ + int ret; + + struct cca_guest_dsc *cca_dsc __free(kfree) =3D + kzalloc_obj(struct cca_guest_dsc); + if (!cca_dsc) + return ERR_PTR(-ENOMEM); + + ret =3D pci_tsm_devsec_constructor(pdev, &cca_dsc->pci, tsm_dev); + if (ret) + return ERR_PTR(ret); + + /* For now always return an error */ + return ERR_PTR(-EIO); +} + +static void cca_tsm_unlock(struct pci_tsm *tsm) +{ + struct cca_guest_dsc *cca_dsc =3D to_cca_guest_dsc(tsm->pdev); + + kfree(cca_dsc); +} + +static struct pci_tsm_ops cca_devsec_pci_ops =3D { + .lock =3D cca_tsm_lock, + .unlock =3D cca_tsm_unlock, +}; + +static void cca_devsec_tsm_remove(void *tsm_dev) +{ + tsm_unregister(tsm_dev); +} + +static int cca_devsec_tsm_register(struct auxiliary_device *adev) +{ + struct tsm_dev *tsm_dev; + + tsm_dev =3D tsm_register(&adev->dev, &cca_devsec_pci_ops); + if (IS_ERR(tsm_dev)) + return PTR_ERR(tsm_dev); + + return devm_add_action_or_reset(&adev->dev, cca_devsec_tsm_remove, tsm_de= v); +} +#endif /* CONFIG_PCI_TSM */ + static int cca_devsec_tsm_probe(struct auxiliary_device *adev, const struct auxiliary_device_id *id) { @@ -212,6 +263,12 @@ static int cca_devsec_tsm_probe(struct auxiliary_devic= e *adev, return ret; } =20 +#ifdef CONFIG_PCI_TSM + /* Allow tsm report even if tsm_register fails */ + if (rsi_has_da_feature()) + cca_devsec_tsm_register(adev); +#endif + return 0; } =20 @@ -227,5 +284,6 @@ static struct auxiliary_driver cca_devsec_tsm_driver = =3D { }; module_auxiliary_driver(cca_devsec_tsm_driver); MODULE_AUTHOR("Sami Mujawar "); +MODULE_AUTHOR("Aneesh Kumar "); MODULE_DESCRIPTION("Arm CCA Guest TSM Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/virt/coco/arm-cca-guest/rsi-da.h b/drivers/virt/coco/a= rm-cca-guest/rsi-da.h new file mode 100644 index 000000000000..858bfdaf59c9 --- /dev/null +++ b/drivers/virt/coco/arm-cca-guest/rsi-da.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2026 ARM Ltd. + */ + +#ifndef _VIRT_COCO_RSI_DA_H_ +#define _VIRT_COCO_RSI_DA_H_ + +#include +#include +#include + +struct cca_guest_dsc { + struct pci_tsm_devsec pci; +}; + +static inline struct cca_guest_dsc *to_cca_guest_dsc(struct pci_dev *pdev) +{ + struct pci_tsm *tsm =3D pdev->tsm; + + if (!tsm) + return NULL; + return container_of(tsm, struct cca_guest_dsc, pci.base_tsm); +} + +/* + * Linux use device requester id as the vdev id. + */ +static inline int rsi_vdev_id(struct pci_dev *pdev) +{ + return (pci_domain_nr(pdev->bus) << 16) | + PCI_DEVID(pdev->bus->number, pdev->devfn); +} + +#endif --=20 2.43.0 From nobody Thu Jun 11 03:18:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 75C5239B4BB; Mon, 27 Apr 2026 08:28:24 +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=1777278504; cv=none; b=P5EUPWT8eRGXfGTsbkr43b941QYmHttaivH9QEhGqYs5Dr2q/Gusozraad3oiSgd982h6KsBsQzpZ3p9rvROeAQxvXSyaYYhUyvSbyRKW345myPxf8Z/tus/8oruAlc02c9Mn+YfwHQUkT3KrCC5CS2ywVrF3A/apf87HmxfQ68= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777278504; c=relaxed/simple; bh=ozzuj0X/PtzwBrR765l0/YzAmLPg8mI7Pw/GI5p4YRg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ppLzDMDkNaSkDPzb/yf3RPS/S2esYkNHLdcUa1TJMquqH35HF6T6BGCf65qvsosUZeOQq9xlJ/TFThBfy5aEzn2zS6+/mFQPj0OAZL/DOOGwYdnlR+99Yc44G41qidYeV8QcNmAelldUgaE69D7w48xrWKXZzLTYgrmX60u9B2k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qABbb+zS; 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="qABbb+zS" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A8ECBC2BCB8; Mon, 27 Apr 2026 08:28:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777278504; bh=ozzuj0X/PtzwBrR765l0/YzAmLPg8mI7Pw/GI5p4YRg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qABbb+zS7pJg/PB72zJd5lhhRbJrAX0d22Sr/Hon2QDiDKCdOJgHXXcIwcwGOa+Xc oUqh0nZidU1Andz/gCaMgXjodzgyDBYSyLQYXoFsl8WRR5XTp7Ke8nl+FF14OicnAg Uc5u+ZM34NrCkin0Bhylbg4GHgTQK0f7EDSf3Ece9R0prnWq6yC0KeSAyTtljVIxC7 i0Kld02dkRTPJoTh55kxnMRZd5J+OrOMMB80Gk+CPmLgXGgm+PwPM1g40Wl4y3dFAQ kiFi2BtcM9bAAkAC4PLWmhmwxbGh7JTg9CsMGjL09Z+pQSgIWcXxGU3MYtxpaD8j13 Hddm8tWpOlGIw== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Alexey Kardashevskiy , Catalin Marinas , Dan Williams , Jason Gunthorpe , Jonathan Cameron , Marc Zyngier , Samuel Ortiz , Steven Price , Suzuki K Poulose , Will Deacon , Xu Yilun Subject: [RFC PATCH v4 02/11] coco: guest: arm64: Fix a typo in the ARM_CCA_GUEST Kconfig help string ("and" -> "an"). Date: Mon, 27 Apr 2026 13:57:56 +0530 Message-ID: <20260427082805.931832-3-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260427082805.931832-1-aneesh.kumar@kernel.org> References: <20260427082805.931832-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" Fix a typo in Kconfig file. Signed-off-by: Aneesh Kumar K.V (Arm) --- drivers/virt/coco/arm-cca-guest/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/virt/coco/arm-cca-guest/Kconfig b/drivers/virt/coco/ar= m-cca-guest/Kconfig index 5f7f284dae1a..d295146bd92a 100644 --- a/drivers/virt/coco/arm-cca-guest/Kconfig +++ b/drivers/virt/coco/arm-cca-guest/Kconfig @@ -8,7 +8,7 @@ config ARM_CCA_GUEST select TSM_REPORTS select AUXILIARY_BUS help - The driver provides userspace interface to request and + The driver provides userspace interface to request an attestation report from the Realm Management Monitor(RMM). If the DA feature is supported, it also register with TSM framework. =20 --=20 2.43.0 From nobody Thu Jun 11 03:18:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F0FD8314D26; Mon, 27 Apr 2026 08:28:29 +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=1777278510; cv=none; b=JTpRbyrETsyNjiAaN/Jrfq0OvUivdmoHiz6moxb7xZEz2MnmKOjN38ENUgxaBZ0HDY5t6f9AW39NI3jusGYzH/CH5QfaA9UBf03Nssx4T10UPH404iygSJmMMueHsCEwFYp5kSW2KXUdygVOVgt04mNXh0di8StmNvmREL25ksM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777278510; c=relaxed/simple; bh=r0yVakx/gXEjh2q8rhYrMYY91oldXQK13RYw+6V38lY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uMF8oo3YdPUCPaXMRaqb2dZQkEuvkthDKLOQPU8N1w5wI1voCS9PKOZXm/KQpUuAihmnSBG6LwyCLlbYqPOsZXUnaMPQ2pjcv38EXKGVM2pg4H+UEUciuXUhLb4Cny7iyKJvRs7uxmztBPb5aGuUiwMxrB4oDWou+Iv+T/B3hmI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=W4SLoYUP; 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="W4SLoYUP" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EEC02C2BCC7; Mon, 27 Apr 2026 08:28:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777278509; bh=r0yVakx/gXEjh2q8rhYrMYY91oldXQK13RYw+6V38lY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=W4SLoYUPkrX78aoqQueMVG4qt48cDh/l1gLoqOje9/kLSMMboLNEJwBcRhNEwsrld hbNuoi87qelcJO5BmqrW5f3eR7+6ixvCYm39grUwFj1TUEd3ThL2nobNif7GjVgwoe 9rCvJn8SQBAvzYyPQawOnDt29dvwS9YhuqPFsocB/68tKFN115s3job6WT0dCa0Dqt 2RoX4wFskuRro/ZPA4798IfKnESjN+UArIaWnHEkQFb2lAjz/fdHDf5aktpCI+PEgJ ByraFbTNc8wXAMeAIsBVV32m9qnue//vnH663zW2ogHL+u6W8j/wPnpp5vrumQXAeP vZVaG9dL7Z3Dw== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Alexey Kardashevskiy , Catalin Marinas , Dan Williams , Jason Gunthorpe , Jonathan Cameron , Marc Zyngier , Samuel Ortiz , Steven Price , Suzuki K Poulose , Will Deacon , Xu Yilun Subject: [RFC PATCH v4 03/11] coco: guest: arm64: Add Realm Host Interface and guest DA helper Date: Mon, 27 Apr 2026 13:57:57 +0530 Message-ID: <20260427082805.931832-4-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260427082805.931832-1-aneesh.kumar@kernel.org> References: <20260427082805.931832-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 guest-side rhi-da helper that drives the vdev TDI state machine via RHI host calls and translates the firmware status codes This provides the basic RHI plumbing that later DA features rely on. Signed-off-by: Aneesh Kumar K.V (Arm) --- arch/arm64/include/asm/rhi.h | 38 +++++ drivers/virt/coco/arm-cca-guest/Makefile | 1 + drivers/virt/coco/arm-cca-guest/arm-cca.c | 3 +- drivers/virt/coco/arm-cca-guest/rhi-da.c | 163 ++++++++++++++++++++++ drivers/virt/coco/arm-cca-guest/rhi-da.h | 14 ++ 5 files changed, 218 insertions(+), 1 deletion(-) create mode 100644 drivers/virt/coco/arm-cca-guest/rhi-da.c create mode 100644 drivers/virt/coco/arm-cca-guest/rhi-da.h diff --git a/arch/arm64/include/asm/rhi.h b/arch/arm64/include/asm/rhi.h index 0895dd92ea1d..88de2d9b34d1 100644 --- a/arch/arm64/include/asm/rhi.h +++ b/arch/arm64/include/asm/rhi.h @@ -21,4 +21,42 @@ unsigned long rhi_get_ipa_change_alignment(void); #define __RHI_HOSTCONF_GET_IPA_CHANGE_ALIGNMENT BIT(0) #define RHI_HOSTCONF_FEATURES SMC_RHI_CALL(0x004F) #define RHI_HOSTCONF_GET_IPA_CHANGE_ALIGNMENT SMC_RHI_CALL(0x0050) + +#define RHI_DA_SUCCESS 0x0 +#define RHI_DA_INCOMPLETE 0x1 +#define RHI_DA_ERROR_DATA_NOT_AVAILABLE 0x2 +#define RHI_DA_ERROR_INVALID_VDEV_ID 0x3 +#define RHI_DA_ERROR_INVALID_OBJECT 0x4 +#define RHI_DA_ERROR_INPUT 0x5 +#define RHI_DA_ERROR_DEVICE 0x6 +#define RHI_DA_ERROR_INVALID_OFFSET 0x7 +#define RHI_DA_ERROR_ACCESS_FAILED 0x8 +#define RHI_DA_ERROR_BUSY 0x9 +#define RHI_DA_ABORTED_OPERATION_HAD_COMPLETED 0xA + +#define RHI_DA_FEATURE_OBJECT_SIZE BIT(0) +#define RHI_DA_FEATURE_OBJECT_READ BIT(1) +#define RHI_DA_FEATURE_VDEV_CONTINUE BIT(2) +#define RHI_DA_FEATURE_VDEV_GET_MEASUREMENT BIT(3) +#define RHI_DA_FEATURE_VDEV_GET_INTF_REPORT BIT(4) +#define RHI_DA_FEATURE_VDEV_SET_TDI_STATE BIT(5) + +#define RHI_DA_BASE_FEATURE (RHI_DA_FEATURE_OBJECT_SIZE | \ + RHI_DA_FEATURE_OBJECT_READ | \ + RHI_DA_FEATURE_VDEV_GET_INTF_REPORT | \ + RHI_DA_FEATURE_VDEV_GET_MEASUREMENT | \ + RHI_DA_FEATURE_VDEV_SET_TDI_STATE) +#define RHI_DA_FEATURES SMC_RHI_CALL(0x004B) + +#define RHI_DA_VDEV_CONTINUE SMC_RHI_CALL(0x0051) + +enum rhi_tdi_state { + RHI_DA_TDI_CONFIG_UNLOCKED, + RHI_DA_TDI_CONFIG_LOCKED, + RHI_DA_TDI_CONFIG_RUN, +}; +#define RHI_DA_VDEV_SET_TDI_STATE SMC_RHI_CALL(0x0054) + +#define RHI_DA_VDEV_ABORT SMC_RHI_CALL(0x0056) + #endif diff --git a/drivers/virt/coco/arm-cca-guest/Makefile b/drivers/virt/coco/a= rm-cca-guest/Makefile index 75a120e24fda..65c4cc52c154 100644 --- a/drivers/virt/coco/arm-cca-guest/Makefile +++ b/drivers/virt/coco/arm-cca-guest/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_ARM_CCA_GUEST) +=3D arm-cca-guest.o =20 arm-cca-guest-y +=3D arm-cca.o +arm-cca-guest-$(CONFIG_PCI_TSM) +=3D rhi-da.o diff --git a/drivers/virt/coco/arm-cca-guest/arm-cca.c b/drivers/virt/coco/= arm-cca-guest/arm-cca.c index 6f13c54fab73..0c12aae85e6d 100644 --- a/drivers/virt/coco/arm-cca-guest/arm-cca.c +++ b/drivers/virt/coco/arm-cca-guest/arm-cca.c @@ -17,6 +17,7 @@ =20 #ifdef CONFIG_PCI_TSM #include "rsi-da.h" +#include "rhi-da.h" #endif =20 /** @@ -265,7 +266,7 @@ static int cca_devsec_tsm_probe(struct auxiliary_device= *adev, =20 #ifdef CONFIG_PCI_TSM /* Allow tsm report even if tsm_register fails */ - if (rsi_has_da_feature()) + if (rsi_has_da_feature() && rhi_has_da_support()) cca_devsec_tsm_register(adev); #endif =20 diff --git a/drivers/virt/coco/arm-cca-guest/rhi-da.c b/drivers/virt/coco/a= rm-cca-guest/rhi-da.c new file mode 100644 index 000000000000..5b48c8d6ebe3 --- /dev/null +++ b/drivers/virt/coco/arm-cca-guest/rhi-da.c @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2026 ARM Ltd. + */ + +#include "rsi-da.h" +#include "rhi-da.h" + +/** + * map_rhi_da_error - Map an RHI DA status to Linux errno + * @rhi_da_error: RHI DA status value to translate + * + * Return: 0 for %RHI_DA_SUCCESS, %RHI_DA_INCOMPLETE when the caller must + * continue the operation with rhi_vdev_continue(), or a negative errno for + * all other failures. Unknown status codes are mapped to -EIO. + */ +static inline int map_rhi_da_error(unsigned long rhi_da_error) +{ + switch (rhi_da_error) { + case RHI_DA_SUCCESS: + return 0; + case RHI_DA_INCOMPLETE: + return RHI_DA_INCOMPLETE; + case RHI_DA_ERROR_BUSY: + return -EBUSY; + case RHI_DA_ERROR_INPUT: + case RHI_DA_ERROR_INVALID_VDEV_ID: + return -EINVAL; + case RHI_DA_ERROR_ACCESS_FAILED: + return -EFAULT; + case RHI_DA_ERROR_DEVICE: + return -EIO; + case RHI_DA_ERROR_INVALID_OBJECT: + return -EINVAL; + default: + return -EIO; + } +} + +bool rhi_has_da_support(void) +{ + int ret; + + struct rsi_host_call *rhi_call __free(kfree) =3D + kmalloc(sizeof(*rhi_call), GFP_KERNEL); + if (!rhi_call) + return -ENOMEM; + + rhi_call->imm =3D 0; + rhi_call->gprs[0] =3D RHI_DA_FEATURES; + + ret =3D rsi_host_call(rhi_call); + if (ret !=3D RSI_SUCCESS || rhi_call->gprs[0] =3D=3D SMCCC_RET_NOT_SUPPOR= TED) + return false; + + /* For base DA to work we need these to be supported */ + if ((rhi_call->gprs[0] & RHI_DA_BASE_FEATURE) =3D=3D RHI_DA_BASE_FEATURE) + return true; + + return false; +} + +static inline int rhi_vdev_continue(unsigned long vdev_id, unsigned long c= ookie) +{ + unsigned long ret; + + struct rsi_host_call *rhi_call __free(kfree) =3D + kmalloc(sizeof(*rhi_call), GFP_KERNEL); + if (!rhi_call) + return -ENOMEM; + + rhi_call->imm =3D 0; + rhi_call->gprs[0] =3D RHI_DA_VDEV_CONTINUE; + rhi_call->gprs[1] =3D vdev_id; + rhi_call->gprs[2] =3D cookie; + + ret =3D rsi_host_call(rhi_call); + if (ret !=3D RSI_SUCCESS) + return -EIO; + + return map_rhi_da_error(rhi_call->gprs[0]); +} + +static int __rhi_vdev_abort(unsigned long vdev_id, unsigned long *da_error) +{ + unsigned long ret; + struct rsi_host_call *rhi_call __free(kfree) =3D + kmalloc(sizeof(struct rsi_host_call), GFP_KERNEL); + if (!rhi_call) + return -ENOMEM; + + rhi_call->imm =3D 0; + rhi_call->gprs[0] =3D RHI_DA_VDEV_ABORT; + rhi_call->gprs[1] =3D vdev_id; + + ret =3D rsi_host_call(rhi_call); + if (ret !=3D RSI_SUCCESS) + return -EIO; + + *da_error =3D rhi_call->gprs[0]; + return 0; +} + +static bool should_abort_rhi_call_loop(unsigned long vdev_id) +{ + int ret; + + cond_resched(); + if (signal_pending(current)) { + unsigned long da_error; + + ret =3D __rhi_vdev_abort(vdev_id, &da_error); + /* consider all kind of error as not aborted */ + if (!ret && (da_error =3D=3D RHI_DA_SUCCESS)) + return true; + } + return false; +} + +static int __rhi_vdev_set_tdi_state(unsigned long vdev_id, + enum rhi_tdi_state target_state, unsigned long *cookie) +{ + unsigned long ret; + + struct rsi_host_call *rhi_call __free(kfree) =3D + kmalloc(sizeof(struct rsi_host_call), GFP_KERNEL); + if (!rhi_call) + return -ENOMEM; + + rhi_call->imm =3D 0; + rhi_call->gprs[0] =3D RHI_DA_VDEV_SET_TDI_STATE; + rhi_call->gprs[1] =3D vdev_id; + rhi_call->gprs[2] =3D target_state; + + ret =3D rsi_host_call(rhi_call); + if (ret !=3D RSI_SUCCESS) + return -EIO; + + *cookie =3D rhi_call->gprs[1]; + return map_rhi_da_error(rhi_call->gprs[0]); +} + +int rhi_vdev_set_tdi_state(struct pci_dev *pdev, enum rhi_tdi_state target= _state) +{ + int ret; + unsigned long cookie; + int vdev_id =3D rsi_vdev_id(pdev); + + for (;;) { + ret =3D __rhi_vdev_set_tdi_state(vdev_id, target_state, &cookie); + if (ret !=3D -EBUSY) + break; + cond_resched(); + } + + while (ret =3D=3D RHI_DA_INCOMPLETE) { + if (should_abort_rhi_call_loop(vdev_id)) + return -EINTR; + ret =3D rhi_vdev_continue(vdev_id, cookie); + } + + return ret; +} diff --git a/drivers/virt/coco/arm-cca-guest/rhi-da.h b/drivers/virt/coco/a= rm-cca-guest/rhi-da.h new file mode 100644 index 000000000000..43c1cda8738d --- /dev/null +++ b/drivers/virt/coco/arm-cca-guest/rhi-da.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2026 ARM Ltd. + */ + +#ifndef _VIRT_COCO_RHI_DA_H_ +#define _VIRT_COCO_RHI_DA_H_ + +#include + +struct pci_dev; +bool rhi_has_da_support(void); +int rhi_vdev_set_tdi_state(struct pci_dev *pdev, enum rhi_tdi_state target= _state); +#endif --=20 2.43.0 From nobody Thu Jun 11 03:18:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ECB9939A804; Mon, 27 Apr 2026 08:28:34 +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=1777278515; cv=none; b=DQPMKKPefbLIBDkprPBKrvCAPJNlUhKlesqR+b11XNFDzqF4HC67f/8lCvug1ADp6rnTI9yvViDhuF9n/ngl4H5ewVwnBlqJIsbcfXwF7ds+KojOS2fe8xqwmDBL6zY1xLZlLRsz/PhKjPd7AFQsikJ39Nn2Ff4uCA9ZJqjO3M4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777278515; c=relaxed/simple; bh=jWDox4PMeXivGPI3967QCwIkfrrCveT4HT7lOBVxKvQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KI0p9n2itu051hEuVEX7ZiBzsxNpIq7E8Ay6Lefq5SNX4zYobG9Ak/x7rE72hlmFVZZ4LUdAehmHtzLyzrTphLXqc5SZZPTj7orFzv6DpDjD83VcZKCFqwKLObVy+9dd2REZ88yDrQMCvwwTlBspYx2hndA1m+IfFVZljWTFesw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UyW/3dlO; 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="UyW/3dlO" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 39541C2BCB4; Mon, 27 Apr 2026 08:28:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777278514; bh=jWDox4PMeXivGPI3967QCwIkfrrCveT4HT7lOBVxKvQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UyW/3dlOMlRwKnrOYnLbYnIDHNXE7tD9O4VWiIfBYUg35tWP0ARIVH1awxO2vHjin DqBizOBPL6vdSGnIEJvtkIVrKEftfehCRX1UhXBZhS6KH7KeRi677YK99/JyPzsFkr YLR1cWGLVX4zz+Msl2nq1rUCSr6c9s38+DGkNXKJTKMgK/waqwzMNVoyvkqyacom/k lT5gOAe+8NtlcPP4RMG+ZpueZI/3FJXf6+glp6YpK6kQkut5NtEJKj1Ckaj1b98Ert iCCWivn83c/f7ZKhPxswIbODnxApI9YoSHGxen3zgAho8kRw6aMF9WJt+VKZZOLsHS 7LL7Wanik2fGQ== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Alexey Kardashevskiy , Catalin Marinas , Dan Williams , Jason Gunthorpe , Jonathan Cameron , Marc Zyngier , Samuel Ortiz , Steven Price , Suzuki K Poulose , Will Deacon , Xu Yilun Subject: [RFC PATCH v4 04/11] coco: guest: arm64: Support guest-initiated TDI lock/unlock transitions Date: Mon, 27 Apr 2026 13:57:58 +0530 Message-ID: <20260427082805.931832-5-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260427082805.931832-1-aneesh.kumar@kernel.org> References: <20260427082805.931832-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 guest helpers to drive TDI state transitions through RHI: - cca_device_lock() -> RHI_DA_TDI_CONFIG_LOCKED - cca_device_unlock() -> RHI_DA_TDI_CONFIG_UNLOCKED Use these helpers in the PCI TSM lock/unlock callbacks so a successful lock path returns a live pci_tsm handle and unlock transitions the device back to unlocked state. Signed-off-by: Aneesh Kumar K.V (Arm) --- drivers/virt/coco/arm-cca-guest/Makefile | 2 +- drivers/virt/coco/arm-cca-guest/arm-cca.c | 9 ++++-- drivers/virt/coco/arm-cca-guest/rsi-da.c | 34 +++++++++++++++++++++++ drivers/virt/coco/arm-cca-guest/rsi-da.h | 3 ++ 4 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 drivers/virt/coco/arm-cca-guest/rsi-da.c diff --git a/drivers/virt/coco/arm-cca-guest/Makefile b/drivers/virt/coco/a= rm-cca-guest/Makefile index 65c4cc52c154..11db7af095c9 100644 --- a/drivers/virt/coco/arm-cca-guest/Makefile +++ b/drivers/virt/coco/arm-cca-guest/Makefile @@ -2,4 +2,4 @@ obj-$(CONFIG_ARM_CCA_GUEST) +=3D arm-cca-guest.o =20 arm-cca-guest-y +=3D arm-cca.o -arm-cca-guest-$(CONFIG_PCI_TSM) +=3D rhi-da.o +arm-cca-guest-$(CONFIG_PCI_TSM) +=3D rhi-da.o rsi-da.o diff --git a/drivers/virt/coco/arm-cca-guest/arm-cca.c b/drivers/virt/coco/= arm-cca-guest/arm-cca.c index 0c12aae85e6d..d4880ca59fc5 100644 --- a/drivers/virt/coco/arm-cca-guest/arm-cca.c +++ b/drivers/virt/coco/arm-cca-guest/arm-cca.c @@ -211,14 +211,19 @@ static struct pci_tsm *cca_tsm_lock(struct tsm_dev *t= sm_dev, struct pci_dev *pde if (ret) return ERR_PTR(ret); =20 - /* For now always return an error */ - return ERR_PTR(-EIO); + ret =3D cca_device_lock(pdev); + if (ret) + return ERR_PTR(ret); + + return &no_free_ptr(cca_dsc)->pci.base_tsm; } =20 static void cca_tsm_unlock(struct pci_tsm *tsm) { struct cca_guest_dsc *cca_dsc =3D to_cca_guest_dsc(tsm->pdev); =20 + cca_device_unlock(tsm->pdev); + kfree(cca_dsc); } =20 diff --git a/drivers/virt/coco/arm-cca-guest/rsi-da.c b/drivers/virt/coco/a= rm-cca-guest/rsi-da.c new file mode 100644 index 000000000000..2c3017933fb0 --- /dev/null +++ b/drivers/virt/coco/arm-cca-guest/rsi-da.c @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2025 ARM Ltd. + */ + +#include +#include + +#include "rsi-da.h" +#include "rhi-da.h" + +int cca_device_lock(struct pci_dev *pdev) +{ + int ret; + + ret =3D rhi_vdev_set_tdi_state(pdev, RHI_DA_TDI_CONFIG_LOCKED); + if (ret) { + pci_err(pdev, "failed to lock the device (%d)\n", ret); + return ret; + } + return 0; +} + +int cca_device_unlock(struct pci_dev *pdev) +{ + int ret; + + ret =3D rhi_vdev_set_tdi_state(pdev, RHI_DA_TDI_CONFIG_UNLOCKED); + if (ret) { + pci_err(pdev, "failed to unlock the device (%d)\n", ret); + return ret; + } + return 0; +} diff --git a/drivers/virt/coco/arm-cca-guest/rsi-da.h b/drivers/virt/coco/a= rm-cca-guest/rsi-da.h index 858bfdaf59c9..06fcea95d888 100644 --- a/drivers/virt/coco/arm-cca-guest/rsi-da.h +++ b/drivers/virt/coco/arm-cca-guest/rsi-da.h @@ -32,4 +32,7 @@ static inline int rsi_vdev_id(struct pci_dev *pdev) PCI_DEVID(pdev->bus->number, pdev->devfn); } =20 +int cca_device_lock(struct pci_dev *pdev); +int cca_device_unlock(struct pci_dev *pdev); + #endif --=20 2.43.0 From nobody Thu Jun 11 03:18:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 79ED0399375; Mon, 27 Apr 2026 08:28:40 +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=1777278520; cv=none; b=s71rxQaJDFns1uG7ctTtODKcMz6CP7KYZ8/5ik3AkmneWGvVNw3eTjgx2NliXgId8ozZluOFTlNHznXFlmKL96arC1yxgfFG9ft+UPJfZSSGmBgPb/BxgE8rc49sPhNwwnsKZOLF5G/fBO05NxDUaqgrQLTA8Vyiv9NxLrGrcKE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777278520; c=relaxed/simple; bh=cUKMVmGtfrho+jfrzN1+rtbjtRwloe9DETwZisu/zN4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TJcmWWkL9r5pTK6x8sqXr4QnN7JQKbrKIUmoOigwrWdRH84Un9ThRGAyEA+Aaba3ayvX9DVQ4aYd3yB77wbLMwYzTnrbs3lOMdO3OHKYbzwyyIYoL6k7Bh+xXgRu89UBn6YyVAlLxl/6EyjH03v578urDZu2YLWVo6jw4zWCes8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=T9VByCMF; 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="T9VByCMF" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 72C9FC2BCB4; Mon, 27 Apr 2026 08:28:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777278520; bh=cUKMVmGtfrho+jfrzN1+rtbjtRwloe9DETwZisu/zN4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=T9VByCMFux0mkmCJFxDhBohTSupzlNjtN43Sel1QfTF695K91/uNFXfMxD/jVVsAi yg7TlQErsAaSUXafjEJ8R3eJvbpDpW6Sr9mUvag4/YME0JDTZaM3FNeq70dwYPAy+L nB5fDfUU11lO1axE3q8dTXh2Od32HSsCu6u7aPkXlw2Xp3H9bSAkMBdRxvLnRq4sdt D4D3Na7tthrxskbqRvsUYn6q+cE1oTwLkAEtWmLJUUSkSKdSlwyRt5nF32po0oAz11 Qi/caP818ZuAMjwJ9jUdvrcBYRQKoXg6ZGQ2gzQ2ax0IHrzzBTaIFDymBT9v1PIBX6 PMoKpmS+Of9EA== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Alexey Kardashevskiy , Catalin Marinas , Dan Williams , Jason Gunthorpe , Jonathan Cameron , Marc Zyngier , Samuel Ortiz , Steven Price , Suzuki K Poulose , Will Deacon , Xu Yilun Subject: [RFC PATCH v4 05/11] coco: guest: arm64: Refresh interface-report cache during device lock Date: Mon, 27 Apr 2026 13:57:59 +0530 Message-ID: <20260427082805.931832-6-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260427082805.931832-1-aneesh.kumar@kernel.org> References: <20260427082805.931832-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 support for RHI_DA_VDEV_GET_INTERFACE_REPORT and use it to refresh the host-side cached interface report when a device is locked. Implement rhi_update_vdev_interface_report_cache() with busy retry and cookie-based CONTINUE handling for incomplete operations. Surface the flow through cca_update_device_object_cache(), and call it from the lock path so the interface report is fetched before lock succeeds. On refresh failure, unwind by unlocking the device and returning the error. Signed-off-by: Aneesh Kumar K.V (Arm) --- arch/arm64/include/asm/rhi.h | 2 ++ drivers/virt/coco/arm-cca-guest/arm-cca.c | 6 ++++ drivers/virt/coco/arm-cca-guest/rhi-da.c | 44 +++++++++++++++++++++++ drivers/virt/coco/arm-cca-guest/rhi-da.h | 1 + drivers/virt/coco/arm-cca-guest/rsi-da.c | 13 +++++++ drivers/virt/coco/arm-cca-guest/rsi-da.h | 1 + 6 files changed, 67 insertions(+) diff --git a/arch/arm64/include/asm/rhi.h b/arch/arm64/include/asm/rhi.h index 88de2d9b34d1..15946fe64484 100644 --- a/arch/arm64/include/asm/rhi.h +++ b/arch/arm64/include/asm/rhi.h @@ -50,6 +50,8 @@ unsigned long rhi_get_ipa_change_alignment(void); =20 #define RHI_DA_VDEV_CONTINUE SMC_RHI_CALL(0x0051) =20 +#define RHI_DA_VDEV_GET_INTERFACE_REPORT SMC_RHI_CALL(0x0053) + enum rhi_tdi_state { RHI_DA_TDI_CONFIG_UNLOCKED, RHI_DA_TDI_CONFIG_LOCKED, diff --git a/drivers/virt/coco/arm-cca-guest/arm-cca.c b/drivers/virt/coco/= arm-cca-guest/arm-cca.c index d4880ca59fc5..411cbbaa5d26 100644 --- a/drivers/virt/coco/arm-cca-guest/arm-cca.c +++ b/drivers/virt/coco/arm-cca-guest/arm-cca.c @@ -215,6 +215,12 @@ static struct pci_tsm *cca_tsm_lock(struct tsm_dev *ts= m_dev, struct pci_dev *pde if (ret) return ERR_PTR(ret); =20 + ret =3D cca_update_device_object_cache(pdev, NULL); + if (ret) { + cca_device_unlock(pdev); + return ERR_PTR(ret); + } + return &no_free_ptr(cca_dsc)->pci.base_tsm; } =20 diff --git a/drivers/virt/coco/arm-cca-guest/rhi-da.c b/drivers/virt/coco/a= rm-cca-guest/rhi-da.c index 5b48c8d6ebe3..5078136a4cc6 100644 --- a/drivers/virt/coco/arm-cca-guest/rhi-da.c +++ b/drivers/virt/coco/arm-cca-guest/rhi-da.c @@ -161,3 +161,47 @@ int rhi_vdev_set_tdi_state(struct pci_dev *pdev, enum = rhi_tdi_state target_state =20 return ret; } + +static inline int rhi_vdev_get_interface_report(unsigned long vdev_id, + unsigned long *cookie) +{ + unsigned long ret; + + struct rsi_host_call *rhi_call __free(kfree) =3D + kmalloc(sizeof(struct rsi_host_call), GFP_KERNEL); + if (!rhi_call) + return -ENOMEM; + + rhi_call->imm =3D 0; + rhi_call->gprs[0] =3D RHI_DA_VDEV_GET_INTERFACE_REPORT; + rhi_call->gprs[1] =3D vdev_id; + + ret =3D rsi_host_call(rhi_call); + if (ret !=3D RSI_SUCCESS) + return -EIO; + + *cookie =3D rhi_call->gprs[1]; + return map_rhi_da_error(rhi_call->gprs[0]); +} + +int rhi_update_vdev_interface_report_cache(struct pci_dev *pdev) +{ + int ret; + unsigned long cookie; + int vdev_id =3D rsi_vdev_id(pdev); + + for (;;) { + ret =3D rhi_vdev_get_interface_report(vdev_id, &cookie); + if (ret !=3D -EBUSY) + break; + cond_resched(); + } + + while (ret =3D=3D RHI_DA_INCOMPLETE) { + if (should_abort_rhi_call_loop(vdev_id)) + return -EINTR; + ret =3D rhi_vdev_continue(vdev_id, cookie); + } + + return ret; +} diff --git a/drivers/virt/coco/arm-cca-guest/rhi-da.h b/drivers/virt/coco/a= rm-cca-guest/rhi-da.h index 43c1cda8738d..8b7faf4d1c8a 100644 --- a/drivers/virt/coco/arm-cca-guest/rhi-da.h +++ b/drivers/virt/coco/arm-cca-guest/rhi-da.h @@ -11,4 +11,5 @@ struct pci_dev; bool rhi_has_da_support(void); int rhi_vdev_set_tdi_state(struct pci_dev *pdev, enum rhi_tdi_state target= _state); +int rhi_update_vdev_interface_report_cache(struct pci_dev *pdev); #endif diff --git a/drivers/virt/coco/arm-cca-guest/rsi-da.c b/drivers/virt/coco/a= rm-cca-guest/rsi-da.c index 2c3017933fb0..6c78f0e2f3a1 100644 --- a/drivers/virt/coco/arm-cca-guest/rsi-da.c +++ b/drivers/virt/coco/arm-cca-guest/rsi-da.c @@ -32,3 +32,16 @@ int cca_device_unlock(struct pci_dev *pdev) } return 0; } + +int cca_update_device_object_cache(struct pci_dev *pdev, const u8 *nonce) +{ + int ret; + + ret =3D rhi_update_vdev_interface_report_cache(pdev); + if (ret) { + pci_err(pdev, "failed to get interface report (%d)\n", ret); + return ret; + } + + return 0; +} diff --git a/drivers/virt/coco/arm-cca-guest/rsi-da.h b/drivers/virt/coco/a= rm-cca-guest/rsi-da.h index 06fcea95d888..dda8026a1c3f 100644 --- a/drivers/virt/coco/arm-cca-guest/rsi-da.h +++ b/drivers/virt/coco/arm-cca-guest/rsi-da.h @@ -34,5 +34,6 @@ static inline int rsi_vdev_id(struct pci_dev *pdev) =20 int cca_device_lock(struct pci_dev *pdev); int cca_device_unlock(struct pci_dev *pdev); +int cca_update_device_object_cache(struct pci_dev *pdev, const u8 *nonce); =20 #endif --=20 2.43.0 From nobody Thu Jun 11 03:18:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 816E1399375; Mon, 27 Apr 2026 08:28:45 +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=1777278525; cv=none; b=e7yJdAFxZIRSku8l5Ih42lmDfWfT7KdaCr3yp3ufxYRSecB2hSSlxrwuEtnWHYvS6QkiLg6pOhT8hyec0JrF0xTR8eObNCNDWsOr16452uhzFqA1aiheDo6TqVJiqpXXEZQ8xIdPlJKxjq3IlrWaG+DqcvL4cQoQeAIKyssm9a0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777278525; c=relaxed/simple; bh=lETn6Kr3OyzzZutG3/vCFA7uINmnc95y+RJn66EJb2Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=kd2Fur6BHzSE+YIVtz3aacTkoP2CSa+Vme3LHYWinwA/byAglyCaIwpIjeQDg/SHYJDRfFeFgC6h1TFR6MRq036h7u84y3k0wDHQDEjFSdeOv983WOffMWq0sq3MOyZCIe6cwiSRXKLMNP/h2VfU0so/OP6kw5hut5gf+P2/zFA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=h243qLzF; 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="h243qLzF" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A9E03C19425; Mon, 27 Apr 2026 08:28:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777278525; bh=lETn6Kr3OyzzZutG3/vCFA7uINmnc95y+RJn66EJb2Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=h243qLzFJ5S339UPMeg3rROQnMZbIdibcNdwFIKHzxamct4S2+cC388t517yyZllG pqP1sSxWRaZDbWjozrsummi7AC1yluW5uxk9LF+4c+V88WvqNi8o8e4+gPD+HZVKDc X4hQfHj3yx2Cn5kwoJkvN4v2pNWlK9TilJXpbY3sL187+xwPRkJ/TFz3Hp22BtoFyP E7ZytP3oG9gxgP5kHgolNT9YQCSyqG46tW558h+BTTamwXhQ38MvgTS2T/odUHbI6L T6GzY57L51s1mDJ5Ah1a0eO8hHTnt5nCzr7wIHuSPb43En8r/z3tFAiyTT38YcJP7D BUlrifBNuRCnQ== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Alexey Kardashevskiy , Catalin Marinas , Dan Williams , Jason Gunthorpe , Jonathan Cameron , Marc Zyngier , Samuel Ortiz , Steven Price , Suzuki K Poulose , Will Deacon , Xu Yilun Subject: [RFC PATCH v4 06/11] coco: guest: arm64: Add measurement refresh via RHI_DA_VDEV_GET_MEASUREMENTS Date: Mon, 27 Apr 2026 13:58:00 +0530 Message-ID: <20260427082805.931832-7-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260427082805.931832-1-aneesh.kumar@kernel.org> References: <20260427082805.931832-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 guest support to request fresh device measurements using RHI_DA_VDEV_GET_MEASUREMENTS. Define measurement request parameters (flags + nonce), request RAW measurements, and implement cookie-based continuation for incomplete DA operations. Extend cca_update_device_object_cache() to refresh both interface report and measurements. Because RHI buffers are shared with the host, add shared-page allocation helpers that convert pages to decrypted/shared memory before use and restore them to encrypted/private state on free. Signed-off-by: Aneesh Kumar K.V (Arm) --- arch/arm64/include/asm/rhi.h | 11 ++++ drivers/virt/coco/arm-cca-guest/arm-cca.c | 1 + drivers/virt/coco/arm-cca-guest/rhi-da.c | 78 +++++++++++++++++++++++ drivers/virt/coco/arm-cca-guest/rhi-da.h | 1 + drivers/virt/coco/arm-cca-guest/rsi-da.c | 42 +++++++++++- drivers/virt/coco/arm-cca-guest/rsi-da.h | 2 + 6 files changed, 134 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/rhi.h b/arch/arm64/include/asm/rhi.h index 15946fe64484..2b56a7760904 100644 --- a/arch/arm64/include/asm/rhi.h +++ b/arch/arm64/include/asm/rhi.h @@ -50,6 +50,17 @@ unsigned long rhi_get_ipa_change_alignment(void); =20 #define RHI_DA_VDEV_CONTINUE SMC_RHI_CALL(0x0051) =20 +#define RHI_VDEV_MEASURE_HASH 0x0 +#define RHI_VDEV_MEASURE_RAW 0x1 +struct rhi_vdev_measurement_params { + union { + u64 flags; + u8 padding0[0x100]; + }; + u8 nonce[32]; +}; +#define RHI_DA_VDEV_GET_MEASUREMENTS SMC_RHI_CALL(0x0052) + #define RHI_DA_VDEV_GET_INTERFACE_REPORT SMC_RHI_CALL(0x0053) =20 enum rhi_tdi_state { diff --git a/drivers/virt/coco/arm-cca-guest/arm-cca.c b/drivers/virt/coco/= arm-cca-guest/arm-cca.c index 411cbbaa5d26..0f9cfb329a06 100644 --- a/drivers/virt/coco/arm-cca-guest/arm-cca.c +++ b/drivers/virt/coco/arm-cca-guest/arm-cca.c @@ -215,6 +215,7 @@ static struct pci_tsm *cca_tsm_lock(struct tsm_dev *tsm= _dev, struct pci_dev *pde if (ret) return ERR_PTR(ret); =20 + /* collect evidence without nonce */ ret =3D cca_update_device_object_cache(pdev, NULL); if (ret) { cca_device_unlock(pdev); diff --git a/drivers/virt/coco/arm-cca-guest/rhi-da.c b/drivers/virt/coco/a= rm-cca-guest/rhi-da.c index 5078136a4cc6..d0f5ae320f83 100644 --- a/drivers/virt/coco/arm-cca-guest/rhi-da.c +++ b/drivers/virt/coco/arm-cca-guest/rhi-da.c @@ -205,3 +205,81 @@ int rhi_update_vdev_interface_report_cache(struct pci_= dev *pdev) =20 return ret; } + +static inline int rhi_vdev_get_measurements(unsigned long vdev_id, + phys_addr_t vdev_meas_phys, unsigned long *cookie) +{ + unsigned long ret; + + struct rsi_host_call *rhi_call __free(kfree) =3D + kmalloc(sizeof(*rhi_call), GFP_KERNEL); + if (!rhi_call) + return -ENOMEM; + + rhi_call->imm =3D 0; + rhi_call->gprs[0] =3D RHI_DA_VDEV_GET_MEASUREMENTS; + rhi_call->gprs[1] =3D vdev_id; + rhi_call->gprs[2] =3D vdev_meas_phys; + + ret =3D rsi_host_call(rhi_call); + if (ret !=3D RSI_SUCCESS) + return -EIO; + + *cookie =3D rhi_call->gprs[1]; + return map_rhi_da_error(rhi_call->gprs[0]); +} + +static inline struct rhi_vdev_measurement_params *alloc_vdev_meas_params(v= oid) +{ + struct page *pages; + + pages =3D alloc_shared_pages(NUMA_NO_NODE, GFP_KERNEL, + sizeof(struct rhi_vdev_measurement_params)); + if (!pages) + return NULL; + return page_address(pages); +} + +static inline void vdev_meas_params_free(struct rhi_vdev_measurement_param= s *params) +{ + struct page *pages =3D virt_to_page(params); + + free_shared_pages(pages, sizeof(struct rhi_vdev_measurement_params)); +} + +DEFINE_FREE(vdev_meas_params_free, struct rhi_vdev_measurement_params *, i= f (_T) vdev_meas_params_free(_T)) +int rhi_update_vdev_measurements_cache(struct pci_dev *pdev, const u8 *non= ce) +{ + int ret; + unsigned long cookie; + int vdev_id =3D rsi_vdev_id(pdev); + phys_addr_t vdev_meas_phys; + + struct rhi_vdev_measurement_params *dev_meas __free(vdev_meas_params_free= ) =3D + alloc_vdev_meas_params(); + if (!dev_meas) + return -ENOMEM; + + vdev_meas_phys =3D virt_to_phys(dev_meas); + /* request for raw bitstream */ + dev_meas->flags =3D RHI_VDEV_MEASURE_RAW; + if (nonce) + memcpy(dev_meas->nonce, nonce, 32); + + for (;;) { + ret =3D rhi_vdev_get_measurements(vdev_id, vdev_meas_phys, &cookie); + if (ret !=3D -EBUSY) + break; + cond_resched(); + } + + while (ret =3D=3D RHI_DA_INCOMPLETE) { + if (should_abort_rhi_call_loop(vdev_id)) + return -EINTR; + ret =3D rhi_vdev_continue(vdev_id, cookie); + } + + if (ret) + pci_err(pdev, "failed to get device measurement (%d)\n", ret); + return ret; +} diff --git a/drivers/virt/coco/arm-cca-guest/rhi-da.h b/drivers/virt/coco/a= rm-cca-guest/rhi-da.h index 8b7faf4d1c8a..d32ccc48c0d0 100644 --- a/drivers/virt/coco/arm-cca-guest/rhi-da.h +++ b/drivers/virt/coco/arm-cca-guest/rhi-da.h @@ -12,4 +12,5 @@ struct pci_dev; bool rhi_has_da_support(void); int rhi_vdev_set_tdi_state(struct pci_dev *pdev, enum rhi_tdi_state target= _state); int rhi_update_vdev_interface_report_cache(struct pci_dev *pdev); +int rhi_update_vdev_measurements_cache(struct pci_dev *pdev, const u8 *non= ce); #endif diff --git a/drivers/virt/coco/arm-cca-guest/rsi-da.c b/drivers/virt/coco/a= rm-cca-guest/rsi-da.c index 6c78f0e2f3a1..9f9e54174813 100644 --- a/drivers/virt/coco/arm-cca-guest/rsi-da.c +++ b/drivers/virt/coco/arm-cca-guest/rsi-da.c @@ -4,6 +4,7 @@ */ =20 #include +#include #include =20 #include "rsi-da.h" @@ -33,6 +34,45 @@ int cca_device_unlock(struct pci_dev *pdev) return 0; } =20 +struct page *alloc_shared_pages(int nid, gfp_t gfp_mask, unsigned long min= _size) +{ + int ret; + struct page *page; + /* We should normalize the size based on hypervisor page size */ + int page_order =3D get_order(min_size); + + page =3D alloc_pages_node(nid, gfp_mask | __GFP_ZERO, page_order); + if (!page) + return NULL; + + ret =3D set_memory_decrypted((unsigned long)page_address(page), + 1 << page_order); + /* + * If set_memory_decrypted() fails then we don't know what state the + * page is in, so we can't free it. Instead we leak it. + * set_memory_decrypted() will already have WARNed. + */ + if (ret) + return NULL; + + return page; +} + +int free_shared_pages(struct page *page, unsigned long size) +{ + int ret; + /* We should normalize the size based on hypervisor page size */ + int page_order =3D get_order(size); + + ret =3D set_memory_encrypted((unsigned long)page_address(page), 1 << page= _order); + /* If we fail to mark it encrypted don't free it back */ + if (ret) + return ret; + + __free_pages(page, page_order); + return 0; +} + int cca_update_device_object_cache(struct pci_dev *pdev, const u8 *nonce) { int ret; @@ -43,5 +83,5 @@ int cca_update_device_object_cache(struct pci_dev *pdev, = const u8 *nonce) return ret; } =20 - return 0; + return rhi_update_vdev_measurements_cache(pdev, nonce); } diff --git a/drivers/virt/coco/arm-cca-guest/rsi-da.h b/drivers/virt/coco/a= rm-cca-guest/rsi-da.h index dda8026a1c3f..297cb800edc0 100644 --- a/drivers/virt/coco/arm-cca-guest/rsi-da.h +++ b/drivers/virt/coco/arm-cca-guest/rsi-da.h @@ -35,5 +35,7 @@ static inline int rsi_vdev_id(struct pci_dev *pdev) int cca_device_lock(struct pci_dev *pdev); int cca_device_unlock(struct pci_dev *pdev); int cca_update_device_object_cache(struct pci_dev *pdev, const u8 *nonce); +struct page *alloc_shared_pages(int nid, gfp_t gfp_mask, unsigned long min= _size); +int free_shared_pages(struct page *page, unsigned long min_size); =20 #endif --=20 2.43.0 From nobody Thu Jun 11 03:18:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F20BF3976A7; Mon, 27 Apr 2026 08:28:50 +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=1777278531; cv=none; b=GFT9pVstdNi+FFo6LVCoIt+1jR77IR1Tv5LgDMptVydCpc1vrKybivialkjsKx00O4i+coBM52ckU1/qZgMz0JAjdTQ7q6sgFWTK7FZiKT4RbZ6VY89U2cXKll58ziDumhQp/qpIo6VfRX6NchY1JJQ40MIwa4lboKP/H4LBQRg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777278531; c=relaxed/simple; bh=jNp9qsUFxSqnqXy8TKaLW9c3z208YtDH/OH/IkVAaus=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dzb5QWpr5H5zZ3Q6xCj4JXVgiDRKDfYDBhkxn3f2KvOpthwLQnQzHWS71QHl0A9FVtU0oYm3XGNm2Q5w4L0CG6oE7bkTQ7bU3Zd0byB+ayjRnRkZYYy8Q1VbbBUem4x0S+gx4WYllZvDbjfBQ6wKWWQmxTGKjs4PDA6VosGtVoE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=fFWMOqPw; 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="fFWMOqPw" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0599FC2BCB8; Mon, 27 Apr 2026 08:28:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777278530; bh=jNp9qsUFxSqnqXy8TKaLW9c3z208YtDH/OH/IkVAaus=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fFWMOqPwJi48SZarPWAHd4BJJEYN3M48EvZo/ZcW1uVch3BPU4TJTe7P4aXrMXsEa B/GLlZ+TFaS6lQl4SjDQazt2Zj2yYaYDZccxBx7onPzj+9Bsnn3XB4o0RTbGNfKBPA U53qyPu67sGXgYC9yzhY63cIAQcDgZRlwKXxbr+oRFQNsGfjjUQiXM0Dv9E736u8g+ 3O0fYf98eVcVaHruaj1jQxbXNzA5N5vHymnwJ5urDXOBGbKBJReAp71jgUh0LrO3a8 xE+2Py6eLkY0t9J51OcqM53yGqnPAG0GeH5hRbvbfig0XdGU55wJtySce8KRQbwl2b Kkp9oaP3k5q+w== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Alexey Kardashevskiy , Catalin Marinas , Dan Williams , Jason Gunthorpe , Jonathan Cameron , Marc Zyngier , Samuel Ortiz , Steven Price , Suzuki K Poulose , Will Deacon , Xu Yilun Subject: [RFC PATCH v4 07/11] coco: guest: arm64: Add guest APIs to read host-cached DA objects Date: Mon, 27 Apr 2026 13:58:01 +0530 Message-ID: <20260427082805.931832-8-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260427082805.931832-1-aneesh.kumar@kernel.org> References: <20260427082805.931832-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" Introduce guest-side helpers to read host-cached DA objects (certificate, VCA, interface report, and measurements). Add RHI_DA_OBJECT_SIZE and RHI_DA_OBJECT_READ definitions, then implement rhi_read_cached_object() that: - queries object size from host - validates size against MAX_CACHE_OBJ_SIZE - allocates a shared buffer - issues OBJECT_READ into shared memory - copies data into private memory and frees shared pages Export the helper for later evidence-collection and verification code. Signed-off-by: Aneesh Kumar K.V (Arm) --- arch/arm64/include/asm/rhi.h | 8 +++ drivers/virt/coco/arm-cca-guest/rhi-da.c | 71 ++++++++++++++++++++++++ drivers/virt/coco/arm-cca-guest/rhi-da.h | 1 + drivers/virt/coco/arm-cca-guest/rsi-da.h | 2 + 4 files changed, 82 insertions(+) diff --git a/arch/arm64/include/asm/rhi.h b/arch/arm64/include/asm/rhi.h index 2b56a7760904..dc7a57370945 100644 --- a/arch/arm64/include/asm/rhi.h +++ b/arch/arm64/include/asm/rhi.h @@ -48,6 +48,14 @@ unsigned long rhi_get_ipa_change_alignment(void); RHI_DA_FEATURE_VDEV_SET_TDI_STATE) #define RHI_DA_FEATURES SMC_RHI_CALL(0x004B) =20 +#define RHI_DA_OBJECT_VCA 0x0 +#define RHI_DA_OBJECT_CERTIFICATE 0x1 +#define RHI_DA_OBJECT_MEASUREMENT 0x2 +#define RHI_DA_OBJECT_INTERFACE_REPORT 0x3 +#define RHI_DA_OBJECT_EXTENSION_EVIDENCE 0x4 +#define RHI_DA_OBJECT_SIZE SMC_RHI_CALL(0x004C) +#define RHI_DA_OBJECT_READ SMC_RHI_CALL(0x004D) + #define RHI_DA_VDEV_CONTINUE SMC_RHI_CALL(0x0051) =20 #define RHI_VDEV_MEASURE_HASH 0x0 diff --git a/drivers/virt/coco/arm-cca-guest/rhi-da.c b/drivers/virt/coco/a= rm-cca-guest/rhi-da.c index d0f5ae320f83..73c599802a93 100644 --- a/drivers/virt/coco/arm-cca-guest/rhi-da.c +++ b/drivers/virt/coco/arm-cca-guest/rhi-da.c @@ -3,6 +3,8 @@ * Copyright (C) 2026 ARM Ltd. */ =20 +#include + #include "rsi-da.h" #include "rhi-da.h" =20 @@ -283,3 +285,72 @@ int rhi_update_vdev_measurements_cache(struct pci_dev = *pdev, const u8 *nonce) pci_err(pdev, "failed to get device measurement (%d)\n", ret); return ret; } + +int rhi_read_cached_object(int vdev_id, int da_object_type, void **object,= int *object_size) +{ + int ret; + int data_size; + void *data_buf_shared; + struct page *shared_pages; + + *object_size =3D 0; + *object =3D NULL; + + struct rsi_host_call *rhicall __free(kfree) =3D + kmalloc(sizeof(struct rsi_host_call), GFP_KERNEL); + if (!rhicall) + return -ENOMEM; + + rhicall->imm =3D 0; + rhicall->gprs[0] =3D RHI_DA_OBJECT_SIZE; + rhicall->gprs[1] =3D vdev_id; + rhicall->gprs[2] =3D da_object_type; + + ret =3D rsi_host_call(rhicall); + if (ret !=3D RSI_SUCCESS) + return -EIO; + + if (rhicall->gprs[0] !=3D RHI_DA_SUCCESS) + return -EIO; + + /* validate against the max cache object size used on host. */ + data_size =3D rhicall->gprs[1]; + if (data_size > MAX_CACHE_OBJ_SIZE || data_size =3D=3D 0) + return -EIO; + + shared_pages =3D alloc_shared_pages(NUMA_NO_NODE, GFP_KERNEL, data_size); + if (!shared_pages) + return -ENOMEM; + + data_buf_shared =3D page_address(shared_pages); + + rhicall->imm =3D 0; + rhicall->gprs[0] =3D RHI_DA_OBJECT_READ; + rhicall->gprs[1] =3D vdev_id; + rhicall->gprs[2] =3D da_object_type; + rhicall->gprs[3] =3D virt_to_phys(data_buf_shared); + rhicall->gprs[4] =3D data_size; + rhicall->gprs[5] =3D 0; /* offset to read from */ + ret =3D rsi_host_call(rhicall); + if (ret !=3D RSI_SUCCESS || rhicall->gprs[0] !=3D RHI_DA_SUCCESS) { + free_shared_pages(shared_pages, data_size); + return -EIO; + } + + if (data_size !=3D rhicall->gprs[1]) { + /* Short read */ + free_shared_pages(shared_pages, data_size); + return -EIO; + } + + void *data_buf_private =3D kvmemdup(data_buf_shared, + data_size, GFP_KERNEL); + /* free the shared pages irrespective of error condition */ + free_shared_pages(shared_pages, data_size); + if (!data_buf_private) + return -ENOMEM; + + *object =3D data_buf_private; + *object_size =3D data_size; + return 0; +} diff --git a/drivers/virt/coco/arm-cca-guest/rhi-da.h b/drivers/virt/coco/a= rm-cca-guest/rhi-da.h index d32ccc48c0d0..f7655d7ecf18 100644 --- a/drivers/virt/coco/arm-cca-guest/rhi-da.h +++ b/drivers/virt/coco/arm-cca-guest/rhi-da.h @@ -13,4 +13,5 @@ bool rhi_has_da_support(void); int rhi_vdev_set_tdi_state(struct pci_dev *pdev, enum rhi_tdi_state target= _state); int rhi_update_vdev_interface_report_cache(struct pci_dev *pdev); int rhi_update_vdev_measurements_cache(struct pci_dev *pdev, const u8 *non= ce); +int rhi_read_cached_object(int vdev_id, int da_object_type, void **object,= int *object_size); #endif diff --git a/drivers/virt/coco/arm-cca-guest/rsi-da.h b/drivers/virt/coco/a= rm-cca-guest/rsi-da.h index 297cb800edc0..88067d2230ab 100644 --- a/drivers/virt/coco/arm-cca-guest/rsi-da.h +++ b/drivers/virt/coco/arm-cca-guest/rsi-da.h @@ -10,6 +10,8 @@ #include #include =20 +#define MAX_CACHE_OBJ_SIZE SZ_16M + struct cca_guest_dsc { struct pci_tsm_devsec pci; }; --=20 2.43.0 From nobody Thu Jun 11 03:18:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 76D2139B4BB; Mon, 27 Apr 2026 08:28: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=1777278536; cv=none; b=gc/VmdNkksdJCJAF7rCIxlJxieeze2eQ1/ENb6/Ypm19nbEAvU0x/NhthqwpRVXRMve5mmMjDGITCRz4hFbK+HzpFzQuEESogt+HLwFTK0lhVzAHWsVrSyJyVs7rqAUDqNdbsWZuipsJ9wg2him56JIt/FnPqnRKWDfOzeneuiY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777278536; c=relaxed/simple; bh=wu76r3KqQHzB0XTeHOywZ8WdvI29/olctlHPyOL7BJw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rtOlM84vx85YiF5BN5JzQaseC3DXA20dikDeMTvFzZ+rm9U9JV/dqxUckZS87XZT1rbfeZrTnQzhVfctKJrPyXI0+AdM5sj/HQHGxa5Y2Ll27osnPcsQWsaTczx5T+6Ccvk6WWpo4nR27I5uVFxNZYbmS+z3th9VmCdYjMMLVz0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=M6hyVm5I; 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="M6hyVm5I" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3D577C2BCB4; Mon, 27 Apr 2026 08:28:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777278536; bh=wu76r3KqQHzB0XTeHOywZ8WdvI29/olctlHPyOL7BJw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=M6hyVm5IUTngiLy+iyNTcGnimc+oyXKEMpR6JQhxWFARvWLacTSnaB9c4/Od3vXQH vp9GujBO6siEYCqoSq0OuM4htGN8ekkZgV6BUuQKWLq1c/n0engXJRgqwhzfTm9rRf FwZf4xHxiK8CyYtpZh4VnXtTuxwespBjmmAURBMFM2LUjjSicwIIyqz9e4wn9CdfFI r6JOQ4DTtUxe9Q4X70zC6H5/u0iklWF0ZcWb4kVnjuIXru+kRCTGE2NEih/yjW0htD FvkY7ttN3vT6dnOXzPzKVK7EXk4gK3kB1UV2VBhzKJd8Ly0aKMCG640WcT90I4oPZg 6GPiuvR2vRubA== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Alexey Kardashevskiy , Catalin Marinas , Dan Williams , Jason Gunthorpe , Jonathan Cameron , Marc Zyngier , Samuel Ortiz , Steven Price , Suzuki K Poulose , Will Deacon , Xu Yilun Subject: [RFC PATCH v4 08/11] coco: guest: arm64: Verify DA evidence with RSI_VDEV_GET_INFO digests Date: Mon, 27 Apr 2026 13:58:02 +0530 Message-ID: <20260427082805.931832-9-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260427082805.931832-1-aneesh.kumar@kernel.org> References: <20260427082805.931832-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 guest-side evidence verification based on RSI_VDEV_GET_INFO and use the verified TDISP interface report to validate Realm MMIO mappings. During lock: - refresh host caches from device - read certificate/VCA/interface-report/measurement objects from host cache - fetch trusted digest metadata from RSI_VDEV_GET_INFO - verify host-provided objects against RSI digests - initialize and populate PCI TSM evidence objects - preserve lock/meas/report nonces and digests in guest state Add mapping helpers to walk MMIO entries from the TDISP report and perform RSI_VDEV_VALIDATE_MAPPING on map, or RIPAS destroy on unmap. Reject malform= ed range progress while validating. During unlock: - invalidate mappings derived from the evidence report - unlock the device and tear down MMIO bookkeeping This ensures host-cached DA objects are cryptographically verified before being trusted for mapping and attestation state transitions. Signed-off-by: Aneesh Kumar K.V (Arm) --- arch/arm64/include/asm/rsi_cmds.h | 40 +++ arch/arm64/include/asm/rsi_smc.h | 60 +++++ drivers/virt/coco/arm-cca-guest/Kconfig | 2 + drivers/virt/coco/arm-cca-guest/arm-cca.c | 287 +++++++++++++++++++++- drivers/virt/coco/arm-cca-guest/rsi-da.c | 145 +++++++++++ drivers/virt/coco/arm-cca-guest/rsi-da.h | 22 ++ 6 files changed, 545 insertions(+), 11 deletions(-) diff --git a/arch/arm64/include/asm/rsi_cmds.h b/arch/arm64/include/asm/rsi= _cmds.h index 596bdc356f1a..f72d8e0cd422 100644 --- a/arch/arm64/include/asm/rsi_cmds.h +++ b/arch/arm64/include/asm/rsi_cmds.h @@ -186,4 +186,44 @@ static inline unsigned long rsi_features(unsigned long= index, u64 *out) return res.a0; } =20 +static inline long +rsi_vdev_validate_mapping(unsigned long vdev_id, + phys_addr_t ipa_base, phys_addr_t ipa_top, + phys_addr_t pa_base, phys_addr_t *next_ipa, + unsigned long flags, unsigned long lock_nonce, + unsigned long meas_nonce, unsigned long report_nonce) +{ + struct arm_smccc_1_2_regs res; + struct arm_smccc_1_2_regs regs =3D { + .a0 =3D SMC_RSI_VDEV_VALIDATE_MAPPING, + .a1 =3D vdev_id, + .a2 =3D ipa_base, + .a3 =3D ipa_top, + .a4 =3D pa_base, + .a5 =3D flags, + .a6 =3D lock_nonce, + .a7 =3D meas_nonce, + .a8 =3D report_nonce, + }; + + arm_smccc_1_2_invoke(®s, &res); + *next_ipa =3D res.a1; + + if (res.a2 !=3D RSI_ACCEPT) + return -EPERM; + + return res.a0; +} + +static inline unsigned long rsi_vdev_get_info(unsigned long vdev_id, + unsigned long digest_phys) +{ + struct arm_smccc_res res; + + arm_smccc_1_1_invoke(SMC_RSI_VDEV_GET_INFO, + vdev_id, digest_phys, &res); + + return res.a0; +} + #endif /* __ASM_RSI_CMDS_H */ diff --git a/arch/arm64/include/asm/rsi_smc.h b/arch/arm64/include/asm/rsi_= smc.h index 4af4638fdd49..99b34b37b693 100644 --- a/arch/arm64/include/asm/rsi_smc.h +++ b/arch/arm64/include/asm/rsi_smc.h @@ -125,6 +125,9 @@ =20 #ifndef __ASSEMBLER__ =20 +#define RSI_HASH_SHA_256 0 +#define RSI_HASH_SHA_512 1 + struct realm_config { union { struct { @@ -183,6 +186,63 @@ struct realm_config { */ #define SMC_RSI_IPA_STATE_GET SMC_RSI_FID(0x198) =20 +#define RSI_VDEV_REPORT_FORMAT_TDISP 0x1 +struct rsi_vdevice_info { + union { + struct { + u64 flags; + u64 id_index; + union { + u8 hash_algo; + u64 padding0; + }; + u64 lock_nonce; + u64 meas_nonce; + u64 report_nonce; + union { + u8 format_type; + u64 padding1; + }; + u64 format_version; + union { + u8 state; + u64 padding2; + }; + + }; + u8 padding3[0x80]; + }; + union { /* 0x80 */ + struct { + u8 protocol_data_digest[0x40]; + u8 identity_digest[0x40]; + u8 pubkey_digest[0x40]; + u8 meas_digest[0x40]; + u8 report_digest[0x40]; + }; + u8 padding4[0x1c0 - 0x80]; + }; + union { /* 0x1c0 */ + struct { + u64 vsmmu_addr; + u64 vsmu_vsid; + }; + u8 padding5[0x200 - 0x1c0]; + }; +}; + +/* + * Get information for a device. + * arg1 =3D=3D Realm device identifier (vdev id) + * arg2 =3D=3D IPA to which configuration data will be written + * ret0 =3D=3D Status / error + */ +#define SMC_RSI_VDEV_GET_INFO SMC_RSI_FID(0x19D) + +#define RSI_DEV_MEM_COHERENT BIT(0) +#define RSI_DEV_MEM_LIMITED_ORDER BIT(1) +#define SMC_RSI_VDEV_VALIDATE_MAPPING SMC_RSI_FID(0x19F) + struct rsi_host_call { union { u16 imm; diff --git a/drivers/virt/coco/arm-cca-guest/Kconfig b/drivers/virt/coco/ar= m-cca-guest/Kconfig index d295146bd92a..8ed4b95df5e4 100644 --- a/drivers/virt/coco/arm-cca-guest/Kconfig +++ b/drivers/virt/coco/arm-cca-guest/Kconfig @@ -5,6 +5,8 @@ config ARM_CCA_GUEST tristate "Arm CCA Guest driver" depends on ARM64 select PCI_TSM if PCI + select CRYPTO_LIB_SHA256 + select CRYPTO_LIB_SHA512 select TSM_REPORTS select AUXILIARY_BUS help diff --git a/drivers/virt/coco/arm-cca-guest/arm-cca.c b/drivers/virt/coco/= arm-cca-guest/arm-cca.c index 0f9cfb329a06..320dd5aa7b9a 100644 --- a/drivers/virt/coco/arm-cca-guest/arm-cca.c +++ b/drivers/virt/coco/arm-cca-guest/arm-cca.c @@ -198,39 +198,304 @@ static void unregister_cca_tsm_report(void *data) } =20 #ifdef CONFIG_PCI_TSM + +static int __maybe_unused +cca_update_dev_measurements(struct pci_dev *pdev, const u8 *nonce) +{ + int ret; + void *measurements; + int measurements_size; + int vdev_id =3D rsi_vdev_id(pdev); + struct pci_tsm_evidence *evidence; + struct rsi_vdevice_info *dev_info; + struct pci_tsm_evidence_object *obj; + struct cca_guest_dsc *dsc =3D to_cca_guest_dsc(pdev); + + /* Regenerate the measurement from the device */ + ret =3D rhi_update_vdev_measurements_cache(pdev, nonce); + if (ret) { + pci_err(pdev, "failed to update device measurements from device (%d)\n",= ret); + return ret; + } + + ret =3D rhi_read_cached_object(vdev_id, RHI_DA_OBJECT_MEASUREMENT, + &measurements, &measurements_size); + if (ret) { + pci_err(pdev, "failed to get device measurements from the host (%d)\n", = ret); + return ret; + } + + dev_info =3D kmalloc(sizeof(*dev_info), GFP_KERNEL); + if (!dev_info) { + ret =3D -ENOMEM; + goto free_measurements; + } + + if (rsi_vdev_get_info(vdev_id, virt_to_phys(dev_info))) { + pci_err(pdev, "failed to get device digests (%d)\n", ret); + ret =3D -EIO; + goto free_dev_info; + } + + /* Make sure no unexpected lock/unlock operation happened from guest */ + if (dsc->dev_info.lock_nonce !=3D dev_info->lock_nonce) { + pci_err(pdev, "Unexpected lock/unlock operation from host (%d)\n", ret); + ret =3D -EIO; + goto free_dev_info; + } + + /* + * Verify that the digests of the provided reports match with the + * digests from RMM + */ + ret =3D cca_verify_digest(dev_info->hash_algo, measurements, + measurements_size, dev_info->meas_digest); + if (ret) { + pci_err(pdev, "RMM provided digest mismatch (%d)\n", ret); + goto free_dev_info; + } + + /* fill evidence details */ + evidence =3D &dsc->pci.base_tsm.evidence; + + /* Now update the evidence under lock. */ + down_write(&evidence->lock); + evidence->generation =3D dev_info->meas_nonce; + + obj =3D &evidence->obj[PCI_TSM_EVIDENCE_TYPE_MEASUREMENTS]; + if (obj->data) + kvfree(obj->data); + obj->data =3D measurements; + obj->len =3D measurements_size; + + dsc->dev_info.meas_nonce =3D dev_info->meas_nonce; + memcpy(dsc->dev_info.meas_digest, dev_info->meas_digest, SHA512_DIGEST_SI= ZE); + up_write(&evidence->lock); + + kfree(dev_info); + return 0; + +free_dev_info: + kfree(dev_info); +free_measurements: + kvfree(measurements); + return ret; +} + +static int cca_collect_dev_evidence(struct pci_dev *pdev, struct cca_guest= _dsc *dsc) +{ + int ret; + int vdev_id =3D rsi_vdev_id(pdev); + struct pci_tsm_evidence *evidence; + struct rsi_vdevice_info *dev_info; + struct pci_tsm_evidence_object *obj; + void *certificate, *vca, *interface_report, *measurements; + int certificate_size, vca_size, interface_report_size, measurements_size; + + /* Regenerate interface report and measurement from the device */ + ret =3D cca_update_device_object_cache(pdev, NULL); + if (ret) { + pci_err(pdev, "failed to update device objects from device (%d)\n", ret); + return ret; + } + + ret =3D rhi_read_cached_object(vdev_id, RHI_DA_OBJECT_CERTIFICATE, + &certificate, &certificate_size); + if (ret) { + pci_err(pdev, "failed to get device certificate from the host (%d)\n", r= et); + return ret; + } + + ret =3D rhi_read_cached_object(vdev_id, RHI_DA_OBJECT_VCA, &vca, &vca_siz= e); + if (ret) { + pci_err(pdev, "failed to get device VCA from the host (%d)\n", ret); + goto free_certificate; + } + + ret =3D rhi_read_cached_object(vdev_id, RHI_DA_OBJECT_INTERFACE_REPORT, + &interface_report, &interface_report_size); + if (ret) { + pci_err(pdev, "failed to get interface report from the host (%d)\n", ret= ); + goto free_vca; + } + + ret =3D rhi_read_cached_object(vdev_id, RHI_DA_OBJECT_MEASUREMENT, + &measurements, &measurements_size); + if (ret) { + pci_err(pdev, "failed to get device certificate from the host (%d)\n", r= et); + goto free_interface_report; + } + + dev_info =3D kmalloc(sizeof(*dev_info), GFP_KERNEL); + if (!dev_info) { + ret =3D -ENOMEM; + goto free_measurements; + } + + if (rsi_vdev_get_info(vdev_id, virt_to_phys(dev_info))) { + pci_err(pdev, "failed to get device digests (%d)\n", ret); + ret =3D -EIO; + goto free_dev_info; + } + + /* Make sure no unexpected lock/unlock operation happened from guest */ + if (dsc->dev_info.lock_nonce !=3D dev_info->lock_nonce) { + pci_err(pdev, "Unexpected lock/unlock operation from host (%d)\n", ret); + ret =3D -EIO; + goto free_dev_info; + } + + /* + * Verify that the digests of the provided reports match with the + * digests from RMM + */ + ret =3D cca_verify_digests(dev_info->hash_algo, certificate, + certificate_size, vca, vca_size, + interface_report, interface_report_size, + measurements, measurements_size, dev_info); + if (ret) { + pci_err(pdev, "RMM provided digest mismatch (%d)\n", ret); + goto free_dev_info; + } + + /* fill evidence details */ + evidence =3D &dsc->pci.base_tsm.evidence; + + /* Now update the evidence under lock. */ + down_write(&evidence->lock); + evidence->generation =3D dev_info->meas_nonce; + + /* we default to slot 0 in pdev_create */ + obj =3D &evidence->obj[PCI_TSM_EVIDENCE_TYPE_CERT0]; + WARN_ON(obj->data); + obj->data =3D certificate; + obj->len =3D certificate_size; + + obj =3D &evidence->obj[PCI_TSM_EVIDENCE_TYPE_VCA]; + WARN_ON(obj->data); + obj->data =3D vca; + obj->len =3D vca_size; + + obj =3D &evidence->obj[PCI_TSM_EVIDENCE_TYPE_REPORT]; + WARN_ON(obj->data); + obj->data =3D interface_report; + obj->len =3D interface_report_size; + + obj =3D &evidence->obj[PCI_TSM_EVIDENCE_TYPE_MEASUREMENTS]; + WARN_ON(obj->data); + obj->data =3D measurements; + obj->len =3D measurements_size; + + dsc->dev_info.meas_nonce =3D dev_info->meas_nonce; + dsc->dev_info.report_nonce =3D dev_info->report_nonce; + memcpy(dsc->dev_info.cert_digest, dev_info->identity_digest, SHA512_DIGES= T_SIZE); + memcpy(dsc->dev_info.vca_digest, dev_info->protocol_data_digest, SHA512_D= IGEST_SIZE); + memcpy(dsc->dev_info.meas_digest, dev_info->meas_digest, SHA512_DIGEST_SI= ZE); + memcpy(dsc->dev_info.report_digest, dev_info->report_digest, SHA512_DIGES= T_SIZE); + up_write(&evidence->lock); + + kfree(dev_info); + return 0; + +free_dev_info: + kfree(dev_info); +free_measurements: + kvfree(measurements); +free_interface_report: + kvfree(interface_report); +free_vca: + kvfree(vca); +free_certificate: + kvfree(certificate); + return ret; +} + static struct pci_tsm *cca_tsm_lock(struct tsm_dev *tsm_dev, struct pci_de= v *pdev) { int ret; + enum hash_algo digest_algo; + struct cca_guest_dsc *cca_dsc; + int vdev_id =3D rsi_vdev_id(pdev); + struct rsi_vdevice_info *dev_info; =20 - struct cca_guest_dsc *cca_dsc __free(kfree) =3D - kzalloc_obj(struct cca_guest_dsc); + cca_dsc =3D kzalloc_obj(struct cca_guest_dsc); if (!cca_dsc) return ERR_PTR(-ENOMEM); =20 ret =3D pci_tsm_devsec_constructor(pdev, &cca_dsc->pci, tsm_dev); if (ret) - return ERR_PTR(ret); + goto free_cca_dsc; =20 ret =3D cca_device_lock(pdev); if (ret) - return ERR_PTR(ret); + goto free_cca_dsc; =20 - /* collect evidence without nonce */ - ret =3D cca_update_device_object_cache(pdev, NULL); - if (ret) { - cca_device_unlock(pdev); - return ERR_PTR(ret); + dev_info =3D kmalloc_obj(struct rsi_vdevice_info); + if (!dev_info) { + ret =3D -ENOMEM; + goto dev_unlock; + } + + if (rsi_vdev_get_info(vdev_id, virt_to_phys(dev_info))) { + ret =3D -EIO; + goto free_dev_info; + } + + /* collect the lock nonce */ + cca_dsc->dev_info.lock_nonce =3D dev_info->lock_nonce; + + switch (dev_info->hash_algo) { + case RSI_HASH_SHA_256: + digest_algo =3D HASH_ALGO_SHA256; + break; + case RSI_HASH_SHA_512: + digest_algo =3D HASH_ALGO_SHA512; + break; + default: + ret =3D -EIO; + goto free_dev_info; } + pci_tsm_init_evidence(&cca_dsc->pci.base_tsm.evidence, + dev_info->id_index, digest_algo); =20 - return &no_free_ptr(cca_dsc)->pci.base_tsm; + /* collect evidence without nonce */ + ret =3D cca_collect_dev_evidence(pdev, cca_dsc); + if (ret) + goto free_dev_info; + + kfree(dev_info); + return &cca_dsc->pci.base_tsm; + +free_dev_info: + kfree(dev_info); +dev_unlock: + cca_device_unlock(pdev); +free_cca_dsc: + kfree(cca_dsc); + return ERR_PTR(ret); } =20 static void cca_tsm_unlock(struct pci_tsm *tsm) { - struct cca_guest_dsc *cca_dsc =3D to_cca_guest_dsc(tsm->pdev); + long ret; + struct pci_dev *pdev =3D tsm->pdev; + struct cca_guest_dsc *cca_dsc =3D to_cca_guest_dsc(pdev); + + /* invalidate dev mapping based on interface report */ + ret =3D cca_unmap_evidence_report_range(tsm->pdev); + if (ret) { + pci_err(tsm->pdev, "failed to invalidate the interface report\n"); + goto err_out; + } =20 cca_device_unlock(tsm->pdev); + pci_tsm_mmio_teardown(cca_dsc->pci.mmio); =20 +err_out: + /* + * No error handling from this function. Leave the device locked + */ + pci_tsm_mmio_free(tsm->pdev, cca_dsc->pci.mmio); kfree(cca_dsc); } =20 diff --git a/drivers/virt/coco/arm-cca-guest/rsi-da.c b/drivers/virt/coco/a= rm-cca-guest/rsi-da.c index 9f9e54174813..039138768f8f 100644 --- a/drivers/virt/coco/arm-cca-guest/rsi-da.c +++ b/drivers/virt/coco/arm-cca-guest/rsi-da.c @@ -6,6 +6,7 @@ #include #include #include +#include =20 #include "rsi-da.h" #include "rhi-da.h" @@ -85,3 +86,147 @@ int cca_update_device_object_cache(struct pci_dev *pdev= , const u8 *nonce) =20 return rhi_update_vdev_measurements_cache(pdev, nonce); } + +static inline int +rsi_validate_dev_mapping(unsigned long vdev_id, phys_addr_t start_ipa, + phys_addr_t end_ipa, phys_addr_t io_pa, + unsigned long flags, unsigned long lock_nonce, + unsigned long meas_nonce, unsigned long report_nonce) +{ + unsigned long ret; + phys_addr_t next_ipa; + + while (start_ipa < end_ipa) { + ret =3D rsi_vdev_validate_mapping(vdev_id, start_ipa, end_ipa, + io_pa, &next_ipa, flags, + lock_nonce, meas_nonce, report_nonce); + if (ret || next_ipa <=3D start_ipa || next_ipa > end_ipa) + return -EINVAL; + io_pa +=3D next_ipa - start_ipa; + start_ipa =3D next_ipa; + } + return 0; +} + +static inline int rsi_invalidate_dev_mapping(phys_addr_t start_ipa, phys_a= ddr_t end_ipa) +{ + return rsi_set_memory_range(start_ipa, end_ipa, RSI_RIPAS_EMPTY, + RSI_CHANGE_DESTROYED); +} + +static int cca_apply_evidence_report_range(struct pci_dev *pdev, + struct pci_tsm_mmio *mmio, bool map) +{ + int i, ret; + struct resource *res; + unsigned long mmio_flags =3D 0; /* non coherent, not limited order */ + int vdev_id =3D rsi_vdev_id(pdev); + struct pci_tsm_mmio_entry *entry; + struct cca_guest_dsc *dsc =3D to_cca_guest_dsc(pdev); + + for (i =3D 0; i < mmio->nr; i++) { + entry =3D pci_tsm_mmio_entry(mmio, i); + res =3D &entry->res; + + if (res->desc !=3D IORES_DESC_ENCRYPTED) + continue; + + if (map) + ret =3D rsi_validate_dev_mapping(vdev_id, res->start, + res->end + 1, entry->tsm_offset, + mmio_flags, + dsc->dev_info.lock_nonce, + dsc->dev_info.meas_nonce, + dsc->dev_info.report_nonce); + else + ret =3D rsi_invalidate_dev_mapping(res->start, res->end + 1); + if (ret) + return ret; + } + return 0; +} + +int cca_map_evidence_report_range(struct pci_dev *pdev, struct pci_tsm_mmi= o *mmio) +{ + return cca_apply_evidence_report_range(pdev, mmio, true); +} + +int cca_unmap_evidence_report_range(struct pci_dev *pdev) +{ + struct cca_guest_dsc *dsc =3D to_cca_guest_dsc(pdev); + struct pci_tsm_mmio *tsm_mmio =3D dsc->pci.mmio; + + return cca_apply_evidence_report_range(pdev, tsm_mmio, false); +} + +int cca_verify_digest(u64 hash_algo, uint8_t *report, + size_t report_size, uint8_t *report_digest) +{ + u8 digest[SHA512_DIGEST_SIZE]; + size_t digest_size; + void (*digest_func)(const u8 *data, size_t len, u8 *out); + + switch (hash_algo) { + case RSI_HASH_SHA_256: + digest_func =3D sha256; + digest_size =3D SHA256_DIGEST_SIZE; + break; + case RSI_HASH_SHA_512: + digest_func =3D sha512; + digest_size =3D SHA512_DIGEST_SIZE; + break; + default: + return -EINVAL; + } + + digest_func(report, report_size, digest); + if (memcmp(report_digest, digest, digest_size)) + return -EINVAL; + + return 0; +} + +int cca_verify_digests(u64 hash_algo, + uint8_t *certificate, size_t certificate_size, + uint8_t *vca, size_t vca_size, + uint8_t *interface_report, size_t interface_report_size, + uint8_t *measurements, size_t measurements_size, + struct rsi_vdevice_info *dev_info) +{ + int ret; + struct { + uint8_t *report; + size_t size; + uint8_t *digest; + } reports[] =3D { + { + certificate, + certificate_size, + dev_info->identity_digest + }, + { + vca, + vca_size, + dev_info->protocol_data_digest + }, + { + interface_report, + interface_report_size, + dev_info->report_digest + }, + { + measurements, + measurements_size, + dev_info->meas_digest + } + + }; + + for (int i =3D 0; i < ARRAY_SIZE(reports); i++) { + ret =3D cca_verify_digest(hash_algo, reports[i].report, + reports[i].size, reports[i].digest); + if (ret) + return ret; + } + return 0; +} diff --git a/drivers/virt/coco/arm-cca-guest/rsi-da.h b/drivers/virt/coco/a= rm-cca-guest/rsi-da.h index 88067d2230ab..07a044d3e335 100644 --- a/drivers/virt/coco/arm-cca-guest/rsi-da.h +++ b/drivers/virt/coco/arm-cca-guest/rsi-da.h @@ -9,11 +9,23 @@ #include #include #include +#include =20 #define MAX_CACHE_OBJ_SIZE SZ_16M =20 +struct dsm_device_info { + u64 lock_nonce; + u64 meas_nonce; + u64 report_nonce; + u8 cert_digest[SHA512_DIGEST_SIZE]; + u8 vca_digest[SHA512_DIGEST_SIZE]; + u8 meas_digest[SHA512_DIGEST_SIZE]; + u8 report_digest[SHA512_DIGEST_SIZE]; +}; + struct cca_guest_dsc { struct pci_tsm_devsec pci; + struct dsm_device_info dev_info; }; =20 static inline struct cca_guest_dsc *to_cca_guest_dsc(struct pci_dev *pdev) @@ -39,5 +51,15 @@ int cca_device_unlock(struct pci_dev *pdev); int cca_update_device_object_cache(struct pci_dev *pdev, const u8 *nonce); struct page *alloc_shared_pages(int nid, gfp_t gfp_mask, unsigned long min= _size); int free_shared_pages(struct page *page, unsigned long min_size); +int cca_map_evidence_report_range(struct pci_dev *pdev, struct pci_tsm_mmi= o *mmio); +int cca_unmap_evidence_report_range(struct pci_dev *pdev); +int cca_verify_digest(u64 hash_algo, uint8_t *report, + size_t report_size, uint8_t *report_digest); +int cca_verify_digests(u64 hash_algo, + uint8_t *certificate, size_t certificate_size, + uint8_t *vca, size_t vca_size, + uint8_t *interface_report, size_t interface_report_size, + uint8_t *measurements, size_t measurements_size, + struct rsi_vdevice_info *dev_info); =20 #endif --=20 2.43.0 From nobody Thu Jun 11 03:18:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B0FBC39C649; Mon, 27 Apr 2026 08:29:01 +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=1777278541; cv=none; b=owK9JBiREu9j4W58qDaicXzANi8YUZjQzYa/bXZ9TI2kS5nZBmKS5Vv82wBn6dfy5csACVUCCQuRjC81+Lb7Gm2gABZTkWAEVYM14JihhbnVtPM6CEyvi1t21O8EJFQdPPRb+rx0JD4zptSz8Z3Q2qnsMR3EuxaZka+DhMVyHOU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777278541; c=relaxed/simple; bh=UqzR/91cMXtsVPaYNh22dFqFyvgw+gFdrAZVLiKKdbU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=I80duCtvyYyeGBc5hMHC7+hV+aRLEY5GlBElnyK8AZ5a3eZgYACq5Ec4QIN6uzaR6pXzTWYNKkkjSs1z4GNIPEHZKv2l1xfMlK+hYz8kr1iIOqQIV+2s2KlKkAUPK0/xZSXBq7mYyysPY6+MuSx/6QcHPZ93E6ymm57tkvKa1Ic= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hzORlFTC; 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="hzORlFTC" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B4912C19425; Mon, 27 Apr 2026 08:28:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777278541; bh=UqzR/91cMXtsVPaYNh22dFqFyvgw+gFdrAZVLiKKdbU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hzORlFTCg8Ml22jww/RSI0Grz/L/0in7g/0z11wdgbHJzhdgnrwARXHQF2dsUQSTV RVK7uAUABqaOR+XERlmU+MLbp7O1i9/neHOEBIZqVeIr1Yl0u7fmQVfIB5EorSsgK0 0v5SM0081Nv9QqFIJpZuSlfJzOIODkg8n6dTu1AUvoRcrDLQUtL7P7JTQdG5DIMFUy cmi1/aVEsCSbXVAHcJYnSn4HEAp27kviuoGk6XvJdQCfi9qqDpWCEbuxygAgSNZ4pJ p5q+3MNuoRtFmuNcUcU3Lkq3Zf8biREzVU9KL0O2oxUwwwPbJnKhWM7ztpODvU9oxS A4NxXu74akg1A== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Alexey Kardashevskiy , Catalin Marinas , Dan Williams , Jason Gunthorpe , Jonathan Cameron , Marc Zyngier , Samuel Ortiz , Steven Price , Suzuki K Poulose , Will Deacon , Xu Yilun , Jonathan Cameron Subject: [RFC PATCH v4 09/11] coco: guest: arm64: Hook TSM accept to Realm TDISP RUN transition Date: Mon, 27 Apr 2026 13:58:03 +0530 Message-ID: <20260427082805.931832-10-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260427082805.931832-1-aneesh.kumar@kernel.org> References: <20260427082805.931832-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 an accept callback in pci_tsm_ops and implement cca_device_accept() to: - verify evidence generation (lock_nonce) - allocate and register protected MMIO ranges - transition TDI state to RUN Reviewed-by: Jonathan Cameron Signed-off-by: Aneesh Kumar K.V (Arm) --- drivers/virt/coco/arm-cca-guest/arm-cca.c | 20 +++++++++++ drivers/virt/coco/arm-cca-guest/rsi-da.c | 43 +++++++++++++++++++++++ drivers/virt/coco/arm-cca-guest/rsi-da.h | 1 + 3 files changed, 64 insertions(+) diff --git a/drivers/virt/coco/arm-cca-guest/arm-cca.c b/drivers/virt/coco/= arm-cca-guest/arm-cca.c index 320dd5aa7b9a..b29b3948a454 100644 --- a/drivers/virt/coco/arm-cca-guest/arm-cca.c +++ b/drivers/virt/coco/arm-cca-guest/arm-cca.c @@ -499,9 +499,29 @@ static void cca_tsm_unlock(struct pci_tsm *tsm) kfree(cca_dsc); } =20 +static int __cca_tsm_accept(struct pci_dev *pdev, unsigned long lock_nonce) +{ + int ret; + + ret =3D cca_device_accept(pdev, lock_nonce); + if (ret) { + pci_err(pdev, "failed to transition the device to run state (%d)\n", ret= ); + return ret; + } + return 0; +} + +static int cca_tsm_accept(struct pci_dev *pdev) +{ + struct cca_guest_dsc *dsc =3D to_cca_guest_dsc(pdev); + + return __cca_tsm_accept(pdev, dsc->dev_info.lock_nonce); +} + static struct pci_tsm_ops cca_devsec_pci_ops =3D { .lock =3D cca_tsm_lock, .unlock =3D cca_tsm_unlock, + .accept =3D cca_tsm_accept, }; =20 static void cca_devsec_tsm_remove(void *tsm_dev) diff --git a/drivers/virt/coco/arm-cca-guest/rsi-da.c b/drivers/virt/coco/a= rm-cca-guest/rsi-da.c index 039138768f8f..7c2b28fa43a1 100644 --- a/drivers/virt/coco/arm-cca-guest/rsi-da.c +++ b/drivers/virt/coco/arm-cca-guest/rsi-da.c @@ -230,3 +230,46 @@ int cca_verify_digests(u64 hash_algo, } return 0; } + +int cca_device_accept(struct pci_dev *pdev, unsigned long lock_nonce) +{ + int ret; + struct cca_guest_dsc *dsc =3D to_cca_guest_dsc(pdev); + + if (lock_nonce !=3D dsc->dev_info.lock_nonce) { + pci_err(pdev, "Device evidence generation mismatch\n"); + return -EIO; + } + + /* Allocation private mmio range based on interface report. */ + struct pci_tsm_mmio *tsm_mmio __free(kfree) =3D pci_tsm_mmio_alloc(pdev); + if (!tsm_mmio) { + pci_err(pdev, "Protected mmio range allocation failure\n"); + return -ENOMEM; + } + + /* + * Present the private mmio range in the resource hierarchy. + * We don't use this for ioremap, ioremap check the RIPAS value. + */ + ret =3D pci_tsm_mmio_setup(pdev, tsm_mmio); + if (ret) { + pci_err(pdev, "Protected mmio setup failure\n"); + return ret; + } + + ret =3D cca_map_evidence_report_range(pdev, tsm_mmio); + if (ret) { + pci_err(pdev, "failed to validate the interface report\n"); + return ret; + } + + ret =3D rhi_vdev_set_tdi_state(pdev, RHI_DA_TDI_CONFIG_RUN); + if (ret) { + pci_err(pdev, "failed to switch the device (%u) to RUN state\n", ret); + return ret; + } + + dsc->pci.mmio =3D no_free_ptr(tsm_mmio); + return 0; +} diff --git a/drivers/virt/coco/arm-cca-guest/rsi-da.h b/drivers/virt/coco/a= rm-cca-guest/rsi-da.h index 07a044d3e335..eeb049d374c5 100644 --- a/drivers/virt/coco/arm-cca-guest/rsi-da.h +++ b/drivers/virt/coco/arm-cca-guest/rsi-da.h @@ -61,5 +61,6 @@ int cca_verify_digests(u64 hash_algo, uint8_t *interface_report, size_t interface_report_size, uint8_t *measurements, size_t measurements_size, struct rsi_vdevice_info *dev_info); +int cca_device_accept(struct pci_dev *pdev, unsigned long lock_nonce); =20 #endif --=20 2.43.0 From nobody Thu Jun 11 03:18:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4B59439B975; Mon, 27 Apr 2026 08:29:07 +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=1777278547; cv=none; b=EYX15qVTlbw8x7kktojSUE+W1jYz85YGnCwrY81OTmXFyTCIGy/HwmQC/0bXmE1GP/f3zOwwC9QqEA2PWC01098WI+PvB0KpZLhnJT9v5l7PE/7rPt68SGnQ92fR+fCqwn3/09yZluUSp7Daw/IU2KDCr8YNqjdBXveN/QlyZXo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777278547; c=relaxed/simple; bh=5SU9hiceDEieVMjK83mZntxO9wZ9JXg8R4Ezb9ZyoxM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=mLNz9RafgSL2B0zQ7i7Yk5IO2io23LW+/gWjFH66GsdzLV6S3+ATkL1i8SVRncNHfWCod0VJjYD691ne33KsSdyTahfG0QLSv/fCi2/yLNxkYglFNtfcVKkQXEDPSmBlQ7Tm5zrZ4HnDskf9vKVOgI/XnczZvYY3lNr3igiZGTs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KkSZ/ppe; 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="KkSZ/ppe" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 37188C2BCB4; Mon, 27 Apr 2026 08:29:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777278546; bh=5SU9hiceDEieVMjK83mZntxO9wZ9JXg8R4Ezb9ZyoxM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=KkSZ/ppesy61ker3Jkwkk5hTM+fFQXy4GJV7E2cfaeCXf21wVzfeHmS3kvwg/mxGM FD+ER02Sl8HpdWe7jAD2H6ooHDXq9EfAX3wUp8ZbdnN4nYAPfeDaKbD1u13v1bRKfc HRdDs7j5FB3er+3KMKTPrgXAZvoH9wZgi22oz/i4H+PBuWZmG1N38Pgnq8GGzXnWKE dyQEqUSXoTTr3wdydX/C06qwbVKvvzhRg+wdstXy/FFLIcrV/Gq2v+4Ps6erU1bJr6 hjpywogzfZ2A0AyMbjFBXRw4QTD56jG0LoF0P9fwxEX6nMPPI45OFQxmlejN7xWBRe 9l0tjqhIKljCw== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Alexey Kardashevskiy , Catalin Marinas , Dan Williams , Jason Gunthorpe , Jonathan Cameron , Marc Zyngier , Samuel Ortiz , Steven Price , Suzuki K Poulose , Will Deacon , Xu Yilun Subject: [RFC PATCH v4 10/11] coco: arm64: dma: Update force_dma_unencrypted for accepted devices Date: Mon, 27 Apr 2026 13:58:04 +0530 Message-ID: <20260427082805.931832-11-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260427082805.931832-1-aneesh.kumar@kernel.org> References: <20260427082805.931832-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 This change updates the DMA behavior for accepted devices by assuming they access only private memory. Currently, the DMA API does not provide a mechanism for allocating shared memory that can be accessed by both the secure realm and the non-secure host. Accepted devices are therefore expected to operate entirely within the private memory space. If future use cases require accepted devices to interact with shared memory=E2=80=94 for example, for host-device communication, we will need to extend the DMA interface to support such allocation semantics. This commit lays the groundwork for that by clearly defining the current assumption and isolating the enforcement to force_dma_unencrypted. Treat swiotlb and decrypted DMA pools as shared-memory paths and avoid them for accepted devices by: - returning false from is_swiotlb_for_alloc() for accepted devices - returning false from is_swiotlb_active() for accepted devices - bypassing dma-direct atomic pool usage for accepted devices This is based on the current assumption that accepted devices operate on pr= ivate Realm memory only, and prevents accidental fallback to shared/decrypted DMA backends. Signed-off-by: Aneesh Kumar K.V (Arm) --- arch/arm64/include/asm/mem_encrypt.h | 6 +----- arch/arm64/mm/mem_encrypt.c | 10 ++++++++++ include/linux/swiotlb.h | 3 +++ kernel/dma/direct.c | 8 ++++++++ kernel/dma/swiotlb.c | 3 +++ 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/arch/arm64/include/asm/mem_encrypt.h b/arch/arm64/include/asm/= mem_encrypt.h index 5541911eb028..ae0b0cac0900 100644 --- a/arch/arm64/include/asm/mem_encrypt.h +++ b/arch/arm64/include/asm/mem_encrypt.h @@ -15,17 +15,13 @@ int arm64_mem_crypt_ops_register(const struct arm64_mem= _crypt_ops *ops); =20 int set_memory_encrypted(unsigned long addr, int numpages); int set_memory_decrypted(unsigned long addr, int numpages); +bool force_dma_unencrypted(struct device *dev); =20 #define mem_decrypt_granule_size mem_decrypt_granule_size size_t mem_decrypt_granule_size(void); =20 int realm_register_memory_enc_ops(void); =20 -static inline bool force_dma_unencrypted(struct device *dev) -{ - return is_realm_world(); -} - /* * For Arm CCA guests, canonical addresses are "encrypted", so no changes * required for dma_addr_encrypted(). diff --git a/arch/arm64/mm/mem_encrypt.c b/arch/arm64/mm/mem_encrypt.c index f5d64bc29c20..18dea5d879b8 100644 --- a/arch/arm64/mm/mem_encrypt.c +++ b/arch/arm64/mm/mem_encrypt.c @@ -18,6 +18,7 @@ #include #include #include +#include =20 static const struct arm64_mem_crypt_ops *crypt_ops; =20 @@ -67,3 +68,12 @@ size_t mem_decrypt_granule_size(void) return PAGE_SIZE; } EXPORT_SYMBOL_GPL(mem_decrypt_granule_size); + +bool force_dma_unencrypted(struct device *dev) +{ + if (device_cc_accepted(dev)) + return false; + + return is_realm_world(); +} +EXPORT_SYMBOL_GPL(force_dma_unencrypted); diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h index 0efb9b8e5dd0..224dcec6a58f 100644 --- a/include/linux/swiotlb.h +++ b/include/linux/swiotlb.h @@ -296,6 +296,9 @@ bool swiotlb_free(struct device *dev, struct page *page= , size_t size); =20 static inline bool is_swiotlb_for_alloc(struct device *dev) { + if (device_cc_accepted(dev)) + return false; + return dev->dma_io_tlb_mem->for_alloc; } #else diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c index 34eccd047e9b..a7a9984db342 100644 --- a/kernel/dma/direct.c +++ b/kernel/dma/direct.c @@ -158,6 +158,14 @@ static struct page *__dma_direct_alloc_pages(struct de= vice *dev, size_t size, */ static bool dma_direct_use_pool(struct device *dev, gfp_t gfp) { + /* + * Atomic pools are marked decrypted and are used if we require + * updation of pfn mem encryption attributes or for DMA non-coherent + * device allocation. Both is not true for trusted device. + */ + if (device_cc_accepted(dev)) + return false; + return !gfpflags_allow_blocking(gfp) && !is_swiotlb_for_alloc(dev); } =20 diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c index c94abc2dcae3..f0d4b9f799bf 100644 --- a/kernel/dma/swiotlb.c +++ b/kernel/dma/swiotlb.c @@ -1651,6 +1651,9 @@ bool is_swiotlb_active(struct device *dev) { struct io_tlb_mem *mem =3D dev->dma_io_tlb_mem; =20 + if (device_cc_accepted(dev)) + return false; + return mem && mem->nslabs; } =20 --=20 2.43.0 From nobody Thu Jun 11 03:18:11 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9E41039B975; Mon, 27 Apr 2026 08:29:12 +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=1777278552; cv=none; b=APHMPfdqsYppL+8K6vs+KP+RgMrw23pGbZNPDeWnt/qGp8cpdHJ1xhlEaK6ajHKNipJ+ZM7tRT+isqAL97rLYY+xXgR6Q+sEEtPHnVJgP9b9d5T2yWdvJ03dBj91WcRUL4rauyHcR51n2oXXp/E4mjFukEzt02KS8fT6ROzTzDA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777278552; c=relaxed/simple; bh=yxjevm5oUKp+Ad1dbtRsU+HvpruAP9tlDylolCjcQ68=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=O43U/KK4Cfrn3AVXII1KbBRES0JFZuJG+hgBmHNt+u9DXquvwl3RcawGKYwy+9X0U+ECYeA75vxjYQxHkQ7XNWheJqoeVBYggb6lj0kl91hRnNqLPlZJOXnsQp3Lj6o5c1Gv13xWPETe+7fwesr87pAYx5jOmssrx3R8KDKtn6Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=BdZ6qEdV; 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="BdZ6qEdV" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 77652C19425; Mon, 27 Apr 2026 08:29:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1777278552; bh=yxjevm5oUKp+Ad1dbtRsU+HvpruAP9tlDylolCjcQ68=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BdZ6qEdV33fGBqfrtAflGDSklSvA6FcI9KLrVk1QUhbCkYpPMy/ZkPSrpPVgc6/um lUREXGnjfWyG88dp9nr3czFBv/PMa5A1EIs4YjlhdPVar1qCP/MKls/M2vcLSyUalq Lfyp3BlIQhmP/P133zjsn7g9O7o6/RkRmK7gu8UL9lu0APc/s6VN2UpmEYV8no7JrS G4FXJQS+WpeqV6ym/+UCkV47BKJfAab7qruaGsBbPyxjcsBIjMlntgUPsGNT1FXcGy 7nMV1b1pQFrtsP4TtOjzMy0pzSqqDJD7NixxXxu3D6LR86pV4YKNpBGilq8VsVOdIs Lv4QSltx5nDZQ== From: "Aneesh Kumar K.V (Arm)" To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: "Aneesh Kumar K.V (Arm)" , Alexey Kardashevskiy , Catalin Marinas , Dan Williams , Jason Gunthorpe , Jonathan Cameron , Marc Zyngier , Samuel Ortiz , Steven Price , Suzuki K Poulose , Will Deacon , Xu Yilun , Jonathan Cameron Subject: [RFC PATCH v4 11/11] coco: guest: arm64: Enable vdev DMA after attestation Date: Mon, 27 Apr 2026 13:58:05 +0530 Message-ID: <20260427082805.931832-12-aneesh.kumar@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260427082805.931832-1-aneesh.kumar@kernel.org> References: <20260427082805.931832-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" - define SMC_RSI_VDEV_DMA_ENABLE and add wrapper in rsi_cmds.h - invoke the new helper from the guest accept path once the device passes attestation, rolling back to TDI_LOCKED on failure Reviewed-by: Jonathan Cameron Signed-off-by: Aneesh Kumar K.V (Arm) --- arch/arm64/include/asm/rsi_cmds.h | 16 ++++++++++++++++ arch/arm64/include/asm/rsi_smc.h | 2 ++ drivers/virt/coco/arm-cca-guest/rsi-da.c | 14 ++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/arch/arm64/include/asm/rsi_cmds.h b/arch/arm64/include/asm/rsi= _cmds.h index f72d8e0cd422..1e0d1cd8841a 100644 --- a/arch/arm64/include/asm/rsi_cmds.h +++ b/arch/arm64/include/asm/rsi_cmds.h @@ -226,4 +226,20 @@ static inline unsigned long rsi_vdev_get_info(unsigned= long vdev_id, return res.a0; } =20 +static inline unsigned long __rsi_vdev_dma_enable(unsigned long vdev_id, + unsigned long flags, + unsigned long non_ats_plane, + unsigned long lock_nonce, + unsigned long meas_nonce, + unsigned long report_nonce) +{ + struct arm_smccc_res res; + + arm_smccc_1_1_invoke(SMC_RSI_VDEV_DMA_ENABLE, vdev_id, flags, + non_ats_plane, lock_nonce, + meas_nonce, report_nonce, &res); + + return res.a0; +} + #endif /* __ASM_RSI_CMDS_H */ diff --git a/arch/arm64/include/asm/rsi_smc.h b/arch/arm64/include/asm/rsi_= smc.h index 99b34b37b693..1d98a3b47c89 100644 --- a/arch/arm64/include/asm/rsi_smc.h +++ b/arch/arm64/include/asm/rsi_smc.h @@ -186,6 +186,8 @@ struct realm_config { */ #define SMC_RSI_IPA_STATE_GET SMC_RSI_FID(0x198) =20 +#define SMC_RSI_VDEV_DMA_ENABLE SMC_RSI_FID(0x19C) + #define RSI_VDEV_REPORT_FORMAT_TDISP 0x1 struct rsi_vdevice_info { union { diff --git a/drivers/virt/coco/arm-cca-guest/rsi-da.c b/drivers/virt/coco/a= rm-cca-guest/rsi-da.c index 7c2b28fa43a1..77267479df19 100644 --- a/drivers/virt/coco/arm-cca-guest/rsi-da.c +++ b/drivers/virt/coco/arm-cca-guest/rsi-da.c @@ -231,9 +231,17 @@ int cca_verify_digests(u64 hash_algo, return 0; } =20 +static inline int rsi_vdev_enable_dma(int vdev_id, struct dsm_device_info = *dev_info) +{ + /* No ATS support */ + return __rsi_vdev_dma_enable(vdev_id, 0, 0, dev_info->lock_nonce, + dev_info->meas_nonce, dev_info->report_nonce); +} + int cca_device_accept(struct pci_dev *pdev, unsigned long lock_nonce) { int ret; + int vdev_id =3D rsi_vdev_id(pdev); struct cca_guest_dsc *dsc =3D to_cca_guest_dsc(pdev); =20 if (lock_nonce !=3D dsc->dev_info.lock_nonce) { @@ -270,6 +278,12 @@ int cca_device_accept(struct pci_dev *pdev, unsigned l= ong lock_nonce) return ret; } =20 + if (rsi_vdev_enable_dma(vdev_id, &dsc->dev_info)) { + rhi_vdev_set_tdi_state(pdev, RHI_DA_TDI_CONFIG_LOCKED); + pci_err(pdev, "failed to enable DMA from the device\n"); + return -EIO; + } + dsc->pci.mmio =3D no_free_ptr(tsm_mmio); return 0; } --=20 2.43.0