From: Mostafa Saleh <smostafa@google.com>
To: linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, kvmarm@lists.linux.dev,
iommu@lists.linux.dev
Cc: catalin.marinas@arm.com, will@kernel.org, maz@kernel.org,
oliver.upton@linux.dev, joey.gouly@arm.com,
suzuki.poulose@arm.com, yuzenghui@huawei.com, joro@8bytes.org,
jgg@ziepe.ca, mark.rutland@arm.com, qperret@google.com,
tabba@google.com, vdonnefort@google.com,
sebastianene@google.com, keirf@google.com,
Mostafa Saleh <smostafa@google.com>
Subject: [PATCH v7 21/24] iommu/io-pgtable-arm: Support io-pgtable-arm in the hypervisor
Date: Wed, 15 Jul 2026 11:59:02 +0000 [thread overview]
Message-ID: <20260715115906.2664882-22-smostafa@google.com> (raw)
In-Reply-To: <20260715115906.2664882-1-smostafa@google.com>
To be able to populate the shadow stage-2 in the hypervisor, compile
io-pgtable-arm object for the hypervisor.
That requires the hypervisor to support iommu-pages, re-defining some
functions as address conversion and stubbing some others as DMA-API.
Signed-off-by: Mostafa Saleh <smostafa@google.com>
---
arch/arm64/kvm/hyp/nvhe/Makefile | 3 +-
.../arm/arm-smmu-v3/pkvm/io-pgtable-arm-hyp.h | 68 +++++++++++++++++++
drivers/iommu/io-pgtable-arm.c | 39 ++++++++---
drivers/iommu/io-pgtable-arm.h | 17 +++++
4 files changed, 117 insertions(+), 10 deletions(-)
create mode 100644 drivers/iommu/arm/arm-smmu-v3/pkvm/io-pgtable-arm-hyp.h
diff --git a/arch/arm64/kvm/hyp/nvhe/Makefile b/arch/arm64/kvm/hyp/nvhe/Makefile
index dcb75fb5b4f1..35ac274ab2c0 100644
--- a/arch/arm64/kvm/hyp/nvhe/Makefile
+++ b/arch/arm64/kvm/hyp/nvhe/Makefile
@@ -36,7 +36,8 @@ hyp-obj-y += $(lib-objs)
HYP_SMMU_V3_DRV_PATH = ../../../../../drivers/iommu/arm/arm-smmu-v3
hyp-obj-$(CONFIG_ARM_SMMU_V3_PKVM) += $(HYP_SMMU_V3_DRV_PATH)/pkvm/arm-smmu-v3.o \
- $(HYP_SMMU_V3_DRV_PATH)/arm-smmu-v3-common-lib.o
+ $(HYP_SMMU_V3_DRV_PATH)/arm-smmu-v3-common-lib.o \
+ $(HYP_SMMU_V3_DRV_PATH)/../../io-pgtable-arm.o
# Path to simple_ring_buffer.c
CFLAGS_trace.nvhe.o += -I$(srctree)/kernel/trace/
diff --git a/drivers/iommu/arm/arm-smmu-v3/pkvm/io-pgtable-arm-hyp.h b/drivers/iommu/arm/arm-smmu-v3/pkvm/io-pgtable-arm-hyp.h
new file mode 100644
index 000000000000..c9d20e781aed
--- /dev/null
+++ b/drivers/iommu/arm/arm-smmu-v3/pkvm/io-pgtable-arm-hyp.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef IO_PGTABLE_ARM_HYP_H_
+#define IO_PGTABLE_ARM_HYP_H_
+
+#include <nvhe/memory.h>
+#include <nvhe/iommu.h>
+
+#undef WARN_ONCE
+#define WARN_ONCE(condition, format...) WARN_ON(condition)
+
+static inline void *iommu_alloc_pages_node_sz(int nid, gfp_t gfp, size_t size)
+{
+ return pkvm_iommu_donate_pages(get_order(size));
+}
+
+static inline void iommu_free_pages(void *virt)
+{
+ pkvm_iommu_reclaim_pages(virt);
+}
+
+static inline void *arm_lpae_alloc_data(size_t size)
+{
+ return pkvm_iommu_donate_pages(get_order(size));
+}
+
+static inline void arm_lpae_free_data(void *p)
+{
+ pkvm_iommu_reclaim_pages(p);
+}
+
+#undef phys_to_virt
+#define phys_to_virt(x) hyp_phys_to_virt(x)
+
+#undef virt_to_phys
+#define virt_to_phys(x) hyp_virt_to_phys(x)
+
+/* Stubs used by io-pgtable-arm but no relevant for hypervisor object. */
+#undef dma_map_single
+#define dma_map_single(d, p, s, dir) (virt_to_phys(p))
+
+#undef dma_unmap_single
+#define dma_unmap_single(d, a, s, r) do { (void)(d); (void)(a); (void)(s); (void)(r); } while (0)
+
+#define dma_mapping_error(...) (0)
+
+#undef dev_err
+#define dev_err(dev, format, ...)
+
+static inline int iommu_pages_start_incoherent(void *virt, struct device *dma_dev)
+{
+ return 0;
+}
+
+static inline void iommu_pages_free_incoherent(void *virt,
+ struct device *dma_dev)
+{
+}
+
+static inline void iommu_pages_flush_incoherent(struct device *dma_dev,
+ void *virt, size_t offset,
+ size_t len)
+{
+}
+
+struct io_pgtable_ops *kvm_alloc_io_pgtable_ops(enum io_pgtable_fmt fmt,
+ struct io_pgtable_cfg *cfg,
+ void *cookie);
+#endif /* IO_PGTABLE_ARM_HYP_H_ */
diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 476c0e25631a..cf71087e4d3a 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -20,7 +20,6 @@
#include <asm/barrier.h>
#include "io-pgtable-arm.h"
-#include "iommu-pages.h"
#define ARM_LPAE_MAX_ADDR_BITS 52
#define ARM_LPAE_S2_MAX_CONCAT_PAGES 16
@@ -301,6 +300,7 @@ static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp,
{
struct device *dev = cfg->iommu_dev;
void *pages;
+ int nid = dev ? dev_to_node(dev) : NUMA_NO_NODE;
/*
* For very small starting-level translation tables the HW requires a
@@ -311,7 +311,7 @@ static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp,
if (cfg->alloc)
return __arm_lpae_cfg_alloc(size, gfp, cfg, cookie);
- pages = iommu_alloc_pages_node_sz(dev_to_node(dev), gfp, size);
+ pages = iommu_alloc_pages_node_sz(nid, gfp, size);
if (!pages)
return NULL;
@@ -350,8 +350,7 @@ static void __arm_lpae_free_pages(void *pages, size_t size,
static void __arm_lpae_sync_pte(arm_lpae_iopte *ptep, int num_entries,
struct io_pgtable_cfg *cfg)
{
- dma_sync_single_for_device(cfg->iommu_dev, __arm_lpae_dma_addr(ptep),
- sizeof(*ptep) * num_entries, DMA_TO_DEVICE);
+ iommu_pages_flush_incoherent(cfg->iommu_dev, ptep, 0, sizeof(*ptep) * num_entries);
}
static void __arm_lpae_clear_pte(arm_lpae_iopte *ptep, struct io_pgtable_cfg *cfg, int num_entries)
@@ -650,7 +649,7 @@ static void arm_lpae_free_pgtable(struct io_pgtable *iop)
struct arm_lpae_io_pgtable *data = io_pgtable_to_data(iop);
__arm_lpae_free_pgtable(data, data->start_level, data->pgd);
- kfree(data);
+ arm_lpae_free_data(data);
}
static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,
@@ -964,7 +963,7 @@ arm_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg)
if (cfg->oas > ARM_LPAE_MAX_ADDR_BITS)
return NULL;
- data = kmalloc_obj(*data);
+ data = arm_lpae_alloc_data(sizeof(*data));
if (!data)
return NULL;
@@ -1091,7 +1090,7 @@ arm_64_lpae_alloc_pgtable_s1(struct io_pgtable_cfg *cfg, void *cookie)
return &data->iop;
out_free_data:
- kfree(data);
+ arm_lpae_free_data(data);
return NULL;
}
@@ -1187,7 +1186,7 @@ arm_64_lpae_alloc_pgtable_s2(struct io_pgtable_cfg *cfg, void *cookie)
return &data->iop;
out_free_data:
- kfree(data);
+ arm_lpae_free_data(data);
return NULL;
}
@@ -1266,7 +1265,7 @@ arm_mali_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)
return &data->iop;
out_free_data:
- kfree(data);
+ arm_lpae_free_data(data);
return NULL;
}
@@ -1299,3 +1298,25 @@ struct io_pgtable_init_fns io_pgtable_arm_mali_lpae_init_fns = {
.alloc = arm_mali_lpae_alloc_pgtable,
.free = arm_lpae_free_pgtable,
};
+
+#ifdef __KVM_NVHE_HYPERVISOR__
+struct io_pgtable_ops *kvm_alloc_io_pgtable_ops(enum io_pgtable_fmt fmt,
+ struct io_pgtable_cfg *cfg,
+ void *cookie)
+{
+ struct io_pgtable *iop;
+
+ if (fmt != ARM_64_LPAE_S2)
+ return NULL;
+
+ iop = arm_64_lpae_alloc_pgtable_s2(cfg, cookie);
+ if (!iop)
+ return NULL;
+
+ iop->fmt = fmt;
+ iop->cookie = cookie;
+ iop->cfg = *cfg;
+
+ return &iop->ops;
+}
+#endif
\ No newline at end of file
diff --git a/drivers/iommu/io-pgtable-arm.h b/drivers/iommu/io-pgtable-arm.h
index ba7cfdf7afa0..fd5c5ff2b550 100644
--- a/drivers/iommu/io-pgtable-arm.h
+++ b/drivers/iommu/io-pgtable-arm.h
@@ -27,4 +27,21 @@
#define ARM_LPAE_TCR_PS_48_BIT 0x5ULL
#define ARM_LPAE_TCR_PS_52_BIT 0x6ULL
+#ifndef __KVM_NVHE_HYPERVISOR__
+#include "iommu-pages.h"
+
+static inline void *arm_lpae_alloc_data(size_t size)
+{
+ return kmalloc(size, GFP_KERNEL);
+}
+
+static inline void arm_lpae_free_data(void *p)
+{
+ kfree(p);
+}
+
+#else
+#include "arm/arm-smmu-v3/pkvm/io-pgtable-arm-hyp.h"
+#endif
+
#endif /* IO_PGTABLE_ARM_H_ */
--
2.55.0.141.g00534a21ce-goog
next prev parent reply other threads:[~2026-07-15 11:59 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-15 11:58 [PATCH v7 00/24] KVM: arm64: SMMUv3 driver for pKVM (trap and emulate) Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 01/24] KVM: arm64: Add a generic clock Mostafa Saleh
2026-07-15 13:48 ` Vincent Donnefort
2026-07-15 14:13 ` Mostafa Saleh
2026-07-15 14:34 ` Vincent Donnefort
2026-07-15 11:58 ` [PATCH v7 02/24] KVM: arm64: Donate MMIO to the hypervisor Mostafa Saleh
2026-07-15 17:26 ` Vincent Donnefort
2026-07-15 11:58 ` [PATCH v7 03/24] iommu/arm-smmu-v3: Split code with hyp Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 04/24] iommu/arm-smmu-v3: Move TLB range invalidation into common code Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 05/24] iommu/arm-smmu-v3: Move IDR parsing to common functions Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 06/24] KVM: arm64: iommu: Introduce IOMMU driver infrastructure Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 07/24] KVM: arm64: iommu: Shadow host stage-2 page table Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 08/24] KVM: arm64: iommu: Add memory pool Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 09/24] KVM: arm64: iommu: Support DABT for IOMMU Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 10/24] iommu/arm-smmu-v3-kvm: Add SMMUv3 driver Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 11/24] iommu/arm-smmu-v3-kvm: Add the kernel driver Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 12/24] iommu/arm-smmu-v3-kvm: Probe SMMU HW Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 13/24] iommu/arm-smmu-v3-kvm: Add MMIO emulation Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 14/24] iommu/arm-smmu-v3-kvm: Shadow the command queue Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 15/24] iommu/arm-smmu-v3-kvm: Add CMDQ functions Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 16/24] iommu/arm-smmu-v3-kvm: Emulate CMDQ for host Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 17/24] iommu/arm-smmu-v3-kvm: Shadow stream table Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 18/24] iommu/arm-smmu-v3-kvm: Shadow STEs Mostafa Saleh
2026-07-15 11:59 ` [PATCH v7 19/24] iommu/arm-smmu-v3-kvm: Share other queues Mostafa Saleh
2026-07-15 11:59 ` [PATCH v7 20/24] iommu/arm-smmu-v3-kvm: Emulate GBPA Mostafa Saleh
2026-07-15 11:59 ` Mostafa Saleh [this message]
2026-07-15 11:59 ` [PATCH v7 22/24] iommu/arm-smmu-v3-kvm: Shadow the CPU stage-2 page table Mostafa Saleh
2026-07-15 11:59 ` [PATCH v7 23/24] iommu/arm-smmu-v3-kvm: Enable nesting Mostafa Saleh
2026-07-15 11:59 ` [PATCH v7 24/24] KVM: arm64: Add documentation for pKVM DMA isolation Mostafa Saleh
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=20260715115906.2664882-22-smostafa@google.com \
--to=smostafa@google.com \
--cc=catalin.marinas@arm.com \
--cc=iommu@lists.linux.dev \
--cc=jgg@ziepe.ca \
--cc=joey.gouly@arm.com \
--cc=joro@8bytes.org \
--cc=keirf@google.com \
--cc=kvmarm@lists.linux.dev \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=maz@kernel.org \
--cc=oliver.upton@linux.dev \
--cc=qperret@google.com \
--cc=sebastianene@google.com \
--cc=suzuki.poulose@arm.com \
--cc=tabba@google.com \
--cc=vdonnefort@google.com \
--cc=will@kernel.org \
--cc=yuzenghui@huawei.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.