[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v3 11/18] xen: get memory map from hypervisor for PVH



Retrieve the memory map from the hypervisor and normalize it to contain
no overlapping entries and to be sorted by address.

Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
---
V3: use grub_e820_mmap_entry instead of own struct (Daniel Kiper)
---
 grub-core/kern/i386/xen/pvh.c | 96 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 95 insertions(+), 1 deletion(-)

diff --git a/grub-core/kern/i386/xen/pvh.c b/grub-core/kern/i386/xen/pvh.c
index 7e90a4538..58e6fefd5 100644
--- a/grub-core/kern/i386/xen/pvh.c
+++ b/grub-core/kern/i386/xen/pvh.c
@@ -23,9 +23,14 @@
 #include <grub/i386/cpuid.h>
 #include <grub/i386/io.h>
 #include <grub/xen.h>
+#include <grub/i386/linux.h>
 #include <grub/machine/kernel.h>
+#include <grub/machine/memory.h>
+#include <xen/memory.h>
 
-#define XEN_CONSOLE_PORT   0xe9
+#define XEN_CONSOLE_PORT      0xe9
+
+#define XEN_MEMORY_MAP_SIZE   128
 
 grub_uint64_t grub_rsdp_addr;
 
@@ -33,6 +38,8 @@ static char hypercall_page[GRUB_XEN_PAGE_SIZE]
   __attribute__ ((aligned (GRUB_XEN_PAGE_SIZE)));
 
 static grub_uint32_t xen_cpuid_base;
+static struct grub_e820_mmap_entry map[XEN_MEMORY_MAP_SIZE];
+static unsigned int nr_map_entries;
 
 static void
 grub_xen_panic (const char *msg)
@@ -92,11 +99,98 @@ grub_xen_hypercall (grub_uint32_t callno, grub_uint32_t a0,
   return __res;
 }
 
+static void
+grub_xen_sort_mmap (void)
+{
+  grub_uint64_t from, to;
+  unsigned int i;
+  struct grub_e820_mmap_entry tmp;
+
+  /* Align map entries to page boundaries. */
+  for (i = 0; i < nr_map_entries; i++)
+    {
+      from = map[i].addr;
+      to = from + map[i].len;
+      if (map[i].type == GRUB_MEMORY_AVAILABLE)
+       {
+         from = ALIGN_UP (from, GRUB_XEN_PAGE_SIZE);
+         to = ALIGN_DOWN (to, GRUB_XEN_PAGE_SIZE);
+       }
+      else
+       {
+         from = ALIGN_DOWN (from, GRUB_XEN_PAGE_SIZE);
+         to = ALIGN_UP (to, GRUB_XEN_PAGE_SIZE);
+       }
+      map[i].addr = from;
+      map[i].len = to - from;
+    }
+
+ again:
+  /* Sort entries by start address. */
+  for (i = 1; i < nr_map_entries; i++)
+    {
+      if (map[i].addr >= map[i - 1].addr)
+       continue;
+      tmp = map[i];
+      map[i] = map[i - 1];
+      map[i - 1] = tmp;
+      i = 0;
+    }
+
+  /* Detect overlapping areas. */
+  for (i = 1; i < nr_map_entries; i++)
+    {
+      if (map[i].addr >= map[i - 1].addr + map[i - 1].len)
+       continue;
+      tmp = map[i - 1];
+      map[i - 1].len = map[i].addr - map[i - 1].addr;
+      if (map[i].addr + map[i].len >= tmp.addr + tmp.len)
+       continue;
+      if (nr_map_entries < ARRAY_SIZE (map))
+       {
+         map[nr_map_entries].addr = map[i].addr + map[i].len;
+         map[nr_map_entries].len = tmp.addr + tmp.len - 
map[nr_map_entries].addr;
+         map[nr_map_entries].type = tmp.type;
+         nr_map_entries++;
+         goto again;
+       }
+    }
+
+  /* Merge adjacent entries. */
+  for (i = 1; i < nr_map_entries; i++)
+    {
+      if (map[i].type == map[i - 1].type &&
+         map[i].addr == map[i - 1].addr + map[i - 1].len)
+       {
+         map[i - 1].len += map[i].len;
+         map[i] = map[nr_map_entries - 1];
+         nr_map_entries--;
+         goto again;
+       }
+    }
+}
+
+static void
+grub_xen_get_mmap (void)
+{
+  struct xen_memory_map memmap;
+
+  memmap.nr_entries = ARRAY_SIZE (map);
+  set_xen_guest_handle (memmap.buffer, map);
+  if (grub_xen_hypercall (__HYPERVISOR_memory_op, XENMEM_memory_map,
+                         (grub_uint32_t) (&memmap), 0, 0, 0, 0))
+    grub_xen_panic ("Could not get memory map from Xen.\n");
+  nr_map_entries = memmap.nr_entries;
+
+  grub_xen_sort_mmap ();
+}
+
 void
 grub_xen_setup_pvh (void)
 {
   grub_xen_cpuid_base ();
   grub_xen_setup_hypercall_page ();
+  grub_xen_get_mmap ();
 }
 
 grub_err_t
-- 
2.16.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.