diff options
Diffstat (limited to 'arch/i386/xen')
-rw-r--r-- | arch/i386/xen/enlighten.c | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/arch/i386/xen/enlighten.c b/arch/i386/xen/enlighten.c index 86e68e680116..9550ae3b1fb1 100644 --- a/arch/i386/xen/enlighten.c +++ b/arch/i386/xen/enlighten.c | |||
@@ -505,7 +505,7 @@ static void xen_write_cr3(unsigned long cr3) | |||
505 | 505 | ||
506 | /* Early in boot, while setting up the initial pagetable, assume | 506 | /* Early in boot, while setting up the initial pagetable, assume |
507 | everything is pinned. */ | 507 | everything is pinned. */ |
508 | static void xen_alloc_pt_init(struct mm_struct *mm, u32 pfn) | 508 | static __init void xen_alloc_pt_init(struct mm_struct *mm, u32 pfn) |
509 | { | 509 | { |
510 | BUG_ON(mem_map); /* should only be used early */ | 510 | BUG_ON(mem_map); /* should only be used early */ |
511 | make_lowmem_page_readonly(__va(PFN_PHYS(pfn))); | 511 | make_lowmem_page_readonly(__va(PFN_PHYS(pfn))); |
@@ -557,10 +557,32 @@ static void *xen_kmap_atomic_pte(struct page *page, enum km_type type) | |||
557 | } | 557 | } |
558 | #endif | 558 | #endif |
559 | 559 | ||
560 | static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte) | ||
561 | { | ||
562 | /* If there's an existing pte, then don't allow _PAGE_RW to be set */ | ||
563 | if (pte_val_ma(*ptep) & _PAGE_PRESENT) | ||
564 | pte = __pte_ma(((pte_val_ma(*ptep) & _PAGE_RW) | ~_PAGE_RW) & | ||
565 | pte_val_ma(pte)); | ||
566 | |||
567 | return pte; | ||
568 | } | ||
569 | |||
570 | /* Init-time set_pte while constructing initial pagetables, which | ||
571 | doesn't allow RO pagetable pages to be remapped RW */ | ||
572 | static __init void xen_set_pte_init(pte_t *ptep, pte_t pte) | ||
573 | { | ||
574 | pte = mask_rw_pte(ptep, pte); | ||
575 | |||
576 | xen_set_pte(ptep, pte); | ||
577 | } | ||
578 | |||
560 | static __init void xen_pagetable_setup_start(pgd_t *base) | 579 | static __init void xen_pagetable_setup_start(pgd_t *base) |
561 | { | 580 | { |
562 | pgd_t *xen_pgd = (pgd_t *)xen_start_info->pt_base; | 581 | pgd_t *xen_pgd = (pgd_t *)xen_start_info->pt_base; |
563 | 582 | ||
583 | /* special set_pte for pagetable initialization */ | ||
584 | paravirt_ops.set_pte = xen_set_pte_init; | ||
585 | |||
564 | init_mm.pgd = base; | 586 | init_mm.pgd = base; |
565 | /* | 587 | /* |
566 | * copy top-level of Xen-supplied pagetable into place. For | 588 | * copy top-level of Xen-supplied pagetable into place. For |
@@ -607,6 +629,7 @@ static __init void xen_pagetable_setup_done(pgd_t *base) | |||
607 | /* This will work as long as patching hasn't happened yet | 629 | /* This will work as long as patching hasn't happened yet |
608 | (which it hasn't) */ | 630 | (which it hasn't) */ |
609 | paravirt_ops.alloc_pt = xen_alloc_pt; | 631 | paravirt_ops.alloc_pt = xen_alloc_pt; |
632 | paravirt_ops.set_pte = xen_set_pte; | ||
610 | 633 | ||
611 | if (!xen_feature(XENFEAT_auto_translated_physmap)) { | 634 | if (!xen_feature(XENFEAT_auto_translated_physmap)) { |
612 | /* | 635 | /* |
@@ -745,7 +768,7 @@ static const struct paravirt_ops xen_paravirt_ops __initdata = { | |||
745 | .kmap_atomic_pte = xen_kmap_atomic_pte, | 768 | .kmap_atomic_pte = xen_kmap_atomic_pte, |
746 | #endif | 769 | #endif |
747 | 770 | ||
748 | .set_pte = xen_set_pte, | 771 | .set_pte = NULL, /* see xen_pagetable_setup_* */ |
749 | .set_pte_at = xen_set_pte_at, | 772 | .set_pte_at = xen_set_pte_at, |
750 | .set_pmd = xen_set_pmd, | 773 | .set_pmd = xen_set_pmd, |
751 | 774 | ||