diff options
Diffstat (limited to 'arch/x86/xen')
-rw-r--r-- | arch/x86/xen/enlighten.c | 74 | ||||
-rw-r--r-- | arch/x86/xen/mmu.c | 7 | ||||
-rw-r--r-- | arch/x86/xen/mmu.h | 7 | ||||
-rw-r--r-- | arch/x86/xen/xen-asm.S | 9 |
4 files changed, 60 insertions, 37 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 8b9ee27805fd..27ee26aedf94 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -95,7 +95,7 @@ struct shared_info *HYPERVISOR_shared_info = (void *)&dummy_shared_info; | |||
95 | * | 95 | * |
96 | * 0: not available, 1: available | 96 | * 0: not available, 1: available |
97 | */ | 97 | */ |
98 | static int have_vcpu_info_placement = 0; | 98 | static int have_vcpu_info_placement = 1; |
99 | 99 | ||
100 | static void __init xen_vcpu_setup(int cpu) | 100 | static void __init xen_vcpu_setup(int cpu) |
101 | { | 101 | { |
@@ -103,6 +103,7 @@ static void __init xen_vcpu_setup(int cpu) | |||
103 | int err; | 103 | int err; |
104 | struct vcpu_info *vcpup; | 104 | struct vcpu_info *vcpup; |
105 | 105 | ||
106 | BUG_ON(HYPERVISOR_shared_info == &dummy_shared_info); | ||
106 | per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu]; | 107 | per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu]; |
107 | 108 | ||
108 | if (!have_vcpu_info_placement) | 109 | if (!have_vcpu_info_placement) |
@@ -666,10 +667,10 @@ static void xen_release_pt_init(u32 pfn) | |||
666 | make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); | 667 | make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); |
667 | } | 668 | } |
668 | 669 | ||
669 | static void pin_pagetable_pfn(unsigned level, unsigned long pfn) | 670 | static void pin_pagetable_pfn(unsigned cmd, unsigned long pfn) |
670 | { | 671 | { |
671 | struct mmuext_op op; | 672 | struct mmuext_op op; |
672 | op.cmd = level; | 673 | op.cmd = cmd; |
673 | op.arg1.mfn = pfn_to_mfn(pfn); | 674 | op.arg1.mfn = pfn_to_mfn(pfn); |
674 | if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF)) | 675 | if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF)) |
675 | BUG(); | 676 | BUG(); |
@@ -686,7 +687,8 @@ static void xen_alloc_ptpage(struct mm_struct *mm, u32 pfn, unsigned level) | |||
686 | 687 | ||
687 | if (!PageHighMem(page)) { | 688 | if (!PageHighMem(page)) { |
688 | make_lowmem_page_readonly(__va(PFN_PHYS(pfn))); | 689 | make_lowmem_page_readonly(__va(PFN_PHYS(pfn))); |
689 | pin_pagetable_pfn(level, pfn); | 690 | if (level == PT_PTE) |
691 | pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn); | ||
690 | } else | 692 | } else |
691 | /* make sure there are no stray mappings of | 693 | /* make sure there are no stray mappings of |
692 | this page */ | 694 | this page */ |
@@ -696,27 +698,39 @@ static void xen_alloc_ptpage(struct mm_struct *mm, u32 pfn, unsigned level) | |||
696 | 698 | ||
697 | static void xen_alloc_pt(struct mm_struct *mm, u32 pfn) | 699 | static void xen_alloc_pt(struct mm_struct *mm, u32 pfn) |
698 | { | 700 | { |
699 | xen_alloc_ptpage(mm, pfn, MMUEXT_PIN_L1_TABLE); | 701 | xen_alloc_ptpage(mm, pfn, PT_PTE); |
700 | } | 702 | } |
701 | 703 | ||
702 | static void xen_alloc_pd(struct mm_struct *mm, u32 pfn) | 704 | static void xen_alloc_pd(struct mm_struct *mm, u32 pfn) |
703 | { | 705 | { |
704 | xen_alloc_ptpage(mm, pfn, MMUEXT_PIN_L2_TABLE); | 706 | xen_alloc_ptpage(mm, pfn, PT_PMD); |
705 | } | 707 | } |
706 | 708 | ||
707 | /* This should never happen until we're OK to use struct page */ | 709 | /* This should never happen until we're OK to use struct page */ |
708 | static void xen_release_pt(u32 pfn) | 710 | static void xen_release_ptpage(u32 pfn, unsigned level) |
709 | { | 711 | { |
710 | struct page *page = pfn_to_page(pfn); | 712 | struct page *page = pfn_to_page(pfn); |
711 | 713 | ||
712 | if (PagePinned(page)) { | 714 | if (PagePinned(page)) { |
713 | if (!PageHighMem(page)) { | 715 | if (!PageHighMem(page)) { |
714 | pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, pfn); | 716 | if (level == PT_PTE) |
717 | pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, pfn); | ||
715 | make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); | 718 | make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); |
716 | } | 719 | } |
720 | ClearPagePinned(page); | ||
717 | } | 721 | } |
718 | } | 722 | } |
719 | 723 | ||
724 | static void xen_release_pt(u32 pfn) | ||
725 | { | ||
726 | xen_release_ptpage(pfn, PT_PTE); | ||
727 | } | ||
728 | |||
729 | static void xen_release_pd(u32 pfn) | ||
730 | { | ||
731 | xen_release_ptpage(pfn, PT_PMD); | ||
732 | } | ||
733 | |||
720 | #ifdef CONFIG_HIGHPTE | 734 | #ifdef CONFIG_HIGHPTE |
721 | static void *xen_kmap_atomic_pte(struct page *page, enum km_type type) | 735 | static void *xen_kmap_atomic_pte(struct page *page, enum km_type type) |
722 | { | 736 | { |
@@ -805,33 +819,43 @@ static __init void xen_pagetable_setup_start(pgd_t *base) | |||
805 | PFN_DOWN(__pa(xen_start_info->pt_base))); | 819 | PFN_DOWN(__pa(xen_start_info->pt_base))); |
806 | } | 820 | } |
807 | 821 | ||
808 | static __init void xen_pagetable_setup_done(pgd_t *base) | 822 | static __init void setup_shared_info(void) |
809 | { | 823 | { |
810 | /* This will work as long as patching hasn't happened yet | ||
811 | (which it hasn't) */ | ||
812 | pv_mmu_ops.alloc_pt = xen_alloc_pt; | ||
813 | pv_mmu_ops.alloc_pd = xen_alloc_pd; | ||
814 | pv_mmu_ops.release_pt = xen_release_pt; | ||
815 | pv_mmu_ops.release_pd = xen_release_pt; | ||
816 | pv_mmu_ops.set_pte = xen_set_pte; | ||
817 | |||
818 | if (!xen_feature(XENFEAT_auto_translated_physmap)) { | 824 | if (!xen_feature(XENFEAT_auto_translated_physmap)) { |
825 | unsigned long addr = fix_to_virt(FIX_PARAVIRT_BOOTMAP); | ||
826 | |||
819 | /* | 827 | /* |
820 | * Create a mapping for the shared info page. | 828 | * Create a mapping for the shared info page. |
821 | * Should be set_fixmap(), but shared_info is a machine | 829 | * Should be set_fixmap(), but shared_info is a machine |
822 | * address with no corresponding pseudo-phys address. | 830 | * address with no corresponding pseudo-phys address. |
823 | */ | 831 | */ |
824 | set_pte_mfn(fix_to_virt(FIX_PARAVIRT_BOOTMAP), | 832 | set_pte_mfn(addr, |
825 | PFN_DOWN(xen_start_info->shared_info), | 833 | PFN_DOWN(xen_start_info->shared_info), |
826 | PAGE_KERNEL); | 834 | PAGE_KERNEL); |
827 | 835 | ||
828 | HYPERVISOR_shared_info = | 836 | HYPERVISOR_shared_info = (struct shared_info *)addr; |
829 | (struct shared_info *)fix_to_virt(FIX_PARAVIRT_BOOTMAP); | ||
830 | |||
831 | } else | 837 | } else |
832 | HYPERVISOR_shared_info = | 838 | HYPERVISOR_shared_info = |
833 | (struct shared_info *)__va(xen_start_info->shared_info); | 839 | (struct shared_info *)__va(xen_start_info->shared_info); |
834 | 840 | ||
841 | #ifndef CONFIG_SMP | ||
842 | /* In UP this is as good a place as any to set up shared info */ | ||
843 | xen_setup_vcpu_info_placement(); | ||
844 | #endif | ||
845 | } | ||
846 | |||
847 | static __init void xen_pagetable_setup_done(pgd_t *base) | ||
848 | { | ||
849 | /* This will work as long as patching hasn't happened yet | ||
850 | (which it hasn't) */ | ||
851 | pv_mmu_ops.alloc_pt = xen_alloc_pt; | ||
852 | pv_mmu_ops.alloc_pd = xen_alloc_pd; | ||
853 | pv_mmu_ops.release_pt = xen_release_pt; | ||
854 | pv_mmu_ops.release_pd = xen_release_pd; | ||
855 | pv_mmu_ops.set_pte = xen_set_pte; | ||
856 | |||
857 | setup_shared_info(); | ||
858 | |||
835 | /* Actually pin the pagetable down, but we can't set PG_pinned | 859 | /* Actually pin the pagetable down, but we can't set PG_pinned |
836 | yet because the page structures don't exist yet. */ | 860 | yet because the page structures don't exist yet. */ |
837 | { | 861 | { |
@@ -1182,15 +1206,9 @@ asmlinkage void __init xen_start_kernel(void) | |||
1182 | x86_write_percpu(xen_cr3, __pa(pgd)); | 1206 | x86_write_percpu(xen_cr3, __pa(pgd)); |
1183 | x86_write_percpu(xen_current_cr3, __pa(pgd)); | 1207 | x86_write_percpu(xen_current_cr3, __pa(pgd)); |
1184 | 1208 | ||
1185 | #ifdef CONFIG_SMP | ||
1186 | /* Don't do the full vcpu_info placement stuff until we have a | 1209 | /* Don't do the full vcpu_info placement stuff until we have a |
1187 | possible map. */ | 1210 | possible map and a non-dummy shared_info. */ |
1188 | per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0]; | 1211 | per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0]; |
1189 | #else | ||
1190 | /* May as well do it now, since there's no good time to call | ||
1191 | it later on UP. */ | ||
1192 | xen_setup_vcpu_info_placement(); | ||
1193 | #endif | ||
1194 | 1212 | ||
1195 | pv_info.kernel_rpl = 1; | 1213 | pv_info.kernel_rpl = 1; |
1196 | if (xen_feature(XENFEAT_supervisor_mode_kernel)) | 1214 | if (xen_feature(XENFEAT_supervisor_mode_kernel)) |
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 0144395448ae..2a054ef2a3da 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c | |||
@@ -310,13 +310,6 @@ pgd_t xen_make_pgd(unsigned long pgd) | |||
310 | } | 310 | } |
311 | #endif /* CONFIG_X86_PAE */ | 311 | #endif /* CONFIG_X86_PAE */ |
312 | 312 | ||
313 | enum pt_level { | ||
314 | PT_PGD, | ||
315 | PT_PUD, | ||
316 | PT_PMD, | ||
317 | PT_PTE | ||
318 | }; | ||
319 | |||
320 | /* | 313 | /* |
321 | (Yet another) pagetable walker. This one is intended for pinning a | 314 | (Yet another) pagetable walker. This one is intended for pinning a |
322 | pagetable. This means that it walks a pagetable and calls the | 315 | pagetable. This means that it walks a pagetable and calls the |
diff --git a/arch/x86/xen/mmu.h b/arch/x86/xen/mmu.h index c9ff27f3ac3a..b5e189b1519d 100644 --- a/arch/x86/xen/mmu.h +++ b/arch/x86/xen/mmu.h | |||
@@ -3,6 +3,13 @@ | |||
3 | #include <linux/linkage.h> | 3 | #include <linux/linkage.h> |
4 | #include <asm/page.h> | 4 | #include <asm/page.h> |
5 | 5 | ||
6 | enum pt_level { | ||
7 | PT_PGD, | ||
8 | PT_PUD, | ||
9 | PT_PMD, | ||
10 | PT_PTE | ||
11 | }; | ||
12 | |||
6 | /* | 13 | /* |
7 | * Page-directory addresses above 4GB do not fit into architectural %cr3. | 14 | * Page-directory addresses above 4GB do not fit into architectural %cr3. |
8 | * When accessing %cr3, or equivalent field in vcpu_guest_context, guests | 15 | * When accessing %cr3, or equivalent field in vcpu_guest_context, guests |
diff --git a/arch/x86/xen/xen-asm.S b/arch/x86/xen/xen-asm.S index 1a43b60c0c62..6b7190449d07 100644 --- a/arch/x86/xen/xen-asm.S +++ b/arch/x86/xen/xen-asm.S | |||
@@ -33,12 +33,17 @@ | |||
33 | events, then enter the hypervisor to get them handled. | 33 | events, then enter the hypervisor to get them handled. |
34 | */ | 34 | */ |
35 | ENTRY(xen_irq_enable_direct) | 35 | ENTRY(xen_irq_enable_direct) |
36 | /* Clear mask and test pending */ | 36 | /* Unmask events */ |
37 | andw $0x00ff, PER_CPU_VAR(xen_vcpu_info)+XEN_vcpu_info_pending | 37 | movb $0, PER_CPU_VAR(xen_vcpu_info)+XEN_vcpu_info_mask |
38 | |||
38 | /* Preempt here doesn't matter because that will deal with | 39 | /* Preempt here doesn't matter because that will deal with |
39 | any pending interrupts. The pending check may end up being | 40 | any pending interrupts. The pending check may end up being |
40 | run on the wrong CPU, but that doesn't hurt. */ | 41 | run on the wrong CPU, but that doesn't hurt. */ |
42 | |||
43 | /* Test for pending */ | ||
44 | testb $0xff, PER_CPU_VAR(xen_vcpu_info)+XEN_vcpu_info_pending | ||
41 | jz 1f | 45 | jz 1f |
46 | |||
42 | 2: call check_events | 47 | 2: call check_events |
43 | 1: | 48 | 1: |
44 | ENDPATCH(xen_irq_enable_direct) | 49 | ENDPATCH(xen_irq_enable_direct) |