diff options
| author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
|---|---|---|
| committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
| commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
| tree | 644b88f8a71896307d71438e9b3af49126ffb22b /arch/powerpc/kernel | |
| parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
| parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) | |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'arch/powerpc/kernel')
74 files changed, 3147 insertions, 1830 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index b23664a0b86c..877326320e74 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
| @@ -42,10 +42,11 @@ obj-$(CONFIG_ALTIVEC) += vecemu.o | |||
| 42 | obj-$(CONFIG_PPC_970_NAP) += idle_power4.o | 42 | obj-$(CONFIG_PPC_970_NAP) += idle_power4.o |
| 43 | obj-$(CONFIG_PPC_OF) += of_device.o of_platform.o prom_parse.o | 43 | obj-$(CONFIG_PPC_OF) += of_device.o of_platform.o prom_parse.o |
| 44 | obj-$(CONFIG_PPC_CLOCK) += clock.o | 44 | obj-$(CONFIG_PPC_CLOCK) += clock.o |
| 45 | procfs-$(CONFIG_PPC64) := proc_ppc64.o | 45 | procfs-y := proc_powerpc.o |
| 46 | obj-$(CONFIG_PROC_FS) += $(procfs-y) | 46 | obj-$(CONFIG_PROC_FS) += $(procfs-y) |
| 47 | rtaspci-$(CONFIG_PPC64)-$(CONFIG_PCI) := rtas_pci.o | 47 | rtaspci-$(CONFIG_PPC64)-$(CONFIG_PCI) := rtas_pci.o |
| 48 | obj-$(CONFIG_PPC_RTAS) += rtas.o rtas-rtc.o $(rtaspci-y-y) | 48 | obj-$(CONFIG_PPC_RTAS) += rtas.o rtas-rtc.o $(rtaspci-y-y) |
| 49 | obj-$(CONFIG_PPC_RTAS_DAEMON) += rtasd.o | ||
| 49 | obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o | 50 | obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o |
| 50 | obj-$(CONFIG_RTAS_PROC) += rtas-proc.o | 51 | obj-$(CONFIG_RTAS_PROC) += rtas-proc.o |
| 51 | obj-$(CONFIG_LPARCFG) += lparcfg.o | 52 | obj-$(CONFIG_LPARCFG) += lparcfg.o |
| @@ -97,11 +98,16 @@ obj64-$(CONFIG_AUDIT) += compat_audit.o | |||
| 97 | 98 | ||
| 98 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o | 99 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o |
| 99 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o | 100 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o |
| 100 | obj-$(CONFIG_PPC_PERF_CTRS) += perf_event.o perf_callchain.o | 101 | obj-$(CONFIG_PERF_EVENTS) += perf_callchain.o |
| 102 | |||
| 103 | obj-$(CONFIG_PPC_PERF_CTRS) += perf_event.o | ||
| 101 | obj64-$(CONFIG_PPC_PERF_CTRS) += power4-pmu.o ppc970-pmu.o power5-pmu.o \ | 104 | obj64-$(CONFIG_PPC_PERF_CTRS) += power4-pmu.o ppc970-pmu.o power5-pmu.o \ |
| 102 | power5+-pmu.o power6-pmu.o power7-pmu.o | 105 | power5+-pmu.o power6-pmu.o power7-pmu.o |
| 103 | obj32-$(CONFIG_PPC_PERF_CTRS) += mpc7450-pmu.o | 106 | obj32-$(CONFIG_PPC_PERF_CTRS) += mpc7450-pmu.o |
| 104 | 107 | ||
| 108 | obj-$(CONFIG_FSL_EMB_PERF_EVENT) += perf_event_fsl_emb.o | ||
| 109 | obj-$(CONFIG_FSL_EMB_PERF_EVENT_E500) += e500-pmu.o | ||
| 110 | |||
| 105 | obj-$(CONFIG_8XX_MINIMAL_FPEMU) += softemu8xx.o | 111 | obj-$(CONFIG_8XX_MINIMAL_FPEMU) += softemu8xx.o |
| 106 | 112 | ||
| 107 | ifneq ($(CONFIG_PPC_INDIRECT_IO),y) | 113 | ifneq ($(CONFIG_PPC_INDIRECT_IO),y) |
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c index a5b632e52fae..b876e989220b 100644 --- a/arch/powerpc/kernel/align.c +++ b/arch/powerpc/kernel/align.c | |||
| @@ -642,10 +642,14 @@ static int emulate_spe(struct pt_regs *regs, unsigned int reg, | |||
| 642 | */ | 642 | */ |
| 643 | static int emulate_vsx(unsigned char __user *addr, unsigned int reg, | 643 | static int emulate_vsx(unsigned char __user *addr, unsigned int reg, |
| 644 | unsigned int areg, struct pt_regs *regs, | 644 | unsigned int areg, struct pt_regs *regs, |
| 645 | unsigned int flags, unsigned int length) | 645 | unsigned int flags, unsigned int length, |
| 646 | unsigned int elsize) | ||
| 646 | { | 647 | { |
| 647 | char *ptr; | 648 | char *ptr; |
| 649 | unsigned long *lptr; | ||
| 648 | int ret = 0; | 650 | int ret = 0; |
| 651 | int sw = 0; | ||
| 652 | int i, j; | ||
| 649 | 653 | ||
| 650 | flush_vsx_to_thread(current); | 654 | flush_vsx_to_thread(current); |
| 651 | 655 | ||
| @@ -654,19 +658,35 @@ static int emulate_vsx(unsigned char __user *addr, unsigned int reg, | |||
| 654 | else | 658 | else |
| 655 | ptr = (char *) ¤t->thread.vr[reg - 32]; | 659 | ptr = (char *) ¤t->thread.vr[reg - 32]; |
| 656 | 660 | ||
| 657 | if (flags & ST) | 661 | lptr = (unsigned long *) ptr; |
| 658 | ret = __copy_to_user(addr, ptr, length); | 662 | |
| 659 | else { | 663 | if (flags & SW) |
| 660 | if (flags & SPLT){ | 664 | sw = elsize-1; |
| 661 | ret = __copy_from_user(ptr, addr, length); | 665 | |
| 662 | ptr += length; | 666 | for (j = 0; j < length; j += elsize) { |
| 667 | for (i = 0; i < elsize; ++i) { | ||
| 668 | if (flags & ST) | ||
| 669 | ret |= __put_user(ptr[i^sw], addr + i); | ||
| 670 | else | ||
| 671 | ret |= __get_user(ptr[i^sw], addr + i); | ||
| 663 | } | 672 | } |
| 664 | ret |= __copy_from_user(ptr, addr, length); | 673 | ptr += elsize; |
| 674 | addr += elsize; | ||
| 665 | } | 675 | } |
| 666 | if (flags & U) | 676 | |
| 667 | regs->gpr[areg] = regs->dar; | 677 | if (!ret) { |
| 668 | if (ret) | 678 | if (flags & U) |
| 679 | regs->gpr[areg] = regs->dar; | ||
| 680 | |||
| 681 | /* Splat load copies the same data to top and bottom 8 bytes */ | ||
| 682 | if (flags & SPLT) | ||
| 683 | lptr[1] = lptr[0]; | ||
| 684 | /* For 8 byte loads, zero the top 8 bytes */ | ||
| 685 | else if (!(flags & ST) && (8 == length)) | ||
| 686 | lptr[1] = 0; | ||
| 687 | } else | ||
| 669 | return -EFAULT; | 688 | return -EFAULT; |
| 689 | |||
| 670 | return 1; | 690 | return 1; |
| 671 | } | 691 | } |
| 672 | #endif | 692 | #endif |
| @@ -732,7 +752,7 @@ int fix_alignment(struct pt_regs *regs) | |||
| 732 | 752 | ||
| 733 | #ifdef CONFIG_SPE | 753 | #ifdef CONFIG_SPE |
| 734 | if ((instr >> 26) == 0x4) { | 754 | if ((instr >> 26) == 0x4) { |
| 735 | PPC_WARN_EMULATED(spe); | 755 | PPC_WARN_ALIGNMENT(spe, regs); |
| 736 | return emulate_spe(regs, reg, instr); | 756 | return emulate_spe(regs, reg, instr); |
| 737 | } | 757 | } |
| 738 | #endif | 758 | #endif |
| @@ -767,16 +787,25 @@ int fix_alignment(struct pt_regs *regs) | |||
| 767 | 787 | ||
| 768 | #ifdef CONFIG_VSX | 788 | #ifdef CONFIG_VSX |
| 769 | if ((instruction & 0xfc00003e) == 0x7c000018) { | 789 | if ((instruction & 0xfc00003e) == 0x7c000018) { |
| 770 | /* Additional register addressing bit (64 VSX vs 32 FPR/GPR */ | 790 | unsigned int elsize; |
| 791 | |||
| 792 | /* Additional register addressing bit (64 VSX vs 32 FPR/GPR) */ | ||
| 771 | reg |= (instruction & 0x1) << 5; | 793 | reg |= (instruction & 0x1) << 5; |
| 772 | /* Simple inline decoder instead of a table */ | 794 | /* Simple inline decoder instead of a table */ |
| 795 | /* VSX has only 8 and 16 byte memory accesses */ | ||
| 796 | nb = 8; | ||
| 773 | if (instruction & 0x200) | 797 | if (instruction & 0x200) |
| 774 | nb = 16; | 798 | nb = 16; |
| 775 | else if (instruction & 0x080) | 799 | |
| 776 | nb = 8; | 800 | /* Vector stores in little-endian mode swap individual |
| 777 | else | 801 | elements, so process them separately */ |
| 778 | nb = 4; | 802 | elsize = 4; |
| 803 | if (instruction & 0x80) | ||
| 804 | elsize = 8; | ||
| 805 | |||
| 779 | flags = 0; | 806 | flags = 0; |
| 807 | if (regs->msr & MSR_LE) | ||
| 808 | flags |= SW; | ||
| 780 | if (instruction & 0x100) | 809 | if (instruction & 0x100) |
| 781 | flags |= ST; | 810 | flags |= ST; |
| 782 | if (instruction & 0x040) | 811 | if (instruction & 0x040) |
| @@ -786,15 +815,15 @@ int fix_alignment(struct pt_regs *regs) | |||
| 786 | flags |= SPLT; | 815 | flags |= SPLT; |
| 787 | nb = 8; | 816 | nb = 8; |
| 788 | } | 817 | } |
| 789 | PPC_WARN_EMULATED(vsx); | 818 | PPC_WARN_ALIGNMENT(vsx, regs); |
| 790 | return emulate_vsx(addr, reg, areg, regs, flags, nb); | 819 | return emulate_vsx(addr, reg, areg, regs, flags, nb, elsize); |
| 791 | } | 820 | } |
| 792 | #endif | 821 | #endif |
| 793 | /* A size of 0 indicates an instruction we don't support, with | 822 | /* A size of 0 indicates an instruction we don't support, with |
| 794 | * the exception of DCBZ which is handled as a special case here | 823 | * the exception of DCBZ which is handled as a special case here |
| 795 | */ | 824 | */ |
| 796 | if (instr == DCBZ) { | 825 | if (instr == DCBZ) { |
| 797 | PPC_WARN_EMULATED(dcbz); | 826 | PPC_WARN_ALIGNMENT(dcbz, regs); |
| 798 | return emulate_dcbz(regs, addr); | 827 | return emulate_dcbz(regs, addr); |
| 799 | } | 828 | } |
| 800 | if (unlikely(nb == 0)) | 829 | if (unlikely(nb == 0)) |
| @@ -804,7 +833,7 @@ int fix_alignment(struct pt_regs *regs) | |||
| 804 | * function | 833 | * function |
| 805 | */ | 834 | */ |
| 806 | if (flags & M) { | 835 | if (flags & M) { |
| 807 | PPC_WARN_EMULATED(multiple); | 836 | PPC_WARN_ALIGNMENT(multiple, regs); |
| 808 | return emulate_multiple(regs, addr, reg, nb, | 837 | return emulate_multiple(regs, addr, reg, nb, |
| 809 | flags, instr, swiz); | 838 | flags, instr, swiz); |
| 810 | } | 839 | } |
| @@ -825,11 +854,11 @@ int fix_alignment(struct pt_regs *regs) | |||
| 825 | 854 | ||
| 826 | /* Special case for 16-byte FP loads and stores */ | 855 | /* Special case for 16-byte FP loads and stores */ |
| 827 | if (nb == 16) { | 856 | if (nb == 16) { |
| 828 | PPC_WARN_EMULATED(fp_pair); | 857 | PPC_WARN_ALIGNMENT(fp_pair, regs); |
| 829 | return emulate_fp_pair(addr, reg, flags); | 858 | return emulate_fp_pair(addr, reg, flags); |
| 830 | } | 859 | } |
| 831 | 860 | ||
| 832 | PPC_WARN_EMULATED(unaligned); | 861 | PPC_WARN_ALIGNMENT(unaligned, regs); |
| 833 | 862 | ||
| 834 | /* If we are loading, get the data from user space, else | 863 | /* If we are loading, get the data from user space, else |
| 835 | * get it from register values | 864 | * get it from register values |
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 0812b0f414bb..c09138d150d4 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
| @@ -133,7 +133,6 @@ int main(void) | |||
| 133 | DEFINE(PACAKMSR, offsetof(struct paca_struct, kernel_msr)); | 133 | DEFINE(PACAKMSR, offsetof(struct paca_struct, kernel_msr)); |
| 134 | DEFINE(PACASOFTIRQEN, offsetof(struct paca_struct, soft_enabled)); | 134 | DEFINE(PACASOFTIRQEN, offsetof(struct paca_struct, soft_enabled)); |
| 135 | DEFINE(PACAHARDIRQEN, offsetof(struct paca_struct, hard_enabled)); | 135 | DEFINE(PACAHARDIRQEN, offsetof(struct paca_struct, hard_enabled)); |
| 136 | DEFINE(PACAPERFPEND, offsetof(struct paca_struct, perf_event_pending)); | ||
| 137 | DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); | 136 | DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); |
| 138 | #ifdef CONFIG_PPC_MM_SLICES | 137 | #ifdef CONFIG_PPC_MM_SLICES |
| 139 | DEFINE(PACALOWSLICESPSIZE, offsetof(struct paca_struct, | 138 | DEFINE(PACALOWSLICESPSIZE, offsetof(struct paca_struct, |
| @@ -190,6 +189,35 @@ int main(void) | |||
| 190 | DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time)); | 189 | DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time)); |
| 191 | DEFINE(PACA_DATA_OFFSET, offsetof(struct paca_struct, data_offset)); | 190 | DEFINE(PACA_DATA_OFFSET, offsetof(struct paca_struct, data_offset)); |
| 192 | DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save)); | 191 | DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save)); |
| 192 | #ifdef CONFIG_KVM_BOOK3S_64_HANDLER | ||
| 193 | DEFINE(PACA_KVM_IN_GUEST, offsetof(struct paca_struct, kvm_in_guest)); | ||
| 194 | DEFINE(PACA_KVM_SLB, offsetof(struct paca_struct, kvm_slb)); | ||
| 195 | DEFINE(PACA_KVM_SLB_MAX, offsetof(struct paca_struct, kvm_slb_max)); | ||
| 196 | DEFINE(PACA_KVM_CR, offsetof(struct paca_struct, shadow_vcpu.cr)); | ||
| 197 | DEFINE(PACA_KVM_XER, offsetof(struct paca_struct, shadow_vcpu.xer)); | ||
| 198 | DEFINE(PACA_KVM_R0, offsetof(struct paca_struct, shadow_vcpu.gpr[0])); | ||
| 199 | DEFINE(PACA_KVM_R1, offsetof(struct paca_struct, shadow_vcpu.gpr[1])); | ||
| 200 | DEFINE(PACA_KVM_R2, offsetof(struct paca_struct, shadow_vcpu.gpr[2])); | ||
| 201 | DEFINE(PACA_KVM_R3, offsetof(struct paca_struct, shadow_vcpu.gpr[3])); | ||
| 202 | DEFINE(PACA_KVM_R4, offsetof(struct paca_struct, shadow_vcpu.gpr[4])); | ||
| 203 | DEFINE(PACA_KVM_R5, offsetof(struct paca_struct, shadow_vcpu.gpr[5])); | ||
| 204 | DEFINE(PACA_KVM_R6, offsetof(struct paca_struct, shadow_vcpu.gpr[6])); | ||
| 205 | DEFINE(PACA_KVM_R7, offsetof(struct paca_struct, shadow_vcpu.gpr[7])); | ||
| 206 | DEFINE(PACA_KVM_R8, offsetof(struct paca_struct, shadow_vcpu.gpr[8])); | ||
| 207 | DEFINE(PACA_KVM_R9, offsetof(struct paca_struct, shadow_vcpu.gpr[9])); | ||
| 208 | DEFINE(PACA_KVM_R10, offsetof(struct paca_struct, shadow_vcpu.gpr[10])); | ||
| 209 | DEFINE(PACA_KVM_R11, offsetof(struct paca_struct, shadow_vcpu.gpr[11])); | ||
| 210 | DEFINE(PACA_KVM_R12, offsetof(struct paca_struct, shadow_vcpu.gpr[12])); | ||
| 211 | DEFINE(PACA_KVM_R13, offsetof(struct paca_struct, shadow_vcpu.gpr[13])); | ||
| 212 | DEFINE(PACA_KVM_HOST_R1, offsetof(struct paca_struct, shadow_vcpu.host_r1)); | ||
| 213 | DEFINE(PACA_KVM_HOST_R2, offsetof(struct paca_struct, shadow_vcpu.host_r2)); | ||
| 214 | DEFINE(PACA_KVM_VMHANDLER, offsetof(struct paca_struct, | ||
| 215 | shadow_vcpu.vmhandler)); | ||
| 216 | DEFINE(PACA_KVM_SCRATCH0, offsetof(struct paca_struct, | ||
| 217 | shadow_vcpu.scratch0)); | ||
| 218 | DEFINE(PACA_KVM_SCRATCH1, offsetof(struct paca_struct, | ||
| 219 | shadow_vcpu.scratch1)); | ||
| 220 | #endif | ||
| 193 | #endif /* CONFIG_PPC64 */ | 221 | #endif /* CONFIG_PPC64 */ |
| 194 | 222 | ||
| 195 | /* RTAS */ | 223 | /* RTAS */ |
| @@ -384,8 +412,6 @@ int main(void) | |||
| 384 | DEFINE(VCPU_HOST_PID, offsetof(struct kvm_vcpu, arch.host_pid)); | 412 | DEFINE(VCPU_HOST_PID, offsetof(struct kvm_vcpu, arch.host_pid)); |
| 385 | DEFINE(VCPU_GPRS, offsetof(struct kvm_vcpu, arch.gpr)); | 413 | DEFINE(VCPU_GPRS, offsetof(struct kvm_vcpu, arch.gpr)); |
| 386 | DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr)); | 414 | DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr)); |
| 387 | DEFINE(VCPU_CR, offsetof(struct kvm_vcpu, arch.cr)); | ||
| 388 | DEFINE(VCPU_XER, offsetof(struct kvm_vcpu, arch.xer)); | ||
| 389 | DEFINE(VCPU_CTR, offsetof(struct kvm_vcpu, arch.ctr)); | 415 | DEFINE(VCPU_CTR, offsetof(struct kvm_vcpu, arch.ctr)); |
| 390 | DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.pc)); | 416 | DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.pc)); |
| 391 | DEFINE(VCPU_MSR, offsetof(struct kvm_vcpu, arch.msr)); | 417 | DEFINE(VCPU_MSR, offsetof(struct kvm_vcpu, arch.msr)); |
| @@ -398,14 +424,29 @@ int main(void) | |||
| 398 | DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst)); | 424 | DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst)); |
| 399 | DEFINE(VCPU_FAULT_DEAR, offsetof(struct kvm_vcpu, arch.fault_dear)); | 425 | DEFINE(VCPU_FAULT_DEAR, offsetof(struct kvm_vcpu, arch.fault_dear)); |
| 400 | DEFINE(VCPU_FAULT_ESR, offsetof(struct kvm_vcpu, arch.fault_esr)); | 426 | DEFINE(VCPU_FAULT_ESR, offsetof(struct kvm_vcpu, arch.fault_esr)); |
| 427 | |||
| 428 | /* book3s_64 */ | ||
| 429 | #ifdef CONFIG_PPC64 | ||
| 430 | DEFINE(VCPU_FAULT_DSISR, offsetof(struct kvm_vcpu, arch.fault_dsisr)); | ||
| 431 | DEFINE(VCPU_HOST_RETIP, offsetof(struct kvm_vcpu, arch.host_retip)); | ||
| 432 | DEFINE(VCPU_HOST_R2, offsetof(struct kvm_vcpu, arch.host_r2)); | ||
| 433 | DEFINE(VCPU_HOST_MSR, offsetof(struct kvm_vcpu, arch.host_msr)); | ||
| 434 | DEFINE(VCPU_SHADOW_MSR, offsetof(struct kvm_vcpu, arch.shadow_msr)); | ||
| 435 | DEFINE(VCPU_SHADOW_SRR1, offsetof(struct kvm_vcpu, arch.shadow_srr1)); | ||
| 436 | DEFINE(VCPU_TRAMPOLINE_LOWMEM, offsetof(struct kvm_vcpu, arch.trampoline_lowmem)); | ||
| 437 | DEFINE(VCPU_TRAMPOLINE_ENTER, offsetof(struct kvm_vcpu, arch.trampoline_enter)); | ||
| 438 | DEFINE(VCPU_HIGHMEM_HANDLER, offsetof(struct kvm_vcpu, arch.highmem_handler)); | ||
| 439 | DEFINE(VCPU_RMCALL, offsetof(struct kvm_vcpu, arch.rmcall)); | ||
| 440 | DEFINE(VCPU_HFLAGS, offsetof(struct kvm_vcpu, arch.hflags)); | ||
| 441 | #else | ||
| 442 | DEFINE(VCPU_CR, offsetof(struct kvm_vcpu, arch.cr)); | ||
| 443 | DEFINE(VCPU_XER, offsetof(struct kvm_vcpu, arch.xer)); | ||
| 444 | #endif /* CONFIG_PPC64 */ | ||
| 401 | #endif | 445 | #endif |
| 402 | #ifdef CONFIG_44x | 446 | #ifdef CONFIG_44x |
| 403 | DEFINE(PGD_T_LOG2, PGD_T_LOG2); | 447 | DEFINE(PGD_T_LOG2, PGD_T_LOG2); |
| 404 | DEFINE(PTE_T_LOG2, PTE_T_LOG2); | 448 | DEFINE(PTE_T_LOG2, PTE_T_LOG2); |
| 405 | #endif | 449 | #endif |
| 406 | #ifdef CONFIG_FSL_BOOKE | ||
| 407 | DEFINE(TLBCAM_SIZE, sizeof(struct tlbcam)); | ||
| 408 | #endif | ||
| 409 | 450 | ||
| 410 | #ifdef CONFIG_KVM_EXIT_TIMING | 451 | #ifdef CONFIG_KVM_EXIT_TIMING |
| 411 | DEFINE(VCPU_TIMING_EXIT_TBU, offsetof(struct kvm_vcpu, | 452 | DEFINE(VCPU_TIMING_EXIT_TBU, offsetof(struct kvm_vcpu, |
diff --git a/arch/powerpc/kernel/cacheinfo.c b/arch/powerpc/kernel/cacheinfo.c index bb37b1d19a58..a3c684b4c862 100644 --- a/arch/powerpc/kernel/cacheinfo.c +++ b/arch/powerpc/kernel/cacheinfo.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/notifier.h> | 19 | #include <linux/notifier.h> |
| 20 | #include <linux/of.h> | 20 | #include <linux/of.h> |
| 21 | #include <linux/percpu.h> | 21 | #include <linux/percpu.h> |
| 22 | #include <linux/slab.h> | ||
| 22 | #include <asm/prom.h> | 23 | #include <asm/prom.h> |
| 23 | 24 | ||
| 24 | #include "cacheinfo.h" | 25 | #include "cacheinfo.h" |
| @@ -642,7 +643,7 @@ static struct kobj_attribute *cache_index_opt_attrs[] = { | |||
| 642 | &cache_assoc_attr, | 643 | &cache_assoc_attr, |
| 643 | }; | 644 | }; |
| 644 | 645 | ||
| 645 | static struct sysfs_ops cache_index_ops = { | 646 | static const struct sysfs_ops cache_index_ops = { |
| 646 | .show = cache_index_show, | 647 | .show = cache_index_show, |
| 647 | }; | 648 | }; |
| 648 | 649 | ||
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 03c862b6a9c4..8af4949434b2 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
| @@ -697,9 +697,9 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
| 697 | .machine_check = machine_check_generic, | 697 | .machine_check = machine_check_generic, |
| 698 | .platform = "ppc750", | 698 | .platform = "ppc750", |
| 699 | }, | 699 | }, |
| 700 | { /* 750CL */ | 700 | { /* 750CL (and "Broadway") */ |
| 701 | .pvr_mask = 0xfffff0f0, | 701 | .pvr_mask = 0xfffff0e0, |
| 702 | .pvr_value = 0x00087010, | 702 | .pvr_value = 0x00087000, |
| 703 | .cpu_name = "750CL", | 703 | .cpu_name = "750CL", |
| 704 | .cpu_features = CPU_FTRS_750CL, | 704 | .cpu_features = CPU_FTRS_750CL, |
| 705 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, | 705 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
| @@ -1808,7 +1808,7 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
| 1808 | .icache_bsize = 64, | 1808 | .icache_bsize = 64, |
| 1809 | .dcache_bsize = 64, | 1809 | .dcache_bsize = 64, |
| 1810 | .num_pmcs = 4, | 1810 | .num_pmcs = 4, |
| 1811 | .oprofile_cpu_type = "ppc/e500", /* xxx - galak, e500mc? */ | 1811 | .oprofile_cpu_type = "ppc/e500mc", |
| 1812 | .oprofile_type = PPC_OPROFILE_FSL_EMB, | 1812 | .oprofile_type = PPC_OPROFILE_FSL_EMB, |
| 1813 | .cpu_setup = __setup_cpu_e500mc, | 1813 | .cpu_setup = __setup_cpu_e500mc, |
| 1814 | .machine_check = machine_check_e500, | 1814 | .machine_check = machine_check_e500, |
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c index 0a8439aafdd1..6f4613dd05ef 100644 --- a/arch/powerpc/kernel/crash.c +++ b/arch/powerpc/kernel/crash.c | |||
| @@ -373,7 +373,7 @@ void default_machine_crash_shutdown(struct pt_regs *regs) | |||
| 373 | hard_irq_disable(); | 373 | hard_irq_disable(); |
| 374 | 374 | ||
| 375 | for_each_irq(i) { | 375 | for_each_irq(i) { |
| 376 | struct irq_desc *desc = irq_desc + i; | 376 | struct irq_desc *desc = irq_to_desc(i); |
| 377 | 377 | ||
| 378 | if (desc->status & IRQ_INPROGRESS) | 378 | if (desc->status & IRQ_INPROGRESS) |
| 379 | desc->chip->eoi(i); | 379 | desc->chip->eoi(i); |
diff --git a/arch/powerpc/kernel/dma-swiotlb.c b/arch/powerpc/kernel/dma-swiotlb.c index e96cbbd9b449..4ff4da2c238b 100644 --- a/arch/powerpc/kernel/dma-swiotlb.c +++ b/arch/powerpc/kernel/dma-swiotlb.c | |||
| @@ -1,7 +1,8 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Contains routines needed to support swiotlb for ppc. | 2 | * Contains routines needed to support swiotlb for ppc. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2009 Becky Bruce, Freescale Semiconductor | 4 | * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. |
| 5 | * Author: Becky Bruce | ||
| 5 | * | 6 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 7 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms of the GNU General Public License as published by the | 8 | * under the terms of the GNU General Public License as published by the |
| @@ -21,7 +22,6 @@ | |||
| 21 | #include <asm/dma.h> | 22 | #include <asm/dma.h> |
| 22 | #include <asm/abs_addr.h> | 23 | #include <asm/abs_addr.h> |
| 23 | 24 | ||
| 24 | int swiotlb __read_mostly; | ||
| 25 | unsigned int ppc_swiotlb_enable; | 25 | unsigned int ppc_swiotlb_enable; |
| 26 | 26 | ||
| 27 | /* | 27 | /* |
| @@ -71,7 +71,7 @@ static int ppc_swiotlb_bus_notify(struct notifier_block *nb, | |||
| 71 | sd->max_direct_dma_addr = 0; | 71 | sd->max_direct_dma_addr = 0; |
| 72 | 72 | ||
| 73 | /* May need to bounce if the device can't address all of DRAM */ | 73 | /* May need to bounce if the device can't address all of DRAM */ |
| 74 | if (dma_get_mask(dev) < lmb_end_of_DRAM()) | 74 | if ((dma_get_mask(dev) + 1) < lmb_end_of_DRAM()) |
| 75 | set_dma_ops(dev, &swiotlb_dma_ops); | 75 | set_dma_ops(dev, &swiotlb_dma_ops); |
| 76 | 76 | ||
| 77 | return NOTIFY_DONE; | 77 | return NOTIFY_DONE; |
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c index 6215062caf8c..6c1df5757cd6 100644 --- a/arch/powerpc/kernel/dma.c +++ b/arch/powerpc/kernel/dma.c | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <linux/device.h> | 8 | #include <linux/device.h> |
| 9 | #include <linux/dma-mapping.h> | 9 | #include <linux/dma-mapping.h> |
| 10 | #include <linux/dma-debug.h> | 10 | #include <linux/dma-debug.h> |
| 11 | #include <linux/gfp.h> | ||
| 11 | #include <linux/lmb.h> | 12 | #include <linux/lmb.h> |
| 12 | #include <asm/bug.h> | 13 | #include <asm/bug.h> |
| 13 | #include <asm/abs_addr.h> | 14 | #include <asm/abs_addr.h> |
diff --git a/arch/powerpc/kernel/e500-pmu.c b/arch/powerpc/kernel/e500-pmu.c new file mode 100644 index 000000000000..7c07de0d8943 --- /dev/null +++ b/arch/powerpc/kernel/e500-pmu.c | |||
| @@ -0,0 +1,129 @@ | |||
| 1 | /* | ||
| 2 | * Performance counter support for e500 family processors. | ||
| 3 | * | ||
| 4 | * Copyright 2008-2009 Paul Mackerras, IBM Corporation. | ||
| 5 | * Copyright 2010 Freescale Semiconductor, Inc. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU General Public License | ||
| 9 | * as published by the Free Software Foundation; either version | ||
| 10 | * 2 of the License, or (at your option) any later version. | ||
| 11 | */ | ||
| 12 | #include <linux/string.h> | ||
| 13 | #include <linux/perf_event.h> | ||
| 14 | #include <asm/reg.h> | ||
| 15 | #include <asm/cputable.h> | ||
| 16 | |||
| 17 | /* | ||
| 18 | * Map of generic hardware event types to hardware events | ||
| 19 | * Zero if unsupported | ||
| 20 | */ | ||
| 21 | static int e500_generic_events[] = { | ||
| 22 | [PERF_COUNT_HW_CPU_CYCLES] = 1, | ||
| 23 | [PERF_COUNT_HW_INSTRUCTIONS] = 2, | ||
| 24 | [PERF_COUNT_HW_CACHE_MISSES] = 41, /* Data L1 cache reloads */ | ||
| 25 | [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 12, | ||
| 26 | [PERF_COUNT_HW_BRANCH_MISSES] = 15, | ||
| 27 | }; | ||
| 28 | |||
| 29 | #define C(x) PERF_COUNT_HW_CACHE_##x | ||
| 30 | |||
| 31 | /* | ||
| 32 | * Table of generalized cache-related events. | ||
| 33 | * 0 means not supported, -1 means nonsensical, other values | ||
| 34 | * are event codes. | ||
| 35 | */ | ||
| 36 | static int e500_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = { | ||
| 37 | /* | ||
| 38 | * D-cache misses are not split into read/write/prefetch; | ||
| 39 | * use raw event 41. | ||
| 40 | */ | ||
| 41 | [C(L1D)] = { /* RESULT_ACCESS RESULT_MISS */ | ||
| 42 | [C(OP_READ)] = { 27, 0 }, | ||
| 43 | [C(OP_WRITE)] = { 28, 0 }, | ||
| 44 | [C(OP_PREFETCH)] = { 29, 0 }, | ||
| 45 | }, | ||
| 46 | [C(L1I)] = { /* RESULT_ACCESS RESULT_MISS */ | ||
| 47 | [C(OP_READ)] = { 2, 60 }, | ||
| 48 | [C(OP_WRITE)] = { -1, -1 }, | ||
| 49 | [C(OP_PREFETCH)] = { 0, 0 }, | ||
| 50 | }, | ||
| 51 | /* | ||
| 52 | * Assuming LL means L2, it's not a good match for this model. | ||
| 53 | * It allocates only on L1 castout or explicit prefetch, and | ||
| 54 | * does not have separate read/write events (but it does have | ||
| 55 | * separate instruction/data events). | ||
| 56 | */ | ||
| 57 | [C(LL)] = { /* RESULT_ACCESS RESULT_MISS */ | ||
| 58 | [C(OP_READ)] = { 0, 0 }, | ||
| 59 | [C(OP_WRITE)] = { 0, 0 }, | ||
| 60 | [C(OP_PREFETCH)] = { 0, 0 }, | ||
| 61 | }, | ||
| 62 | /* | ||
| 63 | * There are data/instruction MMU misses, but that's a miss on | ||
| 64 | * the chip's internal level-one TLB which is probably not | ||
| 65 | * what the user wants. Instead, unified level-two TLB misses | ||
| 66 | * are reported here. | ||
| 67 | */ | ||
| 68 | [C(DTLB)] = { /* RESULT_ACCESS RESULT_MISS */ | ||
| 69 | [C(OP_READ)] = { 26, 66 }, | ||
| 70 | [C(OP_WRITE)] = { -1, -1 }, | ||
| 71 | [C(OP_PREFETCH)] = { -1, -1 }, | ||
| 72 | }, | ||
| 73 | [C(BPU)] = { /* RESULT_ACCESS RESULT_MISS */ | ||
| 74 | [C(OP_READ)] = { 12, 15 }, | ||
| 75 | [C(OP_WRITE)] = { -1, -1 }, | ||
| 76 | [C(OP_PREFETCH)] = { -1, -1 }, | ||
| 77 | }, | ||
| 78 | }; | ||
| 79 | |||
| 80 | static int num_events = 128; | ||
| 81 | |||
| 82 | /* Upper half of event id is PMLCb, for threshold events */ | ||
| 83 | static u64 e500_xlate_event(u64 event_id) | ||
| 84 | { | ||
| 85 | u32 event_low = (u32)event_id; | ||
| 86 | u64 ret; | ||
| 87 | |||
| 88 | if (event_low >= num_events) | ||
| 89 | return 0; | ||
| 90 | |||
| 91 | ret = FSL_EMB_EVENT_VALID; | ||
| 92 | |||
| 93 | if (event_low >= 76 && event_low <= 81) { | ||
| 94 | ret |= FSL_EMB_EVENT_RESTRICTED; | ||
| 95 | ret |= event_id & | ||
| 96 | (FSL_EMB_EVENT_THRESHMUL | FSL_EMB_EVENT_THRESH); | ||
| 97 | } else if (event_id & | ||
| 98 | (FSL_EMB_EVENT_THRESHMUL | FSL_EMB_EVENT_THRESH)) { | ||
| 99 | /* Threshold requested on non-threshold event */ | ||
| 100 | return 0; | ||
| 101 | } | ||
| 102 | |||
| 103 | return ret; | ||
| 104 | } | ||
| 105 | |||
| 106 | static struct fsl_emb_pmu e500_pmu = { | ||
| 107 | .name = "e500 family", | ||
| 108 | .n_counter = 4, | ||
| 109 | .n_restricted = 2, | ||
| 110 | .xlate_event = e500_xlate_event, | ||
| 111 | .n_generic = ARRAY_SIZE(e500_generic_events), | ||
| 112 | .generic_events = e500_generic_events, | ||
| 113 | .cache_events = &e500_cache_events, | ||
| 114 | }; | ||
| 115 | |||
| 116 | static int init_e500_pmu(void) | ||
| 117 | { | ||
| 118 | if (!cur_cpu_spec->oprofile_cpu_type) | ||
| 119 | return -ENODEV; | ||
| 120 | |||
| 121 | if (!strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc/e500mc")) | ||
| 122 | num_events = 256; | ||
| 123 | else if (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc/e500")) | ||
| 124 | return -ENODEV; | ||
| 125 | |||
| 126 | return register_fsl_emb_pmu(&e500_pmu); | ||
| 127 | } | ||
| 128 | |||
| 129 | arch_initcall(init_e500_pmu); | ||
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 9763267e38b4..42e9d908914a 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
| @@ -551,20 +551,11 @@ restore: | |||
| 551 | BEGIN_FW_FTR_SECTION | 551 | BEGIN_FW_FTR_SECTION |
| 552 | ld r5,SOFTE(r1) | 552 | ld r5,SOFTE(r1) |
| 553 | FW_FTR_SECTION_ELSE | 553 | FW_FTR_SECTION_ELSE |
| 554 | b iseries_check_pending_irqs | 554 | b .Liseries_check_pending_irqs |
| 555 | ALT_FW_FTR_SECTION_END_IFCLR(FW_FEATURE_ISERIES) | 555 | ALT_FW_FTR_SECTION_END_IFCLR(FW_FEATURE_ISERIES) |
| 556 | 2: | 556 | 2: |
| 557 | TRACE_AND_RESTORE_IRQ(r5); | 557 | TRACE_AND_RESTORE_IRQ(r5); |
| 558 | 558 | ||
| 559 | #ifdef CONFIG_PERF_EVENTS | ||
| 560 | /* check paca->perf_event_pending if we're enabling ints */ | ||
| 561 | lbz r3,PACAPERFPEND(r13) | ||
| 562 | and. r3,r3,r5 | ||
| 563 | beq 27f | ||
| 564 | bl .perf_event_do_pending | ||
| 565 | 27: | ||
| 566 | #endif /* CONFIG_PERF_EVENTS */ | ||
| 567 | |||
| 568 | /* extract EE bit and use it to restore paca->hard_enabled */ | 559 | /* extract EE bit and use it to restore paca->hard_enabled */ |
| 569 | ld r3,_MSR(r1) | 560 | ld r3,_MSR(r1) |
| 570 | rldicl r4,r3,49,63 /* r0 = (r3 >> 15) & 1 */ | 561 | rldicl r4,r3,49,63 /* r0 = (r3 >> 15) & 1 */ |
| @@ -623,7 +614,7 @@ ALT_FW_FTR_SECTION_END_IFCLR(FW_FEATURE_ISERIES) | |||
| 623 | 614 | ||
| 624 | #endif /* CONFIG_PPC_BOOK3E */ | 615 | #endif /* CONFIG_PPC_BOOK3E */ |
| 625 | 616 | ||
| 626 | iseries_check_pending_irqs: | 617 | .Liseries_check_pending_irqs: |
| 627 | #ifdef CONFIG_PPC_ISERIES | 618 | #ifdef CONFIG_PPC_ISERIES |
| 628 | ld r5,SOFTE(r1) | 619 | ld r5,SOFTE(r1) |
| 629 | cmpdi 0,r5,0 | 620 | cmpdi 0,r5,0 |
| @@ -791,9 +782,8 @@ _GLOBAL(enter_rtas) | |||
| 791 | 782 | ||
| 792 | li r9,1 | 783 | li r9,1 |
| 793 | rldicr r9,r9,MSR_SF_LG,(63-MSR_SF_LG) | 784 | rldicr r9,r9,MSR_SF_LG,(63-MSR_SF_LG) |
| 794 | ori r9,r9,MSR_IR|MSR_DR|MSR_FE0|MSR_FE1|MSR_FP | 785 | ori r9,r9,MSR_IR|MSR_DR|MSR_FE0|MSR_FE1|MSR_FP|MSR_RI |
| 795 | andc r6,r0,r9 | 786 | andc r6,r0,r9 |
| 796 | ori r6,r6,MSR_RI | ||
| 797 | sync /* disable interrupts so SRR0/1 */ | 787 | sync /* disable interrupts so SRR0/1 */ |
| 798 | mtmsrd r0 /* don't get trashed */ | 788 | mtmsrd r0 /* don't get trashed */ |
| 799 | 789 | ||
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index 1808876edcc9..e3be98ffe2a7 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
| @@ -41,6 +41,7 @@ __start_interrupts: | |||
| 41 | . = 0x200 | 41 | . = 0x200 |
| 42 | _machine_check_pSeries: | 42 | _machine_check_pSeries: |
| 43 | HMT_MEDIUM | 43 | HMT_MEDIUM |
| 44 | DO_KVM 0x200 | ||
| 44 | mtspr SPRN_SPRG_SCRATCH0,r13 /* save r13 */ | 45 | mtspr SPRN_SPRG_SCRATCH0,r13 /* save r13 */ |
| 45 | EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common) | 46 | EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common) |
| 46 | 47 | ||
| @@ -48,6 +49,7 @@ _machine_check_pSeries: | |||
| 48 | .globl data_access_pSeries | 49 | .globl data_access_pSeries |
| 49 | data_access_pSeries: | 50 | data_access_pSeries: |
| 50 | HMT_MEDIUM | 51 | HMT_MEDIUM |
| 52 | DO_KVM 0x300 | ||
| 51 | mtspr SPRN_SPRG_SCRATCH0,r13 | 53 | mtspr SPRN_SPRG_SCRATCH0,r13 |
| 52 | BEGIN_FTR_SECTION | 54 | BEGIN_FTR_SECTION |
| 53 | mfspr r13,SPRN_SPRG_PACA | 55 | mfspr r13,SPRN_SPRG_PACA |
| @@ -77,6 +79,7 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_SLB) | |||
| 77 | .globl data_access_slb_pSeries | 79 | .globl data_access_slb_pSeries |
| 78 | data_access_slb_pSeries: | 80 | data_access_slb_pSeries: |
| 79 | HMT_MEDIUM | 81 | HMT_MEDIUM |
| 82 | DO_KVM 0x380 | ||
| 80 | mtspr SPRN_SPRG_SCRATCH0,r13 | 83 | mtspr SPRN_SPRG_SCRATCH0,r13 |
| 81 | mfspr r13,SPRN_SPRG_PACA /* get paca address into r13 */ | 84 | mfspr r13,SPRN_SPRG_PACA /* get paca address into r13 */ |
| 82 | std r3,PACA_EXSLB+EX_R3(r13) | 85 | std r3,PACA_EXSLB+EX_R3(r13) |
| @@ -115,6 +118,7 @@ data_access_slb_pSeries: | |||
| 115 | .globl instruction_access_slb_pSeries | 118 | .globl instruction_access_slb_pSeries |
| 116 | instruction_access_slb_pSeries: | 119 | instruction_access_slb_pSeries: |
| 117 | HMT_MEDIUM | 120 | HMT_MEDIUM |
| 121 | DO_KVM 0x480 | ||
| 118 | mtspr SPRN_SPRG_SCRATCH0,r13 | 122 | mtspr SPRN_SPRG_SCRATCH0,r13 |
| 119 | mfspr r13,SPRN_SPRG_PACA /* get paca address into r13 */ | 123 | mfspr r13,SPRN_SPRG_PACA /* get paca address into r13 */ |
| 120 | std r3,PACA_EXSLB+EX_R3(r13) | 124 | std r3,PACA_EXSLB+EX_R3(r13) |
| @@ -154,6 +158,7 @@ instruction_access_slb_pSeries: | |||
| 154 | .globl system_call_pSeries | 158 | .globl system_call_pSeries |
| 155 | system_call_pSeries: | 159 | system_call_pSeries: |
| 156 | HMT_MEDIUM | 160 | HMT_MEDIUM |
| 161 | DO_KVM 0xc00 | ||
| 157 | BEGIN_FTR_SECTION | 162 | BEGIN_FTR_SECTION |
| 158 | cmpdi r0,0x1ebe | 163 | cmpdi r0,0x1ebe |
| 159 | beq- 1f | 164 | beq- 1f |
| @@ -185,13 +190,19 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) | |||
| 185 | * prolog code of the PerformanceMonitor one. A little | 190 | * prolog code of the PerformanceMonitor one. A little |
| 186 | * trickery is thus necessary | 191 | * trickery is thus necessary |
| 187 | */ | 192 | */ |
| 193 | performance_monitor_pSeries_1: | ||
| 188 | . = 0xf00 | 194 | . = 0xf00 |
| 195 | DO_KVM 0xf00 | ||
| 189 | b performance_monitor_pSeries | 196 | b performance_monitor_pSeries |
| 190 | 197 | ||
| 198 | altivec_unavailable_pSeries_1: | ||
| 191 | . = 0xf20 | 199 | . = 0xf20 |
| 200 | DO_KVM 0xf20 | ||
| 192 | b altivec_unavailable_pSeries | 201 | b altivec_unavailable_pSeries |
| 193 | 202 | ||
| 203 | vsx_unavailable_pSeries_1: | ||
| 194 | . = 0xf40 | 204 | . = 0xf40 |
| 205 | DO_KVM 0xf40 | ||
| 195 | b vsx_unavailable_pSeries | 206 | b vsx_unavailable_pSeries |
| 196 | 207 | ||
| 197 | #ifdef CONFIG_CBE_RAS | 208 | #ifdef CONFIG_CBE_RAS |
diff --git a/arch/powerpc/kernel/firmware.c b/arch/powerpc/kernel/firmware.c index 1679a70bbcad..6b1f4271eb53 100644 --- a/arch/powerpc/kernel/firmware.c +++ b/arch/powerpc/kernel/firmware.c | |||
| @@ -17,5 +17,5 @@ | |||
| 17 | 17 | ||
| 18 | #include <asm/firmware.h> | 18 | #include <asm/firmware.h> |
| 19 | 19 | ||
| 20 | unsigned long powerpc_firmware_features; | 20 | unsigned long powerpc_firmware_features __read_mostly; |
| 21 | EXPORT_SYMBOL_GPL(powerpc_firmware_features); | 21 | EXPORT_SYMBOL_GPL(powerpc_firmware_features); |
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S index 829c3fe7c5a2..e025e89fe93e 100644 --- a/arch/powerpc/kernel/head_32.S +++ b/arch/powerpc/kernel/head_32.S | |||
| @@ -164,6 +164,9 @@ __after_mmu_off: | |||
| 164 | #ifdef CONFIG_PPC_EARLY_DEBUG_CPM | 164 | #ifdef CONFIG_PPC_EARLY_DEBUG_CPM |
| 165 | bl setup_cpm_bat | 165 | bl setup_cpm_bat |
| 166 | #endif | 166 | #endif |
| 167 | #ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO | ||
| 168 | bl setup_usbgecko_bat | ||
| 169 | #endif | ||
| 167 | 170 | ||
| 168 | /* | 171 | /* |
| 169 | * Call setup_cpu for CPU 0 and initialize 6xx Idle | 172 | * Call setup_cpu for CPU 0 and initialize 6xx Idle |
| @@ -1203,6 +1206,28 @@ setup_cpm_bat: | |||
| 1203 | blr | 1206 | blr |
| 1204 | #endif | 1207 | #endif |
| 1205 | 1208 | ||
| 1209 | #ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO | ||
| 1210 | setup_usbgecko_bat: | ||
| 1211 | /* prepare a BAT for early io */ | ||
| 1212 | #if defined(CONFIG_GAMECUBE) | ||
| 1213 | lis r8, 0x0c00 | ||
| 1214 | #elif defined(CONFIG_WII) | ||
| 1215 | lis r8, 0x0d00 | ||
| 1216 | #else | ||
| 1217 | #error Invalid platform for USB Gecko based early debugging. | ||
| 1218 | #endif | ||
| 1219 | /* | ||
| 1220 | * The virtual address used must match the virtual address | ||
| 1221 | * associated to the fixmap entry FIX_EARLY_DEBUG_BASE. | ||
| 1222 | */ | ||
| 1223 | lis r11, 0xfffe /* top 128K */ | ||
| 1224 | ori r8, r8, 0x002a /* uncached, guarded ,rw */ | ||
| 1225 | ori r11, r11, 0x2 /* 128K, Vs=1, Vp=0 */ | ||
| 1226 | mtspr SPRN_DBAT1L, r8 | ||
| 1227 | mtspr SPRN_DBAT1U, r11 | ||
| 1228 | blr | ||
| 1229 | #endif | ||
| 1230 | |||
| 1206 | #ifdef CONFIG_8260 | 1231 | #ifdef CONFIG_8260 |
| 1207 | /* Jump into the system reset for the rom. | 1232 | /* Jump into the system reset for the rom. |
| 1208 | * We first disable the MMU, and then jump to the ROM reset address. | 1233 | * We first disable the MMU, and then jump to the ROM reset address. |
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index c38afdb45d7b..bed9a29ee383 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include <asm/firmware.h> | 37 | #include <asm/firmware.h> |
| 38 | #include <asm/page_64.h> | 38 | #include <asm/page_64.h> |
| 39 | #include <asm/irqflags.h> | 39 | #include <asm/irqflags.h> |
| 40 | #include <asm/kvm_book3s_64_asm.h> | ||
| 40 | 41 | ||
| 41 | /* The physical memory is layed out such that the secondary processor | 42 | /* The physical memory is layed out such that the secondary processor |
| 42 | * spin code sits at 0x0000...0x00ff. On server, the vectors follow | 43 | * spin code sits at 0x0000...0x00ff. On server, the vectors follow |
| @@ -165,6 +166,12 @@ exception_marker: | |||
| 165 | #include "exceptions-64s.S" | 166 | #include "exceptions-64s.S" |
| 166 | #endif | 167 | #endif |
| 167 | 168 | ||
| 169 | /* KVM trampoline code needs to be close to the interrupt handlers */ | ||
| 170 | |||
| 171 | #ifdef CONFIG_KVM_BOOK3S_64_HANDLER | ||
| 172 | #include "../kvm/book3s_64_rmhandlers.S" | ||
| 173 | #endif | ||
| 174 | |||
| 168 | _GLOBAL(generic_secondary_thread_init) | 175 | _GLOBAL(generic_secondary_thread_init) |
| 169 | mr r24,r3 | 176 | mr r24,r3 |
| 170 | 177 | ||
| @@ -212,7 +219,8 @@ generic_secondary_common_init: | |||
| 212 | * physical cpu id in r24, we need to search the pacas to find | 219 | * physical cpu id in r24, we need to search the pacas to find |
| 213 | * which logical id maps to our physical one. | 220 | * which logical id maps to our physical one. |
| 214 | */ | 221 | */ |
| 215 | LOAD_REG_ADDR(r13, paca) /* Get base vaddr of paca array */ | 222 | LOAD_REG_ADDR(r13, paca) /* Load paca pointer */ |
| 223 | ld r13,0(r13) /* Get base vaddr of paca array */ | ||
| 216 | li r5,0 /* logical cpu id */ | 224 | li r5,0 /* logical cpu id */ |
| 217 | 1: lhz r6,PACAHWCPUID(r13) /* Load HW procid from paca */ | 225 | 1: lhz r6,PACAHWCPUID(r13) /* Load HW procid from paca */ |
| 218 | cmpw r6,r24 /* Compare to our id */ | 226 | cmpw r6,r24 /* Compare to our id */ |
| @@ -529,7 +537,8 @@ _GLOBAL(pmac_secondary_start) | |||
| 529 | mtmsrd r3 /* RI on */ | 537 | mtmsrd r3 /* RI on */ |
| 530 | 538 | ||
| 531 | /* Set up a paca value for this processor. */ | 539 | /* Set up a paca value for this processor. */ |
| 532 | LOAD_REG_ADDR(r4,paca) /* Get base vaddr of paca array */ | 540 | LOAD_REG_ADDR(r4,paca) /* Load paca pointer */ |
| 541 | ld r4,0(r4) /* Get base vaddr of paca array */ | ||
| 533 | mulli r13,r24,PACA_SIZE /* Calculate vaddr of right paca */ | 542 | mulli r13,r24,PACA_SIZE /* Calculate vaddr of right paca */ |
| 534 | add r13,r13,r4 /* for this processor. */ | 543 | add r13,r13,r4 /* for this processor. */ |
| 535 | mtspr SPRN_SPRG_PACA,r13 /* Save vaddr of paca in an SPRG*/ | 544 | mtspr SPRN_SPRG_PACA,r13 /* Save vaddr of paca in an SPRG*/ |
| @@ -608,6 +617,17 @@ _GLOBAL(start_secondary_prolog) | |||
| 608 | std r3,0(r1) /* Zero the stack frame pointer */ | 617 | std r3,0(r1) /* Zero the stack frame pointer */ |
| 609 | bl .start_secondary | 618 | bl .start_secondary |
| 610 | b . | 619 | b . |
| 620 | /* | ||
| 621 | * Reset stack pointer and call start_secondary | ||
| 622 | * to continue with online operation when woken up | ||
| 623 | * from cede in cpu offline. | ||
| 624 | */ | ||
| 625 | _GLOBAL(start_secondary_resume) | ||
| 626 | ld r1,PACAKSAVE(r13) /* Reload kernel stack pointer */ | ||
| 627 | li r3,0 | ||
| 628 | std r3,0(r1) /* Zero the stack frame pointer */ | ||
| 629 | bl .start_secondary | ||
| 630 | b . | ||
| 611 | #endif | 631 | #endif |
| 612 | 632 | ||
| 613 | /* | 633 | /* |
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index 6ded19d01891..3ef743fa5d7c 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S | |||
| @@ -206,6 +206,8 @@ MachineCheck: | |||
| 206 | EXCEPTION_PROLOG | 206 | EXCEPTION_PROLOG |
| 207 | mfspr r4,SPRN_DAR | 207 | mfspr r4,SPRN_DAR |
| 208 | stw r4,_DAR(r11) | 208 | stw r4,_DAR(r11) |
| 209 | li r5,0x00f0 | ||
| 210 | mtspr SPRN_DAR,r5 /* Tag DAR, to be used in DTLB Error */ | ||
| 209 | mfspr r5,SPRN_DSISR | 211 | mfspr r5,SPRN_DSISR |
| 210 | stw r5,_DSISR(r11) | 212 | stw r5,_DSISR(r11) |
| 211 | addi r3,r1,STACK_FRAME_OVERHEAD | 213 | addi r3,r1,STACK_FRAME_OVERHEAD |
| @@ -222,6 +224,8 @@ DataAccess: | |||
| 222 | stw r10,_DSISR(r11) | 224 | stw r10,_DSISR(r11) |
| 223 | mr r5,r10 | 225 | mr r5,r10 |
| 224 | mfspr r4,SPRN_DAR | 226 | mfspr r4,SPRN_DAR |
| 227 | li r10,0x00f0 | ||
| 228 | mtspr SPRN_DAR,r10 /* Tag DAR, to be used in DTLB Error */ | ||
| 225 | EXC_XFER_EE_LITE(0x300, handle_page_fault) | 229 | EXC_XFER_EE_LITE(0x300, handle_page_fault) |
| 226 | 230 | ||
| 227 | /* Instruction access exception. | 231 | /* Instruction access exception. |
| @@ -244,6 +248,8 @@ Alignment: | |||
| 244 | EXCEPTION_PROLOG | 248 | EXCEPTION_PROLOG |
| 245 | mfspr r4,SPRN_DAR | 249 | mfspr r4,SPRN_DAR |
| 246 | stw r4,_DAR(r11) | 250 | stw r4,_DAR(r11) |
| 251 | li r5,0x00f0 | ||
| 252 | mtspr SPRN_DAR,r5 /* Tag DAR, to be used in DTLB Error */ | ||
| 247 | mfspr r5,SPRN_DSISR | 253 | mfspr r5,SPRN_DSISR |
| 248 | stw r5,_DSISR(r11) | 254 | stw r5,_DSISR(r11) |
| 249 | addi r3,r1,STACK_FRAME_OVERHEAD | 255 | addi r3,r1,STACK_FRAME_OVERHEAD |
| @@ -333,26 +339,20 @@ InstructionTLBMiss: | |||
| 333 | mfspr r11, SPRN_MD_TWC /* ....and get the pte address */ | 339 | mfspr r11, SPRN_MD_TWC /* ....and get the pte address */ |
| 334 | lwz r10, 0(r11) /* Get the pte */ | 340 | lwz r10, 0(r11) /* Get the pte */ |
| 335 | 341 | ||
| 336 | #ifdef CONFIG_SWAP | 342 | andi. r11, r10, _PAGE_ACCESSED | _PAGE_PRESENT |
| 337 | /* do not set the _PAGE_ACCESSED bit of a non-present page */ | 343 | cmpwi cr0, r11, _PAGE_ACCESSED | _PAGE_PRESENT |
| 338 | andi. r11, r10, _PAGE_PRESENT | 344 | bne- cr0, 2f |
| 339 | beq 4f | 345 | |
| 340 | ori r10, r10, _PAGE_ACCESSED | 346 | /* Clear PP lsb, 0x400 */ |
| 341 | mfspr r11, SPRN_MD_TWC /* get the pte address again */ | 347 | rlwinm r10, r10, 0, 22, 20 |
| 342 | stw r10, 0(r11) | ||
| 343 | 4: | ||
| 344 | #else | ||
| 345 | ori r10, r10, _PAGE_ACCESSED | ||
| 346 | stw r10, 0(r11) | ||
| 347 | #endif | ||
| 348 | 348 | ||
| 349 | /* The Linux PTE won't go exactly into the MMU TLB. | 349 | /* The Linux PTE won't go exactly into the MMU TLB. |
| 350 | * Software indicator bits 21, 22 and 28 must be clear. | 350 | * Software indicator bits 22 and 28 must be clear. |
| 351 | * Software indicator bits 24, 25, 26, and 27 must be | 351 | * Software indicator bits 24, 25, 26, and 27 must be |
| 352 | * set. All other Linux PTE bits control the behavior | 352 | * set. All other Linux PTE bits control the behavior |
| 353 | * of the MMU. | 353 | * of the MMU. |
| 354 | */ | 354 | */ |
| 355 | 2: li r11, 0x00f0 | 355 | li r11, 0x00f0 |
| 356 | rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */ | 356 | rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */ |
| 357 | DO_8xx_CPU6(0x2d80, r3) | 357 | DO_8xx_CPU6(0x2d80, r3) |
| 358 | mtspr SPRN_MI_RPN, r10 /* Update TLB entry */ | 358 | mtspr SPRN_MI_RPN, r10 /* Update TLB entry */ |
| @@ -365,6 +365,22 @@ InstructionTLBMiss: | |||
| 365 | lwz r3, 8(r0) | 365 | lwz r3, 8(r0) |
| 366 | #endif | 366 | #endif |
| 367 | rfi | 367 | rfi |
| 368 | 2: | ||
| 369 | mfspr r11, SPRN_SRR1 | ||
| 370 | /* clear all error bits as TLB Miss | ||
| 371 | * sets a few unconditionally | ||
| 372 | */ | ||
| 373 | rlwinm r11, r11, 0, 0xffff | ||
| 374 | mtspr SPRN_SRR1, r11 | ||
| 375 | |||
| 376 | mfspr r10, SPRN_M_TW /* Restore registers */ | ||
| 377 | lwz r11, 0(r0) | ||
| 378 | mtcr r11 | ||
| 379 | lwz r11, 4(r0) | ||
| 380 | #ifdef CONFIG_8xx_CPU6 | ||
| 381 | lwz r3, 8(r0) | ||
| 382 | #endif | ||
| 383 | b InstructionAccess | ||
| 368 | 384 | ||
| 369 | . = 0x1200 | 385 | . = 0x1200 |
| 370 | DataStoreTLBMiss: | 386 | DataStoreTLBMiss: |
| @@ -406,29 +422,45 @@ DataStoreTLBMiss: | |||
| 406 | * above. | 422 | * above. |
| 407 | */ | 423 | */ |
| 408 | rlwimi r11, r10, 0, 27, 27 | 424 | rlwimi r11, r10, 0, 27, 27 |
| 425 | /* Insert the WriteThru flag into the TWC from the Linux PTE. | ||
| 426 | * It is bit 25 in the Linux PTE and bit 30 in the TWC | ||
| 427 | */ | ||
| 428 | rlwimi r11, r10, 32-5, 30, 30 | ||
| 409 | DO_8xx_CPU6(0x3b80, r3) | 429 | DO_8xx_CPU6(0x3b80, r3) |
| 410 | mtspr SPRN_MD_TWC, r11 | 430 | mtspr SPRN_MD_TWC, r11 |
| 411 | 431 | ||
| 412 | #ifdef CONFIG_SWAP | 432 | /* Both _PAGE_ACCESSED and _PAGE_PRESENT has to be set. |
| 413 | /* do not set the _PAGE_ACCESSED bit of a non-present page */ | 433 | * We also need to know if the insn is a load/store, so: |
| 414 | andi. r11, r10, _PAGE_PRESENT | 434 | * Clear _PAGE_PRESENT and load that which will |
| 415 | beq 4f | 435 | * trap into DTLB Error with store bit set accordinly. |
| 416 | ori r10, r10, _PAGE_ACCESSED | 436 | */ |
| 417 | 4: | 437 | /* PRESENT=0x1, ACCESSED=0x20 |
| 418 | /* and update pte in table */ | 438 | * r11 = ((r10 & PRESENT) & ((r10 & ACCESSED) >> 5)); |
| 419 | #else | 439 | * r10 = (r10 & ~PRESENT) | r11; |
| 420 | ori r10, r10, _PAGE_ACCESSED | 440 | */ |
| 421 | #endif | 441 | rlwinm r11, r10, 32-5, _PAGE_PRESENT |
| 422 | mfspr r11, SPRN_MD_TWC /* get the pte address again */ | 442 | and r11, r11, r10 |
| 423 | stw r10, 0(r11) | 443 | rlwimi r10, r11, 0, _PAGE_PRESENT |
| 444 | |||
| 445 | /* Honour kernel RO, User NA */ | ||
| 446 | /* 0x200 == Extended encoding, bit 22 */ | ||
| 447 | /* r11 = (r10 & _PAGE_USER) >> 2 */ | ||
| 448 | rlwinm r11, r10, 32-2, 0x200 | ||
| 449 | or r10, r11, r10 | ||
| 450 | /* r11 = (r10 & _PAGE_RW) >> 1 */ | ||
| 451 | rlwinm r11, r10, 32-1, 0x200 | ||
| 452 | or r10, r11, r10 | ||
| 453 | /* invert RW and 0x200 bits */ | ||
| 454 | xori r10, r10, _PAGE_RW | 0x200 | ||
| 424 | 455 | ||
| 425 | /* The Linux PTE won't go exactly into the MMU TLB. | 456 | /* The Linux PTE won't go exactly into the MMU TLB. |
| 426 | * Software indicator bits 21, 22 and 28 must be clear. | 457 | * Software indicator bits 22 and 28 must be clear. |
| 427 | * Software indicator bits 24, 25, 26, and 27 must be | 458 | * Software indicator bits 24, 25, 26, and 27 must be |
| 428 | * set. All other Linux PTE bits control the behavior | 459 | * set. All other Linux PTE bits control the behavior |
| 429 | * of the MMU. | 460 | * of the MMU. |
| 430 | */ | 461 | */ |
| 431 | 2: li r11, 0x00f0 | 462 | 2: li r11, 0x00f0 |
| 463 | mtspr SPRN_DAR,r11 /* Tag DAR */ | ||
| 432 | rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */ | 464 | rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */ |
| 433 | DO_8xx_CPU6(0x3d80, r3) | 465 | DO_8xx_CPU6(0x3d80, r3) |
| 434 | mtspr SPRN_MD_RPN, r10 /* Update TLB entry */ | 466 | mtspr SPRN_MD_RPN, r10 /* Update TLB entry */ |
| @@ -469,97 +501,10 @@ DataTLBError: | |||
| 469 | stw r10, 0(r0) | 501 | stw r10, 0(r0) |
| 470 | stw r11, 4(r0) | 502 | stw r11, 4(r0) |
| 471 | 503 | ||
| 472 | /* First, make sure this was a store operation. | ||
| 473 | */ | ||
| 474 | mfspr r10, SPRN_DSISR | ||
| 475 | andis. r11, r10, 0x0200 /* If set, indicates store op */ | ||
| 476 | beq 2f | ||
| 477 | |||
| 478 | /* The EA of a data TLB miss is automatically stored in the MD_EPN | ||
| 479 | * register. The EA of a data TLB error is automatically stored in | ||
| 480 | * the DAR, but not the MD_EPN register. We must copy the 20 most | ||
| 481 | * significant bits of the EA from the DAR to MD_EPN before we | ||
| 482 | * start walking the page tables. We also need to copy the CASID | ||
| 483 | * value from the M_CASID register. | ||
| 484 | * Addendum: The EA of a data TLB error is _supposed_ to be stored | ||
| 485 | * in DAR, but it seems that this doesn't happen in some cases, such | ||
| 486 | * as when the error is due to a dcbi instruction to a page with a | ||
| 487 | * TLB that doesn't have the changed bit set. In such cases, there | ||
| 488 | * does not appear to be any way to recover the EA of the error | ||
| 489 | * since it is neither in DAR nor MD_EPN. As a workaround, the | ||
| 490 | * _PAGE_HWWRITE bit is set for all kernel data pages when the PTEs | ||
| 491 | * are initialized in mapin_ram(). This will avoid the problem, | ||
| 492 | * assuming we only use the dcbi instruction on kernel addresses. | ||
| 493 | */ | ||
| 494 | mfspr r10, SPRN_DAR | 504 | mfspr r10, SPRN_DAR |
| 495 | rlwinm r11, r10, 0, 0, 19 | 505 | cmpwi cr0, r10, 0x00f0 |
| 496 | ori r11, r11, MD_EVALID | 506 | beq- FixupDAR /* must be a buggy dcbX, icbi insn. */ |
| 497 | mfspr r10, SPRN_M_CASID | 507 | DARFixed:/* Return from dcbx instruction bug workaround, r10 holds value of DAR */ |
| 498 | rlwimi r11, r10, 0, 28, 31 | ||
| 499 | DO_8xx_CPU6(0x3780, r3) | ||
| 500 | mtspr SPRN_MD_EPN, r11 | ||
| 501 | |||
| 502 | mfspr r10, SPRN_M_TWB /* Get level 1 table entry address */ | ||
| 503 | |||
| 504 | /* If we are faulting a kernel address, we have to use the | ||
| 505 | * kernel page tables. | ||
| 506 | */ | ||
| 507 | andi. r11, r10, 0x0800 | ||
| 508 | beq 3f | ||
| 509 | lis r11, swapper_pg_dir@h | ||
| 510 | ori r11, r11, swapper_pg_dir@l | ||
| 511 | rlwimi r10, r11, 0, 2, 19 | ||
| 512 | 3: | ||
| 513 | lwz r11, 0(r10) /* Get the level 1 entry */ | ||
| 514 | rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */ | ||
| 515 | beq 2f /* If zero, bail */ | ||
| 516 | |||
| 517 | /* We have a pte table, so fetch the pte from the table. | ||
| 518 | */ | ||
| 519 | ori r11, r11, 1 /* Set valid bit in physical L2 page */ | ||
| 520 | DO_8xx_CPU6(0x3b80, r3) | ||
| 521 | mtspr SPRN_MD_TWC, r11 /* Load pte table base address */ | ||
| 522 | mfspr r11, SPRN_MD_TWC /* ....and get the pte address */ | ||
| 523 | lwz r10, 0(r11) /* Get the pte */ | ||
| 524 | |||
| 525 | andi. r11, r10, _PAGE_RW /* Is it writeable? */ | ||
| 526 | beq 2f /* Bail out if not */ | ||
| 527 | |||
| 528 | /* Update 'changed', among others. | ||
| 529 | */ | ||
| 530 | #ifdef CONFIG_SWAP | ||
| 531 | ori r10, r10, _PAGE_DIRTY|_PAGE_HWWRITE | ||
| 532 | /* do not set the _PAGE_ACCESSED bit of a non-present page */ | ||
| 533 | andi. r11, r10, _PAGE_PRESENT | ||
| 534 | beq 4f | ||
| 535 | ori r10, r10, _PAGE_ACCESSED | ||
| 536 | 4: | ||
| 537 | #else | ||
| 538 | ori r10, r10, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE | ||
| 539 | #endif | ||
| 540 | mfspr r11, SPRN_MD_TWC /* Get pte address again */ | ||
| 541 | stw r10, 0(r11) /* and update pte in table */ | ||
| 542 | |||
| 543 | /* The Linux PTE won't go exactly into the MMU TLB. | ||
| 544 | * Software indicator bits 21, 22 and 28 must be clear. | ||
| 545 | * Software indicator bits 24, 25, 26, and 27 must be | ||
| 546 | * set. All other Linux PTE bits control the behavior | ||
| 547 | * of the MMU. | ||
| 548 | */ | ||
| 549 | li r11, 0x00f0 | ||
| 550 | rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */ | ||
| 551 | DO_8xx_CPU6(0x3d80, r3) | ||
| 552 | mtspr SPRN_MD_RPN, r10 /* Update TLB entry */ | ||
| 553 | |||
| 554 | mfspr r10, SPRN_M_TW /* Restore registers */ | ||
| 555 | lwz r11, 0(r0) | ||
| 556 | mtcr r11 | ||
| 557 | lwz r11, 4(r0) | ||
| 558 | #ifdef CONFIG_8xx_CPU6 | ||
| 559 | lwz r3, 8(r0) | ||
| 560 | #endif | ||
| 561 | rfi | ||
| 562 | 2: | ||
| 563 | mfspr r10, SPRN_M_TW /* Restore registers */ | 508 | mfspr r10, SPRN_M_TW /* Restore registers */ |
| 564 | lwz r11, 0(r0) | 509 | lwz r11, 0(r0) |
| 565 | mtcr r11 | 510 | mtcr r11 |
| @@ -588,6 +533,140 @@ DataTLBError: | |||
| 588 | 533 | ||
| 589 | . = 0x2000 | 534 | . = 0x2000 |
| 590 | 535 | ||
| 536 | /* This is the procedure to calculate the data EA for buggy dcbx,dcbi instructions | ||
| 537 | * by decoding the registers used by the dcbx instruction and adding them. | ||
| 538 | * DAR is set to the calculated address and r10 also holds the EA on exit. | ||
| 539 | */ | ||
| 540 | /* define if you don't want to use self modifying code */ | ||
| 541 | #define NO_SELF_MODIFYING_CODE | ||
| 542 | FixupDAR:/* Entry point for dcbx workaround. */ | ||
| 543 | /* fetch instruction from memory. */ | ||
| 544 | mfspr r10, SPRN_SRR0 | ||
| 545 | andis. r11, r10, 0x8000 /* Address >= 0x80000000 */ | ||
| 546 | DO_8xx_CPU6(0x3780, r3) | ||
| 547 | mtspr SPRN_MD_EPN, r10 | ||
| 548 | mfspr r11, SPRN_M_TWB /* Get level 1 table entry address */ | ||
| 549 | beq- 3f /* Branch if user space */ | ||
| 550 | lis r11, (swapper_pg_dir-PAGE_OFFSET)@h | ||
| 551 | ori r11, r11, (swapper_pg_dir-PAGE_OFFSET)@l | ||
| 552 | rlwimi r11, r10, 32-20, 0xffc /* r11 = r11&~0xffc|(r10>>20)&0xffc */ | ||
| 553 | 3: lwz r11, 0(r11) /* Get the level 1 entry */ | ||
| 554 | DO_8xx_CPU6(0x3b80, r3) | ||
| 555 | mtspr SPRN_MD_TWC, r11 /* Load pte table base address */ | ||
| 556 | mfspr r11, SPRN_MD_TWC /* ....and get the pte address */ | ||
| 557 | lwz r11, 0(r11) /* Get the pte */ | ||
| 558 | /* concat physical page address(r11) and page offset(r10) */ | ||
| 559 | rlwimi r11, r10, 0, 20, 31 | ||
| 560 | lwz r11,0(r11) | ||
| 561 | /* Check if it really is a dcbx instruction. */ | ||
| 562 | /* dcbt and dcbtst does not generate DTLB Misses/Errors, | ||
| 563 | * no need to include them here */ | ||
| 564 | srwi r10, r11, 26 /* check if major OP code is 31 */ | ||
| 565 | cmpwi cr0, r10, 31 | ||
| 566 | bne- 141f | ||
| 567 | rlwinm r10, r11, 0, 21, 30 | ||
| 568 | cmpwi cr0, r10, 2028 /* Is dcbz? */ | ||
| 569 | beq+ 142f | ||
| 570 | cmpwi cr0, r10, 940 /* Is dcbi? */ | ||
| 571 | beq+ 142f | ||
| 572 | cmpwi cr0, r10, 108 /* Is dcbst? */ | ||
| 573 | beq+ 144f /* Fix up store bit! */ | ||
| 574 | cmpwi cr0, r10, 172 /* Is dcbf? */ | ||
| 575 | beq+ 142f | ||
| 576 | cmpwi cr0, r10, 1964 /* Is icbi? */ | ||
| 577 | beq+ 142f | ||
| 578 | 141: mfspr r10, SPRN_DAR /* r10 must hold DAR at exit */ | ||
| 579 | b DARFixed /* Nope, go back to normal TLB processing */ | ||
| 580 | |||
| 581 | 144: mfspr r10, SPRN_DSISR | ||
| 582 | rlwinm r10, r10,0,7,5 /* Clear store bit for buggy dcbst insn */ | ||
| 583 | mtspr SPRN_DSISR, r10 | ||
| 584 | 142: /* continue, it was a dcbx, dcbi instruction. */ | ||
| 585 | #ifdef CONFIG_8xx_CPU6 | ||
| 586 | lwz r3, 8(r0) /* restore r3 from memory */ | ||
| 587 | #endif | ||
| 588 | #ifndef NO_SELF_MODIFYING_CODE | ||
| 589 | andis. r10,r11,0x1f /* test if reg RA is r0 */ | ||
| 590 | li r10,modified_instr@l | ||
| 591 | dcbtst r0,r10 /* touch for store */ | ||
| 592 | rlwinm r11,r11,0,0,20 /* Zero lower 10 bits */ | ||
| 593 | oris r11,r11,640 /* Transform instr. to a "add r10,RA,RB" */ | ||
| 594 | ori r11,r11,532 | ||
| 595 | stw r11,0(r10) /* store add/and instruction */ | ||
| 596 | dcbf 0,r10 /* flush new instr. to memory. */ | ||
| 597 | icbi 0,r10 /* invalidate instr. cache line */ | ||
| 598 | lwz r11, 4(r0) /* restore r11 from memory */ | ||
| 599 | mfspr r10, SPRN_M_TW /* restore r10 from M_TW */ | ||
| 600 | isync /* Wait until new instr is loaded from memory */ | ||
| 601 | modified_instr: | ||
| 602 | .space 4 /* this is where the add instr. is stored */ | ||
| 603 | bne+ 143f | ||
| 604 | subf r10,r0,r10 /* r10=r10-r0, only if reg RA is r0 */ | ||
| 605 | 143: mtdar r10 /* store faulting EA in DAR */ | ||
| 606 | b DARFixed /* Go back to normal TLB handling */ | ||
| 607 | #else | ||
| 608 | mfctr r10 | ||
| 609 | mtdar r10 /* save ctr reg in DAR */ | ||
| 610 | rlwinm r10, r11, 24, 24, 28 /* offset into jump table for reg RB */ | ||
| 611 | addi r10, r10, 150f@l /* add start of table */ | ||
| 612 | mtctr r10 /* load ctr with jump address */ | ||
| 613 | xor r10, r10, r10 /* sum starts at zero */ | ||
| 614 | bctr /* jump into table */ | ||
| 615 | 150: | ||
| 616 | add r10, r10, r0 ;b 151f | ||
| 617 | add r10, r10, r1 ;b 151f | ||
| 618 | add r10, r10, r2 ;b 151f | ||
| 619 | add r10, r10, r3 ;b 151f | ||
| 620 | add r10, r10, r4 ;b 151f | ||
| 621 | add r10, r10, r5 ;b 151f | ||
| 622 | add r10, r10, r6 ;b 151f | ||
| 623 | add r10, r10, r7 ;b 151f | ||
| 624 | add r10, r10, r8 ;b 151f | ||
| 625 | add r10, r10, r9 ;b 151f | ||
| 626 | mtctr r11 ;b 154f /* r10 needs special handling */ | ||
| 627 | mtctr r11 ;b 153f /* r11 needs special handling */ | ||
| 628 | add r10, r10, r12 ;b 151f | ||
| 629 | add r10, r10, r13 ;b 151f | ||
| 630 | add r10, r10, r14 ;b 151f | ||
| 631 | add r10, r10, r15 ;b 151f | ||
| 632 | add r10, r10, r16 ;b 151f | ||
| 633 | add r10, r10, r17 ;b 151f | ||
| 634 | add r10, r10, r18 ;b 151f | ||
| 635 | add r10, r10, r19 ;b 151f | ||
| 636 | add r10, r10, r20 ;b 151f | ||
| 637 | add r10, r10, r21 ;b 151f | ||
| 638 | add r10, r10, r22 ;b 151f | ||
| 639 | add r10, r10, r23 ;b 151f | ||
| 640 | add r10, r10, r24 ;b 151f | ||
| 641 | add r10, r10, r25 ;b 151f | ||
| 642 | add r10, r10, r26 ;b 151f | ||
| 643 | add r10, r10, r27 ;b 151f | ||
| 644 | add r10, r10, r28 ;b 151f | ||
| 645 | add r10, r10, r29 ;b 151f | ||
| 646 | add r10, r10, r30 ;b 151f | ||
| 647 | add r10, r10, r31 | ||
| 648 | 151: | ||
| 649 | rlwinm. r11,r11,19,24,28 /* offset into jump table for reg RA */ | ||
| 650 | beq 152f /* if reg RA is zero, don't add it */ | ||
| 651 | addi r11, r11, 150b@l /* add start of table */ | ||
| 652 | mtctr r11 /* load ctr with jump address */ | ||
| 653 | rlwinm r11,r11,0,16,10 /* make sure we don't execute this more than once */ | ||
| 654 | bctr /* jump into table */ | ||
| 655 | 152: | ||
| 656 | mfdar r11 | ||
| 657 | mtctr r11 /* restore ctr reg from DAR */ | ||
| 658 | mtdar r10 /* save fault EA to DAR */ | ||
| 659 | b DARFixed /* Go back to normal TLB handling */ | ||
| 660 | |||
| 661 | /* special handling for r10,r11 since these are modified already */ | ||
| 662 | 153: lwz r11, 4(r0) /* load r11 from memory */ | ||
| 663 | b 155f | ||
| 664 | 154: mfspr r11, SPRN_M_TW /* load r10 from M_TW */ | ||
| 665 | 155: add r10, r10, r11 /* add it */ | ||
| 666 | mfctr r11 /* restore r11 */ | ||
| 667 | b 151b | ||
| 668 | #endif | ||
| 669 | |||
| 591 | .globl giveup_fpu | 670 | .globl giveup_fpu |
| 592 | giveup_fpu: | 671 | giveup_fpu: |
| 593 | blr | 672 | blr |
| @@ -689,12 +768,12 @@ start_here: | |||
| 689 | */ | 768 | */ |
| 690 | initial_mmu: | 769 | initial_mmu: |
| 691 | tlbia /* Invalidate all TLB entries */ | 770 | tlbia /* Invalidate all TLB entries */ |
| 692 | #ifdef CONFIG_PIN_TLB | 771 | /* Always pin the first 8 MB ITLB to prevent ITLB |
| 772 | misses while mucking around with SRR0/SRR1 in asm | ||
| 773 | */ | ||
| 693 | lis r8, MI_RSV4I@h | 774 | lis r8, MI_RSV4I@h |
| 694 | ori r8, r8, 0x1c00 | 775 | ori r8, r8, 0x1c00 |
| 695 | #else | 776 | |
| 696 | li r8, 0 | ||
| 697 | #endif | ||
| 698 | mtspr SPRN_MI_CTR, r8 /* Set instruction MMU control */ | 777 | mtspr SPRN_MI_CTR, r8 /* Set instruction MMU control */ |
| 699 | 778 | ||
| 700 | #ifdef CONFIG_PIN_TLB | 779 | #ifdef CONFIG_PIN_TLB |
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index 975788ca05d2..725526547994 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S | |||
| @@ -214,11 +214,11 @@ skpinv: addi r6,r6,1 /* Increment */ | |||
| 214 | bl 1f /* Find our address */ | 214 | bl 1f /* Find our address */ |
| 215 | 1: mflr r9 | 215 | 1: mflr r9 |
| 216 | rlwimi r7,r9,0,20,31 | 216 | rlwimi r7,r9,0,20,31 |
| 217 | addi r7,r7,24 | 217 | addi r7,r7,(2f - 1b) |
| 218 | mtspr SPRN_SRR0,r7 | 218 | mtspr SPRN_SRR0,r7 |
| 219 | mtspr SPRN_SRR1,r6 | 219 | mtspr SPRN_SRR1,r6 |
| 220 | rfi | 220 | rfi |
| 221 | 221 | 2: | |
| 222 | /* 4. Clear out PIDs & Search info */ | 222 | /* 4. Clear out PIDs & Search info */ |
| 223 | li r6,0 | 223 | li r6,0 |
| 224 | mtspr SPRN_MAS6,r6 | 224 | mtspr SPRN_MAS6,r6 |
| @@ -747,9 +747,6 @@ finish_tlb_load: | |||
| 747 | #else | 747 | #else |
| 748 | rlwimi r12, r11, 26, 27, 31 /* extract WIMGE from pte */ | 748 | rlwimi r12, r11, 26, 27, 31 /* extract WIMGE from pte */ |
| 749 | #endif | 749 | #endif |
| 750 | #ifdef CONFIG_SMP | ||
| 751 | ori r12, r12, MAS2_M | ||
| 752 | #endif | ||
| 753 | mtspr SPRN_MAS2, r12 | 750 | mtspr SPRN_MAS2, r12 |
| 754 | 751 | ||
| 755 | #ifdef CONFIG_PTE_64BIT | 752 | #ifdef CONFIG_PTE_64BIT |
| @@ -887,13 +884,17 @@ KernelSPE: | |||
| 887 | lwz r3,_MSR(r1) | 884 | lwz r3,_MSR(r1) |
| 888 | oris r3,r3,MSR_SPE@h | 885 | oris r3,r3,MSR_SPE@h |
| 889 | stw r3,_MSR(r1) /* enable use of SPE after return */ | 886 | stw r3,_MSR(r1) /* enable use of SPE after return */ |
| 887 | #ifdef CONFIG_PRINTK | ||
| 890 | lis r3,87f@h | 888 | lis r3,87f@h |
| 891 | ori r3,r3,87f@l | 889 | ori r3,r3,87f@l |
| 892 | mr r4,r2 /* current */ | 890 | mr r4,r2 /* current */ |
| 893 | lwz r5,_NIP(r1) | 891 | lwz r5,_NIP(r1) |
| 894 | bl printk | 892 | bl printk |
| 893 | #endif | ||
| 895 | b ret_from_except | 894 | b ret_from_except |
| 895 | #ifdef CONFIG_PRINTK | ||
| 896 | 87: .string "SPE used in kernel (task=%p, pc=%x) \n" | 896 | 87: .string "SPE used in kernel (task=%p, pc=%x) \n" |
| 897 | #endif | ||
| 897 | .align 4,0 | 898 | .align 4,0 |
| 898 | 899 | ||
| 899 | #endif /* CONFIG_SPE */ | 900 | #endif /* CONFIG_SPE */ |
| @@ -944,28 +945,6 @@ _GLOBAL(__setup_e500mc_ivors) | |||
| 944 | blr | 945 | blr |
| 945 | 946 | ||
| 946 | /* | 947 | /* |
| 947 | * extern void loadcam_entry(unsigned int index) | ||
| 948 | * | ||
| 949 | * Load TLBCAM[index] entry in to the L2 CAM MMU | ||
| 950 | */ | ||
| 951 | _GLOBAL(loadcam_entry) | ||
| 952 | lis r4,TLBCAM@ha | ||
| 953 | addi r4,r4,TLBCAM@l | ||
| 954 | mulli r5,r3,TLBCAM_SIZE | ||
| 955 | add r3,r5,r4 | ||
| 956 | lwz r4,0(r3) | ||
| 957 | mtspr SPRN_MAS0,r4 | ||
| 958 | lwz r4,4(r3) | ||
| 959 | mtspr SPRN_MAS1,r4 | ||
| 960 | lwz r4,8(r3) | ||
| 961 | mtspr SPRN_MAS2,r4 | ||
| 962 | lwz r4,12(r3) | ||
| 963 | mtspr SPRN_MAS3,r4 | ||
| 964 | tlbwe | ||
| 965 | isync | ||
| 966 | blr | ||
| 967 | |||
| 968 | /* | ||
| 969 | * extern void giveup_altivec(struct task_struct *prev) | 948 | * extern void giveup_altivec(struct task_struct *prev) |
| 970 | * | 949 | * |
| 971 | * The e500 core does not have an AltiVec unit. | 950 | * The e500 core does not have an AltiVec unit. |
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c index a4c8b38b0ba1..71cf280da184 100644 --- a/arch/powerpc/kernel/ibmebus.c +++ b/arch/powerpc/kernel/ibmebus.c | |||
| @@ -42,6 +42,7 @@ | |||
| 42 | #include <linux/dma-mapping.h> | 42 | #include <linux/dma-mapping.h> |
| 43 | #include <linux/interrupt.h> | 43 | #include <linux/interrupt.h> |
| 44 | #include <linux/of.h> | 44 | #include <linux/of.h> |
| 45 | #include <linux/slab.h> | ||
| 45 | #include <linux/of_platform.h> | 46 | #include <linux/of_platform.h> |
| 46 | #include <asm/ibmebus.h> | 47 | #include <asm/ibmebus.h> |
| 47 | #include <asm/abs_addr.h> | 48 | #include <asm/abs_addr.h> |
diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c index 88d9c1d5e5fb..049dda60e475 100644 --- a/arch/powerpc/kernel/idle.c +++ b/arch/powerpc/kernel/idle.c | |||
| @@ -110,18 +110,16 @@ int powersave_nap; | |||
| 110 | */ | 110 | */ |
| 111 | static ctl_table powersave_nap_ctl_table[]={ | 111 | static ctl_table powersave_nap_ctl_table[]={ |
| 112 | { | 112 | { |
| 113 | .ctl_name = KERN_PPC_POWERSAVE_NAP, | ||
| 114 | .procname = "powersave-nap", | 113 | .procname = "powersave-nap", |
| 115 | .data = &powersave_nap, | 114 | .data = &powersave_nap, |
| 116 | .maxlen = sizeof(int), | 115 | .maxlen = sizeof(int), |
| 117 | .mode = 0644, | 116 | .mode = 0644, |
| 118 | .proc_handler = &proc_dointvec, | 117 | .proc_handler = proc_dointvec, |
| 119 | }, | 118 | }, |
| 120 | {} | 119 | {} |
| 121 | }; | 120 | }; |
| 122 | static ctl_table powersave_nap_sysctl_root[] = { | 121 | static ctl_table powersave_nap_sysctl_root[] = { |
| 123 | { | 122 | { |
| 124 | .ctl_name = CTL_KERN, | ||
| 125 | .procname = "kernel", | 123 | .procname = "kernel", |
| 126 | .mode = 0555, | 124 | .mode = 0555, |
| 127 | .child = powersave_nap_ctl_table, | 125 | .child = powersave_nap_ctl_table, |
diff --git a/arch/powerpc/kernel/io.c b/arch/powerpc/kernel/io.c index 1882bf419fa6..8dc7547c2377 100644 --- a/arch/powerpc/kernel/io.c +++ b/arch/powerpc/kernel/io.c | |||
| @@ -161,7 +161,7 @@ void _memcpy_fromio(void *dest, const volatile void __iomem *src, | |||
| 161 | dest++; | 161 | dest++; |
| 162 | n--; | 162 | n--; |
| 163 | } | 163 | } |
| 164 | while(n > 4) { | 164 | while(n >= 4) { |
| 165 | *((u32 *)dest) = *((volatile u32 *)vsrc); | 165 | *((u32 *)dest) = *((volatile u32 *)vsrc); |
| 166 | eieio(); | 166 | eieio(); |
| 167 | vsrc += 4; | 167 | vsrc += 4; |
| @@ -190,7 +190,7 @@ void _memcpy_toio(volatile void __iomem *dest, const void *src, unsigned long n) | |||
| 190 | vdest++; | 190 | vdest++; |
| 191 | n--; | 191 | n--; |
| 192 | } | 192 | } |
| 193 | while(n > 4) { | 193 | while(n >= 4) { |
| 194 | *((volatile u32 *)vdest) = *((volatile u32 *)src); | 194 | *((volatile u32 *)vdest) = *((volatile u32 *)src); |
| 195 | src += 4; | 195 | src += 4; |
| 196 | vdest += 4; | 196 | vdest += 4; |
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index fd51578e29dd..ec94f906ea43 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c | |||
| @@ -30,7 +30,7 @@ | |||
| 30 | #include <linux/spinlock.h> | 30 | #include <linux/spinlock.h> |
| 31 | #include <linux/string.h> | 31 | #include <linux/string.h> |
| 32 | #include <linux/dma-mapping.h> | 32 | #include <linux/dma-mapping.h> |
| 33 | #include <linux/bitops.h> | 33 | #include <linux/bitmap.h> |
| 34 | #include <linux/iommu-helper.h> | 34 | #include <linux/iommu-helper.h> |
| 35 | #include <linux/crash_dump.h> | 35 | #include <linux/crash_dump.h> |
| 36 | #include <asm/io.h> | 36 | #include <asm/io.h> |
| @@ -42,12 +42,7 @@ | |||
| 42 | 42 | ||
| 43 | #define DBG(...) | 43 | #define DBG(...) |
| 44 | 44 | ||
| 45 | #ifdef CONFIG_IOMMU_VMERGE | 45 | static int novmerge; |
| 46 | static int novmerge = 0; | ||
| 47 | #else | ||
| 48 | static int novmerge = 1; | ||
| 49 | #endif | ||
| 50 | |||
| 51 | static int protect4gb = 1; | 46 | static int protect4gb = 1; |
| 52 | 47 | ||
| 53 | static void __iommu_free(struct iommu_table *, dma_addr_t, unsigned int); | 48 | static void __iommu_free(struct iommu_table *, dma_addr_t, unsigned int); |
| @@ -251,7 +246,7 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, | |||
| 251 | } | 246 | } |
| 252 | 247 | ||
| 253 | ppc_md.tce_free(tbl, entry, npages); | 248 | ppc_md.tce_free(tbl, entry, npages); |
| 254 | iommu_area_free(tbl->it_map, free_entry, npages); | 249 | bitmap_clear(tbl->it_map, free_entry, npages); |
| 255 | } | 250 | } |
| 256 | 251 | ||
| 257 | static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, | 252 | static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, |
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index e5d121177984..066bd31551d5 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
| @@ -53,7 +53,6 @@ | |||
| 53 | #include <linux/bootmem.h> | 53 | #include <linux/bootmem.h> |
| 54 | #include <linux/pci.h> | 54 | #include <linux/pci.h> |
| 55 | #include <linux/debugfs.h> | 55 | #include <linux/debugfs.h> |
| 56 | #include <linux/perf_event.h> | ||
| 57 | 56 | ||
| 58 | #include <asm/uaccess.h> | 57 | #include <asm/uaccess.h> |
| 59 | #include <asm/system.h> | 58 | #include <asm/system.h> |
| @@ -70,9 +69,13 @@ | |||
| 70 | #include <asm/firmware.h> | 69 | #include <asm/firmware.h> |
| 71 | #include <asm/lv1call.h> | 70 | #include <asm/lv1call.h> |
| 72 | #endif | 71 | #endif |
| 72 | #define CREATE_TRACE_POINTS | ||
| 73 | #include <asm/trace.h> | ||
| 74 | |||
| 75 | DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); | ||
| 76 | EXPORT_PER_CPU_SYMBOL(irq_stat); | ||
| 73 | 77 | ||
| 74 | int __irq_offset_value; | 78 | int __irq_offset_value; |
| 75 | static int ppc_spurious_interrupts; | ||
| 76 | 79 | ||
| 77 | #ifdef CONFIG_PPC32 | 80 | #ifdef CONFIG_PPC32 |
| 78 | EXPORT_SYMBOL(__irq_offset_value); | 81 | EXPORT_SYMBOL(__irq_offset_value); |
| @@ -85,7 +88,10 @@ extern int tau_interrupts(int); | |||
| 85 | #endif /* CONFIG_PPC32 */ | 88 | #endif /* CONFIG_PPC32 */ |
| 86 | 89 | ||
| 87 | #ifdef CONFIG_PPC64 | 90 | #ifdef CONFIG_PPC64 |
| 91 | |||
| 92 | #ifndef CONFIG_SPARSE_IRQ | ||
| 88 | EXPORT_SYMBOL(irq_desc); | 93 | EXPORT_SYMBOL(irq_desc); |
| 94 | #endif | ||
| 89 | 95 | ||
| 90 | int distribute_irqs = 1; | 96 | int distribute_irqs = 1; |
| 91 | 97 | ||
| @@ -138,11 +144,6 @@ notrace void raw_local_irq_restore(unsigned long en) | |||
| 138 | } | 144 | } |
| 139 | #endif /* CONFIG_PPC_STD_MMU_64 */ | 145 | #endif /* CONFIG_PPC_STD_MMU_64 */ |
| 140 | 146 | ||
| 141 | if (test_perf_event_pending()) { | ||
| 142 | clear_perf_event_pending(); | ||
| 143 | perf_event_do_pending(); | ||
| 144 | } | ||
| 145 | |||
| 146 | /* | 147 | /* |
| 147 | * if (get_paca()->hard_enabled) return; | 148 | * if (get_paca()->hard_enabled) return; |
| 148 | * But again we need to take care that gcc gets hard_enabled directly | 149 | * But again we need to take care that gcc gets hard_enabled directly |
| @@ -175,78 +176,135 @@ notrace void raw_local_irq_restore(unsigned long en) | |||
| 175 | EXPORT_SYMBOL(raw_local_irq_restore); | 176 | EXPORT_SYMBOL(raw_local_irq_restore); |
| 176 | #endif /* CONFIG_PPC64 */ | 177 | #endif /* CONFIG_PPC64 */ |
| 177 | 178 | ||
| 179 | static int show_other_interrupts(struct seq_file *p, int prec) | ||
| 180 | { | ||
| 181 | int j; | ||
| 182 | |||
| 183 | #if defined(CONFIG_PPC32) && defined(CONFIG_TAU_INT) | ||
| 184 | if (tau_initialized) { | ||
| 185 | seq_printf(p, "%*s: ", prec, "TAU"); | ||
| 186 | for_each_online_cpu(j) | ||
| 187 | seq_printf(p, "%10u ", tau_interrupts(j)); | ||
| 188 | seq_puts(p, " PowerPC Thermal Assist (cpu temp)\n"); | ||
| 189 | } | ||
| 190 | #endif /* CONFIG_PPC32 && CONFIG_TAU_INT */ | ||
| 191 | |||
| 192 | seq_printf(p, "%*s: ", prec, "LOC"); | ||
| 193 | for_each_online_cpu(j) | ||
| 194 | seq_printf(p, "%10u ", per_cpu(irq_stat, j).timer_irqs); | ||
| 195 | seq_printf(p, " Local timer interrupts\n"); | ||
| 196 | |||
| 197 | seq_printf(p, "%*s: ", prec, "SPU"); | ||
| 198 | for_each_online_cpu(j) | ||
| 199 | seq_printf(p, "%10u ", per_cpu(irq_stat, j).spurious_irqs); | ||
| 200 | seq_printf(p, " Spurious interrupts\n"); | ||
| 201 | |||
| 202 | seq_printf(p, "%*s: ", prec, "CNT"); | ||
| 203 | for_each_online_cpu(j) | ||
| 204 | seq_printf(p, "%10u ", per_cpu(irq_stat, j).pmu_irqs); | ||
| 205 | seq_printf(p, " Performance monitoring interrupts\n"); | ||
| 206 | |||
| 207 | seq_printf(p, "%*s: ", prec, "MCE"); | ||
| 208 | for_each_online_cpu(j) | ||
| 209 | seq_printf(p, "%10u ", per_cpu(irq_stat, j).mce_exceptions); | ||
| 210 | seq_printf(p, " Machine check exceptions\n"); | ||
| 211 | |||
| 212 | return 0; | ||
| 213 | } | ||
| 214 | |||
| 178 | int show_interrupts(struct seq_file *p, void *v) | 215 | int show_interrupts(struct seq_file *p, void *v) |
| 179 | { | 216 | { |
| 180 | int i = *(loff_t *)v, j; | 217 | unsigned long flags, any_count = 0; |
| 218 | int i = *(loff_t *) v, j, prec; | ||
| 181 | struct irqaction *action; | 219 | struct irqaction *action; |
| 182 | struct irq_desc *desc; | 220 | struct irq_desc *desc; |
| 183 | unsigned long flags; | ||
| 184 | 221 | ||
| 222 | if (i > nr_irqs) | ||
| 223 | return 0; | ||
| 224 | |||
| 225 | for (prec = 3, j = 1000; prec < 10 && j <= nr_irqs; ++prec) | ||
| 226 | j *= 10; | ||
| 227 | |||
| 228 | if (i == nr_irqs) | ||
| 229 | return show_other_interrupts(p, prec); | ||
| 230 | |||
| 231 | /* print header */ | ||
| 185 | if (i == 0) { | 232 | if (i == 0) { |
| 186 | seq_puts(p, " "); | 233 | seq_printf(p, "%*s", prec + 8, ""); |
| 187 | for_each_online_cpu(j) | 234 | for_each_online_cpu(j) |
| 188 | seq_printf(p, "CPU%d ", j); | 235 | seq_printf(p, "CPU%-8d", j); |
| 189 | seq_putc(p, '\n'); | 236 | seq_putc(p, '\n'); |
| 190 | } | 237 | } |
| 191 | 238 | ||
| 192 | if (i < NR_IRQS) { | 239 | desc = irq_to_desc(i); |
| 193 | desc = get_irq_desc(i); | 240 | if (!desc) |
| 194 | spin_lock_irqsave(&desc->lock, flags); | 241 | return 0; |
| 195 | action = desc->action; | 242 | |
| 196 | if (!action || !action->handler) | 243 | raw_spin_lock_irqsave(&desc->lock, flags); |
| 197 | goto skip; | 244 | for_each_online_cpu(j) |
| 198 | seq_printf(p, "%3d: ", i); | 245 | any_count |= kstat_irqs_cpu(i, j); |
| 199 | #ifdef CONFIG_SMP | 246 | action = desc->action; |
| 200 | for_each_online_cpu(j) | 247 | if (!action && !any_count) |
| 201 | seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); | 248 | goto out; |
| 202 | #else | 249 | |
| 203 | seq_printf(p, "%10u ", kstat_irqs(i)); | 250 | seq_printf(p, "%*d: ", prec, i); |
| 204 | #endif /* CONFIG_SMP */ | 251 | for_each_online_cpu(j) |
| 205 | if (desc->chip) | 252 | seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); |
| 206 | seq_printf(p, " %s ", desc->chip->typename); | 253 | |
| 207 | else | 254 | if (desc->chip) |
| 208 | seq_puts(p, " None "); | 255 | seq_printf(p, " %-16s", desc->chip->name); |
| 209 | seq_printf(p, "%s", (desc->status & IRQ_LEVEL) ? "Level " : "Edge "); | 256 | else |
| 210 | seq_printf(p, " %s", action->name); | 257 | seq_printf(p, " %-16s", "None"); |
| 211 | for (action = action->next; action; action = action->next) | 258 | seq_printf(p, " %-8s", (desc->status & IRQ_LEVEL) ? "Level" : "Edge"); |
| 259 | |||
| 260 | if (action) { | ||
| 261 | seq_printf(p, " %s", action->name); | ||
| 262 | while ((action = action->next) != NULL) | ||
| 212 | seq_printf(p, ", %s", action->name); | 263 | seq_printf(p, ", %s", action->name); |
| 213 | seq_putc(p, '\n'); | ||
| 214 | skip: | ||
| 215 | spin_unlock_irqrestore(&desc->lock, flags); | ||
| 216 | } else if (i == NR_IRQS) { | ||
| 217 | #if defined(CONFIG_PPC32) && defined(CONFIG_TAU_INT) | ||
| 218 | if (tau_initialized){ | ||
| 219 | seq_puts(p, "TAU: "); | ||
| 220 | for_each_online_cpu(j) | ||
| 221 | seq_printf(p, "%10u ", tau_interrupts(j)); | ||
| 222 | seq_puts(p, " PowerPC Thermal Assist (cpu temp)\n"); | ||
| 223 | } | ||
| 224 | #endif /* CONFIG_PPC32 && CONFIG_TAU_INT*/ | ||
| 225 | seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts); | ||
| 226 | } | 264 | } |
| 265 | |||
| 266 | seq_putc(p, '\n'); | ||
| 267 | out: | ||
| 268 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
| 227 | return 0; | 269 | return 0; |
| 228 | } | 270 | } |
| 229 | 271 | ||
| 272 | /* | ||
| 273 | * /proc/stat helpers | ||
| 274 | */ | ||
| 275 | u64 arch_irq_stat_cpu(unsigned int cpu) | ||
| 276 | { | ||
| 277 | u64 sum = per_cpu(irq_stat, cpu).timer_irqs; | ||
| 278 | |||
| 279 | sum += per_cpu(irq_stat, cpu).pmu_irqs; | ||
| 280 | sum += per_cpu(irq_stat, cpu).mce_exceptions; | ||
| 281 | sum += per_cpu(irq_stat, cpu).spurious_irqs; | ||
| 282 | |||
| 283 | return sum; | ||
| 284 | } | ||
| 285 | |||
| 230 | #ifdef CONFIG_HOTPLUG_CPU | 286 | #ifdef CONFIG_HOTPLUG_CPU |
| 231 | void fixup_irqs(cpumask_t map) | 287 | void fixup_irqs(cpumask_t map) |
| 232 | { | 288 | { |
| 289 | struct irq_desc *desc; | ||
| 233 | unsigned int irq; | 290 | unsigned int irq; |
| 234 | static int warned; | 291 | static int warned; |
| 235 | 292 | ||
| 236 | for_each_irq(irq) { | 293 | for_each_irq(irq) { |
| 237 | cpumask_t mask; | 294 | cpumask_t mask; |
| 238 | 295 | ||
| 239 | if (irq_desc[irq].status & IRQ_PER_CPU) | 296 | desc = irq_to_desc(irq); |
| 297 | if (desc && desc->status & IRQ_PER_CPU) | ||
| 240 | continue; | 298 | continue; |
| 241 | 299 | ||
| 242 | cpumask_and(&mask, irq_desc[irq].affinity, &map); | 300 | cpumask_and(&mask, desc->affinity, &map); |
| 243 | if (any_online_cpu(mask) == NR_CPUS) { | 301 | if (any_online_cpu(mask) == NR_CPUS) { |
| 244 | printk("Breaking affinity for irq %i\n", irq); | 302 | printk("Breaking affinity for irq %i\n", irq); |
| 245 | mask = map; | 303 | mask = map; |
| 246 | } | 304 | } |
| 247 | if (irq_desc[irq].chip->set_affinity) | 305 | if (desc->chip->set_affinity) |
| 248 | irq_desc[irq].chip->set_affinity(irq, &mask); | 306 | desc->chip->set_affinity(irq, &mask); |
| 249 | else if (irq_desc[irq].action && !(warned++)) | 307 | else if (desc->action && !(warned++)) |
| 250 | printk("Cannot set affinity for irq %i\n", irq); | 308 | printk("Cannot set affinity for irq %i\n", irq); |
| 251 | } | 309 | } |
| 252 | 310 | ||
| @@ -273,7 +331,7 @@ static inline void handle_one_irq(unsigned int irq) | |||
| 273 | return; | 331 | return; |
| 274 | } | 332 | } |
| 275 | 333 | ||
| 276 | desc = irq_desc + irq; | 334 | desc = irq_to_desc(irq); |
| 277 | saved_sp_limit = current->thread.ksp_limit; | 335 | saved_sp_limit = current->thread.ksp_limit; |
| 278 | 336 | ||
| 279 | irqtp->task = curtp->task; | 337 | irqtp->task = curtp->task; |
| @@ -325,6 +383,8 @@ void do_IRQ(struct pt_regs *regs) | |||
| 325 | struct pt_regs *old_regs = set_irq_regs(regs); | 383 | struct pt_regs *old_regs = set_irq_regs(regs); |
| 326 | unsigned int irq; | 384 | unsigned int irq; |
| 327 | 385 | ||
| 386 | trace_irq_entry(regs); | ||
| 387 | |||
| 328 | irq_enter(); | 388 | irq_enter(); |
| 329 | 389 | ||
| 330 | check_stack_overflow(); | 390 | check_stack_overflow(); |
| @@ -334,8 +394,7 @@ void do_IRQ(struct pt_regs *regs) | |||
| 334 | if (irq != NO_IRQ && irq != NO_IRQ_IGNORE) | 394 | if (irq != NO_IRQ && irq != NO_IRQ_IGNORE) |
| 335 | handle_one_irq(irq); | 395 | handle_one_irq(irq); |
| 336 | else if (irq != NO_IRQ_IGNORE) | 396 | else if (irq != NO_IRQ_IGNORE) |
| 337 | /* That's not SMP safe ... but who cares ? */ | 397 | __get_cpu_var(irq_stat).spurious_irqs++; |
| 338 | ppc_spurious_interrupts++; | ||
| 339 | 398 | ||
| 340 | irq_exit(); | 399 | irq_exit(); |
| 341 | set_irq_regs(old_regs); | 400 | set_irq_regs(old_regs); |
| @@ -348,6 +407,8 @@ void do_IRQ(struct pt_regs *regs) | |||
| 348 | timer_interrupt(regs); | 407 | timer_interrupt(regs); |
| 349 | } | 408 | } |
| 350 | #endif | 409 | #endif |
| 410 | |||
| 411 | trace_irq_exit(regs); | ||
| 351 | } | 412 | } |
| 352 | 413 | ||
| 353 | void __init init_IRQ(void) | 414 | void __init init_IRQ(void) |
| @@ -453,7 +514,7 @@ void do_softirq(void) | |||
| 453 | */ | 514 | */ |
| 454 | 515 | ||
| 455 | static LIST_HEAD(irq_hosts); | 516 | static LIST_HEAD(irq_hosts); |
| 456 | static DEFINE_SPINLOCK(irq_big_lock); | 517 | static DEFINE_RAW_SPINLOCK(irq_big_lock); |
| 457 | static unsigned int revmap_trees_allocated; | 518 | static unsigned int revmap_trees_allocated; |
| 458 | static DEFINE_MUTEX(revmap_trees_mutex); | 519 | static DEFINE_MUTEX(revmap_trees_mutex); |
| 459 | struct irq_map_entry irq_map[NR_IRQS]; | 520 | struct irq_map_entry irq_map[NR_IRQS]; |
| @@ -499,14 +560,14 @@ struct irq_host *irq_alloc_host(struct device_node *of_node, | |||
| 499 | if (host->ops->match == NULL) | 560 | if (host->ops->match == NULL) |
| 500 | host->ops->match = default_irq_host_match; | 561 | host->ops->match = default_irq_host_match; |
| 501 | 562 | ||
| 502 | spin_lock_irqsave(&irq_big_lock, flags); | 563 | raw_spin_lock_irqsave(&irq_big_lock, flags); |
| 503 | 564 | ||
| 504 | /* If it's a legacy controller, check for duplicates and | 565 | /* If it's a legacy controller, check for duplicates and |
| 505 | * mark it as allocated (we use irq 0 host pointer for that | 566 | * mark it as allocated (we use irq 0 host pointer for that |
| 506 | */ | 567 | */ |
| 507 | if (revmap_type == IRQ_HOST_MAP_LEGACY) { | 568 | if (revmap_type == IRQ_HOST_MAP_LEGACY) { |
| 508 | if (irq_map[0].host != NULL) { | 569 | if (irq_map[0].host != NULL) { |
| 509 | spin_unlock_irqrestore(&irq_big_lock, flags); | 570 | raw_spin_unlock_irqrestore(&irq_big_lock, flags); |
| 510 | /* If we are early boot, we can't free the structure, | 571 | /* If we are early boot, we can't free the structure, |
| 511 | * too bad... | 572 | * too bad... |
| 512 | * this will be fixed once slab is made available early | 573 | * this will be fixed once slab is made available early |
| @@ -520,7 +581,7 @@ struct irq_host *irq_alloc_host(struct device_node *of_node, | |||
| 520 | } | 581 | } |
| 521 | 582 | ||
| 522 | list_add(&host->link, &irq_hosts); | 583 | list_add(&host->link, &irq_hosts); |
| 523 | spin_unlock_irqrestore(&irq_big_lock, flags); | 584 | raw_spin_unlock_irqrestore(&irq_big_lock, flags); |
| 524 | 585 | ||
| 525 | /* Additional setups per revmap type */ | 586 | /* Additional setups per revmap type */ |
| 526 | switch(revmap_type) { | 587 | switch(revmap_type) { |
| @@ -535,7 +596,7 @@ struct irq_host *irq_alloc_host(struct device_node *of_node, | |||
| 535 | smp_wmb(); | 596 | smp_wmb(); |
| 536 | 597 | ||
| 537 | /* Clear norequest flags */ | 598 | /* Clear norequest flags */ |
| 538 | get_irq_desc(i)->status &= ~IRQ_NOREQUEST; | 599 | irq_to_desc(i)->status &= ~IRQ_NOREQUEST; |
| 539 | 600 | ||
| 540 | /* Legacy flags are left to default at this point, | 601 | /* Legacy flags are left to default at this point, |
| 541 | * one can then use irq_create_mapping() to | 602 | * one can then use irq_create_mapping() to |
| @@ -571,13 +632,13 @@ struct irq_host *irq_find_host(struct device_node *node) | |||
| 571 | * the absence of a device node. This isn't a problem so far | 632 | * the absence of a device node. This isn't a problem so far |
| 572 | * yet though... | 633 | * yet though... |
| 573 | */ | 634 | */ |
| 574 | spin_lock_irqsave(&irq_big_lock, flags); | 635 | raw_spin_lock_irqsave(&irq_big_lock, flags); |
| 575 | list_for_each_entry(h, &irq_hosts, link) | 636 | list_for_each_entry(h, &irq_hosts, link) |
| 576 | if (h->ops->match(h, node)) { | 637 | if (h->ops->match(h, node)) { |
| 577 | found = h; | 638 | found = h; |
| 578 | break; | 639 | break; |
| 579 | } | 640 | } |
| 580 | spin_unlock_irqrestore(&irq_big_lock, flags); | 641 | raw_spin_unlock_irqrestore(&irq_big_lock, flags); |
| 581 | return found; | 642 | return found; |
| 582 | } | 643 | } |
| 583 | EXPORT_SYMBOL_GPL(irq_find_host); | 644 | EXPORT_SYMBOL_GPL(irq_find_host); |
| @@ -601,8 +662,16 @@ void irq_set_virq_count(unsigned int count) | |||
| 601 | static int irq_setup_virq(struct irq_host *host, unsigned int virq, | 662 | static int irq_setup_virq(struct irq_host *host, unsigned int virq, |
| 602 | irq_hw_number_t hwirq) | 663 | irq_hw_number_t hwirq) |
| 603 | { | 664 | { |
| 665 | struct irq_desc *desc; | ||
| 666 | |||
| 667 | desc = irq_to_desc_alloc_node(virq, 0); | ||
| 668 | if (!desc) { | ||
| 669 | pr_debug("irq: -> allocating desc failed\n"); | ||
| 670 | goto error; | ||
| 671 | } | ||
| 672 | |||
| 604 | /* Clear IRQ_NOREQUEST flag */ | 673 | /* Clear IRQ_NOREQUEST flag */ |
| 605 | get_irq_desc(virq)->status &= ~IRQ_NOREQUEST; | 674 | desc->status &= ~IRQ_NOREQUEST; |
| 606 | 675 | ||
| 607 | /* map it */ | 676 | /* map it */ |
| 608 | smp_wmb(); | 677 | smp_wmb(); |
| @@ -611,11 +680,14 @@ static int irq_setup_virq(struct irq_host *host, unsigned int virq, | |||
| 611 | 680 | ||
| 612 | if (host->ops->map(host, virq, hwirq)) { | 681 | if (host->ops->map(host, virq, hwirq)) { |
| 613 | pr_debug("irq: -> mapping failed, freeing\n"); | 682 | pr_debug("irq: -> mapping failed, freeing\n"); |
| 614 | irq_free_virt(virq, 1); | 683 | goto error; |
| 615 | return -1; | ||
| 616 | } | 684 | } |
| 617 | 685 | ||
| 618 | return 0; | 686 | return 0; |
| 687 | |||
| 688 | error: | ||
| 689 | irq_free_virt(virq, 1); | ||
| 690 | return -1; | ||
| 619 | } | 691 | } |
| 620 | 692 | ||
| 621 | unsigned int irq_create_direct_mapping(struct irq_host *host) | 693 | unsigned int irq_create_direct_mapping(struct irq_host *host) |
| @@ -699,7 +771,7 @@ unsigned int irq_create_mapping(struct irq_host *host, | |||
| 699 | EXPORT_SYMBOL_GPL(irq_create_mapping); | 771 | EXPORT_SYMBOL_GPL(irq_create_mapping); |
| 700 | 772 | ||
| 701 | unsigned int irq_create_of_mapping(struct device_node *controller, | 773 | unsigned int irq_create_of_mapping(struct device_node *controller, |
| 702 | u32 *intspec, unsigned int intsize) | 774 | const u32 *intspec, unsigned int intsize) |
| 703 | { | 775 | { |
| 704 | struct irq_host *host; | 776 | struct irq_host *host; |
| 705 | irq_hw_number_t hwirq; | 777 | irq_hw_number_t hwirq; |
| @@ -732,7 +804,7 @@ unsigned int irq_create_of_mapping(struct device_node *controller, | |||
| 732 | 804 | ||
| 733 | /* Set type if specified and different than the current one */ | 805 | /* Set type if specified and different than the current one */ |
| 734 | if (type != IRQ_TYPE_NONE && | 806 | if (type != IRQ_TYPE_NONE && |
| 735 | type != (get_irq_desc(virq)->status & IRQF_TRIGGER_MASK)) | 807 | type != (irq_to_desc(virq)->status & IRQF_TRIGGER_MASK)) |
| 736 | set_irq_type(virq, type); | 808 | set_irq_type(virq, type); |
| 737 | return virq; | 809 | return virq; |
| 738 | } | 810 | } |
| @@ -804,7 +876,7 @@ void irq_dispose_mapping(unsigned int virq) | |||
| 804 | irq_map[virq].hwirq = host->inval_irq; | 876 | irq_map[virq].hwirq = host->inval_irq; |
| 805 | 877 | ||
| 806 | /* Set some flags */ | 878 | /* Set some flags */ |
| 807 | get_irq_desc(virq)->status |= IRQ_NOREQUEST; | 879 | irq_to_desc(virq)->status |= IRQ_NOREQUEST; |
| 808 | 880 | ||
| 809 | /* Free it */ | 881 | /* Free it */ |
| 810 | irq_free_virt(virq, 1); | 882 | irq_free_virt(virq, 1); |
| @@ -935,7 +1007,7 @@ unsigned int irq_alloc_virt(struct irq_host *host, | |||
| 935 | if (count == 0 || count > (irq_virq_count - NUM_ISA_INTERRUPTS)) | 1007 | if (count == 0 || count > (irq_virq_count - NUM_ISA_INTERRUPTS)) |
| 936 | return NO_IRQ; | 1008 | return NO_IRQ; |
| 937 | 1009 | ||
| 938 | spin_lock_irqsave(&irq_big_lock, flags); | 1010 | raw_spin_lock_irqsave(&irq_big_lock, flags); |
| 939 | 1011 | ||
| 940 | /* Use hint for 1 interrupt if any */ | 1012 | /* Use hint for 1 interrupt if any */ |
| 941 | if (count == 1 && hint >= NUM_ISA_INTERRUPTS && | 1013 | if (count == 1 && hint >= NUM_ISA_INTERRUPTS && |
| @@ -959,7 +1031,7 @@ unsigned int irq_alloc_virt(struct irq_host *host, | |||
| 959 | } | 1031 | } |
| 960 | } | 1032 | } |
| 961 | if (found == NO_IRQ) { | 1033 | if (found == NO_IRQ) { |
| 962 | spin_unlock_irqrestore(&irq_big_lock, flags); | 1034 | raw_spin_unlock_irqrestore(&irq_big_lock, flags); |
| 963 | return NO_IRQ; | 1035 | return NO_IRQ; |
| 964 | } | 1036 | } |
| 965 | hint_found: | 1037 | hint_found: |
| @@ -968,7 +1040,7 @@ unsigned int irq_alloc_virt(struct irq_host *host, | |||
| 968 | smp_wmb(); | 1040 | smp_wmb(); |
| 969 | irq_map[i].host = host; | 1041 | irq_map[i].host = host; |
| 970 | } | 1042 | } |
| 971 | spin_unlock_irqrestore(&irq_big_lock, flags); | 1043 | raw_spin_unlock_irqrestore(&irq_big_lock, flags); |
| 972 | return found; | 1044 | return found; |
| 973 | } | 1045 | } |
| 974 | 1046 | ||
| @@ -980,7 +1052,7 @@ void irq_free_virt(unsigned int virq, unsigned int count) | |||
| 980 | WARN_ON (virq < NUM_ISA_INTERRUPTS); | 1052 | WARN_ON (virq < NUM_ISA_INTERRUPTS); |
| 981 | WARN_ON (count == 0 || (virq + count) > irq_virq_count); | 1053 | WARN_ON (count == 0 || (virq + count) > irq_virq_count); |
| 982 | 1054 | ||
| 983 | spin_lock_irqsave(&irq_big_lock, flags); | 1055 | raw_spin_lock_irqsave(&irq_big_lock, flags); |
| 984 | for (i = virq; i < (virq + count); i++) { | 1056 | for (i = virq; i < (virq + count); i++) { |
| 985 | struct irq_host *host; | 1057 | struct irq_host *host; |
| 986 | 1058 | ||
| @@ -993,15 +1065,27 @@ void irq_free_virt(unsigned int virq, unsigned int count) | |||
| 993 | smp_wmb(); | 1065 | smp_wmb(); |
| 994 | irq_map[i].host = NULL; | 1066 | irq_map[i].host = NULL; |
| 995 | } | 1067 | } |
| 996 | spin_unlock_irqrestore(&irq_big_lock, flags); | 1068 | raw_spin_unlock_irqrestore(&irq_big_lock, flags); |
| 997 | } | 1069 | } |
| 998 | 1070 | ||
| 999 | void irq_early_init(void) | 1071 | int arch_early_irq_init(void) |
| 1000 | { | 1072 | { |
| 1001 | unsigned int i; | 1073 | struct irq_desc *desc; |
| 1074 | int i; | ||
| 1075 | |||
| 1076 | for (i = 0; i < NR_IRQS; i++) { | ||
| 1077 | desc = irq_to_desc(i); | ||
| 1078 | if (desc) | ||
| 1079 | desc->status |= IRQ_NOREQUEST; | ||
| 1080 | } | ||
| 1002 | 1081 | ||
| 1003 | for (i = 0; i < NR_IRQS; i++) | 1082 | return 0; |
| 1004 | get_irq_desc(i)->status |= IRQ_NOREQUEST; | 1083 | } |
| 1084 | |||
| 1085 | int arch_init_chip_data(struct irq_desc *desc, int node) | ||
| 1086 | { | ||
| 1087 | desc->status |= IRQ_NOREQUEST; | ||
| 1088 | return 0; | ||
| 1005 | } | 1089 | } |
| 1006 | 1090 | ||
| 1007 | /* We need to create the radix trees late */ | 1091 | /* We need to create the radix trees late */ |
| @@ -1063,16 +1147,19 @@ static int virq_debug_show(struct seq_file *m, void *private) | |||
| 1063 | seq_printf(m, "%-5s %-7s %-15s %s\n", "virq", "hwirq", | 1147 | seq_printf(m, "%-5s %-7s %-15s %s\n", "virq", "hwirq", |
| 1064 | "chip name", "host name"); | 1148 | "chip name", "host name"); |
| 1065 | 1149 | ||
| 1066 | for (i = 1; i < NR_IRQS; i++) { | 1150 | for (i = 1; i < nr_irqs; i++) { |
| 1067 | desc = get_irq_desc(i); | 1151 | desc = irq_to_desc(i); |
| 1068 | spin_lock_irqsave(&desc->lock, flags); | 1152 | if (!desc) |
| 1153 | continue; | ||
| 1154 | |||
| 1155 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
| 1069 | 1156 | ||
| 1070 | if (desc->action && desc->action->handler) { | 1157 | if (desc->action && desc->action->handler) { |
| 1071 | seq_printf(m, "%5d ", i); | 1158 | seq_printf(m, "%5d ", i); |
| 1072 | seq_printf(m, "0x%05lx ", virq_to_hw(i)); | 1159 | seq_printf(m, "0x%05lx ", virq_to_hw(i)); |
| 1073 | 1160 | ||
| 1074 | if (desc->chip && desc->chip->typename) | 1161 | if (desc->chip && desc->chip->name) |
| 1075 | p = desc->chip->typename; | 1162 | p = desc->chip->name; |
| 1076 | else | 1163 | else |
| 1077 | p = none; | 1164 | p = none; |
| 1078 | seq_printf(m, "%-15s ", p); | 1165 | seq_printf(m, "%-15s ", p); |
| @@ -1084,7 +1171,7 @@ static int virq_debug_show(struct seq_file *m, void *private) | |||
| 1084 | seq_printf(m, "%s\n", p); | 1171 | seq_printf(m, "%s\n", p); |
| 1085 | } | 1172 | } |
| 1086 | 1173 | ||
| 1087 | spin_unlock_irqrestore(&desc->lock, flags); | 1174 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
| 1088 | } | 1175 | } |
| 1089 | 1176 | ||
| 1090 | return 0; | 1177 | return 0; |
diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c index 641c74bb8e27..41bada0298c8 100644 --- a/arch/powerpc/kernel/kgdb.c +++ b/arch/powerpc/kernel/kgdb.c | |||
| @@ -52,7 +52,7 @@ static struct hard_trap_info | |||
| 52 | { 0x2030, 0x08 /* SIGFPE */ }, /* spe fp data */ | 52 | { 0x2030, 0x08 /* SIGFPE */ }, /* spe fp data */ |
| 53 | { 0x2040, 0x08 /* SIGFPE */ }, /* spe fp data */ | 53 | { 0x2040, 0x08 /* SIGFPE */ }, /* spe fp data */ |
| 54 | { 0x2050, 0x08 /* SIGFPE */ }, /* spe fp round */ | 54 | { 0x2050, 0x08 /* SIGFPE */ }, /* spe fp round */ |
| 55 | { 0x2060, 0x0e /* SIGILL */ }, /* performace monitor */ | 55 | { 0x2060, 0x0e /* SIGILL */ }, /* performance monitor */ |
| 56 | { 0x2900, 0x08 /* SIGFPE */ }, /* apu unavailable */ | 56 | { 0x2900, 0x08 /* SIGFPE */ }, /* apu unavailable */ |
| 57 | { 0x3100, 0x0e /* SIGALRM */ }, /* fixed interval timer */ | 57 | { 0x3100, 0x0e /* SIGALRM */ }, /* fixed interval timer */ |
| 58 | { 0x3200, 0x02 /* SIGINT */ }, /* watchdog */ | 58 | { 0x3200, 0x02 /* SIGINT */ }, /* watchdog */ |
| @@ -333,7 +333,7 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code, | |||
| 333 | atomic_set(&kgdb_cpu_doing_single_step, -1); | 333 | atomic_set(&kgdb_cpu_doing_single_step, -1); |
| 334 | /* set the trace bit if we're stepping */ | 334 | /* set the trace bit if we're stepping */ |
| 335 | if (remcom_in_buffer[0] == 's') { | 335 | if (remcom_in_buffer[0] == 's') { |
| 336 | #if defined(CONFIG_40x) || defined(CONFIG_BOOKE) | 336 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
| 337 | mtspr(SPRN_DBCR0, | 337 | mtspr(SPRN_DBCR0, |
| 338 | mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM); | 338 | mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM); |
| 339 | linux_regs->msr |= MSR_DE; | 339 | linux_regs->msr |= MSR_DE; |
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index c9329786073b..b36f074524ad 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c | |||
| @@ -31,12 +31,13 @@ | |||
| 31 | #include <linux/preempt.h> | 31 | #include <linux/preempt.h> |
| 32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
| 33 | #include <linux/kdebug.h> | 33 | #include <linux/kdebug.h> |
| 34 | #include <linux/slab.h> | ||
| 34 | #include <asm/cacheflush.h> | 35 | #include <asm/cacheflush.h> |
| 35 | #include <asm/sstep.h> | 36 | #include <asm/sstep.h> |
| 36 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
| 37 | #include <asm/system.h> | 38 | #include <asm/system.h> |
| 38 | 39 | ||
| 39 | #ifdef CONFIG_BOOKE | 40 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
| 40 | #define MSR_SINGLESTEP (MSR_DE) | 41 | #define MSR_SINGLESTEP (MSR_DE) |
| 41 | #else | 42 | #else |
| 42 | #define MSR_SINGLESTEP (MSR_SE) | 43 | #define MSR_SINGLESTEP (MSR_SE) |
| @@ -110,7 +111,7 @@ static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs) | |||
| 110 | * like Decrementer or External Interrupt */ | 111 | * like Decrementer or External Interrupt */ |
| 111 | regs->msr &= ~MSR_EE; | 112 | regs->msr &= ~MSR_EE; |
| 112 | regs->msr |= MSR_SINGLESTEP; | 113 | regs->msr |= MSR_SINGLESTEP; |
| 113 | #ifdef CONFIG_BOOKE | 114 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
| 114 | regs->msr &= ~MSR_CE; | 115 | regs->msr &= ~MSR_CE; |
| 115 | mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM); | 116 | mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM); |
| 116 | #endif | 117 | #endif |
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c index 9ddfaef1a184..035ada5443ee 100644 --- a/arch/powerpc/kernel/legacy_serial.c +++ b/arch/powerpc/kernel/legacy_serial.c | |||
| @@ -469,7 +469,7 @@ static int __init serial_dev_init(void) | |||
| 469 | return -ENODEV; | 469 | return -ENODEV; |
| 470 | 470 | ||
| 471 | /* | 471 | /* |
| 472 | * Before we register the platfrom serial devices, we need | 472 | * Before we register the platform serial devices, we need |
| 473 | * to fixup their interrupts and their IO ports. | 473 | * to fixup their interrupts and their IO ports. |
| 474 | */ | 474 | */ |
| 475 | DBG("Fixing serial ports interrupts and IO ports ...\n"); | 475 | DBG("Fixing serial ports interrupts and IO ports ...\n"); |
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index ed0ac4e4b8d8..c2c70e1b32cd 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/proc_fs.h> | 24 | #include <linux/proc_fs.h> |
| 25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
| 26 | #include <linux/seq_file.h> | 26 | #include <linux/seq_file.h> |
| 27 | #include <linux/slab.h> | ||
| 27 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
| 28 | #include <asm/iseries/hv_lp_config.h> | 29 | #include <asm/iseries/hv_lp_config.h> |
| 29 | #include <asm/lppaca.h> | 30 | #include <asm/lppaca.h> |
| @@ -359,7 +360,7 @@ static void parse_system_parameter_string(struct seq_file *m) | |||
| 359 | 360 | ||
| 360 | unsigned char *local_buffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL); | 361 | unsigned char *local_buffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL); |
| 361 | if (!local_buffer) { | 362 | if (!local_buffer) { |
| 362 | printk(KERN_ERR "%s %s kmalloc failure at line %d \n", | 363 | printk(KERN_ERR "%s %s kmalloc failure at line %d\n", |
| 363 | __FILE__, __func__, __LINE__); | 364 | __FILE__, __func__, __LINE__); |
| 364 | return; | 365 | return; |
| 365 | } | 366 | } |
| @@ -383,13 +384,13 @@ static void parse_system_parameter_string(struct seq_file *m) | |||
| 383 | int idx, w_idx; | 384 | int idx, w_idx; |
| 384 | char *workbuffer = kzalloc(SPLPAR_MAXLENGTH, GFP_KERNEL); | 385 | char *workbuffer = kzalloc(SPLPAR_MAXLENGTH, GFP_KERNEL); |
| 385 | if (!workbuffer) { | 386 | if (!workbuffer) { |
| 386 | printk(KERN_ERR "%s %s kmalloc failure at line %d \n", | 387 | printk(KERN_ERR "%s %s kmalloc failure at line %d\n", |
| 387 | __FILE__, __func__, __LINE__); | 388 | __FILE__, __func__, __LINE__); |
| 388 | kfree(local_buffer); | 389 | kfree(local_buffer); |
| 389 | return; | 390 | return; |
| 390 | } | 391 | } |
| 391 | #ifdef LPARCFG_DEBUG | 392 | #ifdef LPARCFG_DEBUG |
| 392 | printk(KERN_INFO "success calling get-system-parameter \n"); | 393 | printk(KERN_INFO "success calling get-system-parameter\n"); |
| 393 | #endif | 394 | #endif |
| 394 | splpar_strlen = local_buffer[0] * 256 + local_buffer[1]; | 395 | splpar_strlen = local_buffer[0] * 256 + local_buffer[1]; |
| 395 | local_buffer += 2; /* step over strlen value */ | 396 | local_buffer += 2; /* step over strlen value */ |
| @@ -440,7 +441,7 @@ static int lparcfg_count_active_processors(void) | |||
| 440 | 441 | ||
| 441 | while ((cpus_dn = of_find_node_by_type(cpus_dn, "cpu"))) { | 442 | while ((cpus_dn = of_find_node_by_type(cpus_dn, "cpu"))) { |
| 442 | #ifdef LPARCFG_DEBUG | 443 | #ifdef LPARCFG_DEBUG |
| 443 | printk(KERN_ERR "cpus_dn %p \n", cpus_dn); | 444 | printk(KERN_ERR "cpus_dn %p\n", cpus_dn); |
| 444 | #endif | 445 | #endif |
| 445 | count++; | 446 | count++; |
| 446 | } | 447 | } |
| @@ -725,7 +726,7 @@ static int lparcfg_data(struct seq_file *m, void *v) | |||
| 725 | const unsigned int *lp_index_ptr; | 726 | const unsigned int *lp_index_ptr; |
| 726 | unsigned int lp_index = 0; | 727 | unsigned int lp_index = 0; |
| 727 | 728 | ||
| 728 | seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS); | 729 | seq_printf(m, "%s %s\n", MODULE_NAME, MODULE_VERS); |
| 729 | 730 | ||
| 730 | rootdn = of_find_node_by_path("/"); | 731 | rootdn = of_find_node_by_path("/"); |
| 731 | if (rootdn) { | 732 | if (rootdn) { |
| @@ -781,9 +782,9 @@ static int __init lparcfg_init(void) | |||
| 781 | !firmware_has_feature(FW_FEATURE_ISERIES)) | 782 | !firmware_has_feature(FW_FEATURE_ISERIES)) |
| 782 | mode |= S_IWUSR; | 783 | mode |= S_IWUSR; |
| 783 | 784 | ||
| 784 | ent = proc_create("ppc64/lparcfg", mode, NULL, &lparcfg_fops); | 785 | ent = proc_create("powerpc/lparcfg", mode, NULL, &lparcfg_fops); |
| 785 | if (!ent) { | 786 | if (!ent) { |
| 786 | printk(KERN_ERR "Failed to create ppc64/lparcfg\n"); | 787 | printk(KERN_ERR "Failed to create powerpc/lparcfg\n"); |
| 787 | return -EIO; | 788 | return -EIO; |
| 788 | } | 789 | } |
| 789 | 790 | ||
diff --git a/arch/powerpc/kernel/misc.S b/arch/powerpc/kernel/misc.S index 2d29752cbe16..22e507c8a556 100644 --- a/arch/powerpc/kernel/misc.S +++ b/arch/powerpc/kernel/misc.S | |||
| @@ -127,3 +127,29 @@ _GLOBAL(__setup_cpu_power7) | |||
| 127 | _GLOBAL(__restore_cpu_power7) | 127 | _GLOBAL(__restore_cpu_power7) |
| 128 | /* place holder */ | 128 | /* place holder */ |
| 129 | blr | 129 | blr |
| 130 | |||
| 131 | /* | ||
| 132 | * Get a minimal set of registers for our caller's nth caller. | ||
| 133 | * r3 = regs pointer, r5 = n. | ||
| 134 | * | ||
| 135 | * We only get R1 (stack pointer), NIP (next instruction pointer) | ||
| 136 | * and LR (link register). These are all we can get in the | ||
| 137 | * general case without doing complicated stack unwinding, but | ||
| 138 | * fortunately they are enough to do a stack backtrace, which | ||
| 139 | * is all we need them for. | ||
| 140 | */ | ||
| 141 | _GLOBAL(perf_arch_fetch_caller_regs) | ||
| 142 | mr r6,r1 | ||
| 143 | cmpwi r5,0 | ||
| 144 | mflr r4 | ||
| 145 | ble 2f | ||
| 146 | mtctr r5 | ||
| 147 | 1: PPC_LL r6,0(r6) | ||
| 148 | bdnz 1b | ||
| 149 | PPC_LL r4,PPC_LR_STKOFF(r6) | ||
| 150 | 2: PPC_LL r7,0(r6) | ||
| 151 | PPC_LL r7,PPC_LR_STKOFF(r7) | ||
| 152 | PPC_STL r6,GPR1-STACK_FRAME_OVERHEAD(r3) | ||
| 153 | PPC_STL r4,_NIP-STACK_FRAME_OVERHEAD(r3) | ||
| 154 | PPC_STL r7,_LINK-STACK_FRAME_OVERHEAD(r3) | ||
| 155 | blr | ||
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index da9c0c4c10f3..8649f536f8df 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S | |||
| @@ -502,15 +502,7 @@ _GLOBAL(clear_pages) | |||
| 502 | li r0,PAGE_SIZE/L1_CACHE_BYTES | 502 | li r0,PAGE_SIZE/L1_CACHE_BYTES |
| 503 | slw r0,r0,r4 | 503 | slw r0,r0,r4 |
| 504 | mtctr r0 | 504 | mtctr r0 |
| 505 | #ifdef CONFIG_8xx | ||
| 506 | li r4, 0 | ||
| 507 | 1: stw r4, 0(r3) | ||
| 508 | stw r4, 4(r3) | ||
| 509 | stw r4, 8(r3) | ||
| 510 | stw r4, 12(r3) | ||
| 511 | #else | ||
| 512 | 1: dcbz 0,r3 | 505 | 1: dcbz 0,r3 |
| 513 | #endif | ||
| 514 | addi r3,r3,L1_CACHE_BYTES | 506 | addi r3,r3,L1_CACHE_BYTES |
| 515 | bdnz 1b | 507 | bdnz 1b |
| 516 | blr | 508 | blr |
| @@ -535,15 +527,6 @@ _GLOBAL(copy_page) | |||
| 535 | addi r3,r3,-4 | 527 | addi r3,r3,-4 |
| 536 | addi r4,r4,-4 | 528 | addi r4,r4,-4 |
| 537 | 529 | ||
| 538 | #ifdef CONFIG_8xx | ||
| 539 | /* don't use prefetch on 8xx */ | ||
| 540 | li r0,4096/L1_CACHE_BYTES | ||
| 541 | mtctr r0 | ||
| 542 | 1: COPY_16_BYTES | ||
| 543 | bdnz 1b | ||
| 544 | blr | ||
| 545 | |||
| 546 | #else /* not 8xx, we can prefetch */ | ||
| 547 | li r5,4 | 530 | li r5,4 |
| 548 | 531 | ||
| 549 | #if MAX_COPY_PREFETCH > 1 | 532 | #if MAX_COPY_PREFETCH > 1 |
| @@ -584,7 +567,6 @@ _GLOBAL(copy_page) | |||
| 584 | li r0,MAX_COPY_PREFETCH | 567 | li r0,MAX_COPY_PREFETCH |
| 585 | li r11,4 | 568 | li r11,4 |
| 586 | b 2b | 569 | b 2b |
| 587 | #endif /* CONFIG_8xx */ | ||
| 588 | 570 | ||
| 589 | /* | 571 | /* |
| 590 | * void atomic_clear_mask(atomic_t mask, atomic_t *addr) | 572 | * void atomic_clear_mask(atomic_t mask, atomic_t *addr) |
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c index 0ed31f220482..9cf197f01e94 100644 --- a/arch/powerpc/kernel/nvram_64.c +++ b/arch/powerpc/kernel/nvram_64.c | |||
| @@ -139,8 +139,8 @@ out: | |||
| 139 | 139 | ||
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | static int dev_nvram_ioctl(struct inode *inode, struct file *file, | 142 | static long dev_nvram_ioctl(struct file *file, unsigned int cmd, |
| 143 | unsigned int cmd, unsigned long arg) | 143 | unsigned long arg) |
| 144 | { | 144 | { |
| 145 | switch(cmd) { | 145 | switch(cmd) { |
| 146 | #ifdef CONFIG_PPC_PMAC | 146 | #ifdef CONFIG_PPC_PMAC |
| @@ -169,11 +169,11 @@ static int dev_nvram_ioctl(struct inode *inode, struct file *file, | |||
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | const struct file_operations nvram_fops = { | 171 | const struct file_operations nvram_fops = { |
| 172 | .owner = THIS_MODULE, | 172 | .owner = THIS_MODULE, |
| 173 | .llseek = dev_nvram_llseek, | 173 | .llseek = dev_nvram_llseek, |
| 174 | .read = dev_nvram_read, | 174 | .read = dev_nvram_read, |
| 175 | .write = dev_nvram_write, | 175 | .write = dev_nvram_write, |
| 176 | .ioctl = dev_nvram_ioctl, | 176 | .unlocked_ioctl = dev_nvram_ioctl, |
| 177 | }; | 177 | }; |
| 178 | 178 | ||
| 179 | static struct miscdevice nvram_dev = { | 179 | static struct miscdevice nvram_dev = { |
| @@ -184,7 +184,7 @@ static struct miscdevice nvram_dev = { | |||
| 184 | 184 | ||
| 185 | 185 | ||
| 186 | #ifdef DEBUG_NVRAM | 186 | #ifdef DEBUG_NVRAM |
| 187 | static void nvram_print_partitions(char * label) | 187 | static void __init nvram_print_partitions(char * label) |
| 188 | { | 188 | { |
| 189 | struct list_head * p; | 189 | struct list_head * p; |
| 190 | struct nvram_partition * tmp_part; | 190 | struct nvram_partition * tmp_part; |
| @@ -202,7 +202,7 @@ static void nvram_print_partitions(char * label) | |||
| 202 | #endif | 202 | #endif |
| 203 | 203 | ||
| 204 | 204 | ||
| 205 | static int nvram_write_header(struct nvram_partition * part) | 205 | static int __init nvram_write_header(struct nvram_partition * part) |
| 206 | { | 206 | { |
| 207 | loff_t tmp_index; | 207 | loff_t tmp_index; |
| 208 | int rc; | 208 | int rc; |
| @@ -214,7 +214,7 @@ static int nvram_write_header(struct nvram_partition * part) | |||
| 214 | } | 214 | } |
| 215 | 215 | ||
| 216 | 216 | ||
| 217 | static unsigned char nvram_checksum(struct nvram_header *p) | 217 | static unsigned char __init nvram_checksum(struct nvram_header *p) |
| 218 | { | 218 | { |
| 219 | unsigned int c_sum, c_sum2; | 219 | unsigned int c_sum, c_sum2; |
| 220 | unsigned short *sp = (unsigned short *)p->name; /* assume 6 shorts */ | 220 | unsigned short *sp = (unsigned short *)p->name; /* assume 6 shorts */ |
| @@ -228,32 +228,7 @@ static unsigned char nvram_checksum(struct nvram_header *p) | |||
| 228 | return c_sum; | 228 | return c_sum; |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | 231 | static int __init nvram_remove_os_partition(void) | |
| 232 | /* | ||
| 233 | * Find an nvram partition, sig can be 0 for any | ||
| 234 | * partition or name can be NULL for any name, else | ||
| 235 | * tries to match both | ||
| 236 | */ | ||
| 237 | struct nvram_partition *nvram_find_partition(int sig, const char *name) | ||
| 238 | { | ||
| 239 | struct nvram_partition * part; | ||
| 240 | struct list_head * p; | ||
| 241 | |||
| 242 | list_for_each(p, &nvram_part->partition) { | ||
| 243 | part = list_entry(p, struct nvram_partition, partition); | ||
| 244 | |||
| 245 | if (sig && part->header.signature != sig) | ||
| 246 | continue; | ||
| 247 | if (name && 0 != strncmp(name, part->header.name, 12)) | ||
| 248 | continue; | ||
| 249 | return part; | ||
| 250 | } | ||
| 251 | return NULL; | ||
| 252 | } | ||
| 253 | EXPORT_SYMBOL(nvram_find_partition); | ||
| 254 | |||
| 255 | |||
| 256 | static int nvram_remove_os_partition(void) | ||
| 257 | { | 232 | { |
| 258 | struct list_head *i; | 233 | struct list_head *i; |
| 259 | struct list_head *j; | 234 | struct list_head *j; |
| @@ -319,7 +294,7 @@ static int nvram_remove_os_partition(void) | |||
| 319 | * Will create a partition starting at the first free | 294 | * Will create a partition starting at the first free |
| 320 | * space found if space has enough room. | 295 | * space found if space has enough room. |
| 321 | */ | 296 | */ |
| 322 | static int nvram_create_os_partition(void) | 297 | static int __init nvram_create_os_partition(void) |
| 323 | { | 298 | { |
| 324 | struct nvram_partition *part; | 299 | struct nvram_partition *part; |
| 325 | struct nvram_partition *new_part; | 300 | struct nvram_partition *new_part; |
| @@ -363,8 +338,8 @@ static int nvram_create_os_partition(void) | |||
| 363 | 338 | ||
| 364 | rc = nvram_write_header(new_part); | 339 | rc = nvram_write_header(new_part); |
| 365 | if (rc <= 0) { | 340 | if (rc <= 0) { |
| 366 | printk(KERN_ERR "nvram_create_os_partition: nvram_write_header \ | 341 | printk(KERN_ERR "nvram_create_os_partition: nvram_write_header " |
| 367 | failed (%d)\n", rc); | 342 | "failed (%d)\n", rc); |
| 368 | return rc; | 343 | return rc; |
| 369 | } | 344 | } |
| 370 | 345 | ||
| @@ -374,7 +349,7 @@ static int nvram_create_os_partition(void) | |||
| 374 | rc = ppc_md.nvram_write((char *)&seq_init, sizeof(seq_init), &tmp_index); | 349 | rc = ppc_md.nvram_write((char *)&seq_init, sizeof(seq_init), &tmp_index); |
| 375 | if (rc <= 0) { | 350 | if (rc <= 0) { |
| 376 | printk(KERN_ERR "nvram_create_os_partition: nvram_write " | 351 | printk(KERN_ERR "nvram_create_os_partition: nvram_write " |
| 377 | "failed (%d)\n", rc); | 352 | "failed (%d)\n", rc); |
| 378 | return rc; | 353 | return rc; |
| 379 | } | 354 | } |
| 380 | 355 | ||
| @@ -422,7 +397,7 @@ static int nvram_create_os_partition(void) | |||
| 422 | * 5.) If the max chunk cannot be allocated then try finding a chunk | 397 | * 5.) If the max chunk cannot be allocated then try finding a chunk |
| 423 | * that will satisfy the minum needed (NVRAM_MIN_REQ). | 398 | * that will satisfy the minum needed (NVRAM_MIN_REQ). |
| 424 | */ | 399 | */ |
| 425 | static int nvram_setup_partition(void) | 400 | static int __init nvram_setup_partition(void) |
| 426 | { | 401 | { |
| 427 | struct list_head * p; | 402 | struct list_head * p; |
| 428 | struct nvram_partition * part; | 403 | struct nvram_partition * part; |
| @@ -480,7 +455,7 @@ static int nvram_setup_partition(void) | |||
| 480 | } | 455 | } |
| 481 | 456 | ||
| 482 | 457 | ||
| 483 | static int nvram_scan_partitions(void) | 458 | static int __init nvram_scan_partitions(void) |
| 484 | { | 459 | { |
| 485 | loff_t cur_index = 0; | 460 | loff_t cur_index = 0; |
| 486 | struct nvram_header phead; | 461 | struct nvram_header phead; |
| @@ -706,6 +681,9 @@ int nvram_clear_error_log(void) | |||
| 706 | int clear_word = ERR_FLAG_ALREADY_LOGGED; | 681 | int clear_word = ERR_FLAG_ALREADY_LOGGED; |
| 707 | int rc; | 682 | int rc; |
| 708 | 683 | ||
| 684 | if (nvram_error_log_index == -1) | ||
| 685 | return -1; | ||
| 686 | |||
| 709 | tmp_index = nvram_error_log_index; | 687 | tmp_index = nvram_error_log_index; |
| 710 | 688 | ||
| 711 | rc = ppc_md.nvram_write((char *)&clear_word, sizeof(int), &tmp_index); | 689 | rc = ppc_md.nvram_write((char *)&clear_word, sizeof(int), &tmp_index); |
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c index 1a4fc0d11a03..6c1dfc3ff8bc 100644 --- a/arch/powerpc/kernel/of_platform.c +++ b/arch/powerpc/kernel/of_platform.c | |||
| @@ -17,7 +17,6 @@ | |||
| 17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
| 18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
| 19 | #include <linux/mod_devicetable.h> | 19 | #include <linux/mod_devicetable.h> |
| 20 | #include <linux/slab.h> | ||
| 21 | #include <linux/pci.h> | 20 | #include <linux/pci.h> |
| 22 | #include <linux/of.h> | 21 | #include <linux/of.h> |
| 23 | #include <linux/of_device.h> | 22 | #include <linux/of_device.h> |
| @@ -214,7 +213,7 @@ EXPORT_SYMBOL(of_find_device_by_node); | |||
| 214 | static int of_dev_phandle_match(struct device *dev, void *data) | 213 | static int of_dev_phandle_match(struct device *dev, void *data) |
| 215 | { | 214 | { |
| 216 | phandle *ph = data; | 215 | phandle *ph = data; |
| 217 | return to_of_device(dev)->node->linux_phandle == *ph; | 216 | return to_of_device(dev)->node->phandle == *ph; |
| 218 | } | 217 | } |
| 219 | 218 | ||
| 220 | struct of_device *of_find_device_by_phandle(phandle ph) | 219 | struct of_device *of_find_device_by_phandle(phandle ph) |
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c index d16b1ea55d44..0c40c6f476fe 100644 --- a/arch/powerpc/kernel/paca.c +++ b/arch/powerpc/kernel/paca.c | |||
| @@ -9,11 +9,15 @@ | |||
| 9 | 9 | ||
| 10 | #include <linux/threads.h> | 10 | #include <linux/threads.h> |
| 11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
| 12 | #include <linux/lmb.h> | ||
| 12 | 13 | ||
| 14 | #include <asm/firmware.h> | ||
| 13 | #include <asm/lppaca.h> | 15 | #include <asm/lppaca.h> |
| 14 | #include <asm/paca.h> | 16 | #include <asm/paca.h> |
| 15 | #include <asm/sections.h> | 17 | #include <asm/sections.h> |
| 16 | #include <asm/pgtable.h> | 18 | #include <asm/pgtable.h> |
| 19 | #include <asm/iseries/lpar_map.h> | ||
| 20 | #include <asm/iseries/hv_types.h> | ||
| 17 | 21 | ||
| 18 | /* This symbol is provided by the linker - let it fill in the paca | 22 | /* This symbol is provided by the linker - let it fill in the paca |
| 19 | * field correctly */ | 23 | * field correctly */ |
| @@ -70,37 +74,82 @@ struct slb_shadow slb_shadow[] __cacheline_aligned = { | |||
| 70 | * processors. The processor VPD array needs one entry per physical | 74 | * processors. The processor VPD array needs one entry per physical |
| 71 | * processor (not thread). | 75 | * processor (not thread). |
| 72 | */ | 76 | */ |
| 73 | struct paca_struct paca[NR_CPUS]; | 77 | struct paca_struct *paca; |
| 74 | EXPORT_SYMBOL(paca); | 78 | EXPORT_SYMBOL(paca); |
| 75 | 79 | ||
| 76 | void __init initialise_pacas(void) | 80 | struct paca_struct boot_paca; |
| 77 | { | ||
| 78 | int cpu; | ||
| 79 | 81 | ||
| 80 | /* The TOC register (GPR2) points 32kB into the TOC, so that 64kB | 82 | void __init initialise_paca(struct paca_struct *new_paca, int cpu) |
| 81 | * of the TOC can be addressed using a single machine instruction. | 83 | { |
| 82 | */ | 84 | /* The TOC register (GPR2) points 32kB into the TOC, so that 64kB |
| 85 | * of the TOC can be addressed using a single machine instruction. | ||
| 86 | */ | ||
| 83 | unsigned long kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL; | 87 | unsigned long kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL; |
| 84 | 88 | ||
| 85 | /* Can't use for_each_*_cpu, as they aren't functional yet */ | ||
| 86 | for (cpu = 0; cpu < NR_CPUS; cpu++) { | ||
| 87 | struct paca_struct *new_paca = &paca[cpu]; | ||
| 88 | |||
| 89 | #ifdef CONFIG_PPC_BOOK3S | 89 | #ifdef CONFIG_PPC_BOOK3S |
| 90 | new_paca->lppaca_ptr = &lppaca[cpu]; | 90 | new_paca->lppaca_ptr = &lppaca[cpu]; |
| 91 | #else | 91 | #else |
| 92 | new_paca->kernel_pgd = swapper_pg_dir; | 92 | new_paca->kernel_pgd = swapper_pg_dir; |
| 93 | #endif | 93 | #endif |
| 94 | new_paca->lock_token = 0x8000; | 94 | new_paca->lock_token = 0x8000; |
| 95 | new_paca->paca_index = cpu; | 95 | new_paca->paca_index = cpu; |
| 96 | new_paca->kernel_toc = kernel_toc; | 96 | new_paca->kernel_toc = kernel_toc; |
| 97 | new_paca->kernelbase = (unsigned long) _stext; | 97 | new_paca->kernelbase = (unsigned long) _stext; |
| 98 | new_paca->kernel_msr = MSR_KERNEL; | 98 | new_paca->kernel_msr = MSR_KERNEL; |
| 99 | new_paca->hw_cpu_id = 0xffff; | 99 | new_paca->hw_cpu_id = 0xffff; |
| 100 | new_paca->__current = &init_task; | 100 | new_paca->__current = &init_task; |
| 101 | #ifdef CONFIG_PPC_STD_MMU_64 | 101 | #ifdef CONFIG_PPC_STD_MMU_64 |
| 102 | new_paca->slb_shadow_ptr = &slb_shadow[cpu]; | 102 | new_paca->slb_shadow_ptr = &slb_shadow[cpu]; |
| 103 | #endif /* CONFIG_PPC_STD_MMU_64 */ | 103 | #endif /* CONFIG_PPC_STD_MMU_64 */ |
| 104 | } | ||
| 105 | |||
| 106 | static int __initdata paca_size; | ||
| 107 | |||
| 108 | void __init allocate_pacas(void) | ||
| 109 | { | ||
| 110 | int nr_cpus, cpu, limit; | ||
| 111 | |||
| 112 | /* | ||
| 113 | * We can't take SLB misses on the paca, and we want to access them | ||
| 114 | * in real mode, so allocate them within the RMA and also within | ||
| 115 | * the first segment. On iSeries they must be within the area mapped | ||
| 116 | * by the HV, which is HvPagesToMap * HVPAGESIZE bytes. | ||
| 117 | */ | ||
| 118 | limit = min(0x10000000ULL, lmb.rmo_size); | ||
| 119 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | ||
| 120 | limit = min(limit, HvPagesToMap * HVPAGESIZE); | ||
| 121 | |||
| 122 | nr_cpus = NR_CPUS; | ||
| 123 | /* On iSeries we know we can never have more than 64 cpus */ | ||
| 124 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | ||
| 125 | nr_cpus = min(64, nr_cpus); | ||
| 126 | |||
| 127 | paca_size = PAGE_ALIGN(sizeof(struct paca_struct) * nr_cpus); | ||
| 128 | |||
| 129 | paca = __va(lmb_alloc_base(paca_size, PAGE_SIZE, limit)); | ||
| 130 | memset(paca, 0, paca_size); | ||
| 131 | |||
| 132 | printk(KERN_DEBUG "Allocated %u bytes for %d pacas at %p\n", | ||
| 133 | paca_size, nr_cpus, paca); | ||
| 134 | |||
| 135 | /* Can't use for_each_*_cpu, as they aren't functional yet */ | ||
| 136 | for (cpu = 0; cpu < nr_cpus; cpu++) | ||
| 137 | initialise_paca(&paca[cpu], cpu); | ||
| 138 | } | ||
| 139 | |||
| 140 | void __init free_unused_pacas(void) | ||
| 141 | { | ||
| 142 | int new_size; | ||
| 143 | |||
| 144 | new_size = PAGE_ALIGN(sizeof(struct paca_struct) * num_possible_cpus()); | ||
| 145 | |||
| 146 | if (new_size >= paca_size) | ||
| 147 | return; | ||
| 148 | |||
| 149 | lmb_free(__pa(paca) + new_size, paca_size - new_size); | ||
| 150 | |||
| 151 | printk(KERN_DEBUG "Freed %u bytes for unused pacas\n", | ||
| 152 | paca_size - new_size); | ||
| 104 | 153 | ||
| 105 | } | 154 | paca_size = new_size; |
| 106 | } | 155 | } |
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index e8dfdbd9327a..0c0567e58409 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/syscalls.h> | 26 | #include <linux/syscalls.h> |
| 27 | #include <linux/irq.h> | 27 | #include <linux/irq.h> |
| 28 | #include <linux/vmalloc.h> | 28 | #include <linux/vmalloc.h> |
| 29 | #include <linux/slab.h> | ||
| 29 | 30 | ||
| 30 | #include <asm/processor.h> | 31 | #include <asm/processor.h> |
| 31 | #include <asm/io.h> | 32 | #include <asm/io.h> |
| @@ -63,21 +64,6 @@ struct dma_map_ops *get_pci_dma_ops(void) | |||
| 63 | } | 64 | } |
| 64 | EXPORT_SYMBOL(get_pci_dma_ops); | 65 | EXPORT_SYMBOL(get_pci_dma_ops); |
| 65 | 66 | ||
| 66 | int pci_set_dma_mask(struct pci_dev *dev, u64 mask) | ||
| 67 | { | ||
| 68 | return dma_set_mask(&dev->dev, mask); | ||
| 69 | } | ||
| 70 | |||
| 71 | int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask) | ||
| 72 | { | ||
| 73 | int rc; | ||
| 74 | |||
| 75 | rc = dma_set_mask(&dev->dev, mask); | ||
| 76 | dev->dev.coherent_dma_mask = dev->dma_mask; | ||
| 77 | |||
| 78 | return rc; | ||
| 79 | } | ||
| 80 | |||
| 81 | struct pci_controller *pcibios_alloc_controller(struct device_node *dev) | 67 | struct pci_controller *pcibios_alloc_controller(struct device_node *dev) |
| 82 | { | 68 | { |
| 83 | struct pci_controller *phb; | 69 | struct pci_controller *phb; |
| @@ -1047,10 +1033,8 @@ static void __devinit pcibios_fixup_bridge(struct pci_bus *bus) | |||
| 1047 | 1033 | ||
| 1048 | struct pci_dev *dev = bus->self; | 1034 | struct pci_dev *dev = bus->self; |
| 1049 | 1035 | ||
| 1050 | for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) { | 1036 | pci_bus_for_each_resource(bus, res, i) { |
| 1051 | if ((res = bus->resource[i]) == NULL) | 1037 | if (!res || !res->flags) |
| 1052 | continue; | ||
| 1053 | if (!res->flags) | ||
| 1054 | continue; | 1038 | continue; |
| 1055 | if (i >= 3 && bus->self->transparent) | 1039 | if (i >= 3 && bus->self->transparent) |
| 1056 | continue; | 1040 | continue; |
| @@ -1107,6 +1091,12 @@ void __devinit pcibios_setup_bus_devices(struct pci_bus *bus) | |||
| 1107 | list_for_each_entry(dev, &bus->devices, bus_list) { | 1091 | list_for_each_entry(dev, &bus->devices, bus_list) { |
| 1108 | struct dev_archdata *sd = &dev->dev.archdata; | 1092 | struct dev_archdata *sd = &dev->dev.archdata; |
| 1109 | 1093 | ||
| 1094 | /* Cardbus can call us to add new devices to a bus, so ignore | ||
| 1095 | * those who are already fully discovered | ||
| 1096 | */ | ||
| 1097 | if (dev->is_added) | ||
| 1098 | continue; | ||
| 1099 | |||
| 1110 | /* Setup OF node pointer in archdata */ | 1100 | /* Setup OF node pointer in archdata */ |
| 1111 | sd->of_node = pci_device_to_OF_node(dev); | 1101 | sd->of_node = pci_device_to_OF_node(dev); |
| 1112 | 1102 | ||
| @@ -1147,6 +1137,13 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) | |||
| 1147 | } | 1137 | } |
| 1148 | EXPORT_SYMBOL(pcibios_fixup_bus); | 1138 | EXPORT_SYMBOL(pcibios_fixup_bus); |
| 1149 | 1139 | ||
| 1140 | void __devinit pci_fixup_cardbus(struct pci_bus *bus) | ||
| 1141 | { | ||
| 1142 | /* Now fixup devices on that bus */ | ||
| 1143 | pcibios_setup_bus_devices(bus); | ||
| 1144 | } | ||
| 1145 | |||
| 1146 | |||
| 1150 | static int skip_isa_ioresource_align(struct pci_dev *dev) | 1147 | static int skip_isa_ioresource_align(struct pci_dev *dev) |
| 1151 | { | 1148 | { |
| 1152 | if ((ppc_pci_flags & PPC_PCI_CAN_SKIP_ISA_ALIGN) && | 1149 | if ((ppc_pci_flags & PPC_PCI_CAN_SKIP_ISA_ALIGN) && |
| @@ -1168,21 +1165,20 @@ static int skip_isa_ioresource_align(struct pci_dev *dev) | |||
| 1168 | * but we want to try to avoid allocating at 0x2900-0x2bff | 1165 | * but we want to try to avoid allocating at 0x2900-0x2bff |
| 1169 | * which might have be mirrored at 0x0100-0x03ff.. | 1166 | * which might have be mirrored at 0x0100-0x03ff.. |
| 1170 | */ | 1167 | */ |
| 1171 | void pcibios_align_resource(void *data, struct resource *res, | 1168 | resource_size_t pcibios_align_resource(void *data, const struct resource *res, |
| 1172 | resource_size_t size, resource_size_t align) | 1169 | resource_size_t size, resource_size_t align) |
| 1173 | { | 1170 | { |
| 1174 | struct pci_dev *dev = data; | 1171 | struct pci_dev *dev = data; |
| 1172 | resource_size_t start = res->start; | ||
| 1175 | 1173 | ||
| 1176 | if (res->flags & IORESOURCE_IO) { | 1174 | if (res->flags & IORESOURCE_IO) { |
| 1177 | resource_size_t start = res->start; | ||
| 1178 | |||
| 1179 | if (skip_isa_ioresource_align(dev)) | 1175 | if (skip_isa_ioresource_align(dev)) |
| 1180 | return; | 1176 | return start; |
| 1181 | if (start & 0x300) { | 1177 | if (start & 0x300) |
| 1182 | start = (start + 0x3ff) & ~0x3ff; | 1178 | start = (start + 0x3ff) & ~0x3ff; |
| 1183 | res->start = start; | ||
| 1184 | } | ||
| 1185 | } | 1179 | } |
| 1180 | |||
| 1181 | return start; | ||
| 1186 | } | 1182 | } |
| 1187 | EXPORT_SYMBOL(pcibios_align_resource); | 1183 | EXPORT_SYMBOL(pcibios_align_resource); |
| 1188 | 1184 | ||
| @@ -1265,9 +1261,8 @@ void pcibios_allocate_bus_resources(struct pci_bus *bus) | |||
| 1265 | pr_debug("PCI: Allocating bus resources for %04x:%02x...\n", | 1261 | pr_debug("PCI: Allocating bus resources for %04x:%02x...\n", |
| 1266 | pci_domain_nr(bus), bus->number); | 1262 | pci_domain_nr(bus), bus->number); |
| 1267 | 1263 | ||
| 1268 | for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) { | 1264 | pci_bus_for_each_resource(bus, res, i) { |
| 1269 | if ((res = bus->resource[i]) == NULL || !res->flags | 1265 | if (!res || !res->flags || res->start > res->end || res->parent) |
| 1270 | || res->start > res->end || res->parent) | ||
| 1271 | continue; | 1266 | continue; |
| 1272 | if (bus->parent == NULL) | 1267 | if (bus->parent == NULL) |
| 1273 | pr = (res->flags & IORESOURCE_IO) ? | 1268 | pr = (res->flags & IORESOURCE_IO) ? |
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index c13668cf36d9..e7db5b48004a 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/irq.h> | 14 | #include <linux/irq.h> |
| 15 | #include <linux/list.h> | 15 | #include <linux/list.h> |
| 16 | #include <linux/of.h> | 16 | #include <linux/of.h> |
| 17 | #include <linux/slab.h> | ||
| 17 | 18 | ||
| 18 | #include <asm/processor.h> | 19 | #include <asm/processor.h> |
| 19 | #include <asm/io.h> | 20 | #include <asm/io.h> |
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index ccf56ac92de5..d43fc65749c1 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c | |||
| @@ -224,7 +224,7 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus, | |||
| 224 | * G5 machines... So when something asks for bus 0 io base | 224 | * G5 machines... So when something asks for bus 0 io base |
| 225 | * (bus 0 is HT root), we return the AGP one instead. | 225 | * (bus 0 is HT root), we return the AGP one instead. |
| 226 | */ | 226 | */ |
| 227 | if (in_bus == 0 && machine_is_compatible("MacRISC4")) { | 227 | if (in_bus == 0 && of_machine_is_compatible("MacRISC4")) { |
| 228 | struct device_node *agp; | 228 | struct device_node *agp; |
| 229 | 229 | ||
| 230 | agp = of_find_compatible_node(NULL, NULL, "u3-agp"); | 230 | agp = of_find_compatible_node(NULL, NULL, "u3-agp"); |
diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c index d5e36e5dc7c2..d56b35ee7f74 100644 --- a/arch/powerpc/kernel/pci_dn.c +++ b/arch/powerpc/kernel/pci_dn.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
| 24 | #include <linux/string.h> | 24 | #include <linux/string.h> |
| 25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
| 26 | #include <linux/gfp.h> | ||
| 26 | 27 | ||
| 27 | #include <asm/io.h> | 28 | #include <asm/io.h> |
| 28 | #include <asm/prom.h> | 29 | #include <asm/prom.h> |
diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c index 7311fdfb9bf8..cd11d5ca80df 100644 --- a/arch/powerpc/kernel/pci_of_scan.c +++ b/arch/powerpc/kernel/pci_of_scan.c | |||
| @@ -123,6 +123,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, | |||
| 123 | { | 123 | { |
| 124 | struct pci_dev *dev; | 124 | struct pci_dev *dev; |
| 125 | const char *type; | 125 | const char *type; |
| 126 | struct pci_slot *slot; | ||
| 126 | 127 | ||
| 127 | dev = alloc_pci_dev(); | 128 | dev = alloc_pci_dev(); |
| 128 | if (!dev) | 129 | if (!dev) |
| @@ -140,6 +141,11 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, | |||
| 140 | dev->devfn = devfn; | 141 | dev->devfn = devfn; |
| 141 | dev->multifunction = 0; /* maybe a lie? */ | 142 | dev->multifunction = 0; /* maybe a lie? */ |
| 142 | dev->needs_freset = 0; /* pcie fundamental reset required */ | 143 | dev->needs_freset = 0; /* pcie fundamental reset required */ |
| 144 | set_pcie_port_type(dev); | ||
| 145 | |||
| 146 | list_for_each_entry(slot, &dev->bus->slots, list) | ||
| 147 | if (PCI_SLOT(dev->devfn) == slot->number) | ||
| 148 | dev->slot = slot; | ||
| 143 | 149 | ||
| 144 | dev->vendor = get_int_prop(node, "vendor-id", 0xffff); | 150 | dev->vendor = get_int_prop(node, "vendor-id", 0xffff); |
| 145 | dev->device = get_int_prop(node, "device-id", 0xffff); | 151 | dev->device = get_int_prop(node, "device-id", 0xffff); |
| @@ -160,10 +166,14 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, | |||
| 160 | dev->error_state = pci_channel_io_normal; | 166 | dev->error_state = pci_channel_io_normal; |
| 161 | dev->dma_mask = 0xffffffff; | 167 | dev->dma_mask = 0xffffffff; |
| 162 | 168 | ||
| 169 | /* Early fixups, before probing the BARs */ | ||
| 170 | pci_fixup_device(pci_fixup_early, dev); | ||
| 171 | |||
| 163 | if (!strcmp(type, "pci") || !strcmp(type, "pciex")) { | 172 | if (!strcmp(type, "pci") || !strcmp(type, "pciex")) { |
| 164 | /* a PCI-PCI bridge */ | 173 | /* a PCI-PCI bridge */ |
| 165 | dev->hdr_type = PCI_HEADER_TYPE_BRIDGE; | 174 | dev->hdr_type = PCI_HEADER_TYPE_BRIDGE; |
| 166 | dev->rom_base_reg = PCI_ROM_ADDRESS1; | 175 | dev->rom_base_reg = PCI_ROM_ADDRESS1; |
| 176 | set_pcie_hotplug_bridge(dev); | ||
| 167 | } else if (!strcmp(type, "cardbus")) { | 177 | } else if (!strcmp(type, "cardbus")) { |
| 168 | dev->hdr_type = PCI_HEADER_TYPE_CARDBUS; | 178 | dev->hdr_type = PCI_HEADER_TYPE_CARDBUS; |
| 169 | } else { | 179 | } else { |
| @@ -294,7 +304,7 @@ static void __devinit __of_scan_bus(struct device_node *node, | |||
| 294 | int reglen, devfn; | 304 | int reglen, devfn; |
| 295 | struct pci_dev *dev; | 305 | struct pci_dev *dev; |
| 296 | 306 | ||
| 297 | pr_debug("of_scan_bus(%s) bus no %d... \n", | 307 | pr_debug("of_scan_bus(%s) bus no %d...\n", |
| 298 | node->full_name, bus->number); | 308 | node->full_name, bus->number); |
| 299 | 309 | ||
| 300 | /* Scan direct children */ | 310 | /* Scan direct children */ |
diff --git a/arch/powerpc/kernel/perf_callchain.c b/arch/powerpc/kernel/perf_callchain.c index 0a03cf70d247..95ad9dad298e 100644 --- a/arch/powerpc/kernel/perf_callchain.c +++ b/arch/powerpc/kernel/perf_callchain.c | |||
| @@ -119,13 +119,6 @@ static void perf_callchain_kernel(struct pt_regs *regs, | |||
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | #ifdef CONFIG_PPC64 | 121 | #ifdef CONFIG_PPC64 |
| 122 | |||
| 123 | #ifdef CONFIG_HUGETLB_PAGE | ||
| 124 | #define is_huge_psize(pagesize) (HPAGE_SHIFT && mmu_huge_psizes[pagesize]) | ||
| 125 | #else | ||
| 126 | #define is_huge_psize(pagesize) 0 | ||
| 127 | #endif | ||
| 128 | |||
| 129 | /* | 122 | /* |
| 130 | * On 64-bit we don't want to invoke hash_page on user addresses from | 123 | * On 64-bit we don't want to invoke hash_page on user addresses from |
| 131 | * interrupt context, so if the access faults, we read the page tables | 124 | * interrupt context, so if the access faults, we read the page tables |
| @@ -135,7 +128,7 @@ static int read_user_stack_slow(void __user *ptr, void *ret, int nb) | |||
| 135 | { | 128 | { |
| 136 | pgd_t *pgdir; | 129 | pgd_t *pgdir; |
| 137 | pte_t *ptep, pte; | 130 | pte_t *ptep, pte; |
| 138 | int pagesize; | 131 | unsigned shift; |
| 139 | unsigned long addr = (unsigned long) ptr; | 132 | unsigned long addr = (unsigned long) ptr; |
| 140 | unsigned long offset; | 133 | unsigned long offset; |
| 141 | unsigned long pfn; | 134 | unsigned long pfn; |
| @@ -145,17 +138,14 @@ static int read_user_stack_slow(void __user *ptr, void *ret, int nb) | |||
| 145 | if (!pgdir) | 138 | if (!pgdir) |
| 146 | return -EFAULT; | 139 | return -EFAULT; |
| 147 | 140 | ||
| 148 | pagesize = get_slice_psize(current->mm, addr); | 141 | ptep = find_linux_pte_or_hugepte(pgdir, addr, &shift); |
| 142 | if (!shift) | ||
| 143 | shift = PAGE_SHIFT; | ||
| 149 | 144 | ||
| 150 | /* align address to page boundary */ | 145 | /* align address to page boundary */ |
| 151 | offset = addr & ((1ul << mmu_psize_defs[pagesize].shift) - 1); | 146 | offset = addr & ((1UL << shift) - 1); |
| 152 | addr -= offset; | 147 | addr -= offset; |
| 153 | 148 | ||
| 154 | if (is_huge_psize(pagesize)) | ||
| 155 | ptep = huge_pte_offset(current->mm, addr); | ||
| 156 | else | ||
| 157 | ptep = find_linux_pte(pgdir, addr); | ||
| 158 | |||
| 159 | if (ptep == NULL) | 149 | if (ptep == NULL) |
| 160 | return -EFAULT; | 150 | return -EFAULT; |
| 161 | pte = *ptep; | 151 | pte = *ptep; |
| @@ -497,17 +487,14 @@ static void perf_callchain_user_32(struct pt_regs *regs, | |||
| 497 | * Since we can't get PMU interrupts inside a PMU interrupt handler, | 487 | * Since we can't get PMU interrupts inside a PMU interrupt handler, |
| 498 | * we don't need separate irq and nmi entries here. | 488 | * we don't need separate irq and nmi entries here. |
| 499 | */ | 489 | */ |
| 500 | static DEFINE_PER_CPU(struct perf_callchain_entry, callchain); | 490 | static DEFINE_PER_CPU(struct perf_callchain_entry, cpu_perf_callchain); |
| 501 | 491 | ||
| 502 | struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) | 492 | struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) |
| 503 | { | 493 | { |
| 504 | struct perf_callchain_entry *entry = &__get_cpu_var(callchain); | 494 | struct perf_callchain_entry *entry = &__get_cpu_var(cpu_perf_callchain); |
| 505 | 495 | ||
| 506 | entry->nr = 0; | 496 | entry->nr = 0; |
| 507 | 497 | ||
| 508 | if (current->pid == 0) /* idle task? */ | ||
| 509 | return entry; | ||
| 510 | |||
| 511 | if (!user_mode(regs)) { | 498 | if (!user_mode(regs)) { |
| 512 | perf_callchain_kernel(regs, entry); | 499 | perf_callchain_kernel(regs, entry); |
| 513 | if (current->mm) | 500 | if (current->mm) |
diff --git a/arch/powerpc/kernel/perf_event.c b/arch/powerpc/kernel/perf_event.c index 87f1663584b0..08460a2e9f41 100644 --- a/arch/powerpc/kernel/perf_event.c +++ b/arch/powerpc/kernel/perf_event.c | |||
| @@ -718,10 +718,10 @@ static int collect_events(struct perf_event *group, int max_count, | |||
| 718 | return n; | 718 | return n; |
| 719 | } | 719 | } |
| 720 | 720 | ||
| 721 | static void event_sched_in(struct perf_event *event, int cpu) | 721 | static void event_sched_in(struct perf_event *event) |
| 722 | { | 722 | { |
| 723 | event->state = PERF_EVENT_STATE_ACTIVE; | 723 | event->state = PERF_EVENT_STATE_ACTIVE; |
| 724 | event->oncpu = cpu; | 724 | event->oncpu = smp_processor_id(); |
| 725 | event->tstamp_running += event->ctx->time - event->tstamp_stopped; | 725 | event->tstamp_running += event->ctx->time - event->tstamp_stopped; |
| 726 | if (is_software_event(event)) | 726 | if (is_software_event(event)) |
| 727 | event->pmu->enable(event); | 727 | event->pmu->enable(event); |
| @@ -735,7 +735,7 @@ static void event_sched_in(struct perf_event *event, int cpu) | |||
| 735 | */ | 735 | */ |
| 736 | int hw_perf_group_sched_in(struct perf_event *group_leader, | 736 | int hw_perf_group_sched_in(struct perf_event *group_leader, |
| 737 | struct perf_cpu_context *cpuctx, | 737 | struct perf_cpu_context *cpuctx, |
| 738 | struct perf_event_context *ctx, int cpu) | 738 | struct perf_event_context *ctx) |
| 739 | { | 739 | { |
| 740 | struct cpu_hw_events *cpuhw; | 740 | struct cpu_hw_events *cpuhw; |
| 741 | long i, n, n0; | 741 | long i, n, n0; |
| @@ -766,10 +766,10 @@ int hw_perf_group_sched_in(struct perf_event *group_leader, | |||
| 766 | cpuhw->event[i]->hw.config = cpuhw->events[i]; | 766 | cpuhw->event[i]->hw.config = cpuhw->events[i]; |
| 767 | cpuctx->active_oncpu += n; | 767 | cpuctx->active_oncpu += n; |
| 768 | n = 1; | 768 | n = 1; |
| 769 | event_sched_in(group_leader, cpu); | 769 | event_sched_in(group_leader); |
| 770 | list_for_each_entry(sub, &group_leader->sibling_list, group_entry) { | 770 | list_for_each_entry(sub, &group_leader->sibling_list, group_entry) { |
| 771 | if (sub->state != PERF_EVENT_STATE_OFF) { | 771 | if (sub->state != PERF_EVENT_STATE_OFF) { |
| 772 | event_sched_in(sub, cpu); | 772 | event_sched_in(sub); |
| 773 | ++n; | 773 | ++n; |
| 774 | } | 774 | } |
| 775 | } | 775 | } |
| @@ -1164,10 +1164,10 @@ static void record_and_restart(struct perf_event *event, unsigned long val, | |||
| 1164 | * Finally record data if requested. | 1164 | * Finally record data if requested. |
| 1165 | */ | 1165 | */ |
| 1166 | if (record) { | 1166 | if (record) { |
| 1167 | struct perf_sample_data data = { | 1167 | struct perf_sample_data data; |
| 1168 | .addr = 0, | 1168 | |
| 1169 | .period = event->hw.last_period, | 1169 | perf_sample_data_init(&data, ~0ULL); |
| 1170 | }; | 1170 | data.period = event->hw.last_period; |
| 1171 | 1171 | ||
| 1172 | if (event->attr.sample_type & PERF_SAMPLE_ADDR) | 1172 | if (event->attr.sample_type & PERF_SAMPLE_ADDR) |
| 1173 | perf_get_data_addr(regs, &data.addr); | 1173 | perf_get_data_addr(regs, &data.addr); |
| @@ -1287,7 +1287,7 @@ static void perf_event_interrupt(struct pt_regs *regs) | |||
| 1287 | irq_exit(); | 1287 | irq_exit(); |
| 1288 | } | 1288 | } |
| 1289 | 1289 | ||
| 1290 | void hw_perf_event_setup(int cpu) | 1290 | static void power_pmu_setup(int cpu) |
| 1291 | { | 1291 | { |
| 1292 | struct cpu_hw_events *cpuhw = &per_cpu(cpu_hw_events, cpu); | 1292 | struct cpu_hw_events *cpuhw = &per_cpu(cpu_hw_events, cpu); |
| 1293 | 1293 | ||
| @@ -1297,6 +1297,23 @@ void hw_perf_event_setup(int cpu) | |||
| 1297 | cpuhw->mmcr[0] = MMCR0_FC; | 1297 | cpuhw->mmcr[0] = MMCR0_FC; |
| 1298 | } | 1298 | } |
| 1299 | 1299 | ||
| 1300 | static int __cpuinit | ||
| 1301 | power_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) | ||
| 1302 | { | ||
| 1303 | unsigned int cpu = (long)hcpu; | ||
| 1304 | |||
| 1305 | switch (action & ~CPU_TASKS_FROZEN) { | ||
| 1306 | case CPU_UP_PREPARE: | ||
| 1307 | power_pmu_setup(cpu); | ||
| 1308 | break; | ||
| 1309 | |||
| 1310 | default: | ||
| 1311 | break; | ||
| 1312 | } | ||
| 1313 | |||
| 1314 | return NOTIFY_OK; | ||
| 1315 | } | ||
| 1316 | |||
| 1300 | int register_power_pmu(struct power_pmu *pmu) | 1317 | int register_power_pmu(struct power_pmu *pmu) |
| 1301 | { | 1318 | { |
| 1302 | if (ppmu) | 1319 | if (ppmu) |
| @@ -1314,5 +1331,7 @@ int register_power_pmu(struct power_pmu *pmu) | |||
| 1314 | freeze_events_kernel = MMCR0_FCHV; | 1331 | freeze_events_kernel = MMCR0_FCHV; |
| 1315 | #endif /* CONFIG_PPC64 */ | 1332 | #endif /* CONFIG_PPC64 */ |
| 1316 | 1333 | ||
| 1334 | perf_cpu_notifier(power_pmu_notifier); | ||
| 1335 | |||
| 1317 | return 0; | 1336 | return 0; |
| 1318 | } | 1337 | } |
diff --git a/arch/powerpc/kernel/perf_event_fsl_emb.c b/arch/powerpc/kernel/perf_event_fsl_emb.c new file mode 100644 index 000000000000..369872f6cf78 --- /dev/null +++ b/arch/powerpc/kernel/perf_event_fsl_emb.c | |||
| @@ -0,0 +1,654 @@ | |||
| 1 | /* | ||
| 2 | * Performance event support - Freescale Embedded Performance Monitor | ||
| 3 | * | ||
| 4 | * Copyright 2008-2009 Paul Mackerras, IBM Corporation. | ||
| 5 | * Copyright 2010 Freescale Semiconductor, Inc. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU General Public License | ||
| 9 | * as published by the Free Software Foundation; either version | ||
| 10 | * 2 of the License, or (at your option) any later version. | ||
| 11 | */ | ||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/sched.h> | ||
| 14 | #include <linux/perf_event.h> | ||
| 15 | #include <linux/percpu.h> | ||
| 16 | #include <linux/hardirq.h> | ||
| 17 | #include <asm/reg_fsl_emb.h> | ||
| 18 | #include <asm/pmc.h> | ||
| 19 | #include <asm/machdep.h> | ||
| 20 | #include <asm/firmware.h> | ||
| 21 | #include <asm/ptrace.h> | ||
| 22 | |||
| 23 | struct cpu_hw_events { | ||
| 24 | int n_events; | ||
| 25 | int disabled; | ||
| 26 | u8 pmcs_enabled; | ||
| 27 | struct perf_event *event[MAX_HWEVENTS]; | ||
| 28 | }; | ||
| 29 | static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events); | ||
| 30 | |||
| 31 | static struct fsl_emb_pmu *ppmu; | ||
| 32 | |||
| 33 | /* Number of perf_events counting hardware events */ | ||
| 34 | static atomic_t num_events; | ||
| 35 | /* Used to avoid races in calling reserve/release_pmc_hardware */ | ||
| 36 | static DEFINE_MUTEX(pmc_reserve_mutex); | ||
| 37 | |||
| 38 | /* | ||
| 39 | * If interrupts were soft-disabled when a PMU interrupt occurs, treat | ||
| 40 | * it as an NMI. | ||
| 41 | */ | ||
| 42 | static inline int perf_intr_is_nmi(struct pt_regs *regs) | ||
| 43 | { | ||
| 44 | #ifdef __powerpc64__ | ||
| 45 | return !regs->softe; | ||
| 46 | #else | ||
| 47 | return 0; | ||
| 48 | #endif | ||
| 49 | } | ||
| 50 | |||
| 51 | static void perf_event_interrupt(struct pt_regs *regs); | ||
| 52 | |||
| 53 | /* | ||
| 54 | * Read one performance monitor counter (PMC). | ||
| 55 | */ | ||
| 56 | static unsigned long read_pmc(int idx) | ||
| 57 | { | ||
| 58 | unsigned long val; | ||
| 59 | |||
| 60 | switch (idx) { | ||
| 61 | case 0: | ||
| 62 | val = mfpmr(PMRN_PMC0); | ||
| 63 | break; | ||
| 64 | case 1: | ||
| 65 | val = mfpmr(PMRN_PMC1); | ||
| 66 | break; | ||
| 67 | case 2: | ||
| 68 | val = mfpmr(PMRN_PMC2); | ||
| 69 | break; | ||
| 70 | case 3: | ||
| 71 | val = mfpmr(PMRN_PMC3); | ||
| 72 | break; | ||
| 73 | default: | ||
| 74 | printk(KERN_ERR "oops trying to read PMC%d\n", idx); | ||
| 75 | val = 0; | ||
| 76 | } | ||
| 77 | return val; | ||
| 78 | } | ||
| 79 | |||
| 80 | /* | ||
| 81 | * Write one PMC. | ||
| 82 | */ | ||
| 83 | static void write_pmc(int idx, unsigned long val) | ||
| 84 | { | ||
| 85 | switch (idx) { | ||
| 86 | case 0: | ||
| 87 | mtpmr(PMRN_PMC0, val); | ||
| 88 | break; | ||
| 89 | case 1: | ||
| 90 | mtpmr(PMRN_PMC1, val); | ||
| 91 | break; | ||
| 92 | case 2: | ||
| 93 | mtpmr(PMRN_PMC2, val); | ||
| 94 | break; | ||
| 95 | case 3: | ||
| 96 | mtpmr(PMRN_PMC3, val); | ||
| 97 | break; | ||
| 98 | default: | ||
| 99 | printk(KERN_ERR "oops trying to write PMC%d\n", idx); | ||
| 100 | } | ||
| 101 | |||
| 102 | isync(); | ||
| 103 | } | ||
| 104 | |||
| 105 | /* | ||
| 106 | * Write one local control A register | ||
| 107 | */ | ||
| 108 | static void write_pmlca(int idx, unsigned long val) | ||
| 109 | { | ||
| 110 | switch (idx) { | ||
| 111 | case 0: | ||
| 112 | mtpmr(PMRN_PMLCA0, val); | ||
| 113 | break; | ||
| 114 | case 1: | ||
| 115 | mtpmr(PMRN_PMLCA1, val); | ||
| 116 | break; | ||
| 117 | case 2: | ||
| 118 | mtpmr(PMRN_PMLCA2, val); | ||
| 119 | break; | ||
| 120 | case 3: | ||
| 121 | mtpmr(PMRN_PMLCA3, val); | ||
| 122 | break; | ||
| 123 | default: | ||
| 124 | printk(KERN_ERR "oops trying to write PMLCA%d\n", idx); | ||
| 125 | } | ||
| 126 | |||
| 127 | isync(); | ||
| 128 | } | ||
| 129 | |||
| 130 | /* | ||
| 131 | * Write one local control B register | ||
| 132 | */ | ||
| 133 | static void write_pmlcb(int idx, unsigned long val) | ||
| 134 | { | ||
| 135 | switch (idx) { | ||
| 136 | case 0: | ||
| 137 | mtpmr(PMRN_PMLCB0, val); | ||
| 138 | break; | ||
| 139 | case 1: | ||
| 140 | mtpmr(PMRN_PMLCB1, val); | ||
| 141 | break; | ||
| 142 | case 2: | ||
| 143 | mtpmr(PMRN_PMLCB2, val); | ||
| 144 | break; | ||
| 145 | case 3: | ||
| 146 | mtpmr(PMRN_PMLCB3, val); | ||
| 147 | break; | ||
| 148 | default: | ||
| 149 | printk(KERN_ERR "oops trying to write PMLCB%d\n", idx); | ||
| 150 | } | ||
| 151 | |||
| 152 | isync(); | ||
| 153 | } | ||
| 154 | |||
| 155 | static void fsl_emb_pmu_read(struct perf_event *event) | ||
| 156 | { | ||
| 157 | s64 val, delta, prev; | ||
| 158 | |||
| 159 | /* | ||
| 160 | * Performance monitor interrupts come even when interrupts | ||
| 161 | * are soft-disabled, as long as interrupts are hard-enabled. | ||
| 162 | * Therefore we treat them like NMIs. | ||
| 163 | */ | ||
| 164 | do { | ||
| 165 | prev = atomic64_read(&event->hw.prev_count); | ||
| 166 | barrier(); | ||
| 167 | val = read_pmc(event->hw.idx); | ||
| 168 | } while (atomic64_cmpxchg(&event->hw.prev_count, prev, val) != prev); | ||
| 169 | |||
| 170 | /* The counters are only 32 bits wide */ | ||
| 171 | delta = (val - prev) & 0xfffffffful; | ||
| 172 | atomic64_add(delta, &event->count); | ||
| 173 | atomic64_sub(delta, &event->hw.period_left); | ||
| 174 | } | ||
| 175 | |||
| 176 | /* | ||
| 177 | * Disable all events to prevent PMU interrupts and to allow | ||
| 178 | * events to be added or removed. | ||
| 179 | */ | ||
| 180 | void hw_perf_disable(void) | ||
| 181 | { | ||
| 182 | struct cpu_hw_events *cpuhw; | ||
| 183 | unsigned long flags; | ||
| 184 | |||
| 185 | local_irq_save(flags); | ||
| 186 | cpuhw = &__get_cpu_var(cpu_hw_events); | ||
| 187 | |||
| 188 | if (!cpuhw->disabled) { | ||
| 189 | cpuhw->disabled = 1; | ||
| 190 | |||
| 191 | /* | ||
| 192 | * Check if we ever enabled the PMU on this cpu. | ||
| 193 | */ | ||
| 194 | if (!cpuhw->pmcs_enabled) { | ||
| 195 | ppc_enable_pmcs(); | ||
| 196 | cpuhw->pmcs_enabled = 1; | ||
| 197 | } | ||
| 198 | |||
| 199 | if (atomic_read(&num_events)) { | ||
| 200 | /* | ||
| 201 | * Set the 'freeze all counters' bit, and disable | ||
| 202 | * interrupts. The barrier is to make sure the | ||
| 203 | * mtpmr has been executed and the PMU has frozen | ||
| 204 | * the events before we return. | ||
| 205 | */ | ||
| 206 | |||
| 207 | mtpmr(PMRN_PMGC0, PMGC0_FAC); | ||
| 208 | isync(); | ||
| 209 | } | ||
| 210 | } | ||
| 211 | local_irq_restore(flags); | ||
| 212 | } | ||
| 213 | |||
| 214 | /* | ||
| 215 | * Re-enable all events if disable == 0. | ||
| 216 | * If we were previously disabled and events were added, then | ||
| 217 | * put the new config on the PMU. | ||
| 218 | */ | ||
| 219 | void hw_perf_enable(void) | ||
| 220 | { | ||
| 221 | struct cpu_hw_events *cpuhw; | ||
| 222 | unsigned long flags; | ||
| 223 | |||
| 224 | local_irq_save(flags); | ||
| 225 | cpuhw = &__get_cpu_var(cpu_hw_events); | ||
| 226 | if (!cpuhw->disabled) | ||
| 227 | goto out; | ||
| 228 | |||
| 229 | cpuhw->disabled = 0; | ||
| 230 | ppc_set_pmu_inuse(cpuhw->n_events != 0); | ||
| 231 | |||
| 232 | if (cpuhw->n_events > 0) { | ||
| 233 | mtpmr(PMRN_PMGC0, PMGC0_PMIE | PMGC0_FCECE); | ||
| 234 | isync(); | ||
| 235 | } | ||
| 236 | |||
| 237 | out: | ||
| 238 | local_irq_restore(flags); | ||
| 239 | } | ||
| 240 | |||
| 241 | static int collect_events(struct perf_event *group, int max_count, | ||
| 242 | struct perf_event *ctrs[]) | ||
| 243 | { | ||
| 244 | int n = 0; | ||
| 245 | struct perf_event *event; | ||
| 246 | |||
| 247 | if (!is_software_event(group)) { | ||
| 248 | if (n >= max_count) | ||
| 249 | return -1; | ||
| 250 | ctrs[n] = group; | ||
| 251 | n++; | ||
| 252 | } | ||
| 253 | list_for_each_entry(event, &group->sibling_list, group_entry) { | ||
| 254 | if (!is_software_event(event) && | ||
| 255 | event->state != PERF_EVENT_STATE_OFF) { | ||
| 256 | if (n >= max_count) | ||
| 257 | return -1; | ||
| 258 | ctrs[n] = event; | ||
| 259 | n++; | ||
| 260 | } | ||
| 261 | } | ||
| 262 | return n; | ||
| 263 | } | ||
| 264 | |||
| 265 | /* perf must be disabled, context locked on entry */ | ||
| 266 | static int fsl_emb_pmu_enable(struct perf_event *event) | ||
| 267 | { | ||
| 268 | struct cpu_hw_events *cpuhw; | ||
| 269 | int ret = -EAGAIN; | ||
| 270 | int num_counters = ppmu->n_counter; | ||
| 271 | u64 val; | ||
| 272 | int i; | ||
| 273 | |||
| 274 | cpuhw = &get_cpu_var(cpu_hw_events); | ||
| 275 | |||
| 276 | if (event->hw.config & FSL_EMB_EVENT_RESTRICTED) | ||
| 277 | num_counters = ppmu->n_restricted; | ||
| 278 | |||
| 279 | /* | ||
| 280 | * Allocate counters from top-down, so that restricted-capable | ||
| 281 | * counters are kept free as long as possible. | ||
| 282 | */ | ||
| 283 | for (i = num_counters - 1; i >= 0; i--) { | ||
| 284 | if (cpuhw->event[i]) | ||
| 285 | continue; | ||
| 286 | |||
| 287 | break; | ||
| 288 | } | ||
| 289 | |||
| 290 | if (i < 0) | ||
| 291 | goto out; | ||
| 292 | |||
| 293 | event->hw.idx = i; | ||
| 294 | cpuhw->event[i] = event; | ||
| 295 | ++cpuhw->n_events; | ||
| 296 | |||
| 297 | val = 0; | ||
| 298 | if (event->hw.sample_period) { | ||
| 299 | s64 left = atomic64_read(&event->hw.period_left); | ||
| 300 | if (left < 0x80000000L) | ||
| 301 | val = 0x80000000L - left; | ||
| 302 | } | ||
| 303 | atomic64_set(&event->hw.prev_count, val); | ||
| 304 | write_pmc(i, val); | ||
| 305 | perf_event_update_userpage(event); | ||
| 306 | |||
| 307 | write_pmlcb(i, event->hw.config >> 32); | ||
| 308 | write_pmlca(i, event->hw.config_base); | ||
| 309 | |||
| 310 | ret = 0; | ||
| 311 | out: | ||
| 312 | put_cpu_var(cpu_hw_events); | ||
| 313 | return ret; | ||
| 314 | } | ||
| 315 | |||
| 316 | /* perf must be disabled, context locked on entry */ | ||
| 317 | static void fsl_emb_pmu_disable(struct perf_event *event) | ||
| 318 | { | ||
| 319 | struct cpu_hw_events *cpuhw; | ||
| 320 | int i = event->hw.idx; | ||
| 321 | |||
| 322 | if (i < 0) | ||
| 323 | goto out; | ||
| 324 | |||
| 325 | fsl_emb_pmu_read(event); | ||
| 326 | |||
| 327 | cpuhw = &get_cpu_var(cpu_hw_events); | ||
| 328 | |||
| 329 | WARN_ON(event != cpuhw->event[event->hw.idx]); | ||
| 330 | |||
| 331 | write_pmlca(i, 0); | ||
| 332 | write_pmlcb(i, 0); | ||
| 333 | write_pmc(i, 0); | ||
| 334 | |||
| 335 | cpuhw->event[i] = NULL; | ||
| 336 | event->hw.idx = -1; | ||
| 337 | |||
| 338 | /* | ||
| 339 | * TODO: if at least one restricted event exists, and we | ||
| 340 | * just freed up a non-restricted-capable counter, and | ||
| 341 | * there is a restricted-capable counter occupied by | ||
| 342 | * a non-restricted event, migrate that event to the | ||
| 343 | * vacated counter. | ||
| 344 | */ | ||
| 345 | |||
| 346 | cpuhw->n_events--; | ||
| 347 | |||
| 348 | out: | ||
| 349 | put_cpu_var(cpu_hw_events); | ||
| 350 | } | ||
| 351 | |||
| 352 | /* | ||
| 353 | * Re-enable interrupts on a event after they were throttled | ||
| 354 | * because they were coming too fast. | ||
| 355 | * | ||
| 356 | * Context is locked on entry, but perf is not disabled. | ||
| 357 | */ | ||
| 358 | static void fsl_emb_pmu_unthrottle(struct perf_event *event) | ||
| 359 | { | ||
| 360 | s64 val, left; | ||
| 361 | unsigned long flags; | ||
| 362 | |||
| 363 | if (event->hw.idx < 0 || !event->hw.sample_period) | ||
| 364 | return; | ||
| 365 | local_irq_save(flags); | ||
| 366 | perf_disable(); | ||
| 367 | fsl_emb_pmu_read(event); | ||
| 368 | left = event->hw.sample_period; | ||
| 369 | event->hw.last_period = left; | ||
| 370 | val = 0; | ||
| 371 | if (left < 0x80000000L) | ||
| 372 | val = 0x80000000L - left; | ||
| 373 | write_pmc(event->hw.idx, val); | ||
| 374 | atomic64_set(&event->hw.prev_count, val); | ||
| 375 | atomic64_set(&event->hw.period_left, left); | ||
| 376 | perf_event_update_userpage(event); | ||
| 377 | perf_enable(); | ||
| 378 | local_irq_restore(flags); | ||
| 379 | } | ||
| 380 | |||
| 381 | static struct pmu fsl_emb_pmu = { | ||
| 382 | .enable = fsl_emb_pmu_enable, | ||
| 383 | .disable = fsl_emb_pmu_disable, | ||
| 384 | .read = fsl_emb_pmu_read, | ||
| 385 | .unthrottle = fsl_emb_pmu_unthrottle, | ||
| 386 | }; | ||
| 387 | |||
| 388 | /* | ||
| 389 | * Release the PMU if this is the last perf_event. | ||
| 390 | */ | ||
| 391 | static void hw_perf_event_destroy(struct perf_event *event) | ||
| 392 | { | ||
| 393 | if (!atomic_add_unless(&num_events, -1, 1)) { | ||
| 394 | mutex_lock(&pmc_reserve_mutex); | ||
| 395 | if (atomic_dec_return(&num_events) == 0) | ||
| 396 | release_pmc_hardware(); | ||
| 397 | mutex_unlock(&pmc_reserve_mutex); | ||
| 398 | } | ||
| 399 | } | ||
| 400 | |||
| 401 | /* | ||
| 402 | * Translate a generic cache event_id config to a raw event_id code. | ||
| 403 | */ | ||
| 404 | static int hw_perf_cache_event(u64 config, u64 *eventp) | ||
| 405 | { | ||
| 406 | unsigned long type, op, result; | ||
| 407 | int ev; | ||
| 408 | |||
| 409 | if (!ppmu->cache_events) | ||
| 410 | return -EINVAL; | ||
| 411 | |||
| 412 | /* unpack config */ | ||
| 413 | type = config & 0xff; | ||
| 414 | op = (config >> 8) & 0xff; | ||
| 415 | result = (config >> 16) & 0xff; | ||
| 416 | |||
| 417 | if (type >= PERF_COUNT_HW_CACHE_MAX || | ||
| 418 | op >= PERF_COUNT_HW_CACHE_OP_MAX || | ||
| 419 | result >= PERF_COUNT_HW_CACHE_RESULT_MAX) | ||
| 420 | return -EINVAL; | ||
| 421 | |||
| 422 | ev = (*ppmu->cache_events)[type][op][result]; | ||
| 423 | if (ev == 0) | ||
| 424 | return -EOPNOTSUPP; | ||
| 425 | if (ev == -1) | ||
| 426 | return -EINVAL; | ||
| 427 | *eventp = ev; | ||
| 428 | return 0; | ||
| 429 | } | ||
| 430 | |||
| 431 | const struct pmu *hw_perf_event_init(struct perf_event *event) | ||
| 432 | { | ||
| 433 | u64 ev; | ||
| 434 | struct perf_event *events[MAX_HWEVENTS]; | ||
| 435 | int n; | ||
| 436 | int err; | ||
| 437 | int num_restricted; | ||
| 438 | int i; | ||
| 439 | |||
| 440 | switch (event->attr.type) { | ||
| 441 | case PERF_TYPE_HARDWARE: | ||
| 442 | ev = event->attr.config; | ||
| 443 | if (ev >= ppmu->n_generic || ppmu->generic_events[ev] == 0) | ||
| 444 | return ERR_PTR(-EOPNOTSUPP); | ||
| 445 | ev = ppmu->generic_events[ev]; | ||
| 446 | break; | ||
| 447 | |||
| 448 | case PERF_TYPE_HW_CACHE: | ||
| 449 | err = hw_perf_cache_event(event->attr.config, &ev); | ||
| 450 | if (err) | ||
| 451 | return ERR_PTR(err); | ||
| 452 | break; | ||
| 453 | |||
| 454 | case PERF_TYPE_RAW: | ||
| 455 | ev = event->attr.config; | ||
| 456 | break; | ||
| 457 | |||
| 458 | default: | ||
| 459 | return ERR_PTR(-EINVAL); | ||
| 460 | } | ||
| 461 | |||
| 462 | event->hw.config = ppmu->xlate_event(ev); | ||
| 463 | if (!(event->hw.config & FSL_EMB_EVENT_VALID)) | ||
| 464 | return ERR_PTR(-EINVAL); | ||
| 465 | |||
| 466 | /* | ||
| 467 | * If this is in a group, check if it can go on with all the | ||
| 468 | * other hardware events in the group. We assume the event | ||
| 469 | * hasn't been linked into its leader's sibling list at this point. | ||
| 470 | */ | ||
| 471 | n = 0; | ||
| 472 | if (event->group_leader != event) { | ||
| 473 | n = collect_events(event->group_leader, | ||
| 474 | ppmu->n_counter - 1, events); | ||
| 475 | if (n < 0) | ||
| 476 | return ERR_PTR(-EINVAL); | ||
| 477 | } | ||
| 478 | |||
| 479 | if (event->hw.config & FSL_EMB_EVENT_RESTRICTED) { | ||
| 480 | num_restricted = 0; | ||
| 481 | for (i = 0; i < n; i++) { | ||
| 482 | if (events[i]->hw.config & FSL_EMB_EVENT_RESTRICTED) | ||
| 483 | num_restricted++; | ||
| 484 | } | ||
| 485 | |||
| 486 | if (num_restricted >= ppmu->n_restricted) | ||
| 487 | return ERR_PTR(-EINVAL); | ||
| 488 | } | ||
| 489 | |||
| 490 | event->hw.idx = -1; | ||
| 491 | |||
| 492 | event->hw.config_base = PMLCA_CE | PMLCA_FCM1 | | ||
| 493 | (u32)((ev << 16) & PMLCA_EVENT_MASK); | ||
| 494 | |||
| 495 | if (event->attr.exclude_user) | ||
| 496 | event->hw.config_base |= PMLCA_FCU; | ||
| 497 | if (event->attr.exclude_kernel) | ||
| 498 | event->hw.config_base |= PMLCA_FCS; | ||
| 499 | if (event->attr.exclude_idle) | ||
| 500 | return ERR_PTR(-ENOTSUPP); | ||
| 501 | |||
| 502 | event->hw.last_period = event->hw.sample_period; | ||
| 503 | atomic64_set(&event->hw.period_left, event->hw.last_period); | ||
| 504 | |||
| 505 | /* | ||
| 506 | * See if we need to reserve the PMU. | ||
| 507 | * If no events are currently in use, then we have to take a | ||
| 508 | * mutex to ensure that we don't race with another task doing | ||
| 509 | * reserve_pmc_hardware or release_pmc_hardware. | ||
| 510 | */ | ||
| 511 | err = 0; | ||
| 512 | if (!atomic_inc_not_zero(&num_events)) { | ||
| 513 | mutex_lock(&pmc_reserve_mutex); | ||
| 514 | if (atomic_read(&num_events) == 0 && | ||
| 515 | reserve_pmc_hardware(perf_event_interrupt)) | ||
| 516 | err = -EBUSY; | ||
| 517 | else | ||
| 518 | atomic_inc(&num_events); | ||
| 519 | mutex_unlock(&pmc_reserve_mutex); | ||
| 520 | |||
| 521 | mtpmr(PMRN_PMGC0, PMGC0_FAC); | ||
| 522 | isync(); | ||
| 523 | } | ||
| 524 | event->destroy = hw_perf_event_destroy; | ||
| 525 | |||
| 526 | if (err) | ||
| 527 | return ERR_PTR(err); | ||
| 528 | return &fsl_emb_pmu; | ||
| 529 | } | ||
| 530 | |||
| 531 | /* | ||
| 532 | * A counter has overflowed; update its count and record | ||
| 533 | * things if requested. Note that interrupts are hard-disabled | ||
| 534 | * here so there is no possibility of being interrupted. | ||
| 535 | */ | ||
| 536 | static void record_and_restart(struct perf_event *event, unsigned long val, | ||
| 537 | struct pt_regs *regs, int nmi) | ||
| 538 | { | ||
| 539 | u64 period = event->hw.sample_period; | ||
| 540 | s64 prev, delta, left; | ||
| 541 | int record = 0; | ||
| 542 | |||
| 543 | /* we don't have to worry about interrupts here */ | ||
| 544 | prev = atomic64_read(&event->hw.prev_count); | ||
| 545 | delta = (val - prev) & 0xfffffffful; | ||
| 546 | atomic64_add(delta, &event->count); | ||
| 547 | |||
| 548 | /* | ||
| 549 | * See if the total period for this event has expired, | ||
| 550 | * and update for the next period. | ||
| 551 | */ | ||
| 552 | val = 0; | ||
| 553 | left = atomic64_read(&event->hw.period_left) - delta; | ||
| 554 | if (period) { | ||
| 555 | if (left <= 0) { | ||
| 556 | left += period; | ||
| 557 | if (left <= 0) | ||
| 558 | left = period; | ||
| 559 | record = 1; | ||
| 560 | } | ||
| 561 | if (left < 0x80000000LL) | ||
| 562 | val = 0x80000000LL - left; | ||
| 563 | } | ||
| 564 | |||
| 565 | /* | ||
| 566 | * Finally record data if requested. | ||
| 567 | */ | ||
| 568 | if (record) { | ||
| 569 | struct perf_sample_data data = { | ||
| 570 | .period = event->hw.last_period, | ||
| 571 | }; | ||
| 572 | |||
| 573 | if (perf_event_overflow(event, nmi, &data, regs)) { | ||
| 574 | /* | ||
| 575 | * Interrupts are coming too fast - throttle them | ||
| 576 | * by setting the event to 0, so it will be | ||
| 577 | * at least 2^30 cycles until the next interrupt | ||
| 578 | * (assuming each event counts at most 2 counts | ||
| 579 | * per cycle). | ||
| 580 | */ | ||
| 581 | val = 0; | ||
| 582 | left = ~0ULL >> 1; | ||
| 583 | } | ||
| 584 | } | ||
| 585 | |||
| 586 | write_pmc(event->hw.idx, val); | ||
| 587 | atomic64_set(&event->hw.prev_count, val); | ||
| 588 | atomic64_set(&event->hw.period_left, left); | ||
| 589 | perf_event_update_userpage(event); | ||
| 590 | } | ||
| 591 | |||
| 592 | static void perf_event_interrupt(struct pt_regs *regs) | ||
| 593 | { | ||
| 594 | int i; | ||
| 595 | struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events); | ||
| 596 | struct perf_event *event; | ||
| 597 | unsigned long val; | ||
| 598 | int found = 0; | ||
| 599 | int nmi; | ||
| 600 | |||
| 601 | nmi = perf_intr_is_nmi(regs); | ||
| 602 | if (nmi) | ||
| 603 | nmi_enter(); | ||
| 604 | else | ||
| 605 | irq_enter(); | ||
| 606 | |||
| 607 | for (i = 0; i < ppmu->n_counter; ++i) { | ||
| 608 | event = cpuhw->event[i]; | ||
| 609 | |||
| 610 | val = read_pmc(i); | ||
| 611 | if ((int)val < 0) { | ||
| 612 | if (event) { | ||
| 613 | /* event has overflowed */ | ||
| 614 | found = 1; | ||
| 615 | record_and_restart(event, val, regs, nmi); | ||
| 616 | } else { | ||
| 617 | /* | ||
| 618 | * Disabled counter is negative, | ||
| 619 | * reset it just in case. | ||
| 620 | */ | ||
| 621 | write_pmc(i, 0); | ||
| 622 | } | ||
| 623 | } | ||
| 624 | } | ||
| 625 | |||
| 626 | /* PMM will keep counters frozen until we return from the interrupt. */ | ||
| 627 | mtmsr(mfmsr() | MSR_PMM); | ||
| 628 | mtpmr(PMRN_PMGC0, PMGC0_PMIE | PMGC0_FCECE); | ||
| 629 | isync(); | ||
| 630 | |||
| 631 | if (nmi) | ||
| 632 | nmi_exit(); | ||
| 633 | else | ||
| 634 | irq_exit(); | ||
| 635 | } | ||
| 636 | |||
| 637 | void hw_perf_event_setup(int cpu) | ||
| 638 | { | ||
| 639 | struct cpu_hw_events *cpuhw = &per_cpu(cpu_hw_events, cpu); | ||
| 640 | |||
| 641 | memset(cpuhw, 0, sizeof(*cpuhw)); | ||
| 642 | } | ||
| 643 | |||
| 644 | int register_fsl_emb_pmu(struct fsl_emb_pmu *pmu) | ||
| 645 | { | ||
| 646 | if (ppmu) | ||
| 647 | return -EBUSY; /* something's already registered */ | ||
| 648 | |||
| 649 | ppmu = pmu; | ||
| 650 | pr_info("%s performance monitor hardware support registered\n", | ||
| 651 | pmu->name); | ||
| 652 | |||
| 653 | return 0; | ||
| 654 | } | ||
diff --git a/arch/powerpc/kernel/pmc.c b/arch/powerpc/kernel/pmc.c index 0516e2d3e02e..461499b43cff 100644 --- a/arch/powerpc/kernel/pmc.c +++ b/arch/powerpc/kernel/pmc.c | |||
| @@ -37,7 +37,7 @@ static void dummy_perf(struct pt_regs *regs) | |||
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | 39 | ||
| 40 | static DEFINE_SPINLOCK(pmc_owner_lock); | 40 | static DEFINE_RAW_SPINLOCK(pmc_owner_lock); |
| 41 | static void *pmc_owner_caller; /* mostly for debugging */ | 41 | static void *pmc_owner_caller; /* mostly for debugging */ |
| 42 | perf_irq_t perf_irq = dummy_perf; | 42 | perf_irq_t perf_irq = dummy_perf; |
| 43 | 43 | ||
| @@ -45,7 +45,7 @@ int reserve_pmc_hardware(perf_irq_t new_perf_irq) | |||
| 45 | { | 45 | { |
| 46 | int err = 0; | 46 | int err = 0; |
| 47 | 47 | ||
| 48 | spin_lock(&pmc_owner_lock); | 48 | raw_spin_lock(&pmc_owner_lock); |
| 49 | 49 | ||
| 50 | if (pmc_owner_caller) { | 50 | if (pmc_owner_caller) { |
| 51 | printk(KERN_WARNING "reserve_pmc_hardware: " | 51 | printk(KERN_WARNING "reserve_pmc_hardware: " |
| @@ -59,21 +59,21 @@ int reserve_pmc_hardware(perf_irq_t new_perf_irq) | |||
| 59 | perf_irq = new_perf_irq ? new_perf_irq : dummy_perf; | 59 | perf_irq = new_perf_irq ? new_perf_irq : dummy_perf; |
| 60 | 60 | ||
| 61 | out: | 61 | out: |
| 62 | spin_unlock(&pmc_owner_lock); | 62 | raw_spin_unlock(&pmc_owner_lock); |
| 63 | return err; | 63 | return err; |
| 64 | } | 64 | } |
| 65 | EXPORT_SYMBOL_GPL(reserve_pmc_hardware); | 65 | EXPORT_SYMBOL_GPL(reserve_pmc_hardware); |
| 66 | 66 | ||
| 67 | void release_pmc_hardware(void) | 67 | void release_pmc_hardware(void) |
| 68 | { | 68 | { |
| 69 | spin_lock(&pmc_owner_lock); | 69 | raw_spin_lock(&pmc_owner_lock); |
| 70 | 70 | ||
| 71 | WARN_ON(! pmc_owner_caller); | 71 | WARN_ON(! pmc_owner_caller); |
| 72 | 72 | ||
| 73 | pmc_owner_caller = NULL; | 73 | pmc_owner_caller = NULL; |
| 74 | perf_irq = dummy_perf; | 74 | perf_irq = dummy_perf; |
| 75 | 75 | ||
| 76 | spin_unlock(&pmc_owner_lock); | 76 | raw_spin_unlock(&pmc_owner_lock); |
| 77 | } | 77 | } |
| 78 | EXPORT_SYMBOL_GPL(release_pmc_hardware); | 78 | EXPORT_SYMBOL_GPL(release_pmc_hardware); |
| 79 | 79 | ||
diff --git a/arch/powerpc/kernel/power5+-pmu.c b/arch/powerpc/kernel/power5+-pmu.c index 0f4c1c73a6ad..199de527d411 100644 --- a/arch/powerpc/kernel/power5+-pmu.c +++ b/arch/powerpc/kernel/power5+-pmu.c | |||
| @@ -73,10 +73,6 @@ | |||
| 73 | #define MMCR1_PMCSEL_MSK 0x7f | 73 | #define MMCR1_PMCSEL_MSK 0x7f |
| 74 | 74 | ||
| 75 | /* | 75 | /* |
| 76 | * Bits in MMCRA | ||
| 77 | */ | ||
| 78 | |||
| 79 | /* | ||
| 80 | * Layout of constraint bits: | 76 | * Layout of constraint bits: |
| 81 | * 6666555555555544444444443333333333222222222211111111110000000000 | 77 | * 6666555555555544444444443333333333222222222211111111110000000000 |
| 82 | * 3210987654321098765432109876543210987654321098765432109876543210 | 78 | * 3210987654321098765432109876543210987654321098765432109876543210 |
diff --git a/arch/powerpc/kernel/power5-pmu.c b/arch/powerpc/kernel/power5-pmu.c index c351b3a57fbb..98b6a729a9dd 100644 --- a/arch/powerpc/kernel/power5-pmu.c +++ b/arch/powerpc/kernel/power5-pmu.c | |||
| @@ -73,10 +73,6 @@ | |||
| 73 | #define MMCR1_PMCSEL_MSK 0x7f | 73 | #define MMCR1_PMCSEL_MSK 0x7f |
| 74 | 74 | ||
| 75 | /* | 75 | /* |
| 76 | * Bits in MMCRA | ||
| 77 | */ | ||
| 78 | |||
| 79 | /* | ||
| 80 | * Layout of constraint bits: | 76 | * Layout of constraint bits: |
| 81 | * 6666555555555544444444443333333333222222222211111111110000000000 | 77 | * 6666555555555544444444443333333333222222222211111111110000000000 |
| 82 | * 3210987654321098765432109876543210987654321098765432109876543210 | 78 | * 3210987654321098765432109876543210987654321098765432109876543210 |
| @@ -390,7 +386,7 @@ static int power5_compute_mmcr(u64 event[], int n_ev, | |||
| 390 | unsigned int hwc[], unsigned long mmcr[]) | 386 | unsigned int hwc[], unsigned long mmcr[]) |
| 391 | { | 387 | { |
| 392 | unsigned long mmcr1 = 0; | 388 | unsigned long mmcr1 = 0; |
| 393 | unsigned long mmcra = 0; | 389 | unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS; |
| 394 | unsigned int pmc, unit, byte, psel; | 390 | unsigned int pmc, unit, byte, psel; |
| 395 | unsigned int ttm, grp; | 391 | unsigned int ttm, grp; |
| 396 | int i, isbus, bit, grsel; | 392 | int i, isbus, bit, grsel; |
diff --git a/arch/powerpc/kernel/power6-pmu.c b/arch/powerpc/kernel/power6-pmu.c index ca399ba5034c..84a607bda8fb 100644 --- a/arch/powerpc/kernel/power6-pmu.c +++ b/arch/powerpc/kernel/power6-pmu.c | |||
| @@ -178,7 +178,7 @@ static int p6_compute_mmcr(u64 event[], int n_ev, | |||
| 178 | unsigned int hwc[], unsigned long mmcr[]) | 178 | unsigned int hwc[], unsigned long mmcr[]) |
| 179 | { | 179 | { |
| 180 | unsigned long mmcr1 = 0; | 180 | unsigned long mmcr1 = 0; |
| 181 | unsigned long mmcra = 0; | 181 | unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS; |
| 182 | int i; | 182 | int i; |
| 183 | unsigned int pmc, ev, b, u, s, psel; | 183 | unsigned int pmc, ev, b, u, s, psel; |
| 184 | unsigned int ttmset = 0; | 184 | unsigned int ttmset = 0; |
diff --git a/arch/powerpc/kernel/power7-pmu.c b/arch/powerpc/kernel/power7-pmu.c index 28a4daacdc02..852f7b7f6b40 100644 --- a/arch/powerpc/kernel/power7-pmu.c +++ b/arch/powerpc/kernel/power7-pmu.c | |||
| @@ -51,10 +51,6 @@ | |||
| 51 | #define MMCR1_PMCSEL_MSK 0xff | 51 | #define MMCR1_PMCSEL_MSK 0xff |
| 52 | 52 | ||
| 53 | /* | 53 | /* |
| 54 | * Bits in MMCRA | ||
| 55 | */ | ||
| 56 | |||
| 57 | /* | ||
| 58 | * Layout of constraint bits: | 54 | * Layout of constraint bits: |
| 59 | * 6666555555555544444444443333333333222222222211111111110000000000 | 55 | * 6666555555555544444444443333333333222222222211111111110000000000 |
| 60 | * 3210987654321098765432109876543210987654321098765432109876543210 | 56 | * 3210987654321098765432109876543210987654321098765432109876543210 |
| @@ -230,7 +226,7 @@ static int power7_compute_mmcr(u64 event[], int n_ev, | |||
| 230 | unsigned int hwc[], unsigned long mmcr[]) | 226 | unsigned int hwc[], unsigned long mmcr[]) |
| 231 | { | 227 | { |
| 232 | unsigned long mmcr1 = 0; | 228 | unsigned long mmcr1 = 0; |
| 233 | unsigned long mmcra = 0; | 229 | unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS; |
| 234 | unsigned int pmc, unit, combine, l2sel, psel; | 230 | unsigned int pmc, unit, combine, l2sel, psel; |
| 235 | unsigned int pmc_inuse = 0; | 231 | unsigned int pmc_inuse = 0; |
| 236 | int i; | 232 | int i; |
diff --git a/arch/powerpc/kernel/ppc970-pmu.c b/arch/powerpc/kernel/ppc970-pmu.c index 479574413a93..8eff48e20dba 100644 --- a/arch/powerpc/kernel/ppc970-pmu.c +++ b/arch/powerpc/kernel/ppc970-pmu.c | |||
| @@ -84,10 +84,6 @@ static short mmcr1_adder_bits[8] = { | |||
| 84 | }; | 84 | }; |
| 85 | 85 | ||
| 86 | /* | 86 | /* |
| 87 | * Bits in MMCRA | ||
| 88 | */ | ||
| 89 | |||
| 90 | /* | ||
| 91 | * Layout of constraint bits: | 87 | * Layout of constraint bits: |
| 92 | * 6666555555555544444444443333333333222222222211111111110000000000 | 88 | * 6666555555555544444444443333333333222222222211111111110000000000 |
| 93 | * 3210987654321098765432109876543210987654321098765432109876543210 | 89 | * 3210987654321098765432109876543210987654321098765432109876543210 |
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index c8b27bb4dbde..ab3e392ac63c 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c | |||
| @@ -96,8 +96,6 @@ EXPORT_SYMBOL(copy_4K_page); | |||
| 96 | EXPORT_SYMBOL(isa_io_base); | 96 | EXPORT_SYMBOL(isa_io_base); |
| 97 | EXPORT_SYMBOL(isa_mem_base); | 97 | EXPORT_SYMBOL(isa_mem_base); |
| 98 | EXPORT_SYMBOL(pci_dram_offset); | 98 | EXPORT_SYMBOL(pci_dram_offset); |
| 99 | EXPORT_SYMBOL(pci_alloc_consistent); | ||
| 100 | EXPORT_SYMBOL(pci_free_consistent); | ||
| 101 | #endif /* CONFIG_PCI */ | 99 | #endif /* CONFIG_PCI */ |
| 102 | 100 | ||
| 103 | EXPORT_SYMBOL(start_thread); | 101 | EXPORT_SYMBOL(start_thread); |
| @@ -109,6 +107,7 @@ EXPORT_SYMBOL(giveup_altivec); | |||
| 109 | #endif /* CONFIG_ALTIVEC */ | 107 | #endif /* CONFIG_ALTIVEC */ |
| 110 | #ifdef CONFIG_VSX | 108 | #ifdef CONFIG_VSX |
| 111 | EXPORT_SYMBOL(giveup_vsx); | 109 | EXPORT_SYMBOL(giveup_vsx); |
| 110 | EXPORT_SYMBOL_GPL(__giveup_vsx); | ||
| 112 | #endif /* CONFIG_VSX */ | 111 | #endif /* CONFIG_VSX */ |
| 113 | #ifdef CONFIG_SPE | 112 | #ifdef CONFIG_SPE |
| 114 | EXPORT_SYMBOL(giveup_spe); | 113 | EXPORT_SYMBOL(giveup_spe); |
| @@ -162,7 +161,6 @@ EXPORT_SYMBOL(screen_info); | |||
| 162 | 161 | ||
| 163 | #ifdef CONFIG_PPC32 | 162 | #ifdef CONFIG_PPC32 |
| 164 | EXPORT_SYMBOL(timer_interrupt); | 163 | EXPORT_SYMBOL(timer_interrupt); |
| 165 | EXPORT_SYMBOL(irq_desc); | ||
| 166 | EXPORT_SYMBOL(tb_ticks_per_jiffy); | 164 | EXPORT_SYMBOL(tb_ticks_per_jiffy); |
| 167 | EXPORT_SYMBOL(cacheable_memcpy); | 165 | EXPORT_SYMBOL(cacheable_memcpy); |
| 168 | EXPORT_SYMBOL(cacheable_memzero); | 166 | EXPORT_SYMBOL(cacheable_memzero); |
diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_powerpc.c index c647ddef40dc..c8ae3714e79b 100644 --- a/arch/powerpc/kernel/proc_ppc64.c +++ b/arch/powerpc/kernel/proc_powerpc.c | |||
| @@ -19,7 +19,6 @@ | |||
| 19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
| 20 | #include <linux/mm.h> | 20 | #include <linux/mm.h> |
| 21 | #include <linux/proc_fs.h> | 21 | #include <linux/proc_fs.h> |
| 22 | #include <linux/slab.h> | ||
| 23 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
| 24 | 23 | ||
| 25 | #include <asm/machdep.h> | 24 | #include <asm/machdep.h> |
| @@ -28,55 +27,7 @@ | |||
| 28 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
| 29 | #include <asm/prom.h> | 28 | #include <asm/prom.h> |
| 30 | 29 | ||
| 31 | static loff_t page_map_seek( struct file *file, loff_t off, int whence); | 30 | #ifdef CONFIG_PPC64 |
| 32 | static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes, | ||
| 33 | loff_t *ppos); | ||
| 34 | static int page_map_mmap( struct file *file, struct vm_area_struct *vma ); | ||
| 35 | |||
| 36 | static const struct file_operations page_map_fops = { | ||
| 37 | .llseek = page_map_seek, | ||
| 38 | .read = page_map_read, | ||
| 39 | .mmap = page_map_mmap | ||
| 40 | }; | ||
| 41 | |||
| 42 | /* | ||
| 43 | * Create the ppc64 and ppc64/rtas directories early. This allows us to | ||
| 44 | * assume that they have been previously created in drivers. | ||
| 45 | */ | ||
| 46 | static int __init proc_ppc64_create(void) | ||
| 47 | { | ||
| 48 | struct proc_dir_entry *root; | ||
| 49 | |||
| 50 | root = proc_mkdir("ppc64", NULL); | ||
| 51 | if (!root) | ||
| 52 | return 1; | ||
| 53 | |||
| 54 | if (!of_find_node_by_path("/rtas")) | ||
| 55 | return 0; | ||
| 56 | |||
| 57 | if (!proc_mkdir("rtas", root)) | ||
| 58 | return 1; | ||
| 59 | |||
| 60 | if (!proc_symlink("rtas", NULL, "ppc64/rtas")) | ||
| 61 | return 1; | ||
| 62 | |||
| 63 | return 0; | ||
| 64 | } | ||
| 65 | core_initcall(proc_ppc64_create); | ||
| 66 | |||
| 67 | static int __init proc_ppc64_init(void) | ||
| 68 | { | ||
| 69 | struct proc_dir_entry *pde; | ||
| 70 | |||
| 71 | pde = proc_create_data("ppc64/systemcfg", S_IFREG|S_IRUGO, NULL, | ||
| 72 | &page_map_fops, vdso_data); | ||
| 73 | if (!pde) | ||
| 74 | return 1; | ||
| 75 | pde->size = PAGE_SIZE; | ||
| 76 | |||
| 77 | return 0; | ||
| 78 | } | ||
| 79 | __initcall(proc_ppc64_init); | ||
| 80 | 31 | ||
| 81 | static loff_t page_map_seek( struct file *file, loff_t off, int whence) | 32 | static loff_t page_map_seek( struct file *file, loff_t off, int whence) |
| 82 | { | 33 | { |
| @@ -120,3 +71,55 @@ static int page_map_mmap( struct file *file, struct vm_area_struct *vma ) | |||
| 120 | return 0; | 71 | return 0; |
| 121 | } | 72 | } |
| 122 | 73 | ||
| 74 | static const struct file_operations page_map_fops = { | ||
| 75 | .llseek = page_map_seek, | ||
| 76 | .read = page_map_read, | ||
| 77 | .mmap = page_map_mmap | ||
| 78 | }; | ||
| 79 | |||
| 80 | |||
| 81 | static int __init proc_ppc64_init(void) | ||
| 82 | { | ||
| 83 | struct proc_dir_entry *pde; | ||
| 84 | |||
| 85 | pde = proc_create_data("powerpc/systemcfg", S_IFREG|S_IRUGO, NULL, | ||
| 86 | &page_map_fops, vdso_data); | ||
| 87 | if (!pde) | ||
| 88 | return 1; | ||
| 89 | pde->size = PAGE_SIZE; | ||
| 90 | |||
| 91 | return 0; | ||
| 92 | } | ||
| 93 | __initcall(proc_ppc64_init); | ||
| 94 | |||
| 95 | #endif /* CONFIG_PPC64 */ | ||
| 96 | |||
| 97 | /* | ||
| 98 | * Create the ppc64 and ppc64/rtas directories early. This allows us to | ||
| 99 | * assume that they have been previously created in drivers. | ||
| 100 | */ | ||
| 101 | static int __init proc_ppc64_create(void) | ||
| 102 | { | ||
| 103 | struct proc_dir_entry *root; | ||
| 104 | |||
| 105 | root = proc_mkdir("powerpc", NULL); | ||
| 106 | if (!root) | ||
| 107 | return 1; | ||
| 108 | |||
| 109 | #ifdef CONFIG_PPC64 | ||
| 110 | if (!proc_symlink("ppc64", NULL, "powerpc")) | ||
| 111 | pr_err("Failed to create link /proc/ppc64 -> /proc/powerpc\n"); | ||
| 112 | #endif | ||
| 113 | |||
| 114 | if (!of_find_node_by_path("/rtas")) | ||
| 115 | return 0; | ||
| 116 | |||
| 117 | if (!proc_mkdir("rtas", root)) | ||
| 118 | return 1; | ||
| 119 | |||
| 120 | if (!proc_symlink("rtas", NULL, "powerpc/rtas")) | ||
| 121 | return 1; | ||
| 122 | |||
| 123 | return 0; | ||
| 124 | } | ||
| 125 | core_initcall(proc_ppc64_create); | ||
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index c930ac38e59f..e4d71ced97ef 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
| @@ -245,6 +245,24 @@ void discard_lazy_cpu_state(void) | |||
| 245 | } | 245 | } |
| 246 | #endif /* CONFIG_SMP */ | 246 | #endif /* CONFIG_SMP */ |
| 247 | 247 | ||
| 248 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | ||
| 249 | void do_send_trap(struct pt_regs *regs, unsigned long address, | ||
| 250 | unsigned long error_code, int signal_code, int breakpt) | ||
| 251 | { | ||
| 252 | siginfo_t info; | ||
| 253 | |||
| 254 | if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code, | ||
| 255 | 11, SIGSEGV) == NOTIFY_STOP) | ||
| 256 | return; | ||
| 257 | |||
| 258 | /* Deliver the signal to userspace */ | ||
| 259 | info.si_signo = SIGTRAP; | ||
| 260 | info.si_errno = breakpt; /* breakpoint or watchpoint id */ | ||
| 261 | info.si_code = signal_code; | ||
| 262 | info.si_addr = (void __user *)address; | ||
| 263 | force_sig_info(SIGTRAP, &info, current); | ||
| 264 | } | ||
| 265 | #else /* !CONFIG_PPC_ADV_DEBUG_REGS */ | ||
| 248 | void do_dabr(struct pt_regs *regs, unsigned long address, | 266 | void do_dabr(struct pt_regs *regs, unsigned long address, |
| 249 | unsigned long error_code) | 267 | unsigned long error_code) |
| 250 | { | 268 | { |
| @@ -257,12 +275,6 @@ void do_dabr(struct pt_regs *regs, unsigned long address, | |||
| 257 | if (debugger_dabr_match(regs)) | 275 | if (debugger_dabr_match(regs)) |
| 258 | return; | 276 | return; |
| 259 | 277 | ||
| 260 | /* Clear the DAC and struct entries. One shot trigger */ | ||
| 261 | #if defined(CONFIG_BOOKE) | ||
| 262 | mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~(DBSR_DAC1R | DBSR_DAC1W | ||
| 263 | | DBCR0_IDM)); | ||
| 264 | #endif | ||
| 265 | |||
| 266 | /* Clear the DABR */ | 278 | /* Clear the DABR */ |
| 267 | set_dabr(0); | 279 | set_dabr(0); |
| 268 | 280 | ||
| @@ -273,9 +285,82 @@ void do_dabr(struct pt_regs *regs, unsigned long address, | |||
| 273 | info.si_addr = (void __user *)address; | 285 | info.si_addr = (void __user *)address; |
| 274 | force_sig_info(SIGTRAP, &info, current); | 286 | force_sig_info(SIGTRAP, &info, current); |
| 275 | } | 287 | } |
| 288 | #endif /* CONFIG_PPC_ADV_DEBUG_REGS */ | ||
| 276 | 289 | ||
| 277 | static DEFINE_PER_CPU(unsigned long, current_dabr); | 290 | static DEFINE_PER_CPU(unsigned long, current_dabr); |
| 278 | 291 | ||
| 292 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | ||
| 293 | /* | ||
| 294 | * Set the debug registers back to their default "safe" values. | ||
| 295 | */ | ||
| 296 | static void set_debug_reg_defaults(struct thread_struct *thread) | ||
| 297 | { | ||
| 298 | thread->iac1 = thread->iac2 = 0; | ||
| 299 | #if CONFIG_PPC_ADV_DEBUG_IACS > 2 | ||
| 300 | thread->iac3 = thread->iac4 = 0; | ||
| 301 | #endif | ||
| 302 | thread->dac1 = thread->dac2 = 0; | ||
| 303 | #if CONFIG_PPC_ADV_DEBUG_DVCS > 0 | ||
| 304 | thread->dvc1 = thread->dvc2 = 0; | ||
| 305 | #endif | ||
| 306 | thread->dbcr0 = 0; | ||
| 307 | #ifdef CONFIG_BOOKE | ||
| 308 | /* | ||
| 309 | * Force User/Supervisor bits to b11 (user-only MSR[PR]=1) | ||
| 310 | */ | ||
| 311 | thread->dbcr1 = DBCR1_IAC1US | DBCR1_IAC2US | \ | ||
| 312 | DBCR1_IAC3US | DBCR1_IAC4US; | ||
| 313 | /* | ||
| 314 | * Force Data Address Compare User/Supervisor bits to be User-only | ||
| 315 | * (0b11 MSR[PR]=1) and set all other bits in DBCR2 register to be 0. | ||
| 316 | */ | ||
| 317 | thread->dbcr2 = DBCR2_DAC1US | DBCR2_DAC2US; | ||
| 318 | #else | ||
| 319 | thread->dbcr1 = 0; | ||
| 320 | #endif | ||
| 321 | } | ||
| 322 | |||
| 323 | static void prime_debug_regs(struct thread_struct *thread) | ||
| 324 | { | ||
| 325 | mtspr(SPRN_IAC1, thread->iac1); | ||
| 326 | mtspr(SPRN_IAC2, thread->iac2); | ||
| 327 | #if CONFIG_PPC_ADV_DEBUG_IACS > 2 | ||
| 328 | mtspr(SPRN_IAC3, thread->iac3); | ||
| 329 | mtspr(SPRN_IAC4, thread->iac4); | ||
| 330 | #endif | ||
| 331 | mtspr(SPRN_DAC1, thread->dac1); | ||
| 332 | mtspr(SPRN_DAC2, thread->dac2); | ||
| 333 | #if CONFIG_PPC_ADV_DEBUG_DVCS > 0 | ||
| 334 | mtspr(SPRN_DVC1, thread->dvc1); | ||
| 335 | mtspr(SPRN_DVC2, thread->dvc2); | ||
| 336 | #endif | ||
| 337 | mtspr(SPRN_DBCR0, thread->dbcr0); | ||
| 338 | mtspr(SPRN_DBCR1, thread->dbcr1); | ||
| 339 | #ifdef CONFIG_BOOKE | ||
| 340 | mtspr(SPRN_DBCR2, thread->dbcr2); | ||
| 341 | #endif | ||
| 342 | } | ||
| 343 | /* | ||
| 344 | * Unless neither the old or new thread are making use of the | ||
| 345 | * debug registers, set the debug registers from the values | ||
| 346 | * stored in the new thread. | ||
| 347 | */ | ||
| 348 | static void switch_booke_debug_regs(struct thread_struct *new_thread) | ||
| 349 | { | ||
| 350 | if ((current->thread.dbcr0 & DBCR0_IDM) | ||
| 351 | || (new_thread->dbcr0 & DBCR0_IDM)) | ||
| 352 | prime_debug_regs(new_thread); | ||
| 353 | } | ||
| 354 | #else /* !CONFIG_PPC_ADV_DEBUG_REGS */ | ||
| 355 | static void set_debug_reg_defaults(struct thread_struct *thread) | ||
| 356 | { | ||
| 357 | if (thread->dabr) { | ||
| 358 | thread->dabr = 0; | ||
| 359 | set_dabr(0); | ||
| 360 | } | ||
| 361 | } | ||
| 362 | #endif /* CONFIG_PPC_ADV_DEBUG_REGS */ | ||
| 363 | |||
| 279 | int set_dabr(unsigned long dabr) | 364 | int set_dabr(unsigned long dabr) |
| 280 | { | 365 | { |
| 281 | __get_cpu_var(current_dabr) = dabr; | 366 | __get_cpu_var(current_dabr) = dabr; |
| @@ -284,7 +369,7 @@ int set_dabr(unsigned long dabr) | |||
| 284 | return ppc_md.set_dabr(dabr); | 369 | return ppc_md.set_dabr(dabr); |
| 285 | 370 | ||
| 286 | /* XXX should we have a CPU_FTR_HAS_DABR ? */ | 371 | /* XXX should we have a CPU_FTR_HAS_DABR ? */ |
| 287 | #if defined(CONFIG_BOOKE) | 372 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
| 288 | mtspr(SPRN_DAC1, dabr); | 373 | mtspr(SPRN_DAC1, dabr); |
| 289 | #elif defined(CONFIG_PPC_BOOK3S) | 374 | #elif defined(CONFIG_PPC_BOOK3S) |
| 290 | mtspr(SPRN_DABR, dabr); | 375 | mtspr(SPRN_DABR, dabr); |
| @@ -371,10 +456,8 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
| 371 | 456 | ||
| 372 | #endif /* CONFIG_SMP */ | 457 | #endif /* CONFIG_SMP */ |
| 373 | 458 | ||
| 374 | #if defined(CONFIG_BOOKE) | 459 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
| 375 | /* If new thread DAC (HW breakpoint) is the same then leave it */ | 460 | switch_booke_debug_regs(&new->thread); |
| 376 | if (new->thread.dabr) | ||
| 377 | set_dabr(new->thread.dabr); | ||
| 378 | #else | 461 | #else |
| 379 | if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) | 462 | if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) |
| 380 | set_dabr(new->thread.dabr); | 463 | set_dabr(new->thread.dabr); |
| @@ -514,7 +597,7 @@ void show_regs(struct pt_regs * regs) | |||
| 514 | printk(" CR: %08lx XER: %08lx\n", regs->ccr, regs->xer); | 597 | printk(" CR: %08lx XER: %08lx\n", regs->ccr, regs->xer); |
| 515 | trap = TRAP(regs); | 598 | trap = TRAP(regs); |
| 516 | if (trap == 0x300 || trap == 0x600) | 599 | if (trap == 0x300 || trap == 0x600) |
| 517 | #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) | 600 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
| 518 | printk("DEAR: "REG", ESR: "REG"\n", regs->dar, regs->dsisr); | 601 | printk("DEAR: "REG", ESR: "REG"\n", regs->dar, regs->dsisr); |
| 519 | #else | 602 | #else |
| 520 | printk("DAR: "REG", DSISR: "REG"\n", regs->dar, regs->dsisr); | 603 | printk("DAR: "REG", DSISR: "REG"\n", regs->dar, regs->dsisr); |
| @@ -554,28 +637,9 @@ void exit_thread(void) | |||
| 554 | 637 | ||
| 555 | void flush_thread(void) | 638 | void flush_thread(void) |
| 556 | { | 639 | { |
| 557 | #ifdef CONFIG_PPC64 | ||
| 558 | struct thread_info *t = current_thread_info(); | ||
| 559 | |||
| 560 | if (test_ti_thread_flag(t, TIF_ABI_PENDING)) { | ||
| 561 | clear_ti_thread_flag(t, TIF_ABI_PENDING); | ||
| 562 | if (test_ti_thread_flag(t, TIF_32BIT)) | ||
| 563 | clear_ti_thread_flag(t, TIF_32BIT); | ||
| 564 | else | ||
| 565 | set_ti_thread_flag(t, TIF_32BIT); | ||
| 566 | } | ||
| 567 | #endif | ||
| 568 | |||
| 569 | discard_lazy_cpu_state(); | 640 | discard_lazy_cpu_state(); |
| 570 | 641 | ||
| 571 | if (current->thread.dabr) { | 642 | set_debug_reg_defaults(¤t->thread); |
| 572 | current->thread.dabr = 0; | ||
| 573 | set_dabr(0); | ||
| 574 | |||
| 575 | #if defined(CONFIG_BOOKE) | ||
| 576 | current->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W); | ||
| 577 | #endif | ||
| 578 | } | ||
| 579 | } | 643 | } |
| 580 | 644 | ||
| 581 | void | 645 | void |
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index d4405b95bfaa..05131d634e73 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
| @@ -43,6 +43,7 @@ | |||
| 43 | #include <asm/smp.h> | 43 | #include <asm/smp.h> |
| 44 | #include <asm/system.h> | 44 | #include <asm/system.h> |
| 45 | #include <asm/mmu.h> | 45 | #include <asm/mmu.h> |
| 46 | #include <asm/paca.h> | ||
| 46 | #include <asm/pgtable.h> | 47 | #include <asm/pgtable.h> |
| 47 | #include <asm/pci.h> | 48 | #include <asm/pci.h> |
| 48 | #include <asm/iommu.h> | 49 | #include <asm/iommu.h> |
| @@ -61,365 +62,12 @@ | |||
| 61 | #define DBG(fmt...) | 62 | #define DBG(fmt...) |
| 62 | #endif | 63 | #endif |
| 63 | 64 | ||
| 64 | |||
| 65 | static int __initdata dt_root_addr_cells; | ||
| 66 | static int __initdata dt_root_size_cells; | ||
| 67 | |||
| 68 | #ifdef CONFIG_PPC64 | 65 | #ifdef CONFIG_PPC64 |
| 69 | int __initdata iommu_is_off; | 66 | int __initdata iommu_is_off; |
| 70 | int __initdata iommu_force_on; | 67 | int __initdata iommu_force_on; |
| 71 | unsigned long tce_alloc_start, tce_alloc_end; | 68 | unsigned long tce_alloc_start, tce_alloc_end; |
| 72 | #endif | 69 | #endif |
| 73 | 70 | ||
| 74 | typedef u32 cell_t; | ||
| 75 | |||
| 76 | #if 0 | ||
| 77 | static struct boot_param_header *initial_boot_params __initdata; | ||
| 78 | #else | ||
| 79 | struct boot_param_header *initial_boot_params; | ||
| 80 | #endif | ||
| 81 | |||
| 82 | extern struct device_node *allnodes; /* temporary while merging */ | ||
| 83 | |||
| 84 | extern rwlock_t devtree_lock; /* temporary while merging */ | ||
| 85 | |||
| 86 | /* export that to outside world */ | ||
| 87 | struct device_node *of_chosen; | ||
| 88 | |||
| 89 | static inline char *find_flat_dt_string(u32 offset) | ||
| 90 | { | ||
| 91 | return ((char *)initial_boot_params) + | ||
| 92 | initial_boot_params->off_dt_strings + offset; | ||
| 93 | } | ||
| 94 | |||
| 95 | /** | ||
| 96 | * This function is used to scan the flattened device-tree, it is | ||
| 97 | * used to extract the memory informations at boot before we can | ||
| 98 | * unflatten the tree | ||
| 99 | */ | ||
| 100 | int __init of_scan_flat_dt(int (*it)(unsigned long node, | ||
| 101 | const char *uname, int depth, | ||
| 102 | void *data), | ||
| 103 | void *data) | ||
| 104 | { | ||
| 105 | unsigned long p = ((unsigned long)initial_boot_params) + | ||
| 106 | initial_boot_params->off_dt_struct; | ||
| 107 | int rc = 0; | ||
| 108 | int depth = -1; | ||
| 109 | |||
| 110 | do { | ||
| 111 | u32 tag = *((u32 *)p); | ||
| 112 | char *pathp; | ||
| 113 | |||
| 114 | p += 4; | ||
| 115 | if (tag == OF_DT_END_NODE) { | ||
| 116 | depth --; | ||
| 117 | continue; | ||
| 118 | } | ||
| 119 | if (tag == OF_DT_NOP) | ||
| 120 | continue; | ||
| 121 | if (tag == OF_DT_END) | ||
| 122 | break; | ||
| 123 | if (tag == OF_DT_PROP) { | ||
| 124 | u32 sz = *((u32 *)p); | ||
| 125 | p += 8; | ||
| 126 | if (initial_boot_params->version < 0x10) | ||
| 127 | p = _ALIGN(p, sz >= 8 ? 8 : 4); | ||
| 128 | p += sz; | ||
| 129 | p = _ALIGN(p, 4); | ||
| 130 | continue; | ||
| 131 | } | ||
| 132 | if (tag != OF_DT_BEGIN_NODE) { | ||
| 133 | printk(KERN_WARNING "Invalid tag %x scanning flattened" | ||
| 134 | " device tree !\n", tag); | ||
| 135 | return -EINVAL; | ||
| 136 | } | ||
| 137 | depth++; | ||
| 138 | pathp = (char *)p; | ||
| 139 | p = _ALIGN(p + strlen(pathp) + 1, 4); | ||
| 140 | if ((*pathp) == '/') { | ||
| 141 | char *lp, *np; | ||
| 142 | for (lp = NULL, np = pathp; *np; np++) | ||
| 143 | if ((*np) == '/') | ||
| 144 | lp = np+1; | ||
| 145 | if (lp != NULL) | ||
| 146 | pathp = lp; | ||
| 147 | } | ||
| 148 | rc = it(p, pathp, depth, data); | ||
| 149 | if (rc != 0) | ||
| 150 | break; | ||
| 151 | } while(1); | ||
| 152 | |||
| 153 | return rc; | ||
| 154 | } | ||
| 155 | |||
| 156 | unsigned long __init of_get_flat_dt_root(void) | ||
| 157 | { | ||
| 158 | unsigned long p = ((unsigned long)initial_boot_params) + | ||
| 159 | initial_boot_params->off_dt_struct; | ||
| 160 | |||
| 161 | while(*((u32 *)p) == OF_DT_NOP) | ||
| 162 | p += 4; | ||
| 163 | BUG_ON (*((u32 *)p) != OF_DT_BEGIN_NODE); | ||
| 164 | p += 4; | ||
| 165 | return _ALIGN(p + strlen((char *)p) + 1, 4); | ||
| 166 | } | ||
| 167 | |||
| 168 | /** | ||
| 169 | * This function can be used within scan_flattened_dt callback to get | ||
| 170 | * access to properties | ||
| 171 | */ | ||
| 172 | void* __init of_get_flat_dt_prop(unsigned long node, const char *name, | ||
| 173 | unsigned long *size) | ||
| 174 | { | ||
| 175 | unsigned long p = node; | ||
| 176 | |||
| 177 | do { | ||
| 178 | u32 tag = *((u32 *)p); | ||
| 179 | u32 sz, noff; | ||
| 180 | const char *nstr; | ||
| 181 | |||
| 182 | p += 4; | ||
| 183 | if (tag == OF_DT_NOP) | ||
| 184 | continue; | ||
| 185 | if (tag != OF_DT_PROP) | ||
| 186 | return NULL; | ||
| 187 | |||
| 188 | sz = *((u32 *)p); | ||
| 189 | noff = *((u32 *)(p + 4)); | ||
| 190 | p += 8; | ||
| 191 | if (initial_boot_params->version < 0x10) | ||
| 192 | p = _ALIGN(p, sz >= 8 ? 8 : 4); | ||
| 193 | |||
| 194 | nstr = find_flat_dt_string(noff); | ||
| 195 | if (nstr == NULL) { | ||
| 196 | printk(KERN_WARNING "Can't find property index" | ||
| 197 | " name !\n"); | ||
| 198 | return NULL; | ||
| 199 | } | ||
| 200 | if (strcmp(name, nstr) == 0) { | ||
| 201 | if (size) | ||
| 202 | *size = sz; | ||
| 203 | return (void *)p; | ||
| 204 | } | ||
| 205 | p += sz; | ||
| 206 | p = _ALIGN(p, 4); | ||
| 207 | } while(1); | ||
| 208 | } | ||
| 209 | |||
| 210 | int __init of_flat_dt_is_compatible(unsigned long node, const char *compat) | ||
| 211 | { | ||
| 212 | const char* cp; | ||
| 213 | unsigned long cplen, l; | ||
| 214 | |||
| 215 | cp = of_get_flat_dt_prop(node, "compatible", &cplen); | ||
| 216 | if (cp == NULL) | ||
| 217 | return 0; | ||
| 218 | while (cplen > 0) { | ||
| 219 | if (strncasecmp(cp, compat, strlen(compat)) == 0) | ||
| 220 | return 1; | ||
| 221 | l = strlen(cp) + 1; | ||
| 222 | cp += l; | ||
| 223 | cplen -= l; | ||
| 224 | } | ||
| 225 | |||
| 226 | return 0; | ||
| 227 | } | ||
| 228 | |||
| 229 | static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, | ||
| 230 | unsigned long align) | ||
| 231 | { | ||
| 232 | void *res; | ||
| 233 | |||
| 234 | *mem = _ALIGN(*mem, align); | ||
| 235 | res = (void *)*mem; | ||
| 236 | *mem += size; | ||
| 237 | |||
| 238 | return res; | ||
| 239 | } | ||
| 240 | |||
| 241 | static unsigned long __init unflatten_dt_node(unsigned long mem, | ||
| 242 | unsigned long *p, | ||
| 243 | struct device_node *dad, | ||
| 244 | struct device_node ***allnextpp, | ||
| 245 | unsigned long fpsize) | ||
| 246 | { | ||
| 247 | struct device_node *np; | ||
| 248 | struct property *pp, **prev_pp = NULL; | ||
| 249 | char *pathp; | ||
| 250 | u32 tag; | ||
| 251 | unsigned int l, allocl; | ||
| 252 | int has_name = 0; | ||
| 253 | int new_format = 0; | ||
| 254 | |||
| 255 | tag = *((u32 *)(*p)); | ||
| 256 | if (tag != OF_DT_BEGIN_NODE) { | ||
| 257 | printk("Weird tag at start of node: %x\n", tag); | ||
| 258 | return mem; | ||
| 259 | } | ||
| 260 | *p += 4; | ||
| 261 | pathp = (char *)*p; | ||
| 262 | l = allocl = strlen(pathp) + 1; | ||
| 263 | *p = _ALIGN(*p + l, 4); | ||
| 264 | |||
| 265 | /* version 0x10 has a more compact unit name here instead of the full | ||
| 266 | * path. we accumulate the full path size using "fpsize", we'll rebuild | ||
| 267 | * it later. We detect this because the first character of the name is | ||
| 268 | * not '/'. | ||
| 269 | */ | ||
| 270 | if ((*pathp) != '/') { | ||
| 271 | new_format = 1; | ||
| 272 | if (fpsize == 0) { | ||
| 273 | /* root node: special case. fpsize accounts for path | ||
| 274 | * plus terminating zero. root node only has '/', so | ||
| 275 | * fpsize should be 2, but we want to avoid the first | ||
| 276 | * level nodes to have two '/' so we use fpsize 1 here | ||
| 277 | */ | ||
| 278 | fpsize = 1; | ||
| 279 | allocl = 2; | ||
| 280 | } else { | ||
| 281 | /* account for '/' and path size minus terminal 0 | ||
| 282 | * already in 'l' | ||
| 283 | */ | ||
| 284 | fpsize += l; | ||
| 285 | allocl = fpsize; | ||
| 286 | } | ||
| 287 | } | ||
| 288 | |||
| 289 | |||
| 290 | np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl, | ||
| 291 | __alignof__(struct device_node)); | ||
| 292 | if (allnextpp) { | ||
| 293 | memset(np, 0, sizeof(*np)); | ||
| 294 | np->full_name = ((char*)np) + sizeof(struct device_node); | ||
| 295 | if (new_format) { | ||
| 296 | char *p = np->full_name; | ||
| 297 | /* rebuild full path for new format */ | ||
| 298 | if (dad && dad->parent) { | ||
| 299 | strcpy(p, dad->full_name); | ||
| 300 | #ifdef DEBUG | ||
| 301 | if ((strlen(p) + l + 1) != allocl) { | ||
| 302 | DBG("%s: p: %d, l: %d, a: %d\n", | ||
| 303 | pathp, (int)strlen(p), l, allocl); | ||
| 304 | } | ||
| 305 | #endif | ||
| 306 | p += strlen(p); | ||
| 307 | } | ||
| 308 | *(p++) = '/'; | ||
| 309 | memcpy(p, pathp, l); | ||
| 310 | } else | ||
| 311 | memcpy(np->full_name, pathp, l); | ||
| 312 | prev_pp = &np->properties; | ||
| 313 | **allnextpp = np; | ||
| 314 | *allnextpp = &np->allnext; | ||
| 315 | if (dad != NULL) { | ||
| 316 | np->parent = dad; | ||
| 317 | /* we temporarily use the next field as `last_child'*/ | ||
| 318 | if (dad->next == 0) | ||
| 319 | dad->child = np; | ||
| 320 | else | ||
| 321 | dad->next->sibling = np; | ||
| 322 | dad->next = np; | ||
| 323 | } | ||
| 324 | kref_init(&np->kref); | ||
| 325 | } | ||
| 326 | while(1) { | ||
| 327 | u32 sz, noff; | ||
| 328 | char *pname; | ||
| 329 | |||
| 330 | tag = *((u32 *)(*p)); | ||
| 331 | if (tag == OF_DT_NOP) { | ||
| 332 | *p += 4; | ||
| 333 | continue; | ||
| 334 | } | ||
| 335 | if (tag != OF_DT_PROP) | ||
| 336 | break; | ||
| 337 | *p += 4; | ||
| 338 | sz = *((u32 *)(*p)); | ||
| 339 | noff = *((u32 *)((*p) + 4)); | ||
| 340 | *p += 8; | ||
| 341 | if (initial_boot_params->version < 0x10) | ||
| 342 | *p = _ALIGN(*p, sz >= 8 ? 8 : 4); | ||
| 343 | |||
| 344 | pname = find_flat_dt_string(noff); | ||
| 345 | if (pname == NULL) { | ||
| 346 | printk("Can't find property name in list !\n"); | ||
| 347 | break; | ||
| 348 | } | ||
| 349 | if (strcmp(pname, "name") == 0) | ||
| 350 | has_name = 1; | ||
| 351 | l = strlen(pname) + 1; | ||
| 352 | pp = unflatten_dt_alloc(&mem, sizeof(struct property), | ||
| 353 | __alignof__(struct property)); | ||
| 354 | if (allnextpp) { | ||
| 355 | if (strcmp(pname, "linux,phandle") == 0) { | ||
| 356 | np->node = *((u32 *)*p); | ||
| 357 | if (np->linux_phandle == 0) | ||
| 358 | np->linux_phandle = np->node; | ||
| 359 | } | ||
| 360 | if (strcmp(pname, "ibm,phandle") == 0) | ||
| 361 | np->linux_phandle = *((u32 *)*p); | ||
| 362 | pp->name = pname; | ||
| 363 | pp->length = sz; | ||
| 364 | pp->value = (void *)*p; | ||
| 365 | *prev_pp = pp; | ||
| 366 | prev_pp = &pp->next; | ||
| 367 | } | ||
| 368 | *p = _ALIGN((*p) + sz, 4); | ||
| 369 | } | ||
| 370 | /* with version 0x10 we may not have the name property, recreate | ||
| 371 | * it here from the unit name if absent | ||
| 372 | */ | ||
| 373 | if (!has_name) { | ||
| 374 | char *p = pathp, *ps = pathp, *pa = NULL; | ||
| 375 | int sz; | ||
| 376 | |||
| 377 | while (*p) { | ||
| 378 | if ((*p) == '@') | ||
| 379 | pa = p; | ||
| 380 | if ((*p) == '/') | ||
| 381 | ps = p + 1; | ||
| 382 | p++; | ||
| 383 | } | ||
| 384 | if (pa < ps) | ||
| 385 | pa = p; | ||
| 386 | sz = (pa - ps) + 1; | ||
| 387 | pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz, | ||
| 388 | __alignof__(struct property)); | ||
| 389 | if (allnextpp) { | ||
| 390 | pp->name = "name"; | ||
| 391 | pp->length = sz; | ||
| 392 | pp->value = pp + 1; | ||
| 393 | *prev_pp = pp; | ||
| 394 | prev_pp = &pp->next; | ||
| 395 | memcpy(pp->value, ps, sz - 1); | ||
| 396 | ((char *)pp->value)[sz - 1] = 0; | ||
| 397 | DBG("fixed up name for %s -> %s\n", pathp, | ||
| 398 | (char *)pp->value); | ||
| 399 | } | ||
| 400 | } | ||
| 401 | if (allnextpp) { | ||
| 402 | *prev_pp = NULL; | ||
| 403 | np->name = of_get_property(np, "name", NULL); | ||
| 404 | np->type = of_get_property(np, "device_type", NULL); | ||
| 405 | |||
| 406 | if (!np->name) | ||
| 407 | np->name = "<NULL>"; | ||
| 408 | if (!np->type) | ||
| 409 | np->type = "<NULL>"; | ||
| 410 | } | ||
| 411 | while (tag == OF_DT_BEGIN_NODE) { | ||
| 412 | mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize); | ||
| 413 | tag = *((u32 *)(*p)); | ||
| 414 | } | ||
| 415 | if (tag != OF_DT_END_NODE) { | ||
| 416 | printk("Weird tag at end of node: %x\n", tag); | ||
| 417 | return mem; | ||
| 418 | } | ||
| 419 | *p += 4; | ||
| 420 | return mem; | ||
| 421 | } | ||
| 422 | |||
| 423 | static int __init early_parse_mem(char *p) | 71 | static int __init early_parse_mem(char *p) |
| 424 | { | 72 | { |
| 425 | if (!p) | 73 | if (!p) |
| @@ -446,7 +94,7 @@ static void __init move_device_tree(void) | |||
| 446 | DBG("-> move_device_tree\n"); | 94 | DBG("-> move_device_tree\n"); |
| 447 | 95 | ||
| 448 | start = __pa(initial_boot_params); | 96 | start = __pa(initial_boot_params); |
| 449 | size = initial_boot_params->totalsize; | 97 | size = be32_to_cpu(initial_boot_params->totalsize); |
| 450 | 98 | ||
| 451 | if ((memory_limit && (start + size) > memory_limit) || | 99 | if ((memory_limit && (start + size) > memory_limit) || |
| 452 | overlaps_crashkernel(start, size)) { | 100 | overlaps_crashkernel(start, size)) { |
| @@ -459,54 +107,6 @@ static void __init move_device_tree(void) | |||
| 459 | DBG("<- move_device_tree\n"); | 107 | DBG("<- move_device_tree\n"); |
| 460 | } | 108 | } |
| 461 | 109 | ||
| 462 | /** | ||
| 463 | * unflattens the device-tree passed by the firmware, creating the | ||
| 464 | * tree of struct device_node. It also fills the "name" and "type" | ||
| 465 | * pointers of the nodes so the normal device-tree walking functions | ||
| 466 | * can be used (this used to be done by finish_device_tree) | ||
| 467 | */ | ||
| 468 | void __init unflatten_device_tree(void) | ||
| 469 | { | ||
| 470 | unsigned long start, mem, size; | ||
| 471 | struct device_node **allnextp = &allnodes; | ||
| 472 | |||
| 473 | DBG(" -> unflatten_device_tree()\n"); | ||
| 474 | |||
| 475 | /* First pass, scan for size */ | ||
| 476 | start = ((unsigned long)initial_boot_params) + | ||
| 477 | initial_boot_params->off_dt_struct; | ||
| 478 | size = unflatten_dt_node(0, &start, NULL, NULL, 0); | ||
| 479 | size = (size | 3) + 1; | ||
| 480 | |||
| 481 | DBG(" size is %lx, allocating...\n", size); | ||
| 482 | |||
| 483 | /* Allocate memory for the expanded device tree */ | ||
| 484 | mem = lmb_alloc(size + 4, __alignof__(struct device_node)); | ||
| 485 | mem = (unsigned long) __va(mem); | ||
| 486 | |||
| 487 | ((u32 *)mem)[size / 4] = 0xdeadbeef; | ||
| 488 | |||
| 489 | DBG(" unflattening %lx...\n", mem); | ||
| 490 | |||
| 491 | /* Second pass, do actual unflattening */ | ||
| 492 | start = ((unsigned long)initial_boot_params) + | ||
| 493 | initial_boot_params->off_dt_struct; | ||
| 494 | unflatten_dt_node(mem, &start, NULL, &allnextp, 0); | ||
| 495 | if (*((u32 *)start) != OF_DT_END) | ||
| 496 | printk(KERN_WARNING "Weird tag at end of tree: %08x\n", *((u32 *)start)); | ||
| 497 | if (((u32 *)mem)[size / 4] != 0xdeadbeef) | ||
| 498 | printk(KERN_WARNING "End of tree marker overwritten: %08x\n", | ||
| 499 | ((u32 *)mem)[size / 4] ); | ||
| 500 | *allnextp = NULL; | ||
| 501 | |||
| 502 | /* Get pointer to OF "/chosen" node for use everywhere */ | ||
| 503 | of_chosen = of_find_node_by_path("/chosen"); | ||
| 504 | if (of_chosen == NULL) | ||
| 505 | of_chosen = of_find_node_by_path("/chosen@0"); | ||
| 506 | |||
| 507 | DBG(" <- unflatten_device_tree()\n"); | ||
| 508 | } | ||
| 509 | |||
| 510 | /* | 110 | /* |
| 511 | * ibm,pa-features is a per-cpu property that contains a string of | 111 | * ibm,pa-features is a per-cpu property that contains a string of |
| 512 | * attribute descriptors, each of which has a 2 byte header plus up | 112 | * attribute descriptors, each of which has a 2 byte header plus up |
| @@ -763,48 +363,9 @@ static int __init early_init_dt_scan_cpus(unsigned long node, | |||
| 763 | return 0; | 363 | return 0; |
| 764 | } | 364 | } |
| 765 | 365 | ||
| 766 | #ifdef CONFIG_BLK_DEV_INITRD | 366 | void __init early_init_dt_scan_chosen_arch(unsigned long node) |
| 767 | static void __init early_init_dt_check_for_initrd(unsigned long node) | ||
| 768 | { | ||
| 769 | unsigned long l; | ||
| 770 | u32 *prop; | ||
| 771 | |||
| 772 | DBG("Looking for initrd properties... "); | ||
| 773 | |||
| 774 | prop = of_get_flat_dt_prop(node, "linux,initrd-start", &l); | ||
| 775 | if (prop) { | ||
| 776 | initrd_start = (unsigned long)__va(of_read_ulong(prop, l/4)); | ||
| 777 | |||
| 778 | prop = of_get_flat_dt_prop(node, "linux,initrd-end", &l); | ||
| 779 | if (prop) { | ||
| 780 | initrd_end = (unsigned long) | ||
| 781 | __va(of_read_ulong(prop, l/4)); | ||
| 782 | initrd_below_start_ok = 1; | ||
| 783 | } else { | ||
| 784 | initrd_start = 0; | ||
| 785 | } | ||
| 786 | } | ||
| 787 | |||
| 788 | DBG("initrd_start=0x%lx initrd_end=0x%lx\n", initrd_start, initrd_end); | ||
| 789 | } | ||
| 790 | #else | ||
| 791 | static inline void early_init_dt_check_for_initrd(unsigned long node) | ||
| 792 | { | ||
| 793 | } | ||
| 794 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
| 795 | |||
| 796 | static int __init early_init_dt_scan_chosen(unsigned long node, | ||
| 797 | const char *uname, int depth, void *data) | ||
| 798 | { | 367 | { |
| 799 | unsigned long *lprop; | 368 | unsigned long *lprop; |
| 800 | unsigned long l; | ||
| 801 | char *p; | ||
| 802 | |||
| 803 | DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname); | ||
| 804 | |||
| 805 | if (depth != 1 || | ||
| 806 | (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) | ||
| 807 | return 0; | ||
| 808 | 369 | ||
| 809 | #ifdef CONFIG_PPC64 | 370 | #ifdef CONFIG_PPC64 |
| 810 | /* check if iommu is forced on or off */ | 371 | /* check if iommu is forced on or off */ |
| @@ -815,17 +376,17 @@ static int __init early_init_dt_scan_chosen(unsigned long node, | |||
| 815 | #endif | 376 | #endif |
| 816 | 377 | ||
| 817 | /* mem=x on the command line is the preferred mechanism */ | 378 | /* mem=x on the command line is the preferred mechanism */ |
| 818 | lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL); | 379 | lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL); |
| 819 | if (lprop) | 380 | if (lprop) |
| 820 | memory_limit = *lprop; | 381 | memory_limit = *lprop; |
| 821 | 382 | ||
| 822 | #ifdef CONFIG_PPC64 | 383 | #ifdef CONFIG_PPC64 |
| 823 | lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-start", NULL); | 384 | lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-start", NULL); |
| 824 | if (lprop) | 385 | if (lprop) |
| 825 | tce_alloc_start = *lprop; | 386 | tce_alloc_start = *lprop; |
| 826 | lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-end", NULL); | 387 | lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-end", NULL); |
| 827 | if (lprop) | 388 | if (lprop) |
| 828 | tce_alloc_end = *lprop; | 389 | tce_alloc_end = *lprop; |
| 829 | #endif | 390 | #endif |
| 830 | 391 | ||
| 831 | #ifdef CONFIG_KEXEC | 392 | #ifdef CONFIG_KEXEC |
| @@ -837,51 +398,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node, | |||
| 837 | if (lprop) | 398 | if (lprop) |
| 838 | crashk_res.end = crashk_res.start + *lprop - 1; | 399 | crashk_res.end = crashk_res.start + *lprop - 1; |
| 839 | #endif | 400 | #endif |
| 840 | |||
| 841 | early_init_dt_check_for_initrd(node); | ||
| 842 | |||
| 843 | /* Retreive command line */ | ||
| 844 | p = of_get_flat_dt_prop(node, "bootargs", &l); | ||
| 845 | if (p != NULL && l > 0) | ||
| 846 | strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE)); | ||
| 847 | |||
| 848 | #ifdef CONFIG_CMDLINE | ||
| 849 | if (p == NULL || l == 0 || (l == 1 && (*p) == 0)) | ||
| 850 | strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); | ||
| 851 | #endif /* CONFIG_CMDLINE */ | ||
| 852 | |||
| 853 | DBG("Command line is: %s\n", cmd_line); | ||
| 854 | |||
| 855 | /* break now */ | ||
| 856 | return 1; | ||
| 857 | } | ||
| 858 | |||
| 859 | static int __init early_init_dt_scan_root(unsigned long node, | ||
| 860 | const char *uname, int depth, void *data) | ||
| 861 | { | ||
| 862 | u32 *prop; | ||
| 863 | |||
| 864 | if (depth != 0) | ||
| 865 | return 0; | ||
| 866 | |||
| 867 | prop = of_get_flat_dt_prop(node, "#size-cells", NULL); | ||
| 868 | dt_root_size_cells = (prop == NULL) ? 1 : *prop; | ||
| 869 | DBG("dt_root_size_cells = %x\n", dt_root_size_cells); | ||
| 870 | |||
| 871 | prop = of_get_flat_dt_prop(node, "#address-cells", NULL); | ||
| 872 | dt_root_addr_cells = (prop == NULL) ? 2 : *prop; | ||
| 873 | DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells); | ||
| 874 | |||
| 875 | /* break now */ | ||
| 876 | return 1; | ||
| 877 | } | ||
| 878 | |||
| 879 | static u64 __init dt_mem_next_cell(int s, cell_t **cellp) | ||
| 880 | { | ||
| 881 | cell_t *p = *cellp; | ||
| 882 | |||
| 883 | *cellp = p + s; | ||
| 884 | return of_read_number(p, s); | ||
| 885 | } | 401 | } |
| 886 | 402 | ||
| 887 | #ifdef CONFIG_PPC_PSERIES | 403 | #ifdef CONFIG_PPC_PSERIES |
| @@ -893,22 +409,22 @@ static u64 __init dt_mem_next_cell(int s, cell_t **cellp) | |||
| 893 | */ | 409 | */ |
| 894 | static int __init early_init_dt_scan_drconf_memory(unsigned long node) | 410 | static int __init early_init_dt_scan_drconf_memory(unsigned long node) |
| 895 | { | 411 | { |
| 896 | cell_t *dm, *ls, *usm; | 412 | __be32 *dm, *ls, *usm; |
| 897 | unsigned long l, n, flags; | 413 | unsigned long l, n, flags; |
| 898 | u64 base, size, lmb_size; | 414 | u64 base, size, lmb_size; |
| 899 | unsigned int is_kexec_kdump = 0, rngs; | 415 | unsigned int is_kexec_kdump = 0, rngs; |
| 900 | 416 | ||
| 901 | ls = of_get_flat_dt_prop(node, "ibm,lmb-size", &l); | 417 | ls = of_get_flat_dt_prop(node, "ibm,lmb-size", &l); |
| 902 | if (ls == NULL || l < dt_root_size_cells * sizeof(cell_t)) | 418 | if (ls == NULL || l < dt_root_size_cells * sizeof(__be32)) |
| 903 | return 0; | 419 | return 0; |
| 904 | lmb_size = dt_mem_next_cell(dt_root_size_cells, &ls); | 420 | lmb_size = dt_mem_next_cell(dt_root_size_cells, &ls); |
| 905 | 421 | ||
| 906 | dm = of_get_flat_dt_prop(node, "ibm,dynamic-memory", &l); | 422 | dm = of_get_flat_dt_prop(node, "ibm,dynamic-memory", &l); |
| 907 | if (dm == NULL || l < sizeof(cell_t)) | 423 | if (dm == NULL || l < sizeof(__be32)) |
| 908 | return 0; | 424 | return 0; |
| 909 | 425 | ||
| 910 | n = *dm++; /* number of entries */ | 426 | n = *dm++; /* number of entries */ |
| 911 | if (l < (n * (dt_root_addr_cells + 4) + 1) * sizeof(cell_t)) | 427 | if (l < (n * (dt_root_addr_cells + 4) + 1) * sizeof(__be32)) |
| 912 | return 0; | 428 | return 0; |
| 913 | 429 | ||
| 914 | /* check if this is a kexec/kdump kernel. */ | 430 | /* check if this is a kexec/kdump kernel. */ |
| @@ -963,65 +479,47 @@ static int __init early_init_dt_scan_drconf_memory(unsigned long node) | |||
| 963 | #define early_init_dt_scan_drconf_memory(node) 0 | 479 | #define early_init_dt_scan_drconf_memory(node) 0 |
| 964 | #endif /* CONFIG_PPC_PSERIES */ | 480 | #endif /* CONFIG_PPC_PSERIES */ |
| 965 | 481 | ||
| 966 | static int __init early_init_dt_scan_memory(unsigned long node, | 482 | static int __init early_init_dt_scan_memory_ppc(unsigned long node, |
| 967 | const char *uname, int depth, void *data) | 483 | const char *uname, |
| 484 | int depth, void *data) | ||
| 968 | { | 485 | { |
| 969 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); | ||
| 970 | cell_t *reg, *endp; | ||
| 971 | unsigned long l; | ||
| 972 | |||
| 973 | /* Look for the ibm,dynamic-reconfiguration-memory node */ | ||
| 974 | if (depth == 1 && | 486 | if (depth == 1 && |
| 975 | strcmp(uname, "ibm,dynamic-reconfiguration-memory") == 0) | 487 | strcmp(uname, "ibm,dynamic-reconfiguration-memory") == 0) |
| 976 | return early_init_dt_scan_drconf_memory(node); | 488 | return early_init_dt_scan_drconf_memory(node); |
| 489 | |||
| 490 | return early_init_dt_scan_memory(node, uname, depth, data); | ||
| 491 | } | ||
| 977 | 492 | ||
| 978 | /* We are scanning "memory" nodes only */ | 493 | void __init early_init_dt_add_memory_arch(u64 base, u64 size) |
| 979 | if (type == NULL) { | 494 | { |
| 980 | /* | 495 | #if defined(CONFIG_PPC64) |
| 981 | * The longtrail doesn't have a device_type on the | 496 | if (iommu_is_off) { |
| 982 | * /memory node, so look for the node called /memory@0. | 497 | if (base >= 0x80000000ul) |
| 983 | */ | 498 | return; |
| 984 | if (depth != 1 || strcmp(uname, "memory@0") != 0) | 499 | if ((base + size) > 0x80000000ul) |
| 985 | return 0; | 500 | size = 0x80000000ul - base; |
| 986 | } else if (strcmp(type, "memory") != 0) | 501 | } |
| 987 | return 0; | 502 | #endif |
| 988 | |||
| 989 | reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l); | ||
| 990 | if (reg == NULL) | ||
| 991 | reg = of_get_flat_dt_prop(node, "reg", &l); | ||
| 992 | if (reg == NULL) | ||
| 993 | return 0; | ||
| 994 | |||
| 995 | endp = reg + (l / sizeof(cell_t)); | ||
| 996 | |||
| 997 | DBG("memory scan node %s, reg size %ld, data: %x %x %x %x,\n", | ||
| 998 | uname, l, reg[0], reg[1], reg[2], reg[3]); | ||
| 999 | |||
| 1000 | while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) { | ||
| 1001 | u64 base, size; | ||
| 1002 | 503 | ||
| 1003 | base = dt_mem_next_cell(dt_root_addr_cells, ®); | 504 | lmb_add(base, size); |
| 1004 | size = dt_mem_next_cell(dt_root_size_cells, ®); | ||
| 1005 | 505 | ||
| 1006 | if (size == 0) | 506 | memstart_addr = min((u64)memstart_addr, base); |
| 1007 | continue; | 507 | } |
| 1008 | DBG(" - %llx , %llx\n", (unsigned long long)base, | ||
| 1009 | (unsigned long long)size); | ||
| 1010 | #ifdef CONFIG_PPC64 | ||
| 1011 | if (iommu_is_off) { | ||
| 1012 | if (base >= 0x80000000ul) | ||
| 1013 | continue; | ||
| 1014 | if ((base + size) > 0x80000000ul) | ||
| 1015 | size = 0x80000000ul - base; | ||
| 1016 | } | ||
| 1017 | #endif | ||
| 1018 | lmb_add(base, size); | ||
| 1019 | 508 | ||
| 1020 | memstart_addr = min((u64)memstart_addr, base); | 509 | u64 __init early_init_dt_alloc_memory_arch(u64 size, u64 align) |
| 1021 | } | 510 | { |
| 511 | return lmb_alloc(size, align); | ||
| 512 | } | ||
| 1022 | 513 | ||
| 1023 | return 0; | 514 | #ifdef CONFIG_BLK_DEV_INITRD |
| 515 | void __init early_init_dt_setup_initrd_arch(unsigned long start, | ||
| 516 | unsigned long end) | ||
| 517 | { | ||
| 518 | initrd_start = (unsigned long)__va(start); | ||
| 519 | initrd_end = (unsigned long)__va(end); | ||
| 520 | initrd_below_start_ok = 1; | ||
| 1024 | } | 521 | } |
| 522 | #endif | ||
| 1025 | 523 | ||
| 1026 | static void __init early_reserve_mem(void) | 524 | static void __init early_reserve_mem(void) |
| 1027 | { | 525 | { |
| @@ -1186,7 +684,7 @@ void __init early_init_devtree(void *params) | |||
| 1186 | /* Scan memory nodes and rebuild LMBs */ | 684 | /* Scan memory nodes and rebuild LMBs */ |
| 1187 | lmb_init(); | 685 | lmb_init(); |
| 1188 | of_scan_flat_dt(early_init_dt_scan_root, NULL); | 686 | of_scan_flat_dt(early_init_dt_scan_root, NULL); |
| 1189 | of_scan_flat_dt(early_init_dt_scan_memory, NULL); | 687 | of_scan_flat_dt(early_init_dt_scan_memory_ppc, NULL); |
| 1190 | 688 | ||
| 1191 | /* Save command line for /proc/cmdline and then parse parameters */ | 689 | /* Save command line for /proc/cmdline and then parse parameters */ |
| 1192 | strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE); | 690 | strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE); |
| @@ -1224,6 +722,8 @@ void __init early_init_devtree(void *params) | |||
| 1224 | * FIXME .. and the initrd too? */ | 722 | * FIXME .. and the initrd too? */ |
| 1225 | move_device_tree(); | 723 | move_device_tree(); |
| 1226 | 724 | ||
| 725 | allocate_pacas(); | ||
| 726 | |||
| 1227 | DBG("Scanning CPUs ...\n"); | 727 | DBG("Scanning CPUs ...\n"); |
| 1228 | 728 | ||
| 1229 | /* Retreive CPU related informations from the flat tree | 729 | /* Retreive CPU related informations from the flat tree |
| @@ -1234,25 +734,6 @@ void __init early_init_devtree(void *params) | |||
| 1234 | DBG(" <- early_init_devtree()\n"); | 734 | DBG(" <- early_init_devtree()\n"); |
| 1235 | } | 735 | } |
| 1236 | 736 | ||
| 1237 | |||
| 1238 | /** | ||
| 1239 | * Indicates whether the root node has a given value in its | ||
| 1240 | * compatible property. | ||
| 1241 | */ | ||
| 1242 | int machine_is_compatible(const char *compat) | ||
| 1243 | { | ||
| 1244 | struct device_node *root; | ||
| 1245 | int rc = 0; | ||
| 1246 | |||
| 1247 | root = of_find_node_by_path("/"); | ||
| 1248 | if (root) { | ||
| 1249 | rc = of_device_is_compatible(root, compat); | ||
| 1250 | of_node_put(root); | ||
| 1251 | } | ||
| 1252 | return rc; | ||
| 1253 | } | ||
| 1254 | EXPORT_SYMBOL(machine_is_compatible); | ||
| 1255 | |||
| 1256 | /******* | 737 | /******* |
| 1257 | * | 738 | * |
| 1258 | * New implementation of the OF "find" APIs, return a refcounted | 739 | * New implementation of the OF "find" APIs, return a refcounted |
| @@ -1265,27 +746,6 @@ EXPORT_SYMBOL(machine_is_compatible); | |||
| 1265 | *******/ | 746 | *******/ |
| 1266 | 747 | ||
| 1267 | /** | 748 | /** |
| 1268 | * of_find_node_by_phandle - Find a node given a phandle | ||
| 1269 | * @handle: phandle of the node to find | ||
| 1270 | * | ||
| 1271 | * Returns a node pointer with refcount incremented, use | ||
| 1272 | * of_node_put() on it when done. | ||
| 1273 | */ | ||
| 1274 | struct device_node *of_find_node_by_phandle(phandle handle) | ||
| 1275 | { | ||
| 1276 | struct device_node *np; | ||
| 1277 | |||
| 1278 | read_lock(&devtree_lock); | ||
| 1279 | for (np = allnodes; np != 0; np = np->allnext) | ||
| 1280 | if (np->linux_phandle == handle) | ||
| 1281 | break; | ||
| 1282 | of_node_get(np); | ||
| 1283 | read_unlock(&devtree_lock); | ||
| 1284 | return np; | ||
| 1285 | } | ||
| 1286 | EXPORT_SYMBOL(of_find_node_by_phandle); | ||
| 1287 | |||
| 1288 | /** | ||
| 1289 | * of_find_next_cache_node - Find a node's subsidiary cache | 749 | * of_find_next_cache_node - Find a node's subsidiary cache |
| 1290 | * @np: node of type "cpu" or "cache" | 750 | * @np: node of type "cpu" or "cache" |
| 1291 | * | 751 | * |
| @@ -1316,161 +776,6 @@ struct device_node *of_find_next_cache_node(struct device_node *np) | |||
| 1316 | return NULL; | 776 | return NULL; |
| 1317 | } | 777 | } |
| 1318 | 778 | ||
| 1319 | /** | ||
| 1320 | * of_find_all_nodes - Get next node in global list | ||
| 1321 | * @prev: Previous node or NULL to start iteration | ||
| 1322 | * of_node_put() will be called on it | ||
| 1323 | * | ||
| 1324 | * Returns a node pointer with refcount incremented, use | ||
| 1325 | * of_node_put() on it when done. | ||
| 1326 | */ | ||
| 1327 | struct device_node *of_find_all_nodes(struct device_node *prev) | ||
| 1328 | { | ||
| 1329 | struct device_node *np; | ||
| 1330 | |||
| 1331 | read_lock(&devtree_lock); | ||
| 1332 | np = prev ? prev->allnext : allnodes; | ||
| 1333 | for (; np != 0; np = np->allnext) | ||
| 1334 | if (of_node_get(np)) | ||
| 1335 | break; | ||
| 1336 | of_node_put(prev); | ||
| 1337 | read_unlock(&devtree_lock); | ||
| 1338 | return np; | ||
| 1339 | } | ||
| 1340 | EXPORT_SYMBOL(of_find_all_nodes); | ||
| 1341 | |||
| 1342 | /** | ||
| 1343 | * of_node_get - Increment refcount of a node | ||
| 1344 | * @node: Node to inc refcount, NULL is supported to | ||
| 1345 | * simplify writing of callers | ||
| 1346 | * | ||
| 1347 | * Returns node. | ||
| 1348 | */ | ||
| 1349 | struct device_node *of_node_get(struct device_node *node) | ||
| 1350 | { | ||
| 1351 | if (node) | ||
| 1352 | kref_get(&node->kref); | ||
| 1353 | return node; | ||
| 1354 | } | ||
| 1355 | EXPORT_SYMBOL(of_node_get); | ||
| 1356 | |||
| 1357 | static inline struct device_node * kref_to_device_node(struct kref *kref) | ||
| 1358 | { | ||
| 1359 | return container_of(kref, struct device_node, kref); | ||
| 1360 | } | ||
| 1361 | |||
| 1362 | /** | ||
| 1363 | * of_node_release - release a dynamically allocated node | ||
| 1364 | * @kref: kref element of the node to be released | ||
| 1365 | * | ||
| 1366 | * In of_node_put() this function is passed to kref_put() | ||
| 1367 | * as the destructor. | ||
| 1368 | */ | ||
| 1369 | static void of_node_release(struct kref *kref) | ||
| 1370 | { | ||
| 1371 | struct device_node *node = kref_to_device_node(kref); | ||
| 1372 | struct property *prop = node->properties; | ||
| 1373 | |||
| 1374 | /* We should never be releasing nodes that haven't been detached. */ | ||
| 1375 | if (!of_node_check_flag(node, OF_DETACHED)) { | ||
| 1376 | printk("WARNING: Bad of_node_put() on %s\n", node->full_name); | ||
| 1377 | dump_stack(); | ||
| 1378 | kref_init(&node->kref); | ||
| 1379 | return; | ||
| 1380 | } | ||
| 1381 | |||
| 1382 | if (!of_node_check_flag(node, OF_DYNAMIC)) | ||
| 1383 | return; | ||
| 1384 | |||
| 1385 | while (prop) { | ||
| 1386 | struct property *next = prop->next; | ||
| 1387 | kfree(prop->name); | ||
| 1388 | kfree(prop->value); | ||
| 1389 | kfree(prop); | ||
| 1390 | prop = next; | ||
| 1391 | |||
| 1392 | if (!prop) { | ||
| 1393 | prop = node->deadprops; | ||
| 1394 | node->deadprops = NULL; | ||
| 1395 | } | ||
| 1396 | } | ||
| 1397 | kfree(node->full_name); | ||
| 1398 | kfree(node->data); | ||
| 1399 | kfree(node); | ||
| 1400 | } | ||
| 1401 | |||
| 1402 | /** | ||
| 1403 | * of_node_put - Decrement refcount of a node | ||
| 1404 | * @node: Node to dec refcount, NULL is supported to | ||
| 1405 | * simplify writing of callers | ||
| 1406 | * | ||
| 1407 | */ | ||
| 1408 | void of_node_put(struct device_node *node) | ||
| 1409 | { | ||
| 1410 | if (node) | ||
| 1411 | kref_put(&node->kref, of_node_release); | ||
| 1412 | } | ||
| 1413 | EXPORT_SYMBOL(of_node_put); | ||
| 1414 | |||
| 1415 | /* | ||
| 1416 | * Plug a device node into the tree and global list. | ||
| 1417 | */ | ||
| 1418 | void of_attach_node(struct device_node *np) | ||
| 1419 | { | ||
| 1420 | unsigned long flags; | ||
| 1421 | |||
| 1422 | write_lock_irqsave(&devtree_lock, flags); | ||
| 1423 | np->sibling = np->parent->child; | ||
| 1424 | np->allnext = allnodes; | ||
| 1425 | np->parent->child = np; | ||
| 1426 | allnodes = np; | ||
| 1427 | write_unlock_irqrestore(&devtree_lock, flags); | ||
| 1428 | } | ||
| 1429 | |||
| 1430 | /* | ||
| 1431 | * "Unplug" a node from the device tree. The caller must hold | ||
| 1432 | * a reference to the node. The memory associated with the node | ||
| 1433 | * is not freed until its refcount goes to zero. | ||
| 1434 | */ | ||
| 1435 | void of_detach_node(struct device_node *np) | ||
| 1436 | { | ||
| 1437 | struct device_node *parent; | ||
| 1438 | unsigned long flags; | ||
| 1439 | |||
| 1440 | write_lock_irqsave(&devtree_lock, flags); | ||
| 1441 | |||
| 1442 | parent = np->parent; | ||
| 1443 | if (!parent) | ||
| 1444 | goto out_unlock; | ||
| 1445 | |||
| 1446 | if (allnodes == np) | ||
| 1447 | allnodes = np->allnext; | ||
| 1448 | else { | ||
| 1449 | struct device_node *prev; | ||
| 1450 | for (prev = allnodes; | ||
| 1451 | prev->allnext != np; | ||
| 1452 | prev = prev->allnext) | ||
| 1453 | ; | ||
| 1454 | prev->allnext = np->allnext; | ||
| 1455 | } | ||
| 1456 | |||
| 1457 | if (parent->child == np) | ||
| 1458 | parent->child = np->sibling; | ||
| 1459 | else { | ||
| 1460 | struct device_node *prevsib; | ||
| 1461 | for (prevsib = np->parent->child; | ||
| 1462 | prevsib->sibling != np; | ||
| 1463 | prevsib = prevsib->sibling) | ||
| 1464 | ; | ||
| 1465 | prevsib->sibling = np->sibling; | ||
| 1466 | } | ||
| 1467 | |||
| 1468 | of_node_set_flag(np, OF_DETACHED); | ||
| 1469 | |||
| 1470 | out_unlock: | ||
| 1471 | write_unlock_irqrestore(&devtree_lock, flags); | ||
| 1472 | } | ||
| 1473 | |||
| 1474 | #ifdef CONFIG_PPC_PSERIES | 779 | #ifdef CONFIG_PPC_PSERIES |
| 1475 | /* | 780 | /* |
| 1476 | * Fix up the uninitialized fields in a new device node: | 781 | * Fix up the uninitialized fields in a new device node: |
| @@ -1502,9 +807,9 @@ static int of_finish_dynamic_node(struct device_node *node) | |||
| 1502 | if (machine_is(powermac)) | 807 | if (machine_is(powermac)) |
| 1503 | return -ENODEV; | 808 | return -ENODEV; |
| 1504 | 809 | ||
| 1505 | /* fix up new node's linux_phandle field */ | 810 | /* fix up new node's phandle field */ |
| 1506 | if ((ibm_phandle = of_get_property(node, "ibm,phandle", NULL))) | 811 | if ((ibm_phandle = of_get_property(node, "ibm,phandle", NULL))) |
| 1507 | node->linux_phandle = *ibm_phandle; | 812 | node->phandle = *ibm_phandle; |
| 1508 | 813 | ||
| 1509 | out: | 814 | out: |
| 1510 | of_node_put(parent); | 815 | of_node_put(parent); |
| @@ -1543,120 +848,6 @@ static int __init prom_reconfig_setup(void) | |||
| 1543 | __initcall(prom_reconfig_setup); | 848 | __initcall(prom_reconfig_setup); |
| 1544 | #endif | 849 | #endif |
| 1545 | 850 | ||
| 1546 | /* | ||
| 1547 | * Add a property to a node | ||
| 1548 | */ | ||
| 1549 | int prom_add_property(struct device_node* np, struct property* prop) | ||
| 1550 | { | ||
| 1551 | struct property **next; | ||
| 1552 | unsigned long flags; | ||
| 1553 | |||
| 1554 | prop->next = NULL; | ||
| 1555 | write_lock_irqsave(&devtree_lock, flags); | ||
| 1556 | next = &np->properties; | ||
| 1557 | while (*next) { | ||
| 1558 | if (strcmp(prop->name, (*next)->name) == 0) { | ||
| 1559 | /* duplicate ! don't insert it */ | ||
| 1560 | write_unlock_irqrestore(&devtree_lock, flags); | ||
| 1561 | return -1; | ||
| 1562 | } | ||
| 1563 | next = &(*next)->next; | ||
| 1564 | } | ||
| 1565 | *next = prop; | ||
| 1566 | write_unlock_irqrestore(&devtree_lock, flags); | ||
| 1567 | |||
| 1568 | #ifdef CONFIG_PROC_DEVICETREE | ||
| 1569 | /* try to add to proc as well if it was initialized */ | ||
| 1570 | if (np->pde) | ||
| 1571 | proc_device_tree_add_prop(np->pde, prop); | ||
| 1572 | #endif /* CONFIG_PROC_DEVICETREE */ | ||
| 1573 | |||
| 1574 | return 0; | ||
| 1575 | } | ||
| 1576 | |||
| 1577 | /* | ||
| 1578 | * Remove a property from a node. Note that we don't actually | ||
| 1579 | * remove it, since we have given out who-knows-how-many pointers | ||
| 1580 | * to the data using get-property. Instead we just move the property | ||
| 1581 | * to the "dead properties" list, so it won't be found any more. | ||
| 1582 | */ | ||
| 1583 | int prom_remove_property(struct device_node *np, struct property *prop) | ||
| 1584 | { | ||
| 1585 | struct property **next; | ||
| 1586 | unsigned long flags; | ||
| 1587 | int found = 0; | ||
| 1588 | |||
| 1589 | write_lock_irqsave(&devtree_lock, flags); | ||
| 1590 | next = &np->properties; | ||
| 1591 | while (*next) { | ||
| 1592 | if (*next == prop) { | ||
| 1593 | /* found the node */ | ||
| 1594 | *next = prop->next; | ||
| 1595 | prop->next = np->deadprops; | ||
| 1596 | np->deadprops = prop; | ||
| 1597 | found = 1; | ||
| 1598 | break; | ||
| 1599 | } | ||
| 1600 | next = &(*next)->next; | ||
| 1601 | } | ||
| 1602 | write_unlock_irqrestore(&devtree_lock, flags); | ||
| 1603 | |||
| 1604 | if (!found) | ||
| 1605 | return -ENODEV; | ||
| 1606 | |||
| 1607 | #ifdef CONFIG_PROC_DEVICETREE | ||
| 1608 | /* try to remove the proc node as well */ | ||
| 1609 | if (np->pde) | ||
| 1610 | proc_device_tree_remove_prop(np->pde, prop); | ||
| 1611 | #endif /* CONFIG_PROC_DEVICETREE */ | ||
| 1612 | |||
| 1613 | return 0; | ||
| 1614 | } | ||
| 1615 | |||
| 1616 | /* | ||
| 1617 | * Update a property in a node. Note that we don't actually | ||
| 1618 | * remove it, since we have given out who-knows-how-many pointers | ||
| 1619 | * to the data using get-property. Instead we just move the property | ||
| 1620 | * to the "dead properties" list, and add the new property to the | ||
| 1621 | * property list | ||
| 1622 | */ | ||
| 1623 | int prom_update_property(struct device_node *np, | ||
| 1624 | struct property *newprop, | ||
| 1625 | struct property *oldprop) | ||
| 1626 | { | ||
| 1627 | struct property **next; | ||
| 1628 | unsigned long flags; | ||
| 1629 | int found = 0; | ||
| 1630 | |||
| 1631 | write_lock_irqsave(&devtree_lock, flags); | ||
| 1632 | next = &np->properties; | ||
| 1633 | while (*next) { | ||
| 1634 | if (*next == oldprop) { | ||
| 1635 | /* found the node */ | ||
| 1636 | newprop->next = oldprop->next; | ||
| 1637 | *next = newprop; | ||
| 1638 | oldprop->next = np->deadprops; | ||
| 1639 | np->deadprops = oldprop; | ||
| 1640 | found = 1; | ||
| 1641 | break; | ||
| 1642 | } | ||
| 1643 | next = &(*next)->next; | ||
| 1644 | } | ||
| 1645 | write_unlock_irqrestore(&devtree_lock, flags); | ||
| 1646 | |||
| 1647 | if (!found) | ||
| 1648 | return -ENODEV; | ||
| 1649 | |||
| 1650 | #ifdef CONFIG_PROC_DEVICETREE | ||
| 1651 | /* try to add to proc as well if it was initialized */ | ||
| 1652 | if (np->pde) | ||
| 1653 | proc_device_tree_update_prop(np->pde, newprop, oldprop); | ||
| 1654 | #endif /* CONFIG_PROC_DEVICETREE */ | ||
| 1655 | |||
| 1656 | return 0; | ||
| 1657 | } | ||
| 1658 | |||
| 1659 | |||
| 1660 | /* Find the device node for a given logical cpu number, also returns the cpu | 851 | /* Find the device node for a given logical cpu number, also returns the cpu |
| 1661 | * local thread number (index in ibm,interrupt-server#s) if relevant and | 852 | * local thread number (index in ibm,interrupt-server#s) if relevant and |
| 1662 | * asked for (non NULL) | 853 | * asked for (non NULL) |
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index bafac2e41ae1..97d4bd9442d3 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
| @@ -653,6 +653,10 @@ static void __init early_cmdline_parse(void) | |||
| 653 | #else | 653 | #else |
| 654 | #define OV5_CMO 0x00 | 654 | #define OV5_CMO 0x00 |
| 655 | #endif | 655 | #endif |
| 656 | #define OV5_TYPE1_AFFINITY 0x80 /* Type 1 NUMA affinity */ | ||
| 657 | |||
| 658 | /* Option Vector 6: IBM PAPR hints */ | ||
| 659 | #define OV6_LINUX 0x02 /* Linux is our OS */ | ||
| 656 | 660 | ||
| 657 | /* | 661 | /* |
| 658 | * The architecture vector has an array of PVR mask/value pairs, | 662 | * The architecture vector has an array of PVR mask/value pairs, |
| @@ -665,7 +669,7 @@ static unsigned char ibm_architecture_vec[] = { | |||
| 665 | W(0xffffffff), W(0x0f000003), /* all 2.06-compliant */ | 669 | W(0xffffffff), W(0x0f000003), /* all 2.06-compliant */ |
| 666 | W(0xffffffff), W(0x0f000002), /* all 2.05-compliant */ | 670 | W(0xffffffff), W(0x0f000002), /* all 2.05-compliant */ |
| 667 | W(0xfffffffe), W(0x0f000001), /* all 2.04-compliant and earlier */ | 671 | W(0xfffffffe), W(0x0f000001), /* all 2.04-compliant and earlier */ |
| 668 | 5 - 1, /* 5 option vectors */ | 672 | 6 - 1, /* 6 option vectors */ |
| 669 | 673 | ||
| 670 | /* option vector 1: processor architectures supported */ | 674 | /* option vector 1: processor architectures supported */ |
| 671 | 3 - 2, /* length */ | 675 | 3 - 2, /* length */ |
| @@ -697,12 +701,29 @@ static unsigned char ibm_architecture_vec[] = { | |||
| 697 | 0, /* don't halt */ | 701 | 0, /* don't halt */ |
| 698 | 702 | ||
| 699 | /* option vector 5: PAPR/OF options */ | 703 | /* option vector 5: PAPR/OF options */ |
| 700 | 5 - 2, /* length */ | 704 | 13 - 2, /* length */ |
| 701 | 0, /* don't ignore, don't halt */ | 705 | 0, /* don't ignore, don't halt */ |
| 702 | OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY | | 706 | OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY | |
| 703 | OV5_DONATE_DEDICATE_CPU | OV5_MSI, | 707 | OV5_DONATE_DEDICATE_CPU | OV5_MSI, |
| 704 | 0, | 708 | 0, |
| 705 | OV5_CMO, | 709 | OV5_CMO, |
| 710 | OV5_TYPE1_AFFINITY, | ||
| 711 | 0, | ||
| 712 | 0, | ||
| 713 | 0, | ||
| 714 | /* WARNING: The offset of the "number of cores" field below | ||
| 715 | * must match by the macro below. Update the definition if | ||
| 716 | * the structure layout changes. | ||
| 717 | */ | ||
| 718 | #define IBM_ARCH_VEC_NRCORES_OFFSET 100 | ||
| 719 | W(NR_CPUS), /* number of cores supported */ | ||
| 720 | |||
| 721 | /* option vector 6: IBM PAPR hints */ | ||
| 722 | 4 - 2, /* length */ | ||
| 723 | 0, | ||
| 724 | 0, | ||
| 725 | OV6_LINUX, | ||
| 726 | |||
| 706 | }; | 727 | }; |
| 707 | 728 | ||
| 708 | /* Old method - ELF header with PT_NOTE sections */ | 729 | /* Old method - ELF header with PT_NOTE sections */ |
| @@ -792,13 +813,70 @@ static struct fake_elf { | |||
| 792 | } | 813 | } |
| 793 | }; | 814 | }; |
| 794 | 815 | ||
| 816 | static int __init prom_count_smt_threads(void) | ||
| 817 | { | ||
| 818 | phandle node; | ||
| 819 | char type[64]; | ||
| 820 | unsigned int plen; | ||
| 821 | |||
| 822 | /* Pick up th first CPU node we can find */ | ||
| 823 | for (node = 0; prom_next_node(&node); ) { | ||
| 824 | type[0] = 0; | ||
| 825 | prom_getprop(node, "device_type", type, sizeof(type)); | ||
| 826 | |||
| 827 | if (strcmp(type, RELOC("cpu"))) | ||
| 828 | continue; | ||
| 829 | /* | ||
| 830 | * There is an entry for each smt thread, each entry being | ||
| 831 | * 4 bytes long. All cpus should have the same number of | ||
| 832 | * smt threads, so return after finding the first. | ||
| 833 | */ | ||
| 834 | plen = prom_getproplen(node, "ibm,ppc-interrupt-server#s"); | ||
| 835 | if (plen == PROM_ERROR) | ||
| 836 | break; | ||
| 837 | plen >>= 2; | ||
| 838 | prom_debug("Found 0x%x smt threads per core\n", (unsigned long)plen); | ||
| 839 | |||
| 840 | /* Sanity check */ | ||
| 841 | if (plen < 1 || plen > 64) { | ||
| 842 | prom_printf("Threads per core 0x%x out of bounds, assuming 1\n", | ||
| 843 | (unsigned long)plen); | ||
| 844 | return 1; | ||
| 845 | } | ||
| 846 | return plen; | ||
| 847 | } | ||
| 848 | prom_debug("No threads found, assuming 1 per core\n"); | ||
| 849 | |||
| 850 | return 1; | ||
| 851 | |||
| 852 | } | ||
| 853 | |||
| 854 | |||
| 795 | static void __init prom_send_capabilities(void) | 855 | static void __init prom_send_capabilities(void) |
| 796 | { | 856 | { |
| 797 | ihandle elfloader, root; | 857 | ihandle elfloader, root; |
| 798 | prom_arg_t ret; | 858 | prom_arg_t ret; |
| 859 | u32 *cores; | ||
| 799 | 860 | ||
| 800 | root = call_prom("open", 1, 1, ADDR("/")); | 861 | root = call_prom("open", 1, 1, ADDR("/")); |
| 801 | if (root != 0) { | 862 | if (root != 0) { |
| 863 | /* We need to tell the FW about the number of cores we support. | ||
| 864 | * | ||
| 865 | * To do that, we count the number of threads on the first core | ||
| 866 | * (we assume this is the same for all cores) and use it to | ||
| 867 | * divide NR_CPUS. | ||
| 868 | */ | ||
| 869 | cores = (u32 *)PTRRELOC(&ibm_architecture_vec[IBM_ARCH_VEC_NRCORES_OFFSET]); | ||
| 870 | if (*cores != NR_CPUS) { | ||
| 871 | prom_printf("WARNING ! " | ||
| 872 | "ibm_architecture_vec structure inconsistent: 0x%x !\n", | ||
| 873 | *cores); | ||
| 874 | } else { | ||
| 875 | *cores = NR_CPUS / prom_count_smt_threads(); | ||
| 876 | prom_printf("Max number of cores passed to firmware: 0x%x\n", | ||
| 877 | (unsigned long)*cores); | ||
| 878 | } | ||
| 879 | |||
| 802 | /* try calling the ibm,client-architecture-support method */ | 880 | /* try calling the ibm,client-architecture-support method */ |
| 803 | prom_printf("Calling ibm,client-architecture-support..."); | 881 | prom_printf("Calling ibm,client-architecture-support..."); |
| 804 | if (call_prom_ret("call-method", 3, 2, &ret, | 882 | if (call_prom_ret("call-method", 3, 2, &ret, |
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index ef149880c145..ed2cfe17d25e 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c | |||
| @@ -46,7 +46,7 @@ | |||
| 46 | /* | 46 | /* |
| 47 | * Set of msr bits that gdb can change on behalf of a process. | 47 | * Set of msr bits that gdb can change on behalf of a process. |
| 48 | */ | 48 | */ |
| 49 | #if defined(CONFIG_40x) || defined(CONFIG_BOOKE) | 49 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
| 50 | #define MSR_DEBUGCHANGE 0 | 50 | #define MSR_DEBUGCHANGE 0 |
| 51 | #else | 51 | #else |
| 52 | #define MSR_DEBUGCHANGE (MSR_SE | MSR_BE) | 52 | #define MSR_DEBUGCHANGE (MSR_SE | MSR_BE) |
| @@ -703,7 +703,7 @@ void user_enable_single_step(struct task_struct *task) | |||
| 703 | struct pt_regs *regs = task->thread.regs; | 703 | struct pt_regs *regs = task->thread.regs; |
| 704 | 704 | ||
| 705 | if (regs != NULL) { | 705 | if (regs != NULL) { |
| 706 | #if defined(CONFIG_40x) || defined(CONFIG_BOOKE) | 706 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
| 707 | task->thread.dbcr0 &= ~DBCR0_BT; | 707 | task->thread.dbcr0 &= ~DBCR0_BT; |
| 708 | task->thread.dbcr0 |= DBCR0_IDM | DBCR0_IC; | 708 | task->thread.dbcr0 |= DBCR0_IDM | DBCR0_IC; |
| 709 | regs->msr |= MSR_DE; | 709 | regs->msr |= MSR_DE; |
| @@ -720,7 +720,7 @@ void user_enable_block_step(struct task_struct *task) | |||
| 720 | struct pt_regs *regs = task->thread.regs; | 720 | struct pt_regs *regs = task->thread.regs; |
| 721 | 721 | ||
| 722 | if (regs != NULL) { | 722 | if (regs != NULL) { |
| 723 | #if defined(CONFIG_40x) || defined(CONFIG_BOOKE) | 723 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
| 724 | task->thread.dbcr0 &= ~DBCR0_IC; | 724 | task->thread.dbcr0 &= ~DBCR0_IC; |
| 725 | task->thread.dbcr0 = DBCR0_IDM | DBCR0_BT; | 725 | task->thread.dbcr0 = DBCR0_IDM | DBCR0_BT; |
| 726 | regs->msr |= MSR_DE; | 726 | regs->msr |= MSR_DE; |
| @@ -737,17 +737,25 @@ void user_disable_single_step(struct task_struct *task) | |||
| 737 | struct pt_regs *regs = task->thread.regs; | 737 | struct pt_regs *regs = task->thread.regs; |
| 738 | 738 | ||
| 739 | if (regs != NULL) { | 739 | if (regs != NULL) { |
| 740 | #if defined(CONFIG_BOOKE) | 740 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
| 741 | /* If DAC don't clear DBCRO_IDM or MSR_DE */ | 741 | /* |
| 742 | if (task->thread.dabr) | 742 | * The logic to disable single stepping should be as |
| 743 | task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT); | 743 | * simple as turning off the Instruction Complete flag. |
| 744 | else { | 744 | * And, after doing so, if all debug flags are off, turn |
| 745 | task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT | DBCR0_IDM); | 745 | * off DBCR0(IDM) and MSR(DE) .... Torez |
| 746 | */ | ||
| 747 | task->thread.dbcr0 &= ~DBCR0_IC; | ||
| 748 | /* | ||
| 749 | * Test to see if any of the DBCR_ACTIVE_EVENTS bits are set. | ||
| 750 | */ | ||
| 751 | if (!DBCR_ACTIVE_EVENTS(task->thread.dbcr0, | ||
| 752 | task->thread.dbcr1)) { | ||
| 753 | /* | ||
| 754 | * All debug events were off..... | ||
| 755 | */ | ||
| 756 | task->thread.dbcr0 &= ~DBCR0_IDM; | ||
| 746 | regs->msr &= ~MSR_DE; | 757 | regs->msr &= ~MSR_DE; |
| 747 | } | 758 | } |
| 748 | #elif defined(CONFIG_40x) | ||
| 749 | task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT | DBCR0_IDM); | ||
| 750 | regs->msr &= ~MSR_DE; | ||
| 751 | #else | 759 | #else |
| 752 | regs->msr &= ~(MSR_SE | MSR_BE); | 760 | regs->msr &= ~(MSR_SE | MSR_BE); |
| 753 | #endif | 761 | #endif |
| @@ -769,8 +777,7 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, | |||
| 769 | if ((data & ~0x7UL) >= TASK_SIZE) | 777 | if ((data & ~0x7UL) >= TASK_SIZE) |
| 770 | return -EIO; | 778 | return -EIO; |
| 771 | 779 | ||
| 772 | #ifndef CONFIG_BOOKE | 780 | #ifndef CONFIG_PPC_ADV_DEBUG_REGS |
| 773 | |||
| 774 | /* For processors using DABR (i.e. 970), the bottom 3 bits are flags. | 781 | /* For processors using DABR (i.e. 970), the bottom 3 bits are flags. |
| 775 | * It was assumed, on previous implementations, that 3 bits were | 782 | * It was assumed, on previous implementations, that 3 bits were |
| 776 | * passed together with the data address, fitting the design of the | 783 | * passed together with the data address, fitting the design of the |
| @@ -789,21 +796,22 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, | |||
| 789 | 796 | ||
| 790 | /* Move contents to the DABR register */ | 797 | /* Move contents to the DABR register */ |
| 791 | task->thread.dabr = data; | 798 | task->thread.dabr = data; |
| 792 | 799 | #else /* CONFIG_PPC_ADV_DEBUG_REGS */ | |
| 793 | #endif | ||
| 794 | #if defined(CONFIG_BOOKE) | ||
| 795 | |||
| 796 | /* As described above, it was assumed 3 bits were passed with the data | 800 | /* As described above, it was assumed 3 bits were passed with the data |
| 797 | * address, but we will assume only the mode bits will be passed | 801 | * address, but we will assume only the mode bits will be passed |
| 798 | * as to not cause alignment restrictions for DAC-based processors. | 802 | * as to not cause alignment restrictions for DAC-based processors. |
| 799 | */ | 803 | */ |
| 800 | 804 | ||
| 801 | /* DAC's hold the whole address without any mode flags */ | 805 | /* DAC's hold the whole address without any mode flags */ |
| 802 | task->thread.dabr = data & ~0x3UL; | 806 | task->thread.dac1 = data & ~0x3UL; |
| 803 | 807 | ||
| 804 | if (task->thread.dabr == 0) { | 808 | if (task->thread.dac1 == 0) { |
| 805 | task->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W | DBCR0_IDM); | 809 | dbcr_dac(task) &= ~(DBCR_DAC1R | DBCR_DAC1W); |
| 806 | task->thread.regs->msr &= ~MSR_DE; | 810 | if (!DBCR_ACTIVE_EVENTS(task->thread.dbcr0, |
| 811 | task->thread.dbcr1)) { | ||
| 812 | task->thread.regs->msr &= ~MSR_DE; | ||
| 813 | task->thread.dbcr0 &= ~DBCR0_IDM; | ||
| 814 | } | ||
| 807 | return 0; | 815 | return 0; |
| 808 | } | 816 | } |
| 809 | 817 | ||
| @@ -814,17 +822,17 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, | |||
| 814 | 822 | ||
| 815 | /* Set the Internal Debugging flag (IDM bit 1) for the DBCR0 | 823 | /* Set the Internal Debugging flag (IDM bit 1) for the DBCR0 |
| 816 | register */ | 824 | register */ |
| 817 | task->thread.dbcr0 = DBCR0_IDM; | 825 | task->thread.dbcr0 |= DBCR0_IDM; |
| 818 | 826 | ||
| 819 | /* Check for write and read flags and set DBCR0 | 827 | /* Check for write and read flags and set DBCR0 |
| 820 | accordingly */ | 828 | accordingly */ |
| 829 | dbcr_dac(task) &= ~(DBCR_DAC1R|DBCR_DAC1W); | ||
| 821 | if (data & 0x1UL) | 830 | if (data & 0x1UL) |
| 822 | task->thread.dbcr0 |= DBSR_DAC1R; | 831 | dbcr_dac(task) |= DBCR_DAC1R; |
| 823 | if (data & 0x2UL) | 832 | if (data & 0x2UL) |
| 824 | task->thread.dbcr0 |= DBSR_DAC1W; | 833 | dbcr_dac(task) |= DBCR_DAC1W; |
| 825 | |||
| 826 | task->thread.regs->msr |= MSR_DE; | 834 | task->thread.regs->msr |= MSR_DE; |
| 827 | #endif | 835 | #endif /* CONFIG_PPC_ADV_DEBUG_REGS */ |
| 828 | return 0; | 836 | return 0; |
| 829 | } | 837 | } |
| 830 | 838 | ||
| @@ -839,6 +847,394 @@ void ptrace_disable(struct task_struct *child) | |||
| 839 | user_disable_single_step(child); | 847 | user_disable_single_step(child); |
| 840 | } | 848 | } |
| 841 | 849 | ||
| 850 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | ||
| 851 | static long set_intruction_bp(struct task_struct *child, | ||
| 852 | struct ppc_hw_breakpoint *bp_info) | ||
| 853 | { | ||
| 854 | int slot; | ||
| 855 | int slot1_in_use = ((child->thread.dbcr0 & DBCR0_IAC1) != 0); | ||
| 856 | int slot2_in_use = ((child->thread.dbcr0 & DBCR0_IAC2) != 0); | ||
| 857 | int slot3_in_use = ((child->thread.dbcr0 & DBCR0_IAC3) != 0); | ||
| 858 | int slot4_in_use = ((child->thread.dbcr0 & DBCR0_IAC4) != 0); | ||
| 859 | |||
| 860 | if (dbcr_iac_range(child) & DBCR_IAC12MODE) | ||
| 861 | slot2_in_use = 1; | ||
| 862 | if (dbcr_iac_range(child) & DBCR_IAC34MODE) | ||
| 863 | slot4_in_use = 1; | ||
| 864 | |||
| 865 | if (bp_info->addr >= TASK_SIZE) | ||
| 866 | return -EIO; | ||
| 867 | |||
| 868 | if (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT) { | ||
| 869 | |||
| 870 | /* Make sure range is valid. */ | ||
| 871 | if (bp_info->addr2 >= TASK_SIZE) | ||
| 872 | return -EIO; | ||
| 873 | |||
| 874 | /* We need a pair of IAC regsisters */ | ||
| 875 | if ((!slot1_in_use) && (!slot2_in_use)) { | ||
| 876 | slot = 1; | ||
| 877 | child->thread.iac1 = bp_info->addr; | ||
| 878 | child->thread.iac2 = bp_info->addr2; | ||
| 879 | child->thread.dbcr0 |= DBCR0_IAC1; | ||
| 880 | if (bp_info->addr_mode == | ||
| 881 | PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE) | ||
| 882 | dbcr_iac_range(child) |= DBCR_IAC12X; | ||
| 883 | else | ||
| 884 | dbcr_iac_range(child) |= DBCR_IAC12I; | ||
| 885 | #if CONFIG_PPC_ADV_DEBUG_IACS > 2 | ||
| 886 | } else if ((!slot3_in_use) && (!slot4_in_use)) { | ||
| 887 | slot = 3; | ||
| 888 | child->thread.iac3 = bp_info->addr; | ||
| 889 | child->thread.iac4 = bp_info->addr2; | ||
| 890 | child->thread.dbcr0 |= DBCR0_IAC3; | ||
| 891 | if (bp_info->addr_mode == | ||
| 892 | PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE) | ||
| 893 | dbcr_iac_range(child) |= DBCR_IAC34X; | ||
| 894 | else | ||
| 895 | dbcr_iac_range(child) |= DBCR_IAC34I; | ||
| 896 | #endif | ||
| 897 | } else | ||
| 898 | return -ENOSPC; | ||
| 899 | } else { | ||
| 900 | /* We only need one. If possible leave a pair free in | ||
| 901 | * case a range is needed later | ||
| 902 | */ | ||
| 903 | if (!slot1_in_use) { | ||
| 904 | /* | ||
| 905 | * Don't use iac1 if iac1-iac2 are free and either | ||
| 906 | * iac3 or iac4 (but not both) are free | ||
| 907 | */ | ||
| 908 | if (slot2_in_use || (slot3_in_use == slot4_in_use)) { | ||
| 909 | slot = 1; | ||
| 910 | child->thread.iac1 = bp_info->addr; | ||
| 911 | child->thread.dbcr0 |= DBCR0_IAC1; | ||
| 912 | goto out; | ||
| 913 | } | ||
| 914 | } | ||
| 915 | if (!slot2_in_use) { | ||
| 916 | slot = 2; | ||
| 917 | child->thread.iac2 = bp_info->addr; | ||
| 918 | child->thread.dbcr0 |= DBCR0_IAC2; | ||
| 919 | #if CONFIG_PPC_ADV_DEBUG_IACS > 2 | ||
| 920 | } else if (!slot3_in_use) { | ||
| 921 | slot = 3; | ||
| 922 | child->thread.iac3 = bp_info->addr; | ||
| 923 | child->thread.dbcr0 |= DBCR0_IAC3; | ||
| 924 | } else if (!slot4_in_use) { | ||
| 925 | slot = 4; | ||
| 926 | child->thread.iac4 = bp_info->addr; | ||
| 927 | child->thread.dbcr0 |= DBCR0_IAC4; | ||
| 928 | #endif | ||
| 929 | } else | ||
| 930 | return -ENOSPC; | ||
| 931 | } | ||
| 932 | out: | ||
| 933 | child->thread.dbcr0 |= DBCR0_IDM; | ||
| 934 | child->thread.regs->msr |= MSR_DE; | ||
| 935 | |||
| 936 | return slot; | ||
| 937 | } | ||
| 938 | |||
| 939 | static int del_instruction_bp(struct task_struct *child, int slot) | ||
| 940 | { | ||
| 941 | switch (slot) { | ||
| 942 | case 1: | ||
| 943 | if ((child->thread.dbcr0 & DBCR0_IAC1) == 0) | ||
| 944 | return -ENOENT; | ||
| 945 | |||
| 946 | if (dbcr_iac_range(child) & DBCR_IAC12MODE) { | ||
| 947 | /* address range - clear slots 1 & 2 */ | ||
| 948 | child->thread.iac2 = 0; | ||
| 949 | dbcr_iac_range(child) &= ~DBCR_IAC12MODE; | ||
| 950 | } | ||
| 951 | child->thread.iac1 = 0; | ||
| 952 | child->thread.dbcr0 &= ~DBCR0_IAC1; | ||
| 953 | break; | ||
| 954 | case 2: | ||
| 955 | if ((child->thread.dbcr0 & DBCR0_IAC2) == 0) | ||
| 956 | return -ENOENT; | ||
| 957 | |||
| 958 | if (dbcr_iac_range(child) & DBCR_IAC12MODE) | ||
| 959 | /* used in a range */ | ||
| 960 | return -EINVAL; | ||
| 961 | child->thread.iac2 = 0; | ||
| 962 | child->thread.dbcr0 &= ~DBCR0_IAC2; | ||
| 963 | break; | ||
| 964 | #if CONFIG_PPC_ADV_DEBUG_IACS > 2 | ||
| 965 | case 3: | ||
| 966 | if ((child->thread.dbcr0 & DBCR0_IAC3) == 0) | ||
| 967 | return -ENOENT; | ||
| 968 | |||
| 969 | if (dbcr_iac_range(child) & DBCR_IAC34MODE) { | ||
| 970 | /* address range - clear slots 3 & 4 */ | ||
| 971 | child->thread.iac4 = 0; | ||
| 972 | dbcr_iac_range(child) &= ~DBCR_IAC34MODE; | ||
| 973 | } | ||
| 974 | child->thread.iac3 = 0; | ||
| 975 | child->thread.dbcr0 &= ~DBCR0_IAC3; | ||
| 976 | break; | ||
| 977 | case 4: | ||
| 978 | if ((child->thread.dbcr0 & DBCR0_IAC4) == 0) | ||
| 979 | return -ENOENT; | ||
| 980 | |||
| 981 | if (dbcr_iac_range(child) & DBCR_IAC34MODE) | ||
| 982 | /* Used in a range */ | ||
| 983 | return -EINVAL; | ||
| 984 | child->thread.iac4 = 0; | ||
| 985 | child->thread.dbcr0 &= ~DBCR0_IAC4; | ||
| 986 | break; | ||
| 987 | #endif | ||
| 988 | default: | ||
| 989 | return -EINVAL; | ||
| 990 | } | ||
| 991 | return 0; | ||
| 992 | } | ||
| 993 | |||
| 994 | static int set_dac(struct task_struct *child, struct ppc_hw_breakpoint *bp_info) | ||
| 995 | { | ||
| 996 | int byte_enable = | ||
| 997 | (bp_info->condition_mode >> PPC_BREAKPOINT_CONDITION_BE_SHIFT) | ||
| 998 | & 0xf; | ||
| 999 | int condition_mode = | ||
| 1000 | bp_info->condition_mode & PPC_BREAKPOINT_CONDITION_MODE; | ||
| 1001 | int slot; | ||
| 1002 | |||
| 1003 | if (byte_enable && (condition_mode == 0)) | ||
| 1004 | return -EINVAL; | ||
| 1005 | |||
| 1006 | if (bp_info->addr >= TASK_SIZE) | ||
| 1007 | return -EIO; | ||
| 1008 | |||
| 1009 | if ((dbcr_dac(child) & (DBCR_DAC1R | DBCR_DAC1W)) == 0) { | ||
| 1010 | slot = 1; | ||
| 1011 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ) | ||
| 1012 | dbcr_dac(child) |= DBCR_DAC1R; | ||
| 1013 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE) | ||
| 1014 | dbcr_dac(child) |= DBCR_DAC1W; | ||
| 1015 | child->thread.dac1 = (unsigned long)bp_info->addr; | ||
| 1016 | #if CONFIG_PPC_ADV_DEBUG_DVCS > 0 | ||
| 1017 | if (byte_enable) { | ||
| 1018 | child->thread.dvc1 = | ||
| 1019 | (unsigned long)bp_info->condition_value; | ||
| 1020 | child->thread.dbcr2 |= | ||
| 1021 | ((byte_enable << DBCR2_DVC1BE_SHIFT) | | ||
| 1022 | (condition_mode << DBCR2_DVC1M_SHIFT)); | ||
| 1023 | } | ||
| 1024 | #endif | ||
| 1025 | #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE | ||
| 1026 | } else if (child->thread.dbcr2 & DBCR2_DAC12MODE) { | ||
| 1027 | /* Both dac1 and dac2 are part of a range */ | ||
| 1028 | return -ENOSPC; | ||
| 1029 | #endif | ||
| 1030 | } else if ((dbcr_dac(child) & (DBCR_DAC2R | DBCR_DAC2W)) == 0) { | ||
| 1031 | slot = 2; | ||
| 1032 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ) | ||
| 1033 | dbcr_dac(child) |= DBCR_DAC2R; | ||
| 1034 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE) | ||
| 1035 | dbcr_dac(child) |= DBCR_DAC2W; | ||
| 1036 | child->thread.dac2 = (unsigned long)bp_info->addr; | ||
| 1037 | #if CONFIG_PPC_ADV_DEBUG_DVCS > 0 | ||
| 1038 | if (byte_enable) { | ||
| 1039 | child->thread.dvc2 = | ||
| 1040 | (unsigned long)bp_info->condition_value; | ||
| 1041 | child->thread.dbcr2 |= | ||
| 1042 | ((byte_enable << DBCR2_DVC2BE_SHIFT) | | ||
| 1043 | (condition_mode << DBCR2_DVC2M_SHIFT)); | ||
| 1044 | } | ||
| 1045 | #endif | ||
| 1046 | } else | ||
| 1047 | return -ENOSPC; | ||
| 1048 | child->thread.dbcr0 |= DBCR0_IDM; | ||
| 1049 | child->thread.regs->msr |= MSR_DE; | ||
| 1050 | |||
| 1051 | return slot + 4; | ||
| 1052 | } | ||
| 1053 | |||
| 1054 | static int del_dac(struct task_struct *child, int slot) | ||
| 1055 | { | ||
| 1056 | if (slot == 1) { | ||
| 1057 | if ((dbcr_dac(child) & (DBCR_DAC1R | DBCR_DAC1W)) == 0) | ||
| 1058 | return -ENOENT; | ||
| 1059 | |||
| 1060 | child->thread.dac1 = 0; | ||
| 1061 | dbcr_dac(child) &= ~(DBCR_DAC1R | DBCR_DAC1W); | ||
| 1062 | #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE | ||
| 1063 | if (child->thread.dbcr2 & DBCR2_DAC12MODE) { | ||
| 1064 | child->thread.dac2 = 0; | ||
| 1065 | child->thread.dbcr2 &= ~DBCR2_DAC12MODE; | ||
| 1066 | } | ||
| 1067 | child->thread.dbcr2 &= ~(DBCR2_DVC1M | DBCR2_DVC1BE); | ||
| 1068 | #endif | ||
| 1069 | #if CONFIG_PPC_ADV_DEBUG_DVCS > 0 | ||
| 1070 | child->thread.dvc1 = 0; | ||
| 1071 | #endif | ||
| 1072 | } else if (slot == 2) { | ||
| 1073 | if ((dbcr_dac(child) & (DBCR_DAC2R | DBCR_DAC2W)) == 0) | ||
| 1074 | return -ENOENT; | ||
| 1075 | |||
| 1076 | #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE | ||
| 1077 | if (child->thread.dbcr2 & DBCR2_DAC12MODE) | ||
| 1078 | /* Part of a range */ | ||
| 1079 | return -EINVAL; | ||
| 1080 | child->thread.dbcr2 &= ~(DBCR2_DVC2M | DBCR2_DVC2BE); | ||
| 1081 | #endif | ||
| 1082 | #if CONFIG_PPC_ADV_DEBUG_DVCS > 0 | ||
| 1083 | child->thread.dvc2 = 0; | ||
| 1084 | #endif | ||
| 1085 | child->thread.dac2 = 0; | ||
| 1086 | dbcr_dac(child) &= ~(DBCR_DAC2R | DBCR_DAC2W); | ||
| 1087 | } else | ||
| 1088 | return -EINVAL; | ||
| 1089 | |||
| 1090 | return 0; | ||
| 1091 | } | ||
| 1092 | #endif /* CONFIG_PPC_ADV_DEBUG_REGS */ | ||
| 1093 | |||
| 1094 | #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE | ||
| 1095 | static int set_dac_range(struct task_struct *child, | ||
| 1096 | struct ppc_hw_breakpoint *bp_info) | ||
| 1097 | { | ||
| 1098 | int mode = bp_info->addr_mode & PPC_BREAKPOINT_MODE_MASK; | ||
| 1099 | |||
| 1100 | /* We don't allow range watchpoints to be used with DVC */ | ||
| 1101 | if (bp_info->condition_mode) | ||
| 1102 | return -EINVAL; | ||
| 1103 | |||
| 1104 | /* | ||
| 1105 | * Best effort to verify the address range. The user/supervisor bits | ||
| 1106 | * prevent trapping in kernel space, but let's fail on an obvious bad | ||
| 1107 | * range. The simple test on the mask is not fool-proof, and any | ||
| 1108 | * exclusive range will spill over into kernel space. | ||
| 1109 | */ | ||
| 1110 | if (bp_info->addr >= TASK_SIZE) | ||
| 1111 | return -EIO; | ||
| 1112 | if (mode == PPC_BREAKPOINT_MODE_MASK) { | ||
| 1113 | /* | ||
| 1114 | * dac2 is a bitmask. Don't allow a mask that makes a | ||
| 1115 | * kernel space address from a valid dac1 value | ||
| 1116 | */ | ||
| 1117 | if (~((unsigned long)bp_info->addr2) >= TASK_SIZE) | ||
| 1118 | return -EIO; | ||
| 1119 | } else { | ||
| 1120 | /* | ||
| 1121 | * For range breakpoints, addr2 must also be a valid address | ||
| 1122 | */ | ||
| 1123 | if (bp_info->addr2 >= TASK_SIZE) | ||
| 1124 | return -EIO; | ||
| 1125 | } | ||
| 1126 | |||
| 1127 | if (child->thread.dbcr0 & | ||
| 1128 | (DBCR0_DAC1R | DBCR0_DAC1W | DBCR0_DAC2R | DBCR0_DAC2W)) | ||
| 1129 | return -ENOSPC; | ||
| 1130 | |||
| 1131 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ) | ||
| 1132 | child->thread.dbcr0 |= (DBCR0_DAC1R | DBCR0_IDM); | ||
| 1133 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE) | ||
| 1134 | child->thread.dbcr0 |= (DBCR0_DAC1W | DBCR0_IDM); | ||
| 1135 | child->thread.dac1 = bp_info->addr; | ||
| 1136 | child->thread.dac2 = bp_info->addr2; | ||
| 1137 | if (mode == PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE) | ||
| 1138 | child->thread.dbcr2 |= DBCR2_DAC12M; | ||
| 1139 | else if (mode == PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE) | ||
| 1140 | child->thread.dbcr2 |= DBCR2_DAC12MX; | ||
| 1141 | else /* PPC_BREAKPOINT_MODE_MASK */ | ||
| 1142 | child->thread.dbcr2 |= DBCR2_DAC12MM; | ||
| 1143 | child->thread.regs->msr |= MSR_DE; | ||
| 1144 | |||
| 1145 | return 5; | ||
| 1146 | } | ||
| 1147 | #endif /* CONFIG_PPC_ADV_DEBUG_DAC_RANGE */ | ||
| 1148 | |||
| 1149 | static long ppc_set_hwdebug(struct task_struct *child, | ||
| 1150 | struct ppc_hw_breakpoint *bp_info) | ||
| 1151 | { | ||
| 1152 | if (bp_info->version != 1) | ||
| 1153 | return -ENOTSUPP; | ||
| 1154 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | ||
| 1155 | /* | ||
| 1156 | * Check for invalid flags and combinations | ||
| 1157 | */ | ||
| 1158 | if ((bp_info->trigger_type == 0) || | ||
| 1159 | (bp_info->trigger_type & ~(PPC_BREAKPOINT_TRIGGER_EXECUTE | | ||
| 1160 | PPC_BREAKPOINT_TRIGGER_RW)) || | ||
| 1161 | (bp_info->addr_mode & ~PPC_BREAKPOINT_MODE_MASK) || | ||
| 1162 | (bp_info->condition_mode & | ||
| 1163 | ~(PPC_BREAKPOINT_CONDITION_MODE | | ||
| 1164 | PPC_BREAKPOINT_CONDITION_BE_ALL))) | ||
| 1165 | return -EINVAL; | ||
| 1166 | #if CONFIG_PPC_ADV_DEBUG_DVCS == 0 | ||
| 1167 | if (bp_info->condition_mode != PPC_BREAKPOINT_CONDITION_NONE) | ||
| 1168 | return -EINVAL; | ||
| 1169 | #endif | ||
| 1170 | |||
| 1171 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_EXECUTE) { | ||
| 1172 | if ((bp_info->trigger_type != PPC_BREAKPOINT_TRIGGER_EXECUTE) || | ||
| 1173 | (bp_info->condition_mode != PPC_BREAKPOINT_CONDITION_NONE)) | ||
| 1174 | return -EINVAL; | ||
| 1175 | return set_intruction_bp(child, bp_info); | ||
| 1176 | } | ||
| 1177 | if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_EXACT) | ||
| 1178 | return set_dac(child, bp_info); | ||
| 1179 | |||
| 1180 | #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE | ||
| 1181 | return set_dac_range(child, bp_info); | ||
| 1182 | #else | ||
| 1183 | return -EINVAL; | ||
| 1184 | #endif | ||
| 1185 | #else /* !CONFIG_PPC_ADV_DEBUG_DVCS */ | ||
| 1186 | /* | ||
| 1187 | * We only support one data breakpoint | ||
| 1188 | */ | ||
| 1189 | if (((bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_RW) == 0) || | ||
| 1190 | ((bp_info->trigger_type & ~PPC_BREAKPOINT_TRIGGER_RW) != 0) || | ||
| 1191 | (bp_info->trigger_type != PPC_BREAKPOINT_TRIGGER_WRITE) || | ||
| 1192 | (bp_info->addr_mode != PPC_BREAKPOINT_MODE_EXACT) || | ||
| 1193 | (bp_info->condition_mode != PPC_BREAKPOINT_CONDITION_NONE)) | ||
| 1194 | return -EINVAL; | ||
| 1195 | |||
| 1196 | if (child->thread.dabr) | ||
| 1197 | return -ENOSPC; | ||
| 1198 | |||
| 1199 | if ((unsigned long)bp_info->addr >= TASK_SIZE) | ||
| 1200 | return -EIO; | ||
| 1201 | |||
| 1202 | child->thread.dabr = (unsigned long)bp_info->addr; | ||
| 1203 | |||
| 1204 | return 1; | ||
| 1205 | #endif /* !CONFIG_PPC_ADV_DEBUG_DVCS */ | ||
| 1206 | } | ||
| 1207 | |||
| 1208 | static long ppc_del_hwdebug(struct task_struct *child, long addr, long data) | ||
| 1209 | { | ||
| 1210 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | ||
| 1211 | int rc; | ||
| 1212 | |||
| 1213 | if (data <= 4) | ||
| 1214 | rc = del_instruction_bp(child, (int)data); | ||
| 1215 | else | ||
| 1216 | rc = del_dac(child, (int)data - 4); | ||
| 1217 | |||
| 1218 | if (!rc) { | ||
| 1219 | if (!DBCR_ACTIVE_EVENTS(child->thread.dbcr0, | ||
| 1220 | child->thread.dbcr1)) { | ||
| 1221 | child->thread.dbcr0 &= ~DBCR0_IDM; | ||
| 1222 | child->thread.regs->msr &= ~MSR_DE; | ||
| 1223 | } | ||
| 1224 | } | ||
| 1225 | return rc; | ||
| 1226 | #else | ||
| 1227 | if (data != 1) | ||
| 1228 | return -EINVAL; | ||
| 1229 | if (child->thread.dabr == 0) | ||
| 1230 | return -ENOENT; | ||
| 1231 | |||
| 1232 | child->thread.dabr = 0; | ||
| 1233 | |||
| 1234 | return 0; | ||
| 1235 | #endif | ||
| 1236 | } | ||
| 1237 | |||
| 842 | /* | 1238 | /* |
| 843 | * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls, | 1239 | * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls, |
| 844 | * we mark them as obsolete now, they will be removed in a future version | 1240 | * we mark them as obsolete now, they will be removed in a future version |
| @@ -932,13 +1328,77 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 932 | break; | 1328 | break; |
| 933 | } | 1329 | } |
| 934 | 1330 | ||
| 1331 | case PPC_PTRACE_GETHWDBGINFO: { | ||
| 1332 | struct ppc_debug_info dbginfo; | ||
| 1333 | |||
| 1334 | dbginfo.version = 1; | ||
| 1335 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | ||
| 1336 | dbginfo.num_instruction_bps = CONFIG_PPC_ADV_DEBUG_IACS; | ||
| 1337 | dbginfo.num_data_bps = CONFIG_PPC_ADV_DEBUG_DACS; | ||
| 1338 | dbginfo.num_condition_regs = CONFIG_PPC_ADV_DEBUG_DVCS; | ||
| 1339 | dbginfo.data_bp_alignment = 4; | ||
| 1340 | dbginfo.sizeof_condition = 4; | ||
| 1341 | dbginfo.features = PPC_DEBUG_FEATURE_INSN_BP_RANGE | | ||
| 1342 | PPC_DEBUG_FEATURE_INSN_BP_MASK; | ||
| 1343 | #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE | ||
| 1344 | dbginfo.features |= | ||
| 1345 | PPC_DEBUG_FEATURE_DATA_BP_RANGE | | ||
| 1346 | PPC_DEBUG_FEATURE_DATA_BP_MASK; | ||
| 1347 | #endif | ||
| 1348 | #else /* !CONFIG_PPC_ADV_DEBUG_REGS */ | ||
| 1349 | dbginfo.num_instruction_bps = 0; | ||
| 1350 | dbginfo.num_data_bps = 1; | ||
| 1351 | dbginfo.num_condition_regs = 0; | ||
| 1352 | #ifdef CONFIG_PPC64 | ||
| 1353 | dbginfo.data_bp_alignment = 8; | ||
| 1354 | #else | ||
| 1355 | dbginfo.data_bp_alignment = 4; | ||
| 1356 | #endif | ||
| 1357 | dbginfo.sizeof_condition = 0; | ||
| 1358 | dbginfo.features = 0; | ||
| 1359 | #endif /* CONFIG_PPC_ADV_DEBUG_REGS */ | ||
| 1360 | |||
| 1361 | if (!access_ok(VERIFY_WRITE, data, | ||
| 1362 | sizeof(struct ppc_debug_info))) | ||
| 1363 | return -EFAULT; | ||
| 1364 | ret = __copy_to_user((struct ppc_debug_info __user *)data, | ||
| 1365 | &dbginfo, sizeof(struct ppc_debug_info)) ? | ||
| 1366 | -EFAULT : 0; | ||
| 1367 | break; | ||
| 1368 | } | ||
| 1369 | |||
| 1370 | case PPC_PTRACE_SETHWDEBUG: { | ||
| 1371 | struct ppc_hw_breakpoint bp_info; | ||
| 1372 | |||
| 1373 | if (!access_ok(VERIFY_READ, data, | ||
| 1374 | sizeof(struct ppc_hw_breakpoint))) | ||
| 1375 | return -EFAULT; | ||
| 1376 | ret = __copy_from_user(&bp_info, | ||
| 1377 | (struct ppc_hw_breakpoint __user *)data, | ||
| 1378 | sizeof(struct ppc_hw_breakpoint)) ? | ||
| 1379 | -EFAULT : 0; | ||
| 1380 | if (!ret) | ||
| 1381 | ret = ppc_set_hwdebug(child, &bp_info); | ||
| 1382 | break; | ||
| 1383 | } | ||
| 1384 | |||
| 1385 | case PPC_PTRACE_DELHWDEBUG: { | ||
| 1386 | ret = ppc_del_hwdebug(child, addr, data); | ||
| 1387 | break; | ||
| 1388 | } | ||
| 1389 | |||
| 935 | case PTRACE_GET_DEBUGREG: { | 1390 | case PTRACE_GET_DEBUGREG: { |
| 936 | ret = -EINVAL; | 1391 | ret = -EINVAL; |
| 937 | /* We only support one DABR and no IABRS at the moment */ | 1392 | /* We only support one DABR and no IABRS at the moment */ |
| 938 | if (addr > 0) | 1393 | if (addr > 0) |
| 939 | break; | 1394 | break; |
| 1395 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | ||
| 1396 | ret = put_user(child->thread.dac1, | ||
| 1397 | (unsigned long __user *)data); | ||
| 1398 | #else | ||
| 940 | ret = put_user(child->thread.dabr, | 1399 | ret = put_user(child->thread.dabr, |
| 941 | (unsigned long __user *)data); | 1400 | (unsigned long __user *)data); |
| 1401 | #endif | ||
| 942 | break; | 1402 | break; |
| 943 | } | 1403 | } |
| 944 | 1404 | ||
diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c index 1be9fe38bcb5..8777fb02349f 100644 --- a/arch/powerpc/kernel/rtas-proc.c +++ b/arch/powerpc/kernel/rtas-proc.c | |||
| @@ -262,19 +262,19 @@ static int __init proc_rtas_init(void) | |||
| 262 | if (rtas_node == NULL) | 262 | if (rtas_node == NULL) |
| 263 | return -ENODEV; | 263 | return -ENODEV; |
| 264 | 264 | ||
| 265 | proc_create("ppc64/rtas/progress", S_IRUGO|S_IWUSR, NULL, | 265 | proc_create("powerpc/rtas/progress", S_IRUGO|S_IWUSR, NULL, |
| 266 | &ppc_rtas_progress_operations); | 266 | &ppc_rtas_progress_operations); |
| 267 | proc_create("ppc64/rtas/clock", S_IRUGO|S_IWUSR, NULL, | 267 | proc_create("powerpc/rtas/clock", S_IRUGO|S_IWUSR, NULL, |
| 268 | &ppc_rtas_clock_operations); | 268 | &ppc_rtas_clock_operations); |
| 269 | proc_create("ppc64/rtas/poweron", S_IWUSR|S_IRUGO, NULL, | 269 | proc_create("powerpc/rtas/poweron", S_IWUSR|S_IRUGO, NULL, |
| 270 | &ppc_rtas_poweron_operations); | 270 | &ppc_rtas_poweron_operations); |
| 271 | proc_create("ppc64/rtas/sensors", S_IRUGO, NULL, | 271 | proc_create("powerpc/rtas/sensors", S_IRUGO, NULL, |
| 272 | &ppc_rtas_sensors_operations); | 272 | &ppc_rtas_sensors_operations); |
| 273 | proc_create("ppc64/rtas/frequency", S_IWUSR|S_IRUGO, NULL, | 273 | proc_create("powerpc/rtas/frequency", S_IWUSR|S_IRUGO, NULL, |
| 274 | &ppc_rtas_tone_freq_operations); | 274 | &ppc_rtas_tone_freq_operations); |
| 275 | proc_create("ppc64/rtas/volume", S_IWUSR|S_IRUGO, NULL, | 275 | proc_create("powerpc/rtas/volume", S_IWUSR|S_IRUGO, NULL, |
| 276 | &ppc_rtas_tone_volume_operations); | 276 | &ppc_rtas_tone_volume_operations); |
| 277 | proc_create("ppc64/rtas/rmo_buffer", S_IRUSR, NULL, | 277 | proc_create("powerpc/rtas/rmo_buffer", S_IRUSR, NULL, |
| 278 | &ppc_rtas_rmo_buf_ops); | 278 | &ppc_rtas_rmo_buf_ops); |
| 279 | return 0; | 279 | return 0; |
| 280 | } | 280 | } |
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index bf90361bb70f..74367841615a 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/completion.h> | 23 | #include <linux/completion.h> |
| 24 | #include <linux/cpumask.h> | 24 | #include <linux/cpumask.h> |
| 25 | #include <linux/lmb.h> | 25 | #include <linux/lmb.h> |
| 26 | #include <linux/slab.h> | ||
| 26 | 27 | ||
| 27 | #include <asm/prom.h> | 28 | #include <asm/prom.h> |
| 28 | #include <asm/rtas.h> | 29 | #include <asm/rtas.h> |
| @@ -42,7 +43,7 @@ | |||
| 42 | #include <asm/mmu.h> | 43 | #include <asm/mmu.h> |
| 43 | 44 | ||
| 44 | struct rtas_t rtas = { | 45 | struct rtas_t rtas = { |
| 45 | .lock = __RAW_SPIN_LOCK_UNLOCKED | 46 | .lock = __ARCH_SPIN_LOCK_UNLOCKED |
| 46 | }; | 47 | }; |
| 47 | EXPORT_SYMBOL(rtas); | 48 | EXPORT_SYMBOL(rtas); |
| 48 | 49 | ||
| @@ -80,13 +81,13 @@ static unsigned long lock_rtas(void) | |||
| 80 | 81 | ||
| 81 | local_irq_save(flags); | 82 | local_irq_save(flags); |
| 82 | preempt_disable(); | 83 | preempt_disable(); |
| 83 | __raw_spin_lock_flags(&rtas.lock, flags); | 84 | arch_spin_lock_flags(&rtas.lock, flags); |
| 84 | return flags; | 85 | return flags; |
| 85 | } | 86 | } |
| 86 | 87 | ||
| 87 | static void unlock_rtas(unsigned long flags) | 88 | static void unlock_rtas(unsigned long flags) |
| 88 | { | 89 | { |
| 89 | __raw_spin_unlock(&rtas.lock); | 90 | arch_spin_unlock(&rtas.lock); |
| 90 | local_irq_restore(flags); | 91 | local_irq_restore(flags); |
| 91 | preempt_enable(); | 92 | preempt_enable(); |
| 92 | } | 93 | } |
| @@ -978,7 +979,7 @@ int __init early_init_dt_scan_rtas(unsigned long node, | |||
| 978 | return 1; | 979 | return 1; |
| 979 | } | 980 | } |
| 980 | 981 | ||
| 981 | static raw_spinlock_t timebase_lock; | 982 | static arch_spinlock_t timebase_lock; |
| 982 | static u64 timebase = 0; | 983 | static u64 timebase = 0; |
| 983 | 984 | ||
| 984 | void __cpuinit rtas_give_timebase(void) | 985 | void __cpuinit rtas_give_timebase(void) |
| @@ -987,10 +988,10 @@ void __cpuinit rtas_give_timebase(void) | |||
| 987 | 988 | ||
| 988 | local_irq_save(flags); | 989 | local_irq_save(flags); |
| 989 | hard_irq_disable(); | 990 | hard_irq_disable(); |
| 990 | __raw_spin_lock(&timebase_lock); | 991 | arch_spin_lock(&timebase_lock); |
| 991 | rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL); | 992 | rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL); |
| 992 | timebase = get_tb(); | 993 | timebase = get_tb(); |
| 993 | __raw_spin_unlock(&timebase_lock); | 994 | arch_spin_unlock(&timebase_lock); |
| 994 | 995 | ||
| 995 | while (timebase) | 996 | while (timebase) |
| 996 | barrier(); | 997 | barrier(); |
| @@ -1002,8 +1003,8 @@ void __cpuinit rtas_take_timebase(void) | |||
| 1002 | { | 1003 | { |
| 1003 | while (!timebase) | 1004 | while (!timebase) |
| 1004 | barrier(); | 1005 | barrier(); |
| 1005 | __raw_spin_lock(&timebase_lock); | 1006 | arch_spin_lock(&timebase_lock); |
| 1006 | set_tb(timebase >> 32, timebase & 0xffffffff); | 1007 | set_tb(timebase >> 32, timebase & 0xffffffff); |
| 1007 | timebase = 0; | 1008 | timebase = 0; |
| 1008 | __raw_spin_unlock(&timebase_lock); | 1009 | arch_spin_unlock(&timebase_lock); |
| 1009 | } | 1010 | } |
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c index 13011a96a977..bfc2abafac44 100644 --- a/arch/powerpc/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * as published by the Free Software Foundation; either version | 6 | * as published by the Free Software Foundation; either version |
| 7 | * 2 of the License, or (at your option) any later version. | 7 | * 2 of the License, or (at your option) any later version. |
| 8 | * | 8 | * |
| 9 | * /proc/ppc64/rtas/firmware_flash interface | 9 | * /proc/powerpc/rtas/firmware_flash interface |
| 10 | * | 10 | * |
| 11 | * This file implements a firmware_flash interface to pump a firmware | 11 | * This file implements a firmware_flash interface to pump a firmware |
| 12 | * image into the kernel. At reboot time rtas_restart() will see the | 12 | * image into the kernel. At reboot time rtas_restart() will see the |
| @@ -15,6 +15,7 @@ | |||
| 15 | 15 | ||
| 16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
| 18 | #include <linux/slab.h> | ||
| 18 | #include <linux/proc_fs.h> | 19 | #include <linux/proc_fs.h> |
| 19 | #include <asm/delay.h> | 20 | #include <asm/delay.h> |
| 20 | #include <asm/uaccess.h> | 21 | #include <asm/uaccess.h> |
| @@ -740,7 +741,7 @@ static int __init rtas_flash_init(void) | |||
| 740 | return 1; | 741 | return 1; |
| 741 | } | 742 | } |
| 742 | 743 | ||
| 743 | firmware_flash_pde = create_flash_pde("ppc64/rtas/" | 744 | firmware_flash_pde = create_flash_pde("powerpc/rtas/" |
| 744 | FIRMWARE_FLASH_NAME, | 745 | FIRMWARE_FLASH_NAME, |
| 745 | &rtas_flash_operations); | 746 | &rtas_flash_operations); |
| 746 | if (firmware_flash_pde == NULL) { | 747 | if (firmware_flash_pde == NULL) { |
| @@ -754,7 +755,7 @@ static int __init rtas_flash_init(void) | |||
| 754 | if (rc != 0) | 755 | if (rc != 0) |
| 755 | goto cleanup; | 756 | goto cleanup; |
| 756 | 757 | ||
| 757 | firmware_update_pde = create_flash_pde("ppc64/rtas/" | 758 | firmware_update_pde = create_flash_pde("powerpc/rtas/" |
| 758 | FIRMWARE_UPDATE_NAME, | 759 | FIRMWARE_UPDATE_NAME, |
| 759 | &rtas_flash_operations); | 760 | &rtas_flash_operations); |
| 760 | if (firmware_update_pde == NULL) { | 761 | if (firmware_update_pde == NULL) { |
| @@ -768,7 +769,7 @@ static int __init rtas_flash_init(void) | |||
| 768 | if (rc != 0) | 769 | if (rc != 0) |
| 769 | goto cleanup; | 770 | goto cleanup; |
| 770 | 771 | ||
| 771 | validate_pde = create_flash_pde("ppc64/rtas/" VALIDATE_FLASH_NAME, | 772 | validate_pde = create_flash_pde("powerpc/rtas/" VALIDATE_FLASH_NAME, |
| 772 | &validate_flash_operations); | 773 | &validate_flash_operations); |
| 773 | if (validate_pde == NULL) { | 774 | if (validate_pde == NULL) { |
| 774 | rc = -ENOMEM; | 775 | rc = -ENOMEM; |
| @@ -781,7 +782,7 @@ static int __init rtas_flash_init(void) | |||
| 781 | if (rc != 0) | 782 | if (rc != 0) |
| 782 | goto cleanup; | 783 | goto cleanup; |
| 783 | 784 | ||
| 784 | manage_pde = create_flash_pde("ppc64/rtas/" MANAGE_FLASH_NAME, | 785 | manage_pde = create_flash_pde("powerpc/rtas/" MANAGE_FLASH_NAME, |
| 785 | &manage_flash_operations); | 786 | &manage_flash_operations); |
| 786 | if (manage_pde == NULL) { | 787 | if (manage_pde == NULL) { |
| 787 | rc = -ENOMEM; | 788 | rc = -ENOMEM; |
diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c new file mode 100644 index 000000000000..4190eae7850a --- /dev/null +++ b/arch/powerpc/kernel/rtasd.c | |||
| @@ -0,0 +1,540 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or | ||
| 5 | * modify it under the terms of the GNU General Public License | ||
| 6 | * as published by the Free Software Foundation; either version | ||
| 7 | * 2 of the License, or (at your option) any later version. | ||
| 8 | * | ||
| 9 | * Communication to userspace based on kernel/printk.c | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/types.h> | ||
| 13 | #include <linux/errno.h> | ||
| 14 | #include <linux/sched.h> | ||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/poll.h> | ||
| 17 | #include <linux/proc_fs.h> | ||
| 18 | #include <linux/init.h> | ||
| 19 | #include <linux/vmalloc.h> | ||
| 20 | #include <linux/spinlock.h> | ||
| 21 | #include <linux/cpu.h> | ||
| 22 | #include <linux/workqueue.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | |||
| 25 | #include <asm/uaccess.h> | ||
| 26 | #include <asm/io.h> | ||
| 27 | #include <asm/rtas.h> | ||
| 28 | #include <asm/prom.h> | ||
| 29 | #include <asm/nvram.h> | ||
| 30 | #include <asm/atomic.h> | ||
| 31 | #include <asm/machdep.h> | ||
| 32 | |||
| 33 | |||
| 34 | static DEFINE_SPINLOCK(rtasd_log_lock); | ||
| 35 | |||
| 36 | static DECLARE_WAIT_QUEUE_HEAD(rtas_log_wait); | ||
| 37 | |||
| 38 | static char *rtas_log_buf; | ||
| 39 | static unsigned long rtas_log_start; | ||
| 40 | static unsigned long rtas_log_size; | ||
| 41 | |||
| 42 | static int surveillance_timeout = -1; | ||
| 43 | |||
| 44 | static unsigned int rtas_error_log_max; | ||
| 45 | static unsigned int rtas_error_log_buffer_max; | ||
| 46 | |||
| 47 | /* RTAS service tokens */ | ||
| 48 | static unsigned int event_scan; | ||
| 49 | static unsigned int rtas_event_scan_rate; | ||
| 50 | |||
| 51 | static int full_rtas_msgs = 0; | ||
| 52 | |||
| 53 | /* Stop logging to nvram after first fatal error */ | ||
| 54 | static int logging_enabled; /* Until we initialize everything, | ||
| 55 | * make sure we don't try logging | ||
| 56 | * anything */ | ||
| 57 | static int error_log_cnt; | ||
| 58 | |||
| 59 | /* | ||
| 60 | * Since we use 32 bit RTAS, the physical address of this must be below | ||
| 61 | * 4G or else bad things happen. Allocate this in the kernel data and | ||
| 62 | * make it big enough. | ||
| 63 | */ | ||
| 64 | static unsigned char logdata[RTAS_ERROR_LOG_MAX]; | ||
| 65 | |||
| 66 | static char *rtas_type[] = { | ||
| 67 | "Unknown", "Retry", "TCE Error", "Internal Device Failure", | ||
| 68 | "Timeout", "Data Parity", "Address Parity", "Cache Parity", | ||
| 69 | "Address Invalid", "ECC Uncorrected", "ECC Corrupted", | ||
| 70 | }; | ||
| 71 | |||
| 72 | static char *rtas_event_type(int type) | ||
| 73 | { | ||
| 74 | if ((type > 0) && (type < 11)) | ||
| 75 | return rtas_type[type]; | ||
| 76 | |||
| 77 | switch (type) { | ||
| 78 | case RTAS_TYPE_EPOW: | ||
| 79 | return "EPOW"; | ||
| 80 | case RTAS_TYPE_PLATFORM: | ||
| 81 | return "Platform Error"; | ||
| 82 | case RTAS_TYPE_IO: | ||
| 83 | return "I/O Event"; | ||
| 84 | case RTAS_TYPE_INFO: | ||
| 85 | return "Platform Information Event"; | ||
| 86 | case RTAS_TYPE_DEALLOC: | ||
| 87 | return "Resource Deallocation Event"; | ||
| 88 | case RTAS_TYPE_DUMP: | ||
| 89 | return "Dump Notification Event"; | ||
| 90 | } | ||
| 91 | |||
| 92 | return rtas_type[0]; | ||
| 93 | } | ||
| 94 | |||
| 95 | /* To see this info, grep RTAS /var/log/messages and each entry | ||
| 96 | * will be collected together with obvious begin/end. | ||
| 97 | * There will be a unique identifier on the begin and end lines. | ||
| 98 | * This will persist across reboots. | ||
| 99 | * | ||
| 100 | * format of error logs returned from RTAS: | ||
| 101 | * bytes (size) : contents | ||
| 102 | * -------------------------------------------------------- | ||
| 103 | * 0-7 (8) : rtas_error_log | ||
| 104 | * 8-47 (40) : extended info | ||
| 105 | * 48-51 (4) : vendor id | ||
| 106 | * 52-1023 (vendor specific) : location code and debug data | ||
| 107 | */ | ||
| 108 | static void printk_log_rtas(char *buf, int len) | ||
| 109 | { | ||
| 110 | |||
| 111 | int i,j,n = 0; | ||
| 112 | int perline = 16; | ||
| 113 | char buffer[64]; | ||
| 114 | char * str = "RTAS event"; | ||
| 115 | |||
| 116 | if (full_rtas_msgs) { | ||
| 117 | printk(RTAS_DEBUG "%d -------- %s begin --------\n", | ||
| 118 | error_log_cnt, str); | ||
| 119 | |||
| 120 | /* | ||
| 121 | * Print perline bytes on each line, each line will start | ||
| 122 | * with RTAS and a changing number, so syslogd will | ||
| 123 | * print lines that are otherwise the same. Separate every | ||
| 124 | * 4 bytes with a space. | ||
| 125 | */ | ||
| 126 | for (i = 0; i < len; i++) { | ||
| 127 | j = i % perline; | ||
| 128 | if (j == 0) { | ||
| 129 | memset(buffer, 0, sizeof(buffer)); | ||
| 130 | n = sprintf(buffer, "RTAS %d:", i/perline); | ||
| 131 | } | ||
| 132 | |||
| 133 | if ((i % 4) == 0) | ||
| 134 | n += sprintf(buffer+n, " "); | ||
| 135 | |||
| 136 | n += sprintf(buffer+n, "%02x", (unsigned char)buf[i]); | ||
| 137 | |||
| 138 | if (j == (perline-1)) | ||
| 139 | printk(KERN_DEBUG "%s\n", buffer); | ||
| 140 | } | ||
| 141 | if ((i % perline) != 0) | ||
| 142 | printk(KERN_DEBUG "%s\n", buffer); | ||
| 143 | |||
| 144 | printk(RTAS_DEBUG "%d -------- %s end ----------\n", | ||
| 145 | error_log_cnt, str); | ||
| 146 | } else { | ||
| 147 | struct rtas_error_log *errlog = (struct rtas_error_log *)buf; | ||
| 148 | |||
| 149 | printk(RTAS_DEBUG "event: %d, Type: %s, Severity: %d\n", | ||
| 150 | error_log_cnt, rtas_event_type(errlog->type), | ||
| 151 | errlog->severity); | ||
| 152 | } | ||
| 153 | } | ||
| 154 | |||
| 155 | static int log_rtas_len(char * buf) | ||
| 156 | { | ||
| 157 | int len; | ||
| 158 | struct rtas_error_log *err; | ||
| 159 | |||
| 160 | /* rtas fixed header */ | ||
| 161 | len = 8; | ||
| 162 | err = (struct rtas_error_log *)buf; | ||
| 163 | if (err->extended_log_length) { | ||
| 164 | |||
| 165 | /* extended header */ | ||
| 166 | len += err->extended_log_length; | ||
| 167 | } | ||
| 168 | |||
| 169 | if (rtas_error_log_max == 0) | ||
| 170 | rtas_error_log_max = rtas_get_error_log_max(); | ||
| 171 | |||
| 172 | if (len > rtas_error_log_max) | ||
| 173 | len = rtas_error_log_max; | ||
| 174 | |||
| 175 | return len; | ||
| 176 | } | ||
| 177 | |||
| 178 | /* | ||
| 179 | * First write to nvram, if fatal error, that is the only | ||
| 180 | * place we log the info. The error will be picked up | ||
| 181 | * on the next reboot by rtasd. If not fatal, run the | ||
| 182 | * method for the type of error. Currently, only RTAS | ||
| 183 | * errors have methods implemented, but in the future | ||
| 184 | * there might be a need to store data in nvram before a | ||
| 185 | * call to panic(). | ||
| 186 | * | ||
| 187 | * XXX We write to nvram periodically, to indicate error has | ||
| 188 | * been written and sync'd, but there is a possibility | ||
| 189 | * that if we don't shutdown correctly, a duplicate error | ||
| 190 | * record will be created on next reboot. | ||
| 191 | */ | ||
| 192 | void pSeries_log_error(char *buf, unsigned int err_type, int fatal) | ||
| 193 | { | ||
| 194 | unsigned long offset; | ||
| 195 | unsigned long s; | ||
| 196 | int len = 0; | ||
| 197 | |||
| 198 | pr_debug("rtasd: logging event\n"); | ||
| 199 | if (buf == NULL) | ||
| 200 | return; | ||
| 201 | |||
| 202 | spin_lock_irqsave(&rtasd_log_lock, s); | ||
| 203 | |||
| 204 | /* get length and increase count */ | ||
| 205 | switch (err_type & ERR_TYPE_MASK) { | ||
| 206 | case ERR_TYPE_RTAS_LOG: | ||
| 207 | len = log_rtas_len(buf); | ||
| 208 | if (!(err_type & ERR_FLAG_BOOT)) | ||
| 209 | error_log_cnt++; | ||
| 210 | break; | ||
| 211 | case ERR_TYPE_KERNEL_PANIC: | ||
| 212 | default: | ||
| 213 | WARN_ON_ONCE(!irqs_disabled()); /* @@@ DEBUG @@@ */ | ||
| 214 | spin_unlock_irqrestore(&rtasd_log_lock, s); | ||
| 215 | return; | ||
| 216 | } | ||
| 217 | |||
| 218 | #ifdef CONFIG_PPC64 | ||
| 219 | /* Write error to NVRAM */ | ||
| 220 | if (logging_enabled && !(err_type & ERR_FLAG_BOOT)) | ||
| 221 | nvram_write_error_log(buf, len, err_type, error_log_cnt); | ||
| 222 | #endif /* CONFIG_PPC64 */ | ||
| 223 | |||
| 224 | /* | ||
| 225 | * rtas errors can occur during boot, and we do want to capture | ||
| 226 | * those somewhere, even if nvram isn't ready (why not?), and even | ||
| 227 | * if rtasd isn't ready. Put them into the boot log, at least. | ||
| 228 | */ | ||
| 229 | if ((err_type & ERR_TYPE_MASK) == ERR_TYPE_RTAS_LOG) | ||
| 230 | printk_log_rtas(buf, len); | ||
| 231 | |||
| 232 | /* Check to see if we need to or have stopped logging */ | ||
| 233 | if (fatal || !logging_enabled) { | ||
| 234 | logging_enabled = 0; | ||
| 235 | WARN_ON_ONCE(!irqs_disabled()); /* @@@ DEBUG @@@ */ | ||
| 236 | spin_unlock_irqrestore(&rtasd_log_lock, s); | ||
| 237 | return; | ||
| 238 | } | ||
| 239 | |||
| 240 | /* call type specific method for error */ | ||
| 241 | switch (err_type & ERR_TYPE_MASK) { | ||
| 242 | case ERR_TYPE_RTAS_LOG: | ||
| 243 | offset = rtas_error_log_buffer_max * | ||
| 244 | ((rtas_log_start+rtas_log_size) & LOG_NUMBER_MASK); | ||
| 245 | |||
| 246 | /* First copy over sequence number */ | ||
| 247 | memcpy(&rtas_log_buf[offset], (void *) &error_log_cnt, sizeof(int)); | ||
| 248 | |||
| 249 | /* Second copy over error log data */ | ||
| 250 | offset += sizeof(int); | ||
| 251 | memcpy(&rtas_log_buf[offset], buf, len); | ||
| 252 | |||
| 253 | if (rtas_log_size < LOG_NUMBER) | ||
| 254 | rtas_log_size += 1; | ||
| 255 | else | ||
| 256 | rtas_log_start += 1; | ||
| 257 | |||
| 258 | WARN_ON_ONCE(!irqs_disabled()); /* @@@ DEBUG @@@ */ | ||
| 259 | spin_unlock_irqrestore(&rtasd_log_lock, s); | ||
| 260 | wake_up_interruptible(&rtas_log_wait); | ||
| 261 | break; | ||
| 262 | case ERR_TYPE_KERNEL_PANIC: | ||
| 263 | default: | ||
| 264 | WARN_ON_ONCE(!irqs_disabled()); /* @@@ DEBUG @@@ */ | ||
| 265 | spin_unlock_irqrestore(&rtasd_log_lock, s); | ||
| 266 | return; | ||
| 267 | } | ||
| 268 | |||
| 269 | } | ||
| 270 | |||
| 271 | static int rtas_log_open(struct inode * inode, struct file * file) | ||
| 272 | { | ||
| 273 | return 0; | ||
| 274 | } | ||
| 275 | |||
| 276 | static int rtas_log_release(struct inode * inode, struct file * file) | ||
| 277 | { | ||
| 278 | return 0; | ||
| 279 | } | ||
| 280 | |||
| 281 | /* This will check if all events are logged, if they are then, we | ||
| 282 | * know that we can safely clear the events in NVRAM. | ||
| 283 | * Next we'll sit and wait for something else to log. | ||
| 284 | */ | ||
| 285 | static ssize_t rtas_log_read(struct file * file, char __user * buf, | ||
| 286 | size_t count, loff_t *ppos) | ||
| 287 | { | ||
| 288 | int error; | ||
| 289 | char *tmp; | ||
| 290 | unsigned long s; | ||
| 291 | unsigned long offset; | ||
| 292 | |||
| 293 | if (!buf || count < rtas_error_log_buffer_max) | ||
| 294 | return -EINVAL; | ||
| 295 | |||
| 296 | count = rtas_error_log_buffer_max; | ||
| 297 | |||
| 298 | if (!access_ok(VERIFY_WRITE, buf, count)) | ||
| 299 | return -EFAULT; | ||
| 300 | |||
| 301 | tmp = kmalloc(count, GFP_KERNEL); | ||
| 302 | if (!tmp) | ||
| 303 | return -ENOMEM; | ||
| 304 | |||
| 305 | spin_lock_irqsave(&rtasd_log_lock, s); | ||
| 306 | |||
| 307 | /* if it's 0, then we know we got the last one (the one in NVRAM) */ | ||
| 308 | while (rtas_log_size == 0) { | ||
| 309 | if (file->f_flags & O_NONBLOCK) { | ||
| 310 | spin_unlock_irqrestore(&rtasd_log_lock, s); | ||
| 311 | error = -EAGAIN; | ||
| 312 | goto out; | ||
| 313 | } | ||
| 314 | |||
| 315 | if (!logging_enabled) { | ||
| 316 | spin_unlock_irqrestore(&rtasd_log_lock, s); | ||
| 317 | error = -ENODATA; | ||
| 318 | goto out; | ||
| 319 | } | ||
| 320 | #ifdef CONFIG_PPC64 | ||
| 321 | nvram_clear_error_log(); | ||
| 322 | #endif /* CONFIG_PPC64 */ | ||
| 323 | |||
| 324 | spin_unlock_irqrestore(&rtasd_log_lock, s); | ||
| 325 | error = wait_event_interruptible(rtas_log_wait, rtas_log_size); | ||
| 326 | if (error) | ||
| 327 | goto out; | ||
| 328 | spin_lock_irqsave(&rtasd_log_lock, s); | ||
| 329 | } | ||
| 330 | |||
| 331 | offset = rtas_error_log_buffer_max * (rtas_log_start & LOG_NUMBER_MASK); | ||
| 332 | memcpy(tmp, &rtas_log_buf[offset], count); | ||
| 333 | |||
| 334 | rtas_log_start += 1; | ||
| 335 | rtas_log_size -= 1; | ||
| 336 | spin_unlock_irqrestore(&rtasd_log_lock, s); | ||
| 337 | |||
| 338 | error = copy_to_user(buf, tmp, count) ? -EFAULT : count; | ||
| 339 | out: | ||
| 340 | kfree(tmp); | ||
| 341 | return error; | ||
| 342 | } | ||
| 343 | |||
| 344 | static unsigned int rtas_log_poll(struct file *file, poll_table * wait) | ||
| 345 | { | ||
| 346 | poll_wait(file, &rtas_log_wait, wait); | ||
| 347 | if (rtas_log_size) | ||
| 348 | return POLLIN | POLLRDNORM; | ||
| 349 | return 0; | ||
| 350 | } | ||
| 351 | |||
| 352 | static const struct file_operations proc_rtas_log_operations = { | ||
| 353 | .read = rtas_log_read, | ||
| 354 | .poll = rtas_log_poll, | ||
| 355 | .open = rtas_log_open, | ||
| 356 | .release = rtas_log_release, | ||
| 357 | }; | ||
| 358 | |||
| 359 | static int enable_surveillance(int timeout) | ||
| 360 | { | ||
| 361 | int error; | ||
| 362 | |||
| 363 | error = rtas_set_indicator(SURVEILLANCE_TOKEN, 0, timeout); | ||
| 364 | |||
| 365 | if (error == 0) | ||
| 366 | return 0; | ||
| 367 | |||
| 368 | if (error == -EINVAL) { | ||
| 369 | printk(KERN_DEBUG "rtasd: surveillance not supported\n"); | ||
| 370 | return 0; | ||
| 371 | } | ||
| 372 | |||
| 373 | printk(KERN_ERR "rtasd: could not update surveillance\n"); | ||
| 374 | return -1; | ||
| 375 | } | ||
| 376 | |||
| 377 | static void do_event_scan(void) | ||
| 378 | { | ||
| 379 | int error; | ||
| 380 | do { | ||
| 381 | memset(logdata, 0, rtas_error_log_max); | ||
| 382 | error = rtas_call(event_scan, 4, 1, NULL, | ||
| 383 | RTAS_EVENT_SCAN_ALL_EVENTS, 0, | ||
| 384 | __pa(logdata), rtas_error_log_max); | ||
| 385 | if (error == -1) { | ||
| 386 | printk(KERN_ERR "event-scan failed\n"); | ||
| 387 | break; | ||
| 388 | } | ||
| 389 | |||
| 390 | if (error == 0) | ||
| 391 | pSeries_log_error(logdata, ERR_TYPE_RTAS_LOG, 0); | ||
| 392 | |||
| 393 | } while(error == 0); | ||
| 394 | } | ||
| 395 | |||
| 396 | static void rtas_event_scan(struct work_struct *w); | ||
| 397 | DECLARE_DELAYED_WORK(event_scan_work, rtas_event_scan); | ||
| 398 | |||
| 399 | /* | ||
| 400 | * Delay should be at least one second since some machines have problems if | ||
| 401 | * we call event-scan too quickly. | ||
| 402 | */ | ||
| 403 | static unsigned long event_scan_delay = 1*HZ; | ||
| 404 | static int first_pass = 1; | ||
| 405 | |||
| 406 | static void rtas_event_scan(struct work_struct *w) | ||
| 407 | { | ||
| 408 | unsigned int cpu; | ||
| 409 | |||
| 410 | do_event_scan(); | ||
| 411 | |||
| 412 | get_online_cpus(); | ||
| 413 | |||
| 414 | cpu = next_cpu(smp_processor_id(), cpu_online_map); | ||
| 415 | if (cpu == NR_CPUS) { | ||
| 416 | cpu = first_cpu(cpu_online_map); | ||
| 417 | |||
| 418 | if (first_pass) { | ||
| 419 | first_pass = 0; | ||
| 420 | event_scan_delay = 30*HZ/rtas_event_scan_rate; | ||
| 421 | |||
| 422 | if (surveillance_timeout != -1) { | ||
| 423 | pr_debug("rtasd: enabling surveillance\n"); | ||
| 424 | enable_surveillance(surveillance_timeout); | ||
| 425 | pr_debug("rtasd: surveillance enabled\n"); | ||
| 426 | } | ||
| 427 | } | ||
| 428 | } | ||
| 429 | |||
| 430 | schedule_delayed_work_on(cpu, &event_scan_work, | ||
| 431 | __round_jiffies_relative(event_scan_delay, cpu)); | ||
| 432 | |||
| 433 | put_online_cpus(); | ||
| 434 | } | ||
| 435 | |||
| 436 | #ifdef CONFIG_PPC64 | ||
| 437 | static void retreive_nvram_error_log(void) | ||
| 438 | { | ||
| 439 | unsigned int err_type ; | ||
| 440 | int rc ; | ||
| 441 | |||
| 442 | /* See if we have any error stored in NVRAM */ | ||
| 443 | memset(logdata, 0, rtas_error_log_max); | ||
| 444 | rc = nvram_read_error_log(logdata, rtas_error_log_max, | ||
| 445 | &err_type, &error_log_cnt); | ||
| 446 | /* We can use rtas_log_buf now */ | ||
| 447 | logging_enabled = 1; | ||
| 448 | if (!rc) { | ||
| 449 | if (err_type != ERR_FLAG_ALREADY_LOGGED) { | ||
| 450 | pSeries_log_error(logdata, err_type | ERR_FLAG_BOOT, 0); | ||
| 451 | } | ||
| 452 | } | ||
| 453 | } | ||
| 454 | #else /* CONFIG_PPC64 */ | ||
| 455 | static void retreive_nvram_error_log(void) | ||
| 456 | { | ||
| 457 | } | ||
| 458 | #endif /* CONFIG_PPC64 */ | ||
| 459 | |||
| 460 | static void start_event_scan(void) | ||
| 461 | { | ||
| 462 | printk(KERN_DEBUG "RTAS daemon started\n"); | ||
| 463 | pr_debug("rtasd: will sleep for %d milliseconds\n", | ||
| 464 | (30000 / rtas_event_scan_rate)); | ||
| 465 | |||
| 466 | /* Retreive errors from nvram if any */ | ||
| 467 | retreive_nvram_error_log(); | ||
| 468 | |||
| 469 | schedule_delayed_work_on(first_cpu(cpu_online_map), &event_scan_work, | ||
| 470 | event_scan_delay); | ||
| 471 | } | ||
| 472 | |||
| 473 | static int __init rtas_init(void) | ||
| 474 | { | ||
| 475 | struct proc_dir_entry *entry; | ||
| 476 | |||
| 477 | if (!machine_is(pseries) && !machine_is(chrp)) | ||
| 478 | return 0; | ||
| 479 | |||
| 480 | /* No RTAS */ | ||
| 481 | event_scan = rtas_token("event-scan"); | ||
| 482 | if (event_scan == RTAS_UNKNOWN_SERVICE) { | ||
| 483 | printk(KERN_INFO "rtasd: No event-scan on system\n"); | ||
| 484 | return -ENODEV; | ||
| 485 | } | ||
| 486 | |||
| 487 | rtas_event_scan_rate = rtas_token("rtas-event-scan-rate"); | ||
| 488 | if (rtas_event_scan_rate == RTAS_UNKNOWN_SERVICE) { | ||
| 489 | printk(KERN_ERR "rtasd: no rtas-event-scan-rate on system\n"); | ||
| 490 | return -ENODEV; | ||
| 491 | } | ||
| 492 | |||
| 493 | /* Make room for the sequence number */ | ||
| 494 | rtas_error_log_max = rtas_get_error_log_max(); | ||
| 495 | rtas_error_log_buffer_max = rtas_error_log_max + sizeof(int); | ||
| 496 | |||
| 497 | rtas_log_buf = vmalloc(rtas_error_log_buffer_max*LOG_NUMBER); | ||
| 498 | if (!rtas_log_buf) { | ||
| 499 | printk(KERN_ERR "rtasd: no memory\n"); | ||
| 500 | return -ENOMEM; | ||
| 501 | } | ||
| 502 | |||
| 503 | entry = proc_create("powerpc/rtas/error_log", S_IRUSR, NULL, | ||
| 504 | &proc_rtas_log_operations); | ||
| 505 | if (!entry) | ||
| 506 | printk(KERN_ERR "Failed to create error_log proc entry\n"); | ||
| 507 | |||
| 508 | start_event_scan(); | ||
| 509 | |||
| 510 | return 0; | ||
| 511 | } | ||
| 512 | __initcall(rtas_init); | ||
| 513 | |||
| 514 | static int __init surveillance_setup(char *str) | ||
| 515 | { | ||
| 516 | int i; | ||
| 517 | |||
| 518 | /* We only do surveillance on pseries */ | ||
| 519 | if (!machine_is(pseries)) | ||
| 520 | return 0; | ||
| 521 | |||
| 522 | if (get_option(&str,&i)) { | ||
| 523 | if (i >= 0 && i <= 255) | ||
| 524 | surveillance_timeout = i; | ||
| 525 | } | ||
| 526 | |||
| 527 | return 1; | ||
| 528 | } | ||
| 529 | __setup("surveillance=", surveillance_setup); | ||
| 530 | |||
| 531 | static int __init rtasmsgs_setup(char *str) | ||
| 532 | { | ||
| 533 | if (strcmp(str, "on") == 0) | ||
| 534 | full_rtas_msgs = 1; | ||
| 535 | else if (strcmp(str, "off") == 0) | ||
| 536 | full_rtas_msgs = 0; | ||
| 537 | |||
| 538 | return 1; | ||
| 539 | } | ||
| 540 | __setup("rtasmsgs=", rtasmsgs_setup); | ||
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 4271f7a655a3..48f0a008b20b 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include <linux/lmb.h> | 36 | #include <linux/lmb.h> |
| 37 | #include <linux/of_platform.h> | 37 | #include <linux/of_platform.h> |
| 38 | #include <asm/io.h> | 38 | #include <asm/io.h> |
| 39 | #include <asm/paca.h> | ||
| 39 | #include <asm/prom.h> | 40 | #include <asm/prom.h> |
| 40 | #include <asm/processor.h> | 41 | #include <asm/processor.h> |
| 41 | #include <asm/vdso_datapage.h> | 42 | #include <asm/vdso_datapage.h> |
| @@ -157,7 +158,7 @@ extern u32 cpu_temp_both(unsigned long cpu); | |||
| 157 | #endif /* CONFIG_TAU */ | 158 | #endif /* CONFIG_TAU */ |
| 158 | 159 | ||
| 159 | #ifdef CONFIG_SMP | 160 | #ifdef CONFIG_SMP |
| 160 | DEFINE_PER_CPU(unsigned int, pvr); | 161 | DEFINE_PER_CPU(unsigned int, cpu_pvr); |
| 161 | #endif | 162 | #endif |
| 162 | 163 | ||
| 163 | static int show_cpuinfo(struct seq_file *m, void *v) | 164 | static int show_cpuinfo(struct seq_file *m, void *v) |
| @@ -209,7 +210,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
| 209 | } | 210 | } |
| 210 | 211 | ||
| 211 | #ifdef CONFIG_SMP | 212 | #ifdef CONFIG_SMP |
| 212 | pvr = per_cpu(pvr, cpu_id); | 213 | pvr = per_cpu(cpu_pvr, cpu_id); |
| 213 | #else | 214 | #else |
| 214 | pvr = mfspr(SPRN_PVR); | 215 | pvr = mfspr(SPRN_PVR); |
| 215 | #endif | 216 | #endif |
| @@ -493,6 +494,8 @@ void __init smp_setup_cpu_maps(void) | |||
| 493 | * here will have to be reworked | 494 | * here will have to be reworked |
| 494 | */ | 495 | */ |
| 495 | cpu_init_thread_core_maps(nthreads); | 496 | cpu_init_thread_core_maps(nthreads); |
| 497 | |||
| 498 | free_unused_pacas(); | ||
| 496 | } | 499 | } |
| 497 | #endif /* CONFIG_SMP */ | 500 | #endif /* CONFIG_SMP */ |
| 498 | 501 | ||
| @@ -660,6 +663,7 @@ late_initcall(check_cache_coherency); | |||
| 660 | 663 | ||
| 661 | #ifdef CONFIG_DEBUG_FS | 664 | #ifdef CONFIG_DEBUG_FS |
| 662 | struct dentry *powerpc_debugfs_root; | 665 | struct dentry *powerpc_debugfs_root; |
| 666 | EXPORT_SYMBOL(powerpc_debugfs_root); | ||
| 663 | 667 | ||
| 664 | static int powerpc_debugfs_init(void) | 668 | static int powerpc_debugfs_init(void) |
| 665 | { | 669 | { |
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 53bcf3d792db..8f58986c2ad9 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c | |||
| @@ -39,7 +39,6 @@ | |||
| 39 | #include <asm/serial.h> | 39 | #include <asm/serial.h> |
| 40 | #include <asm/udbg.h> | 40 | #include <asm/udbg.h> |
| 41 | #include <asm/mmu_context.h> | 41 | #include <asm/mmu_context.h> |
| 42 | #include <asm/swiotlb.h> | ||
| 43 | 42 | ||
| 44 | #include "setup.h" | 43 | #include "setup.h" |
| 45 | 44 | ||
| @@ -343,11 +342,6 @@ void __init setup_arch(char **cmdline_p) | |||
| 343 | ppc_md.setup_arch(); | 342 | ppc_md.setup_arch(); |
| 344 | if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab); | 343 | if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab); |
| 345 | 344 | ||
| 346 | #ifdef CONFIG_SWIOTLB | ||
| 347 | if (ppc_swiotlb_enable) | ||
| 348 | swiotlb_init(); | ||
| 349 | #endif | ||
| 350 | |||
| 351 | paging_init(); | 345 | paging_init(); |
| 352 | 346 | ||
| 353 | /* Initialize the MMU context management stuff */ | 347 | /* Initialize the MMU context management stuff */ |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 04f638d82fb3..914389158a9b 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
| @@ -61,7 +61,6 @@ | |||
| 61 | #include <asm/xmon.h> | 61 | #include <asm/xmon.h> |
| 62 | #include <asm/udbg.h> | 62 | #include <asm/udbg.h> |
| 63 | #include <asm/kexec.h> | 63 | #include <asm/kexec.h> |
| 64 | #include <asm/swiotlb.h> | ||
| 65 | #include <asm/mmu_context.h> | 64 | #include <asm/mmu_context.h> |
| 66 | 65 | ||
| 67 | #include "setup.h" | 66 | #include "setup.h" |
| @@ -144,9 +143,9 @@ early_param("smt-enabled", early_smt_enabled); | |||
| 144 | #endif /* CONFIG_SMP */ | 143 | #endif /* CONFIG_SMP */ |
| 145 | 144 | ||
| 146 | /* Put the paca pointer into r13 and SPRG_PACA */ | 145 | /* Put the paca pointer into r13 and SPRG_PACA */ |
| 147 | void __init setup_paca(int cpu) | 146 | static void __init setup_paca(struct paca_struct *new_paca) |
| 148 | { | 147 | { |
| 149 | local_paca = &paca[cpu]; | 148 | local_paca = new_paca; |
| 150 | mtspr(SPRN_SPRG_PACA, local_paca); | 149 | mtspr(SPRN_SPRG_PACA, local_paca); |
| 151 | #ifdef CONFIG_PPC_BOOK3E | 150 | #ifdef CONFIG_PPC_BOOK3E |
| 152 | mtspr(SPRN_SPRG_TLB_EXFRAME, local_paca->extlb); | 151 | mtspr(SPRN_SPRG_TLB_EXFRAME, local_paca->extlb); |
| @@ -176,14 +175,12 @@ void __init early_setup(unsigned long dt_ptr) | |||
| 176 | { | 175 | { |
| 177 | /* -------- printk is _NOT_ safe to use here ! ------- */ | 176 | /* -------- printk is _NOT_ safe to use here ! ------- */ |
| 178 | 177 | ||
| 179 | /* Fill in any unititialised pacas */ | ||
| 180 | initialise_pacas(); | ||
| 181 | |||
| 182 | /* Identify CPU type */ | 178 | /* Identify CPU type */ |
| 183 | identify_cpu(0, mfspr(SPRN_PVR)); | 179 | identify_cpu(0, mfspr(SPRN_PVR)); |
| 184 | 180 | ||
| 185 | /* Assume we're on cpu 0 for now. Don't write to the paca yet! */ | 181 | /* Assume we're on cpu 0 for now. Don't write to the paca yet! */ |
| 186 | setup_paca(0); | 182 | initialise_paca(&boot_paca, 0); |
| 183 | setup_paca(&boot_paca); | ||
| 187 | 184 | ||
| 188 | /* Initialize lockdep early or else spinlocks will blow */ | 185 | /* Initialize lockdep early or else spinlocks will blow */ |
| 189 | lockdep_init(); | 186 | lockdep_init(); |
| @@ -203,7 +200,7 @@ void __init early_setup(unsigned long dt_ptr) | |||
| 203 | early_init_devtree(__va(dt_ptr)); | 200 | early_init_devtree(__va(dt_ptr)); |
| 204 | 201 | ||
| 205 | /* Now we know the logical id of our boot cpu, setup the paca. */ | 202 | /* Now we know the logical id of our boot cpu, setup the paca. */ |
| 206 | setup_paca(boot_cpuid); | 203 | setup_paca(&paca[boot_cpuid]); |
| 207 | 204 | ||
| 208 | /* Fix up paca fields required for the boot cpu */ | 205 | /* Fix up paca fields required for the boot cpu */ |
| 209 | get_paca()->cpu_start = 1; | 206 | get_paca()->cpu_start = 1; |
| @@ -356,11 +353,6 @@ void __init setup_system(void) | |||
| 356 | */ | 353 | */ |
| 357 | initialize_cache_info(); | 354 | initialize_cache_info(); |
| 358 | 355 | ||
| 359 | /* | ||
| 360 | * Initialize irq remapping subsystem | ||
| 361 | */ | ||
| 362 | irq_early_init(); | ||
| 363 | |||
| 364 | #ifdef CONFIG_PPC_RTAS | 356 | #ifdef CONFIG_PPC_RTAS |
| 365 | /* | 357 | /* |
| 366 | * Initialize RTAS if available | 358 | * Initialize RTAS if available |
| @@ -548,11 +540,6 @@ void __init setup_arch(char **cmdline_p) | |||
| 548 | if (ppc_md.setup_arch) | 540 | if (ppc_md.setup_arch) |
| 549 | ppc_md.setup_arch(); | 541 | ppc_md.setup_arch(); |
| 550 | 542 | ||
| 551 | #ifdef CONFIG_SWIOTLB | ||
| 552 | if (ppc_swiotlb_enable) | ||
| 553 | swiotlb_init(); | ||
| 554 | #endif | ||
| 555 | |||
| 556 | paging_init(); | 543 | paging_init(); |
| 557 | 544 | ||
| 558 | /* Initialize the MMU context management stuff */ | 545 | /* Initialize the MMU context management stuff */ |
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index 00b5078da9a3..a0afb555a7c9 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c | |||
| @@ -140,17 +140,15 @@ static int do_signal_pending(sigset_t *oldset, struct pt_regs *regs) | |||
| 140 | return 0; /* no signals delivered */ | 140 | return 0; /* no signals delivered */ |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | #ifndef CONFIG_PPC_ADV_DEBUG_REGS | ||
| 143 | /* | 144 | /* |
| 144 | * Reenable the DABR before delivering the signal to | 145 | * Reenable the DABR before delivering the signal to |
| 145 | * user space. The DABR will have been cleared if it | 146 | * user space. The DABR will have been cleared if it |
| 146 | * triggered inside the kernel. | 147 | * triggered inside the kernel. |
| 147 | */ | 148 | */ |
| 148 | if (current->thread.dabr) { | 149 | if (current->thread.dabr) |
| 149 | set_dabr(current->thread.dabr); | 150 | set_dabr(current->thread.dabr); |
| 150 | #if defined(CONFIG_BOOKE) | ||
| 151 | mtspr(SPRN_DBCR0, current->thread.dbcr0); | ||
| 152 | #endif | 151 | #endif |
| 153 | } | ||
| 154 | 152 | ||
| 155 | if (is32) { | 153 | if (is32) { |
| 156 | if (ka.sa.sa_flags & SA_SIGINFO) | 154 | if (ka.sa.sa_flags & SA_SIGINFO) |
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index d670429a1608..266610119f66 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c | |||
| @@ -1078,7 +1078,7 @@ int sys_debug_setcontext(struct ucontext __user *ctx, | |||
| 1078 | int i; | 1078 | int i; |
| 1079 | unsigned char tmp; | 1079 | unsigned char tmp; |
| 1080 | unsigned long new_msr = regs->msr; | 1080 | unsigned long new_msr = regs->msr; |
| 1081 | #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) | 1081 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
| 1082 | unsigned long new_dbcr0 = current->thread.dbcr0; | 1082 | unsigned long new_dbcr0 = current->thread.dbcr0; |
| 1083 | #endif | 1083 | #endif |
| 1084 | 1084 | ||
| @@ -1087,13 +1087,17 @@ int sys_debug_setcontext(struct ucontext __user *ctx, | |||
| 1087 | return -EFAULT; | 1087 | return -EFAULT; |
| 1088 | switch (op.dbg_type) { | 1088 | switch (op.dbg_type) { |
| 1089 | case SIG_DBG_SINGLE_STEPPING: | 1089 | case SIG_DBG_SINGLE_STEPPING: |
| 1090 | #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) | 1090 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
| 1091 | if (op.dbg_value) { | 1091 | if (op.dbg_value) { |
| 1092 | new_msr |= MSR_DE; | 1092 | new_msr |= MSR_DE; |
| 1093 | new_dbcr0 |= (DBCR0_IDM | DBCR0_IC); | 1093 | new_dbcr0 |= (DBCR0_IDM | DBCR0_IC); |
| 1094 | } else { | 1094 | } else { |
| 1095 | new_msr &= ~MSR_DE; | 1095 | new_dbcr0 &= ~DBCR0_IC; |
| 1096 | new_dbcr0 &= ~(DBCR0_IDM | DBCR0_IC); | 1096 | if (!DBCR_ACTIVE_EVENTS(new_dbcr0, |
| 1097 | current->thread.dbcr1)) { | ||
| 1098 | new_msr &= ~MSR_DE; | ||
| 1099 | new_dbcr0 &= ~DBCR0_IDM; | ||
| 1100 | } | ||
| 1097 | } | 1101 | } |
| 1098 | #else | 1102 | #else |
| 1099 | if (op.dbg_value) | 1103 | if (op.dbg_value) |
| @@ -1103,7 +1107,7 @@ int sys_debug_setcontext(struct ucontext __user *ctx, | |||
| 1103 | #endif | 1107 | #endif |
| 1104 | break; | 1108 | break; |
| 1105 | case SIG_DBG_BRANCH_TRACING: | 1109 | case SIG_DBG_BRANCH_TRACING: |
| 1106 | #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) | 1110 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
| 1107 | return -EINVAL; | 1111 | return -EINVAL; |
| 1108 | #else | 1112 | #else |
| 1109 | if (op.dbg_value) | 1113 | if (op.dbg_value) |
| @@ -1124,7 +1128,7 @@ int sys_debug_setcontext(struct ucontext __user *ctx, | |||
| 1124 | failure is a problem, anyway, and it's very unlikely unless | 1128 | failure is a problem, anyway, and it's very unlikely unless |
| 1125 | the user is really doing something wrong. */ | 1129 | the user is really doing something wrong. */ |
| 1126 | regs->msr = new_msr; | 1130 | regs->msr = new_msr; |
| 1127 | #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) | 1131 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
| 1128 | current->thread.dbcr0 = new_dbcr0; | 1132 | current->thread.dbcr0 = new_dbcr0; |
| 1129 | #endif | 1133 | #endif |
| 1130 | 1134 | ||
diff --git a/arch/powerpc/kernel/smp-tbsync.c b/arch/powerpc/kernel/smp-tbsync.c index a5e54526403d..03e45c4a9ef1 100644 --- a/arch/powerpc/kernel/smp-tbsync.c +++ b/arch/powerpc/kernel/smp-tbsync.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <linux/smp.h> | 10 | #include <linux/smp.h> |
| 11 | #include <linux/unistd.h> | 11 | #include <linux/unistd.h> |
| 12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
| 13 | #include <linux/slab.h> | ||
| 13 | #include <asm/atomic.h> | 14 | #include <asm/atomic.h> |
| 14 | #include <asm/smp.h> | 15 | #include <asm/smp.h> |
| 15 | #include <asm/time.h> | 16 | #include <asm/time.h> |
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 9b86a74d2815..c2ee14498077 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
| @@ -218,6 +218,9 @@ void crash_send_ipi(void (*crash_ipi_callback)(struct pt_regs *)) | |||
| 218 | 218 | ||
| 219 | static void stop_this_cpu(void *dummy) | 219 | static void stop_this_cpu(void *dummy) |
| 220 | { | 220 | { |
| 221 | /* Remove this CPU */ | ||
| 222 | set_cpu_online(smp_processor_id(), false); | ||
| 223 | |||
| 221 | local_irq_disable(); | 224 | local_irq_disable(); |
| 222 | while (1) | 225 | while (1) |
| 223 | ; | 226 | ; |
| @@ -232,7 +235,7 @@ struct thread_info *current_set[NR_CPUS]; | |||
| 232 | 235 | ||
| 233 | static void __devinit smp_store_cpu_info(int id) | 236 | static void __devinit smp_store_cpu_info(int id) |
| 234 | { | 237 | { |
| 235 | per_cpu(pvr, id) = mfspr(SPRN_PVR); | 238 | per_cpu(cpu_pvr, id) = mfspr(SPRN_PVR); |
| 236 | } | 239 | } |
| 237 | 240 | ||
| 238 | static void __init smp_create_idle(unsigned int cpu) | 241 | static void __init smp_create_idle(unsigned int cpu) |
| @@ -616,4 +619,16 @@ void __cpu_die(unsigned int cpu) | |||
| 616 | if (smp_ops->cpu_die) | 619 | if (smp_ops->cpu_die) |
| 617 | smp_ops->cpu_die(cpu); | 620 | smp_ops->cpu_die(cpu); |
| 618 | } | 621 | } |
| 622 | |||
| 623 | static DEFINE_MUTEX(powerpc_cpu_hotplug_driver_mutex); | ||
| 624 | |||
| 625 | void cpu_hotplug_driver_lock() | ||
| 626 | { | ||
| 627 | mutex_lock(&powerpc_cpu_hotplug_driver_mutex); | ||
| 628 | } | ||
| 629 | |||
| 630 | void cpu_hotplug_driver_unlock() | ||
| 631 | { | ||
| 632 | mutex_unlock(&powerpc_cpu_hotplug_driver_mutex); | ||
| 633 | } | ||
| 619 | #endif | 634 | #endif |
diff --git a/arch/powerpc/kernel/softemu8xx.c b/arch/powerpc/kernel/softemu8xx.c index 23c8c5e7dc4d..af0e8290b4fc 100644 --- a/arch/powerpc/kernel/softemu8xx.c +++ b/arch/powerpc/kernel/softemu8xx.c | |||
| @@ -21,7 +21,6 @@ | |||
| 21 | #include <linux/stddef.h> | 21 | #include <linux/stddef.h> |
| 22 | #include <linux/unistd.h> | 22 | #include <linux/unistd.h> |
| 23 | #include <linux/ptrace.h> | 23 | #include <linux/ptrace.h> |
| 24 | #include <linux/slab.h> | ||
| 25 | #include <linux/user.h> | 24 | #include <linux/user.h> |
| 26 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
| 27 | 26 | ||
diff --git a/arch/powerpc/kernel/swsusp_32.S b/arch/powerpc/kernel/swsusp_32.S index b47d8ceffb52..b0754e237438 100644 --- a/arch/powerpc/kernel/swsusp_32.S +++ b/arch/powerpc/kernel/swsusp_32.S | |||
| @@ -303,7 +303,7 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS) | |||
| 303 | lis r4,0x1000 | 303 | lis r4,0x1000 |
| 304 | 1: addic. r4,r4,-0x1000 | 304 | 1: addic. r4,r4,-0x1000 |
| 305 | tlbie r4 | 305 | tlbie r4 |
| 306 | blt 1b | 306 | bgt 1b |
| 307 | sync | 307 | sync |
| 308 | 308 | ||
| 309 | /* restore the MSR and turn on the MMU */ | 309 | /* restore the MSR and turn on the MMU */ |
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c index b97c2d67f4ac..19471a1cef1a 100644 --- a/arch/powerpc/kernel/sys_ppc32.c +++ b/arch/powerpc/kernel/sys_ppc32.c | |||
| @@ -41,6 +41,7 @@ | |||
| 41 | #include <linux/ptrace.h> | 41 | #include <linux/ptrace.h> |
| 42 | #include <linux/elf.h> | 42 | #include <linux/elf.h> |
| 43 | #include <linux/ipc.h> | 43 | #include <linux/ipc.h> |
| 44 | #include <linux/slab.h> | ||
| 44 | 45 | ||
| 45 | #include <asm/ptrace.h> | 46 | #include <asm/ptrace.h> |
| 46 | #include <asm/types.h> | 47 | #include <asm/types.h> |
| @@ -520,58 +521,6 @@ asmlinkage long compat_sys_umask(u32 mask) | |||
| 520 | return sys_umask((int)mask); | 521 | return sys_umask((int)mask); |
| 521 | } | 522 | } |
| 522 | 523 | ||
| 523 | #ifdef CONFIG_SYSCTL_SYSCALL | ||
| 524 | struct __sysctl_args32 { | ||
| 525 | u32 name; | ||
| 526 | int nlen; | ||
| 527 | u32 oldval; | ||
| 528 | u32 oldlenp; | ||
| 529 | u32 newval; | ||
| 530 | u32 newlen; | ||
| 531 | u32 __unused[4]; | ||
| 532 | }; | ||
| 533 | |||
| 534 | asmlinkage long compat_sys_sysctl(struct __sysctl_args32 __user *args) | ||
| 535 | { | ||
| 536 | struct __sysctl_args32 tmp; | ||
| 537 | int error; | ||
| 538 | size_t oldlen; | ||
| 539 | size_t __user *oldlenp = NULL; | ||
| 540 | unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7; | ||
| 541 | |||
| 542 | if (copy_from_user(&tmp, args, sizeof(tmp))) | ||
| 543 | return -EFAULT; | ||
| 544 | |||
| 545 | if (tmp.oldval && tmp.oldlenp) { | ||
| 546 | /* Duh, this is ugly and might not work if sysctl_args | ||
| 547 | is in read-only memory, but do_sysctl does indirectly | ||
| 548 | a lot of uaccess in both directions and we'd have to | ||
| 549 | basically copy the whole sysctl.c here, and | ||
| 550 | glibc's __sysctl uses rw memory for the structure | ||
| 551 | anyway. */ | ||
| 552 | oldlenp = (size_t __user *)addr; | ||
| 553 | if (get_user(oldlen, (compat_size_t __user *)compat_ptr(tmp.oldlenp)) || | ||
| 554 | put_user(oldlen, oldlenp)) | ||
| 555 | return -EFAULT; | ||
| 556 | } | ||
| 557 | |||
| 558 | lock_kernel(); | ||
| 559 | error = do_sysctl(compat_ptr(tmp.name), tmp.nlen, | ||
| 560 | compat_ptr(tmp.oldval), oldlenp, | ||
| 561 | compat_ptr(tmp.newval), tmp.newlen); | ||
| 562 | unlock_kernel(); | ||
| 563 | if (oldlenp) { | ||
| 564 | if (!error) { | ||
| 565 | if (get_user(oldlen, oldlenp) || | ||
| 566 | put_user(oldlen, (compat_size_t __user *)compat_ptr(tmp.oldlenp))) | ||
| 567 | error = -EFAULT; | ||
| 568 | } | ||
| 569 | copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused)); | ||
| 570 | } | ||
| 571 | return error; | ||
| 572 | } | ||
| 573 | #endif | ||
| 574 | |||
| 575 | unsigned long compat_sys_mmap2(unsigned long addr, size_t len, | 524 | unsigned long compat_sys_mmap2(unsigned long addr, size_t len, |
| 576 | unsigned long prot, unsigned long flags, | 525 | unsigned long prot, unsigned long flags, |
| 577 | unsigned long fd, unsigned long pgoff) | 526 | unsigned long fd, unsigned long pgoff) |
diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c index c04832c4a02e..f2496f2faecc 100644 --- a/arch/powerpc/kernel/syscalls.c +++ b/arch/powerpc/kernel/syscalls.c | |||
| @@ -42,105 +42,10 @@ | |||
| 42 | #include <asm/time.h> | 42 | #include <asm/time.h> |
| 43 | #include <asm/unistd.h> | 43 | #include <asm/unistd.h> |
| 44 | 44 | ||
| 45 | /* | ||
| 46 | * sys_ipc() is the de-multiplexer for the SysV IPC calls.. | ||
| 47 | * | ||
| 48 | * This is really horribly ugly. | ||
| 49 | */ | ||
| 50 | int sys_ipc(uint call, int first, unsigned long second, long third, | ||
| 51 | void __user *ptr, long fifth) | ||
| 52 | { | ||
| 53 | int version, ret; | ||
| 54 | |||
| 55 | version = call >> 16; /* hack for backward compatibility */ | ||
| 56 | call &= 0xffff; | ||
| 57 | |||
| 58 | ret = -ENOSYS; | ||
| 59 | switch (call) { | ||
| 60 | case SEMOP: | ||
| 61 | ret = sys_semtimedop(first, (struct sembuf __user *)ptr, | ||
| 62 | (unsigned)second, NULL); | ||
| 63 | break; | ||
| 64 | case SEMTIMEDOP: | ||
| 65 | ret = sys_semtimedop(first, (struct sembuf __user *)ptr, | ||
| 66 | (unsigned)second, | ||
| 67 | (const struct timespec __user *) fifth); | ||
| 68 | break; | ||
| 69 | case SEMGET: | ||
| 70 | ret = sys_semget (first, (int)second, third); | ||
| 71 | break; | ||
| 72 | case SEMCTL: { | ||
| 73 | union semun fourth; | ||
| 74 | |||
| 75 | ret = -EINVAL; | ||
| 76 | if (!ptr) | ||
| 77 | break; | ||
| 78 | if ((ret = get_user(fourth.__pad, (void __user * __user *)ptr))) | ||
| 79 | break; | ||
| 80 | ret = sys_semctl(first, (int)second, third, fourth); | ||
| 81 | break; | ||
| 82 | } | ||
| 83 | case MSGSND: | ||
| 84 | ret = sys_msgsnd(first, (struct msgbuf __user *)ptr, | ||
| 85 | (size_t)second, third); | ||
| 86 | break; | ||
| 87 | case MSGRCV: | ||
| 88 | switch (version) { | ||
| 89 | case 0: { | ||
| 90 | struct ipc_kludge tmp; | ||
| 91 | |||
| 92 | ret = -EINVAL; | ||
| 93 | if (!ptr) | ||
| 94 | break; | ||
| 95 | if ((ret = copy_from_user(&tmp, | ||
| 96 | (struct ipc_kludge __user *) ptr, | ||
| 97 | sizeof (tmp)) ? -EFAULT : 0)) | ||
| 98 | break; | ||
| 99 | ret = sys_msgrcv(first, tmp.msgp, (size_t) second, | ||
| 100 | tmp.msgtyp, third); | ||
| 101 | break; | ||
| 102 | } | ||
| 103 | default: | ||
| 104 | ret = sys_msgrcv (first, (struct msgbuf __user *) ptr, | ||
| 105 | (size_t)second, fifth, third); | ||
| 106 | break; | ||
| 107 | } | ||
| 108 | break; | ||
| 109 | case MSGGET: | ||
| 110 | ret = sys_msgget((key_t)first, (int)second); | ||
| 111 | break; | ||
| 112 | case MSGCTL: | ||
| 113 | ret = sys_msgctl(first, (int)second, | ||
| 114 | (struct msqid_ds __user *)ptr); | ||
| 115 | break; | ||
| 116 | case SHMAT: { | ||
| 117 | ulong raddr; | ||
| 118 | ret = do_shmat(first, (char __user *)ptr, (int)second, &raddr); | ||
| 119 | if (ret) | ||
| 120 | break; | ||
| 121 | ret = put_user(raddr, (ulong __user *) third); | ||
| 122 | break; | ||
| 123 | } | ||
| 124 | case SHMDT: | ||
| 125 | ret = sys_shmdt((char __user *)ptr); | ||
| 126 | break; | ||
| 127 | case SHMGET: | ||
| 128 | ret = sys_shmget(first, (size_t)second, third); | ||
| 129 | break; | ||
| 130 | case SHMCTL: | ||
| 131 | ret = sys_shmctl(first, (int)second, | ||
| 132 | (struct shmid_ds __user *)ptr); | ||
| 133 | break; | ||
| 134 | } | ||
| 135 | |||
| 136 | return ret; | ||
| 137 | } | ||
| 138 | |||
| 139 | static inline unsigned long do_mmap2(unsigned long addr, size_t len, | 45 | static inline unsigned long do_mmap2(unsigned long addr, size_t len, |
| 140 | unsigned long prot, unsigned long flags, | 46 | unsigned long prot, unsigned long flags, |
| 141 | unsigned long fd, unsigned long off, int shift) | 47 | unsigned long fd, unsigned long off, int shift) |
| 142 | { | 48 | { |
| 143 | struct file * file = NULL; | ||
| 144 | unsigned long ret = -EINVAL; | 49 | unsigned long ret = -EINVAL; |
| 145 | 50 | ||
| 146 | if (!arch_validate_prot(prot)) | 51 | if (!arch_validate_prot(prot)) |
| @@ -151,20 +56,8 @@ static inline unsigned long do_mmap2(unsigned long addr, size_t len, | |||
| 151 | goto out; | 56 | goto out; |
| 152 | off >>= shift; | 57 | off >>= shift; |
| 153 | } | 58 | } |
| 154 | |||
| 155 | ret = -EBADF; | ||
| 156 | if (!(flags & MAP_ANONYMOUS)) { | ||
| 157 | if (!(file = fget(fd))) | ||
| 158 | goto out; | ||
| 159 | } | ||
| 160 | 59 | ||
| 161 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | 60 | ret = sys_mmap_pgoff(addr, len, prot, flags, fd, off); |
| 162 | |||
| 163 | down_write(¤t->mm->mmap_sem); | ||
| 164 | ret = do_mmap_pgoff(file, addr, len, prot, flags, off); | ||
| 165 | up_write(¤t->mm->mmap_sem); | ||
| 166 | if (file) | ||
| 167 | fput(file); | ||
| 168 | out: | 61 | out: |
| 169 | return ret; | 62 | return ret; |
| 170 | } | 63 | } |
| @@ -223,76 +116,6 @@ long ppc64_personality(unsigned long personality) | |||
| 223 | } | 116 | } |
| 224 | #endif | 117 | #endif |
| 225 | 118 | ||
| 226 | #ifdef CONFIG_PPC64 | ||
| 227 | #define OVERRIDE_MACHINE (personality(current->personality) == PER_LINUX32) | ||
| 228 | #else | ||
| 229 | #define OVERRIDE_MACHINE 0 | ||
| 230 | #endif | ||
| 231 | |||
| 232 | static inline int override_machine(char __user *mach) | ||
| 233 | { | ||
| 234 | if (OVERRIDE_MACHINE) { | ||
| 235 | /* change ppc64 to ppc */ | ||
| 236 | if (__put_user(0, mach+3) || __put_user(0, mach+4)) | ||
| 237 | return -EFAULT; | ||
| 238 | } | ||
| 239 | return 0; | ||
| 240 | } | ||
| 241 | |||
| 242 | long ppc_newuname(struct new_utsname __user * name) | ||
| 243 | { | ||
| 244 | int err = 0; | ||
| 245 | |||
| 246 | down_read(&uts_sem); | ||
| 247 | if (copy_to_user(name, utsname(), sizeof(*name))) | ||
| 248 | err = -EFAULT; | ||
| 249 | up_read(&uts_sem); | ||
| 250 | if (!err) | ||
| 251 | err = override_machine(name->machine); | ||
| 252 | return err; | ||
| 253 | } | ||
| 254 | |||
| 255 | int sys_uname(struct old_utsname __user *name) | ||
| 256 | { | ||
| 257 | int err = 0; | ||
| 258 | |||
| 259 | down_read(&uts_sem); | ||
| 260 | if (copy_to_user(name, utsname(), sizeof(*name))) | ||
| 261 | err = -EFAULT; | ||
| 262 | up_read(&uts_sem); | ||
| 263 | if (!err) | ||
| 264 | err = override_machine(name->machine); | ||
| 265 | return err; | ||
| 266 | } | ||
| 267 | |||
| 268 | int sys_olduname(struct oldold_utsname __user *name) | ||
| 269 | { | ||
| 270 | int error; | ||
| 271 | |||
| 272 | if (!access_ok(VERIFY_WRITE, name, sizeof(struct oldold_utsname))) | ||
| 273 | return -EFAULT; | ||
| 274 | |||
| 275 | down_read(&uts_sem); | ||
| 276 | error = __copy_to_user(&name->sysname, &utsname()->sysname, | ||
| 277 | __OLD_UTS_LEN); | ||
| 278 | error |= __put_user(0, name->sysname + __OLD_UTS_LEN); | ||
| 279 | error |= __copy_to_user(&name->nodename, &utsname()->nodename, | ||
| 280 | __OLD_UTS_LEN); | ||
| 281 | error |= __put_user(0, name->nodename + __OLD_UTS_LEN); | ||
| 282 | error |= __copy_to_user(&name->release, &utsname()->release, | ||
| 283 | __OLD_UTS_LEN); | ||
| 284 | error |= __put_user(0, name->release + __OLD_UTS_LEN); | ||
| 285 | error |= __copy_to_user(&name->version, &utsname()->version, | ||
| 286 | __OLD_UTS_LEN); | ||
| 287 | error |= __put_user(0, name->version + __OLD_UTS_LEN); | ||
| 288 | error |= __copy_to_user(&name->machine, &utsname()->machine, | ||
| 289 | __OLD_UTS_LEN); | ||
| 290 | error |= override_machine(name->machine); | ||
| 291 | up_read(&uts_sem); | ||
| 292 | |||
| 293 | return error? -EFAULT: 0; | ||
| 294 | } | ||
| 295 | |||
| 296 | long ppc_fadvise64_64(int fd, int advice, u32 offset_high, u32 offset_low, | 119 | long ppc_fadvise64_64(int fd, int advice, u32 offset_high, u32 offset_low, |
| 297 | u32 len_high, u32 len_low) | 120 | u32 len_high, u32 len_low) |
| 298 | { | 121 | { |
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 956ab33fd73f..e235e52dc4fe 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c | |||
| @@ -461,6 +461,25 @@ static void unregister_cpu_online(unsigned int cpu) | |||
| 461 | 461 | ||
| 462 | cacheinfo_cpu_offline(cpu); | 462 | cacheinfo_cpu_offline(cpu); |
| 463 | } | 463 | } |
| 464 | |||
| 465 | #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE | ||
| 466 | ssize_t arch_cpu_probe(const char *buf, size_t count) | ||
| 467 | { | ||
| 468 | if (ppc_md.cpu_probe) | ||
| 469 | return ppc_md.cpu_probe(buf, count); | ||
| 470 | |||
| 471 | return -EINVAL; | ||
| 472 | } | ||
| 473 | |||
| 474 | ssize_t arch_cpu_release(const char *buf, size_t count) | ||
| 475 | { | ||
| 476 | if (ppc_md.cpu_release) | ||
| 477 | return ppc_md.cpu_release(buf, count); | ||
| 478 | |||
| 479 | return -EINVAL; | ||
| 480 | } | ||
| 481 | #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ | ||
| 482 | |||
| 464 | #endif /* CONFIG_HOTPLUG_CPU */ | 483 | #endif /* CONFIG_HOTPLUG_CPU */ |
| 465 | 484 | ||
| 466 | static int __cpuinit sysfs_cpu_notify(struct notifier_block *self, | 485 | static int __cpuinit sysfs_cpu_notify(struct notifier_block *self, |
diff --git a/arch/powerpc/kernel/tau_6xx.c b/arch/powerpc/kernel/tau_6xx.c index c3a56d65c5a9..a753b72efbc0 100644 --- a/arch/powerpc/kernel/tau_6xx.c +++ b/arch/powerpc/kernel/tau_6xx.c | |||
| @@ -59,7 +59,7 @@ void set_thresholds(unsigned long cpu) | |||
| 59 | mtspr(SPRN_THRM1, THRM1_THRES(tau[cpu].low) | THRM1_V | THRM1_TIE | THRM1_TID); | 59 | mtspr(SPRN_THRM1, THRM1_THRES(tau[cpu].low) | THRM1_V | THRM1_TIE | THRM1_TID); |
| 60 | 60 | ||
| 61 | /* setup THRM2, | 61 | /* setup THRM2, |
| 62 | * threshold, valid bit, enable interrupts, interrupt when above threshhold | 62 | * threshold, valid bit, enable interrupts, interrupt when above threshold |
| 63 | */ | 63 | */ |
| 64 | mtspr (SPRN_THRM2, THRM1_THRES(tau[cpu].high) | THRM1_V | THRM1_TIE); | 64 | mtspr (SPRN_THRM2, THRM1_THRES(tau[cpu].high) | THRM1_V | THRM1_TIE); |
| 65 | #else | 65 | #else |
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index a136a11c490d..0441bbdadbd1 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
| @@ -54,6 +54,7 @@ | |||
| 54 | #include <linux/irq.h> | 54 | #include <linux/irq.h> |
| 55 | #include <linux/delay.h> | 55 | #include <linux/delay.h> |
| 56 | #include <linux/perf_event.h> | 56 | #include <linux/perf_event.h> |
| 57 | #include <asm/trace.h> | ||
| 57 | 58 | ||
| 58 | #include <asm/io.h> | 59 | #include <asm/io.h> |
| 59 | #include <asm/processor.h> | 60 | #include <asm/processor.h> |
| @@ -264,10 +265,11 @@ void account_system_vtime(struct task_struct *tsk) | |||
| 264 | account_system_time(tsk, 0, delta, deltascaled); | 265 | account_system_time(tsk, 0, delta, deltascaled); |
| 265 | else | 266 | else |
| 266 | account_idle_time(delta); | 267 | account_idle_time(delta); |
| 267 | per_cpu(cputime_last_delta, smp_processor_id()) = delta; | 268 | __get_cpu_var(cputime_last_delta) = delta; |
| 268 | per_cpu(cputime_scaled_last_delta, smp_processor_id()) = deltascaled; | 269 | __get_cpu_var(cputime_scaled_last_delta) = deltascaled; |
| 269 | local_irq_restore(flags); | 270 | local_irq_restore(flags); |
| 270 | } | 271 | } |
| 272 | EXPORT_SYMBOL_GPL(account_system_vtime); | ||
| 271 | 273 | ||
| 272 | /* | 274 | /* |
| 273 | * Transfer the user and system times accumulated in the paca | 275 | * Transfer the user and system times accumulated in the paca |
| @@ -530,25 +532,60 @@ void __init iSeries_time_init_early(void) | |||
| 530 | } | 532 | } |
| 531 | #endif /* CONFIG_PPC_ISERIES */ | 533 | #endif /* CONFIG_PPC_ISERIES */ |
| 532 | 534 | ||
| 533 | #if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_PPC32) | 535 | #ifdef CONFIG_PERF_EVENTS |
| 534 | DEFINE_PER_CPU(u8, perf_event_pending); | ||
| 535 | 536 | ||
| 536 | void set_perf_event_pending(void) | 537 | /* |
| 538 | * 64-bit uses a byte in the PACA, 32-bit uses a per-cpu variable... | ||
| 539 | */ | ||
| 540 | #ifdef CONFIG_PPC64 | ||
| 541 | static inline unsigned long test_perf_event_pending(void) | ||
| 537 | { | 542 | { |
| 538 | get_cpu_var(perf_event_pending) = 1; | 543 | unsigned long x; |
| 539 | set_dec(1); | 544 | |
| 540 | put_cpu_var(perf_event_pending); | 545 | asm volatile("lbz %0,%1(13)" |
| 546 | : "=r" (x) | ||
| 547 | : "i" (offsetof(struct paca_struct, perf_event_pending))); | ||
| 548 | return x; | ||
| 549 | } | ||
| 550 | |||
| 551 | static inline void set_perf_event_pending_flag(void) | ||
| 552 | { | ||
| 553 | asm volatile("stb %0,%1(13)" : : | ||
| 554 | "r" (1), | ||
| 555 | "i" (offsetof(struct paca_struct, perf_event_pending))); | ||
| 541 | } | 556 | } |
| 542 | 557 | ||
| 558 | static inline void clear_perf_event_pending(void) | ||
| 559 | { | ||
| 560 | asm volatile("stb %0,%1(13)" : : | ||
| 561 | "r" (0), | ||
| 562 | "i" (offsetof(struct paca_struct, perf_event_pending))); | ||
| 563 | } | ||
| 564 | |||
| 565 | #else /* 32-bit */ | ||
| 566 | |||
| 567 | DEFINE_PER_CPU(u8, perf_event_pending); | ||
| 568 | |||
| 569 | #define set_perf_event_pending_flag() __get_cpu_var(perf_event_pending) = 1 | ||
| 543 | #define test_perf_event_pending() __get_cpu_var(perf_event_pending) | 570 | #define test_perf_event_pending() __get_cpu_var(perf_event_pending) |
| 544 | #define clear_perf_event_pending() __get_cpu_var(perf_event_pending) = 0 | 571 | #define clear_perf_event_pending() __get_cpu_var(perf_event_pending) = 0 |
| 545 | 572 | ||
| 546 | #else /* CONFIG_PERF_EVENTS && CONFIG_PPC32 */ | 573 | #endif /* 32 vs 64 bit */ |
| 574 | |||
| 575 | void set_perf_event_pending(void) | ||
| 576 | { | ||
| 577 | preempt_disable(); | ||
| 578 | set_perf_event_pending_flag(); | ||
| 579 | set_dec(1); | ||
| 580 | preempt_enable(); | ||
| 581 | } | ||
| 582 | |||
| 583 | #else /* CONFIG_PERF_EVENTS */ | ||
| 547 | 584 | ||
| 548 | #define test_perf_event_pending() 0 | 585 | #define test_perf_event_pending() 0 |
| 549 | #define clear_perf_event_pending() | 586 | #define clear_perf_event_pending() |
| 550 | 587 | ||
| 551 | #endif /* CONFIG_PERF_EVENTS && CONFIG_PPC32 */ | 588 | #endif /* CONFIG_PERF_EVENTS */ |
| 552 | 589 | ||
| 553 | /* | 590 | /* |
| 554 | * For iSeries shared processors, we have to let the hypervisor | 591 | * For iSeries shared processors, we have to let the hypervisor |
| @@ -571,15 +608,15 @@ void timer_interrupt(struct pt_regs * regs) | |||
| 571 | struct clock_event_device *evt = &decrementer->event; | 608 | struct clock_event_device *evt = &decrementer->event; |
| 572 | u64 now; | 609 | u64 now; |
| 573 | 610 | ||
| 611 | trace_timer_interrupt_entry(regs); | ||
| 612 | |||
| 613 | __get_cpu_var(irq_stat).timer_irqs++; | ||
| 614 | |||
| 574 | /* Ensure a positive value is written to the decrementer, or else | 615 | /* Ensure a positive value is written to the decrementer, or else |
| 575 | * some CPUs will continuue to take decrementer exceptions */ | 616 | * some CPUs will continuue to take decrementer exceptions */ |
| 576 | set_dec(DECREMENTER_MAX); | 617 | set_dec(DECREMENTER_MAX); |
| 577 | 618 | ||
| 578 | #ifdef CONFIG_PPC32 | 619 | #ifdef CONFIG_PPC32 |
| 579 | if (test_perf_event_pending()) { | ||
| 580 | clear_perf_event_pending(); | ||
| 581 | perf_event_do_pending(); | ||
| 582 | } | ||
| 583 | if (atomic_read(&ppc_n_lost_interrupts) != 0) | 620 | if (atomic_read(&ppc_n_lost_interrupts) != 0) |
| 584 | do_IRQ(regs); | 621 | do_IRQ(regs); |
| 585 | #endif | 622 | #endif |
| @@ -590,6 +627,7 @@ void timer_interrupt(struct pt_regs * regs) | |||
| 590 | now = decrementer->next_tb - now; | 627 | now = decrementer->next_tb - now; |
| 591 | if (now <= DECREMENTER_MAX) | 628 | if (now <= DECREMENTER_MAX) |
| 592 | set_dec((int)now); | 629 | set_dec((int)now); |
| 630 | trace_timer_interrupt_exit(regs); | ||
| 593 | return; | 631 | return; |
| 594 | } | 632 | } |
| 595 | old_regs = set_irq_regs(regs); | 633 | old_regs = set_irq_regs(regs); |
| @@ -597,6 +635,11 @@ void timer_interrupt(struct pt_regs * regs) | |||
| 597 | 635 | ||
| 598 | calculate_steal_time(); | 636 | calculate_steal_time(); |
| 599 | 637 | ||
| 638 | if (test_perf_event_pending()) { | ||
| 639 | clear_perf_event_pending(); | ||
| 640 | perf_event_do_pending(); | ||
| 641 | } | ||
| 642 | |||
| 600 | #ifdef CONFIG_PPC_ISERIES | 643 | #ifdef CONFIG_PPC_ISERIES |
| 601 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | 644 | if (firmware_has_feature(FW_FEATURE_ISERIES)) |
| 602 | get_lppaca()->int_dword.fields.decr_int = 0; | 645 | get_lppaca()->int_dword.fields.decr_int = 0; |
| @@ -620,6 +663,8 @@ void timer_interrupt(struct pt_regs * regs) | |||
| 620 | 663 | ||
| 621 | irq_exit(); | 664 | irq_exit(); |
| 622 | set_irq_regs(old_regs); | 665 | set_irq_regs(old_regs); |
| 666 | |||
| 667 | trace_timer_interrupt_exit(regs); | ||
| 623 | } | 668 | } |
| 624 | 669 | ||
| 625 | void wakeup_decrementer(void) | 670 | void wakeup_decrementer(void) |
| @@ -828,7 +873,8 @@ static cycle_t timebase_read(struct clocksource *cs) | |||
| 828 | return (cycle_t)get_tb(); | 873 | return (cycle_t)get_tb(); |
| 829 | } | 874 | } |
| 830 | 875 | ||
| 831 | void update_vsyscall(struct timespec *wall_time, struct clocksource *clock) | 876 | void update_vsyscall(struct timespec *wall_time, struct clocksource *clock, |
| 877 | u32 mult) | ||
| 832 | { | 878 | { |
| 833 | u64 t2x, stamp_xsec; | 879 | u64 t2x, stamp_xsec; |
| 834 | 880 | ||
| @@ -841,7 +887,7 @@ void update_vsyscall(struct timespec *wall_time, struct clocksource *clock) | |||
| 841 | 887 | ||
| 842 | /* XXX this assumes clock->shift == 22 */ | 888 | /* XXX this assumes clock->shift == 22 */ |
| 843 | /* 4611686018 ~= 2^(20+64-22) / 1e9 */ | 889 | /* 4611686018 ~= 2^(20+64-22) / 1e9 */ |
| 844 | t2x = (u64) clock->mult * 4611686018ULL; | 890 | t2x = (u64) mult * 4611686018ULL; |
| 845 | stamp_xsec = (u64) xtime.tv_nsec * XSEC_PER_SEC; | 891 | stamp_xsec = (u64) xtime.tv_nsec * XSEC_PER_SEC; |
| 846 | do_div(stamp_xsec, 1000000000); | 892 | do_div(stamp_xsec, 1000000000); |
| 847 | stamp_xsec += (u64) xtime.tv_sec * XSEC_PER_SEC; | 893 | stamp_xsec += (u64) xtime.tv_sec * XSEC_PER_SEC; |
| @@ -895,12 +941,21 @@ static void decrementer_set_mode(enum clock_event_mode mode, | |||
| 895 | decrementer_set_next_event(DECREMENTER_MAX, dev); | 941 | decrementer_set_next_event(DECREMENTER_MAX, dev); |
| 896 | } | 942 | } |
| 897 | 943 | ||
| 944 | static inline uint64_t div_sc64(unsigned long ticks, unsigned long nsec, | ||
| 945 | int shift) | ||
| 946 | { | ||
| 947 | uint64_t tmp = ((uint64_t)ticks) << shift; | ||
| 948 | |||
| 949 | do_div(tmp, nsec); | ||
| 950 | return tmp; | ||
| 951 | } | ||
| 952 | |||
| 898 | static void __init setup_clockevent_multiplier(unsigned long hz) | 953 | static void __init setup_clockevent_multiplier(unsigned long hz) |
| 899 | { | 954 | { |
| 900 | u64 mult, shift = 32; | 955 | u64 mult, shift = 32; |
| 901 | 956 | ||
| 902 | while (1) { | 957 | while (1) { |
| 903 | mult = div_sc(hz, NSEC_PER_SEC, shift); | 958 | mult = div_sc64(hz, NSEC_PER_SEC, shift); |
| 904 | if (mult && (mult >> 32UL) == 0UL) | 959 | if (mult && (mult >> 32UL) == 0UL) |
| 905 | break; | 960 | break; |
| 906 | 961 | ||
| @@ -918,8 +973,8 @@ static void register_decrementer_clockevent(int cpu) | |||
| 918 | *dec = decrementer_clockevent; | 973 | *dec = decrementer_clockevent; |
| 919 | dec->cpumask = cpumask_of(cpu); | 974 | dec->cpumask = cpumask_of(cpu); |
| 920 | 975 | ||
| 921 | printk(KERN_DEBUG "clockevent: %s mult[%lx] shift[%d] cpu[%d]\n", | 976 | printk_once(KERN_DEBUG "clockevent: %s mult[%x] shift[%d] cpu[%d]\n", |
| 922 | dec->name, dec->mult, dec->shift, cpu); | 977 | dec->name, dec->mult, dec->shift, cpu); |
| 923 | 978 | ||
| 924 | clockevents_register_device(dec); | 979 | clockevents_register_device(dec); |
| 925 | } | 980 | } |
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 6f0ae1a9bfae..29d128eb6c43 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
| @@ -21,7 +21,6 @@ | |||
| 21 | #include <linux/stddef.h> | 21 | #include <linux/stddef.h> |
| 22 | #include <linux/unistd.h> | 22 | #include <linux/unistd.h> |
| 23 | #include <linux/ptrace.h> | 23 | #include <linux/ptrace.h> |
| 24 | #include <linux/slab.h> | ||
| 25 | #include <linux/user.h> | 24 | #include <linux/user.h> |
| 26 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
| 27 | #include <linux/init.h> | 26 | #include <linux/init.h> |
| @@ -60,13 +59,13 @@ | |||
| 60 | #endif | 59 | #endif |
| 61 | 60 | ||
| 62 | #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC) | 61 | #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC) |
| 63 | int (*__debugger)(struct pt_regs *regs); | 62 | int (*__debugger)(struct pt_regs *regs) __read_mostly; |
| 64 | int (*__debugger_ipi)(struct pt_regs *regs); | 63 | int (*__debugger_ipi)(struct pt_regs *regs) __read_mostly; |
| 65 | int (*__debugger_bpt)(struct pt_regs *regs); | 64 | int (*__debugger_bpt)(struct pt_regs *regs) __read_mostly; |
| 66 | int (*__debugger_sstep)(struct pt_regs *regs); | 65 | int (*__debugger_sstep)(struct pt_regs *regs) __read_mostly; |
| 67 | int (*__debugger_iabr_match)(struct pt_regs *regs); | 66 | int (*__debugger_iabr_match)(struct pt_regs *regs) __read_mostly; |
| 68 | int (*__debugger_dabr_match)(struct pt_regs *regs); | 67 | int (*__debugger_dabr_match)(struct pt_regs *regs) __read_mostly; |
| 69 | int (*__debugger_fault_handler)(struct pt_regs *regs); | 68 | int (*__debugger_fault_handler)(struct pt_regs *regs) __read_mostly; |
| 70 | 69 | ||
| 71 | EXPORT_SYMBOL(__debugger); | 70 | EXPORT_SYMBOL(__debugger); |
| 72 | EXPORT_SYMBOL(__debugger_ipi); | 71 | EXPORT_SYMBOL(__debugger_ipi); |
| @@ -102,11 +101,11 @@ static inline void pmac_backlight_unblank(void) { } | |||
| 102 | int die(const char *str, struct pt_regs *regs, long err) | 101 | int die(const char *str, struct pt_regs *regs, long err) |
| 103 | { | 102 | { |
| 104 | static struct { | 103 | static struct { |
| 105 | spinlock_t lock; | 104 | raw_spinlock_t lock; |
| 106 | u32 lock_owner; | 105 | u32 lock_owner; |
| 107 | int lock_owner_depth; | 106 | int lock_owner_depth; |
| 108 | } die = { | 107 | } die = { |
| 109 | .lock = __SPIN_LOCK_UNLOCKED(die.lock), | 108 | .lock = __RAW_SPIN_LOCK_UNLOCKED(die.lock), |
| 110 | .lock_owner = -1, | 109 | .lock_owner = -1, |
| 111 | .lock_owner_depth = 0 | 110 | .lock_owner_depth = 0 |
| 112 | }; | 111 | }; |
| @@ -120,7 +119,7 @@ int die(const char *str, struct pt_regs *regs, long err) | |||
| 120 | 119 | ||
| 121 | if (die.lock_owner != raw_smp_processor_id()) { | 120 | if (die.lock_owner != raw_smp_processor_id()) { |
| 122 | console_verbose(); | 121 | console_verbose(); |
| 123 | spin_lock_irqsave(&die.lock, flags); | 122 | raw_spin_lock_irqsave(&die.lock, flags); |
| 124 | die.lock_owner = smp_processor_id(); | 123 | die.lock_owner = smp_processor_id(); |
| 125 | die.lock_owner_depth = 0; | 124 | die.lock_owner_depth = 0; |
| 126 | bust_spinlocks(1); | 125 | bust_spinlocks(1); |
| @@ -146,6 +145,11 @@ int die(const char *str, struct pt_regs *regs, long err) | |||
| 146 | #endif | 145 | #endif |
| 147 | printk("%s\n", ppc_md.name ? ppc_md.name : ""); | 146 | printk("%s\n", ppc_md.name ? ppc_md.name : ""); |
| 148 | 147 | ||
| 148 | sysfs_printk_last_file(); | ||
| 149 | if (notify_die(DIE_OOPS, str, regs, err, 255, | ||
| 150 | SIGSEGV) == NOTIFY_STOP) | ||
| 151 | return 1; | ||
| 152 | |||
| 149 | print_modules(); | 153 | print_modules(); |
| 150 | show_regs(regs); | 154 | show_regs(regs); |
| 151 | } else { | 155 | } else { |
| @@ -155,7 +159,7 @@ int die(const char *str, struct pt_regs *regs, long err) | |||
| 155 | bust_spinlocks(0); | 159 | bust_spinlocks(0); |
| 156 | die.lock_owner = -1; | 160 | die.lock_owner = -1; |
| 157 | add_taint(TAINT_DIE); | 161 | add_taint(TAINT_DIE); |
| 158 | spin_unlock_irqrestore(&die.lock, flags); | 162 | raw_spin_unlock_irqrestore(&die.lock, flags); |
| 159 | 163 | ||
| 160 | if (kexec_should_crash(current) || | 164 | if (kexec_should_crash(current) || |
| 161 | kexec_sr_activated(smp_processor_id())) | 165 | kexec_sr_activated(smp_processor_id())) |
| @@ -174,6 +178,15 @@ int die(const char *str, struct pt_regs *regs, long err) | |||
| 174 | return 0; | 178 | return 0; |
| 175 | } | 179 | } |
| 176 | 180 | ||
| 181 | void user_single_step_siginfo(struct task_struct *tsk, | ||
| 182 | struct pt_regs *regs, siginfo_t *info) | ||
| 183 | { | ||
| 184 | memset(info, 0, sizeof(*info)); | ||
| 185 | info->si_signo = SIGTRAP; | ||
| 186 | info->si_code = TRAP_TRACE; | ||
| 187 | info->si_addr = (void __user *)regs->nip; | ||
| 188 | } | ||
| 189 | |||
| 177 | void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) | 190 | void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) |
| 178 | { | 191 | { |
| 179 | siginfo_t info; | 192 | siginfo_t info; |
| @@ -198,28 +211,6 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) | |||
| 198 | info.si_code = code; | 211 | info.si_code = code; |
| 199 | info.si_addr = (void __user *) addr; | 212 | info.si_addr = (void __user *) addr; |
| 200 | force_sig_info(signr, &info, current); | 213 | force_sig_info(signr, &info, current); |
| 201 | |||
| 202 | /* | ||
| 203 | * Init gets no signals that it doesn't have a handler for. | ||
| 204 | * That's all very well, but if it has caused a synchronous | ||
| 205 | * exception and we ignore the resulting signal, it will just | ||
| 206 | * generate the same exception over and over again and we get | ||
| 207 | * nowhere. Better to kill it and let the kernel panic. | ||
| 208 | */ | ||
| 209 | if (is_global_init(current)) { | ||
| 210 | __sighandler_t handler; | ||
| 211 | |||
| 212 | spin_lock_irq(¤t->sighand->siglock); | ||
| 213 | handler = current->sighand->action[signr-1].sa.sa_handler; | ||
| 214 | spin_unlock_irq(¤t->sighand->siglock); | ||
| 215 | if (handler == SIG_DFL) { | ||
| 216 | /* init has generated a synchronous exception | ||
| 217 | and it doesn't have a handler for the signal */ | ||
| 218 | printk(KERN_CRIT "init has generated signal %d " | ||
| 219 | "but has no handler for it\n", signr); | ||
| 220 | do_exit(signr); | ||
| 221 | } | ||
| 222 | } | ||
| 223 | } | 214 | } |
| 224 | 215 | ||
| 225 | #ifdef CONFIG_PPC64 | 216 | #ifdef CONFIG_PPC64 |
| @@ -307,7 +298,7 @@ static inline int check_io_access(struct pt_regs *regs) | |||
| 307 | return 0; | 298 | return 0; |
| 308 | } | 299 | } |
| 309 | 300 | ||
| 310 | #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) | 301 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
| 311 | /* On 4xx, the reason for the machine check or program exception | 302 | /* On 4xx, the reason for the machine check or program exception |
| 312 | is in the ESR. */ | 303 | is in the ESR. */ |
| 313 | #define get_reason(regs) ((regs)->dsisr) | 304 | #define get_reason(regs) ((regs)->dsisr) |
| @@ -491,6 +482,8 @@ void machine_check_exception(struct pt_regs *regs) | |||
| 491 | { | 482 | { |
| 492 | int recover = 0; | 483 | int recover = 0; |
| 493 | 484 | ||
| 485 | __get_cpu_var(irq_stat).mce_exceptions++; | ||
| 486 | |||
| 494 | /* See if any machine dependent calls. In theory, we would want | 487 | /* See if any machine dependent calls. In theory, we would want |
| 495 | * to call the CPU first, and call the ppc_md. one if the CPU | 488 | * to call the CPU first, and call the ppc_md. one if the CPU |
| 496 | * one returns a positive number. However there is existing code | 489 | * one returns a positive number. However there is existing code |
| @@ -759,7 +752,7 @@ static int emulate_instruction(struct pt_regs *regs) | |||
| 759 | 752 | ||
| 760 | /* Emulate the mfspr rD, PVR. */ | 753 | /* Emulate the mfspr rD, PVR. */ |
| 761 | if ((instword & PPC_INST_MFSPR_PVR_MASK) == PPC_INST_MFSPR_PVR) { | 754 | if ((instword & PPC_INST_MFSPR_PVR_MASK) == PPC_INST_MFSPR_PVR) { |
| 762 | PPC_WARN_EMULATED(mfpvr); | 755 | PPC_WARN_EMULATED(mfpvr, regs); |
| 763 | rd = (instword >> 21) & 0x1f; | 756 | rd = (instword >> 21) & 0x1f; |
| 764 | regs->gpr[rd] = mfspr(SPRN_PVR); | 757 | regs->gpr[rd] = mfspr(SPRN_PVR); |
| 765 | return 0; | 758 | return 0; |
| @@ -767,7 +760,7 @@ static int emulate_instruction(struct pt_regs *regs) | |||
| 767 | 760 | ||
| 768 | /* Emulating the dcba insn is just a no-op. */ | 761 | /* Emulating the dcba insn is just a no-op. */ |
| 769 | if ((instword & PPC_INST_DCBA_MASK) == PPC_INST_DCBA) { | 762 | if ((instword & PPC_INST_DCBA_MASK) == PPC_INST_DCBA) { |
| 770 | PPC_WARN_EMULATED(dcba); | 763 | PPC_WARN_EMULATED(dcba, regs); |
| 771 | return 0; | 764 | return 0; |
| 772 | } | 765 | } |
| 773 | 766 | ||
| @@ -776,7 +769,7 @@ static int emulate_instruction(struct pt_regs *regs) | |||
| 776 | int shift = (instword >> 21) & 0x1c; | 769 | int shift = (instword >> 21) & 0x1c; |
| 777 | unsigned long msk = 0xf0000000UL >> shift; | 770 | unsigned long msk = 0xf0000000UL >> shift; |
| 778 | 771 | ||
| 779 | PPC_WARN_EMULATED(mcrxr); | 772 | PPC_WARN_EMULATED(mcrxr, regs); |
| 780 | regs->ccr = (regs->ccr & ~msk) | ((regs->xer >> shift) & msk); | 773 | regs->ccr = (regs->ccr & ~msk) | ((regs->xer >> shift) & msk); |
| 781 | regs->xer &= ~0xf0000000UL; | 774 | regs->xer &= ~0xf0000000UL; |
| 782 | return 0; | 775 | return 0; |
| @@ -784,19 +777,19 @@ static int emulate_instruction(struct pt_regs *regs) | |||
| 784 | 777 | ||
| 785 | /* Emulate load/store string insn. */ | 778 | /* Emulate load/store string insn. */ |
| 786 | if ((instword & PPC_INST_STRING_GEN_MASK) == PPC_INST_STRING) { | 779 | if ((instword & PPC_INST_STRING_GEN_MASK) == PPC_INST_STRING) { |
| 787 | PPC_WARN_EMULATED(string); | 780 | PPC_WARN_EMULATED(string, regs); |
| 788 | return emulate_string_inst(regs, instword); | 781 | return emulate_string_inst(regs, instword); |
| 789 | } | 782 | } |
| 790 | 783 | ||
| 791 | /* Emulate the popcntb (Population Count Bytes) instruction. */ | 784 | /* Emulate the popcntb (Population Count Bytes) instruction. */ |
| 792 | if ((instword & PPC_INST_POPCNTB_MASK) == PPC_INST_POPCNTB) { | 785 | if ((instword & PPC_INST_POPCNTB_MASK) == PPC_INST_POPCNTB) { |
| 793 | PPC_WARN_EMULATED(popcntb); | 786 | PPC_WARN_EMULATED(popcntb, regs); |
| 794 | return emulate_popcntb_inst(regs, instword); | 787 | return emulate_popcntb_inst(regs, instword); |
| 795 | } | 788 | } |
| 796 | 789 | ||
| 797 | /* Emulate isel (Integer Select) instruction */ | 790 | /* Emulate isel (Integer Select) instruction */ |
| 798 | if ((instword & PPC_INST_ISEL_MASK) == PPC_INST_ISEL) { | 791 | if ((instword & PPC_INST_ISEL_MASK) == PPC_INST_ISEL) { |
| 799 | PPC_WARN_EMULATED(isel); | 792 | PPC_WARN_EMULATED(isel, regs); |
| 800 | return emulate_isel(regs, instword); | 793 | return emulate_isel(regs, instword); |
| 801 | } | 794 | } |
| 802 | 795 | ||
| @@ -973,6 +966,8 @@ void vsx_unavailable_exception(struct pt_regs *regs) | |||
| 973 | 966 | ||
| 974 | void performance_monitor_exception(struct pt_regs *regs) | 967 | void performance_monitor_exception(struct pt_regs *regs) |
| 975 | { | 968 | { |
| 969 | __get_cpu_var(irq_stat).pmu_irqs++; | ||
| 970 | |||
| 976 | perf_irq(regs); | 971 | perf_irq(regs); |
| 977 | } | 972 | } |
| 978 | 973 | ||
| @@ -995,7 +990,7 @@ void SoftwareEmulation(struct pt_regs *regs) | |||
| 995 | #ifdef CONFIG_MATH_EMULATION | 990 | #ifdef CONFIG_MATH_EMULATION |
| 996 | errcode = do_mathemu(regs); | 991 | errcode = do_mathemu(regs); |
| 997 | if (errcode >= 0) | 992 | if (errcode >= 0) |
| 998 | PPC_WARN_EMULATED(math); | 993 | PPC_WARN_EMULATED(math, regs); |
| 999 | 994 | ||
| 1000 | switch (errcode) { | 995 | switch (errcode) { |
| 1001 | case 0: | 996 | case 0: |
| @@ -1018,7 +1013,7 @@ void SoftwareEmulation(struct pt_regs *regs) | |||
| 1018 | #elif defined(CONFIG_8XX_MINIMAL_FPEMU) | 1013 | #elif defined(CONFIG_8XX_MINIMAL_FPEMU) |
| 1019 | errcode = Soft_emulate_8xx(regs); | 1014 | errcode = Soft_emulate_8xx(regs); |
| 1020 | if (errcode >= 0) | 1015 | if (errcode >= 0) |
| 1021 | PPC_WARN_EMULATED(8xx); | 1016 | PPC_WARN_EMULATED(8xx, regs); |
| 1022 | 1017 | ||
| 1023 | switch (errcode) { | 1018 | switch (errcode) { |
| 1024 | case 0: | 1019 | case 0: |
| @@ -1037,10 +1032,69 @@ void SoftwareEmulation(struct pt_regs *regs) | |||
| 1037 | } | 1032 | } |
| 1038 | #endif /* CONFIG_8xx */ | 1033 | #endif /* CONFIG_8xx */ |
| 1039 | 1034 | ||
| 1040 | #if defined(CONFIG_40x) || defined(CONFIG_BOOKE) | 1035 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
| 1036 | static void handle_debug(struct pt_regs *regs, unsigned long debug_status) | ||
| 1037 | { | ||
| 1038 | int changed = 0; | ||
| 1039 | /* | ||
| 1040 | * Determine the cause of the debug event, clear the | ||
| 1041 | * event flags and send a trap to the handler. Torez | ||
| 1042 | */ | ||
| 1043 | if (debug_status & (DBSR_DAC1R | DBSR_DAC1W)) { | ||
| 1044 | dbcr_dac(current) &= ~(DBCR_DAC1R | DBCR_DAC1W); | ||
| 1045 | #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE | ||
| 1046 | current->thread.dbcr2 &= ~DBCR2_DAC12MODE; | ||
| 1047 | #endif | ||
| 1048 | do_send_trap(regs, mfspr(SPRN_DAC1), debug_status, TRAP_HWBKPT, | ||
| 1049 | 5); | ||
| 1050 | changed |= 0x01; | ||
| 1051 | } else if (debug_status & (DBSR_DAC2R | DBSR_DAC2W)) { | ||
| 1052 | dbcr_dac(current) &= ~(DBCR_DAC2R | DBCR_DAC2W); | ||
| 1053 | do_send_trap(regs, mfspr(SPRN_DAC2), debug_status, TRAP_HWBKPT, | ||
| 1054 | 6); | ||
| 1055 | changed |= 0x01; | ||
| 1056 | } else if (debug_status & DBSR_IAC1) { | ||
| 1057 | current->thread.dbcr0 &= ~DBCR0_IAC1; | ||
| 1058 | dbcr_iac_range(current) &= ~DBCR_IAC12MODE; | ||
| 1059 | do_send_trap(regs, mfspr(SPRN_IAC1), debug_status, TRAP_HWBKPT, | ||
| 1060 | 1); | ||
| 1061 | changed |= 0x01; | ||
| 1062 | } else if (debug_status & DBSR_IAC2) { | ||
| 1063 | current->thread.dbcr0 &= ~DBCR0_IAC2; | ||
| 1064 | do_send_trap(regs, mfspr(SPRN_IAC2), debug_status, TRAP_HWBKPT, | ||
| 1065 | 2); | ||
| 1066 | changed |= 0x01; | ||
| 1067 | } else if (debug_status & DBSR_IAC3) { | ||
| 1068 | current->thread.dbcr0 &= ~DBCR0_IAC3; | ||
| 1069 | dbcr_iac_range(current) &= ~DBCR_IAC34MODE; | ||
| 1070 | do_send_trap(regs, mfspr(SPRN_IAC3), debug_status, TRAP_HWBKPT, | ||
| 1071 | 3); | ||
| 1072 | changed |= 0x01; | ||
| 1073 | } else if (debug_status & DBSR_IAC4) { | ||
| 1074 | current->thread.dbcr0 &= ~DBCR0_IAC4; | ||
| 1075 | do_send_trap(regs, mfspr(SPRN_IAC4), debug_status, TRAP_HWBKPT, | ||
| 1076 | 4); | ||
| 1077 | changed |= 0x01; | ||
| 1078 | } | ||
| 1079 | /* | ||
| 1080 | * At the point this routine was called, the MSR(DE) was turned off. | ||
| 1081 | * Check all other debug flags and see if that bit needs to be turned | ||
| 1082 | * back on or not. | ||
| 1083 | */ | ||
| 1084 | if (DBCR_ACTIVE_EVENTS(current->thread.dbcr0, current->thread.dbcr1)) | ||
| 1085 | regs->msr |= MSR_DE; | ||
| 1086 | else | ||
| 1087 | /* Make sure the IDM flag is off */ | ||
| 1088 | current->thread.dbcr0 &= ~DBCR0_IDM; | ||
| 1089 | |||
| 1090 | if (changed & 0x01) | ||
| 1091 | mtspr(SPRN_DBCR0, current->thread.dbcr0); | ||
| 1092 | } | ||
| 1041 | 1093 | ||
| 1042 | void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status) | 1094 | void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status) |
| 1043 | { | 1095 | { |
| 1096 | current->thread.dbsr = debug_status; | ||
| 1097 | |||
| 1044 | /* Hack alert: On BookE, Branch Taken stops on the branch itself, while | 1098 | /* Hack alert: On BookE, Branch Taken stops on the branch itself, while |
| 1045 | * on server, it stops on the target of the branch. In order to simulate | 1099 | * on server, it stops on the target of the branch. In order to simulate |
| 1046 | * the server behaviour, we thus restart right away with a single step | 1100 | * the server behaviour, we thus restart right away with a single step |
| @@ -1084,29 +1138,23 @@ void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status) | |||
| 1084 | if (debugger_sstep(regs)) | 1138 | if (debugger_sstep(regs)) |
| 1085 | return; | 1139 | return; |
| 1086 | 1140 | ||
| 1087 | if (user_mode(regs)) | ||
| 1088 | current->thread.dbcr0 &= ~(DBCR0_IC); | ||
| 1089 | |||
| 1090 | _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip); | ||
| 1091 | } else if (debug_status & (DBSR_DAC1R | DBSR_DAC1W)) { | ||
| 1092 | regs->msr &= ~MSR_DE; | ||
| 1093 | |||
| 1094 | if (user_mode(regs)) { | 1141 | if (user_mode(regs)) { |
| 1095 | current->thread.dbcr0 &= ~(DBSR_DAC1R | DBSR_DAC1W | | 1142 | current->thread.dbcr0 &= ~DBCR0_IC; |
| 1096 | DBCR0_IDM); | 1143 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
| 1097 | } else { | 1144 | if (DBCR_ACTIVE_EVENTS(current->thread.dbcr0, |
| 1098 | /* Disable DAC interupts */ | 1145 | current->thread.dbcr1)) |
| 1099 | mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~(DBSR_DAC1R | | 1146 | regs->msr |= MSR_DE; |
| 1100 | DBSR_DAC1W | DBCR0_IDM)); | 1147 | else |
| 1101 | 1148 | /* Make sure the IDM bit is off */ | |
| 1102 | /* Clear the DAC event */ | 1149 | current->thread.dbcr0 &= ~DBCR0_IDM; |
| 1103 | mtspr(SPRN_DBSR, (DBSR_DAC1R | DBSR_DAC1W)); | 1150 | #endif |
| 1104 | } | 1151 | } |
| 1105 | /* Setup and send the trap to the handler */ | 1152 | |
| 1106 | do_dabr(regs, mfspr(SPRN_DAC1), debug_status); | 1153 | _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip); |
| 1107 | } | 1154 | } else |
| 1155 | handle_debug(regs, debug_status); | ||
| 1108 | } | 1156 | } |
| 1109 | #endif /* CONFIG_4xx || CONFIG_BOOKE */ | 1157 | #endif /* CONFIG_PPC_ADV_DEBUG_REGS */ |
| 1110 | 1158 | ||
| 1111 | #if !defined(CONFIG_TAU_INT) | 1159 | #if !defined(CONFIG_TAU_INT) |
| 1112 | void TAUException(struct pt_regs *regs) | 1160 | void TAUException(struct pt_regs *regs) |
| @@ -1129,7 +1177,7 @@ void altivec_assist_exception(struct pt_regs *regs) | |||
| 1129 | 1177 | ||
| 1130 | flush_altivec_to_thread(current); | 1178 | flush_altivec_to_thread(current); |
| 1131 | 1179 | ||
| 1132 | PPC_WARN_EMULATED(altivec); | 1180 | PPC_WARN_EMULATED(altivec, regs); |
| 1133 | err = emulate_altivec(regs); | 1181 | err = emulate_altivec(regs); |
| 1134 | if (err == 0) { | 1182 | if (err == 0) { |
| 1135 | regs->nip += 4; /* skip emulated instruction */ | 1183 | regs->nip += 4; /* skip emulated instruction */ |
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c index fc9af47e2128..e39cad83c884 100644 --- a/arch/powerpc/kernel/udbg.c +++ b/arch/powerpc/kernel/udbg.c | |||
| @@ -60,6 +60,8 @@ void __init udbg_early_init(void) | |||
| 60 | udbg_init_40x_realmode(); | 60 | udbg_init_40x_realmode(); |
| 61 | #elif defined(CONFIG_PPC_EARLY_DEBUG_CPM) | 61 | #elif defined(CONFIG_PPC_EARLY_DEBUG_CPM) |
| 62 | udbg_init_cpm(); | 62 | udbg_init_cpm(); |
| 63 | #elif defined(CONFIG_PPC_EARLY_DEBUG_USBGECKO) | ||
| 64 | udbg_init_usbgecko(); | ||
| 63 | #endif | 65 | #endif |
| 64 | 66 | ||
| 65 | #ifdef CONFIG_PPC_EARLY_DEBUG | 67 | #ifdef CONFIG_PPC_EARLY_DEBUG |
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index 137dc22afa42..d84d19224a95 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c | |||
| @@ -721,7 +721,7 @@ static int __init vdso_init(void) | |||
| 721 | 721 | ||
| 722 | #ifdef CONFIG_PPC64 | 722 | #ifdef CONFIG_PPC64 |
| 723 | /* | 723 | /* |
| 724 | * Fill up the "systemcfg" stuff for backward compatiblity | 724 | * Fill up the "systemcfg" stuff for backward compatibility |
| 725 | */ | 725 | */ |
| 726 | strcpy((char *)vdso_data->eye_catcher, "SYSTEMCFG:PPC64"); | 726 | strcpy((char *)vdso_data->eye_catcher, "SYSTEMCFG:PPC64"); |
| 727 | vdso_data->version.major = SYSTEMCFG_MAJOR; | 727 | vdso_data->version.major = SYSTEMCFG_MAJOR; |
diff --git a/arch/powerpc/kernel/vector.S b/arch/powerpc/kernel/vector.S index 67b6916f0e94..fe460482fa68 100644 --- a/arch/powerpc/kernel/vector.S +++ b/arch/powerpc/kernel/vector.S | |||
| @@ -58,7 +58,7 @@ _GLOBAL(load_up_altivec) | |||
| 58 | * all 1's | 58 | * all 1's |
| 59 | */ | 59 | */ |
| 60 | mfspr r4,SPRN_VRSAVE | 60 | mfspr r4,SPRN_VRSAVE |
| 61 | cmpdi 0,r4,0 | 61 | cmpwi 0,r4,0 |
| 62 | bne+ 1f | 62 | bne+ 1f |
| 63 | li r4,-1 | 63 | li r4,-1 |
| 64 | mtspr SPRN_VRSAVE,r4 | 64 | mtspr SPRN_VRSAVE,r4 |
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index 77f64218abf3..82237176a2a3 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/types.h> | 17 | #include <linux/types.h> |
| 18 | #include <linux/device.h> | 18 | #include <linux/device.h> |
| 19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
| 20 | #include <linux/slab.h> | ||
| 20 | #include <linux/console.h> | 21 | #include <linux/console.h> |
| 21 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 22 | #include <linux/mm.h> | 23 | #include <linux/mm.h> |
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index 27735a7ac12b..dcd01c82e701 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S | |||
| @@ -38,6 +38,9 @@ jiffies = jiffies_64 + 4; | |||
| 38 | #endif | 38 | #endif |
| 39 | SECTIONS | 39 | SECTIONS |
| 40 | { | 40 | { |
| 41 | . = 0; | ||
| 42 | reloc_start = .; | ||
| 43 | |||
| 41 | . = KERNELBASE; | 44 | . = KERNELBASE; |
| 42 | 45 | ||
| 43 | /* | 46 | /* |
