forked from pool/grub2
150 lines
4.8 KiB
Diff
150 lines
4.8 KiB
Diff
|
From e776ceae4d7fe4ba66484bec7f85110f737168f9 Mon Sep 17 00:00:00 2001
|
||
|
From: Juergen Gross <jgross@suse.com>
|
||
|
Date: Thu, 3 Mar 2016 10:38:16 +0100
|
||
|
Subject: [PATCH 11/11] xen: add capability to load p2m list outside of kernel
|
||
|
mapping
|
||
|
|
||
|
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 | 53 +++++++++++++++++++++++++++++++-------
|
||
|
grub-core/loader/i386/xen_fileXX.c | 4 +++
|
||
|
include/grub/xen_file.h | 2 ++
|
||
|
3 files changed, 50 insertions(+), 9 deletions(-)
|
||
|
|
||
|
diff --git a/grub-core/loader/i386/xen.c b/grub-core/loader/i386/xen.c
|
||
|
index a98badf..51d1ddd 100644
|
||
|
--- a/grub-core/loader/i386/xen.c
|
||
|
+++ b/grub-core/loader/i386/xen.c
|
||
|
@@ -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)
|
||
|
diff --git a/grub-core/loader/i386/xen_fileXX.c b/grub-core/loader/i386/xen_fileXX.c
|
||
|
index 8751174..fb66e66 100644
|
||
|
--- a/grub-core/loader/i386/xen_fileXX.c
|
||
|
+++ b/grub-core/loader/i386/xen_fileXX.c
|
||
|
@@ -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;
|
||
|
diff --git a/include/grub/xen_file.h b/include/grub/xen_file.h
|
||
|
index ed749fa..6587999 100644
|
||
|
--- a/include/grub/xen_file.h
|
||
|
+++ b/include/grub/xen_file.h
|
||
|
@@ -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
|
||
|
--
|
||
|
2.6.6
|
||
|
|