xen: implement hook to fetch and parse e820 memory map
e820 memory map is fetched using a hypercall under Xen PVH, so add a hook to init_ops in oder to diverge from bare metal and implement a Xen variant. Approved by: gibbs Sponsored by: Citrix Systems R&D x86/include/init.h: - Add a parse_memmap hook to init_ops, that will be called to fetch and parse the memory map. amd64/amd64/machdep.c: - Decouple the fetch and the parse of the memmap, so the parse function can be shared with Xen code. - Move code around in order to implement the parse_memmap hook. amd64/include/pc/bios.h: - Declare bios_add_smap_entries (implemented in machdep.c). x86/xen/pv.c: - Implement fetching of e820 memmap when running as a PVH guest by using the XENMEM_memory_map hypercall.
This commit is contained in:
parent
5f05c79450
commit
1e69553ed1
@ -169,11 +169,15 @@ 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);
|
||||
|
||||
/* Native function to fetch and parse the e820 map */
|
||||
static void native_parse_memmap(caddr_t, vm_paddr_t *, int *);
|
||||
|
||||
/* Default init_ops implementation. */
|
||||
struct init_ops init_ops = {
|
||||
.parse_preload_data = native_parse_preload_data,
|
||||
.early_clock_source_init = i8254_init,
|
||||
.early_delay = i8254_delay,
|
||||
.parse_memmap = native_parse_memmap,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -1403,21 +1407,12 @@ add_physmap_entry(uint64_t base, uint64_t length, vm_paddr_t *physmap,
|
||||
return (1);
|
||||
}
|
||||
|
||||
static void
|
||||
add_smap_entries(struct bios_smap *smapbase, vm_paddr_t *physmap,
|
||||
int *physmap_idx)
|
||||
void
|
||||
bios_add_smap_entries(struct bios_smap *smapbase, u_int32_t smapsize,
|
||||
vm_paddr_t *physmap, int *physmap_idx)
|
||||
{
|
||||
struct bios_smap *smap, *smapend;
|
||||
u_int32_t smapsize;
|
||||
|
||||
/*
|
||||
* Memory map from INT 15:E820.
|
||||
*
|
||||
* subr_module.c says:
|
||||
* "Consumer may safely assume that size value precedes data."
|
||||
* ie: an int32_t immediately precedes smap.
|
||||
*/
|
||||
smapsize = *((u_int32_t *)smapbase - 1);
|
||||
smapend = (struct bios_smap *)((uintptr_t)smapbase + smapsize);
|
||||
|
||||
for (smap = smapbase; smap < smapend; smap++) {
|
||||
@ -1434,6 +1429,29 @@ add_smap_entries(struct bios_smap *smapbase, vm_paddr_t *physmap,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
native_parse_memmap(caddr_t kmdp, vm_paddr_t *physmap, int *physmap_idx)
|
||||
{
|
||||
struct bios_smap *smap;
|
||||
u_int32_t size;
|
||||
|
||||
/*
|
||||
* Memory map from INT 15:E820.
|
||||
*
|
||||
* subr_module.c says:
|
||||
* "Consumer may safely assume that size value precedes data."
|
||||
* ie: an int32_t immediately precedes smap.
|
||||
*/
|
||||
|
||||
smap = (struct bios_smap *)preload_search_info(kmdp,
|
||||
MODINFO_METADATA | MODINFOMD_SMAP);
|
||||
if (smap == NULL)
|
||||
panic("No BIOS smap info from loader!");
|
||||
size = *((u_int32_t *)smap - 1);
|
||||
|
||||
bios_add_smap_entries(smap, size, physmap, physmap_idx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Populate the (physmap) array with base/bound pairs describing the
|
||||
* available physical memory in the system, then test this memory and
|
||||
@ -1451,19 +1469,13 @@ getmemsize(caddr_t kmdp, u_int64_t first)
|
||||
vm_paddr_t pa, physmap[PHYSMAP_SIZE];
|
||||
u_long physmem_start, physmem_tunable, memtest;
|
||||
pt_entry_t *pte;
|
||||
struct bios_smap *smapbase;
|
||||
quad_t dcons_addr, dcons_size;
|
||||
|
||||
bzero(physmap, sizeof(physmap));
|
||||
basemem = 0;
|
||||
physmap_idx = 0;
|
||||
|
||||
smapbase = (struct bios_smap *)preload_search_info(kmdp,
|
||||
MODINFO_METADATA | MODINFOMD_SMAP);
|
||||
if (smapbase == NULL)
|
||||
panic("No BIOS smap info from loader!");
|
||||
|
||||
add_smap_entries(smapbase, physmap, &physmap_idx);
|
||||
init_ops.parse_memmap(kmdp, physmap, &physmap_idx);
|
||||
|
||||
/*
|
||||
* Find the 'base memory' segment for SMP
|
||||
|
@ -106,6 +106,8 @@ struct bios_oem {
|
||||
int bios_oem_strings(struct bios_oem *oem, u_char *buffer, size_t maxlen);
|
||||
uint32_t bios_sigsearch(uint32_t start, u_char *sig, int siglen, int paralen,
|
||||
int sigofs);
|
||||
void bios_add_smap_entries(struct bios_smap *smapbase, u_int32_t smapsize,
|
||||
vm_paddr_t *physmap, int *physmap_idx);
|
||||
#endif
|
||||
|
||||
#endif /* _MACHINE_PC_BIOS_H_ */
|
||||
|
@ -38,6 +38,7 @@ struct init_ops {
|
||||
caddr_t (*parse_preload_data)(u_int64_t);
|
||||
void (*early_clock_source_init)(void);
|
||||
void (*early_delay)(int);
|
||||
void (*parse_memmap)(caddr_t, vm_paddr_t *, int *);
|
||||
};
|
||||
|
||||
extern struct init_ops init_ops;
|
||||
|
@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <vm/vm_param.h>
|
||||
|
||||
#include <x86/init.h>
|
||||
#include <machine/pc/bios.h>
|
||||
|
||||
#include <xen/xen-os.h>
|
||||
#include <xen/hypervisor.h>
|
||||
@ -60,8 +61,11 @@ 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);
|
||||
|
||||
#define MAX_E820_ENTRIES 128
|
||||
|
||||
/*--------------------------- Forward Declarations ---------------------------*/
|
||||
static caddr_t xen_pv_parse_preload_data(u_int64_t);
|
||||
static void xen_pv_parse_memmap(caddr_t, vm_paddr_t *, int *);
|
||||
|
||||
/*-------------------------------- Global Data -------------------------------*/
|
||||
/* Xen init_ops implementation. */
|
||||
@ -69,8 +73,11 @@ struct init_ops xen_init_ops = {
|
||||
.parse_preload_data = xen_pv_parse_preload_data,
|
||||
.early_clock_source_init = xen_clock_init,
|
||||
.early_delay = xen_delay,
|
||||
.parse_memmap = xen_pv_parse_memmap,
|
||||
};
|
||||
|
||||
static struct bios_smap xen_smap[MAX_E820_ENTRIES];
|
||||
|
||||
/*-------------------------------- Xen PV init -------------------------------*/
|
||||
/*
|
||||
* First function called by the Xen PVH boot sequence.
|
||||
@ -189,3 +196,21 @@ xen_pv_parse_preload_data(u_int64_t modulep)
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
xen_pv_parse_memmap(caddr_t kmdp, vm_paddr_t *physmap, int *physmap_idx)
|
||||
{
|
||||
struct xen_memory_map memmap;
|
||||
u_int32_t size;
|
||||
int rc;
|
||||
|
||||
/* Fetch the E820 map from Xen */
|
||||
memmap.nr_entries = MAX_E820_ENTRIES;
|
||||
set_xen_guest_handle(memmap.buffer, xen_smap);
|
||||
rc = HYPERVISOR_memory_op(XENMEM_memory_map, &memmap);
|
||||
if (rc)
|
||||
panic("unable to fetch Xen E820 memory map");
|
||||
size = memmap.nr_entries * sizeof(xen_smap[0]);
|
||||
|
||||
bios_add_smap_entries(xen_smap, size, physmap, physmap_idx);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user