The branch main has been updated by royger:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=77cb05db0cee0b052cc1a75da0741eb404eed473

commit 77cb05db0cee0b052cc1a75da0741eb404eed473
Author:     Roger Pau Monné <roy...@freebsd.org>
AuthorDate: 2022-06-28 15:37:00 +0000
Commit:     Roger Pau Monné <roy...@freebsd.org>
CommitDate: 2022-06-30 06:53:16 +0000

    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
---
 sys/x86/xen/pv.c | 52 ++++++++++++++++++++++++++++++----------------------
 1 file 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;

Reply via email to