diff options
Diffstat (limited to 'arch/x86/xen/enlighten.c')
-rw-r--r-- | arch/x86/xen/enlighten.c | 232 |
1 files changed, 171 insertions, 61 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index c8a56e457d61..bb508456ef52 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <asm/pgtable.h> | 45 | #include <asm/pgtable.h> |
46 | #include <asm/tlbflush.h> | 46 | #include <asm/tlbflush.h> |
47 | #include <asm/reboot.h> | 47 | #include <asm/reboot.h> |
48 | #include <asm/pgalloc.h> | ||
48 | 49 | ||
49 | #include "xen-ops.h" | 50 | #include "xen-ops.h" |
50 | #include "mmu.h" | 51 | #include "mmu.h" |
@@ -75,13 +76,13 @@ DEFINE_PER_CPU(unsigned long, xen_current_cr3); /* actual vcpu cr3 */ | |||
75 | struct start_info *xen_start_info; | 76 | struct start_info *xen_start_info; |
76 | EXPORT_SYMBOL_GPL(xen_start_info); | 77 | EXPORT_SYMBOL_GPL(xen_start_info); |
77 | 78 | ||
78 | static /* __initdata */ struct shared_info dummy_shared_info; | 79 | struct shared_info xen_dummy_shared_info; |
79 | 80 | ||
80 | /* | 81 | /* |
81 | * Point at some empty memory to start with. We map the real shared_info | 82 | * Point at some empty memory to start with. We map the real shared_info |
82 | * page as soon as fixmap is up and running. | 83 | * page as soon as fixmap is up and running. |
83 | */ | 84 | */ |
84 | struct shared_info *HYPERVISOR_shared_info = (void *)&dummy_shared_info; | 85 | struct shared_info *HYPERVISOR_shared_info = (void *)&xen_dummy_shared_info; |
85 | 86 | ||
86 | /* | 87 | /* |
87 | * Flag to determine whether vcpu info placement is available on all | 88 | * Flag to determine whether vcpu info placement is available on all |
@@ -98,13 +99,13 @@ struct shared_info *HYPERVISOR_shared_info = (void *)&dummy_shared_info; | |||
98 | */ | 99 | */ |
99 | static int have_vcpu_info_placement = 1; | 100 | static int have_vcpu_info_placement = 1; |
100 | 101 | ||
101 | static void __init xen_vcpu_setup(int cpu) | 102 | static void xen_vcpu_setup(int cpu) |
102 | { | 103 | { |
103 | struct vcpu_register_vcpu_info info; | 104 | struct vcpu_register_vcpu_info info; |
104 | int err; | 105 | int err; |
105 | struct vcpu_info *vcpup; | 106 | struct vcpu_info *vcpup; |
106 | 107 | ||
107 | BUG_ON(HYPERVISOR_shared_info == &dummy_shared_info); | 108 | BUG_ON(HYPERVISOR_shared_info == &xen_dummy_shared_info); |
108 | per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu]; | 109 | per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu]; |
109 | 110 | ||
110 | if (!have_vcpu_info_placement) | 111 | if (!have_vcpu_info_placement) |
@@ -136,11 +137,41 @@ static void __init xen_vcpu_setup(int cpu) | |||
136 | } | 137 | } |
137 | } | 138 | } |
138 | 139 | ||
140 | /* | ||
141 | * On restore, set the vcpu placement up again. | ||
142 | * If it fails, then we're in a bad state, since | ||
143 | * we can't back out from using it... | ||
144 | */ | ||
145 | void xen_vcpu_restore(void) | ||
146 | { | ||
147 | if (have_vcpu_info_placement) { | ||
148 | int cpu; | ||
149 | |||
150 | for_each_online_cpu(cpu) { | ||
151 | bool other_cpu = (cpu != smp_processor_id()); | ||
152 | |||
153 | if (other_cpu && | ||
154 | HYPERVISOR_vcpu_op(VCPUOP_down, cpu, NULL)) | ||
155 | BUG(); | ||
156 | |||
157 | xen_vcpu_setup(cpu); | ||
158 | |||
159 | if (other_cpu && | ||
160 | HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL)) | ||
161 | BUG(); | ||
162 | } | ||
163 | |||
164 | BUG_ON(!have_vcpu_info_placement); | ||
165 | } | ||
166 | } | ||
167 | |||
139 | static void __init xen_banner(void) | 168 | static void __init xen_banner(void) |
140 | { | 169 | { |
141 | printk(KERN_INFO "Booting paravirtualized kernel on %s\n", | 170 | printk(KERN_INFO "Booting paravirtualized kernel on %s\n", |
142 | pv_info.name); | 171 | pv_info.name); |
143 | printk(KERN_INFO "Hypervisor signature: %s\n", xen_start_info->magic); | 172 | printk(KERN_INFO "Hypervisor signature: %s%s\n", |
173 | xen_start_info->magic, | ||
174 | xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : ""); | ||
144 | } | 175 | } |
145 | 176 | ||
146 | static void xen_cpuid(unsigned int *ax, unsigned int *bx, | 177 | static void xen_cpuid(unsigned int *ax, unsigned int *bx, |
@@ -235,13 +266,13 @@ static void xen_irq_enable(void) | |||
235 | { | 266 | { |
236 | struct vcpu_info *vcpu; | 267 | struct vcpu_info *vcpu; |
237 | 268 | ||
238 | /* There's a one instruction preempt window here. We need to | 269 | /* We don't need to worry about being preempted here, since |
239 | make sure we're don't switch CPUs between getting the vcpu | 270 | either a) interrupts are disabled, so no preemption, or b) |
240 | pointer and updating the mask. */ | 271 | the caller is confused and is trying to re-enable interrupts |
241 | preempt_disable(); | 272 | on an indeterminate processor. */ |
273 | |||
242 | vcpu = x86_read_percpu(xen_vcpu); | 274 | vcpu = x86_read_percpu(xen_vcpu); |
243 | vcpu->evtchn_upcall_mask = 0; | 275 | vcpu->evtchn_upcall_mask = 0; |
244 | preempt_enable_no_resched(); | ||
245 | 276 | ||
246 | /* Doesn't matter if we get preempted here, because any | 277 | /* Doesn't matter if we get preempted here, because any |
247 | pending event will get dealt with anyway. */ | 278 | pending event will get dealt with anyway. */ |
@@ -254,7 +285,7 @@ static void xen_irq_enable(void) | |||
254 | static void xen_safe_halt(void) | 285 | static void xen_safe_halt(void) |
255 | { | 286 | { |
256 | /* Blocking includes an implicit local_irq_enable(). */ | 287 | /* Blocking includes an implicit local_irq_enable(). */ |
257 | if (HYPERVISOR_sched_op(SCHEDOP_block, 0) != 0) | 288 | if (HYPERVISOR_sched_op(SCHEDOP_block, NULL) != 0) |
258 | BUG(); | 289 | BUG(); |
259 | } | 290 | } |
260 | 291 | ||
@@ -607,6 +638,30 @@ static void xen_flush_tlb_others(const cpumask_t *cpus, struct mm_struct *mm, | |||
607 | xen_mc_issue(PARAVIRT_LAZY_MMU); | 638 | xen_mc_issue(PARAVIRT_LAZY_MMU); |
608 | } | 639 | } |
609 | 640 | ||
641 | static void xen_clts(void) | ||
642 | { | ||
643 | struct multicall_space mcs; | ||
644 | |||
645 | mcs = xen_mc_entry(0); | ||
646 | |||
647 | MULTI_fpu_taskswitch(mcs.mc, 0); | ||
648 | |||
649 | xen_mc_issue(PARAVIRT_LAZY_CPU); | ||
650 | } | ||
651 | |||
652 | static void xen_write_cr0(unsigned long cr0) | ||
653 | { | ||
654 | struct multicall_space mcs; | ||
655 | |||
656 | /* Only pay attention to cr0.TS; everything else is | ||
657 | ignored. */ | ||
658 | mcs = xen_mc_entry(0); | ||
659 | |||
660 | MULTI_fpu_taskswitch(mcs.mc, (cr0 & X86_CR0_TS) != 0); | ||
661 | |||
662 | xen_mc_issue(PARAVIRT_LAZY_CPU); | ||
663 | } | ||
664 | |||
610 | static void xen_write_cr2(unsigned long cr2) | 665 | static void xen_write_cr2(unsigned long cr2) |
611 | { | 666 | { |
612 | x86_read_percpu(xen_vcpu)->arch.cr2 = cr2; | 667 | x86_read_percpu(xen_vcpu)->arch.cr2 = cr2; |
@@ -624,8 +679,10 @@ static unsigned long xen_read_cr2_direct(void) | |||
624 | 679 | ||
625 | static void xen_write_cr4(unsigned long cr4) | 680 | static void xen_write_cr4(unsigned long cr4) |
626 | { | 681 | { |
627 | /* Just ignore cr4 changes; Xen doesn't allow us to do | 682 | cr4 &= ~X86_CR4_PGE; |
628 | anything anyway. */ | 683 | cr4 &= ~X86_CR4_PSE; |
684 | |||
685 | native_write_cr4(cr4); | ||
629 | } | 686 | } |
630 | 687 | ||
631 | static unsigned long xen_read_cr3(void) | 688 | static unsigned long xen_read_cr3(void) |
@@ -785,38 +842,35 @@ static __init void xen_set_pte_init(pte_t *ptep, pte_t pte) | |||
785 | static __init void xen_pagetable_setup_start(pgd_t *base) | 842 | static __init void xen_pagetable_setup_start(pgd_t *base) |
786 | { | 843 | { |
787 | pgd_t *xen_pgd = (pgd_t *)xen_start_info->pt_base; | 844 | pgd_t *xen_pgd = (pgd_t *)xen_start_info->pt_base; |
845 | int i; | ||
788 | 846 | ||
789 | /* special set_pte for pagetable initialization */ | 847 | /* special set_pte for pagetable initialization */ |
790 | pv_mmu_ops.set_pte = xen_set_pte_init; | 848 | pv_mmu_ops.set_pte = xen_set_pte_init; |
791 | 849 | ||
792 | init_mm.pgd = base; | 850 | init_mm.pgd = base; |
793 | /* | 851 | /* |
794 | * copy top-level of Xen-supplied pagetable into place. For | 852 | * copy top-level of Xen-supplied pagetable into place. This |
795 | * !PAE we can use this as-is, but for PAE it is a stand-in | 853 | * is a stand-in while we copy the pmd pages. |
796 | * while we copy the pmd pages. | ||
797 | */ | 854 | */ |
798 | memcpy(base, xen_pgd, PTRS_PER_PGD * sizeof(pgd_t)); | 855 | memcpy(base, xen_pgd, PTRS_PER_PGD * sizeof(pgd_t)); |
799 | 856 | ||
800 | if (PTRS_PER_PMD > 1) { | 857 | /* |
801 | int i; | 858 | * For PAE, need to allocate new pmds, rather than |
802 | /* | 859 | * share Xen's, since Xen doesn't like pmd's being |
803 | * For PAE, need to allocate new pmds, rather than | 860 | * shared between address spaces. |
804 | * share Xen's, since Xen doesn't like pmd's being | 861 | */ |
805 | * shared between address spaces. | 862 | for (i = 0; i < PTRS_PER_PGD; i++) { |
806 | */ | 863 | if (pgd_val_ma(xen_pgd[i]) & _PAGE_PRESENT) { |
807 | for (i = 0; i < PTRS_PER_PGD; i++) { | 864 | pmd_t *pmd = (pmd_t *)alloc_bootmem_low_pages(PAGE_SIZE); |
808 | if (pgd_val_ma(xen_pgd[i]) & _PAGE_PRESENT) { | ||
809 | pmd_t *pmd = (pmd_t *)alloc_bootmem_low_pages(PAGE_SIZE); | ||
810 | 865 | ||
811 | memcpy(pmd, (void *)pgd_page_vaddr(xen_pgd[i]), | 866 | memcpy(pmd, (void *)pgd_page_vaddr(xen_pgd[i]), |
812 | PAGE_SIZE); | 867 | PAGE_SIZE); |
813 | 868 | ||
814 | make_lowmem_page_readonly(pmd); | 869 | make_lowmem_page_readonly(pmd); |
815 | 870 | ||
816 | set_pgd(&base[i], __pgd(1 + __pa(pmd))); | 871 | set_pgd(&base[i], __pgd(1 + __pa(pmd))); |
817 | } else | 872 | } else |
818 | pgd_clear(&base[i]); | 873 | pgd_clear(&base[i]); |
819 | } | ||
820 | } | 874 | } |
821 | 875 | ||
822 | /* make sure zero_page is mapped RO so we can use it in pagetables */ | 876 | /* make sure zero_page is mapped RO so we can use it in pagetables */ |
@@ -834,7 +888,7 @@ static __init void xen_pagetable_setup_start(pgd_t *base) | |||
834 | PFN_DOWN(__pa(xen_start_info->pt_base))); | 888 | PFN_DOWN(__pa(xen_start_info->pt_base))); |
835 | } | 889 | } |
836 | 890 | ||
837 | static __init void setup_shared_info(void) | 891 | void xen_setup_shared_info(void) |
838 | { | 892 | { |
839 | if (!xen_feature(XENFEAT_auto_translated_physmap)) { | 893 | if (!xen_feature(XENFEAT_auto_translated_physmap)) { |
840 | unsigned long addr = fix_to_virt(FIX_PARAVIRT_BOOTMAP); | 894 | unsigned long addr = fix_to_virt(FIX_PARAVIRT_BOOTMAP); |
@@ -857,6 +911,8 @@ static __init void setup_shared_info(void) | |||
857 | /* In UP this is as good a place as any to set up shared info */ | 911 | /* In UP this is as good a place as any to set up shared info */ |
858 | xen_setup_vcpu_info_placement(); | 912 | xen_setup_vcpu_info_placement(); |
859 | #endif | 913 | #endif |
914 | |||
915 | xen_setup_mfn_list_list(); | ||
860 | } | 916 | } |
861 | 917 | ||
862 | static __init void xen_pagetable_setup_done(pgd_t *base) | 918 | static __init void xen_pagetable_setup_done(pgd_t *base) |
@@ -869,25 +925,23 @@ static __init void xen_pagetable_setup_done(pgd_t *base) | |||
869 | pv_mmu_ops.release_pmd = xen_release_pmd; | 925 | pv_mmu_ops.release_pmd = xen_release_pmd; |
870 | pv_mmu_ops.set_pte = xen_set_pte; | 926 | pv_mmu_ops.set_pte = xen_set_pte; |
871 | 927 | ||
872 | setup_shared_info(); | 928 | xen_setup_shared_info(); |
873 | 929 | ||
874 | /* Actually pin the pagetable down, but we can't set PG_pinned | 930 | /* Actually pin the pagetable down, but we can't set PG_pinned |
875 | yet because the page structures don't exist yet. */ | 931 | yet because the page structures don't exist yet. */ |
876 | { | 932 | pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, PFN_DOWN(__pa(base))); |
877 | unsigned level; | 933 | } |
878 | 934 | ||
879 | #ifdef CONFIG_X86_PAE | 935 | static __init void xen_post_allocator_init(void) |
880 | level = MMUEXT_PIN_L3_TABLE; | 936 | { |
881 | #else | 937 | pv_mmu_ops.set_pmd = xen_set_pmd; |
882 | level = MMUEXT_PIN_L2_TABLE; | 938 | pv_mmu_ops.set_pud = xen_set_pud; |
883 | #endif | ||
884 | 939 | ||
885 | pin_pagetable_pfn(level, PFN_DOWN(__pa(base))); | 940 | xen_mark_init_mm_pinned(); |
886 | } | ||
887 | } | 941 | } |
888 | 942 | ||
889 | /* This is called once we have the cpu_possible_map */ | 943 | /* This is called once we have the cpu_possible_map */ |
890 | void __init xen_setup_vcpu_info_placement(void) | 944 | void xen_setup_vcpu_info_placement(void) |
891 | { | 945 | { |
892 | int cpu; | 946 | int cpu; |
893 | 947 | ||
@@ -960,6 +1014,33 @@ static unsigned xen_patch(u8 type, u16 clobbers, void *insnbuf, | |||
960 | return ret; | 1014 | return ret; |
961 | } | 1015 | } |
962 | 1016 | ||
1017 | static void xen_set_fixmap(unsigned idx, unsigned long phys, pgprot_t prot) | ||
1018 | { | ||
1019 | pte_t pte; | ||
1020 | |||
1021 | phys >>= PAGE_SHIFT; | ||
1022 | |||
1023 | switch (idx) { | ||
1024 | case FIX_BTMAP_END ... FIX_BTMAP_BEGIN: | ||
1025 | #ifdef CONFIG_X86_F00F_BUG | ||
1026 | case FIX_F00F_IDT: | ||
1027 | #endif | ||
1028 | case FIX_WP_TEST: | ||
1029 | case FIX_VDSO: | ||
1030 | #ifdef CONFIG_X86_LOCAL_APIC | ||
1031 | case FIX_APIC_BASE: /* maps dummy local APIC */ | ||
1032 | #endif | ||
1033 | pte = pfn_pte(phys, prot); | ||
1034 | break; | ||
1035 | |||
1036 | default: | ||
1037 | pte = mfn_pte(phys, prot); | ||
1038 | break; | ||
1039 | } | ||
1040 | |||
1041 | __native_set_fixmap(idx, pte); | ||
1042 | } | ||
1043 | |||
963 | static const struct pv_info xen_info __initdata = { | 1044 | static const struct pv_info xen_info __initdata = { |
964 | .paravirt_enabled = 1, | 1045 | .paravirt_enabled = 1, |
965 | .shared_kernel_pmd = 0, | 1046 | .shared_kernel_pmd = 0, |
@@ -973,7 +1054,7 @@ static const struct pv_init_ops xen_init_ops __initdata = { | |||
973 | .banner = xen_banner, | 1054 | .banner = xen_banner, |
974 | .memory_setup = xen_memory_setup, | 1055 | .memory_setup = xen_memory_setup, |
975 | .arch_setup = xen_arch_setup, | 1056 | .arch_setup = xen_arch_setup, |
976 | .post_allocator_init = xen_mark_init_mm_pinned, | 1057 | .post_allocator_init = xen_post_allocator_init, |
977 | }; | 1058 | }; |
978 | 1059 | ||
979 | static const struct pv_time_ops xen_time_ops __initdata = { | 1060 | static const struct pv_time_ops xen_time_ops __initdata = { |
@@ -981,7 +1062,7 @@ static const struct pv_time_ops xen_time_ops __initdata = { | |||
981 | 1062 | ||
982 | .set_wallclock = xen_set_wallclock, | 1063 | .set_wallclock = xen_set_wallclock, |
983 | .get_wallclock = xen_get_wallclock, | 1064 | .get_wallclock = xen_get_wallclock, |
984 | .get_cpu_khz = xen_cpu_khz, | 1065 | .get_tsc_khz = xen_tsc_khz, |
985 | .sched_clock = xen_sched_clock, | 1066 | .sched_clock = xen_sched_clock, |
986 | }; | 1067 | }; |
987 | 1068 | ||
@@ -991,10 +1072,10 @@ static const struct pv_cpu_ops xen_cpu_ops __initdata = { | |||
991 | .set_debugreg = xen_set_debugreg, | 1072 | .set_debugreg = xen_set_debugreg, |
992 | .get_debugreg = xen_get_debugreg, | 1073 | .get_debugreg = xen_get_debugreg, |
993 | 1074 | ||
994 | .clts = native_clts, | 1075 | .clts = xen_clts, |
995 | 1076 | ||
996 | .read_cr0 = native_read_cr0, | 1077 | .read_cr0 = native_read_cr0, |
997 | .write_cr0 = native_write_cr0, | 1078 | .write_cr0 = xen_write_cr0, |
998 | 1079 | ||
999 | .read_cr4 = native_read_cr4, | 1080 | .read_cr4 = native_read_cr4, |
1000 | .read_cr4_safe = native_read_cr4_safe, | 1081 | .read_cr4_safe = native_read_cr4_safe, |
@@ -1008,7 +1089,7 @@ static const struct pv_cpu_ops xen_cpu_ops __initdata = { | |||
1008 | .read_pmc = native_read_pmc, | 1089 | .read_pmc = native_read_pmc, |
1009 | 1090 | ||
1010 | .iret = xen_iret, | 1091 | .iret = xen_iret, |
1011 | .irq_enable_syscall_ret = xen_sysexit, | 1092 | .irq_enable_sysexit = xen_sysexit, |
1012 | 1093 | ||
1013 | .load_tr_desc = paravirt_nop, | 1094 | .load_tr_desc = paravirt_nop, |
1014 | .set_ldt = xen_set_ldt, | 1095 | .set_ldt = xen_set_ldt, |
@@ -1042,6 +1123,9 @@ static const struct pv_irq_ops xen_irq_ops __initdata = { | |||
1042 | .irq_enable = xen_irq_enable, | 1123 | .irq_enable = xen_irq_enable, |
1043 | .safe_halt = xen_safe_halt, | 1124 | .safe_halt = xen_safe_halt, |
1044 | .halt = xen_halt, | 1125 | .halt = xen_halt, |
1126 | #ifdef CONFIG_X86_64 | ||
1127 | .adjust_exception_frame = paravirt_nop, | ||
1128 | #endif | ||
1045 | }; | 1129 | }; |
1046 | 1130 | ||
1047 | static const struct pv_apic_ops xen_apic_ops __initdata = { | 1131 | static const struct pv_apic_ops xen_apic_ops __initdata = { |
@@ -1073,6 +1157,9 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = { | |||
1073 | .pte_update = paravirt_nop, | 1157 | .pte_update = paravirt_nop, |
1074 | .pte_update_defer = paravirt_nop, | 1158 | .pte_update_defer = paravirt_nop, |
1075 | 1159 | ||
1160 | .pgd_alloc = __paravirt_pgd_alloc, | ||
1161 | .pgd_free = paravirt_nop, | ||
1162 | |||
1076 | .alloc_pte = xen_alloc_pte_init, | 1163 | .alloc_pte = xen_alloc_pte_init, |
1077 | .release_pte = xen_release_pte_init, | 1164 | .release_pte = xen_release_pte_init, |
1078 | .alloc_pmd = xen_alloc_pte_init, | 1165 | .alloc_pmd = xen_alloc_pte_init, |
@@ -1085,24 +1172,26 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = { | |||
1085 | 1172 | ||
1086 | .set_pte = NULL, /* see xen_pagetable_setup_* */ | 1173 | .set_pte = NULL, /* see xen_pagetable_setup_* */ |
1087 | .set_pte_at = xen_set_pte_at, | 1174 | .set_pte_at = xen_set_pte_at, |
1088 | .set_pmd = xen_set_pmd, | 1175 | .set_pmd = xen_set_pmd_hyper, |
1176 | |||
1177 | .ptep_modify_prot_start = __ptep_modify_prot_start, | ||
1178 | .ptep_modify_prot_commit = __ptep_modify_prot_commit, | ||
1089 | 1179 | ||
1090 | .pte_val = xen_pte_val, | 1180 | .pte_val = xen_pte_val, |
1181 | .pte_flags = native_pte_val, | ||
1091 | .pgd_val = xen_pgd_val, | 1182 | .pgd_val = xen_pgd_val, |
1092 | 1183 | ||
1093 | .make_pte = xen_make_pte, | 1184 | .make_pte = xen_make_pte, |
1094 | .make_pgd = xen_make_pgd, | 1185 | .make_pgd = xen_make_pgd, |
1095 | 1186 | ||
1096 | #ifdef CONFIG_X86_PAE | ||
1097 | .set_pte_atomic = xen_set_pte_atomic, | 1187 | .set_pte_atomic = xen_set_pte_atomic, |
1098 | .set_pte_present = xen_set_pte_at, | 1188 | .set_pte_present = xen_set_pte_at, |
1099 | .set_pud = xen_set_pud, | 1189 | .set_pud = xen_set_pud_hyper, |
1100 | .pte_clear = xen_pte_clear, | 1190 | .pte_clear = xen_pte_clear, |
1101 | .pmd_clear = xen_pmd_clear, | 1191 | .pmd_clear = xen_pmd_clear, |
1102 | 1192 | ||
1103 | .make_pmd = xen_make_pmd, | 1193 | .make_pmd = xen_make_pmd, |
1104 | .pmd_val = xen_pmd_val, | 1194 | .pmd_val = xen_pmd_val, |
1105 | #endif /* PAE */ | ||
1106 | 1195 | ||
1107 | .activate_mm = xen_activate_mm, | 1196 | .activate_mm = xen_activate_mm, |
1108 | .dup_mmap = xen_dup_mmap, | 1197 | .dup_mmap = xen_dup_mmap, |
@@ -1112,6 +1201,8 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = { | |||
1112 | .enter = paravirt_enter_lazy_mmu, | 1201 | .enter = paravirt_enter_lazy_mmu, |
1113 | .leave = xen_leave_lazy, | 1202 | .leave = xen_leave_lazy, |
1114 | }, | 1203 | }, |
1204 | |||
1205 | .set_fixmap = xen_set_fixmap, | ||
1115 | }; | 1206 | }; |
1116 | 1207 | ||
1117 | #ifdef CONFIG_SMP | 1208 | #ifdef CONFIG_SMP |
@@ -1123,17 +1214,21 @@ static const struct smp_ops xen_smp_ops __initdata = { | |||
1123 | 1214 | ||
1124 | .smp_send_stop = xen_smp_send_stop, | 1215 | .smp_send_stop = xen_smp_send_stop, |
1125 | .smp_send_reschedule = xen_smp_send_reschedule, | 1216 | .smp_send_reschedule = xen_smp_send_reschedule, |
1126 | .smp_call_function_mask = xen_smp_call_function_mask, | 1217 | |
1218 | .send_call_func_ipi = xen_smp_send_call_function_ipi, | ||
1219 | .send_call_func_single_ipi = xen_smp_send_call_function_single_ipi, | ||
1127 | }; | 1220 | }; |
1128 | #endif /* CONFIG_SMP */ | 1221 | #endif /* CONFIG_SMP */ |
1129 | 1222 | ||
1130 | static void xen_reboot(int reason) | 1223 | static void xen_reboot(int reason) |
1131 | { | 1224 | { |
1225 | struct sched_shutdown r = { .reason = reason }; | ||
1226 | |||
1132 | #ifdef CONFIG_SMP | 1227 | #ifdef CONFIG_SMP |
1133 | smp_send_stop(); | 1228 | smp_send_stop(); |
1134 | #endif | 1229 | #endif |
1135 | 1230 | ||
1136 | if (HYPERVISOR_sched_op(SCHEDOP_shutdown, reason)) | 1231 | if (HYPERVISOR_sched_op(SCHEDOP_shutdown, &r)) |
1137 | BUG(); | 1232 | BUG(); |
1138 | } | 1233 | } |
1139 | 1234 | ||
@@ -1188,6 +1283,8 @@ asmlinkage void __init xen_start_kernel(void) | |||
1188 | 1283 | ||
1189 | BUG_ON(memcmp(xen_start_info->magic, "xen-3", 5) != 0); | 1284 | BUG_ON(memcmp(xen_start_info->magic, "xen-3", 5) != 0); |
1190 | 1285 | ||
1286 | xen_setup_features(); | ||
1287 | |||
1191 | /* Install Xen paravirt ops */ | 1288 | /* Install Xen paravirt ops */ |
1192 | pv_info = xen_info; | 1289 | pv_info = xen_info; |
1193 | pv_init_ops = xen_init_ops; | 1290 | pv_init_ops = xen_init_ops; |
@@ -1197,21 +1294,26 @@ asmlinkage void __init xen_start_kernel(void) | |||
1197 | pv_apic_ops = xen_apic_ops; | 1294 | pv_apic_ops = xen_apic_ops; |
1198 | pv_mmu_ops = xen_mmu_ops; | 1295 | pv_mmu_ops = xen_mmu_ops; |
1199 | 1296 | ||
1297 | if (xen_feature(XENFEAT_mmu_pt_update_preserve_ad)) { | ||
1298 | pv_mmu_ops.ptep_modify_prot_start = xen_ptep_modify_prot_start; | ||
1299 | pv_mmu_ops.ptep_modify_prot_commit = xen_ptep_modify_prot_commit; | ||
1300 | } | ||
1301 | |||
1200 | machine_ops = xen_machine_ops; | 1302 | machine_ops = xen_machine_ops; |
1201 | 1303 | ||
1202 | #ifdef CONFIG_SMP | 1304 | #ifdef CONFIG_SMP |
1203 | smp_ops = xen_smp_ops; | 1305 | smp_ops = xen_smp_ops; |
1204 | #endif | 1306 | #endif |
1205 | 1307 | ||
1206 | xen_setup_features(); | ||
1207 | |||
1208 | /* Get mfn list */ | 1308 | /* Get mfn list */ |
1209 | if (!xen_feature(XENFEAT_auto_translated_physmap)) | 1309 | if (!xen_feature(XENFEAT_auto_translated_physmap)) |
1210 | phys_to_machine_mapping = (unsigned long *)xen_start_info->mfn_list; | 1310 | xen_build_dynamic_phys_to_machine(); |
1211 | 1311 | ||
1212 | pgd = (pgd_t *)xen_start_info->pt_base; | 1312 | pgd = (pgd_t *)xen_start_info->pt_base; |
1213 | 1313 | ||
1314 | init_pg_tables_start = __pa(pgd); | ||
1214 | init_pg_tables_end = __pa(pgd) + xen_start_info->nr_pt_frames*PAGE_SIZE; | 1315 | init_pg_tables_end = __pa(pgd) + xen_start_info->nr_pt_frames*PAGE_SIZE; |
1316 | max_pfn_mapped = (init_pg_tables_end + 512*1024) >> PAGE_SHIFT; | ||
1215 | 1317 | ||
1216 | init_mm.pgd = pgd; /* use the Xen pagetables to start */ | 1318 | init_mm.pgd = pgd; /* use the Xen pagetables to start */ |
1217 | 1319 | ||
@@ -1228,6 +1330,11 @@ asmlinkage void __init xen_start_kernel(void) | |||
1228 | if (xen_feature(XENFEAT_supervisor_mode_kernel)) | 1330 | if (xen_feature(XENFEAT_supervisor_mode_kernel)) |
1229 | pv_info.kernel_rpl = 0; | 1331 | pv_info.kernel_rpl = 0; |
1230 | 1332 | ||
1333 | /* Prevent unwanted bits from being set in PTEs. */ | ||
1334 | __supported_pte_mask &= ~_PAGE_GLOBAL; | ||
1335 | if (!is_initial_xendomain()) | ||
1336 | __supported_pte_mask &= ~(_PAGE_PWT | _PAGE_PCD); | ||
1337 | |||
1231 | /* set the limit of our address space */ | 1338 | /* set the limit of our address space */ |
1232 | xen_reserve_top(); | 1339 | xen_reserve_top(); |
1233 | 1340 | ||
@@ -1242,9 +1349,12 @@ asmlinkage void __init xen_start_kernel(void) | |||
1242 | ? __pa(xen_start_info->mod_start) : 0; | 1349 | ? __pa(xen_start_info->mod_start) : 0; |
1243 | boot_params.hdr.ramdisk_size = xen_start_info->mod_len; | 1350 | boot_params.hdr.ramdisk_size = xen_start_info->mod_len; |
1244 | 1351 | ||
1245 | if (!is_initial_xendomain()) | 1352 | if (!is_initial_xendomain()) { |
1353 | add_preferred_console("xenboot", 0, NULL); | ||
1354 | add_preferred_console("tty", 0, NULL); | ||
1246 | add_preferred_console("hvc", 0, NULL); | 1355 | add_preferred_console("hvc", 0, NULL); |
1356 | } | ||
1247 | 1357 | ||
1248 | /* Start the world */ | 1358 | /* Start the world */ |
1249 | start_kernel(); | 1359 | i386_start_kernel(); |
1250 | } | 1360 | } |