Skip site navigation (1)Skip section navigation (2)
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>