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; }