diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c index 01891293b8..4d6c971f37 100644 --- a/xen/arch/arm/mm.c +++ b/xen/arch/arm/mm.c @@ -973,11 +973,41 @@ static int create_xen_table(lpae_t *entry) static lpae_t *xen_map_table(mfn_t mfn) { + /* + * We may require to map the page table before map_domain_page() is + * useable. The requirements here is it must be useable as soon as + * page-tables are allocated dynamically via alloc_boot_pages(). + * + * We need to do the check on physical address rather than virtual + * address to avoid truncation on Arm32. Therefore is_kernel() cannot + * be used. + */ + if ( system_state == SYS_STATE_early_boot ) + { + if ( is_xen_fixed_mfn(mfn) ) + { + /* + * It is fine to demote the type because the size of Xen + * will always fit in vaddr_t. + */ + vaddr_t offset = mfn_to_maddr(mfn) - virt_to_maddr(&_start); + + return (lpae_t *)(XEN_VIRT_START + offset); + } + } + return map_domain_page(mfn); } static void xen_unmap_table(const lpae_t *table) { + /* + * During early boot, xen_map_table() will not use map_domain_page() + * for page-tables residing in Xen binary. So skip the unmap part. + */ + if ( system_state == SYS_STATE_early_boot && is_kernel(table) ) + return; + unmap_domain_page(table); }