[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Minios-devel] [UNIKRAFT PATCH 5/5] plat/kvm: x86: Retrieve initrd location from Multiboot
Inspects Multiboot modules information to retrieve the location of an loaded initramdisk. It will most likely be placed by Multiboot within the region that we announce as usable for heap. In such a case, we cut out the initrd from the heap range and report two heap regions: one before the initrd, one after the initrd. Signed-off-by: Simon Kuenzer <simon.kuenzer@xxxxxxxxx> --- plat/kvm/memory.c | 31 ++++++++++- plat/kvm/x86/setup.c | 130 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+), 1 deletion(-) diff --git a/plat/kvm/memory.c b/plat/kvm/memory.c index d8293293..7f2fb46a 100644 --- a/plat/kvm/memory.c +++ b/plat/kvm/memory.c @@ -27,7 +27,9 @@ int ukplat_memregion_count(void) { - return 9; + return (9 + + ((_libkvmplat_cfg.initrd.len > 0) ? 1 : 0) + + ((_libkvmplat_cfg.heap2.len > 0) ? 1 : 0)); } int ukplat_memregion_get(int i, struct ukplat_memregion_desc *m) @@ -131,6 +133,33 @@ int ukplat_memregion_get(int i, struct ukplat_memregion_desc *m) m->name = "bstack"; #endif break; + case 9: /* initrd */ + if (_libkvmplat_cfg.initrd.len) { + m->base = (void *) _libkvmplat_cfg.initrd.start; + m->len = _libkvmplat_cfg.initrd.len; + m->flags = (UKPLAT_MEMRF_INITRD | + UKPLAT_MEMRF_WRITABLE); +#if CONFIG_UKPLAT_MEMRNAME + m->name = "initrd"; +#endif + ret = 0; + break; + } + /* fall-through */ + case 10: /* heap2 + * NOTE: heap2 could only exist if initrd was there, + * otherwise we fall through */ + if (_libkvmplat_cfg.initrd.len && _libkvmplat_cfg.heap2.len) { + m->base = (void *) _libkvmplat_cfg.heap2.start; + m->len = _libkvmplat_cfg.heap2.len; + m->flags = UKPLAT_MEMRF_ALLOCATABLE; +#if CONFIG_UKPLAT_MEMRNAME + m->name = "heap"; +#endif + ret = 0; + break; + } + /* fall-through */ default: m->base = __NULL; m->len = 0; diff --git a/plat/kvm/x86/setup.c b/plat/kvm/x86/setup.c index c3959c40..38f5cd32 100644 --- a/plat/kvm/x86/setup.c +++ b/plat/kvm/x86/setup.c @@ -115,6 +115,129 @@ static inline void _mb_init_mem(struct multiboot_info *mi) _libkvmplat_cfg.bstack.len = __STACK_SIZE; } +static inline void _mb_init_initrd(struct multiboot_info *mi) +{ + multiboot_module_t *mod1; + uintptr_t heap0_start, heap0_end; + uintptr_t heap1_start, heap1_end; + size_t heap0_len, heap1_len; + + /* + * Search for initrd (called boot module according multiboot) + */ + if (mi->mods_count == 0) { + uk_pr_debug("No initrd present\n"); + _libkvmplat_cfg.initrd.start = 0; + _libkvmplat_cfg.initrd.end = 0; + _libkvmplat_cfg.initrd.len = 0; + return; + } + + /* + * NOTE: We are only taking the first boot module as initrd. + * Initrd arguments and further modules are ignored. + */ + UK_ASSERT(mi->mods_addr); + + mod1 = (multiboot_module_t *)((uintptr_t) mi->mods_addr); + UK_ASSERT(mod1->mod_end >= mod1->mod_start); + + _libkvmplat_cfg.initrd.start = (uintptr_t) mod1->mod_start; + _libkvmplat_cfg.initrd.end = (uintptr_t) mod1->mod_end; + _libkvmplat_cfg.initrd.len = (size_t) (mod1->mod_end - mod1->mod_start); + + /* + * Check if initrd is part of heap + * In such a case, we figure out the remaining pieces as heap + */ + if (_libkvmplat_cfg.heap.len == 0) { + /* We do not have a heap */ + return; + } + heap0_start = 0; + heap0_end = 0; + heap1_start = 0; + heap1_end = 0; + if (RANGE_OVERLAP(_libkvmplat_cfg.heap.start, + _libkvmplat_cfg.heap.len, + _libkvmplat_cfg.initrd.start, + _libkvmplat_cfg.initrd.len)) { + if (IN_RANGE(_libkvmplat_cfg.initrd.start, + _libkvmplat_cfg.heap.start, + _libkvmplat_cfg.heap.len)) { + /* Start of initrd within heap range; + * Use the prepending left piece as heap */ + heap0_start = _libkvmplat_cfg.heap.start; + heap0_end = ALIGN_DOWN(_libkvmplat_cfg.initrd.start, + __PAGE_SIZE); + } + if (IN_RANGE(_libkvmplat_cfg.initrd.start, + + _libkvmplat_cfg.heap.start, + _libkvmplat_cfg.heap.len)) { + /* End of initrd within heap range; + * Use the remaining left piece as heap */ + heap1_start = ALIGN_UP(_libkvmplat_cfg.initrd.end, + __PAGE_SIZE); + heap1_end = _libkvmplat_cfg.heap.end; + } + } else { + /* Initrd is not overlapping with heap */ + heap0_start = _libkvmplat_cfg.heap.start; + heap0_end = _libkvmplat_cfg.heap.end; + } + heap0_len = heap0_end - heap0_start; + heap1_len = heap1_end - heap1_start; + + /* + * Update heap regions + * We make sure that in we start filling left heap pieces at + * `_libkvmplat_cfg.heap`. Any additional piece will then be + * placed to `_libkvmplat_cfg.heap2`. + */ + if (heap0_len == 0) { + /* Heap piece 0 is empty, use piece 1 as only */ + if (heap1_len != 0) { + _libkvmplat_cfg.heap.start = heap1_start; + _libkvmplat_cfg.heap.end = heap1_end; + _libkvmplat_cfg.heap.len = heap1_len; + } else { + _libkvmplat_cfg.heap.start = 0; + _libkvmplat_cfg.heap.end = 0; + _libkvmplat_cfg.heap.len = 0; + } + _libkvmplat_cfg.heap2.start = 0; + _libkvmplat_cfg.heap2.end = 0; + _libkvmplat_cfg.heap2.len = 0; + } else { + /* Heap piece 0 has memory */ + _libkvmplat_cfg.heap.start = heap0_start; + _libkvmplat_cfg.heap.end = heap0_end; + _libkvmplat_cfg.heap.len = heap0_len; + if (heap1_len != 0) { + _libkvmplat_cfg.heap2.start = heap1_start; + _libkvmplat_cfg.heap2.end = heap1_end; + _libkvmplat_cfg.heap2.len = heap1_len; + } else { + _libkvmplat_cfg.heap2.start = 0; + _libkvmplat_cfg.heap2.end = 0; + _libkvmplat_cfg.heap2.len = 0; + } + } + + /* + * Double-check that initrd is not overlapping with previously allocated + * boot stack. We crash in such a case because we assume that multiboot + * places the initrd close to the beginning of the heap region. One need + * to assign just more memory in order to avoid this crash. + */ + if (RANGE_OVERLAP(_libkvmplat_cfg.heap.start, + _libkvmplat_cfg.heap.len, + _libkvmplat_cfg.initrd.start, + _libkvmplat_cfg.initrd.len)) + UK_CRASH("Not enough space at end of memory for boot stack\n"); +} + static void _libkvmplat_entry2(void *arg __attribute__((unused))) { ukplat_entry_argp(NULL, cmdline, sizeof(cmdline)); @@ -138,9 +261,16 @@ void _libkvmplat_entry(void *arg) */ _mb_get_cmdline(mi); _mb_init_mem(mi); + _mb_init_initrd(mi); + if (_libkvmplat_cfg.initrd.len) + uk_pr_info(" initrd: %p\n", + (void *) _libkvmplat_cfg.initrd.start); uk_pr_info(" heap start: %p\n", (void *) _libkvmplat_cfg.heap.start); + if (_libkvmplat_cfg.heap2.len) + uk_pr_info(" heap start (2): %p\n", + (void *) _libkvmplat_cfg.heap2.start); uk_pr_info(" stack top: %p\n", (void *) _libkvmplat_cfg.bstack.start); -- 2.21.0 _______________________________________________ Minios-devel mailing list Minios-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/minios-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |