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
This commit is contained in:
Warner Losh 2023-02-03 08:41:11 -07:00
parent db8d0c0cd9
commit 335e3daaf0

View file

@ -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,