diff options
Diffstat (limited to 'arch/x86/xen/enlighten.c')
-rw-r--r-- | arch/x86/xen/enlighten.c | 317 |
1 files changed, 134 insertions, 183 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index a4e201b47f64..0013a729b41d 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -30,12 +30,12 @@ | |||
30 | #include <xen/interface/xen.h> | 30 | #include <xen/interface/xen.h> |
31 | #include <xen/interface/physdev.h> | 31 | #include <xen/interface/physdev.h> |
32 | #include <xen/interface/vcpu.h> | 32 | #include <xen/interface/vcpu.h> |
33 | #include <xen/interface/sched.h> | ||
34 | #include <xen/features.h> | 33 | #include <xen/features.h> |
35 | #include <xen/page.h> | 34 | #include <xen/page.h> |
36 | #include <xen/hvc-console.h> | 35 | #include <xen/hvc-console.h> |
37 | 36 | ||
38 | #include <asm/paravirt.h> | 37 | #include <asm/paravirt.h> |
38 | #include <asm/apic.h> | ||
39 | #include <asm/page.h> | 39 | #include <asm/page.h> |
40 | #include <asm/xen/hypercall.h> | 40 | #include <asm/xen/hypercall.h> |
41 | #include <asm/xen/hypervisor.h> | 41 | #include <asm/xen/hypervisor.h> |
@@ -57,6 +57,9 @@ EXPORT_SYMBOL_GPL(hypercall_page); | |||
57 | DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu); | 57 | DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu); |
58 | DEFINE_PER_CPU(struct vcpu_info, xen_vcpu_info); | 58 | DEFINE_PER_CPU(struct vcpu_info, xen_vcpu_info); |
59 | 59 | ||
60 | enum xen_domain_type xen_domain_type = XEN_NATIVE; | ||
61 | EXPORT_SYMBOL_GPL(xen_domain_type); | ||
62 | |||
60 | /* | 63 | /* |
61 | * Identity map, in addition to plain kernel map. This needs to be | 64 | * Identity map, in addition to plain kernel map. This needs to be |
62 | * large enough to allocate page table pages to allocate the rest. | 65 | * large enough to allocate page table pages to allocate the rest. |
@@ -110,7 +113,14 @@ struct shared_info *HYPERVISOR_shared_info = (void *)&xen_dummy_shared_info; | |||
110 | * | 113 | * |
111 | * 0: not available, 1: available | 114 | * 0: not available, 1: available |
112 | */ | 115 | */ |
113 | static int have_vcpu_info_placement = 1; | 116 | static int have_vcpu_info_placement = |
117 | #ifdef CONFIG_X86_32 | ||
118 | 1 | ||
119 | #else | ||
120 | 0 | ||
121 | #endif | ||
122 | ; | ||
123 | |||
114 | 124 | ||
115 | static void xen_vcpu_setup(int cpu) | 125 | static void xen_vcpu_setup(int cpu) |
116 | { | 126 | { |
@@ -226,103 +236,68 @@ static unsigned long xen_get_debugreg(int reg) | |||
226 | return HYPERVISOR_get_debugreg(reg); | 236 | return HYPERVISOR_get_debugreg(reg); |
227 | } | 237 | } |
228 | 238 | ||
229 | static unsigned long xen_save_fl(void) | 239 | static void xen_leave_lazy(void) |
230 | { | 240 | { |
231 | struct vcpu_info *vcpu; | 241 | paravirt_leave_lazy(paravirt_get_lazy_mode()); |
232 | unsigned long flags; | 242 | xen_mc_flush(); |
233 | |||
234 | vcpu = x86_read_percpu(xen_vcpu); | ||
235 | |||
236 | /* flag has opposite sense of mask */ | ||
237 | flags = !vcpu->evtchn_upcall_mask; | ||
238 | |||
239 | /* convert to IF type flag | ||
240 | -0 -> 0x00000000 | ||
241 | -1 -> 0xffffffff | ||
242 | */ | ||
243 | return (-flags) & X86_EFLAGS_IF; | ||
244 | } | 243 | } |
245 | 244 | ||
246 | static void xen_restore_fl(unsigned long flags) | 245 | static unsigned long xen_store_tr(void) |
247 | { | 246 | { |
248 | struct vcpu_info *vcpu; | 247 | return 0; |
249 | |||
250 | /* convert from IF type flag */ | ||
251 | flags = !(flags & X86_EFLAGS_IF); | ||
252 | |||
253 | /* There's a one instruction preempt window here. We need to | ||
254 | make sure we're don't switch CPUs between getting the vcpu | ||
255 | pointer and updating the mask. */ | ||
256 | preempt_disable(); | ||
257 | vcpu = x86_read_percpu(xen_vcpu); | ||
258 | vcpu->evtchn_upcall_mask = flags; | ||
259 | preempt_enable_no_resched(); | ||
260 | |||
261 | /* Doesn't matter if we get preempted here, because any | ||
262 | pending event will get dealt with anyway. */ | ||
263 | |||
264 | if (flags == 0) { | ||
265 | preempt_check_resched(); | ||
266 | barrier(); /* unmask then check (avoid races) */ | ||
267 | if (unlikely(vcpu->evtchn_upcall_pending)) | ||
268 | force_evtchn_callback(); | ||
269 | } | ||
270 | } | 248 | } |
271 | 249 | ||
272 | static void xen_irq_disable(void) | 250 | /* |
251 | * Set the page permissions for a particular virtual address. If the | ||
252 | * address is a vmalloc mapping (or other non-linear mapping), then | ||
253 | * find the linear mapping of the page and also set its protections to | ||
254 | * match. | ||
255 | */ | ||
256 | static void set_aliased_prot(void *v, pgprot_t prot) | ||
273 | { | 257 | { |
274 | /* There's a one instruction preempt window here. We need to | 258 | int level; |
275 | make sure we're don't switch CPUs between getting the vcpu | 259 | pte_t *ptep; |
276 | pointer and updating the mask. */ | 260 | pte_t pte; |
277 | preempt_disable(); | 261 | unsigned long pfn; |
278 | x86_read_percpu(xen_vcpu)->evtchn_upcall_mask = 1; | 262 | struct page *page; |
279 | preempt_enable_no_resched(); | ||
280 | } | ||
281 | 263 | ||
282 | static void xen_irq_enable(void) | 264 | ptep = lookup_address((unsigned long)v, &level); |
283 | { | 265 | BUG_ON(ptep == NULL); |
284 | struct vcpu_info *vcpu; | ||
285 | 266 | ||
286 | /* We don't need to worry about being preempted here, since | 267 | pfn = pte_pfn(*ptep); |
287 | either a) interrupts are disabled, so no preemption, or b) | 268 | page = pfn_to_page(pfn); |
288 | the caller is confused and is trying to re-enable interrupts | ||
289 | on an indeterminate processor. */ | ||
290 | 269 | ||
291 | vcpu = x86_read_percpu(xen_vcpu); | 270 | pte = pfn_pte(pfn, prot); |
292 | vcpu->evtchn_upcall_mask = 0; | ||
293 | 271 | ||
294 | /* Doesn't matter if we get preempted here, because any | 272 | if (HYPERVISOR_update_va_mapping((unsigned long)v, pte, 0)) |
295 | pending event will get dealt with anyway. */ | 273 | BUG(); |
296 | 274 | ||
297 | barrier(); /* unmask then check (avoid races) */ | 275 | if (!PageHighMem(page)) { |
298 | if (unlikely(vcpu->evtchn_upcall_pending)) | 276 | void *av = __va(PFN_PHYS(pfn)); |
299 | force_evtchn_callback(); | ||
300 | } | ||
301 | 277 | ||
302 | static void xen_safe_halt(void) | 278 | if (av != v) |
303 | { | 279 | if (HYPERVISOR_update_va_mapping((unsigned long)av, pte, 0)) |
304 | /* Blocking includes an implicit local_irq_enable(). */ | 280 | BUG(); |
305 | if (HYPERVISOR_sched_op(SCHEDOP_block, NULL) != 0) | 281 | } else |
306 | BUG(); | 282 | kmap_flush_unused(); |
307 | } | 283 | } |
308 | 284 | ||
309 | static void xen_halt(void) | 285 | static void xen_alloc_ldt(struct desc_struct *ldt, unsigned entries) |
310 | { | 286 | { |
311 | if (irqs_disabled()) | 287 | const unsigned entries_per_page = PAGE_SIZE / LDT_ENTRY_SIZE; |
312 | HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL); | 288 | int i; |
313 | else | ||
314 | xen_safe_halt(); | ||
315 | } | ||
316 | 289 | ||
317 | static void xen_leave_lazy(void) | 290 | for(i = 0; i < entries; i += entries_per_page) |
318 | { | 291 | set_aliased_prot(ldt + i, PAGE_KERNEL_RO); |
319 | paravirt_leave_lazy(paravirt_get_lazy_mode()); | ||
320 | xen_mc_flush(); | ||
321 | } | 292 | } |
322 | 293 | ||
323 | static unsigned long xen_store_tr(void) | 294 | static void xen_free_ldt(struct desc_struct *ldt, unsigned entries) |
324 | { | 295 | { |
325 | return 0; | 296 | const unsigned entries_per_page = PAGE_SIZE / LDT_ENTRY_SIZE; |
297 | int i; | ||
298 | |||
299 | for(i = 0; i < entries; i += entries_per_page) | ||
300 | set_aliased_prot(ldt + i, PAGE_KERNEL); | ||
326 | } | 301 | } |
327 | 302 | ||
328 | static void xen_set_ldt(const void *addr, unsigned entries) | 303 | static void xen_set_ldt(const void *addr, unsigned entries) |
@@ -425,8 +400,7 @@ static void xen_load_gs_index(unsigned int idx) | |||
425 | static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum, | 400 | static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum, |
426 | const void *ptr) | 401 | const void *ptr) |
427 | { | 402 | { |
428 | unsigned long lp = (unsigned long)&dt[entrynum]; | 403 | xmaddr_t mach_lp = arbitrary_virt_to_machine(&dt[entrynum]); |
429 | xmaddr_t mach_lp = virt_to_machine(lp); | ||
430 | u64 entry = *(u64 *)ptr; | 404 | u64 entry = *(u64 *)ptr; |
431 | 405 | ||
432 | preempt_disable(); | 406 | preempt_disable(); |
@@ -559,7 +533,7 @@ static void xen_write_gdt_entry(struct desc_struct *dt, int entry, | |||
559 | } | 533 | } |
560 | 534 | ||
561 | static void xen_load_sp0(struct tss_struct *tss, | 535 | static void xen_load_sp0(struct tss_struct *tss, |
562 | struct thread_struct *thread) | 536 | struct thread_struct *thread) |
563 | { | 537 | { |
564 | struct multicall_space mcs = xen_mc_entry(0); | 538 | struct multicall_space mcs = xen_mc_entry(0); |
565 | MULTI_stack_switch(mcs.mc, __KERNEL_DS, thread->sp0); | 539 | MULTI_stack_switch(mcs.mc, __KERNEL_DS, thread->sp0); |
@@ -580,16 +554,47 @@ static void xen_io_delay(void) | |||
580 | } | 554 | } |
581 | 555 | ||
582 | #ifdef CONFIG_X86_LOCAL_APIC | 556 | #ifdef CONFIG_X86_LOCAL_APIC |
583 | static u32 xen_apic_read(unsigned long reg) | 557 | static u32 xen_apic_read(u32 reg) |
584 | { | 558 | { |
585 | return 0; | 559 | return 0; |
586 | } | 560 | } |
587 | 561 | ||
588 | static void xen_apic_write(unsigned long reg, u32 val) | 562 | static void xen_apic_write(u32 reg, u32 val) |
589 | { | 563 | { |
590 | /* Warn to see if there's any stray references */ | 564 | /* Warn to see if there's any stray references */ |
591 | WARN_ON(1); | 565 | WARN_ON(1); |
592 | } | 566 | } |
567 | |||
568 | static u64 xen_apic_icr_read(void) | ||
569 | { | ||
570 | return 0; | ||
571 | } | ||
572 | |||
573 | static void xen_apic_icr_write(u32 low, u32 id) | ||
574 | { | ||
575 | /* Warn to see if there's any stray references */ | ||
576 | WARN_ON(1); | ||
577 | } | ||
578 | |||
579 | static void xen_apic_wait_icr_idle(void) | ||
580 | { | ||
581 | return; | ||
582 | } | ||
583 | |||
584 | static u32 xen_safe_apic_wait_icr_idle(void) | ||
585 | { | ||
586 | return 0; | ||
587 | } | ||
588 | |||
589 | static struct apic_ops xen_basic_apic_ops = { | ||
590 | .read = xen_apic_read, | ||
591 | .write = xen_apic_write, | ||
592 | .icr_read = xen_apic_icr_read, | ||
593 | .icr_write = xen_apic_icr_write, | ||
594 | .wait_icr_idle = xen_apic_wait_icr_idle, | ||
595 | .safe_wait_icr_idle = xen_safe_apic_wait_icr_idle, | ||
596 | }; | ||
597 | |||
593 | #endif | 598 | #endif |
594 | 599 | ||
595 | static void xen_flush_tlb(void) | 600 | static void xen_flush_tlb(void) |
@@ -803,6 +808,19 @@ static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high) | |||
803 | ret = -EFAULT; | 808 | ret = -EFAULT; |
804 | break; | 809 | break; |
805 | #endif | 810 | #endif |
811 | |||
812 | case MSR_STAR: | ||
813 | case MSR_CSTAR: | ||
814 | case MSR_LSTAR: | ||
815 | case MSR_SYSCALL_MASK: | ||
816 | case MSR_IA32_SYSENTER_CS: | ||
817 | case MSR_IA32_SYSENTER_ESP: | ||
818 | case MSR_IA32_SYSENTER_EIP: | ||
819 | /* Fast syscall setup is all done in hypercalls, so | ||
820 | these are all ignored. Stub them out here to stop | ||
821 | Xen console noise. */ | ||
822 | break; | ||
823 | |||
806 | default: | 824 | default: |
807 | ret = native_write_msr_safe(msr, low, high); | 825 | ret = native_write_msr_safe(msr, low, high); |
808 | } | 826 | } |
@@ -812,7 +830,7 @@ static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high) | |||
812 | 830 | ||
813 | /* Early in boot, while setting up the initial pagetable, assume | 831 | /* Early in boot, while setting up the initial pagetable, assume |
814 | everything is pinned. */ | 832 | everything is pinned. */ |
815 | static __init void xen_alloc_pte_init(struct mm_struct *mm, u32 pfn) | 833 | static __init void xen_alloc_pte_init(struct mm_struct *mm, unsigned long pfn) |
816 | { | 834 | { |
817 | #ifdef CONFIG_FLATMEM | 835 | #ifdef CONFIG_FLATMEM |
818 | BUG_ON(mem_map); /* should only be used early */ | 836 | BUG_ON(mem_map); /* should only be used early */ |
@@ -822,7 +840,7 @@ static __init void xen_alloc_pte_init(struct mm_struct *mm, u32 pfn) | |||
822 | 840 | ||
823 | /* Early release_pte assumes that all pts are pinned, since there's | 841 | /* Early release_pte assumes that all pts are pinned, since there's |
824 | only init_mm and anything attached to that is pinned. */ | 842 | only init_mm and anything attached to that is pinned. */ |
825 | static void xen_release_pte_init(u32 pfn) | 843 | static void xen_release_pte_init(unsigned long pfn) |
826 | { | 844 | { |
827 | make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); | 845 | make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); |
828 | } | 846 | } |
@@ -838,7 +856,7 @@ static void pin_pagetable_pfn(unsigned cmd, unsigned long pfn) | |||
838 | 856 | ||
839 | /* This needs to make sure the new pte page is pinned iff its being | 857 | /* This needs to make sure the new pte page is pinned iff its being |
840 | attached to a pinned pagetable. */ | 858 | attached to a pinned pagetable. */ |
841 | static void xen_alloc_ptpage(struct mm_struct *mm, u32 pfn, unsigned level) | 859 | static void xen_alloc_ptpage(struct mm_struct *mm, unsigned long pfn, unsigned level) |
842 | { | 860 | { |
843 | struct page *page = pfn_to_page(pfn); | 861 | struct page *page = pfn_to_page(pfn); |
844 | 862 | ||
@@ -846,8 +864,8 @@ static void xen_alloc_ptpage(struct mm_struct *mm, u32 pfn, unsigned level) | |||
846 | SetPagePinned(page); | 864 | SetPagePinned(page); |
847 | 865 | ||
848 | if (!PageHighMem(page)) { | 866 | if (!PageHighMem(page)) { |
849 | make_lowmem_page_readonly(__va(PFN_PHYS(pfn))); | 867 | make_lowmem_page_readonly(__va(PFN_PHYS((unsigned long)pfn))); |
850 | if (level == PT_PTE) | 868 | if (level == PT_PTE && USE_SPLIT_PTLOCKS) |
851 | pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn); | 869 | pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn); |
852 | } else | 870 | } else |
853 | /* make sure there are no stray mappings of | 871 | /* make sure there are no stray mappings of |
@@ -856,12 +874,12 @@ static void xen_alloc_ptpage(struct mm_struct *mm, u32 pfn, unsigned level) | |||
856 | } | 874 | } |
857 | } | 875 | } |
858 | 876 | ||
859 | static void xen_alloc_pte(struct mm_struct *mm, u32 pfn) | 877 | static void xen_alloc_pte(struct mm_struct *mm, unsigned long pfn) |
860 | { | 878 | { |
861 | xen_alloc_ptpage(mm, pfn, PT_PTE); | 879 | xen_alloc_ptpage(mm, pfn, PT_PTE); |
862 | } | 880 | } |
863 | 881 | ||
864 | static void xen_alloc_pmd(struct mm_struct *mm, u32 pfn) | 882 | static void xen_alloc_pmd(struct mm_struct *mm, unsigned long pfn) |
865 | { | 883 | { |
866 | xen_alloc_ptpage(mm, pfn, PT_PMD); | 884 | xen_alloc_ptpage(mm, pfn, PT_PMD); |
867 | } | 885 | } |
@@ -909,13 +927,13 @@ static void xen_pgd_free(struct mm_struct *mm, pgd_t *pgd) | |||
909 | } | 927 | } |
910 | 928 | ||
911 | /* This should never happen until we're OK to use struct page */ | 929 | /* This should never happen until we're OK to use struct page */ |
912 | static void xen_release_ptpage(u32 pfn, unsigned level) | 930 | static void xen_release_ptpage(unsigned long pfn, unsigned level) |
913 | { | 931 | { |
914 | struct page *page = pfn_to_page(pfn); | 932 | struct page *page = pfn_to_page(pfn); |
915 | 933 | ||
916 | if (PagePinned(page)) { | 934 | if (PagePinned(page)) { |
917 | if (!PageHighMem(page)) { | 935 | if (!PageHighMem(page)) { |
918 | if (level == PT_PTE) | 936 | if (level == PT_PTE && USE_SPLIT_PTLOCKS) |
919 | pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, pfn); | 937 | pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, pfn); |
920 | make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); | 938 | make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); |
921 | } | 939 | } |
@@ -923,23 +941,23 @@ static void xen_release_ptpage(u32 pfn, unsigned level) | |||
923 | } | 941 | } |
924 | } | 942 | } |
925 | 943 | ||
926 | static void xen_release_pte(u32 pfn) | 944 | static void xen_release_pte(unsigned long pfn) |
927 | { | 945 | { |
928 | xen_release_ptpage(pfn, PT_PTE); | 946 | xen_release_ptpage(pfn, PT_PTE); |
929 | } | 947 | } |
930 | 948 | ||
931 | static void xen_release_pmd(u32 pfn) | 949 | static void xen_release_pmd(unsigned long pfn) |
932 | { | 950 | { |
933 | xen_release_ptpage(pfn, PT_PMD); | 951 | xen_release_ptpage(pfn, PT_PMD); |
934 | } | 952 | } |
935 | 953 | ||
936 | #if PAGETABLE_LEVELS == 4 | 954 | #if PAGETABLE_LEVELS == 4 |
937 | static void xen_alloc_pud(struct mm_struct *mm, u32 pfn) | 955 | static void xen_alloc_pud(struct mm_struct *mm, unsigned long pfn) |
938 | { | 956 | { |
939 | xen_alloc_ptpage(mm, pfn, PT_PUD); | 957 | xen_alloc_ptpage(mm, pfn, PT_PUD); |
940 | } | 958 | } |
941 | 959 | ||
942 | static void xen_release_pud(u32 pfn) | 960 | static void xen_release_pud(unsigned long pfn) |
943 | { | 961 | { |
944 | xen_release_ptpage(pfn, PT_PUD); | 962 | xen_release_ptpage(pfn, PT_PUD); |
945 | } | 963 | } |
@@ -962,6 +980,7 @@ static void *xen_kmap_atomic_pte(struct page *page, enum km_type type) | |||
962 | } | 980 | } |
963 | #endif | 981 | #endif |
964 | 982 | ||
983 | #ifdef CONFIG_X86_32 | ||
965 | static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte) | 984 | static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte) |
966 | { | 985 | { |
967 | /* If there's an existing pte, then don't allow _PAGE_RW to be set */ | 986 | /* If there's an existing pte, then don't allow _PAGE_RW to be set */ |
@@ -980,6 +999,7 @@ static __init void xen_set_pte_init(pte_t *ptep, pte_t pte) | |||
980 | 999 | ||
981 | xen_set_pte(ptep, pte); | 1000 | xen_set_pte(ptep, pte); |
982 | } | 1001 | } |
1002 | #endif | ||
983 | 1003 | ||
984 | static __init void xen_pagetable_setup_start(pgd_t *base) | 1004 | static __init void xen_pagetable_setup_start(pgd_t *base) |
985 | { | 1005 | { |
@@ -1046,7 +1066,6 @@ void xen_setup_vcpu_info_placement(void) | |||
1046 | 1066 | ||
1047 | /* xen_vcpu_setup managed to place the vcpu_info within the | 1067 | /* xen_vcpu_setup managed to place the vcpu_info within the |
1048 | percpu area for all cpus, so make use of it */ | 1068 | percpu area for all cpus, so make use of it */ |
1049 | #ifdef CONFIG_X86_32 | ||
1050 | if (have_vcpu_info_placement) { | 1069 | if (have_vcpu_info_placement) { |
1051 | printk(KERN_INFO "Xen: using vcpu_info placement\n"); | 1070 | printk(KERN_INFO "Xen: using vcpu_info placement\n"); |
1052 | 1071 | ||
@@ -1056,7 +1075,6 @@ void xen_setup_vcpu_info_placement(void) | |||
1056 | pv_irq_ops.irq_enable = xen_irq_enable_direct; | 1075 | pv_irq_ops.irq_enable = xen_irq_enable_direct; |
1057 | pv_mmu_ops.read_cr2 = xen_read_cr2_direct; | 1076 | pv_mmu_ops.read_cr2 = xen_read_cr2_direct; |
1058 | } | 1077 | } |
1059 | #endif | ||
1060 | } | 1078 | } |
1061 | 1079 | ||
1062 | static unsigned xen_patch(u8 type, u16 clobbers, void *insnbuf, | 1080 | static unsigned xen_patch(u8 type, u16 clobbers, void *insnbuf, |
@@ -1077,12 +1095,10 @@ static unsigned xen_patch(u8 type, u16 clobbers, void *insnbuf, | |||
1077 | goto patch_site | 1095 | goto patch_site |
1078 | 1096 | ||
1079 | switch (type) { | 1097 | switch (type) { |
1080 | #ifdef CONFIG_X86_32 | ||
1081 | SITE(pv_irq_ops, irq_enable); | 1098 | SITE(pv_irq_ops, irq_enable); |
1082 | SITE(pv_irq_ops, irq_disable); | 1099 | SITE(pv_irq_ops, irq_disable); |
1083 | SITE(pv_irq_ops, save_fl); | 1100 | SITE(pv_irq_ops, save_fl); |
1084 | SITE(pv_irq_ops, restore_fl); | 1101 | SITE(pv_irq_ops, restore_fl); |
1085 | #endif /* CONFIG_X86_32 */ | ||
1086 | #undef SITE | 1102 | #undef SITE |
1087 | 1103 | ||
1088 | patch_site: | 1104 | patch_site: |
@@ -1220,6 +1236,9 @@ static const struct pv_cpu_ops xen_cpu_ops __initdata = { | |||
1220 | .load_gs_index = xen_load_gs_index, | 1236 | .load_gs_index = xen_load_gs_index, |
1221 | #endif | 1237 | #endif |
1222 | 1238 | ||
1239 | .alloc_ldt = xen_alloc_ldt, | ||
1240 | .free_ldt = xen_free_ldt, | ||
1241 | |||
1223 | .store_gdt = native_store_gdt, | 1242 | .store_gdt = native_store_gdt, |
1224 | .store_idt = native_store_idt, | 1243 | .store_idt = native_store_idt, |
1225 | .store_tr = xen_store_tr, | 1244 | .store_tr = xen_store_tr, |
@@ -1241,40 +1260,8 @@ static const struct pv_cpu_ops xen_cpu_ops __initdata = { | |||
1241 | }, | 1260 | }, |
1242 | }; | 1261 | }; |
1243 | 1262 | ||
1244 | static void __init __xen_init_IRQ(void) | ||
1245 | { | ||
1246 | #ifdef CONFIG_X86_64 | ||
1247 | int i; | ||
1248 | |||
1249 | /* Create identity vector->irq map */ | ||
1250 | for(i = 0; i < NR_VECTORS; i++) { | ||
1251 | int cpu; | ||
1252 | |||
1253 | for_each_possible_cpu(cpu) | ||
1254 | per_cpu(vector_irq, cpu)[i] = i; | ||
1255 | } | ||
1256 | #endif /* CONFIG_X86_64 */ | ||
1257 | |||
1258 | xen_init_IRQ(); | ||
1259 | } | ||
1260 | |||
1261 | static const struct pv_irq_ops xen_irq_ops __initdata = { | ||
1262 | .init_IRQ = __xen_init_IRQ, | ||
1263 | .save_fl = xen_save_fl, | ||
1264 | .restore_fl = xen_restore_fl, | ||
1265 | .irq_disable = xen_irq_disable, | ||
1266 | .irq_enable = xen_irq_enable, | ||
1267 | .safe_halt = xen_safe_halt, | ||
1268 | .halt = xen_halt, | ||
1269 | #ifdef CONFIG_X86_64 | ||
1270 | .adjust_exception_frame = xen_adjust_exception_frame, | ||
1271 | #endif | ||
1272 | }; | ||
1273 | |||
1274 | static const struct pv_apic_ops xen_apic_ops __initdata = { | 1263 | static const struct pv_apic_ops xen_apic_ops __initdata = { |
1275 | #ifdef CONFIG_X86_LOCAL_APIC | 1264 | #ifdef CONFIG_X86_LOCAL_APIC |
1276 | .apic_write = xen_apic_write, | ||
1277 | .apic_read = xen_apic_read, | ||
1278 | .setup_boot_clock = paravirt_nop, | 1265 | .setup_boot_clock = paravirt_nop, |
1279 | .setup_secondary_clock = paravirt_nop, | 1266 | .setup_secondary_clock = paravirt_nop, |
1280 | .startup_ipi_hook = paravirt_nop, | 1267 | .startup_ipi_hook = paravirt_nop, |
@@ -1413,7 +1400,7 @@ static void __init xen_reserve_top(void) | |||
1413 | if (HYPERVISOR_xen_version(XENVER_platform_parameters, &pp) == 0) | 1400 | if (HYPERVISOR_xen_version(XENVER_platform_parameters, &pp) == 0) |
1414 | top = pp.virt_start; | 1401 | top = pp.virt_start; |
1415 | 1402 | ||
1416 | reserve_top_address(-top + 2 * PAGE_SIZE); | 1403 | reserve_top_address(-top); |
1417 | #endif /* CONFIG_X86_32 */ | 1404 | #endif /* CONFIG_X86_32 */ |
1418 | } | 1405 | } |
1419 | 1406 | ||
@@ -1447,48 +1434,11 @@ static void *m2v(phys_addr_t maddr) | |||
1447 | return __ka(m2p(maddr)); | 1434 | return __ka(m2p(maddr)); |
1448 | } | 1435 | } |
1449 | 1436 | ||
1450 | #ifdef CONFIG_X86_64 | ||
1451 | static void walk(pgd_t *pgd, unsigned long addr) | ||
1452 | { | ||
1453 | unsigned l4idx = pgd_index(addr); | ||
1454 | unsigned l3idx = pud_index(addr); | ||
1455 | unsigned l2idx = pmd_index(addr); | ||
1456 | unsigned l1idx = pte_index(addr); | ||
1457 | pgd_t l4; | ||
1458 | pud_t l3; | ||
1459 | pmd_t l2; | ||
1460 | pte_t l1; | ||
1461 | |||
1462 | xen_raw_printk("walk %p, %lx -> %d %d %d %d\n", | ||
1463 | pgd, addr, l4idx, l3idx, l2idx, l1idx); | ||
1464 | |||
1465 | l4 = pgd[l4idx]; | ||
1466 | xen_raw_printk(" l4: %016lx\n", l4.pgd); | ||
1467 | xen_raw_printk(" %016lx\n", pgd_val(l4)); | ||
1468 | |||
1469 | l3 = ((pud_t *)(m2v(l4.pgd)))[l3idx]; | ||
1470 | xen_raw_printk(" l3: %016lx\n", l3.pud); | ||
1471 | xen_raw_printk(" %016lx\n", pud_val(l3)); | ||
1472 | |||
1473 | l2 = ((pmd_t *)(m2v(l3.pud)))[l2idx]; | ||
1474 | xen_raw_printk(" l2: %016lx\n", l2.pmd); | ||
1475 | xen_raw_printk(" %016lx\n", pmd_val(l2)); | ||
1476 | |||
1477 | l1 = ((pte_t *)(m2v(l2.pmd)))[l1idx]; | ||
1478 | xen_raw_printk(" l1: %016lx\n", l1.pte); | ||
1479 | xen_raw_printk(" %016lx\n", pte_val(l1)); | ||
1480 | } | ||
1481 | #endif | ||
1482 | |||
1483 | static void set_page_prot(void *addr, pgprot_t prot) | 1437 | static void set_page_prot(void *addr, pgprot_t prot) |
1484 | { | 1438 | { |
1485 | unsigned long pfn = __pa(addr) >> PAGE_SHIFT; | 1439 | unsigned long pfn = __pa(addr) >> PAGE_SHIFT; |
1486 | pte_t pte = pfn_pte(pfn, prot); | 1440 | pte_t pte = pfn_pte(pfn, prot); |
1487 | 1441 | ||
1488 | xen_raw_printk("addr=%p pfn=%lx mfn=%lx prot=%016llx pte=%016llx\n", | ||
1489 | addr, pfn, get_phys_to_machine(pfn), | ||
1490 | pgprot_val(prot), pte.pte); | ||
1491 | |||
1492 | if (HYPERVISOR_update_va_mapping((unsigned long)addr, pte, 0)) | 1442 | if (HYPERVISOR_update_va_mapping((unsigned long)addr, pte, 0)) |
1493 | BUG(); | 1443 | BUG(); |
1494 | } | 1444 | } |
@@ -1664,6 +1614,8 @@ asmlinkage void __init xen_start_kernel(void) | |||
1664 | if (!xen_start_info) | 1614 | if (!xen_start_info) |
1665 | return; | 1615 | return; |
1666 | 1616 | ||
1617 | xen_domain_type = XEN_PV_DOMAIN; | ||
1618 | |||
1667 | BUG_ON(memcmp(xen_start_info->magic, "xen-3", 5) != 0); | 1619 | BUG_ON(memcmp(xen_start_info->magic, "xen-3", 5) != 0); |
1668 | 1620 | ||
1669 | xen_setup_features(); | 1621 | xen_setup_features(); |
@@ -1673,10 +1625,18 @@ asmlinkage void __init xen_start_kernel(void) | |||
1673 | pv_init_ops = xen_init_ops; | 1625 | pv_init_ops = xen_init_ops; |
1674 | pv_time_ops = xen_time_ops; | 1626 | pv_time_ops = xen_time_ops; |
1675 | pv_cpu_ops = xen_cpu_ops; | 1627 | pv_cpu_ops = xen_cpu_ops; |
1676 | pv_irq_ops = xen_irq_ops; | ||
1677 | pv_apic_ops = xen_apic_ops; | 1628 | pv_apic_ops = xen_apic_ops; |
1678 | pv_mmu_ops = xen_mmu_ops; | 1629 | pv_mmu_ops = xen_mmu_ops; |
1679 | 1630 | ||
1631 | xen_init_irq_ops(); | ||
1632 | |||
1633 | #ifdef CONFIG_X86_LOCAL_APIC | ||
1634 | /* | ||
1635 | * set up the basic apic ops. | ||
1636 | */ | ||
1637 | apic_ops = &xen_basic_apic_ops; | ||
1638 | #endif | ||
1639 | |||
1680 | if (xen_feature(XENFEAT_mmu_pt_update_preserve_ad)) { | 1640 | if (xen_feature(XENFEAT_mmu_pt_update_preserve_ad)) { |
1681 | pv_mmu_ops.ptep_modify_prot_start = xen_ptep_modify_prot_start; | 1641 | pv_mmu_ops.ptep_modify_prot_start = xen_ptep_modify_prot_start; |
1682 | pv_mmu_ops.ptep_modify_prot_commit = xen_ptep_modify_prot_commit; | 1642 | pv_mmu_ops.ptep_modify_prot_commit = xen_ptep_modify_prot_commit; |
@@ -1700,7 +1660,7 @@ asmlinkage void __init xen_start_kernel(void) | |||
1700 | 1660 | ||
1701 | /* Prevent unwanted bits from being set in PTEs. */ | 1661 | /* Prevent unwanted bits from being set in PTEs. */ |
1702 | __supported_pte_mask &= ~_PAGE_GLOBAL; | 1662 | __supported_pte_mask &= ~_PAGE_GLOBAL; |
1703 | if (!is_initial_xendomain()) | 1663 | if (!xen_initial_domain()) |
1704 | __supported_pte_mask &= ~(_PAGE_PWT | _PAGE_PCD); | 1664 | __supported_pte_mask &= ~(_PAGE_PWT | _PAGE_PCD); |
1705 | 1665 | ||
1706 | /* Don't do the full vcpu_info placement stuff until we have a | 1666 | /* Don't do the full vcpu_info placement stuff until we have a |
@@ -1735,7 +1695,7 @@ asmlinkage void __init xen_start_kernel(void) | |||
1735 | boot_params.hdr.ramdisk_size = xen_start_info->mod_len; | 1695 | boot_params.hdr.ramdisk_size = xen_start_info->mod_len; |
1736 | boot_params.hdr.cmd_line_ptr = __pa(xen_start_info->cmd_line); | 1696 | boot_params.hdr.cmd_line_ptr = __pa(xen_start_info->cmd_line); |
1737 | 1697 | ||
1738 | if (!is_initial_xendomain()) { | 1698 | if (!xen_initial_domain()) { |
1739 | add_preferred_console("xenboot", 0, NULL); | 1699 | add_preferred_console("xenboot", 0, NULL); |
1740 | add_preferred_console("tty", 0, NULL); | 1700 | add_preferred_console("tty", 0, NULL); |
1741 | add_preferred_console("hvc", 0, NULL); | 1701 | add_preferred_console("hvc", 0, NULL); |
@@ -1743,15 +1703,6 @@ asmlinkage void __init xen_start_kernel(void) | |||
1743 | 1703 | ||
1744 | xen_raw_console_write("about to get started...\n"); | 1704 | xen_raw_console_write("about to get started...\n"); |
1745 | 1705 | ||
1746 | #if 0 | ||
1747 | xen_raw_printk("&boot_params=%p __pa(&boot_params)=%lx __va(__pa(&boot_params))=%lx\n", | ||
1748 | &boot_params, __pa_symbol(&boot_params), | ||
1749 | __va(__pa_symbol(&boot_params))); | ||
1750 | |||
1751 | walk(pgd, &boot_params); | ||
1752 | walk(pgd, __va(__pa(&boot_params))); | ||
1753 | #endif | ||
1754 | |||
1755 | /* Start the world */ | 1706 | /* Start the world */ |
1756 | #ifdef CONFIG_X86_32 | 1707 | #ifdef CONFIG_X86_32 |
1757 | i386_start_kernel(); | 1708 | i386_start_kernel(); |