x86/xen: stop assuming kernel memory loading order in PVH
Do not assume that start_info will always be loaded at the highest memory address, and instead check the position of all the loaded elements in order to find the last loaded one, and thus a likely safe place to use as early boot allocation memory space. Reported by: markj, cperciva Sponsored by: Citrix Systems R&D Reviewed by: markj Differential revision: https://reviews.freebsd.org/D35628
This commit is contained in:
parent
038405f32f
commit
77cb05db0c
@ -68,6 +68,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/intr_machdep.h>
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/metadata.h>
|
||||
#include <machine/cpu.h>
|
||||
|
||||
#include <xen/xen-os.h>
|
||||
#include <xen/hvm.h>
|
||||
@ -143,10 +144,36 @@ hammer_time_xen(vm_paddr_t start_info_paddr)
|
||||
}
|
||||
|
||||
/*
|
||||
* The hvm_start_into structure is always appended after loading
|
||||
* the kernel and modules.
|
||||
* Select the higher address to use as physfree: either after
|
||||
* start_info, after the kernel, after the memory map or after any of
|
||||
* the modules. We assume enough memory to be available after the
|
||||
* selected address for the needs of very early memory allocations.
|
||||
*/
|
||||
physfree = roundup2(start_info_paddr + PAGE_SIZE, PAGE_SIZE);
|
||||
physfree = roundup2(start_info_paddr + sizeof(struct hvm_start_info),
|
||||
PAGE_SIZE);
|
||||
physfree = MAX(roundup2((vm_paddr_t)_end - KERNBASE, PAGE_SIZE),
|
||||
physfree);
|
||||
|
||||
if (start_info->memmap_paddr != 0)
|
||||
physfree = MAX(roundup2(start_info->memmap_paddr +
|
||||
start_info->memmap_entries *
|
||||
sizeof(struct hvm_memmap_table_entry), PAGE_SIZE),
|
||||
physfree);
|
||||
|
||||
if (start_info->modlist_paddr != 0) {
|
||||
unsigned int i;
|
||||
|
||||
if (start_info->nr_modules == 0) {
|
||||
xc_printf(
|
||||
"ERROR: modlist_paddr != 0 but nr_modules == 0\n");
|
||||
HYPERVISOR_shutdown(SHUTDOWN_crash);
|
||||
}
|
||||
mod = (struct hvm_modlist_entry *)
|
||||
(start_info->modlist_paddr + KERNBASE);
|
||||
for (i = 0; i < start_info->nr_modules; i++)
|
||||
physfree = MAX(roundup2(mod[i].paddr + mod[i].size,
|
||||
PAGE_SIZE), physfree);
|
||||
}
|
||||
|
||||
xatp.domid = DOMID_SELF;
|
||||
xatp.idx = 0;
|
||||
@ -168,25 +195,6 @@ hammer_time_xen(vm_paddr_t start_info_paddr)
|
||||
bzero_early(kenv, PAGE_SIZE);
|
||||
init_static_kenv(kenv, PAGE_SIZE);
|
||||
|
||||
if (start_info->modlist_paddr != 0) {
|
||||
if (start_info->modlist_paddr >= physfree) {
|
||||
xc_printf(
|
||||
"ERROR: unexpected module list memory address\n");
|
||||
HYPERVISOR_shutdown(SHUTDOWN_crash);
|
||||
}
|
||||
if (start_info->nr_modules == 0) {
|
||||
xc_printf(
|
||||
"ERROR: modlist_paddr != 0 but nr_modules == 0\n");
|
||||
HYPERVISOR_shutdown(SHUTDOWN_crash);
|
||||
}
|
||||
mod = (struct hvm_modlist_entry *)
|
||||
(start_info->modlist_paddr + KERNBASE);
|
||||
if (mod[0].paddr >= physfree) {
|
||||
xc_printf("ERROR: unexpected module memory address\n");
|
||||
HYPERVISOR_shutdown(SHUTDOWN_crash);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the hooks for early functions that diverge from bare metal */
|
||||
init_ops = xen_pvh_init_ops;
|
||||
hvm_start_flags = start_info->flags;
|
||||
|
Loading…
x
Reference in New Issue
Block a user