diff options
author | royger <royger@FreeBSD.org> | 2014-03-11 10:23:03 +0000 |
---|---|---|
committer | royger <royger@FreeBSD.org> | 2014-03-11 10:23:03 +0000 |
commit | 891131cb52c5aa334778f1f5cb0ac125c88c32cb (patch) | |
tree | b7cab660078ecadafa7c5b0f9abceac9a436bff1 | |
parent | 467e743960e4cc864b1c9be42fb2be7852f0ebb0 (diff) | |
download | FreeBSD-src-891131cb52c5aa334778f1f5cb0ac125c88c32cb.zip FreeBSD-src-891131cb52c5aa334778f1f5cb0ac125c88c32cb.tar.gz |
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.
-rw-r--r-- | sys/amd64/amd64/machdep.c | 50 | ||||
-rw-r--r-- | sys/amd64/include/pc/bios.h | 2 | ||||
-rw-r--r-- | sys/x86/include/init.h | 1 | ||||
-rw-r--r-- | sys/x86/xen/pv.c | 25 |
4 files changed, 59 insertions, 19 deletions
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index d52020c..857d7e9 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -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 diff --git a/sys/amd64/include/pc/bios.h b/sys/amd64/include/pc/bios.h index e7d568e..95ef703 100644 --- a/sys/amd64/include/pc/bios.h +++ b/sys/amd64/include/pc/bios.h @@ -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_ */ diff --git a/sys/x86/include/init.h b/sys/x86/include/init.h index c72889f..562e582 100644 --- a/sys/x86/include/init.h +++ b/sys/x86/include/init.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; diff --git a/sys/x86/xen/pv.c b/sys/x86/xen/pv.c index 4bc7e86..f7d5e47 100644 --- a/sys/x86/xen/pv.c +++ b/sys/x86/xen/pv.c @@ -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); +} |