diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-01 16:33:41 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-01 16:33:41 -0400 |
| commit | 8b53ef33d9d8fa5f771ae11cc6a6e7bc0182beec (patch) | |
| tree | 7835bab94824b3d52e7466ae28825941f6c6277a /arch/ia64/kernel | |
| parent | ef5ddd3d591399f2c722a77bce543d20bef31663 (diff) | |
| parent | 80a03e29164c76b70e6dbb1d10515820cc24487a (diff) | |
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6: (29 commits)
[IA64] BUG to BUG_ON changes
[IA64] Fix typo/thinko in arch/ia64/sn/kernel/sn2/sn2_smp.c
ia64: remove some warnings.
ia64/xen: fix the link error.
ia64/pv_ops/bp/xen: implemented binary patchable pv_cpu_ops.
ia64/pv_ops/binary patch: define paravirt_dv_serialize_data() and suppress false positive warning.
ia64/pv_ops/bp/module: support binary patching for kernel module.
ia64/pv_ops: implement binary patching optimization for native.
ia64/pv_op/binarypatch: add helper functions to support binary patching for paravirt_ops.
ia64/pv_ops/xen/gate.S: xen gate page paravirtualization
ia64/pv_ops: paravirtualize gate.S.
ia64/pv_ops: move down __kernel_syscall_via_epc.
ia64/pv_ops/xen: define xen specific gate page.
ia64/pv_ops: gate page paravirtualization.
ia64/pv_ops/xen/pv_time_ops: implement sched_clock.
ia64/pv_ops/pv_time_ops: add sched_clock hook.
ia64/pv_ops/xen: paravirtualize read/write ar.itc and ar.itm
ia64/pv_ops: paravirtualize mov = ar.itc.
ia64/pv_ops/pvchecker: support mov = ar.itc paravirtualization
ia64/pv_ops: paravirtualize fsys.S.
...
Diffstat (limited to 'arch/ia64/kernel')
26 files changed, 1532 insertions, 205 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/acpi.c b/arch/ia64/kernel/acpi.c index bdef2ce38c8b..5510317db37b 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c | |||
| @@ -890,7 +890,7 @@ __init void prefill_possible_map(void) | |||
| 890 | possible, max((possible - available_cpus), 0)); | 890 | possible, max((possible - available_cpus), 0)); |
| 891 | 891 | ||
| 892 | for (i = 0; i < possible; i++) | 892 | for (i = 0; i < possible; i++) |
| 893 | cpu_set(i, cpu_possible_map); | 893 | set_cpu_possible(i, true); |
| 894 | } | 894 | } |
| 895 | 895 | ||
| 896 | int acpi_map_lsapic(acpi_handle handle, int *pcpu) | 896 | int acpi_map_lsapic(acpi_handle handle, int *pcpu) |
| @@ -928,9 +928,9 @@ int acpi_map_lsapic(acpi_handle handle, int *pcpu) | |||
| 928 | buffer.length = ACPI_ALLOCATE_BUFFER; | 928 | buffer.length = ACPI_ALLOCATE_BUFFER; |
| 929 | buffer.pointer = NULL; | 929 | buffer.pointer = NULL; |
| 930 | 930 | ||
| 931 | cpus_complement(tmp_map, cpu_present_map); | 931 | cpumask_complement(&tmp_map, cpu_present_mask); |
| 932 | cpu = first_cpu(tmp_map); | 932 | cpu = cpumask_first(&tmp_map); |
| 933 | if (cpu >= NR_CPUS) | 933 | if (cpu >= nr_cpu_ids) |
| 934 | return -EINVAL; | 934 | return -EINVAL; |
| 935 | 935 | ||
| 936 | acpi_map_cpu2node(handle, cpu, physid); | 936 | acpi_map_cpu2node(handle, cpu, physid); |
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/mca.c b/arch/ia64/kernel/mca.c index bab1de2d2f6a..8f33a8840422 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c | |||
| @@ -1456,9 +1456,9 @@ ia64_mca_cmc_int_caller(int cmc_irq, void *arg) | |||
| 1456 | 1456 | ||
| 1457 | ia64_mca_cmc_int_handler(cmc_irq, arg); | 1457 | ia64_mca_cmc_int_handler(cmc_irq, arg); |
| 1458 | 1458 | ||
| 1459 | for (++cpuid ; cpuid < NR_CPUS && !cpu_online(cpuid) ; cpuid++); | 1459 | cpuid = cpumask_next(cpuid+1, cpu_online_mask); |
| 1460 | 1460 | ||
| 1461 | if (cpuid < NR_CPUS) { | 1461 | if (cpuid < nr_cpu_ids) { |
| 1462 | platform_send_ipi(cpuid, IA64_CMCP_VECTOR, IA64_IPI_DM_INT, 0); | 1462 | platform_send_ipi(cpuid, IA64_CMCP_VECTOR, IA64_IPI_DM_INT, 0); |
| 1463 | } else { | 1463 | } else { |
| 1464 | /* If no log record, switch out of polling mode */ | 1464 | /* If no log record, switch out of polling mode */ |
| @@ -1525,7 +1525,7 @@ ia64_mca_cpe_int_caller(int cpe_irq, void *arg) | |||
| 1525 | 1525 | ||
| 1526 | ia64_mca_cpe_int_handler(cpe_irq, arg); | 1526 | ia64_mca_cpe_int_handler(cpe_irq, arg); |
| 1527 | 1527 | ||
| 1528 | for (++cpuid ; cpuid < NR_CPUS && !cpu_online(cpuid) ; cpuid++); | 1528 | cpuid = cpumask_next(cpuid+1, cpu_online_mask); |
| 1529 | 1529 | ||
| 1530 | if (cpuid < NR_CPUS) { | 1530 | if (cpuid < NR_CPUS) { |
| 1531 | platform_send_ipi(cpuid, IA64_CPEP_VECTOR, IA64_IPI_DM_INT, 0); | 1531 | platform_send_ipi(cpuid, IA64_CPEP_VECTOR, IA64_IPI_DM_INT, 0); |
diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c index aaa7d901521f..da3b0cf495a3 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); |
| @@ -525,8 +533,7 @@ get_ltoff (struct module *mod, uint64_t value, int *okp) | |||
| 525 | goto found; | 533 | goto found; |
| 526 | 534 | ||
| 527 | /* Not enough GOT entries? */ | 535 | /* Not enough GOT entries? */ |
| 528 | if (e >= (struct got_entry *) (mod->arch.got->sh_addr + mod->arch.got->sh_size)) | 536 | BUG_ON(e >= (struct got_entry *) (mod->arch.got->sh_addr + mod->arch.got->sh_size)); |
| 529 | BUG(); | ||
| 530 | 537 | ||
| 531 | e->val = value; | 538 | e->val = value; |
| 532 | ++mod->arch.next_got_entry; | 539 | ++mod->arch.next_got_entry; |
| @@ -921,6 +928,30 @@ module_finalize (const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *mo | |||
| 921 | DEBUGP("%s: init: entry=%p\n", __func__, mod->init); | 928 | DEBUGP("%s: init: entry=%p\n", __func__, mod->init); |
| 922 | if (mod->arch.unwind) | 929 | if (mod->arch.unwind) |
| 923 | register_unwind_table(mod); | 930 | register_unwind_table(mod); |
| 931 | #ifdef CONFIG_PARAVIRT | ||
| 932 | if (mod->arch.paravirt_bundles) { | ||
| 933 | struct paravirt_patch_site_bundle *start = | ||
| 934 | (struct paravirt_patch_site_bundle *) | ||
| 935 | mod->arch.paravirt_bundles->sh_addr; | ||
| 936 | struct paravirt_patch_site_bundle *end = | ||
| 937 | (struct paravirt_patch_site_bundle *) | ||
| 938 | (mod->arch.paravirt_bundles->sh_addr + | ||
| 939 | mod->arch.paravirt_bundles->sh_size); | ||
| 940 | |||
| 941 | paravirt_patch_apply_bundle(start, end); | ||
| 942 | } | ||
| 943 | if (mod->arch.paravirt_insts) { | ||
| 944 | struct paravirt_patch_site_inst *start = | ||
| 945 | (struct paravirt_patch_site_inst *) | ||
| 946 | mod->arch.paravirt_insts->sh_addr; | ||
| 947 | struct paravirt_patch_site_inst *end = | ||
| 948 | (struct paravirt_patch_site_inst *) | ||
| 949 | (mod->arch.paravirt_insts->sh_addr + | ||
| 950 | mod->arch.paravirt_insts->sh_size); | ||
| 951 | |||
| 952 | paravirt_patch_apply_inst(start, end); | ||
| 953 | } | ||
| 954 | #endif | ||
| 924 | return 0; | 955 | return 0; |
| 925 | } | 956 | } |
| 926 | 957 | ||
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/perfmon.c b/arch/ia64/kernel/perfmon.c index 5c0f408cfd71..8a06dc480594 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c | |||
| @@ -5603,7 +5603,7 @@ pfm_interrupt_handler(int irq, void *arg) | |||
| 5603 | * /proc/perfmon interface, for debug only | 5603 | * /proc/perfmon interface, for debug only |
| 5604 | */ | 5604 | */ |
| 5605 | 5605 | ||
| 5606 | #define PFM_PROC_SHOW_HEADER ((void *)NR_CPUS+1) | 5606 | #define PFM_PROC_SHOW_HEADER ((void *)nr_cpu_ids+1) |
| 5607 | 5607 | ||
| 5608 | static void * | 5608 | static void * |
| 5609 | pfm_proc_start(struct seq_file *m, loff_t *pos) | 5609 | pfm_proc_start(struct seq_file *m, loff_t *pos) |
| @@ -5612,7 +5612,7 @@ pfm_proc_start(struct seq_file *m, loff_t *pos) | |||
| 5612 | return PFM_PROC_SHOW_HEADER; | 5612 | return PFM_PROC_SHOW_HEADER; |
| 5613 | } | 5613 | } |
| 5614 | 5614 | ||
| 5615 | while (*pos <= NR_CPUS) { | 5615 | while (*pos <= nr_cpu_ids) { |
| 5616 | if (cpu_online(*pos - 1)) { | 5616 | if (cpu_online(*pos - 1)) { |
| 5617 | return (void *)*pos; | 5617 | return (void *)*pos; |
| 5618 | } | 5618 | } |
diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c index ecb9eb78d687..7053c55b7649 100644 --- a/arch/ia64/kernel/salinfo.c +++ b/arch/ia64/kernel/salinfo.c | |||
| @@ -317,7 +317,7 @@ retry: | |||
| 317 | } | 317 | } |
| 318 | 318 | ||
| 319 | n = data->cpu_check; | 319 | n = data->cpu_check; |
| 320 | for (i = 0; i < NR_CPUS; i++) { | 320 | for (i = 0; i < nr_cpu_ids; i++) { |
| 321 | if (cpu_isset(n, data->cpu_event)) { | 321 | if (cpu_isset(n, data->cpu_event)) { |
| 322 | if (!cpu_online(n)) { | 322 | if (!cpu_online(n)) { |
| 323 | cpu_clear(n, data->cpu_event); | 323 | cpu_clear(n, data->cpu_event); |
| @@ -326,7 +326,7 @@ retry: | |||
| 326 | cpu = n; | 326 | cpu = n; |
| 327 | break; | 327 | break; |
| 328 | } | 328 | } |
| 329 | if (++n == NR_CPUS) | 329 | if (++n == nr_cpu_ids) |
| 330 | n = 0; | 330 | n = 0; |
| 331 | } | 331 | } |
| 332 | 332 | ||
| @@ -337,7 +337,7 @@ retry: | |||
| 337 | 337 | ||
| 338 | /* for next read, start checking at next CPU */ | 338 | /* for next read, start checking at next CPU */ |
| 339 | data->cpu_check = cpu; | 339 | data->cpu_check = cpu; |
| 340 | if (++data->cpu_check == NR_CPUS) | 340 | if (++data->cpu_check == nr_cpu_ids) |
| 341 | data->cpu_check = 0; | 341 | data->cpu_check = 0; |
| 342 | 342 | ||
| 343 | snprintf(cmd, sizeof(cmd), "read %d\n", cpu); | 343 | snprintf(cmd, sizeof(cmd), "read %d\n", cpu); |
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 865af27c7737..714066aeda7f 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); |
| @@ -730,10 +732,10 @@ static void * | |||
| 730 | c_start (struct seq_file *m, loff_t *pos) | 732 | c_start (struct seq_file *m, loff_t *pos) |
| 731 | { | 733 | { |
| 732 | #ifdef CONFIG_SMP | 734 | #ifdef CONFIG_SMP |
| 733 | while (*pos < NR_CPUS && !cpu_isset(*pos, cpu_online_map)) | 735 | while (*pos < nr_cpu_ids && !cpu_online(*pos)) |
| 734 | ++*pos; | 736 | ++*pos; |
| 735 | #endif | 737 | #endif |
| 736 | return *pos < NR_CPUS ? cpu_data(*pos) : NULL; | 738 | return *pos < nr_cpu_ids ? cpu_data(*pos) : NULL; |
| 737 | } | 739 | } |
| 738 | 740 | ||
| 739 | static void * | 741 | static void * |
| @@ -1016,8 +1018,7 @@ cpu_init (void) | |||
| 1016 | | IA64_DCR_DA | IA64_DCR_DD | IA64_DCR_LC)); | 1018 | | IA64_DCR_DA | IA64_DCR_DD | IA64_DCR_LC)); |
| 1017 | atomic_inc(&init_mm.mm_count); | 1019 | atomic_inc(&init_mm.mm_count); |
| 1018 | current->active_mm = &init_mm; | 1020 | current->active_mm = &init_mm; |
| 1019 | if (current->mm) | 1021 | BUG_ON(current->mm); |
| 1020 | BUG(); | ||
| 1021 | 1022 | ||
| 1022 | ia64_mmu_init(ia64_imva(cpu_data)); | 1023 | ia64_mmu_init(ia64_imva(cpu_data)); |
| 1023 | ia64_mca_cpu_init(ia64_imva(cpu_data)); | 1024 | ia64_mca_cpu_init(ia64_imva(cpu_data)); |
diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c index da8f020d82c1..2ea4199d9c57 100644 --- a/arch/ia64/kernel/smp.c +++ b/arch/ia64/kernel/smp.c | |||
| @@ -166,11 +166,11 @@ send_IPI_allbutself (int op) | |||
| 166 | * Called with preemption disabled. | 166 | * Called with preemption disabled. |
| 167 | */ | 167 | */ |
| 168 | static inline void | 168 | static inline void |
| 169 | send_IPI_mask(cpumask_t mask, int op) | 169 | send_IPI_mask(const struct cpumask *mask, int op) |
| 170 | { | 170 | { |
| 171 | unsigned int cpu; | 171 | unsigned int cpu; |
| 172 | 172 | ||
| 173 | for_each_cpu_mask(cpu, mask) { | 173 | for_each_cpu(cpu, mask) { |
| 174 | send_IPI_single(cpu, op); | 174 | send_IPI_single(cpu, op); |
| 175 | } | 175 | } |
| 176 | } | 176 | } |
| @@ -316,7 +316,7 @@ void arch_send_call_function_single_ipi(int cpu) | |||
| 316 | send_IPI_single(cpu, IPI_CALL_FUNC_SINGLE); | 316 | send_IPI_single(cpu, IPI_CALL_FUNC_SINGLE); |
| 317 | } | 317 | } |
| 318 | 318 | ||
| 319 | void arch_send_call_function_ipi(cpumask_t mask) | 319 | void arch_send_call_function_ipi_mask(const struct cpumask *mask) |
| 320 | { | 320 | { |
| 321 | send_IPI_mask(mask, IPI_CALL_FUNC); | 321 | send_IPI_mask(mask, IPI_CALL_FUNC); |
| 322 | } | 322 | } |
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index 52290547c85b..7700e23034bb 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c | |||
| @@ -581,14 +581,14 @@ smp_build_cpu_map (void) | |||
| 581 | 581 | ||
| 582 | ia64_cpu_to_sapicid[0] = boot_cpu_id; | 582 | ia64_cpu_to_sapicid[0] = boot_cpu_id; |
| 583 | cpus_clear(cpu_present_map); | 583 | cpus_clear(cpu_present_map); |
| 584 | cpu_set(0, cpu_present_map); | 584 | set_cpu_present(0, true); |
| 585 | cpu_set(0, cpu_possible_map); | 585 | set_cpu_possible(0, true); |
| 586 | for (cpu = 1, i = 0; i < smp_boot_data.cpu_count; i++) { | 586 | for (cpu = 1, i = 0; i < smp_boot_data.cpu_count; i++) { |
| 587 | sapicid = smp_boot_data.cpu_phys_id[i]; | 587 | sapicid = smp_boot_data.cpu_phys_id[i]; |
| 588 | if (sapicid == boot_cpu_id) | 588 | if (sapicid == boot_cpu_id) |
| 589 | continue; | 589 | continue; |
| 590 | cpu_set(cpu, cpu_present_map); | 590 | set_cpu_present(cpu, true); |
| 591 | cpu_set(cpu, cpu_possible_map); | 591 | set_cpu_possible(cpu, true); |
| 592 | ia64_cpu_to_sapicid[cpu] = sapicid; | 592 | ia64_cpu_to_sapicid[cpu] = sapicid; |
| 593 | cpu++; | 593 | cpu++; |
| 594 | } | 594 | } |
| @@ -626,12 +626,9 @@ smp_prepare_cpus (unsigned int max_cpus) | |||
| 626 | */ | 626 | */ |
| 627 | if (!max_cpus) { | 627 | if (!max_cpus) { |
| 628 | printk(KERN_INFO "SMP mode deactivated.\n"); | 628 | printk(KERN_INFO "SMP mode deactivated.\n"); |
| 629 | cpus_clear(cpu_online_map); | 629 | init_cpu_online(cpumask_of(0)); |
| 630 | cpus_clear(cpu_present_map); | 630 | init_cpu_present(cpumask_of(0)); |
| 631 | cpus_clear(cpu_possible_map); | 631 | init_cpu_possible(cpumask_of(0)); |
| 632 | cpu_set(0, cpu_online_map); | ||
| 633 | cpu_set(0, cpu_present_map); | ||
| 634 | cpu_set(0, cpu_possible_map); | ||
| 635 | return; | 632 | return; |
| 636 | } | 633 | } |
| 637 | } | 634 | } |
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c index d6747bae52d8..641c8b61c4f1 100644 --- a/arch/ia64/kernel/time.c +++ b/arch/ia64/kernel/time.c | |||
| @@ -51,6 +51,15 @@ EXPORT_SYMBOL(last_cli_ip); | |||
| 51 | #endif | 51 | #endif |
| 52 | 52 | ||
| 53 | #ifdef CONFIG_PARAVIRT | 53 | #ifdef CONFIG_PARAVIRT |
| 54 | /* We need to define a real function for sched_clock, to override the | ||
| 55 | weak default version */ | ||
| 56 | unsigned long long sched_clock(void) | ||
| 57 | { | ||
| 58 | return paravirt_sched_clock(); | ||
| 59 | } | ||
| 60 | #endif | ||
| 61 | |||
| 62 | #ifdef CONFIG_PARAVIRT | ||
| 54 | static void | 63 | static void |
| 55 | paravirt_clocksource_resume(void) | 64 | paravirt_clocksource_resume(void) |
| 56 | { | 65 | { |
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 |
