[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250811061104.10326-6-fangyu.yu@linux.alibaba.com>
Date: Mon, 11 Aug 2025 14:11:03 +0800
From: fangyu.yu@...ux.alibaba.com
To: anup@...infault.org,
paul.walmsley@...ive.com,
palmer@...belt.com,
aou@...s.berkeley.edu,
alex@...ti.fr,
atishp@...shpatra.org,
tjeznach@...osinc.com,
joro@...tes.org,
will@...nel.org,
robin.murphy@....com,
sunilvl@...tanamicro.com,
rafael.j.wysocki@...el.com,
tglx@...utronix.de,
ajones@...tanamicro.com
Cc: guoren@...ux.alibaba.com,
guoren@...nel.org,
kvm@...r.kernel.org,
kvm-riscv@...ts.infradead.org,
linux-riscv@...ts.infradead.org,
linux-kernel@...r.kernel.org,
iommu@...ts.linux.dev,
Fangyu Yu <fangyu.yu@...ux.alibaba.com>
Subject: [RFC PATCH 5/6] iommu/riscv: Add MRIF mode support
From: Fangyu Yu <fangyu.yu@...ux.alibaba.com>
If the guest interrupt files are exhausted and the MRIF is supported
we configure the MSI PTE with MRIF mode, and set the NPPN and NID
using notice MSI from host irq.
Otherwise, we redirect the guest interrupt back to the original host
irq and inject the interrupt into the guest machine through irqfd.
Signed-off-by: Fangyu Yu <fangyu.yu@...ux.alibaba.com>
---
drivers/iommu/riscv/iommu-bits.h | 6 ++++++
drivers/iommu/riscv/iommu-ir.c | 35 +++++++++++++++++++++++++++++---
2 files changed, 38 insertions(+), 3 deletions(-)
diff --git a/drivers/iommu/riscv/iommu-bits.h b/drivers/iommu/riscv/iommu-bits.h
index d3d98dbed709..3af6436d5c5c 100644
--- a/drivers/iommu/riscv/iommu-bits.h
+++ b/drivers/iommu/riscv/iommu-bits.h
@@ -39,6 +39,12 @@
/* RISC-V IOMMU PPN <> PHYS address conversions, PHYS <=> PPN[53:10] */
#define riscv_iommu_phys_to_ppn(pa) (((pa) >> 2) & (((1ULL << 44) - 1) << 10))
#define riscv_iommu_ppn_to_phys(pn) (((pn) << 2) & (((1ULL << 44) - 1) << 12))
+/* RISC-V IOMMU MRIF Address <> PHYS address conversions, PHYS <=> MRIF[53:7] */
+#define riscv_iommu_phys_to_mrif(pa) (((pa) >> 2) & (((1ULL << 47) - 1) << 7))
+/* RISC-V IOMMU nppn <> PHYS address conversions, PHYS <=> nppn[53:10] */
+#define riscv_iommu_phys_to_nppn(pa) (((pa) >> 2) & (((1ULL << 44) - 1) << 10))
+#define riscv_iommu_data_to_nid(data) \
+ ((((data) & 0x3FFULL)) | (((((data) >> 10) & 1ULL)) << 60))
/* 5.3 IOMMU Capabilities (64bits) */
#define RISCV_IOMMU_REG_CAPABILITIES 0x0000
diff --git a/drivers/iommu/riscv/iommu-ir.c b/drivers/iommu/riscv/iommu-ir.c
index 73f552ed5b65..f3ebf62de53e 100644
--- a/drivers/iommu/riscv/iommu-ir.c
+++ b/drivers/iommu/riscv/iommu-ir.c
@@ -150,9 +150,12 @@ static int riscv_iommu_irq_set_vcpu_affinity(struct irq_data *data, void *info)
{
struct riscv_iommu_vcpu_info *vcpu_info = info;
struct riscv_iommu_domain *domain = data->domain->host_data;
+ struct device *dev = msi_desc_to_dev(irq_data_get_msi_desc(data));
+ struct riscv_iommu_device *iommu = dev_to_iommu(dev);
struct riscv_iommu_msipte *pte;
int ret = -EINVAL;
- u64 pteval;
+ u64 pteval, mrifval = 0;
+ bool mrif_support = (iommu->caps & RISCV_IOMMU_CAPABILITIES_MSI_MRIF);
if (WARN_ON(domain->domain.type != IOMMU_DOMAIN_UNMANAGED))
return ret;
@@ -186,12 +189,38 @@ static int riscv_iommu_irq_set_vcpu_affinity(struct irq_data *data, void *info)
if (!pte)
goto out_unlock;
- pteval = FIELD_PREP(RISCV_IOMMU_MSIPTE_M, 3) |
- riscv_iommu_phys_to_ppn(vcpu_info->hpa) |
+ if (!vcpu_info->mrif) {
+ pteval = FIELD_PREP(RISCV_IOMMU_MSIPTE_M, 3) |
+ riscv_iommu_phys_to_ppn(vcpu_info->hpa) |
+ FIELD_PREP(RISCV_IOMMU_MSIPTE_V, 1);
+ goto update_pte;
+ }
+
+ pteval = FIELD_PREP(RISCV_IOMMU_MSIPTE_M, 1) |
+ riscv_iommu_phys_to_mrif(vcpu_info->hpa) |
FIELD_PREP(RISCV_IOMMU_MSIPTE_V, 1);
+ if (mrif_support) {
+ mrifval = riscv_iommu_data_to_nid(vcpu_info->host_msg->data) |
+ riscv_iommu_phys_to_nppn(
+ (u64)vcpu_info->host_msg->address_hi << 32 |
+ vcpu_info->host_msg->address_lo);
+ } else {
+ /* If the guest interrupt file is exhausted and MRIF is not supported, we
+ * redirect the guest interrupt back to the original host interrupt and
+ * inject the interrupt into the guest machine through irqfd.
+ */
+ struct irq_data *irqdata = irq_get_irq_data(vcpu_info->host_irq);
+
+ irq_data_get_irq_chip(irqdata)->irq_write_msi_msg(irqdata,
+ vcpu_info->host_msg);
+ ret = -ENODEV;
+ goto out_unlock;
+ }
+update_pte:
if (pte->pte != pteval) {
pte->pte = pteval;
+ pte->mrif_info = mrifval;
riscv_iommu_ir_msitbl_inval(domain, pte);
}
--
2.49.0
Powered by blists - more mailing lists