unsigned long max_pfn)
{
pmd_t *kernel_pmd;
+ int i;
max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->pt_base) +
xen_start_info->nr_pt_frames * PAGE_SIZE +
xen_map_identity_early(level2_kernel_pgt, max_pfn);
memcpy(swapper_pg_dir, pgd, sizeof(pgd_t) * PTRS_PER_PGD);
+
+ /*
+ * When running a 32 bit domain 0 on a 64 bit hypervisor a
+ * pinned L3 (such as the initial pgd here) contains bits
+ * which are reserved in the PAE layout but not in the 64 bit
+ * layout. Unfortunately some versions of the hypervisor
+ * (incorrectly) validate compat mode guests against the PAE
+ * layout and hence will not allow such a pagetable to be
+ * pinned by the guest. Therefore we mask off only the PFN and
+ * Present bits of the supplied L3.
+ */
+ for (i = 0; i < PTRS_PER_PGD; i++)
+ swapper_pg_dir[i].pgd &= (PTE_PFN_MASK | _PAGE_PRESENT);
+
set_pgd(&swapper_pg_dir[KERNEL_PGD_BOUNDARY],
__pgd(__pa(level2_kernel_pgt) | _PAGE_PRESENT));