aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel
diff options
context:
space:
mode:
authorTony Luck <aegl@agluck-desktop.(none)>2009-03-31 17:25:08 -0400
committerTony Luck <tony.luck@intel.com>2009-03-31 17:25:08 -0400
commitc66b31f3926165bc1d4128adc97a064dcbab421a (patch)
tree13be75d33bd2b9d4ec45ec512ac38a2e7069062e /arch/ia64/kernel
parent50fbe56c127efde659c686495eb1f925fd84ff0a (diff)
parent7120569c76028a6883697b7643564f0c419cfe07 (diff)
Pull pvops into release branch
Diffstat (limited to 'arch/ia64/kernel')
-rw-r--r--arch/ia64/kernel/Makefile39
-rw-r--r--arch/ia64/kernel/Makefile.gate27
-rw-r--r--arch/ia64/kernel/asm-offsets.c2
-rw-r--r--arch/ia64/kernel/efi.c1
-rw-r--r--arch/ia64/kernel/entry.S4
-rw-r--r--arch/ia64/kernel/fsys.S35
-rw-r--r--arch/ia64/kernel/gate.S171
-rw-r--r--arch/ia64/kernel/gate.lds.S17
-rw-r--r--arch/ia64/kernel/head.S10
-rw-r--r--arch/ia64/kernel/ivt.S2
-rw-r--r--arch/ia64/kernel/module.c32
-rw-r--r--arch/ia64/kernel/paravirt.c539
-rw-r--r--arch/ia64/kernel/paravirt_patch.c514
-rw-r--r--arch/ia64/kernel/paravirt_patchlist.c79
-rw-r--r--arch/ia64/kernel/paravirt_patchlist.h28
-rw-r--r--arch/ia64/kernel/paravirtentry.S99
-rw-r--r--arch/ia64/kernel/patch.c40
-rw-r--r--arch/ia64/kernel/setup.c2
-rw-r--r--arch/ia64/kernel/time.c9
-rw-r--r--arch/ia64/kernel/vmlinux.lds.S30
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 @@
5extra-y := head.o init_task.o vmlinux.lds 5extra-y := head.o init_task.o vmlinux.lds
6 6
7obj-y := acpi.o entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o irq_ia64.o \ 7obj-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
36mca_recovery-y += mca_drv.o mca_drv_asm.o 36mca_recovery-y += mca_drv.o mca_drv_asm.o
37obj-$(CONFIG_IA64_MC_ERR_INJECT)+= err_inject.o 37obj-$(CONFIG_IA64_MC_ERR_INJECT)+= err_inject.o
38 38
39obj-$(CONFIG_PARAVIRT) += paravirt.o paravirtentry.o 39obj-$(CONFIG_PARAVIRT) += paravirt.o paravirtentry.o \
40 paravirt_patch.o
40 41
41obj-$(CONFIG_IA64_ESI) += esi.o 42obj-$(CONFIG_IA64_ESI) += esi.o
42ifneq ($(CONFIG_IA64_ESI),) 43ifneq ($(CONFIG_IA64_ESI),)
@@ -45,35 +46,13 @@ endif
45obj-$(CONFIG_DMAR) += pci-dma.o 46obj-$(CONFIG_DMAR) += pci-dma.o
46obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o 47obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o
47 48
48# The gate DSO image is built using a special linker script.
49targets += gate.so gate-syms.o
50
51extra-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.
54CFLAGS_traps.o += -mfixed-range=f2-f5,f16-f31 50CFLAGS_traps.o += -mfixed-range=f2-f5,f16-f31
55 51
56CPPFLAGS_gate.lds := -P -C -U$(ARCH) 52# The gate DSO image is built using a special linker script.
57 53include $(srctree)/arch/ia64/kernel/Makefile.gate
58quiet_cmd_gate = GATE $@ 54# tell compiled for native
59 cmd_gate = $(CC) -nostdlib $(GATECFLAGS_$(@F)) -Wl,-T,$(filter-out FORCE,$^) -o $@ 55CPPFLAGS_gate.lds += -D__IA64_GATE_PARAVIRTUALIZED_NATIVE
60
61GATECFLAGS_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
69GATECFLAGS_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
79define sed-y 58define sed-y
@@ -109,9 +88,9 @@ include/asm-ia64/nr-irqs.h: arch/$(SRCARCH)/kernel/nr-irqs.s
109clean-files += $(objtree)/include/asm-ia64/nr-irqs.h 88clean-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#
114ASM_PARAVIRT_OBJS = ivt.o entry.o 93ASM_PARAVIRT_OBJS = ivt.o entry.o fsys.o
115define paravirtualized_native 94define paravirtualized_native
116AFLAGS_$(1) += -D__IA64_ASM_PARAVIRTUALIZED_NATIVE 95AFLAGS_$(1) += -D__IA64_ASM_PARAVIRTUALIZED_NATIVE
117AFLAGS_pvchk-sed-$(1) += -D__IA64_ASM_PARAVIRTUALIZED_PVCHECK 96AFLAGS_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
3targets += gate.so gate-syms.o
4
5extra-y += gate.so gate-syms.o gate.lds gate.o
6
7CPPFLAGS_gate.lds := -P -C -U$(ARCH)
8
9quiet_cmd_gate = GATE $@
10 cmd_gate = $(CC) -nostdlib $(GATECFLAGS_$(@F)) -Wl,-T,$(filter-out FORCE,$^) -o $@
11
12GATECFLAGS_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
20GATECFLAGS_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
603END(fsys_fallback_syscall) 604END(fsys_fallback_syscall)
604 /* FALL THROUGH */ 605 /* FALL THROUGH */
605GLOBAL_ENTRY(fsys_bubble_down) 606GLOBAL_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
744END(fsys_bubble_down) 745END(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
751fsyscall_table: 752paravirt_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}
49END(__kernel_syscall_via_break) 50END(__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
65GLOBAL_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
130END(__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
376END(__kernel_sigtramp) 296END(__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
312GLOBAL_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
385END(__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
11SECTIONS 12SECTIONS
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 */
1053GLOBAL_ENTRY(sched_clock) 1053GLOBAL_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
1069END(sched_clock) 1069END(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
1074sched_clock = ia64_native_sched_clock
1075#endif
1070 1076
1071#ifdef CONFIG_VIRT_CPU_ACCOUNTING 1077#ifdef CONFIG_VIRT_CPU_ACCOUNTING
1072GLOBAL_ENTRY(cycle_to_cputime) 1078GLOBAL_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
49struct pv_init_ops pv_init_ops; 49static void __init
50ia64_native_patch_branch(unsigned long tag, unsigned long type);
51
52struct 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
87DEFINE_VOID_FUNC1(fc); 104DEFINE_VOID_FUNC1_VOID(fc);
88DEFINE_VOID_FUNC1(intrin_local_irq_restore); 105DEFINE_VOID_FUNC1(intrin_local_irq_restore);
89 106
90DEFINE_VOID_FUNC2(ptcga); 107DEFINE_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
339DEFINE_VOID_FUNC1_VOID(fc,
340 "fc r8\n");
341DEFINE_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
350DEFINE_VOID_FUNC2(ptcga,
351 "ptc.ga r8, r9\n");
352DEFINE_VOID_FUNC2(set_rr,
353 "mov rr[r8] = r9\n");
354
355/* ia64_native_getreg(_IA64_REG_PSR) & IA64_PSR_I */
356DEFINE_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
362DEFINE_FUNC1(thash, unsigned long,
363 "thash r8 = r8\n");
364DEFINE_FUNC1(get_cpuid, int,
365 "mov r8 = cpuid[r8]\n");
366DEFINE_FUNC1(get_pmd, int,
367 "mov r8 = pmd[r8]\n");
368DEFINE_FUNC1(get_rr, unsigned long,
369 "mov r8 = rr[r8]\n");
370
371DEFINE_VOID_FUNC0(ssm_i,
372 "ssm psr.i\n");
373DEFINE_VOID_FUNC0(rsm_i,
374 "rsm psr.i\n");
375
376extern void
377ia64_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
395extern unsigned long ia64_native_getreg_func(int regnum);
396asm(".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
473extern void ia64_native_setreg_func(int regnum, unsigned long val);
474asm(".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
278struct pv_cpu_ops pv_cpu_ops = { 555struct 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
367struct pv_time_ops pv_time_ops = { 644struct 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
678IA64_NATIVE_PATCH_DEFINE_GET_REG(psr, psr);
679IA64_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
690IA64_NATIVE_PATCH_DEFINE_REG(gp, gp);
691IA64_NATIVE_PATCH_DEFINE_REG(sp, sp);
692
693IA64_NATIVE_PATCH_DEFINE_REG(kr0, ar0);
694IA64_NATIVE_PATCH_DEFINE_REG(kr1, ar1);
695IA64_NATIVE_PATCH_DEFINE_REG(kr2, ar2);
696IA64_NATIVE_PATCH_DEFINE_REG(kr3, ar3);
697IA64_NATIVE_PATCH_DEFINE_REG(kr4, ar4);
698IA64_NATIVE_PATCH_DEFINE_REG(kr5, ar5);
699IA64_NATIVE_PATCH_DEFINE_REG(kr6, ar6);
700IA64_NATIVE_PATCH_DEFINE_REG(kr7, ar7);
701
702IA64_NATIVE_PATCH_DEFINE_AR(rsc, rsc);
703IA64_NATIVE_PATCH_DEFINE_AR(bsp, bsp);
704IA64_NATIVE_PATCH_DEFINE_AR(bspstore, bspstore);
705IA64_NATIVE_PATCH_DEFINE_AR(rnat, rnat);
706IA64_NATIVE_PATCH_DEFINE_AR(fcr, fcr);
707IA64_NATIVE_PATCH_DEFINE_AR(eflag, eflag);
708IA64_NATIVE_PATCH_DEFINE_AR(csd, csd);
709IA64_NATIVE_PATCH_DEFINE_AR(ssd, ssd);
710IA64_NATIVE_PATCH_DEFINE_REG(ar27, ar27);
711IA64_NATIVE_PATCH_DEFINE_AR(fsr, fsr);
712IA64_NATIVE_PATCH_DEFINE_AR(fir, fir);
713IA64_NATIVE_PATCH_DEFINE_AR(fdr, fdr);
714IA64_NATIVE_PATCH_DEFINE_AR(ccv, ccv);
715IA64_NATIVE_PATCH_DEFINE_AR(unat, unat);
716IA64_NATIVE_PATCH_DEFINE_AR(fpsr, fpsr);
717IA64_NATIVE_PATCH_DEFINE_AR(itc, itc);
718IA64_NATIVE_PATCH_DEFINE_AR(pfs, pfs);
719IA64_NATIVE_PATCH_DEFINE_AR(lc, lc);
720IA64_NATIVE_PATCH_DEFINE_AR(ec, ec);
721
722IA64_NATIVE_PATCH_DEFINE_CR(dcr, dcr);
723IA64_NATIVE_PATCH_DEFINE_CR(itm, itm);
724IA64_NATIVE_PATCH_DEFINE_CR(iva, iva);
725IA64_NATIVE_PATCH_DEFINE_CR(pta, pta);
726IA64_NATIVE_PATCH_DEFINE_CR(ipsr, ipsr);
727IA64_NATIVE_PATCH_DEFINE_CR(isr, isr);
728IA64_NATIVE_PATCH_DEFINE_CR(iip, iip);
729IA64_NATIVE_PATCH_DEFINE_CR(ifa, ifa);
730IA64_NATIVE_PATCH_DEFINE_CR(itir, itir);
731IA64_NATIVE_PATCH_DEFINE_CR(iipa, iipa);
732IA64_NATIVE_PATCH_DEFINE_CR(ifs, ifs);
733IA64_NATIVE_PATCH_DEFINE_CR(iim, iim);
734IA64_NATIVE_PATCH_DEFINE_CR(iha, iha);
735IA64_NATIVE_PATCH_DEFINE_CR(lid, lid);
736IA64_NATIVE_PATCH_DEFINE_CR(ivr, ivr);
737IA64_NATIVE_PATCH_DEFINE_CR(tpr, tpr);
738IA64_NATIVE_PATCH_DEFINE_CR(eoi, eoi);
739IA64_NATIVE_PATCH_DEFINE_CR(irr0, irr0);
740IA64_NATIVE_PATCH_DEFINE_CR(irr1, irr1);
741IA64_NATIVE_PATCH_DEFINE_CR(irr2, irr2);
742IA64_NATIVE_PATCH_DEFINE_CR(irr3, irr3);
743IA64_NATIVE_PATCH_DEFINE_CR(itv, itv);
744IA64_NATIVE_PATCH_DEFINE_CR(pmv, pmv);
745IA64_NATIVE_PATCH_DEFINE_CR(cmcv, cmcv);
746IA64_NATIVE_PATCH_DEFINE_CR(lrr0, lrr0);
747IA64_NATIVE_PATCH_DEFINE_CR(lrr1, lrr1);
748
749static 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
862unsigned long __init_or_module
863ia64_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
874extern const char ia64_native_switch_to[];
875extern const char ia64_native_leave_syscall[];
876extern const char ia64_native_work_processed_syscall[];
877extern const char ia64_native_leave_kernel[];
878
879const 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
892static void __init
893ia64_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
29typedef 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 */
44void __init_or_module
45paravirt_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
54bundle_t* __init_or_module
55paravirt_get_bundle(unsigned long tag)
56{
57 return (bundle_t *)(tag & ~3UL);
58}
59
60unsigned long __init_or_module
61paravirt_get_slot(unsigned long tag)
62{
63 return tag & 3UL;
64}
65
66unsigned long __init_or_module
67paravirt_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
77unsigned long __init_or_module
78paravirt_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
96ia64_inst_t __init_or_module
97paravirt_read_slot0(const bundle_t *bundle)
98{
99 ia64_inst_t inst;
100 inst.l = bundle->quad0.slot0;
101 return inst;
102}
103
104ia64_inst_t __init_or_module
105paravirt_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
113ia64_inst_t __init_or_module
114paravirt_read_slot2(const bundle_t *bundle)
115{
116 ia64_inst_t inst;
117 inst.l = bundle->quad1.slot2;
118 return inst;
119}
120
121ia64_inst_t __init_or_module
122paravirt_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
140void __init_or_module
141paravirt_write_slot0(bundle_t *bundle, ia64_inst_t inst)
142{
143 bundle->quad0.slot0 = inst.l;
144}
145
146void __init_or_module
147paravirt_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
153void __init_or_module
154paravirt_write_slot2(bundle_t *bundle, ia64_inst_t inst)
155{
156 bundle->quad1.slot2 = inst.l;
157}
158
159void __init_or_module
160paravirt_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 */
183void
184paravirt_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
207static int noreplace_paravirt __init_or_module = 0;
208
209static 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
217static void __init_or_module
218fill_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 */
236unsigned 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
276void __init_or_module
277paravirt_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 */
308static void __init_or_module
309fill_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
320void __init_or_module
321paravirt_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 */
352typedef 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
368typedef 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
377void __init_or_module
378paravirt_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 */
411typedef 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
427void __init
428paravirt_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
449void __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
464static void __init
465paravirt_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
482void __init
483paravirt_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
30DECLARE(fsyscall);
31DECLARE(brl_fsys_bubble_down);
32DECLARE(vtop);
33DECLARE(mckinley_e9);
34
35extern 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
43struct 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
53unsigned long __init
54paravirt_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
75void * __init
76paravirt_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
57BRANCH_PROC(switch_to, r22, b7) 62BRANCH_PROC(switch_to, r22, b7, SWITCH_TO)
58BRANCH_PROC_UNWINFO(leave_syscall, r22, b7) 63BRANCH_PROC_UNWINFO(leave_syscall, r22, b7, LEAVE_SYSCALL)
59BRANCH_PROC(work_processed_syscall, r2, b7) 64BRANCH_PROC(work_processed_syscall, r2, b7, WORK_PROCESSED_SYSCALL)
60BRANCH_PROC_UNWINFO(leave_kernel, r22, b7) 65BRANCH_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)
107paravirt_nop_bundle_start:
108 {
109 nop 0
110 nop 0
111 nop 0
112 }
113paravirt_nop_bundle_end:
114 END(paravirt_nop_bundle)
115 __FINIT
116
117 __INITDATA_OR_MODULE
118 .align 8
119 .global paravirt_nop_bundle_size
120paravirt_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
173extern unsigned long ia64_native_fsyscall_table[NR_syscalls];
174extern char ia64_native_fsys_bubble_down[];
175struct 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
180unsigned long * __init
181paravirt_get_fsyscall_table(void)
182{
183 return pv_fsys_data.fsyscall_table;
184}
185
186char * __init
187paravirt_get_fsys_bubble_down(void)
188{
189 return pv_fsys_data.fsys_bubble_down;
190}
191
172static void __init 192static void __init
173patch_fsyscall_table (unsigned long start, unsigned long end) 193patch_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)
189static void __init 209static void __init
190patch_brl_fsys_bubble_down (unsigned long start, unsigned long end) 210patch_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)
207void __init 227void __init
208ia64_patch_gate (void) 228ia64_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
219void ia64_patch_phys_stack_reg(unsigned long val) 239void 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 */
55unsigned long long sched_clock(void)
56{
57 return paravirt_sched_clock();
58}
59#endif
60
61#ifdef CONFIG_PARAVIRT
53static void 62static void
54paravirt_clocksource_resume(void) 63paravirt_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