]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
xen: add capability to load p2m list outside of kernel mapping
authorJuergen Gross <jgross@suse.com>
Thu, 3 Mar 2016 09:38:16 +0000 (10:38 +0100)
committerDaniel Kiper <daniel.kiper@oracle.com>
Thu, 27 Oct 2016 14:22:06 +0000 (16:22 +0200)
Modern pvops linux kernels support a p2m list not covered by the
kernel mapping. This capability is flagged by an elf-note specifying
the virtual address the kernel is expecting the p2m list to be mapped
to.

In case the elf-note is set by the kernel don't place the p2m list
into the kernel mapping, but map it to the given address. This will
allow to support domains with larger memory, as the kernel mapping is
limited to 2GB and a domain with huge memory in the TB range will have
a p2m list larger than this.

Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
grub-core/loader/i386/xen.c
grub-core/loader/i386/xen_fileXX.c
include/grub/xen_file.h

index a98badf440b7989fd6b1406f935dbba4124f7775..51d1ddd378cc6e07211db2349bce74b1158728f2 100644 (file)
@@ -313,24 +313,50 @@ static grub_err_t
 grub_xen_p2m_alloc (void)
 {
   grub_relocator_chunk_t ch;
-  grub_size_t p2msize;
+  grub_size_t p2msize, p2malloc;
   grub_err_t err;
+  struct grub_xen_mapping *map;
 
   if (xen_state.virt_mfn_list)
     return GRUB_ERR_NONE;
 
+  map = xen_state.mappings + xen_state.n_mappings;
+  p2msize = ALIGN_UP (sizeof (grub_xen_mfn_t) *
+                     grub_xen_start_page_addr->nr_pages, PAGE_SIZE);
+  if (xen_state.xen_inf.has_p2m_base)
+    {
+      err = get_pgtable_size (xen_state.xen_inf.p2m_base,
+                             xen_state.xen_inf.p2m_base + p2msize,
+                             (xen_state.max_addr + p2msize) >> PAGE_SHIFT);
+      if (err)
+       return err;
+
+      map->area.pfn_start = xen_state.max_addr >> PAGE_SHIFT;
+      p2malloc = p2msize + page2offset (map->area.n_pt_pages);
+      xen_state.n_mappings++;
+      xen_state.next_start.mfn_list = xen_state.xen_inf.p2m_base;
+      xen_state.next_start.first_p2m_pfn = map->area.pfn_start;
+      xen_state.next_start.nr_p2m_frames = p2malloc >> PAGE_SHIFT;
+    }
+  else
+    {
+      xen_state.next_start.mfn_list =
+       xen_state.max_addr + xen_state.xen_inf.virt_base;
+      p2malloc = p2msize;
+    }
+
   xen_state.state.mfn_list = xen_state.max_addr;
-  xen_state.next_start.mfn_list =
-    xen_state.max_addr + xen_state.xen_inf.virt_base;
-  p2msize = sizeof (grub_xen_mfn_t) * grub_xen_start_page_addr->nr_pages;
   err = grub_relocator_alloc_chunk_addr (xen_state.relocator, &ch,
-                                        xen_state.max_addr, p2msize);
+                                        xen_state.max_addr, p2malloc);
   if (err)
     return err;
   xen_state.virt_mfn_list = get_virtual_current_address (ch);
+  if (xen_state.xen_inf.has_p2m_base)
+    map->where = (grub_uint64_t *) xen_state.virt_mfn_list +
+                p2msize / sizeof (grub_uint64_t);
   grub_memcpy (xen_state.virt_mfn_list,
               (void *) grub_xen_start_page_addr->mfn_list, p2msize);
-  xen_state.max_addr = ALIGN_UP (xen_state.max_addr + p2msize, PAGE_SIZE);
+  xen_state.max_addr += p2malloc;
 
   return GRUB_ERR_NONE;
 }
@@ -448,9 +474,12 @@ grub_xen_alloc_boot_data (void)
 {
   grub_err_t err;
 
-  err = grub_xen_p2m_alloc ();
-  if (err)
-    return err;
+  if (!xen_state.xen_inf.has_p2m_base)
+    {
+      err = grub_xen_p2m_alloc ();
+      if (err)
+       return err;
+    }
   err = grub_xen_special_alloc ();
   if (err)
     return err;
@@ -475,6 +504,12 @@ grub_xen_boot (void)
   err = grub_xen_alloc_boot_data ();
   if (err)
     return err;
+  if (xen_state.xen_inf.has_p2m_base)
+    {
+      err = grub_xen_p2m_alloc ();
+      if (err)
+       return err;
+    }
 
   err = set_mfns (xen_state.console_pfn);
   if (err)
index 8751174cf578c58a985ec07955d94a4e9cccbfcc..fb66e66fe960db0da24a86e6c248e1f213078091 100644 (file)
@@ -261,6 +261,10 @@ parse_note (grub_elf_t elf, struct grub_xen_file_info *xi,
                                          descsz == 2 ? 2 : 3) == 0)
            xi->arch = GRUB_XEN_FILE_I386;
          break;
+       case XEN_ELFNOTE_INIT_P2M:
+         xi->p2m_base = grub_le_to_cpu_addr (*(Elf_Addr *) desc);
+         xi->has_p2m_base = 1;
+         break;
        case XEN_ELFNOTE_MOD_START_PFN:
          xi->unmapped_initrd = !!grub_le_to_cpu32(*(grub_uint32_t *) desc);
          break;
index ed749fafeaca29698ecb9b7bc74cbc4d3d56b746..658799952bbc94f6ec2e8fe8baf2aa5de5e3478b 100644 (file)
@@ -32,9 +32,11 @@ struct grub_xen_file_info
   grub_uint64_t entry_point;
   grub_uint64_t hypercall_page;
   grub_uint64_t paddr_offset;
+  grub_uint64_t p2m_base;
   int has_hypercall_page;
   int has_note;
   int has_xen_guest;
+  int has_p2m_base;
   int extended_cr3;
   int unmapped_initrd;
   enum