[PATCH v7 04/19] amd64: introduce hook for custom preload metadata parsers

From: Roger Pau Monne <roger.pau_at_citrix.com>
Date: Thu, 19 Dec 2013 19:54:41 +0100
---
 sys/amd64/amd64/machdep.c   |   45 +++++++++++++----
 sys/amd64/include/sysarch.h |   12 +++++
 sys/conf/files.amd64        |    1 +
 sys/x86/xen/pv.c            |  114 +++++++++++++++++++++++++++++++++++++++++++
 sys/xen/pv.h                |   28 +++++++++++
 5 files changed, 189 insertions(+), 11 deletions(-)
 create mode 100644 sys/x86/xen/pv.c
 create mode 100644 sys/xen/pv.h

diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index 1880f23..09d9a1a 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
_at__at_ -126,6 +126,7 _at__at_ __FBSDID("$FreeBSD$");
 #include <machine/reg.h>
 #include <machine/sigframe.h>
 #include <machine/specialreg.h>
+#include <machine/sysarch.h>
 #ifdef PERFMON
 #include <machine/perfmon.h>
 #endif
_at__at_ -148,6 +149,7 _at__at_ __FBSDID("$FreeBSD$");
 
 #ifdef XENHVM
 #include <xen/xen-os.h>
+#include <xen/pv.h>
 #endif
 
 /* Sanity check for __curthread() */
_at__at_ -172,6 +174,14 _at__at_ static int  set_fpcontext(struct thread *td, const mcontext_t *mcp,
     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.
_at__at_ -1690,6 +1700,26 _at__at_ 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);
+}
+
 #ifdef XENHVM
 /*
  * First function called by the Xen PVH boot sequence.
_at__at_ -1754,6 +1784,9 _at__at_ hammer_time_xen(start_info_t *si, u_int64_t xenstack)
 	}
 	load_cr3(((u_int64_t)&PT4[0]) - KERNBASE);
 
+	/* Set the hooks for early functions that diverge from bare metal */
+	xen_pv_set_init_ops();
+
 	/* Now we can jump into the native init function */
 	return (hammer_time(0, physfree));
 }
_at__at_ -1783,17 +1816,7 _at__at_ hammer_time(u_int64_t modulep, u_int64_t physfree)
 	 */
 	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();
diff --git a/sys/amd64/include/sysarch.h b/sys/amd64/include/sysarch.h
index cd380d4..58ac8cd 100644
--- a/sys/amd64/include/sysarch.h
+++ b/sys/amd64/include/sysarch.h
_at__at_ -4,3 +4,15 _at__at_
 /* $FreeBSD$ */
 
 #include <x86/sysarch.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;
diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
index d1bdcd9..b3b1319 100644
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
_at__at_ -566,3 +566,4 _at__at_ x86/x86/nexus.c			standard
 x86/x86/tsc.c			standard
 x86/xen/hvm.c			optional	xenhvm
 x86/xen/xen_intr.c		optional	xen | xenhvm
+x86/xen/pv.c			optional	xenhvm
diff --git a/sys/x86/xen/pv.c b/sys/x86/xen/pv.c
new file mode 100644
index 0000000..bbaca32
--- /dev/null
+++ b/sys/x86/xen/pv.c
_at__at_ -0,0 +1,114 _at__at_
+/*
+ * Copyright (c) 2004 Christian Limpach.
+ * Copyright (c) 2004-2006,2008 Kip Macy
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/reboot.h>
+#include <sys/systm.h>
+
+#include <machine/sysarch.h>
+
+#include <xen/xen-os.h>
+#include <xen/pv.h>
+
+/*--------------------------- 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,
+};
+
+static struct
+{
+	const char	*ev;
+	int		mask;
+} howto_names[] = {
+	{"boot_askname",	RB_ASKNAME},
+	{"boot_single",		RB_SINGLE},
+	{"boot_nosync",		RB_NOSYNC},
+	{"boot_halt",		RB_ASKNAME},
+	{"boot_serial",		RB_SERIAL},
+	{"boot_cdrom",		RB_CDROM},
+	{"boot_gdb",		RB_GDB},
+	{"boot_gdb_pause",	RB_RESERVED1},
+	{"boot_verbose",	RB_VERBOSE},
+	{"boot_multicons",	RB_MULTIPLE},
+	{NULL,	0}
+};
+
+/*
+ * Functions to convert the "extra" parameters passed by Xen
+ * into FreeBSD boot options (from the i386 Xen port).
+ */
+static char *
+xen_setbootenv(char *cmd_line)
+{
+	char *cmd_line_next;
+
+        /* Skip leading spaces */
+        for (; *cmd_line == ' '; cmd_line++);
+
+	for (cmd_line_next = cmd_line; strsep(&cmd_line_next, ",") != NULL;);
+	return (cmd_line);
+}
+
+static int
+xen_boothowto(char *envp)
+{
+	int i, howto = 0;
+
+	/* get equivalents from the environment */
+	for (i = 0; howto_names[i].ev != NULL; i++)
+		if (getenv(howto_names[i].ev) != NULL)
+			howto |= howto_names[i].mask;
+	return (howto);
+}
+
+static caddr_t
+xen_pv_parse_preload_data(u_int64_t modulep)
+{
+	/* Parse the extra boot information given by Xen */
+	if (HYPERVISOR_start_info->cmd_line)
+		kern_envp = xen_setbootenv(HYPERVISOR_start_info->cmd_line);
+	boothowto |= xen_boothowto(kern_envp);
+
+	return (NULL);
+}
+
+void
+xen_pv_set_init_ops(void)
+{
+	/* Init ops for Xen PV */
+	init_ops = xen_init_ops;
+}
diff --git a/sys/xen/pv.h b/sys/xen/pv.h
new file mode 100644
index 0000000..71b8776
--- /dev/null
+++ b/sys/xen/pv.h
_at__at_ -0,0 +1,28 _at__at_
+/*
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef	__XEN_PV_H__
+#define	__XEN_PV_H__
+
+void	xen_pv_set_init_ops(void);
+
+#endif	/* __XEN_PV_H__ */
-- 
1.7.7.5 (Apple Git-26)
Received on Thu Dec 19 2013 - 17:55:28 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:45 UTC