xen: Cope with unmapped pages when initializing kernel pagetable

Xen requires that all pages containing pagetable entries to be mapped
read-only. If pages used for the initial pagetable are already mapped
then we can change the mapping to RO. However, if they are initially
unmapped, we need to make sure that when they are later mapped, they
are also mapped RO.

We do this by knowing that the kernel pagetable memory is pre-allocated
in the range e820_table_start - e820_table_end, so any pfn within this
range should be mapped read-only. However, the pagetable setup code
early_ioremaps the pages to write their entries, so we must make sure
that mappings created in the early_ioremap fixmap area are mapped RW.
(Those mappings are removed before the pages are presented to Xen
as pagetable pages.)

Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
LKML-Reference: <4CB63A80.8060702@goop.org>
Cc: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>

authored by Jeremy Fitzhardinge and committed by H. Peter Anvin fef5ba79 c7fc2de0

+24 -8
+1
arch/x86/include/asm/io.h
··· 348 unsigned long size); 349 extern void early_iounmap(void __iomem *addr, unsigned long size); 350 extern void fixup_early_ioremap(void); 351 352 #define IO_SPACE_LIMIT 0xffff 353
··· 348 unsigned long size); 349 extern void early_iounmap(void __iomem *addr, unsigned long size); 350 extern void fixup_early_ioremap(void); 351 + extern bool is_early_ioremap_ptep(pte_t *ptep); 352 353 #define IO_SPACE_LIMIT 0xffff 354
+5
arch/x86/mm/ioremap.c
··· 362 return &bm_pte[pte_index(addr)]; 363 } 364 365 static unsigned long slot_virt[FIX_BTMAPS_SLOTS] __initdata; 366 367 void __init early_ioremap_init(void)
··· 362 return &bm_pte[pte_index(addr)]; 363 } 364 365 + bool __init is_early_ioremap_ptep(pte_t *ptep) 366 + { 367 + return ptep >= &bm_pte[0] && ptep < &bm_pte[PAGE_SIZE/sizeof(pte_t)]; 368 + } 369 + 370 static unsigned long slot_virt[FIX_BTMAPS_SLOTS] __initdata; 371 372 void __init early_ioremap_init(void)
+18 -8
arch/x86/xen/mmu.c
··· 56 #include <asm/e820.h> 57 #include <asm/linkage.h> 58 #include <asm/page.h> 59 60 #include <asm/xen/hypercall.h> 61 #include <asm/xen/hypervisor.h> ··· 361 unsigned int level; 362 363 pte = lookup_address(address, &level); 364 - BUG_ON(pte == NULL); 365 366 ptev = pte_wrprotect(*pte); 367 ··· 377 unsigned int level; 378 379 pte = lookup_address(address, &level); 380 - BUG_ON(pte == NULL); 381 382 ptev = pte_mkwrite(*pte); 383 ··· 1512 #endif 1513 } 1514 1515 - #ifdef CONFIG_X86_32 1516 static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte) 1517 { 1518 /* If there's an existing pte, then don't allow _PAGE_RW to be set */ 1519 if (pte_val_ma(*ptep) & _PAGE_PRESENT) 1520 pte = __pte_ma(((pte_val_ma(*ptep) & _PAGE_RW) | ~_PAGE_RW) & 1521 pte_val_ma(pte)); 1522 1523 return pte; 1524 } ··· 1543 1544 xen_set_pte(ptep, pte); 1545 } 1546 - #endif 1547 1548 static void pin_pagetable_pfn(unsigned cmd, unsigned long pfn) 1549 { ··· 1987 .alloc_pmd_clone = paravirt_nop, 1988 .release_pmd = xen_release_pmd_init, 1989 1990 - #ifdef CONFIG_X86_64 1991 - .set_pte = xen_set_pte, 1992 - #else 1993 .set_pte = xen_set_pte_init, 1994 - #endif 1995 .set_pte_at = xen_set_pte_at, 1996 .set_pmd = xen_set_pmd_hyper, 1997
··· 56 #include <asm/e820.h> 57 #include <asm/linkage.h> 58 #include <asm/page.h> 59 + #include <asm/init.h> 60 61 #include <asm/xen/hypercall.h> 62 #include <asm/xen/hypervisor.h> ··· 360 unsigned int level; 361 362 pte = lookup_address(address, &level); 363 + if (pte == NULL) 364 + return; /* vaddr missing */ 365 366 ptev = pte_wrprotect(*pte); 367 ··· 375 unsigned int level; 376 377 pte = lookup_address(address, &level); 378 + if (pte == NULL) 379 + return; /* vaddr missing */ 380 381 ptev = pte_mkwrite(*pte); 382 ··· 1509 #endif 1510 } 1511 1512 static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte) 1513 { 1514 + unsigned long pfn = pte_pfn(pte); 1515 + 1516 + #ifdef CONFIG_X86_32 1517 /* If there's an existing pte, then don't allow _PAGE_RW to be set */ 1518 if (pte_val_ma(*ptep) & _PAGE_PRESENT) 1519 pte = __pte_ma(((pte_val_ma(*ptep) & _PAGE_RW) | ~_PAGE_RW) & 1520 pte_val_ma(pte)); 1521 + #endif 1522 + 1523 + /* 1524 + * If the new pfn is within the range of the newly allocated 1525 + * kernel pagetable, and it isn't being mapped into an 1526 + * early_ioremap fixmap slot, make sure it is RO. 1527 + */ 1528 + if (!is_early_ioremap_ptep(ptep) && 1529 + pfn >= e820_table_start && pfn < e820_table_end) 1530 + pte = pte_wrprotect(pte); 1531 1532 return pte; 1533 } ··· 1528 1529 xen_set_pte(ptep, pte); 1530 } 1531 1532 static void pin_pagetable_pfn(unsigned cmd, unsigned long pfn) 1533 { ··· 1973 .alloc_pmd_clone = paravirt_nop, 1974 .release_pmd = xen_release_pmd_init, 1975 1976 .set_pte = xen_set_pte_init, 1977 .set_pte_at = xen_set_pte_at, 1978 .set_pmd = xen_set_pmd_hyper, 1979