From 7fe550548152905be9209c313f40f1ea6cac0211 Mon Sep 17 00:00:00 2001 From: Oleksii Kurochko Date: Thu, 7 May 2026 10:58:48 +0200 Subject: [PATCH] xen/riscv: introduce p2m_gpa_bits common/device-tree/domain-build.c uses p2m_gpa_bits to determine the upper bound of the GPA space when searching for unused regions, so it must be defined when CONFIG_DOMAIN_BUILD_HELPERS=y. The variable is initialised to PADDR_BITS and narrowed in p2m_init() to the GPA width of the selected G-stage mode, allowing an external entity (e.g. an IOMMU) to restrict it further if needed. p2m_gpa_bits is a global rather than a per-domain value, which is acceptable for now because all domains are required to use the same G-stage MMU mode, as dom0less common code allocates it per all domains. Signed-off-by: Oleksii Kurochko Acked-by: Jan Beulich --- xen/arch/riscv/include/asm/p2m.h | 3 +++ xen/arch/riscv/p2m.c | 15 +++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/xen/arch/riscv/include/asm/p2m.h b/xen/arch/riscv/include/asm/p2m.h index 638c60ddc2..0d1dace1a0 100644 --- a/xen/arch/riscv/include/asm/p2m.h +++ b/xen/arch/riscv/include/asm/p2m.h @@ -47,6 +47,9 @@ #define P2M_LEVEL_MASK(p2m, lvl) \ (P2M_TABLE_OFFSET(p2m, lvl) << P2M_GFN_LEVEL_SHIFT(lvl)) +/* Holds the bit size of GPAs in p2m tables */ +extern unsigned int p2m_gpa_bits; + #define paddr_bits PADDR_BITS /* Get host p2m table */ diff --git a/xen/arch/riscv/p2m.c b/xen/arch/riscv/p2m.c index f889978cf7..703b9f4d25 100644 --- a/xen/arch/riscv/p2m.c +++ b/xen/arch/riscv/p2m.c @@ -11,6 +11,8 @@ #include #include +#include + #include #include #include @@ -67,6 +69,12 @@ static const struct gstage_mode_desc gstage_modes[] = { const struct gstage_mode_desc *__ro_after_init max_gstage_mode = &gstage_modes[0]; +/* + * Set to the maximum configured support for GPA bits, so the number of GPA + * bits can be restricted by an external entity (e.g. IOMMU). + */ +unsigned int __ro_after_init p2m_gpa_bits = PADDR_BITS; + static void p2m_free_page(struct p2m_domain *p2m, struct page_info *pg); static inline void p2m_free_metadata_page(struct p2m_domain *p2m, @@ -355,6 +363,7 @@ int p2m_init(struct domain *d, const struct xen_domctl_createdomain *config) */ static const struct gstage_mode_desc __ro_after_init *m = &gstage_modes[0]; struct p2m_domain *p2m = p2m_get_hostp2m(d); + unsigned int gpa_bits; /* * "Trivial" initialisation is now complete. Set the backpointer so the @@ -410,6 +419,12 @@ int p2m_init(struct domain *d, const struct xen_domctl_createdomain *config) # error "Add init of p2m->clean_dcache" #endif + gpa_bits = P2M_GFN_LEVEL_SHIFT(p2m->mode->paging_levels + 1) + + P2M_ROOT_EXTRA_BITS; + + if ( gpa_bits < p2m_gpa_bits ) + p2m_gpa_bits = gpa_bits; + return 0; }