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

[Xen-devel] [PATCH v2 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>
---
 grub-core/kern/i386/xen/pvh.c | 98 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 98 insertions(+)

diff --git a/grub-core/kern/i386/xen/pvh.c b/grub-core/kern/i386/xen/pvh.c
index c1b1cf8db..b4933b454 100644
--- a/grub-core/kern/i386/xen/pvh.c
+++ b/grub-core/kern/i386/xen/pvh.c
@@ -22,7 +22,16 @@
 #include <grub/mm.h>
 #include <grub/i386/cpuid.h>
 #include <grub/xen.h>
+#include <grub/i386/linux.h>
 #include <grub/machine/kernel.h>
+#include <xen/memory.h>
+
+struct xen_machine_mmap_entry
+{
+  grub_uint64_t addr;
+  grub_uint64_t len;
+  grub_uint32_t type;
+} GRUB_PACKED;
 
 grub_uint64_t grub_rsdp_addr;
 
@@ -30,6 +39,8 @@ static struct { char _entry[32]; } hypercall_page[128]
   __attribute__ ((aligned (GRUB_XEN_PAGE_SIZE)));
 
 static grub_uint32_t xen_cpuid_base;
+static struct xen_machine_mmap_entry map[128];
+static unsigned int nr_map_entries;
 
 static void
 grub_xen_early_halt (void)
@@ -93,11 +104,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 xen_machine_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_early_halt ();
+  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®.