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,
jean-philippe@linaro.org, jgg@ziepe.ca, praan@google.com,
danielmentz@google.com, mark.rutland@arm.com,
qperret@google.com, tabba@google.com,
Mostafa Saleh <smostafa@google.com>
Subject: [PATCH v5 10/27] KVM: arm64: iommu: Add memory pool
Date: Mon, 17 Nov 2025 18:47:57 +0000 [thread overview]
Message-ID: <20251117184815.1027271-11-smostafa@google.com> (raw)
In-Reply-To: <20251117184815.1027271-1-smostafa@google.com>
IOMMU drivers would require to allocate memory for the shadow page
table. Similar to the host stage-2 CPU page table, the IOMMU pool
is allocated early from the carveout and it's memory is added in
a pool which the IOMMU driver can allocate from and reclaim at
run time.
As this is too early for drivers to use init calls, a default value
can be set in the kernel config through IOMMU_POOL_PAGES, which
then can be overridden later from the kernel command line:
"kvm-arm.hyp_iommu_pages".
Later when the driver registers, it will pass how many pages it
needs, and if it was less than what was allocated, it will fail
to register.
Signed-off-by: Mostafa Saleh <smostafa@google.com>
---
.../admin-guide/kernel-parameters.txt | 4 +++
arch/arm64/include/asm/kvm_host.h | 3 +-
arch/arm64/kvm/Kconfig | 7 +++++
arch/arm64/kvm/hyp/include/nvhe/iommu.h | 5 ++-
arch/arm64/kvm/hyp/nvhe/iommu/iommu.c | 20 +++++++++++-
arch/arm64/kvm/hyp/nvhe/setup.c | 16 +++++++++-
arch/arm64/kvm/iommu.c | 31 ++++++++++++++++++-
arch/arm64/kvm/pkvm.c | 1 +
8 files changed, 82 insertions(+), 5 deletions(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 6c42061ca20e..f843d10a3dfc 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -3059,6 +3059,10 @@
trap: set WFI instruction trap
notrap: clear WFI instruction trap
+ kvm-arm.hyp_iommu_pages=
+ [KVM, ARM, EARLY]
+ Number of pages allocated for the IOMMU pool from the
+ KVM carveout when running in protected mode.
kvm_cma_resv_ratio=n [PPC,EARLY]
Reserves given percentage from system memory area for
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index fb2551ba8798..5496c52d0163 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -1654,7 +1654,8 @@ static __always_inline enum fgt_group_id __fgt_reg_to_group_id(enum vcpu_sysreg
#ifndef __KVM_NVHE_HYPERVISOR__
struct kvm_iommu_ops;
-int kvm_iommu_register_driver(struct kvm_iommu_ops *hyp_ops);
+int kvm_iommu_register_driver(struct kvm_iommu_ops *hyp_ops, size_t pool_pages);
+size_t kvm_iommu_pages(void);
#endif
#endif /* __ARM64_KVM_HOST_H__ */
diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index 4f803fd1c99a..6a1bd82a0d07 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -83,4 +83,11 @@ config PTDUMP_STAGE2_DEBUGFS
If in doubt, say N.
+config IOMMU_POOL_PAGES
+ hex "Number of pages reserved for IOMMU pool"
+ depends on KVM && IOMMU_SUPPORT
+ default 0x0
+ help
+ IOMMU pool is used with protected mode to allocated IOMMU drivers page tables.
+
endif # VIRTUALIZATION
diff --git a/arch/arm64/kvm/hyp/include/nvhe/iommu.h b/arch/arm64/kvm/hyp/include/nvhe/iommu.h
index 219363045b1c..9f4906c6dcc9 100644
--- a/arch/arm64/kvm/hyp/include/nvhe/iommu.h
+++ b/arch/arm64/kvm/hyp/include/nvhe/iommu.h
@@ -10,8 +10,11 @@ struct kvm_iommu_ops {
void (*host_stage2_idmap)(phys_addr_t start, phys_addr_t end, int prot);
};
-int kvm_iommu_init(void);
+int kvm_iommu_init(void *pool_base, size_t nr_pages);
void kvm_iommu_host_stage2_idmap(phys_addr_t start, phys_addr_t end,
enum kvm_pgtable_prot prot);
+void *kvm_iommu_donate_pages(u8 order);
+void kvm_iommu_reclaim_pages(void *ptr);
+
#endif /* __ARM64_KVM_NVHE_IOMMU_H__ */
diff --git a/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c b/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c
index 414bd4c97690..a0df34ecf6b0 100644
--- a/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c
+++ b/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c
@@ -15,6 +15,7 @@ struct kvm_iommu_ops *kvm_iommu_ops;
/* Protected by host_mmu.lock */
static bool kvm_idmap_initialized;
+static struct hyp_pool iommu_pages_pool;
static inline int pkvm_to_iommu_prot(enum kvm_pgtable_prot prot)
{
@@ -72,7 +73,7 @@ static int kvm_iommu_snapshot_host_stage2(void)
return ret;
}
-int kvm_iommu_init(void)
+int kvm_iommu_init(void *pool_base, size_t nr_pages)
{
int ret;
@@ -80,6 +81,13 @@ int kvm_iommu_init(void)
!kvm_iommu_ops->host_stage2_idmap)
return -ENODEV;
+ if (nr_pages) {
+ ret = hyp_pool_init(&iommu_pages_pool, hyp_virt_to_pfn(pool_base),
+ nr_pages, 0);
+ if (ret)
+ return ret;
+ }
+
ret = kvm_iommu_ops->init();
if (ret)
return ret;
@@ -95,3 +103,13 @@ void kvm_iommu_host_stage2_idmap(phys_addr_t start, phys_addr_t end,
return;
kvm_iommu_ops->host_stage2_idmap(start, end, pkvm_to_iommu_prot(prot));
}
+
+void *kvm_iommu_donate_pages(u8 order)
+{
+ return hyp_alloc_pages(&iommu_pages_pool, order);
+}
+
+void kvm_iommu_reclaim_pages(void *ptr)
+{
+ hyp_put_page(&iommu_pages_pool, ptr);
+}
diff --git a/arch/arm64/kvm/hyp/nvhe/setup.c b/arch/arm64/kvm/hyp/nvhe/setup.c
index de79803e7439..c245ea88c480 100644
--- a/arch/arm64/kvm/hyp/nvhe/setup.c
+++ b/arch/arm64/kvm/hyp/nvhe/setup.c
@@ -22,6 +22,13 @@
unsigned long hyp_nr_cpus;
+/* See kvm_iommu_pages() */
+#ifdef CONFIG_IOMMU_POOL_PAGES
+size_t hyp_kvm_iommu_pages = CONFIG_IOMMU_POOL_PAGES;
+#else
+size_t hyp_kvm_iommu_pages;
+#endif
+
#define hyp_percpu_size ((unsigned long)__per_cpu_end - \
(unsigned long)__per_cpu_start)
@@ -33,6 +40,7 @@ static void *selftest_base;
static void *ffa_proxy_pages;
static struct kvm_pgtable_mm_ops pkvm_pgtable_mm_ops;
static struct hyp_pool hpool;
+static void *iommu_base;
static int divide_memory_pool(void *virt, unsigned long size)
{
@@ -70,6 +78,12 @@ static int divide_memory_pool(void *virt, unsigned long size)
if (!ffa_proxy_pages)
return -ENOMEM;
+ if (hyp_kvm_iommu_pages) {
+ iommu_base = hyp_early_alloc_contig(hyp_kvm_iommu_pages);
+ if (!iommu_base)
+ return -ENOMEM;
+ }
+
return 0;
}
@@ -329,7 +343,7 @@ void __noreturn __pkvm_init_finalise(void)
if (ret)
goto out;
- ret = kvm_iommu_init();
+ ret = kvm_iommu_init(iommu_base, hyp_kvm_iommu_pages);
if (ret)
goto out;
diff --git a/arch/arm64/kvm/iommu.c b/arch/arm64/kvm/iommu.c
index c9041dcb6c57..6143fd3e1de3 100644
--- a/arch/arm64/kvm/iommu.c
+++ b/arch/arm64/kvm/iommu.c
@@ -7,9 +7,38 @@
#include <linux/kvm_host.h>
extern struct kvm_iommu_ops *kvm_nvhe_sym(kvm_iommu_ops);
+extern size_t kvm_nvhe_sym(hyp_kvm_iommu_pages);
-int kvm_iommu_register_driver(struct kvm_iommu_ops *hyp_ops)
+int kvm_iommu_register_driver(struct kvm_iommu_ops *hyp_ops, size_t pool_pages)
{
+ /* See kvm_iommu_pages() */
+ if (pool_pages > kvm_nvhe_sym(hyp_kvm_iommu_pages)) {
+ kvm_err("Missing memory for the IOMMU pool, need 0x%zx pages, check kvm-arm.hyp_iommu_pages",
+ pool_pages);
+ return -ENOMEM;
+ }
+
kvm_nvhe_sym(kvm_iommu_ops) = hyp_ops;
return 0;
}
+
+size_t kvm_iommu_pages(void)
+{
+ /*
+ * This is called very early during setup_arch() where no initcalls,
+ * so this has to call specific functions per each KVM driver.
+ * So we allow a config option that can set the defaul value for
+ * the IOMMU pool that can overridden by a command line option.
+ * When the driver registers it will pass the number pages needed
+ * for it's page tables, if less that what the system has already
+ * allocated we fail.
+ */
+ return kvm_nvhe_sym(hyp_kvm_iommu_pages);
+}
+
+/* Number of pages to reserve for iommu pool*/
+static int __init early_hyp_iommu_pages(char *arg)
+{
+ return kstrtoul(arg, 10, &kvm_nvhe_sym(hyp_kvm_iommu_pages));
+}
+early_param("kvm-arm.hyp_iommu_pages", early_hyp_iommu_pages);
diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c
index 24f0f8a8c943..b9d212b48c04 100644
--- a/arch/arm64/kvm/pkvm.c
+++ b/arch/arm64/kvm/pkvm.c
@@ -63,6 +63,7 @@ void __init kvm_hyp_reserve(void)
hyp_mem_pages += hyp_vmemmap_pages(STRUCT_HYP_PAGE_SIZE);
hyp_mem_pages += pkvm_selftest_pages();
hyp_mem_pages += hyp_ffa_proxy_pages();
+ hyp_mem_pages += kvm_iommu_pages();
/*
* Try to allocate a PMD-aligned region to reduce TLB pressure once
--
2.52.0.rc1.455.g30608eb744-goog
next prev parent reply other threads:[~2025-11-17 18:49 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-17 18:47 [PATCH v5 00/27] KVM: arm64: SMMUv3 driver for pKVM (trap and emulate) Mostafa Saleh
2025-11-17 18:47 ` [PATCH v5 01/27] KVM: arm64: Add a new function to donate memory with prot Mostafa Saleh
2025-11-17 18:47 ` [PATCH v5 02/27] KVM: arm64: Donate MMIO to the hypervisor Mostafa Saleh
2025-11-17 18:47 ` [PATCH v5 03/27] KVM: arm64: pkvm: Add pkvm_time_get() Mostafa Saleh
2025-11-17 18:47 ` [PATCH v5 04/27] iommu/io-pgtable-arm: Factor kernel specific code out Mostafa Saleh
2025-11-28 16:45 ` Jason Gunthorpe
2025-12-12 15:37 ` Mostafa Saleh
2025-12-16 0:58 ` Jason Gunthorpe
2025-12-16 23:08 ` Mostafa Saleh
2025-11-17 18:47 ` [PATCH v5 05/27] iommu/arm-smmu-v3: Split code with hyp Mostafa Saleh
2025-11-28 16:46 ` Jason Gunthorpe
2025-12-12 15:41 ` Mostafa Saleh
2025-11-17 18:47 ` [PATCH v5 06/27] iommu/arm-smmu-v3: Move TLB range invalidation into common code Mostafa Saleh
2025-11-17 18:47 ` [PATCH v5 07/27] iommu/arm-smmu-v3: Move IDR parsing to common functions Mostafa Saleh
2025-11-28 16:48 ` Jason Gunthorpe
2025-12-12 15:42 ` Mostafa Saleh
2025-12-17 13:59 ` Jason Gunthorpe
2025-11-17 18:47 ` [PATCH v5 08/27] KVM: arm64: iommu: Introduce IOMMU driver infrastructure Mostafa Saleh
2025-11-17 18:47 ` [PATCH v5 09/27] KVM: arm64: iommu: Shadow host stage-2 page table Mostafa Saleh
2025-11-17 18:47 ` Mostafa Saleh [this message]
2025-11-17 18:47 ` [PATCH v5 11/27] KVM: arm64: iommu: Support DABT for IOMMU Mostafa Saleh
2025-11-17 18:47 ` [PATCH v5 12/27] iommu/arm-smmu-v3-kvm: Add SMMUv3 driver Mostafa Saleh
2025-11-17 18:48 ` [PATCH v5 13/27] iommu/arm-smmu-v3-kvm: Add the kernel driver Mostafa Saleh
2025-11-17 18:48 ` [PATCH v5 14/27] iommu/arm-smmu-v3: Support probing KVM emulated devices Mostafa Saleh
2025-11-28 16:56 ` Jason Gunthorpe
2025-12-12 15:53 ` Mostafa Saleh
2025-12-17 14:00 ` Jason Gunthorpe
2025-11-17 18:48 ` [PATCH v5 15/27] iommu/arm-smmu-v3-kvm: Create array for hyp SMMUv3 Mostafa Saleh
2025-11-17 18:48 ` [PATCH v5 16/27] iommu/arm-smmu-v3-kvm: Take over SMMUs Mostafa Saleh
2025-11-17 18:48 ` [PATCH v5 17/27] iommu/arm-smmu-v3-kvm: Probe SMMU HW Mostafa Saleh
2025-11-28 17:07 ` Jason Gunthorpe
2025-12-12 16:07 ` Mostafa Saleh
2025-11-17 18:48 ` [PATCH v5 18/27] iommu/arm-smmu-v3-kvm: Add MMIO emulation Mostafa Saleh
2025-11-17 18:48 ` [PATCH v5 19/27] iommu/arm-smmu-v3-kvm: Shadow the command queue Mostafa Saleh
2025-11-17 18:48 ` [PATCH v5 20/27] iommu/arm-smmu-v3-kvm: Add CMDQ functions Mostafa Saleh
2025-11-17 18:48 ` [PATCH v5 21/27] iommu/arm-smmu-v3-kvm: Emulate CMDQ for host Mostafa Saleh
2025-11-17 18:48 ` [PATCH v5 22/27] iommu/arm-smmu-v3-kvm: Shadow stream table Mostafa Saleh
2025-11-17 18:48 ` [PATCH v5 23/27] iommu/arm-smmu-v3-kvm: Shadow STEs Mostafa Saleh
2025-11-17 18:48 ` [PATCH v5 24/27] iommu/arm-smmu-v3-kvm: Emulate GBPA Mostafa Saleh
2025-11-17 18:48 ` [PATCH v5 25/27] iommu/arm-smmu-v3-kvm: Support io-pgtable Mostafa Saleh
2025-11-17 18:48 ` [PATCH v5 26/27] iommu/arm-smmu-v3-kvm: Shadow the CPU stage-2 page table Mostafa Saleh
2025-11-17 18:48 ` [PATCH v5 27/27] iommu/arm-smmu-v3-kvm: Enable nesting Mostafa Saleh
2025-11-28 17:12 ` Jason Gunthorpe
2025-12-12 16:15 ` 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=20251117184815.1027271-11-smostafa@google.com \
--to=smostafa@google.com \
--cc=catalin.marinas@arm.com \
--cc=danielmentz@google.com \
--cc=iommu@lists.linux.dev \
--cc=jean-philippe@linaro.org \
--cc=jgg@ziepe.ca \
--cc=joey.gouly@arm.com \
--cc=joro@8bytes.org \
--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=praan@google.com \
--cc=qperret@google.com \
--cc=suzuki.poulose@arm.com \
--cc=tabba@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).