]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
xen: adjust early dom0 p2m handling to xen hypervisor behavior
authorJuergen Gross <jgross@suse.com>
Wed, 10 May 2017 04:08:44 +0000 (06:08 +0200)
committerStefan Bader <stefan.bader@canonical.com>
Tue, 20 Jun 2017 08:50:08 +0000 (10:50 +0200)
BugLink: http://bugs.launchpad.net/bugs/1692898
commit 69861e0a52f8733355ce246f0db15e1b240ad667 upstream.

When booted as pv-guest the p2m list presented by the Xen is already
mapped to virtual addresses. In dom0 case the hypervisor might make use
of 2M- or 1G-pages for this mapping. Unfortunately while being properly
aligned in virtual and machine address space, those pages might not be
aligned properly in guest physical address space.

So when trying to obtain the guest physical address of such a page
pud_pfn() and pmd_pfn() must be avoided as those will mask away guest
physical address bits not being zero in this special case.

Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Signed-off-by: Juergen Gross <jgross@suse.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
arch/x86/xen/mmu.c

index 7d5afdb417cc5e47a590f8f650e3fdcb96d544ac..418f1b8576cf3d7554f5ac2b2096d989a581f96d 100644 (file)
@@ -2028,7 +2028,8 @@ static unsigned long __init xen_read_phys_ulong(phys_addr_t addr)
 
 /*
  * Translate a virtual address to a physical one without relying on mapped
- * page tables.
+ * page tables. Don't rely on big pages being aligned in (guest) physical
+ * space!
  */
 static phys_addr_t __init xen_early_virt_to_phys(unsigned long vaddr)
 {
@@ -2049,7 +2050,7 @@ static phys_addr_t __init xen_early_virt_to_phys(unsigned long vaddr)
                                                       sizeof(pud)));
        if (!pud_present(pud))
                return 0;
-       pa = pud_pfn(pud) << PAGE_SHIFT;
+       pa = pud_val(pud) & PTE_PFN_MASK;
        if (pud_large(pud))
                return pa + (vaddr & ~PUD_MASK);
 
@@ -2057,7 +2058,7 @@ static phys_addr_t __init xen_early_virt_to_phys(unsigned long vaddr)
                                                       sizeof(pmd)));
        if (!pmd_present(pmd))
                return 0;
-       pa = pmd_pfn(pmd) << PAGE_SHIFT;
+       pa = pmd_val(pmd) & PTE_PFN_MASK;
        if (pmd_large(pmd))
                return pa + (vaddr & ~PMD_MASK);