From: "Aneesh Kumar K.V (Arm)" <aneesh.kumar@kernel.org>
To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev,
linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org,
"Aneesh Kumar K.V (Arm)" <aneesh.kumar@kernel.org>,
Marc Zyngier <maz@kernel.org>,
Catalin Marinas <catalin.marinas@arm.com>,
Will Deacon <will@kernel.org>,
Jonathan Cameron <Jonathan.Cameron@huawei.com>,
Jason Gunthorpe <jgg@ziepe.ca>,
Dan Williams <dan.j.williams@intel.com>,
Alexey Kardashevskiy <aik@amd.com>,
Samuel Ortiz <sameo@rivosinc.com>,
Xu Yilun <yilun.xu@linux.intel.com>,
Suzuki K Poulose <Suzuki.Poulose@arm.com>,
Steven Price <steven.price@arm.com>
Subject: [RFC PATCH v3 03/11] coco: guest: arm64: Add Realm Host Interface and guest DA helper
Date: Thu, 12 Mar 2026 13:34:34 +0530 [thread overview]
Message-ID: <20260312080442.3485633-4-aneesh.kumar@kernel.org> (raw)
In-Reply-To: <20260312080442.3485633-1-aneesh.kumar@kernel.org>
- 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.
Cc: Marc Zyngier <maz@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Alexey Kardashevskiy <aik@amd.com>
Cc: Samuel Ortiz <sameo@rivosinc.com>
Cc: Xu Yilun <yilun.xu@linux.intel.com>
Cc: Suzuki K Poulose <Suzuki.Poulose@arm.com>
Cc: Steven Price <steven.price@arm.com>
Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
---
arch/arm64/include/asm/rhi.h | 37 +++++
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 | 158 ++++++++++++++++++++++
drivers/virt/coco/arm-cca-guest/rhi-da.h | 14 ++
5 files changed, 212 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..029ccd77cfbf 100644
--- a/arch/arm64/include/asm/rhi.h
+++ b/arch/arm64/include/asm/rhi.h
@@ -21,4 +21,41 @@ 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_ERROR_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/arm-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) += arm-cca-guest.o
arm-cca-guest-y += arm-cca.o
+arm-cca-guest-$(CONFIG_PCI_TSM) += 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 1d78727702be..07f74f67d22c 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 @@
#ifdef CONFIG_PCI_TSM
#include "rsi-da.h"
+#include "rhi-da.h"
#endif
/**
@@ -265,7 +266,7 @@ static int cca_devsec_tsm_probe(struct auxiliary_device *adev,
#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
diff --git a/drivers/virt/coco/arm-cca-guest/rhi-da.c b/drivers/virt/coco/arm-cca-guest/rhi-da.c
new file mode 100644
index 000000000000..0a04c0ec9320
--- /dev/null
+++ b/drivers/virt/coco/arm-cca-guest/rhi-da.c
@@ -0,0 +1,158 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2026 ARM Ltd.
+ */
+
+#include "rsi-da.h"
+#include "rhi-da.h"
+
+/* return value to indicate the need to call rhi_vdev_continue*/
+#define E_INCOMPLETE 1
+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_ERROR_INCOMPLETE:
+ return E_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) =
+ kmalloc(sizeof(*rhi_call), GFP_KERNEL);
+ if (!rhi_call)
+ return -ENOMEM;
+
+ rhi_call->imm = 0;
+ rhi_call->gprs[0] = RHI_DA_FEATURES;
+
+ ret = rsi_host_call(rhi_call);
+ if (ret != RSI_SUCCESS || rhi_call->gprs[0] == SMCCC_RET_NOT_SUPPORTED)
+ return false;
+
+ /* For base DA to work we need these to be supported */
+ if ((rhi_call->gprs[0] & RHI_DA_BASE_FEATURE) == RHI_DA_BASE_FEATURE)
+ return true;
+
+ return false;
+}
+
+static inline int rhi_vdev_continue(unsigned long vdev_id, unsigned long cookie)
+{
+ unsigned long ret;
+
+ struct rsi_host_call *rhi_call __free(kfree) =
+ kmalloc(sizeof(*rhi_call), GFP_KERNEL);
+ if (!rhi_call)
+ return -ENOMEM;
+
+ rhi_call->imm = 0;
+ rhi_call->gprs[0] = RHI_DA_VDEV_CONTINUE;
+ rhi_call->gprs[1] = vdev_id;
+ rhi_call->gprs[2] = cookie;
+
+ ret = rsi_host_call(rhi_call);
+ if (ret != 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) =
+ kmalloc(sizeof(struct rsi_host_call), GFP_KERNEL);
+ if (!rhi_call)
+ return -ENOMEM;
+
+ rhi_call->imm = 0;
+ rhi_call->gprs[0] = RHI_DA_VDEV_ABORT;
+ rhi_call->gprs[1] = vdev_id;
+
+ ret = rsi_host_call(rhi_call);
+ if (ret != RSI_SUCCESS)
+ return -EIO;
+
+ *da_error = 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 = __rhi_vdev_abort(vdev_id, &da_error);
+ /* consider all kind of error as not aborted */
+ if (!ret && (da_error == 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) =
+ kmalloc(sizeof(struct rsi_host_call), GFP_KERNEL);
+ if (!rhi_call)
+ return -ENOMEM;
+
+ rhi_call->imm = 0;
+ rhi_call->gprs[0] = RHI_DA_VDEV_SET_TDI_STATE;
+ rhi_call->gprs[1] = vdev_id;
+ rhi_call->gprs[2] = target_state;
+
+ ret = rsi_host_call(rhi_call);
+ if (ret != RSI_SUCCESS)
+ return -EIO;
+
+ *cookie = 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 = rsi_vdev_id(pdev);
+
+ for (;;) {
+ ret = __rhi_vdev_set_tdi_state(vdev_id, target_state, &cookie);
+ if (ret != -EBUSY)
+ break;
+ cond_resched();
+ }
+
+ while (ret == E_INCOMPLETE) {
+ if (should_abort_rhi_call_loop(vdev_id))
+ return -EINTR;
+ ret = rhi_vdev_continue(vdev_id, cookie);
+ }
+
+ return ret;
+}
diff --git a/drivers/virt/coco/arm-cca-guest/rhi-da.h b/drivers/virt/coco/arm-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 <asm/rhi.h>
+
+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
--
2.43.0
next prev parent reply other threads:[~2026-03-12 8:05 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-12 8:04 [RFC PATCH v3 00/11] coco/TSM: Arm CCA guest TDISP lock/accept flow with verification and DMA enable Aneesh Kumar K.V (Arm)
2026-03-12 8:04 ` [RFC PATCH v3 01/11] coco: guest: arm64: Guest TSM callback and realm device lock support Aneesh Kumar K.V (Arm)
2026-03-12 8:04 ` [RFC PATCH v3 02/11] coco: guest: arm64: Fix a typo in the ARM_CCA_GUEST Kconfig help string ("and" -> "an") Aneesh Kumar K.V (Arm)
2026-03-12 8:04 ` Aneesh Kumar K.V (Arm) [this message]
2026-03-12 8:04 ` [RFC PATCH v3 04/11] coco: guest: arm64: Support guest-initiated TDI lock/unlock transitions Aneesh Kumar K.V (Arm)
2026-03-12 8:04 ` [RFC PATCH v3 05/11] coco: guest: arm64: Refresh interface-report cache during device lock Aneesh Kumar K.V (Arm)
2026-03-12 8:04 ` [RFC PATCH v3 06/11] coco: guest: arm64: Add measurement refresh via RHI_DA_VDEV_GET_MEASUREMENTS Aneesh Kumar K.V (Arm)
2026-03-12 8:04 ` [RFC PATCH v3 07/11] coco: guest: arm64: Add guest APIs to read host-cached DA objects Aneesh Kumar K.V (Arm)
2026-03-12 8:04 ` [RFC PATCH v3 08/11] coco: guest: arm64: Verify DA evidence with RSI_VDEV_GET_INFO digests Aneesh Kumar K.V (Arm)
2026-03-12 8:04 ` [RFC PATCH v3 09/11] coco: guest: arm64: Hook TSM accept to Realm TDISP RUN transition Aneesh Kumar K.V (Arm)
2026-03-12 8:04 ` [RFC PATCH v3 10/11] coco: arm64: dma: Update force_dma_unencrypted for accepted devices Aneesh Kumar K.V (Arm)
2026-03-12 8:04 ` [RFC PATCH v3 11/11] coco: guest: arm64: Enable vdev DMA after attestation Aneesh Kumar K.V (Arm)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260312080442.3485633-4-aneesh.kumar@kernel.org \
--to=aneesh.kumar@kernel.org \
--cc=Jonathan.Cameron@huawei.com \
--cc=Suzuki.Poulose@arm.com \
--cc=aik@amd.com \
--cc=catalin.marinas@arm.com \
--cc=dan.j.williams@intel.com \
--cc=jgg@ziepe.ca \
--cc=kvmarm@lists.linux.dev \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-coco@lists.linux.dev \
--cc=linux-kernel@vger.kernel.org \
--cc=maz@kernel.org \
--cc=sameo@rivosinc.com \
--cc=steven.price@arm.com \
--cc=will@kernel.org \
--cc=yilun.xu@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox