1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-26 16:18:31 +00:00

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.
This commit is contained in:
Roger Pau Monné 2014-03-11 10:15:25 +00:00
parent aa389b4f8c
commit 97baeefd5b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=263006
3 changed files with 136 additions and 11 deletions

View File

@ -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 @@ getmemsize(caddr_t kmdp, u_int64_t first)
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();

43
sys/x86/include/init.h Normal file
View File

@ -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__ */

View File

@ -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);
}