diff --git a/xen/arch/x86/pv/dom0_build.c b/xen/arch/x86/pv/dom0_build.c index cdae17b276..cc882bee61 100644 --- a/xen/arch/x86/pv/dom0_build.c +++ b/xen/arch/x86/pv/dom0_build.c @@ -641,6 +641,15 @@ static int __init dom0_construct(struct domain *d, if ( assign_pages(mfn_to_page(_mfn(mfn++)), 1, d, 0) ) BUG(); } + + /* + * We have either: + * - Mapped the initrd directly into dom0, or + * - Copied it and freed the module. + * + * Either way, tell discard_initial_images() to not free it a second + * time. + */ initrd->mod_end = 0; iommu_memory_setup(d, "initrd", mfn_to_page(_mfn(initrd_mfn)), diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index 511cf5b979..177f4024ab 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -340,7 +340,7 @@ unsigned long __init initial_images_nrpages(nodeid_t node) return nr; } -void __init discard_initial_images(void) +void __init discard_initial_images(void) /* a.k.a. Free boot modules */ { struct boot_info *bi = &xen_boot_info; unsigned int i; @@ -348,9 +348,16 @@ void __init discard_initial_images(void) for ( i = 0; i < bi->nr_modules; ++i ) { uint64_t start = pfn_to_paddr(bi->mods[i].mod->mod_start); + uint64_t size = bi->mods[i].mod->mod_end; - init_domheap_pages(start, - start + PAGE_ALIGN(bi->mods[i].mod->mod_end)); + /* + * Sometimes the initrd is mapped, rather than copied, into dom0. + * Size being 0 is how we're instructed to leave the module alone. + */ + if ( size == 0 ) + continue; + + init_domheap_pages(start, start + PAGE_ALIGN(size)); } bi->nr_modules = 0;