svn commit: r263006 - in head/sys: amd64/amd64 x86/include x86/xen

Roger Pau Monné royger at FreeBSD.org
Tue Mar 11 10:15:26 UTC 2014


Author: royger
Date: Tue Mar 11 10:15:25 2014
New Revision: 263006
URL: http://svnweb.freebsd.org/changeset/base/263006

Log:
  amd64: introduce hook for custom preload metadata parsers
  
  Add hooks to amd64 in order to have diverging implementations, since
  on Xen PV the metadata is passed to the kernel in a different form.
  
  Approbed by: gibbs
  Sponsored by: Citrix Systems R&D
  
  amd64/amd64/machdep.c:
   - Define init_ops for native.
   - Put native code inside of native_parse_preload_data hook.
   - Call the parse_preload_data in order to fill the metadata info.
  
  x86/include/init.h:
   - Declare the init_ops struct.
  
  x86/xen/pv.c:
   - Declare xen_init_ops that contains the Xen PV implementation of
     init_ops.
   - Implement the parse_preload_data for Xen PVH, the info is fetched
     from HYPERVISOR_start_info->cmd_line as provided by Xen.

Added:
  head/sys/x86/include/init.h   (contents, props changed)
Modified:
  head/sys/amd64/amd64/machdep.c
  head/sys/x86/xen/pv.c

Modified: head/sys/amd64/amd64/machdep.c
==============================================================================
--- head/sys/amd64/amd64/machdep.c	Tue Mar 11 10:13:06 2014	(r263005)
+++ head/sys/amd64/amd64/machdep.c	Tue Mar 11 10:15:25 2014	(r263006)
@@ -145,6 +145,7 @@ __FBSDID("$FreeBSD$");
 
 #include <isa/isareg.h>
 #include <isa/rtc.h>
+#include <x86/init.h>
 
 /* Sanity check for __curthread() */
 CTASSERT(offsetof(struct pcpu, pc_curthread) == 0);
@@ -165,6 +166,14 @@ static int  set_fpcontext(struct thread 
     char *xfpustate, size_t xfpustate_len);
 SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL);
 
+/* Preload data parse function */
+static caddr_t native_parse_preload_data(u_int64_t);
+
+/* Default init_ops implementation. */
+struct init_ops init_ops = {
+	.parse_preload_data =	native_parse_preload_data,
+};
+
 /*
  * The file "conf/ldscript.amd64" defines the symbol "kernphys".  Its value is
  * the physical address at which the kernel is loaded.
@@ -1685,6 +1694,26 @@ do_next:
 	msgbufp = (struct msgbuf *)PHYS_TO_DMAP(phys_avail[pa_indx]);
 }
 
+static caddr_t
+native_parse_preload_data(u_int64_t modulep)
+{
+	caddr_t kmdp;
+
+	preload_metadata = (caddr_t)(uintptr_t)(modulep + KERNBASE);
+	preload_bootstrap_relocate(KERNBASE);
+	kmdp = preload_search_by_type("elf kernel");
+	if (kmdp == NULL)
+		kmdp = preload_search_by_type("elf64 kernel");
+	boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
+	kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *) + KERNBASE;
+#ifdef DDB
+	ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t);
+	ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t);
+#endif
+
+	return (kmdp);
+}
+
 u_int64_t
 hammer_time(u_int64_t modulep, u_int64_t physfree)
 {
@@ -1709,17 +1738,7 @@ hammer_time(u_int64_t modulep, u_int64_t
 	 */
 	proc_linkup0(&proc0, &thread0);
 
-	preload_metadata = (caddr_t)(uintptr_t)(modulep + KERNBASE);
-	preload_bootstrap_relocate(KERNBASE);
-	kmdp = preload_search_by_type("elf kernel");
-	if (kmdp == NULL)
-		kmdp = preload_search_by_type("elf64 kernel");
-	boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
-	kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *) + KERNBASE;
-#ifdef DDB
-	ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t);
-	ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t);
-#endif
+	kmdp = init_ops.parse_preload_data(modulep);
 
 	/* Init basic tunables, hz etc */
 	init_param1();

Added: head/sys/x86/include/init.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/x86/include/init.h	Tue Mar 11 10:15:25 2014	(r263006)
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2013 Roger Pau Monné <roger.pau at citrix.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __X86_INIT_H__
+#define __X86_INIT_H__
+/*
+ * Struct containing pointers to init functions whose
+ * implementation is run time selectable.  Selection can be made,
+ * for example, based on detection of a BIOS variant or
+ * hypervisor environment.
+ */
+struct init_ops {
+	caddr_t	(*parse_preload_data)(u_int64_t);
+};
+
+extern struct init_ops init_ops;
+
+#endif /* __X86_INIT_H__ */

Modified: head/sys/x86/xen/pv.c
==============================================================================
--- head/sys/x86/xen/pv.c	Tue Mar 11 10:13:06 2014	(r263005)
+++ head/sys/x86/xen/pv.c	Tue Mar 11 10:15:25 2014	(r263006)
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/lock.h>
 #include <sys/rwlock.h>
 #include <sys/boot.h>
+#include <sys/ctype.h>
 
 #include <vm/vm.h>
 #include <vm/vm_extern.h>
@@ -47,6 +48,8 @@ __FBSDID("$FreeBSD$");
 #include <vm/vm_pager.h>
 #include <vm/vm_param.h>
 
+#include <x86/init.h>
+
 #include <xen/xen-os.h>
 #include <xen/hypervisor.h>
 
@@ -55,6 +58,16 @@ extern u_int64_t hammer_time(u_int64_t, 
 /* Xen initial function */
 uint64_t hammer_time_xen(start_info_t *, uint64_t);
 
+/*--------------------------- Forward Declarations ---------------------------*/
+static caddr_t xen_pv_parse_preload_data(u_int64_t);
+
+/*-------------------------------- Global Data -------------------------------*/
+/* Xen init_ops implementation. */
+struct init_ops xen_init_ops = {
+	.parse_preload_data =	xen_pv_parse_preload_data,
+};
+
+/*-------------------------------- Xen PV init -------------------------------*/
 /*
  * First function called by the Xen PVH boot sequence.
  *
@@ -119,6 +132,56 @@ hammer_time_xen(start_info_t *si, uint64
 	}
 	load_cr3(((uint64_t)&PT4[0]) - KERNBASE);
 
+	/* Set the hooks for early functions that diverge from bare metal */
+	init_ops = xen_init_ops;
+
 	/* Now we can jump into the native init function */
 	return (hammer_time(0, physfree));
 }
+
+/*-------------------------------- PV specific -------------------------------*/
+/*
+ * Functions to convert the "extra" parameters passed by Xen
+ * into FreeBSD boot options.
+ */
+static void
+xen_pv_set_env(void)
+{
+	char *cmd_line_next, *cmd_line;
+	size_t env_size;
+
+	cmd_line = HYPERVISOR_start_info->cmd_line;
+	env_size = sizeof(HYPERVISOR_start_info->cmd_line);
+
+	/* Skip leading spaces */
+	for (; isspace(*cmd_line) && (env_size != 0); cmd_line++)
+		env_size--;
+
+	/* Replace ',' with '\0' */
+	for (cmd_line_next = cmd_line; strsep(&cmd_line_next, ",") != NULL;)
+		;
+
+	init_static_kenv(cmd_line, env_size);
+}
+
+static void
+xen_pv_set_boothowto(void)
+{
+	int i;
+
+	/* get equivalents from the environment */
+	for (i = 0; howto_names[i].ev != NULL; i++) {
+		if (getenv(howto_names[i].ev) != NULL)
+			boothowto |= howto_names[i].mask;
+	}
+}
+
+static caddr_t
+xen_pv_parse_preload_data(u_int64_t modulep)
+{
+	/* Parse the extra boot information given by Xen */
+	xen_pv_set_env();
+	xen_pv_set_boothowto();
+
+	return (NULL);
+}


More information about the svn-src-all mailing list