From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 05D3BFF8862 for ; Mon, 27 Apr 2026 08:28:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=+SMmER7cOfSbE7D0oT45KBGvECF0Vghw4XViNErt0pc=; b=Ix3RDdwJTdgRXSWEboylsOD1K+ AUsSQ46pSO7KuZXJ8hWtdiKopwfso3Mqyz9MR2N18ZOk2Ih6FxTpzXf0QTZMFvTtRmNIEMObEq7UU yDECXNdWM7zGqrCi7DAluJgd6kCxlL8dKAcrYcHteewU7LyLznZxgGMhB6eHeL5uUu4zwytsgELWg GxZL4t2iA3BWcpJEjtwkUf261Ks8rkfQ1U5nPHhcUIa3loEwIOHU9TXvdC61JoKB3V/bErvH03llO kq180u2xxYnEzpxcwHKIuuUzHL5VIk35sw0RrsddprG+59Q2Nk/1A/M2xFqgREXxJZBNwAgnHOqX1 yY04uiHw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98.2 #2 (Red Hat Linux)) id 1wHHKS-0000000GSSv-0r9s; Mon, 27 Apr 2026 08:28:32 +0000 Received: from sea.source.kernel.org ([2600:3c0a:e001:78e:0:1991:8:25]) by bombadil.infradead.org with esmtps (Exim 4.98.2 #2 (Red Hat Linux)) id 1wHHKQ-0000000GSRs-0e1N for linux-arm-kernel@lists.infradead.org; Mon, 27 Apr 2026 08:28:31 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by sea.source.kernel.org (Postfix) with ESMTP id B6310437A7; Mon, 27 Apr 2026 08:28:29 +0000 (UTC) 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> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20260427_012830_253717_95CB0ACF X-CRM114-Status: GOOD ( 21.22 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.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. 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/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 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 @@ #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..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) = + 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 == RHI_DA_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 + +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