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

[Xen-devel] [PATCH v3 12/18] xen: setup Xen specific data for PVH



Initialize the needed Xen specific data. This is:

- the Xen start of day page containing the console and Xenstore ring
  page PFN and event channel
- the grant table
- the shared info page

Set the RSDP address for the guest from the start_info page passed
as boot parameter.

Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
---
 grub-core/kern/i386/xen/pvh.c | 106 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 106 insertions(+)

diff --git a/grub-core/kern/i386/xen/pvh.c b/grub-core/kern/i386/xen/pvh.c
index 58e6fefd5..487a87214 100644
--- a/grub-core/kern/i386/xen/pvh.c
+++ b/grub-core/kern/i386/xen/pvh.c
@@ -26,6 +26,7 @@
 #include <grub/i386/linux.h>
 #include <grub/machine/kernel.h>
 #include <grub/machine/memory.h>
+#include <xen/hvm/params.h>
 #include <xen/memory.h>
 
 #define XEN_CONSOLE_PORT      0xe9
@@ -38,6 +39,7 @@ static char hypercall_page[GRUB_XEN_PAGE_SIZE]
   __attribute__ ((aligned (GRUB_XEN_PAGE_SIZE)));
 
 static grub_uint32_t xen_cpuid_base;
+static struct start_info grub_xen_start_page;
 static struct grub_e820_mmap_entry map[XEN_MEMORY_MAP_SIZE];
 static unsigned int nr_map_entries;
 
@@ -99,6 +101,36 @@ grub_xen_hypercall (grub_uint32_t callno, grub_uint32_t a0,
   return __res;
 }
 
+static grub_uint32_t
+grub_xen_get_param (int idx)
+{
+  struct xen_hvm_param xhv;
+  int r;
+
+  xhv.domid = DOMID_SELF;
+  xhv.index = idx;
+  r = grub_xen_hypercall (__HYPERVISOR_hvm_op, HVMOP_get_param,
+                         (grub_uint32_t) (&xhv), 0, 0, 0, 0);
+  if (r < 0)
+    grub_xen_panic ("Could not get parameter from Xen.\n");
+  return xhv.value;
+}
+
+static void *
+grub_xen_add_physmap (unsigned int space, void *addr)
+{
+  struct xen_add_to_physmap xatp;
+
+  xatp.domid = DOMID_SELF;
+  xatp.idx = 0;
+  xatp.space = space;
+  xatp.gpfn = (grub_addr_t) addr >> GRUB_XEN_LOG_PAGE_SIZE;
+  if (grub_xen_hypercall (__HYPERVISOR_memory_op, XENMEM_add_to_physmap,
+                         (grub_uint32_t) (&xatp), 0, 0, 0, 0))
+    grub_xen_panic ("Memory_op hypercall failed.\n");
+  return addr;
+}
+
 static void
 grub_xen_sort_mmap (void)
 {
@@ -185,12 +217,86 @@ grub_xen_get_mmap (void)
   grub_xen_sort_mmap ();
 }
 
+static grub_uint64_t
+grub_xen_find_page (grub_uint64_t start)
+{
+  unsigned int i, j;
+  grub_uint64_t last = start;
+
+  /* Try to find a e820 map hole below 4G. */
+  for (i = 0; i < nr_map_entries; i++)
+    {
+      if (last > map[i].addr + map[i].len)
+       continue;
+      if (last < map[i].addr)
+       return last;
+      if ((map[i].addr >> 32) || ((map[i].addr + map[i].len) >> 32))
+       break;
+      last = map[i].addr + map[i].len;
+    }
+    if (i == nr_map_entries)
+      return last;
+
+  /* No hole found, use the highest RAM page below 4G and reserve it. */
+  if (nr_map_entries == ARRAY_SIZE (map))
+    grub_xen_panic ("Memory map size limit reached.\n");
+  for (i = 0, j = 0; i < nr_map_entries; i++)
+    {
+      if (map[i].type != GRUB_MEMORY_AVAILABLE)
+       continue;
+      if (map[i].addr >> 32)
+       break;
+      j = i;
+      if ((map[i].addr + map[i].len) >> 32)
+       break;
+    }
+  if (map[j].type != GRUB_MEMORY_AVAILABLE)
+    grub_xen_panic ("No free memory page found.\n");
+  if ((map[i].addr + map[i].len) >> 32)
+    last = (1ULL << 32) - GRUB_XEN_PAGE_SIZE;
+  else
+    last = map[i].addr + map[i].len - GRUB_XEN_PAGE_SIZE;
+  map[nr_map_entries].addr = last;
+  map[nr_map_entries].len = GRUB_XEN_PAGE_SIZE;
+  map[nr_map_entries].type = GRUB_MEMORY_RESERVED;
+  nr_map_entries++;
+  grub_xen_sort_mmap ();
+
+  return last;
+}
+
 void
 grub_xen_setup_pvh (void)
 {
+  grub_addr_t par;
+
   grub_xen_cpuid_base ();
   grub_xen_setup_hypercall_page ();
   grub_xen_get_mmap ();
+
+  /* Setup Xen data. */
+  grub_xen_start_page_addr = &grub_xen_start_page;
+
+  par = grub_xen_get_param (HVM_PARAM_CONSOLE_PFN);
+  grub_xen_start_page_addr->console.domU.mfn = par;
+  grub_xen_xcons = (void *) (grub_addr_t) (par << GRUB_XEN_LOG_PAGE_SIZE);
+  par = grub_xen_get_param (HVM_PARAM_CONSOLE_EVTCHN);
+  grub_xen_start_page_addr->console.domU.evtchn = par;
+
+  par = grub_xen_get_param (HVM_PARAM_STORE_PFN);
+  grub_xen_start_page_addr->store_mfn = par;
+  grub_xen_xenstore = (void *) (grub_addr_t) (par << GRUB_XEN_LOG_PAGE_SIZE);
+  par = grub_xen_get_param (HVM_PARAM_STORE_EVTCHN);
+  grub_xen_start_page_addr->store_evtchn = par;
+
+  par = grub_xen_find_page (0);
+  grub_xen_grant_table = grub_xen_add_physmap (XENMAPSPACE_grant_table,
+                                              (void *) par);
+  par = grub_xen_find_page (par + GRUB_XEN_PAGE_SIZE);
+  grub_xen_shared_info = grub_xen_add_physmap (XENMAPSPACE_shared_info,
+                                              (void *) par);
+
+  grub_rsdp_addr = pvh_start_info->rsdp_paddr;
 }
 
 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®.