aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/xen
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/xen')
-rw-r--r--arch/x86/xen/enlighten.c74
-rw-r--r--arch/x86/xen/mmu.c7
-rw-r--r--arch/x86/xen/mmu.h7
-rw-r--r--arch/x86/xen/xen-asm.S9
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 */
98static int have_vcpu_info_placement = 0; 98static int have_vcpu_info_placement = 1;
99 99
100static void __init xen_vcpu_setup(int cpu) 100static 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
669static void pin_pagetable_pfn(unsigned level, unsigned long pfn) 670static 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
697static void xen_alloc_pt(struct mm_struct *mm, u32 pfn) 699static 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
702static void xen_alloc_pd(struct mm_struct *mm, u32 pfn) 704static 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 */
708static void xen_release_pt(u32 pfn) 710static 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
724static void xen_release_pt(u32 pfn)
725{
726 xen_release_ptpage(pfn, PT_PTE);
727}
728
729static void xen_release_pd(u32 pfn)
730{
731 xen_release_ptpage(pfn, PT_PMD);
732}
733
720#ifdef CONFIG_HIGHPTE 734#ifdef CONFIG_HIGHPTE
721static void *xen_kmap_atomic_pte(struct page *page, enum km_type type) 735static 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
808static __init void xen_pagetable_setup_done(pgd_t *base) 822static __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
847static __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
313enum 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
6enum 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 */
35ENTRY(xen_irq_enable_direct) 35ENTRY(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
422: call check_events 472: call check_events
431: 481:
44ENDPATCH(xen_irq_enable_direct) 49ENDPATCH(xen_irq_enable_direct)