diff options
Diffstat (limited to 'arch/x86/xen/mmu.c')
-rw-r--r-- | arch/x86/xen/mmu.c | 64 |
1 files changed, 42 insertions, 22 deletions
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index a991b57f91fe..02d752460371 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c | |||
@@ -1054,7 +1054,7 @@ void xen_mm_pin_all(void) | |||
1054 | * that's before we have page structures to store the bits. So do all | 1054 | * that's before we have page structures to store the bits. So do all |
1055 | * the book-keeping now. | 1055 | * the book-keeping now. |
1056 | */ | 1056 | */ |
1057 | static __init int xen_mark_pinned(struct mm_struct *mm, struct page *page, | 1057 | static int __init xen_mark_pinned(struct mm_struct *mm, struct page *page, |
1058 | enum pt_level level) | 1058 | enum pt_level level) |
1059 | { | 1059 | { |
1060 | SetPagePinned(page); | 1060 | SetPagePinned(page); |
@@ -1187,7 +1187,7 @@ static void drop_other_mm_ref(void *info) | |||
1187 | 1187 | ||
1188 | active_mm = percpu_read(cpu_tlbstate.active_mm); | 1188 | active_mm = percpu_read(cpu_tlbstate.active_mm); |
1189 | 1189 | ||
1190 | if (active_mm == mm) | 1190 | if (active_mm == mm && percpu_read(cpu_tlbstate.state) != TLBSTATE_OK) |
1191 | leave_mm(smp_processor_id()); | 1191 | leave_mm(smp_processor_id()); |
1192 | 1192 | ||
1193 | /* If this cpu still has a stale cr3 reference, then make sure | 1193 | /* If this cpu still has a stale cr3 reference, then make sure |
@@ -1271,13 +1271,27 @@ void xen_exit_mmap(struct mm_struct *mm) | |||
1271 | spin_unlock(&mm->page_table_lock); | 1271 | spin_unlock(&mm->page_table_lock); |
1272 | } | 1272 | } |
1273 | 1273 | ||
1274 | static __init void xen_pagetable_setup_start(pgd_t *base) | 1274 | static void __init xen_pagetable_setup_start(pgd_t *base) |
1275 | { | 1275 | { |
1276 | } | 1276 | } |
1277 | 1277 | ||
1278 | static __init void xen_mapping_pagetable_reserve(u64 start, u64 end) | ||
1279 | { | ||
1280 | /* reserve the range used */ | ||
1281 | native_pagetable_reserve(start, end); | ||
1282 | |||
1283 | /* set as RW the rest */ | ||
1284 | printk(KERN_DEBUG "xen: setting RW the range %llx - %llx\n", end, | ||
1285 | PFN_PHYS(pgt_buf_top)); | ||
1286 | while (end < PFN_PHYS(pgt_buf_top)) { | ||
1287 | make_lowmem_page_readwrite(__va(end)); | ||
1288 | end += PAGE_SIZE; | ||
1289 | } | ||
1290 | } | ||
1291 | |||
1278 | static void xen_post_allocator_init(void); | 1292 | static void xen_post_allocator_init(void); |
1279 | 1293 | ||
1280 | static __init void xen_pagetable_setup_done(pgd_t *base) | 1294 | static void __init xen_pagetable_setup_done(pgd_t *base) |
1281 | { | 1295 | { |
1282 | xen_setup_shared_info(); | 1296 | xen_setup_shared_info(); |
1283 | xen_post_allocator_init(); | 1297 | xen_post_allocator_init(); |
@@ -1473,16 +1487,20 @@ static void xen_pgd_free(struct mm_struct *mm, pgd_t *pgd) | |||
1473 | #endif | 1487 | #endif |
1474 | } | 1488 | } |
1475 | 1489 | ||
1476 | static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte) | ||
1477 | { | ||
1478 | unsigned long pfn = pte_pfn(pte); | ||
1479 | |||
1480 | #ifdef CONFIG_X86_32 | 1490 | #ifdef CONFIG_X86_32 |
1491 | static pte_t __init mask_rw_pte(pte_t *ptep, pte_t pte) | ||
1492 | { | ||
1481 | /* If there's an existing pte, then don't allow _PAGE_RW to be set */ | 1493 | /* If there's an existing pte, then don't allow _PAGE_RW to be set */ |
1482 | if (pte_val_ma(*ptep) & _PAGE_PRESENT) | 1494 | if (pte_val_ma(*ptep) & _PAGE_PRESENT) |
1483 | pte = __pte_ma(((pte_val_ma(*ptep) & _PAGE_RW) | ~_PAGE_RW) & | 1495 | pte = __pte_ma(((pte_val_ma(*ptep) & _PAGE_RW) | ~_PAGE_RW) & |
1484 | pte_val_ma(pte)); | 1496 | pte_val_ma(pte)); |
1485 | #endif | 1497 | |
1498 | return pte; | ||
1499 | } | ||
1500 | #else /* CONFIG_X86_64 */ | ||
1501 | static pte_t __init mask_rw_pte(pte_t *ptep, pte_t pte) | ||
1502 | { | ||
1503 | unsigned long pfn = pte_pfn(pte); | ||
1486 | 1504 | ||
1487 | /* | 1505 | /* |
1488 | * If the new pfn is within the range of the newly allocated | 1506 | * If the new pfn is within the range of the newly allocated |
@@ -1491,16 +1509,17 @@ static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte) | |||
1491 | * it is RO. | 1509 | * it is RO. |
1492 | */ | 1510 | */ |
1493 | if (((!is_early_ioremap_ptep(ptep) && | 1511 | if (((!is_early_ioremap_ptep(ptep) && |
1494 | pfn >= pgt_buf_start && pfn < pgt_buf_end)) || | 1512 | pfn >= pgt_buf_start && pfn < pgt_buf_top)) || |
1495 | (is_early_ioremap_ptep(ptep) && pfn != (pgt_buf_end - 1))) | 1513 | (is_early_ioremap_ptep(ptep) && pfn != (pgt_buf_end - 1))) |
1496 | pte = pte_wrprotect(pte); | 1514 | pte = pte_wrprotect(pte); |
1497 | 1515 | ||
1498 | return pte; | 1516 | return pte; |
1499 | } | 1517 | } |
1518 | #endif /* CONFIG_X86_64 */ | ||
1500 | 1519 | ||
1501 | /* Init-time set_pte while constructing initial pagetables, which | 1520 | /* Init-time set_pte while constructing initial pagetables, which |
1502 | doesn't allow RO pagetable pages to be remapped RW */ | 1521 | doesn't allow RO pagetable pages to be remapped RW */ |
1503 | static __init void xen_set_pte_init(pte_t *ptep, pte_t pte) | 1522 | static void __init xen_set_pte_init(pte_t *ptep, pte_t pte) |
1504 | { | 1523 | { |
1505 | pte = mask_rw_pte(ptep, pte); | 1524 | pte = mask_rw_pte(ptep, pte); |
1506 | 1525 | ||
@@ -1518,7 +1537,7 @@ static void pin_pagetable_pfn(unsigned cmd, unsigned long pfn) | |||
1518 | 1537 | ||
1519 | /* Early in boot, while setting up the initial pagetable, assume | 1538 | /* Early in boot, while setting up the initial pagetable, assume |
1520 | everything is pinned. */ | 1539 | everything is pinned. */ |
1521 | static __init void xen_alloc_pte_init(struct mm_struct *mm, unsigned long pfn) | 1540 | static void __init xen_alloc_pte_init(struct mm_struct *mm, unsigned long pfn) |
1522 | { | 1541 | { |
1523 | #ifdef CONFIG_FLATMEM | 1542 | #ifdef CONFIG_FLATMEM |
1524 | BUG_ON(mem_map); /* should only be used early */ | 1543 | BUG_ON(mem_map); /* should only be used early */ |
@@ -1528,7 +1547,7 @@ static __init void xen_alloc_pte_init(struct mm_struct *mm, unsigned long pfn) | |||
1528 | } | 1547 | } |
1529 | 1548 | ||
1530 | /* Used for pmd and pud */ | 1549 | /* Used for pmd and pud */ |
1531 | static __init void xen_alloc_pmd_init(struct mm_struct *mm, unsigned long pfn) | 1550 | static void __init xen_alloc_pmd_init(struct mm_struct *mm, unsigned long pfn) |
1532 | { | 1551 | { |
1533 | #ifdef CONFIG_FLATMEM | 1552 | #ifdef CONFIG_FLATMEM |
1534 | BUG_ON(mem_map); /* should only be used early */ | 1553 | BUG_ON(mem_map); /* should only be used early */ |
@@ -1538,13 +1557,13 @@ static __init void xen_alloc_pmd_init(struct mm_struct *mm, unsigned long pfn) | |||
1538 | 1557 | ||
1539 | /* Early release_pte assumes that all pts are pinned, since there's | 1558 | /* Early release_pte assumes that all pts are pinned, since there's |
1540 | only init_mm and anything attached to that is pinned. */ | 1559 | only init_mm and anything attached to that is pinned. */ |
1541 | static __init void xen_release_pte_init(unsigned long pfn) | 1560 | static void __init xen_release_pte_init(unsigned long pfn) |
1542 | { | 1561 | { |
1543 | pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, pfn); | 1562 | pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, pfn); |
1544 | make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); | 1563 | make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); |
1545 | } | 1564 | } |
1546 | 1565 | ||
1547 | static __init void xen_release_pmd_init(unsigned long pfn) | 1566 | static void __init xen_release_pmd_init(unsigned long pfn) |
1548 | { | 1567 | { |
1549 | make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); | 1568 | make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); |
1550 | } | 1569 | } |
@@ -1670,7 +1689,7 @@ static void set_page_prot(void *addr, pgprot_t prot) | |||
1670 | BUG(); | 1689 | BUG(); |
1671 | } | 1690 | } |
1672 | 1691 | ||
1673 | static __init void xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn) | 1692 | static void __init xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn) |
1674 | { | 1693 | { |
1675 | unsigned pmdidx, pteidx; | 1694 | unsigned pmdidx, pteidx; |
1676 | unsigned ident_pte; | 1695 | unsigned ident_pte; |
@@ -1753,7 +1772,7 @@ static void convert_pfn_mfn(void *v) | |||
1753 | * of the physical mapping once some sort of allocator has been set | 1772 | * of the physical mapping once some sort of allocator has been set |
1754 | * up. | 1773 | * up. |
1755 | */ | 1774 | */ |
1756 | __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, | 1775 | pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd, |
1757 | unsigned long max_pfn) | 1776 | unsigned long max_pfn) |
1758 | { | 1777 | { |
1759 | pud_t *l3; | 1778 | pud_t *l3; |
@@ -1824,7 +1843,7 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, | |||
1824 | static RESERVE_BRK_ARRAY(pmd_t, initial_kernel_pmd, PTRS_PER_PMD); | 1843 | static RESERVE_BRK_ARRAY(pmd_t, initial_kernel_pmd, PTRS_PER_PMD); |
1825 | static RESERVE_BRK_ARRAY(pmd_t, swapper_kernel_pmd, PTRS_PER_PMD); | 1844 | static RESERVE_BRK_ARRAY(pmd_t, swapper_kernel_pmd, PTRS_PER_PMD); |
1826 | 1845 | ||
1827 | static __init void xen_write_cr3_init(unsigned long cr3) | 1846 | static void __init xen_write_cr3_init(unsigned long cr3) |
1828 | { | 1847 | { |
1829 | unsigned long pfn = PFN_DOWN(__pa(swapper_pg_dir)); | 1848 | unsigned long pfn = PFN_DOWN(__pa(swapper_pg_dir)); |
1830 | 1849 | ||
@@ -1861,7 +1880,7 @@ static __init void xen_write_cr3_init(unsigned long cr3) | |||
1861 | pv_mmu_ops.write_cr3 = &xen_write_cr3; | 1880 | pv_mmu_ops.write_cr3 = &xen_write_cr3; |
1862 | } | 1881 | } |
1863 | 1882 | ||
1864 | __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, | 1883 | pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd, |
1865 | unsigned long max_pfn) | 1884 | unsigned long max_pfn) |
1866 | { | 1885 | { |
1867 | pmd_t *kernel_pmd; | 1886 | pmd_t *kernel_pmd; |
@@ -1967,7 +1986,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot) | |||
1967 | #endif | 1986 | #endif |
1968 | } | 1987 | } |
1969 | 1988 | ||
1970 | __init void xen_ident_map_ISA(void) | 1989 | void __init xen_ident_map_ISA(void) |
1971 | { | 1990 | { |
1972 | unsigned long pa; | 1991 | unsigned long pa; |
1973 | 1992 | ||
@@ -1990,7 +2009,7 @@ __init void xen_ident_map_ISA(void) | |||
1990 | xen_flush_tlb(); | 2009 | xen_flush_tlb(); |
1991 | } | 2010 | } |
1992 | 2011 | ||
1993 | static __init void xen_post_allocator_init(void) | 2012 | static void __init xen_post_allocator_init(void) |
1994 | { | 2013 | { |
1995 | #ifdef CONFIG_XEN_DEBUG | 2014 | #ifdef CONFIG_XEN_DEBUG |
1996 | pv_mmu_ops.make_pte = PV_CALLEE_SAVE(xen_make_pte_debug); | 2015 | pv_mmu_ops.make_pte = PV_CALLEE_SAVE(xen_make_pte_debug); |
@@ -2027,7 +2046,7 @@ static void xen_leave_lazy_mmu(void) | |||
2027 | preempt_enable(); | 2046 | preempt_enable(); |
2028 | } | 2047 | } |
2029 | 2048 | ||
2030 | static const struct pv_mmu_ops xen_mmu_ops __initdata = { | 2049 | static const struct pv_mmu_ops xen_mmu_ops __initconst = { |
2031 | .read_cr2 = xen_read_cr2, | 2050 | .read_cr2 = xen_read_cr2, |
2032 | .write_cr2 = xen_write_cr2, | 2051 | .write_cr2 = xen_write_cr2, |
2033 | 2052 | ||
@@ -2100,6 +2119,7 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = { | |||
2100 | 2119 | ||
2101 | void __init xen_init_mmu_ops(void) | 2120 | void __init xen_init_mmu_ops(void) |
2102 | { | 2121 | { |
2122 | x86_init.mapping.pagetable_reserve = xen_mapping_pagetable_reserve; | ||
2103 | x86_init.paging.pagetable_setup_start = xen_pagetable_setup_start; | 2123 | x86_init.paging.pagetable_setup_start = xen_pagetable_setup_start; |
2104 | x86_init.paging.pagetable_setup_done = xen_pagetable_setup_done; | 2124 | x86_init.paging.pagetable_setup_done = xen_pagetable_setup_done; |
2105 | pv_mmu_ops = xen_mmu_ops; | 2125 | pv_mmu_ops = xen_mmu_ops; |