Date: Thu, 13 Apr 2017 09:59:12 +0000 (UTC) From: =?UTF-8?Q?Roger_Pau_Monn=c3=a9?= <royger@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r316754 - in head/sys/boot: common i386/libi386 Message-ID: <201704130959.v3D9xCOo056518@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: royger Date: Thu Apr 13 09:59:12 2017 New Revision: 316754 URL: https://svnweb.freebsd.org/changeset/base/316754 Log: loader/multiboot: fix multiboot loading The current multiboot loader code doesn't clean the metadata added to the kernel after the bi_load64 dry run, which breaks accounting of the required memory for the metadata. This issue didn't show itself before because all the metadata items where small (8bytes), but after r316343 there's a big blob in the metadata, which triggers this. Fix it by cleaning the metadata added to the kernel after the bi_load64 dry run. Also add a comment describing the memory layout when booting using multiboot (Xen Dom0). This unbreaks booting a FreeBSD/Xen Dom0 after r316343. MFC after: 3 weeks Sponsored by: Citrix Systems R&D Modified: head/sys/boot/common/bootstrap.h head/sys/boot/common/module.c head/sys/boot/i386/libi386/multiboot.c Modified: head/sys/boot/common/bootstrap.h ============================================================================== --- head/sys/boot/common/bootstrap.h Thu Apr 13 08:21:29 2017 (r316753) +++ head/sys/boot/common/bootstrap.h Thu Apr 13 09:59:12 2017 (r316754) @@ -228,6 +228,7 @@ void file_discard(struct preloaded_file void file_addmetadata(struct preloaded_file *fp, int type, size_t size, void *p); int file_addmodule(struct preloaded_file *fp, char *modname, int version, struct kernel_module **newmp); +void file_removemetadata(struct preloaded_file *fp); /* MI module loaders */ #ifdef __elfN Modified: head/sys/boot/common/module.c ============================================================================== --- head/sys/boot/common/module.c Thu Apr 13 08:21:29 2017 (r316753) +++ head/sys/boot/common/module.c Thu Apr 13 09:59:12 2017 (r316754) @@ -663,6 +663,22 @@ file_findmetadata(struct preloaded_file return(md); } +/* + * Remove all metadata from the file. + */ +void +file_removemetadata(struct preloaded_file *fp) +{ + struct file_metadata *md, *next; + + for (md = fp->f_metadata; md != NULL; md = next) + { + next = md->md_next; + free(md); + } + fp->f_metadata = NULL; +} + struct file_metadata * metadata_next(struct file_metadata *md, int type) { Modified: head/sys/boot/i386/libi386/multiboot.c ============================================================================== --- head/sys/boot/i386/libi386/multiboot.c Thu Apr 13 08:21:29 2017 (r316753) +++ head/sys/boot/i386/libi386/multiboot.c Thu Apr 13 09:59:12 2017 (r316754) @@ -267,7 +267,39 @@ multiboot_exec(struct preloaded_file *fp * information is placed at the start of the second module and * the original modulep value is saved together with the other * metadata, so we can relocate everything. + * + * Native layout: + * fp->f_addr + fp->f_size + * +---------+----------------+------------+ + * | | | | + * | Kernel | Modules | Metadata | + * | | | | + * +---------+----------------+------------+ + * fp->f_addr modulep kernend + * + * Xen layout: + * + * Initial: + * fp->f_addr + fp->f_size + * +---------+----------+----------------+------------+ + * | | | | | + * | Kernel | Reserved | Modules | Metadata | + * | | | | dry run | + * +---------+----------+----------------+------------+ + * fp->f_addr + * + * After metadata polacement (ie: final): + * fp->f_addr + fp->f_size + * +-----------+---------+----------+----------------+ + * | | | | | + * | Kernel | Free | Metadata | Modules | + * | | | | | + * +-----------+---------+----------+----------------+ + * fp->f_addr modulep kernend + * \__________/ \__________________________/ + * Multiboot module 0 Multiboot module 1 */ + fp = file_findfile(NULL, "elf kernel"); if (fp == NULL) { printf("No FreeBSD kernel provided, aborting\n"); @@ -275,6 +307,13 @@ multiboot_exec(struct preloaded_file *fp goto error; } + if (fp->f_metadata != NULL) { + printf("FreeBSD kernel already contains metadata, aborting\n"); + error = EINVAL; + goto error; + } + + mb_mod = malloc(sizeof(struct multiboot_mod_list) * NUM_MODULES); if (mb_mod == NULL) { error = ENOMEM; @@ -312,6 +351,9 @@ multiboot_exec(struct preloaded_file *fp goto error; } + /* Clean the metadata added to the kernel in the bi_load64 dry run */ + file_removemetadata(fp); + /* * This is the position where the second multiboot module * will be placed.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201704130959.v3D9xCOo056518>