summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorroyger <royger@FreeBSD.org>2014-03-11 10:15:25 +0000
committerroyger <royger@FreeBSD.org>2014-03-11 10:15:25 +0000
commit4df602a6bf5fb29881afd7bd076a9b24951de9f1 (patch)
tree1fe4381c5b35ee4e887b9a4082c2ef05e223e72a
parentb13d7383ff521e0632a1a7bb0c0abb7c65a98ab2 (diff)
downloadFreeBSD-src-4df602a6bf5fb29881afd7bd076a9b24951de9f1.zip
FreeBSD-src-4df602a6bf5fb29881afd7bd076a9b24951de9f1.tar.gz
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.
-rw-r--r--sys/amd64/amd64/machdep.c41
-rw-r--r--sys/x86/include/init.h43
-rw-r--r--sys/x86/xen/pv.c63
3 files changed, 136 insertions, 11 deletions
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index 52256f7..dc4b09c 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -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 *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.
@@ -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 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/x86/include/init.h b/sys/x86/include/init.h
new file mode 100644
index 0000000..7e032df
--- /dev/null
+++ b/sys/x86/include/init.h
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2013 Roger Pau Monné <roger.pau@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__ */
diff --git a/sys/x86/xen/pv.c b/sys/x86/xen/pv.c
index 94985e3..63dc39b 100644
--- a/sys/x86/xen/pv.c
+++ b/sys/x86/xen/pv.c
@@ -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, 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_t xenstack)
}
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);
+}
OpenPOWER on IntegriCloud