Commit 70e61199 authored by Juergen Gross's avatar Juergen Gross Committed by David Vrabel

xen: move p2m list if conflicting with e820 map

Check whether the hypervisor supplied p2m list is placed at a location
which is conflicting with the target E820 map. If this is the case
relocate it to a new area unused up to now and compliant to the E820
map.

As the p2m list might by huge (up to several GB) and is required to be
mapped virtually, set up a temporary mapping for the copied list.

For pvh domains just delete the p2m related information from start
info instead of reserving the p2m memory, as we don't need it at all.

For 32 bit kernels adjust the memblock_reserve() parameters in order
to cover the page tables only. This requires to memblock_reserve() the
start_info page on it's own.
Signed-off-by: default avatarJuergen Gross <jgross@suse.com>
Acked-by: default avatarKonrad Rzeszutek Wilk <Konrad.wilk@oracle.com>
Signed-off-by: default avatarDavid Vrabel <david.vrabel@citrix.com>
parent 6c2681c8
This diff is collapsed.
...@@ -663,37 +663,35 @@ static void __init xen_phys_memcpy(phys_addr_t dest, phys_addr_t src, ...@@ -663,37 +663,35 @@ static void __init xen_phys_memcpy(phys_addr_t dest, phys_addr_t src,
/* /*
* Reserve Xen mfn_list. * Reserve Xen mfn_list.
* See comment above "struct start_info" in <xen/interface/xen.h>
* We tried to make the the memblock_reserve more selective so
* that it would be clear what region is reserved. Sadly we ran
* in the problem wherein on a 64-bit hypervisor with a 32-bit
* initial domain, the pt_base has the cr3 value which is not
* neccessarily where the pagetable starts! As Jan put it: "
* Actually, the adjustment turns out to be correct: The page
* tables for a 32-on-64 dom0 get allocated in the order "first L1",
* "first L2", "first L3", so the offset to the page table base is
* indeed 2. When reading xen/include/public/xen.h's comment
* very strictly, this is not a violation (since there nothing is said
* that the first thing in the page table space is pointed to by
* pt_base; I admit that this seems to be implied though, namely
* do I think that it is implied that the page table space is the
* range [pt_base, pt_base + nt_pt_frames), whereas that
* range here indeed is [pt_base - 2, pt_base - 2 + nt_pt_frames),
* which - without a priori knowledge - the kernel would have
* difficulty to figure out)." - so lets just fall back to the
* easy way and reserve the whole region.
*/ */
static void __init xen_reserve_xen_mfnlist(void) static void __init xen_reserve_xen_mfnlist(void)
{ {
phys_addr_t start, size;
if (xen_start_info->mfn_list >= __START_KERNEL_map) { if (xen_start_info->mfn_list >= __START_KERNEL_map) {
memblock_reserve(__pa(xen_start_info->mfn_list), start = __pa(xen_start_info->mfn_list);
xen_start_info->pt_base - size = PFN_ALIGN(xen_start_info->nr_pages *
xen_start_info->mfn_list); sizeof(unsigned long));
} else {
start = PFN_PHYS(xen_start_info->first_p2m_pfn);
size = PFN_PHYS(xen_start_info->nr_p2m_frames);
}
if (!xen_is_e820_reserved(start, size)) {
memblock_reserve(start, size);
return; return;
} }
memblock_reserve(PFN_PHYS(xen_start_info->first_p2m_pfn), #ifdef CONFIG_X86_32
PFN_PHYS(xen_start_info->nr_p2m_frames)); /*
* Relocating the p2m on 32 bit system to an arbitrary virtual address
* is not supported, so just give up.
*/
xen_raw_console_write("Xen hypervisor allocated p2m list conflicts with E820 map\n");
BUG();
#else
xen_relocate_p2m();
#endif
} }
/** /**
...@@ -895,7 +893,10 @@ char * __init xen_auto_xlated_memory_setup(void) ...@@ -895,7 +893,10 @@ char * __init xen_auto_xlated_memory_setup(void)
e820_add_region(xen_e820_map[i].addr, xen_e820_map[i].size, e820_add_region(xen_e820_map[i].addr, xen_e820_map[i].size,
xen_e820_map[i].type); xen_e820_map[i].type);
xen_reserve_xen_mfnlist(); /* Remove p2m info, it is not needed. */
xen_start_info->mfn_list = 0;
xen_start_info->first_p2m_pfn = 0;
xen_start_info->nr_p2m_frames = 0;
return "Xen"; return "Xen";
} }
......
...@@ -40,6 +40,9 @@ void __init xen_pt_check_e820(void); ...@@ -40,6 +40,9 @@ void __init xen_pt_check_e820(void);
void xen_mm_pin_all(void); void xen_mm_pin_all(void);
void xen_mm_unpin_all(void); void xen_mm_unpin_all(void);
#ifdef CONFIG_X86_64
void __init xen_relocate_p2m(void);
#endif
bool __init xen_is_e820_reserved(phys_addr_t start, phys_addr_t size); bool __init xen_is_e820_reserved(phys_addr_t start, phys_addr_t size);
unsigned long __ref xen_chk_extra_mem(unsigned long pfn); unsigned long __ref xen_chk_extra_mem(unsigned long pfn);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment