diff options
author | royger <royger@FreeBSD.org> | 2014-03-11 10:15:25 +0000 |
---|---|---|
committer | royger <royger@FreeBSD.org> | 2014-03-11 10:15:25 +0000 |
commit | 4df602a6bf5fb29881afd7bd076a9b24951de9f1 (patch) | |
tree | 1fe4381c5b35ee4e887b9a4082c2ef05e223e72a | |
parent | b13d7383ff521e0632a1a7bb0c0abb7c65a98ab2 (diff) | |
download | FreeBSD-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.c | 41 | ||||
-rw-r--r-- | sys/x86/include/init.h | 43 | ||||
-rw-r--r-- | sys/x86/xen/pv.c | 63 |
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); +} |