From owner-svn-src-head@freebsd.org Thu Apr 13 09:59:13 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 917CED3C7F5; Thu, 13 Apr 2017 09:59:13 +0000 (UTC) (envelope-from royger@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 53071124; Thu, 13 Apr 2017 09:59:13 +0000 (UTC) (envelope-from royger@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v3D9xCSC056521; Thu, 13 Apr 2017 09:59:12 GMT (envelope-from royger@FreeBSD.org) Received: (from royger@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v3D9xCOo056518; Thu, 13 Apr 2017 09:59:12 GMT (envelope-from royger@FreeBSD.org) Message-Id: <201704130959.v3D9xCOo056518@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: royger set sender to royger@FreeBSD.org using -f From: =?UTF-8?Q?Roger_Pau_Monn=c3=a9?= Date: Thu, 13 Apr 2017 09:59:12 +0000 (UTC) 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 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 13 Apr 2017 09:59:13 -0000 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.