diff options
author | Tony Luck <aegl@agluck-desktop.(none)> | 2009-03-31 17:25:08 -0400 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2009-03-31 17:25:08 -0400 |
commit | c66b31f3926165bc1d4128adc97a064dcbab421a (patch) | |
tree | 13be75d33bd2b9d4ec45ec512ac38a2e7069062e /arch/ia64/kernel | |
parent | 50fbe56c127efde659c686495eb1f925fd84ff0a (diff) | |
parent | 7120569c76028a6883697b7643564f0c419cfe07 (diff) |
Pull pvops into release branch
Diffstat (limited to 'arch/ia64/kernel')
-rw-r--r-- | arch/ia64/kernel/Makefile | 39 | ||||
-rw-r--r-- | arch/ia64/kernel/Makefile.gate | 27 | ||||
-rw-r--r-- | arch/ia64/kernel/asm-offsets.c | 2 | ||||
-rw-r--r-- | arch/ia64/kernel/efi.c | 1 | ||||
-rw-r--r-- | arch/ia64/kernel/entry.S | 4 | ||||
-rw-r--r-- | arch/ia64/kernel/fsys.S | 35 | ||||
-rw-r--r-- | arch/ia64/kernel/gate.S | 171 | ||||
-rw-r--r-- | arch/ia64/kernel/gate.lds.S | 17 | ||||
-rw-r--r-- | arch/ia64/kernel/head.S | 10 | ||||
-rw-r--r-- | arch/ia64/kernel/ivt.S | 2 | ||||
-rw-r--r-- | arch/ia64/kernel/module.c | 32 | ||||
-rw-r--r-- | arch/ia64/kernel/paravirt.c | 539 | ||||
-rw-r--r-- | arch/ia64/kernel/paravirt_patch.c | 514 | ||||
-rw-r--r-- | arch/ia64/kernel/paravirt_patchlist.c | 79 | ||||
-rw-r--r-- | arch/ia64/kernel/paravirt_patchlist.h | 28 | ||||
-rw-r--r-- | arch/ia64/kernel/paravirtentry.S | 99 | ||||
-rw-r--r-- | arch/ia64/kernel/patch.c | 40 | ||||
-rw-r--r-- | arch/ia64/kernel/setup.c | 2 | ||||
-rw-r--r-- | arch/ia64/kernel/time.c | 9 | ||||
-rw-r--r-- | arch/ia64/kernel/vmlinux.lds.S | 30 |
20 files changed, 1506 insertions, 174 deletions
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile index f2778f2c4fd9..5628e9a990a6 100644 --- a/arch/ia64/kernel/Makefile +++ b/arch/ia64/kernel/Makefile | |||
@@ -5,7 +5,7 @@ | |||
5 | extra-y := head.o init_task.o vmlinux.lds | 5 | extra-y := head.o init_task.o vmlinux.lds |
6 | 6 | ||
7 | obj-y := acpi.o entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o irq_ia64.o \ | 7 | obj-y := acpi.o entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o irq_ia64.o \ |
8 | irq_lsapic.o ivt.o machvec.o pal.o patch.o process.o perfmon.o ptrace.o sal.o \ | 8 | irq_lsapic.o ivt.o machvec.o pal.o paravirt_patchlist.o patch.o process.o perfmon.o ptrace.o sal.o \ |
9 | salinfo.o setup.o signal.o sys_ia64.o time.o traps.o unaligned.o \ | 9 | salinfo.o setup.o signal.o sys_ia64.o time.o traps.o unaligned.o \ |
10 | unwind.o mca.o mca_asm.o topology.o dma-mapping.o | 10 | unwind.o mca.o mca_asm.o topology.o dma-mapping.o |
11 | 11 | ||
@@ -36,7 +36,8 @@ obj-$(CONFIG_PCI_MSI) += msi_ia64.o | |||
36 | mca_recovery-y += mca_drv.o mca_drv_asm.o | 36 | mca_recovery-y += mca_drv.o mca_drv_asm.o |
37 | obj-$(CONFIG_IA64_MC_ERR_INJECT)+= err_inject.o | 37 | obj-$(CONFIG_IA64_MC_ERR_INJECT)+= err_inject.o |
38 | 38 | ||
39 | obj-$(CONFIG_PARAVIRT) += paravirt.o paravirtentry.o | 39 | obj-$(CONFIG_PARAVIRT) += paravirt.o paravirtentry.o \ |
40 | paravirt_patch.o | ||
40 | 41 | ||
41 | obj-$(CONFIG_IA64_ESI) += esi.o | 42 | obj-$(CONFIG_IA64_ESI) += esi.o |
42 | ifneq ($(CONFIG_IA64_ESI),) | 43 | ifneq ($(CONFIG_IA64_ESI),) |
@@ -45,35 +46,13 @@ endif | |||
45 | obj-$(CONFIG_DMAR) += pci-dma.o | 46 | obj-$(CONFIG_DMAR) += pci-dma.o |
46 | obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o | 47 | obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o |
47 | 48 | ||
48 | # The gate DSO image is built using a special linker script. | ||
49 | targets += gate.so gate-syms.o | ||
50 | |||
51 | extra-y += gate.so gate-syms.o gate.lds gate.o | ||
52 | |||
53 | # fp_emulate() expects f2-f5,f16-f31 to contain the user-level state. | 49 | # fp_emulate() expects f2-f5,f16-f31 to contain the user-level state. |
54 | CFLAGS_traps.o += -mfixed-range=f2-f5,f16-f31 | 50 | CFLAGS_traps.o += -mfixed-range=f2-f5,f16-f31 |
55 | 51 | ||
56 | CPPFLAGS_gate.lds := -P -C -U$(ARCH) | 52 | # The gate DSO image is built using a special linker script. |
57 | 53 | include $(srctree)/arch/ia64/kernel/Makefile.gate | |
58 | quiet_cmd_gate = GATE $@ | 54 | # tell compiled for native |
59 | cmd_gate = $(CC) -nostdlib $(GATECFLAGS_$(@F)) -Wl,-T,$(filter-out FORCE,$^) -o $@ | 55 | CPPFLAGS_gate.lds += -D__IA64_GATE_PARAVIRTUALIZED_NATIVE |
60 | |||
61 | GATECFLAGS_gate.so = -shared -s -Wl,-soname=linux-gate.so.1 \ | ||
62 | $(call ld-option, -Wl$(comma)--hash-style=sysv) | ||
63 | $(obj)/gate.so: $(obj)/gate.lds $(obj)/gate.o FORCE | ||
64 | $(call if_changed,gate) | ||
65 | |||
66 | $(obj)/built-in.o: $(obj)/gate-syms.o | ||
67 | $(obj)/built-in.o: ld_flags += -R $(obj)/gate-syms.o | ||
68 | |||
69 | GATECFLAGS_gate-syms.o = -r | ||
70 | $(obj)/gate-syms.o: $(obj)/gate.lds $(obj)/gate.o FORCE | ||
71 | $(call if_changed,gate) | ||
72 | |||
73 | # gate-data.o contains the gate DSO image as data in section .data.gate. | ||
74 | # We must build gate.so before we can assemble it. | ||
75 | # Note: kbuild does not track this dependency due to usage of .incbin | ||
76 | $(obj)/gate-data.o: $(obj)/gate.so | ||
77 | 56 | ||
78 | # Calculate NR_IRQ = max(IA64_NATIVE_NR_IRQS, XEN_NR_IRQS, ...) based on config | 57 | # Calculate NR_IRQ = max(IA64_NATIVE_NR_IRQS, XEN_NR_IRQS, ...) based on config |
79 | define sed-y | 58 | define sed-y |
@@ -109,9 +88,9 @@ include/asm-ia64/nr-irqs.h: arch/$(SRCARCH)/kernel/nr-irqs.s | |||
109 | clean-files += $(objtree)/include/asm-ia64/nr-irqs.h | 88 | clean-files += $(objtree)/include/asm-ia64/nr-irqs.h |
110 | 89 | ||
111 | # | 90 | # |
112 | # native ivt.S and entry.S | 91 | # native ivt.S, entry.S and fsys.S |
113 | # | 92 | # |
114 | ASM_PARAVIRT_OBJS = ivt.o entry.o | 93 | ASM_PARAVIRT_OBJS = ivt.o entry.o fsys.o |
115 | define paravirtualized_native | 94 | define paravirtualized_native |
116 | AFLAGS_$(1) += -D__IA64_ASM_PARAVIRTUALIZED_NATIVE | 95 | AFLAGS_$(1) += -D__IA64_ASM_PARAVIRTUALIZED_NATIVE |
117 | AFLAGS_pvchk-sed-$(1) += -D__IA64_ASM_PARAVIRTUALIZED_PVCHECK | 96 | AFLAGS_pvchk-sed-$(1) += -D__IA64_ASM_PARAVIRTUALIZED_PVCHECK |
diff --git a/arch/ia64/kernel/Makefile.gate b/arch/ia64/kernel/Makefile.gate new file mode 100644 index 000000000000..1d87f84069b3 --- /dev/null +++ b/arch/ia64/kernel/Makefile.gate | |||
@@ -0,0 +1,27 @@ | |||
1 | # The gate DSO image is built using a special linker script. | ||
2 | |||
3 | targets += gate.so gate-syms.o | ||
4 | |||
5 | extra-y += gate.so gate-syms.o gate.lds gate.o | ||
6 | |||
7 | CPPFLAGS_gate.lds := -P -C -U$(ARCH) | ||
8 | |||
9 | quiet_cmd_gate = GATE $@ | ||
10 | cmd_gate = $(CC) -nostdlib $(GATECFLAGS_$(@F)) -Wl,-T,$(filter-out FORCE,$^) -o $@ | ||
11 | |||
12 | GATECFLAGS_gate.so = -shared -s -Wl,-soname=linux-gate.so.1 \ | ||
13 | $(call ld-option, -Wl$(comma)--hash-style=sysv) | ||
14 | $(obj)/gate.so: $(obj)/gate.lds $(obj)/gate.o FORCE | ||
15 | $(call if_changed,gate) | ||
16 | |||
17 | $(obj)/built-in.o: $(obj)/gate-syms.o | ||
18 | $(obj)/built-in.o: ld_flags += -R $(obj)/gate-syms.o | ||
19 | |||
20 | GATECFLAGS_gate-syms.o = -r | ||
21 | $(obj)/gate-syms.o: $(obj)/gate.lds $(obj)/gate.o FORCE | ||
22 | $(call if_changed,gate) | ||
23 | |||
24 | # gate-data.o contains the gate DSO image as data in section .data.gate. | ||
25 | # We must build gate.so before we can assemble it. | ||
26 | # Note: kbuild does not track this dependency due to usage of .incbin | ||
27 | $(obj)/gate-data.o: $(obj)/gate.so | ||
diff --git a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c index 742dbb1d5a4f..af5650169043 100644 --- a/arch/ia64/kernel/asm-offsets.c +++ b/arch/ia64/kernel/asm-offsets.c | |||
@@ -316,5 +316,7 @@ void foo(void) | |||
316 | DEFINE_MAPPED_REG_OFS(XSI_BANK1_R16_OFS, bank1_regs[0]); | 316 | DEFINE_MAPPED_REG_OFS(XSI_BANK1_R16_OFS, bank1_regs[0]); |
317 | DEFINE_MAPPED_REG_OFS(XSI_B0NATS_OFS, vbnat); | 317 | DEFINE_MAPPED_REG_OFS(XSI_B0NATS_OFS, vbnat); |
318 | DEFINE_MAPPED_REG_OFS(XSI_B1NATS_OFS, vnat); | 318 | DEFINE_MAPPED_REG_OFS(XSI_B1NATS_OFS, vnat); |
319 | DEFINE_MAPPED_REG_OFS(XSI_ITC_OFFSET_OFS, itc_offset); | ||
320 | DEFINE_MAPPED_REG_OFS(XSI_ITC_LAST_OFS, itc_last); | ||
319 | #endif /* CONFIG_XEN */ | 321 | #endif /* CONFIG_XEN */ |
320 | } | 322 | } |
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index efaff15d8cf1..7ef80e8161ce 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c | |||
@@ -456,6 +456,7 @@ efi_map_pal_code (void) | |||
456 | GRANULEROUNDDOWN((unsigned long) pal_vaddr), | 456 | GRANULEROUNDDOWN((unsigned long) pal_vaddr), |
457 | pte_val(pfn_pte(__pa(pal_vaddr) >> PAGE_SHIFT, PAGE_KERNEL)), | 457 | pte_val(pfn_pte(__pa(pal_vaddr) >> PAGE_SHIFT, PAGE_KERNEL)), |
458 | IA64_GRANULE_SHIFT); | 458 | IA64_GRANULE_SHIFT); |
459 | paravirt_dv_serialize_data(); | ||
459 | ia64_set_psr(psr); /* restore psr */ | 460 | ia64_set_psr(psr); /* restore psr */ |
460 | } | 461 | } |
461 | 462 | ||
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index e5341e2c1175..ccfdeee9d89f 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S | |||
@@ -735,7 +735,7 @@ GLOBAL_ENTRY(__paravirt_leave_syscall) | |||
735 | __paravirt_work_processed_syscall: | 735 | __paravirt_work_processed_syscall: |
736 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 736 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
737 | adds r2=PT(LOADRS)+16,r12 | 737 | adds r2=PT(LOADRS)+16,r12 |
738 | (pUStk) mov.m r22=ar.itc // fetch time at leave | 738 | MOV_FROM_ITC(pUStk, p9, r22, r19) // fetch time at leave |
739 | adds r18=TI_FLAGS+IA64_TASK_SIZE,r13 | 739 | adds r18=TI_FLAGS+IA64_TASK_SIZE,r13 |
740 | ;; | 740 | ;; |
741 | (p6) ld4 r31=[r18] // load current_thread_info()->flags | 741 | (p6) ld4 r31=[r18] // load current_thread_info()->flags |
@@ -984,7 +984,7 @@ GLOBAL_ENTRY(__paravirt_leave_kernel) | |||
984 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 984 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
985 | .pred.rel.mutex pUStk,pKStk | 985 | .pred.rel.mutex pUStk,pKStk |
986 | MOV_FROM_PSR(pKStk, r22, r29) // M2 read PSR now that interrupts are disabled | 986 | MOV_FROM_PSR(pKStk, r22, r29) // M2 read PSR now that interrupts are disabled |
987 | (pUStk) mov.m r22=ar.itc // M fetch time at leave | 987 | MOV_FROM_ITC(pUStk, p9, r22, r29) // M fetch time at leave |
988 | nop.i 0 | 988 | nop.i 0 |
989 | ;; | 989 | ;; |
990 | #else | 990 | #else |
diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S index c1625c7e1779..3567d54f8cee 100644 --- a/arch/ia64/kernel/fsys.S +++ b/arch/ia64/kernel/fsys.S | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <asm/unistd.h> | 25 | #include <asm/unistd.h> |
26 | 26 | ||
27 | #include "entry.h" | 27 | #include "entry.h" |
28 | #include "paravirt_inst.h" | ||
28 | 29 | ||
29 | /* | 30 | /* |
30 | * See Documentation/ia64/fsys.txt for details on fsyscalls. | 31 | * See Documentation/ia64/fsys.txt for details on fsyscalls. |
@@ -279,7 +280,7 @@ ENTRY(fsys_gettimeofday) | |||
279 | (p9) cmp.eq p13,p0 = 0,r30 // if mmio_ptr, clear p13 jitter control | 280 | (p9) cmp.eq p13,p0 = 0,r30 // if mmio_ptr, clear p13 jitter control |
280 | ;; | 281 | ;; |
281 | .pred.rel.mutex p8,p9 | 282 | .pred.rel.mutex p8,p9 |
282 | (p8) mov r2 = ar.itc // CPU_TIMER. 36 clocks latency!!! | 283 | MOV_FROM_ITC(p8, p6, r2, r10) // CPU_TIMER. 36 clocks latency!!! |
283 | (p9) ld8 r2 = [r30] // MMIO_TIMER. Could also have latency issues.. | 284 | (p9) ld8 r2 = [r30] // MMIO_TIMER. Could also have latency issues.. |
284 | (p13) ld8 r25 = [r19] // get itc_lastcycle value | 285 | (p13) ld8 r25 = [r19] // get itc_lastcycle value |
285 | ld8 r9 = [r22],IA64_TIMESPEC_TV_NSEC_OFFSET // tv_sec | 286 | ld8 r9 = [r22],IA64_TIMESPEC_TV_NSEC_OFFSET // tv_sec |
@@ -418,7 +419,7 @@ EX(.fail_efault, ld8 r14=[r33]) // r14 <- *set | |||
418 | mov r17=(1 << (SIGKILL - 1)) | (1 << (SIGSTOP - 1)) | 419 | mov r17=(1 << (SIGKILL - 1)) | (1 << (SIGSTOP - 1)) |
419 | ;; | 420 | ;; |
420 | 421 | ||
421 | rsm psr.i // mask interrupt delivery | 422 | RSM_PSR_I(p0, r18, r19) // mask interrupt delivery |
422 | mov ar.ccv=0 | 423 | mov ar.ccv=0 |
423 | andcm r14=r14,r17 // filter out SIGKILL & SIGSTOP | 424 | andcm r14=r14,r17 // filter out SIGKILL & SIGSTOP |
424 | 425 | ||
@@ -491,7 +492,7 @@ EX(.fail_efault, ld8 r14=[r33]) // r14 <- *set | |||
491 | #ifdef CONFIG_SMP | 492 | #ifdef CONFIG_SMP |
492 | st4.rel [r31]=r0 // release the lock | 493 | st4.rel [r31]=r0 // release the lock |
493 | #endif | 494 | #endif |
494 | ssm psr.i | 495 | SSM_PSR_I(p0, p9, r31) |
495 | ;; | 496 | ;; |
496 | 497 | ||
497 | srlz.d // ensure psr.i is set again | 498 | srlz.d // ensure psr.i is set again |
@@ -513,7 +514,7 @@ EX(.fail_efault, (p15) st8 [r34]=r3) | |||
513 | #ifdef CONFIG_SMP | 514 | #ifdef CONFIG_SMP |
514 | st4.rel [r31]=r0 // release the lock | 515 | st4.rel [r31]=r0 // release the lock |
515 | #endif | 516 | #endif |
516 | ssm psr.i | 517 | SSM_PSR_I(p0, p9, r17) |
517 | ;; | 518 | ;; |
518 | srlz.d | 519 | srlz.d |
519 | br.sptk.many fsys_fallback_syscall // with signal pending, do the heavy-weight syscall | 520 | br.sptk.many fsys_fallback_syscall // with signal pending, do the heavy-weight syscall |
@@ -521,7 +522,7 @@ EX(.fail_efault, (p15) st8 [r34]=r3) | |||
521 | #ifdef CONFIG_SMP | 522 | #ifdef CONFIG_SMP |
522 | .lock_contention: | 523 | .lock_contention: |
523 | /* Rather than spinning here, fall back on doing a heavy-weight syscall. */ | 524 | /* Rather than spinning here, fall back on doing a heavy-weight syscall. */ |
524 | ssm psr.i | 525 | SSM_PSR_I(p0, p9, r17) |
525 | ;; | 526 | ;; |
526 | srlz.d | 527 | srlz.d |
527 | br.sptk.many fsys_fallback_syscall | 528 | br.sptk.many fsys_fallback_syscall |
@@ -592,17 +593,17 @@ ENTRY(fsys_fallback_syscall) | |||
592 | adds r17=-1024,r15 | 593 | adds r17=-1024,r15 |
593 | movl r14=sys_call_table | 594 | movl r14=sys_call_table |
594 | ;; | 595 | ;; |
595 | rsm psr.i | 596 | RSM_PSR_I(p0, r26, r27) |
596 | shladd r18=r17,3,r14 | 597 | shladd r18=r17,3,r14 |
597 | ;; | 598 | ;; |
598 | ld8 r18=[r18] // load normal (heavy-weight) syscall entry-point | 599 | ld8 r18=[r18] // load normal (heavy-weight) syscall entry-point |
599 | mov r29=psr // read psr (12 cyc load latency) | 600 | MOV_FROM_PSR(p0, r29, r26) // read psr (12 cyc load latency) |
600 | mov r27=ar.rsc | 601 | mov r27=ar.rsc |
601 | mov r21=ar.fpsr | 602 | mov r21=ar.fpsr |
602 | mov r26=ar.pfs | 603 | mov r26=ar.pfs |
603 | END(fsys_fallback_syscall) | 604 | END(fsys_fallback_syscall) |
604 | /* FALL THROUGH */ | 605 | /* FALL THROUGH */ |
605 | GLOBAL_ENTRY(fsys_bubble_down) | 606 | GLOBAL_ENTRY(paravirt_fsys_bubble_down) |
606 | .prologue | 607 | .prologue |
607 | .altrp b6 | 608 | .altrp b6 |
608 | .body | 609 | .body |
@@ -640,7 +641,7 @@ GLOBAL_ENTRY(fsys_bubble_down) | |||
640 | * | 641 | * |
641 | * PSR.BE : already is turned off in __kernel_syscall_via_epc() | 642 | * PSR.BE : already is turned off in __kernel_syscall_via_epc() |
642 | * PSR.AC : don't care (kernel normally turns PSR.AC on) | 643 | * PSR.AC : don't care (kernel normally turns PSR.AC on) |
643 | * PSR.I : already turned off by the time fsys_bubble_down gets | 644 | * PSR.I : already turned off by the time paravirt_fsys_bubble_down gets |
644 | * invoked | 645 | * invoked |
645 | * PSR.DFL: always 0 (kernel never turns it on) | 646 | * PSR.DFL: always 0 (kernel never turns it on) |
646 | * PSR.DFH: don't care --- kernel never touches f32-f127 on its own | 647 | * PSR.DFH: don't care --- kernel never touches f32-f127 on its own |
@@ -650,7 +651,7 @@ GLOBAL_ENTRY(fsys_bubble_down) | |||
650 | * PSR.DB : don't care --- kernel never enables kernel-level | 651 | * PSR.DB : don't care --- kernel never enables kernel-level |
651 | * breakpoints | 652 | * breakpoints |
652 | * PSR.TB : must be 0 already; if it wasn't zero on entry to | 653 | * PSR.TB : must be 0 already; if it wasn't zero on entry to |
653 | * __kernel_syscall_via_epc, the branch to fsys_bubble_down | 654 | * __kernel_syscall_via_epc, the branch to paravirt_fsys_bubble_down |
654 | * will trigger a taken branch; the taken-trap-handler then | 655 | * will trigger a taken branch; the taken-trap-handler then |
655 | * converts the syscall into a break-based system-call. | 656 | * converts the syscall into a break-based system-call. |
656 | */ | 657 | */ |
@@ -683,7 +684,7 @@ GLOBAL_ENTRY(fsys_bubble_down) | |||
683 | ;; | 684 | ;; |
684 | mov ar.rsc=0 // M2 set enforced lazy mode, pl 0, LE, loadrs=0 | 685 | mov ar.rsc=0 // M2 set enforced lazy mode, pl 0, LE, loadrs=0 |
685 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 686 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
686 | mov.m r30=ar.itc // M get cycle for accounting | 687 | MOV_FROM_ITC(p0, p6, r30, r23) // M get cycle for accounting |
687 | #else | 688 | #else |
688 | nop.m 0 | 689 | nop.m 0 |
689 | #endif | 690 | #endif |
@@ -734,21 +735,21 @@ GLOBAL_ENTRY(fsys_bubble_down) | |||
734 | mov rp=r14 // I0 set the real return addr | 735 | mov rp=r14 // I0 set the real return addr |
735 | and r3=_TIF_SYSCALL_TRACEAUDIT,r3 // A | 736 | and r3=_TIF_SYSCALL_TRACEAUDIT,r3 // A |
736 | ;; | 737 | ;; |
737 | ssm psr.i // M2 we're on kernel stacks now, reenable irqs | 738 | SSM_PSR_I(p0, p6, r22) // M2 we're on kernel stacks now, reenable irqs |
738 | cmp.eq p8,p0=r3,r0 // A | 739 | cmp.eq p8,p0=r3,r0 // A |
739 | (p10) br.cond.spnt.many ia64_ret_from_syscall // B return if bad call-frame or r15 is a NaT | 740 | (p10) br.cond.spnt.many ia64_ret_from_syscall // B return if bad call-frame or r15 is a NaT |
740 | 741 | ||
741 | nop.m 0 | 742 | nop.m 0 |
742 | (p8) br.call.sptk.many b6=b6 // B (ignore return address) | 743 | (p8) br.call.sptk.many b6=b6 // B (ignore return address) |
743 | br.cond.spnt ia64_trace_syscall // B | 744 | br.cond.spnt ia64_trace_syscall // B |
744 | END(fsys_bubble_down) | 745 | END(paravirt_fsys_bubble_down) |
745 | 746 | ||
746 | .rodata | 747 | .rodata |
747 | .align 8 | 748 | .align 8 |
748 | .globl fsyscall_table | 749 | .globl paravirt_fsyscall_table |
749 | 750 | ||
750 | data8 fsys_bubble_down | 751 | data8 paravirt_fsys_bubble_down |
751 | fsyscall_table: | 752 | paravirt_fsyscall_table: |
752 | data8 fsys_ni_syscall | 753 | data8 fsys_ni_syscall |
753 | data8 0 // exit // 1025 | 754 | data8 0 // exit // 1025 |
754 | data8 0 // read | 755 | data8 0 // read |
@@ -1033,4 +1034,4 @@ fsyscall_table: | |||
1033 | 1034 | ||
1034 | // fill in zeros for the remaining entries | 1035 | // fill in zeros for the remaining entries |
1035 | .zero: | 1036 | .zero: |
1036 | .space fsyscall_table + 8*NR_syscalls - .zero, 0 | 1037 | .space paravirt_fsyscall_table + 8*NR_syscalls - .zero, 0 |
diff --git a/arch/ia64/kernel/gate.S b/arch/ia64/kernel/gate.S index 74b1ccce4e84..cf5e0a105e16 100644 --- a/arch/ia64/kernel/gate.S +++ b/arch/ia64/kernel/gate.S | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <asm/sigcontext.h> | 13 | #include <asm/sigcontext.h> |
14 | #include <asm/system.h> | 14 | #include <asm/system.h> |
15 | #include <asm/unistd.h> | 15 | #include <asm/unistd.h> |
16 | #include "paravirt_inst.h" | ||
16 | 17 | ||
17 | /* | 18 | /* |
18 | * We can't easily refer to symbols inside the kernel. To avoid full runtime relocation, | 19 | * We can't easily refer to symbols inside the kernel. To avoid full runtime relocation, |
@@ -48,87 +49,6 @@ GLOBAL_ENTRY(__kernel_syscall_via_break) | |||
48 | } | 49 | } |
49 | END(__kernel_syscall_via_break) | 50 | END(__kernel_syscall_via_break) |
50 | 51 | ||
51 | /* | ||
52 | * On entry: | ||
53 | * r11 = saved ar.pfs | ||
54 | * r15 = system call # | ||
55 | * b0 = saved return address | ||
56 | * b6 = return address | ||
57 | * On exit: | ||
58 | * r11 = saved ar.pfs | ||
59 | * r15 = system call # | ||
60 | * b0 = saved return address | ||
61 | * all other "scratch" registers: undefined | ||
62 | * all "preserved" registers: same as on entry | ||
63 | */ | ||
64 | |||
65 | GLOBAL_ENTRY(__kernel_syscall_via_epc) | ||
66 | .prologue | ||
67 | .altrp b6 | ||
68 | .body | ||
69 | { | ||
70 | /* | ||
71 | * Note: the kernel cannot assume that the first two instructions in this | ||
72 | * bundle get executed. The remaining code must be safe even if | ||
73 | * they do not get executed. | ||
74 | */ | ||
75 | adds r17=-1024,r15 // A | ||
76 | mov r10=0 // A default to successful syscall execution | ||
77 | epc // B causes split-issue | ||
78 | } | ||
79 | ;; | ||
80 | rsm psr.be | psr.i // M2 (5 cyc to srlz.d) | ||
81 | LOAD_FSYSCALL_TABLE(r14) // X | ||
82 | ;; | ||
83 | mov r16=IA64_KR(CURRENT) // M2 (12 cyc) | ||
84 | shladd r18=r17,3,r14 // A | ||
85 | mov r19=NR_syscalls-1 // A | ||
86 | ;; | ||
87 | lfetch [r18] // M0|1 | ||
88 | mov r29=psr // M2 (12 cyc) | ||
89 | // If r17 is a NaT, p6 will be zero | ||
90 | cmp.geu p6,p7=r19,r17 // A (sysnr > 0 && sysnr < 1024+NR_syscalls)? | ||
91 | ;; | ||
92 | mov r21=ar.fpsr // M2 (12 cyc) | ||
93 | tnat.nz p10,p9=r15 // I0 | ||
94 | mov.i r26=ar.pfs // I0 (would stall anyhow due to srlz.d...) | ||
95 | ;; | ||
96 | srlz.d // M0 (forces split-issue) ensure PSR.BE==0 | ||
97 | (p6) ld8 r18=[r18] // M0|1 | ||
98 | nop.i 0 | ||
99 | ;; | ||
100 | nop.m 0 | ||
101 | (p6) tbit.z.unc p8,p0=r18,0 // I0 (dual-issues with "mov b7=r18"!) | ||
102 | nop.i 0 | ||
103 | ;; | ||
104 | (p8) ssm psr.i | ||
105 | (p6) mov b7=r18 // I0 | ||
106 | (p8) br.dptk.many b7 // B | ||
107 | |||
108 | mov r27=ar.rsc // M2 (12 cyc) | ||
109 | /* | ||
110 | * brl.cond doesn't work as intended because the linker would convert this branch | ||
111 | * into a branch to a PLT. Perhaps there will be a way to avoid this with some | ||
112 | * future version of the linker. In the meantime, we just use an indirect branch | ||
113 | * instead. | ||
114 | */ | ||
115 | #ifdef CONFIG_ITANIUM | ||
116 | (p6) add r14=-8,r14 // r14 <- addr of fsys_bubble_down entry | ||
117 | ;; | ||
118 | (p6) ld8 r14=[r14] // r14 <- fsys_bubble_down | ||
119 | ;; | ||
120 | (p6) mov b7=r14 | ||
121 | (p6) br.sptk.many b7 | ||
122 | #else | ||
123 | BRL_COND_FSYS_BUBBLE_DOWN(p6) | ||
124 | #endif | ||
125 | ssm psr.i | ||
126 | mov r10=-1 | ||
127 | (p10) mov r8=EINVAL | ||
128 | (p9) mov r8=ENOSYS | ||
129 | FSYS_RETURN | ||
130 | END(__kernel_syscall_via_epc) | ||
131 | |||
132 | # define ARG0_OFF (16 + IA64_SIGFRAME_ARG0_OFFSET) | 52 | # define ARG0_OFF (16 + IA64_SIGFRAME_ARG0_OFFSET) |
133 | # define ARG1_OFF (16 + IA64_SIGFRAME_ARG1_OFFSET) | 53 | # define ARG1_OFF (16 + IA64_SIGFRAME_ARG1_OFFSET) |
134 | # define ARG2_OFF (16 + IA64_SIGFRAME_ARG2_OFFSET) | 54 | # define ARG2_OFF (16 + IA64_SIGFRAME_ARG2_OFFSET) |
@@ -374,3 +294,92 @@ restore_rbs: | |||
374 | // invala not necessary as that will happen when returning to user-mode | 294 | // invala not necessary as that will happen when returning to user-mode |
375 | br.cond.sptk back_from_restore_rbs | 295 | br.cond.sptk back_from_restore_rbs |
376 | END(__kernel_sigtramp) | 296 | END(__kernel_sigtramp) |
297 | |||
298 | /* | ||
299 | * On entry: | ||
300 | * r11 = saved ar.pfs | ||
301 | * r15 = system call # | ||
302 | * b0 = saved return address | ||
303 | * b6 = return address | ||
304 | * On exit: | ||
305 | * r11 = saved ar.pfs | ||
306 | * r15 = system call # | ||
307 | * b0 = saved return address | ||
308 | * all other "scratch" registers: undefined | ||
309 | * all "preserved" registers: same as on entry | ||
310 | */ | ||
311 | |||
312 | GLOBAL_ENTRY(__kernel_syscall_via_epc) | ||
313 | .prologue | ||
314 | .altrp b6 | ||
315 | .body | ||
316 | { | ||
317 | /* | ||
318 | * Note: the kernel cannot assume that the first two instructions in this | ||
319 | * bundle get executed. The remaining code must be safe even if | ||
320 | * they do not get executed. | ||
321 | */ | ||
322 | adds r17=-1024,r15 // A | ||
323 | mov r10=0 // A default to successful syscall execution | ||
324 | epc // B causes split-issue | ||
325 | } | ||
326 | ;; | ||
327 | RSM_PSR_BE_I(r20, r22) // M2 (5 cyc to srlz.d) | ||
328 | LOAD_FSYSCALL_TABLE(r14) // X | ||
329 | ;; | ||
330 | mov r16=IA64_KR(CURRENT) // M2 (12 cyc) | ||
331 | shladd r18=r17,3,r14 // A | ||
332 | mov r19=NR_syscalls-1 // A | ||
333 | ;; | ||
334 | lfetch [r18] // M0|1 | ||
335 | MOV_FROM_PSR(p0, r29, r8) // M2 (12 cyc) | ||
336 | // If r17 is a NaT, p6 will be zero | ||
337 | cmp.geu p6,p7=r19,r17 // A (sysnr > 0 && sysnr < 1024+NR_syscalls)? | ||
338 | ;; | ||
339 | mov r21=ar.fpsr // M2 (12 cyc) | ||
340 | tnat.nz p10,p9=r15 // I0 | ||
341 | mov.i r26=ar.pfs // I0 (would stall anyhow due to srlz.d...) | ||
342 | ;; | ||
343 | srlz.d // M0 (forces split-issue) ensure PSR.BE==0 | ||
344 | (p6) ld8 r18=[r18] // M0|1 | ||
345 | nop.i 0 | ||
346 | ;; | ||
347 | nop.m 0 | ||
348 | (p6) tbit.z.unc p8,p0=r18,0 // I0 (dual-issues with "mov b7=r18"!) | ||
349 | nop.i 0 | ||
350 | ;; | ||
351 | SSM_PSR_I(p8, p14, r25) | ||
352 | (p6) mov b7=r18 // I0 | ||
353 | (p8) br.dptk.many b7 // B | ||
354 | |||
355 | mov r27=ar.rsc // M2 (12 cyc) | ||
356 | /* | ||
357 | * brl.cond doesn't work as intended because the linker would convert this branch | ||
358 | * into a branch to a PLT. Perhaps there will be a way to avoid this with some | ||
359 | * future version of the linker. In the meantime, we just use an indirect branch | ||
360 | * instead. | ||
361 | */ | ||
362 | #ifdef CONFIG_ITANIUM | ||
363 | (p6) add r14=-8,r14 // r14 <- addr of fsys_bubble_down entry | ||
364 | ;; | ||
365 | (p6) ld8 r14=[r14] // r14 <- fsys_bubble_down | ||
366 | ;; | ||
367 | (p6) mov b7=r14 | ||
368 | (p6) br.sptk.many b7 | ||
369 | #else | ||
370 | BRL_COND_FSYS_BUBBLE_DOWN(p6) | ||
371 | #endif | ||
372 | SSM_PSR_I(p0, p14, r10) | ||
373 | mov r10=-1 | ||
374 | (p10) mov r8=EINVAL | ||
375 | (p9) mov r8=ENOSYS | ||
376 | FSYS_RETURN | ||
377 | |||
378 | #ifdef CONFIG_PARAVIRT | ||
379 | /* | ||
380 | * padd to make the size of this symbol constant | ||
381 | * independent of paravirtualization. | ||
382 | */ | ||
383 | .align PAGE_SIZE / 8 | ||
384 | #endif | ||
385 | END(__kernel_syscall_via_epc) | ||
diff --git a/arch/ia64/kernel/gate.lds.S b/arch/ia64/kernel/gate.lds.S index 3cb1abc00e24..88c64ed47c36 100644 --- a/arch/ia64/kernel/gate.lds.S +++ b/arch/ia64/kernel/gate.lds.S | |||
@@ -7,6 +7,7 @@ | |||
7 | 7 | ||
8 | 8 | ||
9 | #include <asm/system.h> | 9 | #include <asm/system.h> |
10 | #include "paravirt_patchlist.h" | ||
10 | 11 | ||
11 | SECTIONS | 12 | SECTIONS |
12 | { | 13 | { |
@@ -33,21 +34,21 @@ SECTIONS | |||
33 | . = GATE_ADDR + 0x600; | 34 | . = GATE_ADDR + 0x600; |
34 | 35 | ||
35 | .data.patch : { | 36 | .data.patch : { |
36 | __start_gate_mckinley_e9_patchlist = .; | 37 | __paravirt_start_gate_mckinley_e9_patchlist = .; |
37 | *(.data.patch.mckinley_e9) | 38 | *(.data.patch.mckinley_e9) |
38 | __end_gate_mckinley_e9_patchlist = .; | 39 | __paravirt_end_gate_mckinley_e9_patchlist = .; |
39 | 40 | ||
40 | __start_gate_vtop_patchlist = .; | 41 | __paravirt_start_gate_vtop_patchlist = .; |
41 | *(.data.patch.vtop) | 42 | *(.data.patch.vtop) |
42 | __end_gate_vtop_patchlist = .; | 43 | __paravirt_end_gate_vtop_patchlist = .; |
43 | 44 | ||
44 | __start_gate_fsyscall_patchlist = .; | 45 | __paravirt_start_gate_fsyscall_patchlist = .; |
45 | *(.data.patch.fsyscall_table) | 46 | *(.data.patch.fsyscall_table) |
46 | __end_gate_fsyscall_patchlist = .; | 47 | __paravirt_end_gate_fsyscall_patchlist = .; |
47 | 48 | ||
48 | __start_gate_brl_fsys_bubble_down_patchlist = .; | 49 | __paravirt_start_gate_brl_fsys_bubble_down_patchlist = .; |
49 | *(.data.patch.brl_fsys_bubble_down) | 50 | *(.data.patch.brl_fsys_bubble_down) |
50 | __end_gate_brl_fsys_bubble_down_patchlist = .; | 51 | __paravirt_end_gate_brl_fsys_bubble_down_patchlist = .; |
51 | } :readable | 52 | } :readable |
52 | 53 | ||
53 | .IA_64.unwind_info : { *(.IA_64.unwind_info*) } | 54 | .IA_64.unwind_info : { *(.IA_64.unwind_info*) } |
diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S index 59301c472800..23f846de62d5 100644 --- a/arch/ia64/kernel/head.S +++ b/arch/ia64/kernel/head.S | |||
@@ -1050,7 +1050,7 @@ END(ia64_delay_loop) | |||
1050 | * except that the multiplication and the shift are done with 128-bit | 1050 | * except that the multiplication and the shift are done with 128-bit |
1051 | * intermediate precision so that we can produce a full 64-bit result. | 1051 | * intermediate precision so that we can produce a full 64-bit result. |
1052 | */ | 1052 | */ |
1053 | GLOBAL_ENTRY(sched_clock) | 1053 | GLOBAL_ENTRY(ia64_native_sched_clock) |
1054 | addl r8=THIS_CPU(cpu_info) + IA64_CPUINFO_NSEC_PER_CYC_OFFSET,r0 | 1054 | addl r8=THIS_CPU(cpu_info) + IA64_CPUINFO_NSEC_PER_CYC_OFFSET,r0 |
1055 | mov.m r9=ar.itc // fetch cycle-counter (35 cyc) | 1055 | mov.m r9=ar.itc // fetch cycle-counter (35 cyc) |
1056 | ;; | 1056 | ;; |
@@ -1066,7 +1066,13 @@ GLOBAL_ENTRY(sched_clock) | |||
1066 | ;; | 1066 | ;; |
1067 | shrp r8=r9,r8,IA64_NSEC_PER_CYC_SHIFT | 1067 | shrp r8=r9,r8,IA64_NSEC_PER_CYC_SHIFT |
1068 | br.ret.sptk.many rp | 1068 | br.ret.sptk.many rp |
1069 | END(sched_clock) | 1069 | END(ia64_native_sched_clock) |
1070 | #ifndef CONFIG_PARAVIRT | ||
1071 | //unsigned long long | ||
1072 | //sched_clock(void) __attribute__((alias("ia64_native_sched_clock"))); | ||
1073 | .global sched_clock | ||
1074 | sched_clock = ia64_native_sched_clock | ||
1075 | #endif | ||
1070 | 1076 | ||
1071 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 1077 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
1072 | GLOBAL_ENTRY(cycle_to_cputime) | 1078 | GLOBAL_ENTRY(cycle_to_cputime) |
diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S index f675d8e33853..ec9a5fdfa1b9 100644 --- a/arch/ia64/kernel/ivt.S +++ b/arch/ia64/kernel/ivt.S | |||
@@ -804,7 +804,7 @@ ENTRY(break_fault) | |||
804 | /////////////////////////////////////////////////////////////////////// | 804 | /////////////////////////////////////////////////////////////////////// |
805 | st1 [r16]=r0 // M2|3 clear current->thread.on_ustack flag | 805 | st1 [r16]=r0 // M2|3 clear current->thread.on_ustack flag |
806 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 806 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
807 | mov.m r30=ar.itc // M get cycle for accounting | 807 | MOV_FROM_ITC(p0, p14, r30, r18) // M get cycle for accounting |
808 | #else | 808 | #else |
809 | mov b6=r30 // I0 setup syscall handler branch reg early | 809 | mov b6=r30 // I0 setup syscall handler branch reg early |
810 | #endif | 810 | #endif |
diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c index aaa7d901521f..34fe4259a144 100644 --- a/arch/ia64/kernel/module.c +++ b/arch/ia64/kernel/module.c | |||
@@ -446,6 +446,14 @@ module_frob_arch_sections (Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, char *secstrings, | |||
446 | mod->arch.opd = s; | 446 | mod->arch.opd = s; |
447 | else if (strcmp(".IA_64.unwind", secstrings + s->sh_name) == 0) | 447 | else if (strcmp(".IA_64.unwind", secstrings + s->sh_name) == 0) |
448 | mod->arch.unwind = s; | 448 | mod->arch.unwind = s; |
449 | #ifdef CONFIG_PARAVIRT | ||
450 | else if (strcmp(".paravirt_bundles", | ||
451 | secstrings + s->sh_name) == 0) | ||
452 | mod->arch.paravirt_bundles = s; | ||
453 | else if (strcmp(".paravirt_insts", | ||
454 | secstrings + s->sh_name) == 0) | ||
455 | mod->arch.paravirt_insts = s; | ||
456 | #endif | ||
449 | 457 | ||
450 | if (!mod->arch.core_plt || !mod->arch.init_plt || !mod->arch.got || !mod->arch.opd) { | 458 | if (!mod->arch.core_plt || !mod->arch.init_plt || !mod->arch.got || !mod->arch.opd) { |
451 | printk(KERN_ERR "%s: sections missing\n", mod->name); | 459 | printk(KERN_ERR "%s: sections missing\n", mod->name); |
@@ -921,6 +929,30 @@ module_finalize (const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *mo | |||
921 | DEBUGP("%s: init: entry=%p\n", __func__, mod->init); | 929 | DEBUGP("%s: init: entry=%p\n", __func__, mod->init); |
922 | if (mod->arch.unwind) | 930 | if (mod->arch.unwind) |
923 | register_unwind_table(mod); | 931 | register_unwind_table(mod); |
932 | #ifdef CONFIG_PARAVIRT | ||
933 | if (mod->arch.paravirt_bundles) { | ||
934 | struct paravirt_patch_site_bundle *start = | ||
935 | (struct paravirt_patch_site_bundle *) | ||
936 | mod->arch.paravirt_bundles->sh_addr; | ||
937 | struct paravirt_patch_site_bundle *end = | ||
938 | (struct paravirt_patch_site_bundle *) | ||
939 | (mod->arch.paravirt_bundles->sh_addr + | ||
940 | mod->arch.paravirt_bundles->sh_size); | ||
941 | |||
942 | paravirt_patch_apply_bundle(start, end); | ||
943 | } | ||
944 | if (mod->arch.paravirt_insts) { | ||
945 | struct paravirt_patch_site_inst *start = | ||
946 | (struct paravirt_patch_site_inst *) | ||
947 | mod->arch.paravirt_insts->sh_addr; | ||
948 | struct paravirt_patch_site_inst *end = | ||
949 | (struct paravirt_patch_site_inst *) | ||
950 | (mod->arch.paravirt_insts->sh_addr + | ||
951 | mod->arch.paravirt_insts->sh_size); | ||
952 | |||
953 | paravirt_patch_apply_inst(start, end); | ||
954 | } | ||
955 | #endif | ||
924 | return 0; | 956 | return 0; |
925 | } | 957 | } |
926 | 958 | ||
diff --git a/arch/ia64/kernel/paravirt.c b/arch/ia64/kernel/paravirt.c index 9f14c16f6369..a21d7bb9c69c 100644 --- a/arch/ia64/kernel/paravirt.c +++ b/arch/ia64/kernel/paravirt.c | |||
@@ -46,13 +46,23 @@ struct pv_info pv_info = { | |||
46 | * initialization hooks. | 46 | * initialization hooks. |
47 | */ | 47 | */ |
48 | 48 | ||
49 | struct pv_init_ops pv_init_ops; | 49 | static void __init |
50 | ia64_native_patch_branch(unsigned long tag, unsigned long type); | ||
51 | |||
52 | struct pv_init_ops pv_init_ops = | ||
53 | { | ||
54 | #ifdef ASM_SUPPORTED | ||
55 | .patch_bundle = ia64_native_patch_bundle, | ||
56 | #endif | ||
57 | .patch_branch = ia64_native_patch_branch, | ||
58 | }; | ||
50 | 59 | ||
51 | /*************************************************************************** | 60 | /*************************************************************************** |
52 | * pv_cpu_ops | 61 | * pv_cpu_ops |
53 | * intrinsics hooks. | 62 | * intrinsics hooks. |
54 | */ | 63 | */ |
55 | 64 | ||
65 | #ifndef ASM_SUPPORTED | ||
56 | /* ia64_native_xxx are macros so that we have to make them real functions */ | 66 | /* ia64_native_xxx are macros so that we have to make them real functions */ |
57 | 67 | ||
58 | #define DEFINE_VOID_FUNC1(name) \ | 68 | #define DEFINE_VOID_FUNC1(name) \ |
@@ -60,7 +70,14 @@ struct pv_init_ops pv_init_ops; | |||
60 | ia64_native_ ## name ## _func(unsigned long arg) \ | 70 | ia64_native_ ## name ## _func(unsigned long arg) \ |
61 | { \ | 71 | { \ |
62 | ia64_native_ ## name(arg); \ | 72 | ia64_native_ ## name(arg); \ |
63 | } \ | 73 | } |
74 | |||
75 | #define DEFINE_VOID_FUNC1_VOID(name) \ | ||
76 | static void \ | ||
77 | ia64_native_ ## name ## _func(void *arg) \ | ||
78 | { \ | ||
79 | ia64_native_ ## name(arg); \ | ||
80 | } | ||
64 | 81 | ||
65 | #define DEFINE_VOID_FUNC2(name) \ | 82 | #define DEFINE_VOID_FUNC2(name) \ |
66 | static void \ | 83 | static void \ |
@@ -68,7 +85,7 @@ struct pv_init_ops pv_init_ops; | |||
68 | unsigned long arg1) \ | 85 | unsigned long arg1) \ |
69 | { \ | 86 | { \ |
70 | ia64_native_ ## name(arg0, arg1); \ | 87 | ia64_native_ ## name(arg0, arg1); \ |
71 | } \ | 88 | } |
72 | 89 | ||
73 | #define DEFINE_FUNC0(name) \ | 90 | #define DEFINE_FUNC0(name) \ |
74 | static unsigned long \ | 91 | static unsigned long \ |
@@ -84,7 +101,7 @@ struct pv_init_ops pv_init_ops; | |||
84 | return ia64_native_ ## name(arg); \ | 101 | return ia64_native_ ## name(arg); \ |
85 | } \ | 102 | } \ |
86 | 103 | ||
87 | DEFINE_VOID_FUNC1(fc); | 104 | DEFINE_VOID_FUNC1_VOID(fc); |
88 | DEFINE_VOID_FUNC1(intrin_local_irq_restore); | 105 | DEFINE_VOID_FUNC1(intrin_local_irq_restore); |
89 | 106 | ||
90 | DEFINE_VOID_FUNC2(ptcga); | 107 | DEFINE_VOID_FUNC2(ptcga); |
@@ -274,6 +291,266 @@ ia64_native_setreg_func(int regnum, unsigned long val) | |||
274 | break; | 291 | break; |
275 | } | 292 | } |
276 | } | 293 | } |
294 | #else | ||
295 | |||
296 | #define __DEFINE_FUNC(name, code) \ | ||
297 | extern const char ia64_native_ ## name ## _direct_start[]; \ | ||
298 | extern const char ia64_native_ ## name ## _direct_end[]; \ | ||
299 | asm (".align 32\n" \ | ||
300 | ".proc ia64_native_" #name "_func\n" \ | ||
301 | "ia64_native_" #name "_func:\n" \ | ||
302 | "ia64_native_" #name "_direct_start:\n" \ | ||
303 | code \ | ||
304 | "ia64_native_" #name "_direct_end:\n" \ | ||
305 | "br.cond.sptk.many b6\n" \ | ||
306 | ".endp ia64_native_" #name "_func\n") | ||
307 | |||
308 | #define DEFINE_VOID_FUNC0(name, code) \ | ||
309 | extern void \ | ||
310 | ia64_native_ ## name ## _func(void); \ | ||
311 | __DEFINE_FUNC(name, code) | ||
312 | |||
313 | #define DEFINE_VOID_FUNC1(name, code) \ | ||
314 | extern void \ | ||
315 | ia64_native_ ## name ## _func(unsigned long arg); \ | ||
316 | __DEFINE_FUNC(name, code) | ||
317 | |||
318 | #define DEFINE_VOID_FUNC1_VOID(name, code) \ | ||
319 | extern void \ | ||
320 | ia64_native_ ## name ## _func(void *arg); \ | ||
321 | __DEFINE_FUNC(name, code) | ||
322 | |||
323 | #define DEFINE_VOID_FUNC2(name, code) \ | ||
324 | extern void \ | ||
325 | ia64_native_ ## name ## _func(unsigned long arg0, \ | ||
326 | unsigned long arg1); \ | ||
327 | __DEFINE_FUNC(name, code) | ||
328 | |||
329 | #define DEFINE_FUNC0(name, code) \ | ||
330 | extern unsigned long \ | ||
331 | ia64_native_ ## name ## _func(void); \ | ||
332 | __DEFINE_FUNC(name, code) | ||
333 | |||
334 | #define DEFINE_FUNC1(name, type, code) \ | ||
335 | extern unsigned long \ | ||
336 | ia64_native_ ## name ## _func(type arg); \ | ||
337 | __DEFINE_FUNC(name, code) | ||
338 | |||
339 | DEFINE_VOID_FUNC1_VOID(fc, | ||
340 | "fc r8\n"); | ||
341 | DEFINE_VOID_FUNC1(intrin_local_irq_restore, | ||
342 | ";;\n" | ||
343 | " cmp.ne p6, p7 = r8, r0\n" | ||
344 | ";;\n" | ||
345 | "(p6) ssm psr.i\n" | ||
346 | "(p7) rsm psr.i\n" | ||
347 | ";;\n" | ||
348 | "(p6) srlz.d\n"); | ||
349 | |||
350 | DEFINE_VOID_FUNC2(ptcga, | ||
351 | "ptc.ga r8, r9\n"); | ||
352 | DEFINE_VOID_FUNC2(set_rr, | ||
353 | "mov rr[r8] = r9\n"); | ||
354 | |||
355 | /* ia64_native_getreg(_IA64_REG_PSR) & IA64_PSR_I */ | ||
356 | DEFINE_FUNC0(get_psr_i, | ||
357 | "mov r2 = " __stringify(1 << IA64_PSR_I_BIT) "\n" | ||
358 | "mov r8 = psr\n" | ||
359 | ";;\n" | ||
360 | "and r8 = r2, r8\n"); | ||
361 | |||
362 | DEFINE_FUNC1(thash, unsigned long, | ||
363 | "thash r8 = r8\n"); | ||
364 | DEFINE_FUNC1(get_cpuid, int, | ||
365 | "mov r8 = cpuid[r8]\n"); | ||
366 | DEFINE_FUNC1(get_pmd, int, | ||
367 | "mov r8 = pmd[r8]\n"); | ||
368 | DEFINE_FUNC1(get_rr, unsigned long, | ||
369 | "mov r8 = rr[r8]\n"); | ||
370 | |||
371 | DEFINE_VOID_FUNC0(ssm_i, | ||
372 | "ssm psr.i\n"); | ||
373 | DEFINE_VOID_FUNC0(rsm_i, | ||
374 | "rsm psr.i\n"); | ||
375 | |||
376 | extern void | ||
377 | ia64_native_set_rr0_to_rr4_func(unsigned long val0, unsigned long val1, | ||
378 | unsigned long val2, unsigned long val3, | ||
379 | unsigned long val4); | ||
380 | __DEFINE_FUNC(set_rr0_to_rr4, | ||
381 | "mov rr[r0] = r8\n" | ||
382 | "movl r2 = 0x2000000000000000\n" | ||
383 | ";;\n" | ||
384 | "mov rr[r2] = r9\n" | ||
385 | "shl r3 = r2, 1\n" /* movl r3 = 0x4000000000000000 */ | ||
386 | ";;\n" | ||
387 | "add r2 = r2, r3\n" /* movl r2 = 0x6000000000000000 */ | ||
388 | "mov rr[r3] = r10\n" | ||
389 | ";;\n" | ||
390 | "mov rr[r2] = r11\n" | ||
391 | "shl r3 = r3, 1\n" /* movl r3 = 0x8000000000000000 */ | ||
392 | ";;\n" | ||
393 | "mov rr[r3] = r14\n"); | ||
394 | |||
395 | extern unsigned long ia64_native_getreg_func(int regnum); | ||
396 | asm(".global ia64_native_getreg_func\n"); | ||
397 | #define __DEFINE_GET_REG(id, reg) \ | ||
398 | "mov r2 = " __stringify(_IA64_REG_ ## id) "\n" \ | ||
399 | ";;\n" \ | ||
400 | "cmp.eq p6, p0 = r2, r8\n" \ | ||
401 | ";;\n" \ | ||
402 | "(p6) mov r8 = " #reg "\n" \ | ||
403 | "(p6) br.cond.sptk.many b6\n" \ | ||
404 | ";;\n" | ||
405 | #define __DEFINE_GET_AR(id, reg) __DEFINE_GET_REG(AR_ ## id, ar.reg) | ||
406 | #define __DEFINE_GET_CR(id, reg) __DEFINE_GET_REG(CR_ ## id, cr.reg) | ||
407 | |||
408 | __DEFINE_FUNC(getreg, | ||
409 | __DEFINE_GET_REG(GP, gp) | ||
410 | /*__DEFINE_GET_REG(IP, ip)*/ /* returned ip value shouldn't be constant */ | ||
411 | __DEFINE_GET_REG(PSR, psr) | ||
412 | __DEFINE_GET_REG(TP, tp) | ||
413 | __DEFINE_GET_REG(SP, sp) | ||
414 | |||
415 | __DEFINE_GET_REG(AR_KR0, ar0) | ||
416 | __DEFINE_GET_REG(AR_KR1, ar1) | ||
417 | __DEFINE_GET_REG(AR_KR2, ar2) | ||
418 | __DEFINE_GET_REG(AR_KR3, ar3) | ||
419 | __DEFINE_GET_REG(AR_KR4, ar4) | ||
420 | __DEFINE_GET_REG(AR_KR5, ar5) | ||
421 | __DEFINE_GET_REG(AR_KR6, ar6) | ||
422 | __DEFINE_GET_REG(AR_KR7, ar7) | ||
423 | __DEFINE_GET_AR(RSC, rsc) | ||
424 | __DEFINE_GET_AR(BSP, bsp) | ||
425 | __DEFINE_GET_AR(BSPSTORE, bspstore) | ||
426 | __DEFINE_GET_AR(RNAT, rnat) | ||
427 | __DEFINE_GET_AR(FCR, fcr) | ||
428 | __DEFINE_GET_AR(EFLAG, eflag) | ||
429 | __DEFINE_GET_AR(CSD, csd) | ||
430 | __DEFINE_GET_AR(SSD, ssd) | ||
431 | __DEFINE_GET_REG(AR_CFLAG, ar27) | ||
432 | __DEFINE_GET_AR(FSR, fsr) | ||
433 | __DEFINE_GET_AR(FIR, fir) | ||
434 | __DEFINE_GET_AR(FDR, fdr) | ||
435 | __DEFINE_GET_AR(CCV, ccv) | ||
436 | __DEFINE_GET_AR(UNAT, unat) | ||
437 | __DEFINE_GET_AR(FPSR, fpsr) | ||
438 | __DEFINE_GET_AR(ITC, itc) | ||
439 | __DEFINE_GET_AR(PFS, pfs) | ||
440 | __DEFINE_GET_AR(LC, lc) | ||
441 | __DEFINE_GET_AR(EC, ec) | ||
442 | |||
443 | __DEFINE_GET_CR(DCR, dcr) | ||
444 | __DEFINE_GET_CR(ITM, itm) | ||
445 | __DEFINE_GET_CR(IVA, iva) | ||
446 | __DEFINE_GET_CR(PTA, pta) | ||
447 | __DEFINE_GET_CR(IPSR, ipsr) | ||
448 | __DEFINE_GET_CR(ISR, isr) | ||
449 | __DEFINE_GET_CR(IIP, iip) | ||
450 | __DEFINE_GET_CR(IFA, ifa) | ||
451 | __DEFINE_GET_CR(ITIR, itir) | ||
452 | __DEFINE_GET_CR(IIPA, iipa) | ||
453 | __DEFINE_GET_CR(IFS, ifs) | ||
454 | __DEFINE_GET_CR(IIM, iim) | ||
455 | __DEFINE_GET_CR(IHA, iha) | ||
456 | __DEFINE_GET_CR(LID, lid) | ||
457 | __DEFINE_GET_CR(IVR, ivr) | ||
458 | __DEFINE_GET_CR(TPR, tpr) | ||
459 | __DEFINE_GET_CR(EOI, eoi) | ||
460 | __DEFINE_GET_CR(IRR0, irr0) | ||
461 | __DEFINE_GET_CR(IRR1, irr1) | ||
462 | __DEFINE_GET_CR(IRR2, irr2) | ||
463 | __DEFINE_GET_CR(IRR3, irr3) | ||
464 | __DEFINE_GET_CR(ITV, itv) | ||
465 | __DEFINE_GET_CR(PMV, pmv) | ||
466 | __DEFINE_GET_CR(CMCV, cmcv) | ||
467 | __DEFINE_GET_CR(LRR0, lrr0) | ||
468 | __DEFINE_GET_CR(LRR1, lrr1) | ||
469 | |||
470 | "mov r8 = -1\n" /* unsupported case */ | ||
471 | ); | ||
472 | |||
473 | extern void ia64_native_setreg_func(int regnum, unsigned long val); | ||
474 | asm(".global ia64_native_setreg_func\n"); | ||
475 | #define __DEFINE_SET_REG(id, reg) \ | ||
476 | "mov r2 = " __stringify(_IA64_REG_ ## id) "\n" \ | ||
477 | ";;\n" \ | ||
478 | "cmp.eq p6, p0 = r2, r9\n" \ | ||
479 | ";;\n" \ | ||
480 | "(p6) mov " #reg " = r8\n" \ | ||
481 | "(p6) br.cond.sptk.many b6\n" \ | ||
482 | ";;\n" | ||
483 | #define __DEFINE_SET_AR(id, reg) __DEFINE_SET_REG(AR_ ## id, ar.reg) | ||
484 | #define __DEFINE_SET_CR(id, reg) __DEFINE_SET_REG(CR_ ## id, cr.reg) | ||
485 | __DEFINE_FUNC(setreg, | ||
486 | "mov r2 = " __stringify(_IA64_REG_PSR_L) "\n" | ||
487 | ";;\n" | ||
488 | "cmp.eq p6, p0 = r2, r9\n" | ||
489 | ";;\n" | ||
490 | "(p6) mov psr.l = r8\n" | ||
491 | #ifdef HAVE_SERIALIZE_DIRECTIVE | ||
492 | ".serialize.data\n" | ||
493 | #endif | ||
494 | "(p6) br.cond.sptk.many b6\n" | ||
495 | __DEFINE_SET_REG(GP, gp) | ||
496 | __DEFINE_SET_REG(SP, sp) | ||
497 | |||
498 | __DEFINE_SET_REG(AR_KR0, ar0) | ||
499 | __DEFINE_SET_REG(AR_KR1, ar1) | ||
500 | __DEFINE_SET_REG(AR_KR2, ar2) | ||
501 | __DEFINE_SET_REG(AR_KR3, ar3) | ||
502 | __DEFINE_SET_REG(AR_KR4, ar4) | ||
503 | __DEFINE_SET_REG(AR_KR5, ar5) | ||
504 | __DEFINE_SET_REG(AR_KR6, ar6) | ||
505 | __DEFINE_SET_REG(AR_KR7, ar7) | ||
506 | __DEFINE_SET_AR(RSC, rsc) | ||
507 | __DEFINE_SET_AR(BSP, bsp) | ||
508 | __DEFINE_SET_AR(BSPSTORE, bspstore) | ||
509 | __DEFINE_SET_AR(RNAT, rnat) | ||
510 | __DEFINE_SET_AR(FCR, fcr) | ||
511 | __DEFINE_SET_AR(EFLAG, eflag) | ||
512 | __DEFINE_SET_AR(CSD, csd) | ||
513 | __DEFINE_SET_AR(SSD, ssd) | ||
514 | __DEFINE_SET_REG(AR_CFLAG, ar27) | ||
515 | __DEFINE_SET_AR(FSR, fsr) | ||
516 | __DEFINE_SET_AR(FIR, fir) | ||
517 | __DEFINE_SET_AR(FDR, fdr) | ||
518 | __DEFINE_SET_AR(CCV, ccv) | ||
519 | __DEFINE_SET_AR(UNAT, unat) | ||
520 | __DEFINE_SET_AR(FPSR, fpsr) | ||
521 | __DEFINE_SET_AR(ITC, itc) | ||
522 | __DEFINE_SET_AR(PFS, pfs) | ||
523 | __DEFINE_SET_AR(LC, lc) | ||
524 | __DEFINE_SET_AR(EC, ec) | ||
525 | |||
526 | __DEFINE_SET_CR(DCR, dcr) | ||
527 | __DEFINE_SET_CR(ITM, itm) | ||
528 | __DEFINE_SET_CR(IVA, iva) | ||
529 | __DEFINE_SET_CR(PTA, pta) | ||
530 | __DEFINE_SET_CR(IPSR, ipsr) | ||
531 | __DEFINE_SET_CR(ISR, isr) | ||
532 | __DEFINE_SET_CR(IIP, iip) | ||
533 | __DEFINE_SET_CR(IFA, ifa) | ||
534 | __DEFINE_SET_CR(ITIR, itir) | ||
535 | __DEFINE_SET_CR(IIPA, iipa) | ||
536 | __DEFINE_SET_CR(IFS, ifs) | ||
537 | __DEFINE_SET_CR(IIM, iim) | ||
538 | __DEFINE_SET_CR(IHA, iha) | ||
539 | __DEFINE_SET_CR(LID, lid) | ||
540 | __DEFINE_SET_CR(IVR, ivr) | ||
541 | __DEFINE_SET_CR(TPR, tpr) | ||
542 | __DEFINE_SET_CR(EOI, eoi) | ||
543 | __DEFINE_SET_CR(IRR0, irr0) | ||
544 | __DEFINE_SET_CR(IRR1, irr1) | ||
545 | __DEFINE_SET_CR(IRR2, irr2) | ||
546 | __DEFINE_SET_CR(IRR3, irr3) | ||
547 | __DEFINE_SET_CR(ITV, itv) | ||
548 | __DEFINE_SET_CR(PMV, pmv) | ||
549 | __DEFINE_SET_CR(CMCV, cmcv) | ||
550 | __DEFINE_SET_CR(LRR0, lrr0) | ||
551 | __DEFINE_SET_CR(LRR1, lrr1) | ||
552 | ); | ||
553 | #endif | ||
277 | 554 | ||
278 | struct pv_cpu_ops pv_cpu_ops = { | 555 | struct pv_cpu_ops pv_cpu_ops = { |
279 | .fc = ia64_native_fc_func, | 556 | .fc = ia64_native_fc_func, |
@@ -366,4 +643,258 @@ ia64_native_do_steal_accounting(unsigned long *new_itm) | |||
366 | 643 | ||
367 | struct pv_time_ops pv_time_ops = { | 644 | struct pv_time_ops pv_time_ops = { |
368 | .do_steal_accounting = ia64_native_do_steal_accounting, | 645 | .do_steal_accounting = ia64_native_do_steal_accounting, |
646 | .sched_clock = ia64_native_sched_clock, | ||
647 | }; | ||
648 | |||
649 | /*************************************************************************** | ||
650 | * binary pacthing | ||
651 | * pv_init_ops.patch_bundle | ||
652 | */ | ||
653 | |||
654 | #ifdef ASM_SUPPORTED | ||
655 | #define IA64_NATIVE_PATCH_DEFINE_GET_REG(name, reg) \ | ||
656 | __DEFINE_FUNC(get_ ## name, \ | ||
657 | ";;\n" \ | ||
658 | "mov r8 = " #reg "\n" \ | ||
659 | ";;\n") | ||
660 | |||
661 | #define IA64_NATIVE_PATCH_DEFINE_SET_REG(name, reg) \ | ||
662 | __DEFINE_FUNC(set_ ## name, \ | ||
663 | ";;\n" \ | ||
664 | "mov " #reg " = r8\n" \ | ||
665 | ";;\n") | ||
666 | |||
667 | #define IA64_NATIVE_PATCH_DEFINE_REG(name, reg) \ | ||
668 | IA64_NATIVE_PATCH_DEFINE_GET_REG(name, reg); \ | ||
669 | IA64_NATIVE_PATCH_DEFINE_SET_REG(name, reg) \ | ||
670 | |||
671 | #define IA64_NATIVE_PATCH_DEFINE_AR(name, reg) \ | ||
672 | IA64_NATIVE_PATCH_DEFINE_REG(ar_ ## name, ar.reg) | ||
673 | |||
674 | #define IA64_NATIVE_PATCH_DEFINE_CR(name, reg) \ | ||
675 | IA64_NATIVE_PATCH_DEFINE_REG(cr_ ## name, cr.reg) | ||
676 | |||
677 | |||
678 | IA64_NATIVE_PATCH_DEFINE_GET_REG(psr, psr); | ||
679 | IA64_NATIVE_PATCH_DEFINE_GET_REG(tp, tp); | ||
680 | |||
681 | /* IA64_NATIVE_PATCH_DEFINE_SET_REG(psr_l, psr.l); */ | ||
682 | __DEFINE_FUNC(set_psr_l, | ||
683 | ";;\n" | ||
684 | "mov psr.l = r8\n" | ||
685 | #ifdef HAVE_SERIALIZE_DIRECTIVE | ||
686 | ".serialize.data\n" | ||
687 | #endif | ||
688 | ";;\n"); | ||
689 | |||
690 | IA64_NATIVE_PATCH_DEFINE_REG(gp, gp); | ||
691 | IA64_NATIVE_PATCH_DEFINE_REG(sp, sp); | ||
692 | |||
693 | IA64_NATIVE_PATCH_DEFINE_REG(kr0, ar0); | ||
694 | IA64_NATIVE_PATCH_DEFINE_REG(kr1, ar1); | ||
695 | IA64_NATIVE_PATCH_DEFINE_REG(kr2, ar2); | ||
696 | IA64_NATIVE_PATCH_DEFINE_REG(kr3, ar3); | ||
697 | IA64_NATIVE_PATCH_DEFINE_REG(kr4, ar4); | ||
698 | IA64_NATIVE_PATCH_DEFINE_REG(kr5, ar5); | ||
699 | IA64_NATIVE_PATCH_DEFINE_REG(kr6, ar6); | ||
700 | IA64_NATIVE_PATCH_DEFINE_REG(kr7, ar7); | ||
701 | |||
702 | IA64_NATIVE_PATCH_DEFINE_AR(rsc, rsc); | ||
703 | IA64_NATIVE_PATCH_DEFINE_AR(bsp, bsp); | ||
704 | IA64_NATIVE_PATCH_DEFINE_AR(bspstore, bspstore); | ||
705 | IA64_NATIVE_PATCH_DEFINE_AR(rnat, rnat); | ||
706 | IA64_NATIVE_PATCH_DEFINE_AR(fcr, fcr); | ||
707 | IA64_NATIVE_PATCH_DEFINE_AR(eflag, eflag); | ||
708 | IA64_NATIVE_PATCH_DEFINE_AR(csd, csd); | ||
709 | IA64_NATIVE_PATCH_DEFINE_AR(ssd, ssd); | ||
710 | IA64_NATIVE_PATCH_DEFINE_REG(ar27, ar27); | ||
711 | IA64_NATIVE_PATCH_DEFINE_AR(fsr, fsr); | ||
712 | IA64_NATIVE_PATCH_DEFINE_AR(fir, fir); | ||
713 | IA64_NATIVE_PATCH_DEFINE_AR(fdr, fdr); | ||
714 | IA64_NATIVE_PATCH_DEFINE_AR(ccv, ccv); | ||
715 | IA64_NATIVE_PATCH_DEFINE_AR(unat, unat); | ||
716 | IA64_NATIVE_PATCH_DEFINE_AR(fpsr, fpsr); | ||
717 | IA64_NATIVE_PATCH_DEFINE_AR(itc, itc); | ||
718 | IA64_NATIVE_PATCH_DEFINE_AR(pfs, pfs); | ||
719 | IA64_NATIVE_PATCH_DEFINE_AR(lc, lc); | ||
720 | IA64_NATIVE_PATCH_DEFINE_AR(ec, ec); | ||
721 | |||
722 | IA64_NATIVE_PATCH_DEFINE_CR(dcr, dcr); | ||
723 | IA64_NATIVE_PATCH_DEFINE_CR(itm, itm); | ||
724 | IA64_NATIVE_PATCH_DEFINE_CR(iva, iva); | ||
725 | IA64_NATIVE_PATCH_DEFINE_CR(pta, pta); | ||
726 | IA64_NATIVE_PATCH_DEFINE_CR(ipsr, ipsr); | ||
727 | IA64_NATIVE_PATCH_DEFINE_CR(isr, isr); | ||
728 | IA64_NATIVE_PATCH_DEFINE_CR(iip, iip); | ||
729 | IA64_NATIVE_PATCH_DEFINE_CR(ifa, ifa); | ||
730 | IA64_NATIVE_PATCH_DEFINE_CR(itir, itir); | ||
731 | IA64_NATIVE_PATCH_DEFINE_CR(iipa, iipa); | ||
732 | IA64_NATIVE_PATCH_DEFINE_CR(ifs, ifs); | ||
733 | IA64_NATIVE_PATCH_DEFINE_CR(iim, iim); | ||
734 | IA64_NATIVE_PATCH_DEFINE_CR(iha, iha); | ||
735 | IA64_NATIVE_PATCH_DEFINE_CR(lid, lid); | ||
736 | IA64_NATIVE_PATCH_DEFINE_CR(ivr, ivr); | ||
737 | IA64_NATIVE_PATCH_DEFINE_CR(tpr, tpr); | ||
738 | IA64_NATIVE_PATCH_DEFINE_CR(eoi, eoi); | ||
739 | IA64_NATIVE_PATCH_DEFINE_CR(irr0, irr0); | ||
740 | IA64_NATIVE_PATCH_DEFINE_CR(irr1, irr1); | ||
741 | IA64_NATIVE_PATCH_DEFINE_CR(irr2, irr2); | ||
742 | IA64_NATIVE_PATCH_DEFINE_CR(irr3, irr3); | ||
743 | IA64_NATIVE_PATCH_DEFINE_CR(itv, itv); | ||
744 | IA64_NATIVE_PATCH_DEFINE_CR(pmv, pmv); | ||
745 | IA64_NATIVE_PATCH_DEFINE_CR(cmcv, cmcv); | ||
746 | IA64_NATIVE_PATCH_DEFINE_CR(lrr0, lrr0); | ||
747 | IA64_NATIVE_PATCH_DEFINE_CR(lrr1, lrr1); | ||
748 | |||
749 | static const struct paravirt_patch_bundle_elem ia64_native_patch_bundle_elems[] | ||
750 | __initdata_or_module = | ||
751 | { | ||
752 | #define IA64_NATIVE_PATCH_BUNDLE_ELEM(name, type) \ | ||
753 | { \ | ||
754 | (void*)ia64_native_ ## name ## _direct_start, \ | ||
755 | (void*)ia64_native_ ## name ## _direct_end, \ | ||
756 | PARAVIRT_PATCH_TYPE_ ## type, \ | ||
757 | } | ||
758 | |||
759 | IA64_NATIVE_PATCH_BUNDLE_ELEM(fc, FC), | ||
760 | IA64_NATIVE_PATCH_BUNDLE_ELEM(thash, THASH), | ||
761 | IA64_NATIVE_PATCH_BUNDLE_ELEM(get_cpuid, GET_CPUID), | ||
762 | IA64_NATIVE_PATCH_BUNDLE_ELEM(get_pmd, GET_PMD), | ||
763 | IA64_NATIVE_PATCH_BUNDLE_ELEM(ptcga, PTCGA), | ||
764 | IA64_NATIVE_PATCH_BUNDLE_ELEM(get_rr, GET_RR), | ||
765 | IA64_NATIVE_PATCH_BUNDLE_ELEM(set_rr, SET_RR), | ||
766 | IA64_NATIVE_PATCH_BUNDLE_ELEM(set_rr0_to_rr4, SET_RR0_TO_RR4), | ||
767 | IA64_NATIVE_PATCH_BUNDLE_ELEM(ssm_i, SSM_I), | ||
768 | IA64_NATIVE_PATCH_BUNDLE_ELEM(rsm_i, RSM_I), | ||
769 | IA64_NATIVE_PATCH_BUNDLE_ELEM(get_psr_i, GET_PSR_I), | ||
770 | IA64_NATIVE_PATCH_BUNDLE_ELEM(intrin_local_irq_restore, | ||
771 | INTRIN_LOCAL_IRQ_RESTORE), | ||
772 | |||
773 | #define IA64_NATIVE_PATCH_BUNDLE_ELEM_GETREG(name, reg) \ | ||
774 | { \ | ||
775 | (void*)ia64_native_get_ ## name ## _direct_start, \ | ||
776 | (void*)ia64_native_get_ ## name ## _direct_end, \ | ||
777 | PARAVIRT_PATCH_TYPE_GETREG + _IA64_REG_ ## reg, \ | ||
778 | } | ||
779 | |||
780 | #define IA64_NATIVE_PATCH_BUNDLE_ELEM_SETREG(name, reg) \ | ||
781 | { \ | ||
782 | (void*)ia64_native_set_ ## name ## _direct_start, \ | ||
783 | (void*)ia64_native_set_ ## name ## _direct_end, \ | ||
784 | PARAVIRT_PATCH_TYPE_SETREG + _IA64_REG_ ## reg, \ | ||
785 | } | ||
786 | |||
787 | #define IA64_NATIVE_PATCH_BUNDLE_ELEM_REG(name, reg) \ | ||
788 | IA64_NATIVE_PATCH_BUNDLE_ELEM_GETREG(name, reg), \ | ||
789 | IA64_NATIVE_PATCH_BUNDLE_ELEM_SETREG(name, reg) \ | ||
790 | |||
791 | #define IA64_NATIVE_PATCH_BUNDLE_ELEM_AR(name, reg) \ | ||
792 | IA64_NATIVE_PATCH_BUNDLE_ELEM_REG(ar_ ## name, AR_ ## reg) | ||
793 | |||
794 | #define IA64_NATIVE_PATCH_BUNDLE_ELEM_CR(name, reg) \ | ||
795 | IA64_NATIVE_PATCH_BUNDLE_ELEM_REG(cr_ ## name, CR_ ## reg) | ||
796 | |||
797 | IA64_NATIVE_PATCH_BUNDLE_ELEM_GETREG(psr, PSR), | ||
798 | IA64_NATIVE_PATCH_BUNDLE_ELEM_GETREG(tp, TP), | ||
799 | |||
800 | IA64_NATIVE_PATCH_BUNDLE_ELEM_SETREG(psr_l, PSR_L), | ||
801 | |||
802 | IA64_NATIVE_PATCH_BUNDLE_ELEM_REG(gp, GP), | ||
803 | IA64_NATIVE_PATCH_BUNDLE_ELEM_REG(sp, SP), | ||
804 | |||
805 | IA64_NATIVE_PATCH_BUNDLE_ELEM_REG(kr0, AR_KR0), | ||
806 | IA64_NATIVE_PATCH_BUNDLE_ELEM_REG(kr1, AR_KR1), | ||
807 | IA64_NATIVE_PATCH_BUNDLE_ELEM_REG(kr2, AR_KR2), | ||
808 | IA64_NATIVE_PATCH_BUNDLE_ELEM_REG(kr3, AR_KR3), | ||
809 | IA64_NATIVE_PATCH_BUNDLE_ELEM_REG(kr4, AR_KR4), | ||
810 | IA64_NATIVE_PATCH_BUNDLE_ELEM_REG(kr5, AR_KR5), | ||
811 | IA64_NATIVE_PATCH_BUNDLE_ELEM_REG(kr6, AR_KR6), | ||
812 | IA64_NATIVE_PATCH_BUNDLE_ELEM_REG(kr7, AR_KR7), | ||
813 | |||
814 | IA64_NATIVE_PATCH_BUNDLE_ELEM_AR(rsc, RSC), | ||
815 | IA64_NATIVE_PATCH_BUNDLE_ELEM_AR(bsp, BSP), | ||
816 | IA64_NATIVE_PATCH_BUNDLE_ELEM_AR(bspstore, BSPSTORE), | ||
817 | IA64_NATIVE_PATCH_BUNDLE_ELEM_AR(rnat, RNAT), | ||
818 | IA64_NATIVE_PATCH_BUNDLE_ELEM_AR(fcr, FCR), | ||
819 | IA64_NATIVE_PATCH_BUNDLE_ELEM_AR(eflag, EFLAG), | ||
820 | IA64_NATIVE_PATCH_BUNDLE_ELEM_AR(csd, CSD), | ||
821 | IA64_NATIVE_PATCH_BUNDLE_ELEM_AR(ssd, SSD), | ||
822 | IA64_NATIVE_PATCH_BUNDLE_ELEM_REG(ar27, AR_CFLAG), | ||
823 | IA64_NATIVE_PATCH_BUNDLE_ELEM_AR(fsr, FSR), | ||
824 | IA64_NATIVE_PATCH_BUNDLE_ELEM_AR(fir, FIR), | ||
825 | IA64_NATIVE_PATCH_BUNDLE_ELEM_AR(fdr, FDR), | ||
826 | IA64_NATIVE_PATCH_BUNDLE_ELEM_AR(ccv, CCV), | ||
827 | IA64_NATIVE_PATCH_BUNDLE_ELEM_AR(unat, UNAT), | ||
828 | IA64_NATIVE_PATCH_BUNDLE_ELEM_AR(fpsr, FPSR), | ||
829 | IA64_NATIVE_PATCH_BUNDLE_ELEM_AR(itc, ITC), | ||
830 | IA64_NATIVE_PATCH_BUNDLE_ELEM_AR(pfs, PFS), | ||
831 | IA64_NATIVE_PATCH_BUNDLE_ELEM_AR(lc, LC), | ||
832 | IA64_NATIVE_PATCH_BUNDLE_ELEM_AR(ec, EC), | ||
833 | |||
834 | IA64_NATIVE_PATCH_BUNDLE_ELEM_CR(dcr, DCR), | ||
835 | IA64_NATIVE_PATCH_BUNDLE_ELEM_CR(itm, ITM), | ||
836 | IA64_NATIVE_PATCH_BUNDLE_ELEM_CR(iva, IVA), | ||
837 | IA64_NATIVE_PATCH_BUNDLE_ELEM_CR(pta, PTA), | ||
838 | IA64_NATIVE_PATCH_BUNDLE_ELEM_CR(ipsr, IPSR), | ||
839 | IA64_NATIVE_PATCH_BUNDLE_ELEM_CR(isr, ISR), | ||
840 | IA64_NATIVE_PATCH_BUNDLE_ELEM_CR(iip, IIP), | ||
841 | IA64_NATIVE_PATCH_BUNDLE_ELEM_CR(ifa, IFA), | ||
842 | IA64_NATIVE_PATCH_BUNDLE_ELEM_CR(itir, ITIR), | ||
843 | IA64_NATIVE_PATCH_BUNDLE_ELEM_CR(iipa, IIPA), | ||
844 | IA64_NATIVE_PATCH_BUNDLE_ELEM_CR(ifs, IFS), | ||
845 | IA64_NATIVE_PATCH_BUNDLE_ELEM_CR(iim, IIM), | ||
846 | IA64_NATIVE_PATCH_BUNDLE_ELEM_CR(iha, IHA), | ||
847 | IA64_NATIVE_PATCH_BUNDLE_ELEM_CR(lid, LID), | ||
848 | IA64_NATIVE_PATCH_BUNDLE_ELEM_CR(ivr, IVR), | ||
849 | IA64_NATIVE_PATCH_BUNDLE_ELEM_CR(tpr, TPR), | ||
850 | IA64_NATIVE_PATCH_BUNDLE_ELEM_CR(eoi, EOI), | ||
851 | IA64_NATIVE_PATCH_BUNDLE_ELEM_CR(irr0, IRR0), | ||
852 | IA64_NATIVE_PATCH_BUNDLE_ELEM_CR(irr1, IRR1), | ||
853 | IA64_NATIVE_PATCH_BUNDLE_ELEM_CR(irr2, IRR2), | ||
854 | IA64_NATIVE_PATCH_BUNDLE_ELEM_CR(irr3, IRR3), | ||
855 | IA64_NATIVE_PATCH_BUNDLE_ELEM_CR(itv, ITV), | ||
856 | IA64_NATIVE_PATCH_BUNDLE_ELEM_CR(pmv, PMV), | ||
857 | IA64_NATIVE_PATCH_BUNDLE_ELEM_CR(cmcv, CMCV), | ||
858 | IA64_NATIVE_PATCH_BUNDLE_ELEM_CR(lrr0, LRR0), | ||
859 | IA64_NATIVE_PATCH_BUNDLE_ELEM_CR(lrr1, LRR1), | ||
369 | }; | 860 | }; |
861 | |||
862 | unsigned long __init_or_module | ||
863 | ia64_native_patch_bundle(void *sbundle, void *ebundle, unsigned long type) | ||
864 | { | ||
865 | const unsigned long nelems = sizeof(ia64_native_patch_bundle_elems) / | ||
866 | sizeof(ia64_native_patch_bundle_elems[0]); | ||
867 | |||
868 | return __paravirt_patch_apply_bundle(sbundle, ebundle, type, | ||
869 | ia64_native_patch_bundle_elems, | ||
870 | nelems, NULL); | ||
871 | } | ||
872 | #endif /* ASM_SUPPOTED */ | ||
873 | |||
874 | extern const char ia64_native_switch_to[]; | ||
875 | extern const char ia64_native_leave_syscall[]; | ||
876 | extern const char ia64_native_work_processed_syscall[]; | ||
877 | extern const char ia64_native_leave_kernel[]; | ||
878 | |||
879 | const struct paravirt_patch_branch_target ia64_native_branch_target[] | ||
880 | __initconst = { | ||
881 | #define PARAVIRT_BR_TARGET(name, type) \ | ||
882 | { \ | ||
883 | ia64_native_ ## name, \ | ||
884 | PARAVIRT_PATCH_TYPE_BR_ ## type, \ | ||
885 | } | ||
886 | PARAVIRT_BR_TARGET(switch_to, SWITCH_TO), | ||
887 | PARAVIRT_BR_TARGET(leave_syscall, LEAVE_SYSCALL), | ||
888 | PARAVIRT_BR_TARGET(work_processed_syscall, WORK_PROCESSED_SYSCALL), | ||
889 | PARAVIRT_BR_TARGET(leave_kernel, LEAVE_KERNEL), | ||
890 | }; | ||
891 | |||
892 | static void __init | ||
893 | ia64_native_patch_branch(unsigned long tag, unsigned long type) | ||
894 | { | ||
895 | const unsigned long nelem = | ||
896 | sizeof(ia64_native_branch_target) / | ||
897 | sizeof(ia64_native_branch_target[0]); | ||
898 | __paravirt_patch_apply_branch(tag, type, | ||
899 | ia64_native_branch_target, nelem); | ||
900 | } | ||
diff --git a/arch/ia64/kernel/paravirt_patch.c b/arch/ia64/kernel/paravirt_patch.c new file mode 100644 index 000000000000..bfdfef1b1ffd --- /dev/null +++ b/arch/ia64/kernel/paravirt_patch.c | |||
@@ -0,0 +1,514 @@ | |||
1 | /****************************************************************************** | ||
2 | * linux/arch/ia64/xen/paravirt_patch.c | ||
3 | * | ||
4 | * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> | ||
5 | * VA Linux Systems Japan K.K. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/init.h> | ||
24 | #include <asm/intrinsics.h> | ||
25 | #include <asm/kprobes.h> | ||
26 | #include <asm/paravirt.h> | ||
27 | #include <asm/paravirt_patch.h> | ||
28 | |||
29 | typedef union ia64_inst { | ||
30 | struct { | ||
31 | unsigned long long qp : 6; | ||
32 | unsigned long long : 31; | ||
33 | unsigned long long opcode : 4; | ||
34 | unsigned long long reserved : 23; | ||
35 | } generic; | ||
36 | unsigned long long l; | ||
37 | } ia64_inst_t; | ||
38 | |||
39 | /* | ||
40 | * flush_icache_range() can't be used here. | ||
41 | * we are here before cpu_init() which initializes | ||
42 | * ia64_i_cache_stride_shift. flush_icache_range() uses it. | ||
43 | */ | ||
44 | void __init_or_module | ||
45 | paravirt_flush_i_cache_range(const void *instr, unsigned long size) | ||
46 | { | ||
47 | extern void paravirt_fc_i(const void *addr); | ||
48 | unsigned long i; | ||
49 | |||
50 | for (i = 0; i < size; i += sizeof(bundle_t)) | ||
51 | paravirt_fc_i(instr + i); | ||
52 | } | ||
53 | |||
54 | bundle_t* __init_or_module | ||
55 | paravirt_get_bundle(unsigned long tag) | ||
56 | { | ||
57 | return (bundle_t *)(tag & ~3UL); | ||
58 | } | ||
59 | |||
60 | unsigned long __init_or_module | ||
61 | paravirt_get_slot(unsigned long tag) | ||
62 | { | ||
63 | return tag & 3UL; | ||
64 | } | ||
65 | |||
66 | unsigned long __init_or_module | ||
67 | paravirt_get_num_inst(unsigned long stag, unsigned long etag) | ||
68 | { | ||
69 | bundle_t *sbundle = paravirt_get_bundle(stag); | ||
70 | unsigned long sslot = paravirt_get_slot(stag); | ||
71 | bundle_t *ebundle = paravirt_get_bundle(etag); | ||
72 | unsigned long eslot = paravirt_get_slot(etag); | ||
73 | |||
74 | return (ebundle - sbundle) * 3 + eslot - sslot + 1; | ||
75 | } | ||
76 | |||
77 | unsigned long __init_or_module | ||
78 | paravirt_get_next_tag(unsigned long tag) | ||
79 | { | ||
80 | unsigned long slot = paravirt_get_slot(tag); | ||
81 | |||
82 | switch (slot) { | ||
83 | case 0: | ||
84 | case 1: | ||
85 | return tag + 1; | ||
86 | case 2: { | ||
87 | bundle_t *bundle = paravirt_get_bundle(tag); | ||
88 | return (unsigned long)(bundle + 1); | ||
89 | } | ||
90 | default: | ||
91 | BUG(); | ||
92 | } | ||
93 | /* NOTREACHED */ | ||
94 | } | ||
95 | |||
96 | ia64_inst_t __init_or_module | ||
97 | paravirt_read_slot0(const bundle_t *bundle) | ||
98 | { | ||
99 | ia64_inst_t inst; | ||
100 | inst.l = bundle->quad0.slot0; | ||
101 | return inst; | ||
102 | } | ||
103 | |||
104 | ia64_inst_t __init_or_module | ||
105 | paravirt_read_slot1(const bundle_t *bundle) | ||
106 | { | ||
107 | ia64_inst_t inst; | ||
108 | inst.l = bundle->quad0.slot1_p0 | | ||
109 | ((unsigned long long)bundle->quad1.slot1_p1 << 18UL); | ||
110 | return inst; | ||
111 | } | ||
112 | |||
113 | ia64_inst_t __init_or_module | ||
114 | paravirt_read_slot2(const bundle_t *bundle) | ||
115 | { | ||
116 | ia64_inst_t inst; | ||
117 | inst.l = bundle->quad1.slot2; | ||
118 | return inst; | ||
119 | } | ||
120 | |||
121 | ia64_inst_t __init_or_module | ||
122 | paravirt_read_inst(unsigned long tag) | ||
123 | { | ||
124 | bundle_t *bundle = paravirt_get_bundle(tag); | ||
125 | unsigned long slot = paravirt_get_slot(tag); | ||
126 | |||
127 | switch (slot) { | ||
128 | case 0: | ||
129 | return paravirt_read_slot0(bundle); | ||
130 | case 1: | ||
131 | return paravirt_read_slot1(bundle); | ||
132 | case 2: | ||
133 | return paravirt_read_slot2(bundle); | ||
134 | default: | ||
135 | BUG(); | ||
136 | } | ||
137 | /* NOTREACHED */ | ||
138 | } | ||
139 | |||
140 | void __init_or_module | ||
141 | paravirt_write_slot0(bundle_t *bundle, ia64_inst_t inst) | ||
142 | { | ||
143 | bundle->quad0.slot0 = inst.l; | ||
144 | } | ||
145 | |||
146 | void __init_or_module | ||
147 | paravirt_write_slot1(bundle_t *bundle, ia64_inst_t inst) | ||
148 | { | ||
149 | bundle->quad0.slot1_p0 = inst.l; | ||
150 | bundle->quad1.slot1_p1 = inst.l >> 18UL; | ||
151 | } | ||
152 | |||
153 | void __init_or_module | ||
154 | paravirt_write_slot2(bundle_t *bundle, ia64_inst_t inst) | ||
155 | { | ||
156 | bundle->quad1.slot2 = inst.l; | ||
157 | } | ||
158 | |||
159 | void __init_or_module | ||
160 | paravirt_write_inst(unsigned long tag, ia64_inst_t inst) | ||
161 | { | ||
162 | bundle_t *bundle = paravirt_get_bundle(tag); | ||
163 | unsigned long slot = paravirt_get_slot(tag); | ||
164 | |||
165 | switch (slot) { | ||
166 | case 0: | ||
167 | paravirt_write_slot0(bundle, inst); | ||
168 | break; | ||
169 | case 1: | ||
170 | paravirt_write_slot1(bundle, inst); | ||
171 | break; | ||
172 | case 2: | ||
173 | paravirt_write_slot2(bundle, inst); | ||
174 | break; | ||
175 | default: | ||
176 | BUG(); | ||
177 | break; | ||
178 | } | ||
179 | paravirt_flush_i_cache_range(bundle, sizeof(*bundle)); | ||
180 | } | ||
181 | |||
182 | /* for debug */ | ||
183 | void | ||
184 | paravirt_print_bundle(const bundle_t *bundle) | ||
185 | { | ||
186 | const unsigned long *quad = (const unsigned long *)bundle; | ||
187 | ia64_inst_t slot0 = paravirt_read_slot0(bundle); | ||
188 | ia64_inst_t slot1 = paravirt_read_slot1(bundle); | ||
189 | ia64_inst_t slot2 = paravirt_read_slot2(bundle); | ||
190 | |||
191 | printk(KERN_DEBUG | ||
192 | "bundle 0x%p 0x%016lx 0x%016lx\n", bundle, quad[0], quad[1]); | ||
193 | printk(KERN_DEBUG | ||
194 | "bundle template 0x%x\n", | ||
195 | bundle->quad0.template); | ||
196 | printk(KERN_DEBUG | ||
197 | "slot0 0x%lx slot1_p0 0x%lx slot1_p1 0x%lx slot2 0x%lx\n", | ||
198 | (unsigned long)bundle->quad0.slot0, | ||
199 | (unsigned long)bundle->quad0.slot1_p0, | ||
200 | (unsigned long)bundle->quad1.slot1_p1, | ||
201 | (unsigned long)bundle->quad1.slot2); | ||
202 | printk(KERN_DEBUG | ||
203 | "slot0 0x%016llx slot1 0x%016llx slot2 0x%016llx\n", | ||
204 | slot0.l, slot1.l, slot2.l); | ||
205 | } | ||
206 | |||
207 | static int noreplace_paravirt __init_or_module = 0; | ||
208 | |||
209 | static int __init setup_noreplace_paravirt(char *str) | ||
210 | { | ||
211 | noreplace_paravirt = 1; | ||
212 | return 1; | ||
213 | } | ||
214 | __setup("noreplace-paravirt", setup_noreplace_paravirt); | ||
215 | |||
216 | #ifdef ASM_SUPPORTED | ||
217 | static void __init_or_module | ||
218 | fill_nop_bundle(void *sbundle, void *ebundle) | ||
219 | { | ||
220 | extern const char paravirt_nop_bundle[]; | ||
221 | extern const unsigned long paravirt_nop_bundle_size; | ||
222 | |||
223 | void *bundle = sbundle; | ||
224 | |||
225 | BUG_ON((((unsigned long)sbundle) % sizeof(bundle_t)) != 0); | ||
226 | BUG_ON((((unsigned long)ebundle) % sizeof(bundle_t)) != 0); | ||
227 | |||
228 | while (bundle < ebundle) { | ||
229 | memcpy(bundle, paravirt_nop_bundle, paravirt_nop_bundle_size); | ||
230 | |||
231 | bundle += paravirt_nop_bundle_size; | ||
232 | } | ||
233 | } | ||
234 | |||
235 | /* helper function */ | ||
236 | unsigned long __init_or_module | ||
237 | __paravirt_patch_apply_bundle(void *sbundle, void *ebundle, unsigned long type, | ||
238 | const struct paravirt_patch_bundle_elem *elems, | ||
239 | unsigned long nelems, | ||
240 | const struct paravirt_patch_bundle_elem **found) | ||
241 | { | ||
242 | unsigned long used = 0; | ||
243 | unsigned long i; | ||
244 | |||
245 | BUG_ON((((unsigned long)sbundle) % sizeof(bundle_t)) != 0); | ||
246 | BUG_ON((((unsigned long)ebundle) % sizeof(bundle_t)) != 0); | ||
247 | |||
248 | found = NULL; | ||
249 | for (i = 0; i < nelems; i++) { | ||
250 | const struct paravirt_patch_bundle_elem *p = &elems[i]; | ||
251 | if (p->type == type) { | ||
252 | unsigned long need = p->ebundle - p->sbundle; | ||
253 | unsigned long room = ebundle - sbundle; | ||
254 | |||
255 | if (found != NULL) | ||
256 | *found = p; | ||
257 | |||
258 | if (room < need) { | ||
259 | /* no room to replace. skip it */ | ||
260 | printk(KERN_DEBUG | ||
261 | "the space is too small to put " | ||
262 | "bundles. type %ld need %ld room %ld\n", | ||
263 | type, need, room); | ||
264 | break; | ||
265 | } | ||
266 | |||
267 | used = need; | ||
268 | memcpy(sbundle, p->sbundle, used); | ||
269 | break; | ||
270 | } | ||
271 | } | ||
272 | |||
273 | return used; | ||
274 | } | ||
275 | |||
276 | void __init_or_module | ||
277 | paravirt_patch_apply_bundle(const struct paravirt_patch_site_bundle *start, | ||
278 | const struct paravirt_patch_site_bundle *end) | ||
279 | { | ||
280 | const struct paravirt_patch_site_bundle *p; | ||
281 | |||
282 | if (noreplace_paravirt) | ||
283 | return; | ||
284 | if (pv_init_ops.patch_bundle == NULL) | ||
285 | return; | ||
286 | |||
287 | for (p = start; p < end; p++) { | ||
288 | unsigned long used; | ||
289 | |||
290 | used = (*pv_init_ops.patch_bundle)(p->sbundle, p->ebundle, | ||
291 | p->type); | ||
292 | if (used == 0) | ||
293 | continue; | ||
294 | |||
295 | fill_nop_bundle(p->sbundle + used, p->ebundle); | ||
296 | paravirt_flush_i_cache_range(p->sbundle, | ||
297 | p->ebundle - p->sbundle); | ||
298 | } | ||
299 | ia64_sync_i(); | ||
300 | ia64_srlz_i(); | ||
301 | } | ||
302 | |||
303 | /* | ||
304 | * nop.i, nop.m, nop.f instruction are same format. | ||
305 | * but nop.b has differennt format. | ||
306 | * This doesn't support nop.b for now. | ||
307 | */ | ||
308 | static void __init_or_module | ||
309 | fill_nop_inst(unsigned long stag, unsigned long etag) | ||
310 | { | ||
311 | extern const bundle_t paravirt_nop_mfi_inst_bundle[]; | ||
312 | unsigned long tag; | ||
313 | const ia64_inst_t nop_inst = | ||
314 | paravirt_read_slot0(paravirt_nop_mfi_inst_bundle); | ||
315 | |||
316 | for (tag = stag; tag < etag; tag = paravirt_get_next_tag(tag)) | ||
317 | paravirt_write_inst(tag, nop_inst); | ||
318 | } | ||
319 | |||
320 | void __init_or_module | ||
321 | paravirt_patch_apply_inst(const struct paravirt_patch_site_inst *start, | ||
322 | const struct paravirt_patch_site_inst *end) | ||
323 | { | ||
324 | const struct paravirt_patch_site_inst *p; | ||
325 | |||
326 | if (noreplace_paravirt) | ||
327 | return; | ||
328 | if (pv_init_ops.patch_inst == NULL) | ||
329 | return; | ||
330 | |||
331 | for (p = start; p < end; p++) { | ||
332 | unsigned long tag; | ||
333 | bundle_t *sbundle; | ||
334 | bundle_t *ebundle; | ||
335 | |||
336 | tag = (*pv_init_ops.patch_inst)(p->stag, p->etag, p->type); | ||
337 | if (tag == p->stag) | ||
338 | continue; | ||
339 | |||
340 | fill_nop_inst(tag, p->etag); | ||
341 | sbundle = paravirt_get_bundle(p->stag); | ||
342 | ebundle = paravirt_get_bundle(p->etag) + 1; | ||
343 | paravirt_flush_i_cache_range(sbundle, (ebundle - sbundle) * | ||
344 | sizeof(bundle_t)); | ||
345 | } | ||
346 | ia64_sync_i(); | ||
347 | ia64_srlz_i(); | ||
348 | } | ||
349 | #endif /* ASM_SUPPOTED */ | ||
350 | |||
351 | /* brl.cond.sptk.many <target64> X3 */ | ||
352 | typedef union inst_x3_op { | ||
353 | ia64_inst_t inst; | ||
354 | struct { | ||
355 | unsigned long qp: 6; | ||
356 | unsigned long btyp: 3; | ||
357 | unsigned long unused: 3; | ||
358 | unsigned long p: 1; | ||
359 | unsigned long imm20b: 20; | ||
360 | unsigned long wh: 2; | ||
361 | unsigned long d: 1; | ||
362 | unsigned long i: 1; | ||
363 | unsigned long opcode: 4; | ||
364 | }; | ||
365 | unsigned long l; | ||
366 | } inst_x3_op_t; | ||
367 | |||
368 | typedef union inst_x3_imm { | ||
369 | ia64_inst_t inst; | ||
370 | struct { | ||
371 | unsigned long unused: 2; | ||
372 | unsigned long imm39: 39; | ||
373 | }; | ||
374 | unsigned long l; | ||
375 | } inst_x3_imm_t; | ||
376 | |||
377 | void __init_or_module | ||
378 | paravirt_patch_reloc_brl(unsigned long tag, const void *target) | ||
379 | { | ||
380 | unsigned long tag_op = paravirt_get_next_tag(tag); | ||
381 | unsigned long tag_imm = tag; | ||
382 | bundle_t *bundle = paravirt_get_bundle(tag); | ||
383 | |||
384 | ia64_inst_t inst_op = paravirt_read_inst(tag_op); | ||
385 | ia64_inst_t inst_imm = paravirt_read_inst(tag_imm); | ||
386 | |||
387 | inst_x3_op_t inst_x3_op = { .l = inst_op.l }; | ||
388 | inst_x3_imm_t inst_x3_imm = { .l = inst_imm.l }; | ||
389 | |||
390 | unsigned long imm60 = | ||
391 | ((unsigned long)target - (unsigned long)bundle) >> 4; | ||
392 | |||
393 | BUG_ON(paravirt_get_slot(tag) != 1); /* MLX */ | ||
394 | BUG_ON(((unsigned long)target & (sizeof(bundle_t) - 1)) != 0); | ||
395 | |||
396 | /* imm60[59] 1bit */ | ||
397 | inst_x3_op.i = (imm60 >> 59) & 1; | ||
398 | /* imm60[19:0] 20bit */ | ||
399 | inst_x3_op.imm20b = imm60 & ((1UL << 20) - 1); | ||
400 | /* imm60[58:20] 39bit */ | ||
401 | inst_x3_imm.imm39 = (imm60 >> 20) & ((1UL << 39) - 1); | ||
402 | |||
403 | inst_op.l = inst_x3_op.l; | ||
404 | inst_imm.l = inst_x3_imm.l; | ||
405 | |||
406 | paravirt_write_inst(tag_op, inst_op); | ||
407 | paravirt_write_inst(tag_imm, inst_imm); | ||
408 | } | ||
409 | |||
410 | /* br.cond.sptk.many <target25> B1 */ | ||
411 | typedef union inst_b1 { | ||
412 | ia64_inst_t inst; | ||
413 | struct { | ||
414 | unsigned long qp: 6; | ||
415 | unsigned long btype: 3; | ||
416 | unsigned long unused: 3; | ||
417 | unsigned long p: 1; | ||
418 | unsigned long imm20b: 20; | ||
419 | unsigned long wh: 2; | ||
420 | unsigned long d: 1; | ||
421 | unsigned long s: 1; | ||
422 | unsigned long opcode: 4; | ||
423 | }; | ||
424 | unsigned long l; | ||
425 | } inst_b1_t; | ||
426 | |||
427 | void __init | ||
428 | paravirt_patch_reloc_br(unsigned long tag, const void *target) | ||
429 | { | ||
430 | bundle_t *bundle = paravirt_get_bundle(tag); | ||
431 | ia64_inst_t inst = paravirt_read_inst(tag); | ||
432 | unsigned long target25 = (unsigned long)target - (unsigned long)bundle; | ||
433 | inst_b1_t inst_b1; | ||
434 | |||
435 | BUG_ON(((unsigned long)target & (sizeof(bundle_t) - 1)) != 0); | ||
436 | |||
437 | inst_b1.l = inst.l; | ||
438 | if (target25 & (1UL << 63)) | ||
439 | inst_b1.s = 1; | ||
440 | else | ||
441 | inst_b1.s = 0; | ||
442 | |||
443 | inst_b1.imm20b = target25 >> 4; | ||
444 | inst.l = inst_b1.l; | ||
445 | |||
446 | paravirt_write_inst(tag, inst); | ||
447 | } | ||
448 | |||
449 | void __init | ||
450 | __paravirt_patch_apply_branch( | ||
451 | unsigned long tag, unsigned long type, | ||
452 | const struct paravirt_patch_branch_target *entries, | ||
453 | unsigned int nr_entries) | ||
454 | { | ||
455 | unsigned int i; | ||
456 | for (i = 0; i < nr_entries; i++) { | ||
457 | if (entries[i].type == type) { | ||
458 | paravirt_patch_reloc_br(tag, entries[i].entry); | ||
459 | break; | ||
460 | } | ||
461 | } | ||
462 | } | ||
463 | |||
464 | static void __init | ||
465 | paravirt_patch_apply_branch(const struct paravirt_patch_site_branch *start, | ||
466 | const struct paravirt_patch_site_branch *end) | ||
467 | { | ||
468 | const struct paravirt_patch_site_branch *p; | ||
469 | |||
470 | if (noreplace_paravirt) | ||
471 | return; | ||
472 | if (pv_init_ops.patch_branch == NULL) | ||
473 | return; | ||
474 | |||
475 | for (p = start; p < end; p++) | ||
476 | (*pv_init_ops.patch_branch)(p->tag, p->type); | ||
477 | |||
478 | ia64_sync_i(); | ||
479 | ia64_srlz_i(); | ||
480 | } | ||
481 | |||
482 | void __init | ||
483 | paravirt_patch_apply(void) | ||
484 | { | ||
485 | extern const char __start_paravirt_bundles[]; | ||
486 | extern const char __stop_paravirt_bundles[]; | ||
487 | extern const char __start_paravirt_insts[]; | ||
488 | extern const char __stop_paravirt_insts[]; | ||
489 | extern const char __start_paravirt_branches[]; | ||
490 | extern const char __stop_paravirt_branches[]; | ||
491 | |||
492 | paravirt_patch_apply_bundle((const struct paravirt_patch_site_bundle *) | ||
493 | __start_paravirt_bundles, | ||
494 | (const struct paravirt_patch_site_bundle *) | ||
495 | __stop_paravirt_bundles); | ||
496 | paravirt_patch_apply_inst((const struct paravirt_patch_site_inst *) | ||
497 | __start_paravirt_insts, | ||
498 | (const struct paravirt_patch_site_inst *) | ||
499 | __stop_paravirt_insts); | ||
500 | paravirt_patch_apply_branch((const struct paravirt_patch_site_branch *) | ||
501 | __start_paravirt_branches, | ||
502 | (const struct paravirt_patch_site_branch *) | ||
503 | __stop_paravirt_branches); | ||
504 | } | ||
505 | |||
506 | /* | ||
507 | * Local variables: | ||
508 | * mode: C | ||
509 | * c-set-style: "linux" | ||
510 | * c-basic-offset: 8 | ||
511 | * tab-width: 8 | ||
512 | * indent-tabs-mode: t | ||
513 | * End: | ||
514 | */ | ||
diff --git a/arch/ia64/kernel/paravirt_patchlist.c b/arch/ia64/kernel/paravirt_patchlist.c new file mode 100644 index 000000000000..b28082a95d45 --- /dev/null +++ b/arch/ia64/kernel/paravirt_patchlist.c | |||
@@ -0,0 +1,79 @@ | |||
1 | /****************************************************************************** | ||
2 | * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> | ||
3 | * VA Linux Systems Japan K.K. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #include <linux/bug.h> | ||
22 | #include <asm/paravirt.h> | ||
23 | |||
24 | #define DECLARE(name) \ | ||
25 | extern unsigned long \ | ||
26 | __ia64_native_start_gate_##name##_patchlist[]; \ | ||
27 | extern unsigned long \ | ||
28 | __ia64_native_end_gate_##name##_patchlist[] | ||
29 | |||
30 | DECLARE(fsyscall); | ||
31 | DECLARE(brl_fsys_bubble_down); | ||
32 | DECLARE(vtop); | ||
33 | DECLARE(mckinley_e9); | ||
34 | |||
35 | extern unsigned long __start_gate_section[]; | ||
36 | |||
37 | #define ASSIGN(name) \ | ||
38 | .start_##name##_patchlist = \ | ||
39 | (unsigned long)__ia64_native_start_gate_##name##_patchlist, \ | ||
40 | .end_##name##_patchlist = \ | ||
41 | (unsigned long)__ia64_native_end_gate_##name##_patchlist | ||
42 | |||
43 | struct pv_patchdata pv_patchdata __initdata = { | ||
44 | ASSIGN(fsyscall), | ||
45 | ASSIGN(brl_fsys_bubble_down), | ||
46 | ASSIGN(vtop), | ||
47 | ASSIGN(mckinley_e9), | ||
48 | |||
49 | .gate_section = (void*)__start_gate_section, | ||
50 | }; | ||
51 | |||
52 | |||
53 | unsigned long __init | ||
54 | paravirt_get_gate_patchlist(enum pv_gate_patchlist type) | ||
55 | { | ||
56 | |||
57 | #define CASE(NAME, name) \ | ||
58 | case PV_GATE_START_##NAME: \ | ||
59 | return pv_patchdata.start_##name##_patchlist; \ | ||
60 | case PV_GATE_END_##NAME: \ | ||
61 | return pv_patchdata.end_##name##_patchlist; \ | ||
62 | |||
63 | switch (type) { | ||
64 | CASE(FSYSCALL, fsyscall); | ||
65 | CASE(BRL_FSYS_BUBBLE_DOWN, brl_fsys_bubble_down); | ||
66 | CASE(VTOP, vtop); | ||
67 | CASE(MCKINLEY_E9, mckinley_e9); | ||
68 | default: | ||
69 | BUG(); | ||
70 | break; | ||
71 | } | ||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | void * __init | ||
76 | paravirt_get_gate_section(void) | ||
77 | { | ||
78 | return pv_patchdata.gate_section; | ||
79 | } | ||
diff --git a/arch/ia64/kernel/paravirt_patchlist.h b/arch/ia64/kernel/paravirt_patchlist.h new file mode 100644 index 000000000000..0684aa6c6507 --- /dev/null +++ b/arch/ia64/kernel/paravirt_patchlist.h | |||
@@ -0,0 +1,28 @@ | |||
1 | /****************************************************************************** | ||
2 | * linux/arch/ia64/xen/paravirt_patchlist.h | ||
3 | * | ||
4 | * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> | ||
5 | * VA Linux Systems Japan K.K. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #if defined(__IA64_GATE_PARAVIRTUALIZED_XEN) | ||
24 | #include <asm/xen/patchlist.h> | ||
25 | #else | ||
26 | #include <asm/native/patchlist.h> | ||
27 | #endif | ||
28 | |||
diff --git a/arch/ia64/kernel/paravirtentry.S b/arch/ia64/kernel/paravirtentry.S index 2f42fcb9776a..6158560d7f17 100644 --- a/arch/ia64/kernel/paravirtentry.S +++ b/arch/ia64/kernel/paravirtentry.S | |||
@@ -20,8 +20,11 @@ | |||
20 | * | 20 | * |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/init.h> | ||
23 | #include <asm/asmmacro.h> | 24 | #include <asm/asmmacro.h> |
24 | #include <asm/asm-offsets.h> | 25 | #include <asm/asm-offsets.h> |
26 | #include <asm/paravirt_privop.h> | ||
27 | #include <asm/paravirt_patch.h> | ||
25 | #include "entry.h" | 28 | #include "entry.h" |
26 | 29 | ||
27 | #define DATA8(sym, init_value) \ | 30 | #define DATA8(sym, init_value) \ |
@@ -32,29 +35,87 @@ | |||
32 | data8 init_value ; \ | 35 | data8 init_value ; \ |
33 | .popsection | 36 | .popsection |
34 | 37 | ||
35 | #define BRANCH(targ, reg, breg) \ | 38 | #define BRANCH(targ, reg, breg, type) \ |
36 | movl reg=targ ; \ | 39 | PARAVIRT_PATCH_SITE_BR(PARAVIRT_PATCH_TYPE_BR_ ## type) ; \ |
37 | ;; \ | 40 | ;; \ |
38 | ld8 reg=[reg] ; \ | 41 | movl reg=targ ; \ |
39 | ;; \ | 42 | ;; \ |
40 | mov breg=reg ; \ | 43 | ld8 reg=[reg] ; \ |
44 | ;; \ | ||
45 | mov breg=reg ; \ | ||
41 | br.cond.sptk.many breg | 46 | br.cond.sptk.many breg |
42 | 47 | ||
43 | #define BRANCH_PROC(sym, reg, breg) \ | 48 | #define BRANCH_PROC(sym, reg, breg, type) \ |
44 | DATA8(paravirt_ ## sym ## _targ, ia64_native_ ## sym) ; \ | 49 | DATA8(paravirt_ ## sym ## _targ, ia64_native_ ## sym) ; \ |
45 | GLOBAL_ENTRY(paravirt_ ## sym) ; \ | 50 | GLOBAL_ENTRY(paravirt_ ## sym) ; \ |
46 | BRANCH(paravirt_ ## sym ## _targ, reg, breg) ; \ | 51 | BRANCH(paravirt_ ## sym ## _targ, reg, breg, type) ; \ |
47 | END(paravirt_ ## sym) | 52 | END(paravirt_ ## sym) |
48 | 53 | ||
49 | #define BRANCH_PROC_UNWINFO(sym, reg, breg) \ | 54 | #define BRANCH_PROC_UNWINFO(sym, reg, breg, type) \ |
50 | DATA8(paravirt_ ## sym ## _targ, ia64_native_ ## sym) ; \ | 55 | DATA8(paravirt_ ## sym ## _targ, ia64_native_ ## sym) ; \ |
51 | GLOBAL_ENTRY(paravirt_ ## sym) ; \ | 56 | GLOBAL_ENTRY(paravirt_ ## sym) ; \ |
52 | PT_REGS_UNWIND_INFO(0) ; \ | 57 | PT_REGS_UNWIND_INFO(0) ; \ |
53 | BRANCH(paravirt_ ## sym ## _targ, reg, breg) ; \ | 58 | BRANCH(paravirt_ ## sym ## _targ, reg, breg, type) ; \ |
54 | END(paravirt_ ## sym) | 59 | END(paravirt_ ## sym) |
55 | 60 | ||
56 | 61 | ||
57 | BRANCH_PROC(switch_to, r22, b7) | 62 | BRANCH_PROC(switch_to, r22, b7, SWITCH_TO) |
58 | BRANCH_PROC_UNWINFO(leave_syscall, r22, b7) | 63 | BRANCH_PROC_UNWINFO(leave_syscall, r22, b7, LEAVE_SYSCALL) |
59 | BRANCH_PROC(work_processed_syscall, r2, b7) | 64 | BRANCH_PROC(work_processed_syscall, r2, b7, WORK_PROCESSED_SYSCALL) |
60 | BRANCH_PROC_UNWINFO(leave_kernel, r22, b7) | 65 | BRANCH_PROC_UNWINFO(leave_kernel, r22, b7, LEAVE_KERNEL) |
66 | |||
67 | |||
68 | #ifdef CONFIG_MODULES | ||
69 | #define __INIT_OR_MODULE .text | ||
70 | #define __INITDATA_OR_MODULE .data | ||
71 | #else | ||
72 | #define __INIT_OR_MODULE __INIT | ||
73 | #define __INITDATA_OR_MODULE __INITDATA | ||
74 | #endif /* CONFIG_MODULES */ | ||
75 | |||
76 | __INIT_OR_MODULE | ||
77 | GLOBAL_ENTRY(paravirt_fc_i) | ||
78 | fc.i r32 | ||
79 | br.ret.sptk.many rp | ||
80 | END(paravirt_fc_i) | ||
81 | __FINIT | ||
82 | |||
83 | __INIT_OR_MODULE | ||
84 | .align 32 | ||
85 | GLOBAL_ENTRY(paravirt_nop_b_inst_bundle) | ||
86 | { | ||
87 | nop.b 0 | ||
88 | nop.b 0 | ||
89 | nop.b 0 | ||
90 | } | ||
91 | END(paravirt_nop_b_inst_bundle) | ||
92 | __FINIT | ||
93 | |||
94 | /* NOTE: nop.[mfi] has same format */ | ||
95 | __INIT_OR_MODULE | ||
96 | GLOBAL_ENTRY(paravirt_nop_mfi_inst_bundle) | ||
97 | { | ||
98 | nop.m 0 | ||
99 | nop.f 0 | ||
100 | nop.i 0 | ||
101 | } | ||
102 | END(paravirt_nop_mfi_inst_bundle) | ||
103 | __FINIT | ||
104 | |||
105 | __INIT_OR_MODULE | ||
106 | GLOBAL_ENTRY(paravirt_nop_bundle) | ||
107 | paravirt_nop_bundle_start: | ||
108 | { | ||
109 | nop 0 | ||
110 | nop 0 | ||
111 | nop 0 | ||
112 | } | ||
113 | paravirt_nop_bundle_end: | ||
114 | END(paravirt_nop_bundle) | ||
115 | __FINIT | ||
116 | |||
117 | __INITDATA_OR_MODULE | ||
118 | .align 8 | ||
119 | .global paravirt_nop_bundle_size | ||
120 | paravirt_nop_bundle_size: | ||
121 | data8 paravirt_nop_bundle_end - paravirt_nop_bundle_start | ||
diff --git a/arch/ia64/kernel/patch.c b/arch/ia64/kernel/patch.c index b83b2c516008..68a1311db806 100644 --- a/arch/ia64/kernel/patch.c +++ b/arch/ia64/kernel/patch.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <linux/init.h> | 7 | #include <linux/init.h> |
8 | #include <linux/string.h> | 8 | #include <linux/string.h> |
9 | 9 | ||
10 | #include <asm/paravirt.h> | ||
10 | #include <asm/patch.h> | 11 | #include <asm/patch.h> |
11 | #include <asm/processor.h> | 12 | #include <asm/processor.h> |
12 | #include <asm/sections.h> | 13 | #include <asm/sections.h> |
@@ -169,16 +170,35 @@ ia64_patch_mckinley_e9 (unsigned long start, unsigned long end) | |||
169 | ia64_srlz_i(); | 170 | ia64_srlz_i(); |
170 | } | 171 | } |
171 | 172 | ||
173 | extern unsigned long ia64_native_fsyscall_table[NR_syscalls]; | ||
174 | extern char ia64_native_fsys_bubble_down[]; | ||
175 | struct pv_fsys_data pv_fsys_data __initdata = { | ||
176 | .fsyscall_table = (unsigned long *)ia64_native_fsyscall_table, | ||
177 | .fsys_bubble_down = (void *)ia64_native_fsys_bubble_down, | ||
178 | }; | ||
179 | |||
180 | unsigned long * __init | ||
181 | paravirt_get_fsyscall_table(void) | ||
182 | { | ||
183 | return pv_fsys_data.fsyscall_table; | ||
184 | } | ||
185 | |||
186 | char * __init | ||
187 | paravirt_get_fsys_bubble_down(void) | ||
188 | { | ||
189 | return pv_fsys_data.fsys_bubble_down; | ||
190 | } | ||
191 | |||
172 | static void __init | 192 | static void __init |
173 | patch_fsyscall_table (unsigned long start, unsigned long end) | 193 | patch_fsyscall_table (unsigned long start, unsigned long end) |
174 | { | 194 | { |
175 | extern unsigned long fsyscall_table[NR_syscalls]; | 195 | u64 fsyscall_table = (u64)paravirt_get_fsyscall_table(); |
176 | s32 *offp = (s32 *) start; | 196 | s32 *offp = (s32 *) start; |
177 | u64 ip; | 197 | u64 ip; |
178 | 198 | ||
179 | while (offp < (s32 *) end) { | 199 | while (offp < (s32 *) end) { |
180 | ip = (u64) ia64_imva((char *) offp + *offp); | 200 | ip = (u64) ia64_imva((char *) offp + *offp); |
181 | ia64_patch_imm64(ip, (u64) fsyscall_table); | 201 | ia64_patch_imm64(ip, fsyscall_table); |
182 | ia64_fc((void *) ip); | 202 | ia64_fc((void *) ip); |
183 | ++offp; | 203 | ++offp; |
184 | } | 204 | } |
@@ -189,7 +209,7 @@ patch_fsyscall_table (unsigned long start, unsigned long end) | |||
189 | static void __init | 209 | static void __init |
190 | patch_brl_fsys_bubble_down (unsigned long start, unsigned long end) | 210 | patch_brl_fsys_bubble_down (unsigned long start, unsigned long end) |
191 | { | 211 | { |
192 | extern char fsys_bubble_down[]; | 212 | u64 fsys_bubble_down = (u64)paravirt_get_fsys_bubble_down(); |
193 | s32 *offp = (s32 *) start; | 213 | s32 *offp = (s32 *) start; |
194 | u64 ip; | 214 | u64 ip; |
195 | 215 | ||
@@ -207,13 +227,13 @@ patch_brl_fsys_bubble_down (unsigned long start, unsigned long end) | |||
207 | void __init | 227 | void __init |
208 | ia64_patch_gate (void) | 228 | ia64_patch_gate (void) |
209 | { | 229 | { |
210 | # define START(name) ((unsigned long) __start_gate_##name##_patchlist) | 230 | # define START(name) paravirt_get_gate_patchlist(PV_GATE_START_##name) |
211 | # define END(name) ((unsigned long)__end_gate_##name##_patchlist) | 231 | # define END(name) paravirt_get_gate_patchlist(PV_GATE_END_##name) |
212 | 232 | ||
213 | patch_fsyscall_table(START(fsyscall), END(fsyscall)); | 233 | patch_fsyscall_table(START(FSYSCALL), END(FSYSCALL)); |
214 | patch_brl_fsys_bubble_down(START(brl_fsys_bubble_down), END(brl_fsys_bubble_down)); | 234 | patch_brl_fsys_bubble_down(START(BRL_FSYS_BUBBLE_DOWN), END(BRL_FSYS_BUBBLE_DOWN)); |
215 | ia64_patch_vtop(START(vtop), END(vtop)); | 235 | ia64_patch_vtop(START(VTOP), END(VTOP)); |
216 | ia64_patch_mckinley_e9(START(mckinley_e9), END(mckinley_e9)); | 236 | ia64_patch_mckinley_e9(START(MCKINLEY_E9), END(MCKINLEY_E9)); |
217 | } | 237 | } |
218 | 238 | ||
219 | void ia64_patch_phys_stack_reg(unsigned long val) | 239 | void ia64_patch_phys_stack_reg(unsigned long val) |
@@ -229,7 +249,7 @@ void ia64_patch_phys_stack_reg(unsigned long val) | |||
229 | while (offp < end) { | 249 | while (offp < end) { |
230 | ip = (u64) offp + *offp; | 250 | ip = (u64) offp + *offp; |
231 | ia64_patch(ip, mask, imm); | 251 | ia64_patch(ip, mask, imm); |
232 | ia64_fc(ip); | 252 | ia64_fc((void *)ip); |
233 | ++offp; | 253 | ++offp; |
234 | } | 254 | } |
235 | ia64_sync_i(); | 255 | ia64_sync_i(); |
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index ae9ec3dc76b8..833b3ef92779 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c | |||
@@ -52,6 +52,7 @@ | |||
52 | #include <asm/meminit.h> | 52 | #include <asm/meminit.h> |
53 | #include <asm/page.h> | 53 | #include <asm/page.h> |
54 | #include <asm/paravirt.h> | 54 | #include <asm/paravirt.h> |
55 | #include <asm/paravirt_patch.h> | ||
55 | #include <asm/patch.h> | 56 | #include <asm/patch.h> |
56 | #include <asm/pgtable.h> | 57 | #include <asm/pgtable.h> |
57 | #include <asm/processor.h> | 58 | #include <asm/processor.h> |
@@ -537,6 +538,7 @@ setup_arch (char **cmdline_p) | |||
537 | paravirt_arch_setup_early(); | 538 | paravirt_arch_setup_early(); |
538 | 539 | ||
539 | ia64_patch_vtop((u64) __start___vtop_patchlist, (u64) __end___vtop_patchlist); | 540 | ia64_patch_vtop((u64) __start___vtop_patchlist, (u64) __end___vtop_patchlist); |
541 | paravirt_patch_apply(); | ||
540 | 542 | ||
541 | *cmdline_p = __va(ia64_boot_param->command_line); | 543 | *cmdline_p = __va(ia64_boot_param->command_line); |
542 | strlcpy(boot_command_line, *cmdline_p, COMMAND_LINE_SIZE); | 544 | strlcpy(boot_command_line, *cmdline_p, COMMAND_LINE_SIZE); |
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c index f0ebb342409d..c323c7b9c775 100644 --- a/arch/ia64/kernel/time.c +++ b/arch/ia64/kernel/time.c | |||
@@ -50,6 +50,15 @@ EXPORT_SYMBOL(last_cli_ip); | |||
50 | #endif | 50 | #endif |
51 | 51 | ||
52 | #ifdef CONFIG_PARAVIRT | 52 | #ifdef CONFIG_PARAVIRT |
53 | /* We need to define a real function for sched_clock, to override the | ||
54 | weak default version */ | ||
55 | unsigned long long sched_clock(void) | ||
56 | { | ||
57 | return paravirt_sched_clock(); | ||
58 | } | ||
59 | #endif | ||
60 | |||
61 | #ifdef CONFIG_PARAVIRT | ||
53 | static void | 62 | static void |
54 | paravirt_clocksource_resume(void) | 63 | paravirt_clocksource_resume(void) |
55 | { | 64 | { |
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S index 3765efc5f963..4a95e86b9ac2 100644 --- a/arch/ia64/kernel/vmlinux.lds.S +++ b/arch/ia64/kernel/vmlinux.lds.S | |||
@@ -169,6 +169,30 @@ SECTIONS | |||
169 | __end___mckinley_e9_bundles = .; | 169 | __end___mckinley_e9_bundles = .; |
170 | } | 170 | } |
171 | 171 | ||
172 | #if defined(CONFIG_PARAVIRT) | ||
173 | . = ALIGN(16); | ||
174 | .paravirt_bundles : AT(ADDR(.paravirt_bundles) - LOAD_OFFSET) | ||
175 | { | ||
176 | __start_paravirt_bundles = .; | ||
177 | *(.paravirt_bundles) | ||
178 | __stop_paravirt_bundles = .; | ||
179 | } | ||
180 | . = ALIGN(16); | ||
181 | .paravirt_insts : AT(ADDR(.paravirt_insts) - LOAD_OFFSET) | ||
182 | { | ||
183 | __start_paravirt_insts = .; | ||
184 | *(.paravirt_insts) | ||
185 | __stop_paravirt_insts = .; | ||
186 | } | ||
187 | . = ALIGN(16); | ||
188 | .paravirt_branches : AT(ADDR(.paravirt_branches) - LOAD_OFFSET) | ||
189 | { | ||
190 | __start_paravirt_branches = .; | ||
191 | *(.paravirt_branches) | ||
192 | __stop_paravirt_branches = .; | ||
193 | } | ||
194 | #endif | ||
195 | |||
172 | #if defined(CONFIG_IA64_GENERIC) | 196 | #if defined(CONFIG_IA64_GENERIC) |
173 | /* Machine Vector */ | 197 | /* Machine Vector */ |
174 | . = ALIGN(16); | 198 | . = ALIGN(16); |
@@ -201,6 +225,12 @@ SECTIONS | |||
201 | __start_gate_section = .; | 225 | __start_gate_section = .; |
202 | *(.data.gate) | 226 | *(.data.gate) |
203 | __stop_gate_section = .; | 227 | __stop_gate_section = .; |
228 | #ifdef CONFIG_XEN | ||
229 | . = ALIGN(PAGE_SIZE); | ||
230 | __xen_start_gate_section = .; | ||
231 | *(.data.gate.xen) | ||
232 | __xen_stop_gate_section = .; | ||
233 | #endif | ||
204 | } | 234 | } |
205 | . = ALIGN(PAGE_SIZE); /* make sure the gate page doesn't expose | 235 | . = ALIGN(PAGE_SIZE); /* make sure the gate page doesn't expose |
206 | * kernel data | 236 | * kernel data |