From 335e3daaf043fb32aaa5fbef513cae0c8c858ee7 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Fri, 3 Feb 2023 08:41:11 -0700 Subject: [PATCH] kboot: Keep track of what's used in the segment Keep track of how much is used in the segment as we allocate it to the application. Set memsz to 0 first, and increment it as used. Adjust the bufsz before we call kexec so the kernel copies the right amount (it's an error for bufsz to be bigger than memsz, so we set them == when we retrieve the segment). Make sure we round to the page size, otherwise kexec_load gets cranky. Sponsored by: Netflix Reviewed by: tsoome Differential Revision: https://reviews.freebsd.org/D38315 --- stand/kboot/main.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/stand/kboot/main.c b/stand/kboot/main.c index 450934b72777..f81d7b2cead4 100644 --- a/stand/kboot/main.c +++ b/stand/kboot/main.c @@ -322,14 +322,14 @@ get_phys_buffer(vm_offset_t dest, const size_t len, void **buf) { int i = 0; const size_t segsize = 64*1024*1024; - size_t sz; + size_t sz, amt, l; if (nkexec_segments == HOST_KEXEC_SEGMENT_MAX) panic("Tried to load too many kexec segments"); for (i = 0; i < nkexec_segments; i++) { if (dest >= (vm_offset_t)loaded_segments[i].mem && dest < (vm_offset_t)loaded_segments[i].mem + - loaded_segments[i].memsz) + loaded_segments[i].bufsz) /* Need to use bufsz since memsz is in use size */ goto out; } @@ -348,16 +348,21 @@ get_phys_buffer(vm_offset_t dest, const size_t len, void **buf) loaded_segments[nkexec_segments].buf = host_getmem(sz); loaded_segments[nkexec_segments].bufsz = sz; loaded_segments[nkexec_segments].mem = (void *)rounddown2(dest,SEGALIGN); - loaded_segments[nkexec_segments].memsz = sz; + loaded_segments[nkexec_segments].memsz = 0; i = nkexec_segments; nkexec_segments++; out: - *buf = loaded_segments[i].buf + (dest - - (vm_offset_t)loaded_segments[i].mem); - return (min(len,loaded_segments[i].bufsz - (dest - - (vm_offset_t)loaded_segments[i].mem))); + /* + * Keep track of the highest amount used in a segment + */ + amt = dest - (vm_offset_t)loaded_segments[i].mem; + l = min(len,loaded_segments[i].bufsz - amt); + *buf = loaded_segments[i].buf + amt; + if (amt + l > loaded_segments[i].memsz) + loaded_segments[i].memsz = amt + l; + return (l); } ssize_t @@ -447,12 +452,16 @@ kboot_autoload(void) void kboot_kseg_get(int *nseg, void **ptr) { - int a; - printf("kseg_get: %d segments\n", nkexec_segments); printf("VA SZ PA MEMSZ\n"); printf("---------------- -------- ---------------- -----\n"); - for (a = 0; a < nkexec_segments; a++) { + for (int a = 0; a < nkexec_segments; a++) { + /* + * Truncate each segment to just what we've used in the segment, + * rounded up to the next page. + */ + loaded_segments[a].memsz = roundup2(loaded_segments[a].memsz,PAGE_SIZE); + loaded_segments[a].bufsz = loaded_segments[a].memsz; printf("%016jx %08jx %016jx %08jx\n", (uintmax_t)loaded_segments[a].buf, (uintmax_t)loaded_segments[a].bufsz,