| From 69861e0a52f8733355ce246f0db15e1b240ad667 Mon Sep 17 00:00:00 2001 |
| From: Juergen Gross <jgross@suse.com> |
| Date: Wed, 10 May 2017 06:08:44 +0200 |
| Subject: [PATCH] xen: adjust early dom0 p2m handling to xen hypervisor |
| behavior |
| |
| 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> |
| |
| diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c |
| index 9d9ae6650aa1..7397d8b8459d 100644 |
| --- a/arch/x86/xen/mmu_pv.c |
| +++ b/arch/x86/xen/mmu_pv.c |
| @@ -2025,7 +2025,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) |
| { |
| @@ -2046,7 +2047,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); |
| |
| @@ -2054,7 +2055,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); |
| |
| -- |
| 2.12.0 |
| |