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,
linux-kernel@vger.kernel.org
Cc: "Aneesh Kumar K.V (Arm)" <aneesh.kumar@kernel.org>,
Alexey Kardashevskiy <aik@amd.com>,
Catalin Marinas <catalin.marinas@arm.com>,
Dan Williams <dan.j.williams@intel.com>,
Jason Gunthorpe <jgg@ziepe.ca>,
Jonathan Cameron <jic23@kernel.org>,
Marc Zyngier <maz@kernel.org>, Samuel Ortiz <sameo@rivosinc.com>,
Steven Price <steven.price@arm.com>,
Suzuki K Poulose <Suzuki.Poulose@arm.com>,
Will Deacon <will@kernel.org>,
Xu Yilun <yilun.xu@linux.intel.com>
Subject: [PATCH v5 01/15] coco: host: arm64: Prepare host TSM plumbing for IDE streams
Date: Thu, 10 Sep 2026 19:34:54 +0530 [thread overview]
Message-ID: <20260910140509.868402-2-aneesh.kumar@kernel.org> (raw)
In-Reply-To: <20260910140509.868402-1-aneesh.kumar@kernel.org>
Add the initial Arm CCA host driver plumbing needed for device assignment
support. Register the RMI SMCCC device, add the host TSM driver, and hook
up the PCI TSM probe/remove callbacks when RMM reports Device Assignment
support.
This patch only establishes the driver and per-device PCI TSM state needed
by later patches. The RMM-facing pdev lifecycle, device communication, key
setup, peer stream coordination, IDE stream setup, and connect/disconnect
callbacks are added later in the series.
This keeps the patch as preparatory groundwork; complete enablement happens
once the follow-up patches wire these pieces into the RMM stream lifecycle.
Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
---
drivers/firmware/arm_rmm/rmi.c | 4 +-
drivers/firmware/smccc/smccc.c | 6 +
drivers/virt/coco/Kconfig | 2 +
drivers/virt/coco/Makefile | 1 +
drivers/virt/coco/arm-cca-host/Kconfig | 19 +++
drivers/virt/coco/arm-cca-host/Makefile | 5 +
drivers/virt/coco/arm-cca-host/main.c | 192 ++++++++++++++++++++++++
drivers/virt/coco/arm-cca-host/rmi-da.h | 46 ++++++
8 files changed, 273 insertions(+), 2 deletions(-)
create mode 100644 drivers/virt/coco/arm-cca-host/Kconfig
create mode 100644 drivers/virt/coco/arm-cca-host/Makefile
create mode 100644 drivers/virt/coco/arm-cca-host/main.c
create mode 100644 drivers/virt/coco/arm-cca-host/rmi-da.h
diff --git a/drivers/firmware/arm_rmm/rmi.c b/drivers/firmware/arm_rmm/rmi.c
index 34058e34188d..ba415b66991b 100644
--- a/drivers/firmware/arm_rmm/rmi.c
+++ b/drivers/firmware/arm_rmm/rmi.c
@@ -15,8 +15,8 @@
static bool arm64_rmi_is_available;
-/* Currently only the first 2 registers are used by Linux */
-#define RMI_FEAT_REG_COUNT 2
+/* Currently only the first 3 registers are used by Linux */
+#define RMI_FEAT_REG_COUNT 3
static __ro_after_init unsigned long rmi_feat_reg_cache[RMI_FEAT_REG_COUNT];
unsigned long rmi_feat_reg(unsigned long id)
diff --git a/drivers/firmware/smccc/smccc.c b/drivers/firmware/smccc/smccc.c
index 854276a3cd57..90b87a622a6b 100644
--- a/drivers/firmware/smccc/smccc.c
+++ b/drivers/firmware/smccc/smccc.c
@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/arm-smccc-bus.h>
#include <linux/arm-smccc-rsi.h>
+#include <linux/arm-smccc-rmi.h>
#include <asm/archrandom.h>
@@ -100,6 +101,11 @@ static const struct smccc_device_info smccc_devices[] __initconst = {
.requires_smc = true,
.device_name = "arm-rsi",
},
+ {
+ .func_id = SMC_RMI_VERSION,
+ .requires_smc = true,
+ .device_name = "arm-rmi",
+ },
};
static bool __init smccc_probe_smccc_device(const struct smccc_device_info *smccc_dev)
diff --git a/drivers/virt/coco/Kconfig b/drivers/virt/coco/Kconfig
index f7691f64fbe3..1cbc2134f9ea 100644
--- a/drivers/virt/coco/Kconfig
+++ b/drivers/virt/coco/Kconfig
@@ -19,5 +19,7 @@ endif
source "drivers/virt/coco/tdx-host/Kconfig"
+source "drivers/virt/coco/arm-cca-host/Kconfig"
+
config TSM
bool
diff --git a/drivers/virt/coco/Makefile b/drivers/virt/coco/Makefile
index b323b0ae4f82..f2310c34daf9 100644
--- a/drivers/virt/coco/Makefile
+++ b/drivers/virt/coco/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_INTEL_TDX_HOST) += tdx-host/
obj-$(CONFIG_ARM_CCA_GUEST) += arm-cca-guest/
obj-$(CONFIG_TSM) += tsm-core.o
obj-$(CONFIG_TSM_GUEST) += guest/
+obj-$(CONFIG_ARM_CCA_HOST) += arm-cca-host/
diff --git a/drivers/virt/coco/arm-cca-host/Kconfig b/drivers/virt/coco/arm-cca-host/Kconfig
new file mode 100644
index 000000000000..d2bf44f9776a
--- /dev/null
+++ b/drivers/virt/coco/arm-cca-host/Kconfig
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# TSM (TEE Security Manager) host drivers
+#
+config ARM_CCA_HOST
+ tristate "Arm CCA Host driver"
+ depends on ARM64
+ depends on PCI
+ depends on ARM_RMM_RMI
+ depends on HAVE_ARM_SMCCC_DISCOVERY
+ select PCI_TSM
+
+ help
+ ARM CCA RMM firmware is the trusted runtime that enforces memory
+ isolation and security for confidential computing on ARM. This driver
+ provides the interface for communicating with RMM to support secure
+ device assignment.
+
+ If you choose 'M' here, this module will be called arm-cca-host.
diff --git a/drivers/virt/coco/arm-cca-host/Makefile b/drivers/virt/coco/arm-cca-host/Makefile
new file mode 100644
index 000000000000..7a4c2e0e5d26
--- /dev/null
+++ b/drivers/virt/coco/arm-cca-host/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+obj-$(CONFIG_ARM_CCA_HOST) += arm-cca-host.o
+
+arm-cca-host-y += main.o
diff --git a/drivers/virt/coco/arm-cca-host/main.c b/drivers/virt/coco/arm-cca-host/main.c
new file mode 100644
index 000000000000..df2cc761f68b
--- /dev/null
+++ b/drivers/virt/coco/arm-cca-host/main.c
@@ -0,0 +1,192 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2026 ARM Ltd.
+ */
+
+#include <linux/arm-smccc.h>
+#include <linux/arm-smccc-bus.h>
+#include <linux/pci-tsm.h>
+#include <linux/pci-ide.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/tsm.h>
+#include <linux/vmalloc.h>
+#include <linux/cleanup.h>
+
+#include "rmi-da.h"
+
+static struct pci_tsm *cca_tsm_pci_probe(struct tsm_dev *tsm_dev, struct pci_dev *pdev)
+{
+ int ret;
+
+ if (!is_pci_tsm_pf0(pdev)) {
+ struct cca_host_fn_dsc *fn_dsc __free(kfree) =
+ kzalloc(sizeof(*fn_dsc), GFP_KERNEL);
+
+ if (!fn_dsc)
+ return NULL;
+
+ ret = pci_tsm_link_constructor(pdev, &fn_dsc->pci, tsm_dev);
+ if (ret)
+ return NULL;
+
+ return &no_free_ptr(fn_dsc)->pci;
+ }
+
+ if (!pdev->ide_cap)
+ return NULL;
+
+ struct cca_host_pf0_ep_dsc *pf0_ep_dsc __free(kfree) =
+ kzalloc(sizeof(*pf0_ep_dsc), GFP_KERNEL);
+ if (!pf0_ep_dsc)
+ return NULL;
+
+ ret = pci_tsm_pf0_constructor(pdev, &pf0_ep_dsc->pci, tsm_dev);
+ if (ret)
+ return NULL;
+
+ pci_dbg(pdev, "tsm enabled\n");
+ return &no_free_ptr(pf0_ep_dsc)->pci.base_tsm;
+}
+
+static void cca_tsm_pci_remove(struct pci_tsm *tsm)
+{
+ struct pci_dev *pdev = tsm->pdev;
+
+ if (is_pci_tsm_pf0(pdev)) {
+ struct cca_host_pf0_ep_dsc *pf0_ep_dsc = to_cca_pf0_ep_dsc(pdev);
+
+ pci_tsm_pf0_destructor(&pf0_ep_dsc->pci);
+ kfree(pf0_ep_dsc);
+ } else {
+ kfree(to_cca_fn_dsc(pdev));
+ }
+}
+
+static inline bool cca_pdev_need_sel_ide_streams(struct pci_dev *pdev)
+{
+ return pci_pcie_type(pdev) == PCI_EXP_TYPE_ENDPOINT;
+}
+
+static int __maybe_unused cca_tsm_connect(struct pci_dev *pdev)
+{
+ struct pci_dev *rp = pcie_find_root_port(pdev);
+ struct cca_host_pf0_ep_dsc *pf0_ep_dsc;
+ struct pci_ide *ide;
+ int ret, stream_id = 0;
+
+ /* Only function 0 supports connect in host */
+ if (WARN_ON(!is_pci_tsm_pf0(pdev)))
+ return -EIO;
+
+ pf0_ep_dsc = to_cca_pf0_ep_dsc(pdev);
+ if (cca_pdev_need_sel_ide_streams(pdev)) {
+
+ ide = pci_ide_stream_alloc(pdev);
+ if (!ide) {
+ ret = -ENOMEM;
+ goto err_stream_alloc;
+ }
+
+ pf0_ep_dsc->sel_stream = ide;
+ /*
+ * keep the stream id simple by using the host-bridge id
+ */
+ stream_id = ide->host_bridge_stream;
+ ide->stream_id = stream_id;
+ ret = pci_ide_stream_register(ide);
+ if (ret)
+ goto err_stream;
+ /*
+ * Configure IDE capability for target device
+ *
+ * Some test devices work only with DEFAULT_STREAM enabled.
+ * For simplicity, enable DEFAULT_STREAM for all devices. A
+ * future decent solution may be to have a quirk table to
+ * specify which devices need DEFAULT_STREAM.
+ */
+ ide->partner[PCI_IDE_EP].default_stream = 1;
+ pci_ide_stream_setup(pdev, ide);
+ pci_ide_stream_setup(rp, ide);
+
+ /*
+ * Once ide is setup, enable the stream at the endpoint
+ * Root port will be done by RMM
+ */
+ pci_ide_stream_enable(pdev, ide);
+ }
+ return 0;
+
+err_stream:
+ if (cca_pdev_need_sel_ide_streams(pdev))
+ pci_ide_stream_free(ide);
+ pf0_ep_dsc->sel_stream = NULL;
+err_stream_alloc:
+
+ return ret;
+}
+
+static void __maybe_unused cca_tsm_disconnect(struct pci_dev *pdev)
+{
+ struct pci_ide *ide;
+ struct cca_host_pf0_ep_dsc *pf0_ep_dsc;
+
+ pf0_ep_dsc = to_cca_pf0_ep_dsc(pdev);
+ if (!pf0_ep_dsc)
+ return;
+
+ if (cca_pdev_need_sel_ide_streams(pdev)) {
+ ide = pf0_ep_dsc->sel_stream;
+
+ pci_ide_stream_release(ide);
+ pf0_ep_dsc->sel_stream = NULL;
+ }
+
+}
+
+static struct pci_tsm_ops cca_link_pci_ops = {
+ .probe = cca_tsm_pci_probe,
+ .remove = cca_tsm_pci_remove,
+};
+
+static void cca_link_tsm_remove(void *tsm_dev)
+{
+ tsm_unregister(tsm_dev);
+}
+
+static bool rmi_has_reg2_feature(unsigned long feature)
+{
+ return !!u64_get_bits(rmi_feat_reg(2), feature);
+}
+
+static int cca_link_tsm_probe(struct arm_smccc_device *sdev)
+{
+ struct tsm_dev *tsm_dev;
+
+ if (!rmi_has_reg2_feature(RMI_FEATURE_REGISTER_2_DA))
+ return -ENODEV;
+
+ tsm_dev = tsm_register(&sdev->dev, &cca_link_pci_ops);
+ if (IS_ERR(tsm_dev))
+ return PTR_ERR(tsm_dev);
+
+ return devm_add_action_or_reset(&sdev->dev, cca_link_tsm_remove,
+ tsm_dev);
+}
+
+static const struct arm_smccc_device_id cca_link_tsm_id_table[] = {
+ { .func_id = SMC_RMI_VERSION },
+ {}
+};
+MODULE_DEVICE_TABLE(arm_smccc, cca_link_tsm_id_table);
+
+static struct arm_smccc_driver cca_link_tsm_driver = {
+ .name = KBUILD_MODNAME,
+ .probe = cca_link_tsm_probe,
+ .id_table = cca_link_tsm_id_table,
+};
+module_arm_smccc_driver(cca_link_tsm_driver);
+MODULE_IMPORT_NS("PCI_IDE");
+MODULE_AUTHOR("Aneesh Kumar <aneesh.kumar@kernel.org>");
+MODULE_DESCRIPTION("ARM CCA Host TSM driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.h b/drivers/virt/coco/arm-cca-host/rmi-da.h
new file mode 100644
index 000000000000..c5a568cb5674
--- /dev/null
+++ b/drivers/virt/coco/arm-cca-host/rmi-da.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2026 ARM Ltd.
+ */
+
+#ifndef _VIRT_COCO_RMM_DA_H_
+#define _VIRT_COCO_RMM_DA_H_
+
+#include <linux/arm-smccc-rmi.h>
+#include <linux/arm-rmi-cmds.h>
+#include <linux/pci.h>
+#include <linux/pci-ide.h>
+#include <linux/pci-tsm.h>
+
+/**
+ * struct cca_host_pf0_ep_dsc - PF0 endpoint device security context.
+ * @pci: Physical Function 0 TDISP link context
+ * @sel_stream: Selective IDE Stream descriptor
+ */
+struct cca_host_pf0_ep_dsc {
+ struct pci_tsm_pf0 pci;
+ struct pci_ide *sel_stream;
+};
+
+struct cca_host_fn_dsc {
+ struct pci_tsm pci;
+};
+
+static inline struct cca_host_pf0_ep_dsc *to_cca_pf0_ep_dsc(struct pci_dev *pdev)
+{
+ struct pci_tsm *tsm = pdev->tsm;
+
+ if (!tsm || !is_pci_tsm_pf0(pdev))
+ return NULL;
+
+ return container_of(tsm, struct cca_host_pf0_ep_dsc, pci.base_tsm);
+}
+
+static inline struct cca_host_fn_dsc *to_cca_fn_dsc(struct pci_dev *pdev)
+{
+ struct pci_tsm *tsm = pdev->tsm;
+
+ return container_of(tsm, struct cca_host_fn_dsc, pci);
+}
+
+#endif
--
2.43.0
next prev parent reply other threads:[~2026-09-10 14:05 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-10 14:04 [PATCH v5 00/15] coco/TSM: Host-side Arm CCA IDE setup via connect/disconnect callbacks Aneesh Kumar K.V (Arm)
2026-09-10 14:04 ` Aneesh Kumar K.V (Arm) [this message]
2026-09-10 14:04 ` [PATCH v5 02/15] coco: host: arm64: Create RMM pdev objects for PCI endpoints Aneesh Kumar K.V (Arm)
2026-09-10 14:04 ` [PATCH v5 03/15] coco: host: arm64: Add RMM pdev communication plumbing Aneesh Kumar K.V (Arm)
2026-09-10 14:04 ` [PATCH v5 04/15] coco: host: arm64: Add RMM pdev stop and destroy helper Aneesh Kumar K.V (Arm)
2026-09-10 14:04 ` [PATCH v5 05/15] X.509: Make certificate parser public Aneesh Kumar K.V (Arm)
2026-09-10 14:04 ` [PATCH v5 06/15] X.509: Parse Subject Alternative Name in certificates Aneesh Kumar K.V (Arm)
2026-09-10 14:05 ` [PATCH v5 07/15] X.509: Move certificate length retrieval into new helper Aneesh Kumar K.V (Arm)
2026-09-10 14:05 ` [PATCH v5 08/15] coco: host: arm64: Register device public key with RMM Aneesh Kumar K.V (Arm)
2026-09-10 14:05 ` [PATCH v5 09/15] coco: host: arm64: Initialize RMM pdev state for TDISP IDE connect Aneesh Kumar K.V (Arm)
2026-09-10 14:05 ` [PATCH v5 10/15] coco: host: arm64: Coordinate peer stream waits during pdev communication Aneesh Kumar K.V (Arm)
2026-09-10 14:05 ` [PATCH v5 11/15] coco: host: arm64: Connect RMM pdev streams for IDE devices Aneesh Kumar K.V (Arm)
2026-09-10 14:05 ` [PATCH v5 12/15] coco: host: arm64: Refcount root-port pdevs used by IDE streams Aneesh Kumar K.V (Arm)
2026-09-10 14:05 ` [PATCH v5 13/15] PCI/TSM: Move CMA DOE mailbox discovery out of pci_tsm_pf0_constructor() Aneesh Kumar K.V (Arm)
2026-09-10 14:05 ` [PATCH v5 14/15] coco: host: arm64: Add NCOH_SYS stream support for RC endpoints Aneesh Kumar K.V (Arm)
2026-09-10 14:05 ` [PATCH v5 15/15] coco: host: arm64: Enable PCI TSM connect callbacks 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=20260910140509.868402-2-aneesh.kumar@kernel.org \
--to=aneesh.kumar@kernel.org \
--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=jic23@kernel.org \
--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
all inboxes | Powered by JetHome®