aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Pau Monné <royger@FreeBSD.org>2022-06-28 15:37:00 +0000
committerRoger Pau Monné <royger@FreeBSD.org>2022-06-30 06:53:16 +0000
commit77cb05db0cee0b052cc1a75da0741eb404eed473 (patch)
treea2c3746e73cb72dfb41aee61518ce2446f02498f
parent038405f32f71ad8ba0280ae066417f986ede79db (diff)
downloadsrc-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.c52
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;