Author: royger
Date: Tue Mar 11 10:23:03 2014
New Revision: 263009
URL: http://svnweb.freebsd.org/changeset/base/263009

Log:
  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.

Modified:
  head/sys/amd64/amd64/machdep.c
  head/sys/amd64/include/pc/bios.h
  head/sys/x86/include/init.h
  head/sys/x86/xen/pv.c

Modified: head/sys/amd64/amd64/machdep.c
==============================================================================
--- head/sys/amd64/amd64/machdep.c      Tue Mar 11 10:20:42 2014        
(r263008)
+++ head/sys/amd64/amd64/machdep.c      Tue Mar 11 10:23:03 2014        
(r263009)
@@ -169,11 +169,15 @@ SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST,
 /* 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_
        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 *smapb
        }
 }
 
+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

Modified: head/sys/amd64/include/pc/bios.h
==============================================================================
--- head/sys/amd64/include/pc/bios.h    Tue Mar 11 10:20:42 2014        
(r263008)
+++ head/sys/amd64/include/pc/bios.h    Tue Mar 11 10:23:03 2014        
(r263009)
@@ -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_ */

Modified: head/sys/x86/include/init.h
==============================================================================
--- head/sys/x86/include/init.h Tue Mar 11 10:20:42 2014        (r263008)
+++ head/sys/x86/include/init.h Tue Mar 11 10:23:03 2014        (r263009)
@@ -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;

Modified: head/sys/x86/xen/pv.c
==============================================================================
--- head/sys/x86/xen/pv.c       Tue Mar 11 10:20:42 2014        (r263008)
+++ head/sys/x86/xen/pv.c       Tue Mar 11 10:23:03 2014        (r263009)
@@ -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, 
 /* 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 modu
 
        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);
+}
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to