diff options
author | Roger Pau Monné <royger@FreeBSD.org> | 2022-06-28 15:37:00 +0000 |
---|---|---|
committer | Roger Pau Monné <royger@FreeBSD.org> | 2022-06-30 06:53:16 +0000 |
commit | 77cb05db0cee0b052cc1a75da0741eb404eed473 (patch) | |
tree | a2c3746e73cb72dfb41aee61518ce2446f02498f | |
parent | 038405f32f71ad8ba0280ae066417f986ede79db (diff) | |
download | src-77cb05db0cee0b052cc1a75da0741eb404eed473.tar.gz src-77cb05db0cee0b052cc1a75da0741eb404eed473.zip |
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
-rw-r--r-- | sys/x86/xen/pv.c | 52 |
1 files changed, 30 insertions, 22 deletions
diff --git a/sys/x86/xen/pv.c b/sys/x86/xen/pv.c index c5d7629d0bc5..796b3ca844de 100644 --- a/sys/x86/xen/pv.c +++ b/sys/x86/xen/pv.c @@ -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; |