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:
parent
db8d0c0cd9
commit
335e3daaf0
@ -322,14 +322,14 @@ get_phys_buffer(vm_offset_t dest, const size_t len, void **buf)
|
|||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
const size_t segsize = 64*1024*1024;
|
const size_t segsize = 64*1024*1024;
|
||||||
size_t sz;
|
size_t sz, amt, l;
|
||||||
|
|
||||||
if (nkexec_segments == HOST_KEXEC_SEGMENT_MAX)
|
if (nkexec_segments == HOST_KEXEC_SEGMENT_MAX)
|
||||||
panic("Tried to load too many kexec segments");
|
panic("Tried to load too many kexec segments");
|
||||||
for (i = 0; i < nkexec_segments; i++) {
|
for (i = 0; i < nkexec_segments; i++) {
|
||||||
if (dest >= (vm_offset_t)loaded_segments[i].mem &&
|
if (dest >= (vm_offset_t)loaded_segments[i].mem &&
|
||||||
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;
|
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].buf = host_getmem(sz);
|
||||||
loaded_segments[nkexec_segments].bufsz = sz;
|
loaded_segments[nkexec_segments].bufsz = sz;
|
||||||
loaded_segments[nkexec_segments].mem = (void *)rounddown2(dest,SEGALIGN);
|
loaded_segments[nkexec_segments].mem = (void *)rounddown2(dest,SEGALIGN);
|
||||||
loaded_segments[nkexec_segments].memsz = sz;
|
loaded_segments[nkexec_segments].memsz = 0;
|
||||||
|
|
||||||
i = nkexec_segments;
|
i = nkexec_segments;
|
||||||
nkexec_segments++;
|
nkexec_segments++;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
*buf = loaded_segments[i].buf + (dest -
|
/*
|
||||||
(vm_offset_t)loaded_segments[i].mem);
|
* Keep track of the highest amount used in a segment
|
||||||
return (min(len,loaded_segments[i].bufsz - (dest -
|
*/
|
||||||
(vm_offset_t)loaded_segments[i].mem)));
|
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
|
ssize_t
|
||||||
@ -447,12 +452,16 @@ kboot_autoload(void)
|
|||||||
void
|
void
|
||||||
kboot_kseg_get(int *nseg, void **ptr)
|
kboot_kseg_get(int *nseg, void **ptr)
|
||||||
{
|
{
|
||||||
int a;
|
|
||||||
|
|
||||||
printf("kseg_get: %d segments\n", nkexec_segments);
|
printf("kseg_get: %d segments\n", nkexec_segments);
|
||||||
printf("VA SZ PA MEMSZ\n");
|
printf("VA SZ PA MEMSZ\n");
|
||||||
printf("---------------- -------- ---------------- -----\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",
|
printf("%016jx %08jx %016jx %08jx\n",
|
||||||
(uintmax_t)loaded_segments[a].buf,
|
(uintmax_t)loaded_segments[a].buf,
|
||||||
(uintmax_t)loaded_segments[a].bufsz,
|
(uintmax_t)loaded_segments[a].bufsz,
|
||||||
|
Loading…
Reference in New Issue
Block a user