diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-09-07 02:19:51 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-09-07 02:19:51 -0400 |
commit | a1922ed661ab2c1637d0b10cde933bd9cd33d965 (patch) | |
tree | 0f1777542b385ebefd30b3586d830fd8ed6fda5b /arch/powerpc/kernel | |
parent | 75e33751ca8bbb72dd6f1a74d2810ddc8cbe4bdf (diff) | |
parent | d28daf923ac5e4a0d7cecebae56f3e339189366b (diff) |
Merge branch 'tracing/core' into tracing/hw-breakpoints
Conflicts:
arch/Kconfig
kernel/trace/trace.h
Merge reason: resolve the conflicts, plus adopt to the new
ring-buffer APIs.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/powerpc/kernel')
26 files changed, 1209 insertions, 346 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 612b0c4dc26d..b73396b93905 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -4,6 +4,8 @@ | |||
4 | 4 | ||
5 | CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"' | 5 | CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"' |
6 | 6 | ||
7 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | ||
8 | |||
7 | ifeq ($(CONFIG_PPC64),y) | 9 | ifeq ($(CONFIG_PPC64),y) |
8 | CFLAGS_prom_init.o += -mno-minimal-toc | 10 | CFLAGS_prom_init.o += -mno-minimal-toc |
9 | endif | 11 | endif |
@@ -95,9 +97,10 @@ obj64-$(CONFIG_AUDIT) += compat_audit.o | |||
95 | 97 | ||
96 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o | 98 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o |
97 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o | 99 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o |
98 | obj-$(CONFIG_PERF_COUNTERS) += perf_counter.o power4-pmu.o ppc970-pmu.o \ | 100 | obj-$(CONFIG_PPC_PERF_CTRS) += perf_counter.o |
99 | power5-pmu.o power5+-pmu.o power6-pmu.o \ | 101 | obj64-$(CONFIG_PPC_PERF_CTRS) += power4-pmu.o ppc970-pmu.o power5-pmu.o \ |
100 | power7-pmu.o | 102 | power5+-pmu.o power6-pmu.o power7-pmu.o |
103 | obj32-$(CONFIG_PPC_PERF_CTRS) += mpc7450-pmu.o | ||
101 | 104 | ||
102 | obj-$(CONFIG_8XX_MINIMAL_FPEMU) += softemu8xx.o | 105 | obj-$(CONFIG_8XX_MINIMAL_FPEMU) += softemu8xx.o |
103 | 106 | ||
@@ -106,6 +109,7 @@ obj-y += iomap.o | |||
106 | endif | 109 | endif |
107 | 110 | ||
108 | obj-$(CONFIG_PPC64) += $(obj64-y) | 111 | obj-$(CONFIG_PPC64) += $(obj64-y) |
112 | obj-$(CONFIG_PPC32) += $(obj32-y) | ||
109 | 113 | ||
110 | ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC),) | 114 | ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC),) |
111 | obj-y += ppc_save_regs.o | 115 | obj-y += ppc_save_regs.o |
diff --git a/arch/powerpc/kernel/cpu_setup_6xx.S b/arch/powerpc/kernel/cpu_setup_6xx.S index 54f767e31a1a..1e9949e68856 100644 --- a/arch/powerpc/kernel/cpu_setup_6xx.S +++ b/arch/powerpc/kernel/cpu_setup_6xx.S | |||
@@ -239,6 +239,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_L3CR) | |||
239 | ori r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE | 239 | ori r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE |
240 | ori r11,r11,HID0_LRSTK | HID0_BTIC | 240 | ori r11,r11,HID0_LRSTK | HID0_BTIC |
241 | oris r11,r11,HID0_DPM@h | 241 | oris r11,r11,HID0_DPM@h |
242 | BEGIN_MMU_FTR_SECTION | ||
243 | oris r11,r11,HID0_HIGH_BAT@h | ||
244 | END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS) | ||
242 | BEGIN_FTR_SECTION | 245 | BEGIN_FTR_SECTION |
243 | xori r11,r11,HID0_BTIC | 246 | xori r11,r11,HID0_BTIC |
244 | END_FTR_SECTION_IFSET(CPU_FTR_NO_BTIC) | 247 | END_FTR_SECTION_IFSET(CPU_FTR_NO_BTIC) |
diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S b/arch/powerpc/kernel/cpu_setup_fsl_booke.S index eb4b9adcedb4..0adb50ad8031 100644 --- a/arch/powerpc/kernel/cpu_setup_fsl_booke.S +++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S | |||
@@ -17,6 +17,40 @@ | |||
17 | #include <asm/cputable.h> | 17 | #include <asm/cputable.h> |
18 | #include <asm/ppc_asm.h> | 18 | #include <asm/ppc_asm.h> |
19 | 19 | ||
20 | _GLOBAL(__e500_icache_setup) | ||
21 | mfspr r0, SPRN_L1CSR1 | ||
22 | andi. r3, r0, L1CSR1_ICE | ||
23 | bnelr /* Already enabled */ | ||
24 | oris r0, r0, L1CSR1_CPE@h | ||
25 | ori r0, r0, (L1CSR1_ICFI | L1CSR1_ICLFR | L1CSR1_ICE) | ||
26 | mtspr SPRN_L1CSR1, r0 /* Enable I-Cache */ | ||
27 | isync | ||
28 | blr | ||
29 | |||
30 | _GLOBAL(__e500_dcache_setup) | ||
31 | mfspr r0, SPRN_L1CSR0 | ||
32 | andi. r3, r0, L1CSR0_DCE | ||
33 | bnelr /* Already enabled */ | ||
34 | msync | ||
35 | isync | ||
36 | li r0, 0 | ||
37 | mtspr SPRN_L1CSR0, r0 /* Disable */ | ||
38 | msync | ||
39 | isync | ||
40 | li r0, (L1CSR0_DCFI | L1CSR0_CLFC) | ||
41 | mtspr SPRN_L1CSR0, r0 /* Invalidate */ | ||
42 | isync | ||
43 | 1: mfspr r0, SPRN_L1CSR0 | ||
44 | andi. r3, r0, L1CSR0_CLFC | ||
45 | bne+ 1b /* Wait for lock bits reset */ | ||
46 | oris r0, r0, L1CSR0_CPE@h | ||
47 | ori r0, r0, L1CSR0_DCE | ||
48 | msync | ||
49 | isync | ||
50 | mtspr SPRN_L1CSR0, r0 /* Enable */ | ||
51 | isync | ||
52 | blr | ||
53 | |||
20 | _GLOBAL(__setup_cpu_e200) | 54 | _GLOBAL(__setup_cpu_e200) |
21 | /* enable dedicated debug exception handling resources (Debug APU) */ | 55 | /* enable dedicated debug exception handling resources (Debug APU) */ |
22 | mfspr r3,SPRN_HID0 | 56 | mfspr r3,SPRN_HID0 |
@@ -25,7 +59,16 @@ _GLOBAL(__setup_cpu_e200) | |||
25 | b __setup_e200_ivors | 59 | b __setup_e200_ivors |
26 | _GLOBAL(__setup_cpu_e500v1) | 60 | _GLOBAL(__setup_cpu_e500v1) |
27 | _GLOBAL(__setup_cpu_e500v2) | 61 | _GLOBAL(__setup_cpu_e500v2) |
28 | b __setup_e500_ivors | 62 | mflr r4 |
63 | bl __e500_icache_setup | ||
64 | bl __e500_dcache_setup | ||
65 | bl __setup_e500_ivors | ||
66 | mtlr r4 | ||
67 | blr | ||
29 | _GLOBAL(__setup_cpu_e500mc) | 68 | _GLOBAL(__setup_cpu_e500mc) |
30 | b __setup_e500mc_ivors | 69 | mflr r4 |
31 | 70 | bl __e500_icache_setup | |
71 | bl __e500_dcache_setup | ||
72 | bl __setup_e500mc_ivors | ||
73 | mtlr r4 | ||
74 | blr | ||
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c index 20a60d661ba8..ccf129d47d84 100644 --- a/arch/powerpc/kernel/dma.c +++ b/arch/powerpc/kernel/dma.c | |||
@@ -7,6 +7,7 @@ | |||
7 | 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/lmb.h> | ||
10 | #include <asm/bug.h> | 11 | #include <asm/bug.h> |
11 | #include <asm/abs_addr.h> | 12 | #include <asm/abs_addr.h> |
12 | 13 | ||
@@ -90,11 +91,10 @@ static void dma_direct_unmap_sg(struct device *dev, struct scatterlist *sg, | |||
90 | static int dma_direct_dma_supported(struct device *dev, u64 mask) | 91 | static int dma_direct_dma_supported(struct device *dev, u64 mask) |
91 | { | 92 | { |
92 | #ifdef CONFIG_PPC64 | 93 | #ifdef CONFIG_PPC64 |
93 | /* Could be improved to check for memory though it better be | 94 | /* Could be improved so platforms can set the limit in case |
94 | * done via some global so platforms can set the limit in case | ||
95 | * they have limited DMA windows | 95 | * they have limited DMA windows |
96 | */ | 96 | */ |
97 | return mask >= DMA_BIT_MASK(32); | 97 | return mask >= (lmb_end_of_DRAM() - 1); |
98 | #else | 98 | #else |
99 | return 1; | 99 | return 1; |
100 | #endif | 100 | #endif |
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 4dd38f129153..3cadba60a4b6 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S | |||
@@ -191,11 +191,49 @@ transfer_to_handler_cont: | |||
191 | mflr r9 | 191 | mflr r9 |
192 | lwz r11,0(r9) /* virtual address of handler */ | 192 | lwz r11,0(r9) /* virtual address of handler */ |
193 | lwz r9,4(r9) /* where to go when done */ | 193 | lwz r9,4(r9) /* where to go when done */ |
194 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
195 | lis r12,reenable_mmu@h | ||
196 | ori r12,r12,reenable_mmu@l | ||
197 | mtspr SPRN_SRR0,r12 | ||
198 | mtspr SPRN_SRR1,r10 | ||
199 | SYNC | ||
200 | RFI | ||
201 | reenable_mmu: /* re-enable mmu so we can */ | ||
202 | mfmsr r10 | ||
203 | lwz r12,_MSR(r1) | ||
204 | xor r10,r10,r12 | ||
205 | andi. r10,r10,MSR_EE /* Did EE change? */ | ||
206 | beq 1f | ||
207 | |||
208 | /* Save handler and return address into the 2 unused words | ||
209 | * of the STACK_FRAME_OVERHEAD (sneak sneak sneak). Everything | ||
210 | * else can be recovered from the pt_regs except r3 which for | ||
211 | * normal interrupts has been set to pt_regs and for syscalls | ||
212 | * is an argument, so we temporarily use ORIG_GPR3 to save it | ||
213 | */ | ||
214 | stw r9,8(r1) | ||
215 | stw r11,12(r1) | ||
216 | stw r3,ORIG_GPR3(r1) | ||
217 | bl trace_hardirqs_off | ||
218 | lwz r0,GPR0(r1) | ||
219 | lwz r3,ORIG_GPR3(r1) | ||
220 | lwz r4,GPR4(r1) | ||
221 | lwz r5,GPR5(r1) | ||
222 | lwz r6,GPR6(r1) | ||
223 | lwz r7,GPR7(r1) | ||
224 | lwz r8,GPR8(r1) | ||
225 | lwz r9,8(r1) | ||
226 | lwz r11,12(r1) | ||
227 | 1: mtctr r11 | ||
228 | mtlr r9 | ||
229 | bctr /* jump to handler */ | ||
230 | #else /* CONFIG_TRACE_IRQFLAGS */ | ||
194 | mtspr SPRN_SRR0,r11 | 231 | mtspr SPRN_SRR0,r11 |
195 | mtspr SPRN_SRR1,r10 | 232 | mtspr SPRN_SRR1,r10 |
196 | mtlr r9 | 233 | mtlr r9 |
197 | SYNC | 234 | SYNC |
198 | RFI /* jump to handler, enable MMU */ | 235 | RFI /* jump to handler, enable MMU */ |
236 | #endif /* CONFIG_TRACE_IRQFLAGS */ | ||
199 | 237 | ||
200 | #if defined (CONFIG_6xx) || defined(CONFIG_E500) | 238 | #if defined (CONFIG_6xx) || defined(CONFIG_E500) |
201 | 4: rlwinm r12,r12,0,~_TLF_NAPPING | 239 | 4: rlwinm r12,r12,0,~_TLF_NAPPING |
@@ -251,6 +289,31 @@ _GLOBAL(DoSyscall) | |||
251 | #ifdef SHOW_SYSCALLS | 289 | #ifdef SHOW_SYSCALLS |
252 | bl do_show_syscall | 290 | bl do_show_syscall |
253 | #endif /* SHOW_SYSCALLS */ | 291 | #endif /* SHOW_SYSCALLS */ |
292 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
293 | /* Return from syscalls can (and generally will) hard enable | ||
294 | * interrupts. You aren't supposed to call a syscall with | ||
295 | * interrupts disabled in the first place. However, to ensure | ||
296 | * that we get it right vs. lockdep if it happens, we force | ||
297 | * that hard enable here with appropriate tracing if we see | ||
298 | * that we have been called with interrupts off | ||
299 | */ | ||
300 | mfmsr r11 | ||
301 | andi. r12,r11,MSR_EE | ||
302 | bne+ 1f | ||
303 | /* We came in with interrupts disabled, we enable them now */ | ||
304 | bl trace_hardirqs_on | ||
305 | mfmsr r11 | ||
306 | lwz r0,GPR0(r1) | ||
307 | lwz r3,GPR3(r1) | ||
308 | lwz r4,GPR4(r1) | ||
309 | ori r11,r11,MSR_EE | ||
310 | lwz r5,GPR5(r1) | ||
311 | lwz r6,GPR6(r1) | ||
312 | lwz r7,GPR7(r1) | ||
313 | lwz r8,GPR8(r1) | ||
314 | mtmsr r11 | ||
315 | 1: | ||
316 | #endif /* CONFIG_TRACE_IRQFLAGS */ | ||
254 | rlwinm r10,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */ | 317 | rlwinm r10,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */ |
255 | lwz r11,TI_FLAGS(r10) | 318 | lwz r11,TI_FLAGS(r10) |
256 | andi. r11,r11,_TIF_SYSCALL_T_OR_A | 319 | andi. r11,r11,_TIF_SYSCALL_T_OR_A |
@@ -275,6 +338,7 @@ ret_from_syscall: | |||
275 | rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */ | 338 | rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */ |
276 | /* disable interrupts so current_thread_info()->flags can't change */ | 339 | /* disable interrupts so current_thread_info()->flags can't change */ |
277 | LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */ | 340 | LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */ |
341 | /* Note: We don't bother telling lockdep about it */ | ||
278 | SYNC | 342 | SYNC |
279 | MTMSRD(r10) | 343 | MTMSRD(r10) |
280 | lwz r9,TI_FLAGS(r12) | 344 | lwz r9,TI_FLAGS(r12) |
@@ -288,6 +352,19 @@ ret_from_syscall: | |||
288 | oris r11,r11,0x1000 /* Set SO bit in CR */ | 352 | oris r11,r11,0x1000 /* Set SO bit in CR */ |
289 | stw r11,_CCR(r1) | 353 | stw r11,_CCR(r1) |
290 | syscall_exit_cont: | 354 | syscall_exit_cont: |
355 | lwz r8,_MSR(r1) | ||
356 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
357 | /* If we are going to return from the syscall with interrupts | ||
358 | * off, we trace that here. It shouldn't happen though but we | ||
359 | * want to catch the bugger if it does right ? | ||
360 | */ | ||
361 | andi. r10,r8,MSR_EE | ||
362 | bne+ 1f | ||
363 | stw r3,GPR3(r1) | ||
364 | bl trace_hardirqs_off | ||
365 | lwz r3,GPR3(r1) | ||
366 | 1: | ||
367 | #endif /* CONFIG_TRACE_IRQFLAGS */ | ||
291 | #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) | 368 | #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) |
292 | /* If the process has its own DBCR0 value, load it up. The internal | 369 | /* If the process has its own DBCR0 value, load it up. The internal |
293 | debug mode bit tells us that dbcr0 should be loaded. */ | 370 | debug mode bit tells us that dbcr0 should be loaded. */ |
@@ -311,7 +388,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX) | |||
311 | mtlr r4 | 388 | mtlr r4 |
312 | mtcr r5 | 389 | mtcr r5 |
313 | lwz r7,_NIP(r1) | 390 | lwz r7,_NIP(r1) |
314 | lwz r8,_MSR(r1) | ||
315 | FIX_SRR1(r8, r0) | 391 | FIX_SRR1(r8, r0) |
316 | lwz r2,GPR2(r1) | 392 | lwz r2,GPR2(r1) |
317 | lwz r1,GPR1(r1) | 393 | lwz r1,GPR1(r1) |
@@ -394,7 +470,9 @@ syscall_exit_work: | |||
394 | andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP) | 470 | andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP) |
395 | beq ret_from_except | 471 | beq ret_from_except |
396 | 472 | ||
397 | /* Re-enable interrupts */ | 473 | /* Re-enable interrupts. There is no need to trace that with |
474 | * lockdep as we are supposed to have IRQs on at this point | ||
475 | */ | ||
398 | ori r10,r10,MSR_EE | 476 | ori r10,r10,MSR_EE |
399 | SYNC | 477 | SYNC |
400 | MTMSRD(r10) | 478 | MTMSRD(r10) |
@@ -705,6 +783,7 @@ ret_from_except: | |||
705 | /* Hard-disable interrupts so that current_thread_info()->flags | 783 | /* Hard-disable interrupts so that current_thread_info()->flags |
706 | * can't change between when we test it and when we return | 784 | * can't change between when we test it and when we return |
707 | * from the interrupt. */ | 785 | * from the interrupt. */ |
786 | /* Note: We don't bother telling lockdep about it */ | ||
708 | LOAD_MSR_KERNEL(r10,MSR_KERNEL) | 787 | LOAD_MSR_KERNEL(r10,MSR_KERNEL) |
709 | SYNC /* Some chip revs have problems here... */ | 788 | SYNC /* Some chip revs have problems here... */ |
710 | MTMSRD(r10) /* disable interrupts */ | 789 | MTMSRD(r10) /* disable interrupts */ |
@@ -744,11 +823,24 @@ resume_kernel: | |||
744 | beq+ restore | 823 | beq+ restore |
745 | andi. r0,r3,MSR_EE /* interrupts off? */ | 824 | andi. r0,r3,MSR_EE /* interrupts off? */ |
746 | beq restore /* don't schedule if so */ | 825 | beq restore /* don't schedule if so */ |
826 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
827 | /* Lockdep thinks irqs are enabled, we need to call | ||
828 | * preempt_schedule_irq with IRQs off, so we inform lockdep | ||
829 | * now that we -did- turn them off already | ||
830 | */ | ||
831 | bl trace_hardirqs_off | ||
832 | #endif | ||
747 | 1: bl preempt_schedule_irq | 833 | 1: bl preempt_schedule_irq |
748 | rlwinm r9,r1,0,0,(31-THREAD_SHIFT) | 834 | rlwinm r9,r1,0,0,(31-THREAD_SHIFT) |
749 | lwz r3,TI_FLAGS(r9) | 835 | lwz r3,TI_FLAGS(r9) |
750 | andi. r0,r3,_TIF_NEED_RESCHED | 836 | andi. r0,r3,_TIF_NEED_RESCHED |
751 | bne- 1b | 837 | bne- 1b |
838 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
839 | /* And now, to properly rebalance the above, we tell lockdep they | ||
840 | * are being turned back on, which will happen when we return | ||
841 | */ | ||
842 | bl trace_hardirqs_on | ||
843 | #endif | ||
752 | #else | 844 | #else |
753 | resume_kernel: | 845 | resume_kernel: |
754 | #endif /* CONFIG_PREEMPT */ | 846 | #endif /* CONFIG_PREEMPT */ |
@@ -765,6 +857,28 @@ restore: | |||
765 | stw r6,icache_44x_need_flush@l(r4) | 857 | stw r6,icache_44x_need_flush@l(r4) |
766 | 1: | 858 | 1: |
767 | #endif /* CONFIG_44x */ | 859 | #endif /* CONFIG_44x */ |
860 | |||
861 | lwz r9,_MSR(r1) | ||
862 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
863 | /* Lockdep doesn't know about the fact that IRQs are temporarily turned | ||
864 | * off in this assembly code while peeking at TI_FLAGS() and such. However | ||
865 | * we need to inform it if the exception turned interrupts off, and we | ||
866 | * are about to trun them back on. | ||
867 | * | ||
868 | * The problem here sadly is that we don't know whether the exceptions was | ||
869 | * one that turned interrupts off or not. So we always tell lockdep about | ||
870 | * turning them on here when we go back to wherever we came from with EE | ||
871 | * on, even if that may meen some redudant calls being tracked. Maybe later | ||
872 | * we could encode what the exception did somewhere or test the exception | ||
873 | * type in the pt_regs but that sounds overkill | ||
874 | */ | ||
875 | andi. r10,r9,MSR_EE | ||
876 | beq 1f | ||
877 | bl trace_hardirqs_on | ||
878 | lwz r9,_MSR(r1) | ||
879 | 1: | ||
880 | #endif /* CONFIG_TRACE_IRQFLAGS */ | ||
881 | |||
768 | lwz r0,GPR0(r1) | 882 | lwz r0,GPR0(r1) |
769 | lwz r2,GPR2(r1) | 883 | lwz r2,GPR2(r1) |
770 | REST_4GPRS(3, r1) | 884 | REST_4GPRS(3, r1) |
@@ -782,7 +896,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX) | |||
782 | stwcx. r0,0,r1 /* to clear the reservation */ | 896 | stwcx. r0,0,r1 /* to clear the reservation */ |
783 | 897 | ||
784 | #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE)) | 898 | #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE)) |
785 | lwz r9,_MSR(r1) | ||
786 | andi. r10,r9,MSR_RI /* check if this exception occurred */ | 899 | andi. r10,r9,MSR_RI /* check if this exception occurred */ |
787 | beql nonrecoverable /* at a bad place (MSR:RI = 0) */ | 900 | beql nonrecoverable /* at a bad place (MSR:RI = 0) */ |
788 | 901 | ||
@@ -805,7 +918,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX) | |||
805 | MTMSRD(r10) /* clear the RI bit */ | 918 | MTMSRD(r10) /* clear the RI bit */ |
806 | .globl exc_exit_restart | 919 | .globl exc_exit_restart |
807 | exc_exit_restart: | 920 | exc_exit_restart: |
808 | lwz r9,_MSR(r1) | ||
809 | lwz r12,_NIP(r1) | 921 | lwz r12,_NIP(r1) |
810 | FIX_SRR1(r9,r10) | 922 | FIX_SRR1(r9,r10) |
811 | mtspr SPRN_SRR0,r12 | 923 | mtspr SPRN_SRR0,r12 |
@@ -1035,11 +1147,18 @@ do_work: /* r10 contains MSR_KERNEL here */ | |||
1035 | beq do_user_signal | 1147 | beq do_user_signal |
1036 | 1148 | ||
1037 | do_resched: /* r10 contains MSR_KERNEL here */ | 1149 | do_resched: /* r10 contains MSR_KERNEL here */ |
1150 | /* Note: We don't need to inform lockdep that we are enabling | ||
1151 | * interrupts here. As far as it knows, they are already enabled | ||
1152 | */ | ||
1038 | ori r10,r10,MSR_EE | 1153 | ori r10,r10,MSR_EE |
1039 | SYNC | 1154 | SYNC |
1040 | MTMSRD(r10) /* hard-enable interrupts */ | 1155 | MTMSRD(r10) /* hard-enable interrupts */ |
1041 | bl schedule | 1156 | bl schedule |
1042 | recheck: | 1157 | recheck: |
1158 | /* Note: And we don't tell it we are disabling them again | ||
1159 | * neither. Those disable/enable cycles used to peek at | ||
1160 | * TI_FLAGS aren't advertised. | ||
1161 | */ | ||
1043 | LOAD_MSR_KERNEL(r10,MSR_KERNEL) | 1162 | LOAD_MSR_KERNEL(r10,MSR_KERNEL) |
1044 | SYNC | 1163 | SYNC |
1045 | MTMSRD(r10) /* disable interrupts */ | 1164 | MTMSRD(r10) /* disable interrupts */ |
diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c index 1b12696cca06..ce1f3e44c24f 100644 --- a/arch/powerpc/kernel/ftrace.c +++ b/arch/powerpc/kernel/ftrace.c | |||
@@ -586,7 +586,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) | |||
586 | return; | 586 | return; |
587 | } | 587 | } |
588 | 588 | ||
589 | if (ftrace_push_return_trace(old, self_addr, &trace.depth) == -EBUSY) { | 589 | if (ftrace_push_return_trace(old, self_addr, &trace.depth, 0) == -EBUSY) { |
590 | *parent = old; | 590 | *parent = old; |
591 | return; | 591 | return; |
592 | } | 592 | } |
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S index 48469463f89e..fc2132942754 100644 --- a/arch/powerpc/kernel/head_32.S +++ b/arch/powerpc/kernel/head_32.S | |||
@@ -1124,9 +1124,8 @@ mmu_off: | |||
1124 | RFI | 1124 | RFI |
1125 | 1125 | ||
1126 | /* | 1126 | /* |
1127 | * Use the first pair of BAT registers to map the 1st 16MB | 1127 | * On 601, we use 3 BATs to map up to 24M of RAM at _PAGE_OFFSET |
1128 | * of RAM to PAGE_OFFSET. From this point on we can't safely | 1128 | * (we keep one for debugging) and on others, we use one 256M BAT. |
1129 | * call OF any more. | ||
1130 | */ | 1129 | */ |
1131 | initial_bats: | 1130 | initial_bats: |
1132 | lis r11,PAGE_OFFSET@h | 1131 | lis r11,PAGE_OFFSET@h |
@@ -1136,12 +1135,16 @@ initial_bats: | |||
1136 | bne 4f | 1135 | bne 4f |
1137 | ori r11,r11,4 /* set up BAT registers for 601 */ | 1136 | ori r11,r11,4 /* set up BAT registers for 601 */ |
1138 | li r8,0x7f /* valid, block length = 8MB */ | 1137 | li r8,0x7f /* valid, block length = 8MB */ |
1139 | oris r9,r11,0x800000@h /* set up BAT reg for 2nd 8M */ | ||
1140 | oris r10,r8,0x800000@h /* set up BAT reg for 2nd 8M */ | ||
1141 | mtspr SPRN_IBAT0U,r11 /* N.B. 601 has valid bit in */ | 1138 | mtspr SPRN_IBAT0U,r11 /* N.B. 601 has valid bit in */ |
1142 | mtspr SPRN_IBAT0L,r8 /* lower BAT register */ | 1139 | mtspr SPRN_IBAT0L,r8 /* lower BAT register */ |
1143 | mtspr SPRN_IBAT1U,r9 | 1140 | addis r11,r11,0x800000@h |
1144 | mtspr SPRN_IBAT1L,r10 | 1141 | addis r8,r8,0x800000@h |
1142 | mtspr SPRN_IBAT1U,r11 | ||
1143 | mtspr SPRN_IBAT1L,r8 | ||
1144 | addis r11,r11,0x800000@h | ||
1145 | addis r8,r8,0x800000@h | ||
1146 | mtspr SPRN_IBAT2U,r11 | ||
1147 | mtspr SPRN_IBAT2L,r8 | ||
1145 | isync | 1148 | isync |
1146 | blr | 1149 | blr |
1147 | 1150 | ||
diff --git a/arch/powerpc/kernel/mpc7450-pmu.c b/arch/powerpc/kernel/mpc7450-pmu.c new file mode 100644 index 000000000000..cc466d039af6 --- /dev/null +++ b/arch/powerpc/kernel/mpc7450-pmu.c | |||
@@ -0,0 +1,417 @@ | |||
1 | /* | ||
2 | * Performance counter support for MPC7450-family processors. | ||
3 | * | ||
4 | * Copyright 2008-2009 Paul Mackerras, IBM Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | #include <linux/string.h> | ||
12 | #include <linux/perf_counter.h> | ||
13 | #include <asm/reg.h> | ||
14 | #include <asm/cputable.h> | ||
15 | |||
16 | #define N_COUNTER 6 /* Number of hardware counters */ | ||
17 | #define MAX_ALT 3 /* Maximum number of event alternative codes */ | ||
18 | |||
19 | /* | ||
20 | * Bits in event code for MPC7450 family | ||
21 | */ | ||
22 | #define PM_THRMULT_MSKS 0x40000 | ||
23 | #define PM_THRESH_SH 12 | ||
24 | #define PM_THRESH_MSK 0x3f | ||
25 | #define PM_PMC_SH 8 | ||
26 | #define PM_PMC_MSK 7 | ||
27 | #define PM_PMCSEL_MSK 0x7f | ||
28 | |||
29 | /* | ||
30 | * Classify events according to how specific their PMC requirements are. | ||
31 | * Result is: | ||
32 | * 0: can go on any PMC | ||
33 | * 1: can go on PMCs 1-4 | ||
34 | * 2: can go on PMCs 1,2,4 | ||
35 | * 3: can go on PMCs 1 or 2 | ||
36 | * 4: can only go on one PMC | ||
37 | * -1: event code is invalid | ||
38 | */ | ||
39 | #define N_CLASSES 5 | ||
40 | |||
41 | static int mpc7450_classify_event(u32 event) | ||
42 | { | ||
43 | int pmc; | ||
44 | |||
45 | pmc = (event >> PM_PMC_SH) & PM_PMC_MSK; | ||
46 | if (pmc) { | ||
47 | if (pmc > N_COUNTER) | ||
48 | return -1; | ||
49 | return 4; | ||
50 | } | ||
51 | event &= PM_PMCSEL_MSK; | ||
52 | if (event <= 1) | ||
53 | return 0; | ||
54 | if (event <= 7) | ||
55 | return 1; | ||
56 | if (event <= 13) | ||
57 | return 2; | ||
58 | if (event <= 22) | ||
59 | return 3; | ||
60 | return -1; | ||
61 | } | ||
62 | |||
63 | /* | ||
64 | * Events using threshold and possible threshold scale: | ||
65 | * code scale? name | ||
66 | * 11e N PM_INSTQ_EXCEED_CYC | ||
67 | * 11f N PM_ALTV_IQ_EXCEED_CYC | ||
68 | * 128 Y PM_DTLB_SEARCH_EXCEED_CYC | ||
69 | * 12b Y PM_LD_MISS_EXCEED_L1_CYC | ||
70 | * 220 N PM_CQ_EXCEED_CYC | ||
71 | * 30c N PM_GPR_RB_EXCEED_CYC | ||
72 | * 30d ? PM_FPR_IQ_EXCEED_CYC ? | ||
73 | * 311 Y PM_ITLB_SEARCH_EXCEED | ||
74 | * 410 N PM_GPR_IQ_EXCEED_CYC | ||
75 | */ | ||
76 | |||
77 | /* | ||
78 | * Return use of threshold and threshold scale bits: | ||
79 | * 0 = uses neither, 1 = uses threshold, 2 = uses both | ||
80 | */ | ||
81 | static int mpc7450_threshold_use(u32 event) | ||
82 | { | ||
83 | int pmc, sel; | ||
84 | |||
85 | pmc = (event >> PM_PMC_SH) & PM_PMC_MSK; | ||
86 | sel = event & PM_PMCSEL_MSK; | ||
87 | switch (pmc) { | ||
88 | case 1: | ||
89 | if (sel == 0x1e || sel == 0x1f) | ||
90 | return 1; | ||
91 | if (sel == 0x28 || sel == 0x2b) | ||
92 | return 2; | ||
93 | break; | ||
94 | case 2: | ||
95 | if (sel == 0x20) | ||
96 | return 1; | ||
97 | break; | ||
98 | case 3: | ||
99 | if (sel == 0xc || sel == 0xd) | ||
100 | return 1; | ||
101 | if (sel == 0x11) | ||
102 | return 2; | ||
103 | break; | ||
104 | case 4: | ||
105 | if (sel == 0x10) | ||
106 | return 1; | ||
107 | break; | ||
108 | } | ||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | /* | ||
113 | * Layout of constraint bits: | ||
114 | * 33222222222211111111110000000000 | ||
115 | * 10987654321098765432109876543210 | ||
116 | * |< >< > < > < ><><><><><><> | ||
117 | * TS TV G4 G3 G2P6P5P4P3P2P1 | ||
118 | * | ||
119 | * P1 - P6 | ||
120 | * 0 - 11: Count of events needing PMC1 .. PMC6 | ||
121 | * | ||
122 | * G2 | ||
123 | * 12 - 14: Count of events needing PMC1 or PMC2 | ||
124 | * | ||
125 | * G3 | ||
126 | * 16 - 18: Count of events needing PMC1, PMC2 or PMC4 | ||
127 | * | ||
128 | * G4 | ||
129 | * 20 - 23: Count of events needing PMC1, PMC2, PMC3 or PMC4 | ||
130 | * | ||
131 | * TV | ||
132 | * 24 - 29: Threshold value requested | ||
133 | * | ||
134 | * TS | ||
135 | * 30: Threshold scale value requested | ||
136 | */ | ||
137 | |||
138 | static u32 pmcbits[N_COUNTER][2] = { | ||
139 | { 0x00844002, 0x00111001 }, /* PMC1 mask, value: P1,G2,G3,G4 */ | ||
140 | { 0x00844008, 0x00111004 }, /* PMC2: P2,G2,G3,G4 */ | ||
141 | { 0x00800020, 0x00100010 }, /* PMC3: P3,G4 */ | ||
142 | { 0x00840080, 0x00110040 }, /* PMC4: P4,G3,G4 */ | ||
143 | { 0x00000200, 0x00000100 }, /* PMC5: P5 */ | ||
144 | { 0x00000800, 0x00000400 } /* PMC6: P6 */ | ||
145 | }; | ||
146 | |||
147 | static u32 classbits[N_CLASSES - 1][2] = { | ||
148 | { 0x00000000, 0x00000000 }, /* class 0: no constraint */ | ||
149 | { 0x00800000, 0x00100000 }, /* class 1: G4 */ | ||
150 | { 0x00040000, 0x00010000 }, /* class 2: G3 */ | ||
151 | { 0x00004000, 0x00001000 }, /* class 3: G2 */ | ||
152 | }; | ||
153 | |||
154 | static int mpc7450_get_constraint(u64 event, unsigned long *maskp, | ||
155 | unsigned long *valp) | ||
156 | { | ||
157 | int pmc, class; | ||
158 | u32 mask, value; | ||
159 | int thresh, tuse; | ||
160 | |||
161 | class = mpc7450_classify_event(event); | ||
162 | if (class < 0) | ||
163 | return -1; | ||
164 | if (class == 4) { | ||
165 | pmc = ((unsigned int)event >> PM_PMC_SH) & PM_PMC_MSK; | ||
166 | mask = pmcbits[pmc - 1][0]; | ||
167 | value = pmcbits[pmc - 1][1]; | ||
168 | } else { | ||
169 | mask = classbits[class][0]; | ||
170 | value = classbits[class][1]; | ||
171 | } | ||
172 | |||
173 | tuse = mpc7450_threshold_use(event); | ||
174 | if (tuse) { | ||
175 | thresh = ((unsigned int)event >> PM_THRESH_SH) & PM_THRESH_MSK; | ||
176 | mask |= 0x3f << 24; | ||
177 | value |= thresh << 24; | ||
178 | if (tuse == 2) { | ||
179 | mask |= 0x40000000; | ||
180 | if ((unsigned int)event & PM_THRMULT_MSKS) | ||
181 | value |= 0x40000000; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | *maskp = mask; | ||
186 | *valp = value; | ||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static const unsigned int event_alternatives[][MAX_ALT] = { | ||
191 | { 0x217, 0x317 }, /* PM_L1_DCACHE_MISS */ | ||
192 | { 0x418, 0x50f, 0x60f }, /* PM_SNOOP_RETRY */ | ||
193 | { 0x502, 0x602 }, /* PM_L2_HIT */ | ||
194 | { 0x503, 0x603 }, /* PM_L3_HIT */ | ||
195 | { 0x504, 0x604 }, /* PM_L2_ICACHE_MISS */ | ||
196 | { 0x505, 0x605 }, /* PM_L3_ICACHE_MISS */ | ||
197 | { 0x506, 0x606 }, /* PM_L2_DCACHE_MISS */ | ||
198 | { 0x507, 0x607 }, /* PM_L3_DCACHE_MISS */ | ||
199 | { 0x50a, 0x623 }, /* PM_LD_HIT_L3 */ | ||
200 | { 0x50b, 0x624 }, /* PM_ST_HIT_L3 */ | ||
201 | { 0x50d, 0x60d }, /* PM_L2_TOUCH_HIT */ | ||
202 | { 0x50e, 0x60e }, /* PM_L3_TOUCH_HIT */ | ||
203 | { 0x512, 0x612 }, /* PM_INT_LOCAL */ | ||
204 | { 0x513, 0x61d }, /* PM_L2_MISS */ | ||
205 | { 0x514, 0x61e }, /* PM_L3_MISS */ | ||
206 | }; | ||
207 | |||
208 | /* | ||
209 | * Scan the alternatives table for a match and return the | ||
210 | * index into the alternatives table if found, else -1. | ||
211 | */ | ||
212 | static int find_alternative(u32 event) | ||
213 | { | ||
214 | int i, j; | ||
215 | |||
216 | for (i = 0; i < ARRAY_SIZE(event_alternatives); ++i) { | ||
217 | if (event < event_alternatives[i][0]) | ||
218 | break; | ||
219 | for (j = 0; j < MAX_ALT && event_alternatives[i][j]; ++j) | ||
220 | if (event == event_alternatives[i][j]) | ||
221 | return i; | ||
222 | } | ||
223 | return -1; | ||
224 | } | ||
225 | |||
226 | static int mpc7450_get_alternatives(u64 event, unsigned int flags, u64 alt[]) | ||
227 | { | ||
228 | int i, j, nalt = 1; | ||
229 | u32 ae; | ||
230 | |||
231 | alt[0] = event; | ||
232 | nalt = 1; | ||
233 | i = find_alternative((u32)event); | ||
234 | if (i >= 0) { | ||
235 | for (j = 0; j < MAX_ALT; ++j) { | ||
236 | ae = event_alternatives[i][j]; | ||
237 | if (ae && ae != (u32)event) | ||
238 | alt[nalt++] = ae; | ||
239 | } | ||
240 | } | ||
241 | return nalt; | ||
242 | } | ||
243 | |||
244 | /* | ||
245 | * Bitmaps of which PMCs each class can use for classes 0 - 3. | ||
246 | * Bit i is set if PMC i+1 is usable. | ||
247 | */ | ||
248 | static const u8 classmap[N_CLASSES] = { | ||
249 | 0x3f, 0x0f, 0x0b, 0x03, 0 | ||
250 | }; | ||
251 | |||
252 | /* Bit position and width of each PMCSEL field */ | ||
253 | static const int pmcsel_shift[N_COUNTER] = { | ||
254 | 6, 0, 27, 22, 17, 11 | ||
255 | }; | ||
256 | static const u32 pmcsel_mask[N_COUNTER] = { | ||
257 | 0x7f, 0x3f, 0x1f, 0x1f, 0x1f, 0x3f | ||
258 | }; | ||
259 | |||
260 | /* | ||
261 | * Compute MMCR0/1/2 values for a set of events. | ||
262 | */ | ||
263 | static int mpc7450_compute_mmcr(u64 event[], int n_ev, | ||
264 | unsigned int hwc[], unsigned long mmcr[]) | ||
265 | { | ||
266 | u8 event_index[N_CLASSES][N_COUNTER]; | ||
267 | int n_classevent[N_CLASSES]; | ||
268 | int i, j, class, tuse; | ||
269 | u32 pmc_inuse = 0, pmc_avail; | ||
270 | u32 mmcr0 = 0, mmcr1 = 0, mmcr2 = 0; | ||
271 | u32 ev, pmc, thresh; | ||
272 | |||
273 | if (n_ev > N_COUNTER) | ||
274 | return -1; | ||
275 | |||
276 | /* First pass: count usage in each class */ | ||
277 | for (i = 0; i < N_CLASSES; ++i) | ||
278 | n_classevent[i] = 0; | ||
279 | for (i = 0; i < n_ev; ++i) { | ||
280 | class = mpc7450_classify_event(event[i]); | ||
281 | if (class < 0) | ||
282 | return -1; | ||
283 | j = n_classevent[class]++; | ||
284 | event_index[class][j] = i; | ||
285 | } | ||
286 | |||
287 | /* Second pass: allocate PMCs from most specific event to least */ | ||
288 | for (class = N_CLASSES - 1; class >= 0; --class) { | ||
289 | for (i = 0; i < n_classevent[class]; ++i) { | ||
290 | ev = event[event_index[class][i]]; | ||
291 | if (class == 4) { | ||
292 | pmc = (ev >> PM_PMC_SH) & PM_PMC_MSK; | ||
293 | if (pmc_inuse & (1 << (pmc - 1))) | ||
294 | return -1; | ||
295 | } else { | ||
296 | /* Find a suitable PMC */ | ||
297 | pmc_avail = classmap[class] & ~pmc_inuse; | ||
298 | if (!pmc_avail) | ||
299 | return -1; | ||
300 | pmc = ffs(pmc_avail); | ||
301 | } | ||
302 | pmc_inuse |= 1 << (pmc - 1); | ||
303 | |||
304 | tuse = mpc7450_threshold_use(ev); | ||
305 | if (tuse) { | ||
306 | thresh = (ev >> PM_THRESH_SH) & PM_THRESH_MSK; | ||
307 | mmcr0 |= thresh << 16; | ||
308 | if (tuse == 2 && (ev & PM_THRMULT_MSKS)) | ||
309 | mmcr2 = 0x80000000; | ||
310 | } | ||
311 | ev &= pmcsel_mask[pmc - 1]; | ||
312 | ev <<= pmcsel_shift[pmc - 1]; | ||
313 | if (pmc <= 2) | ||
314 | mmcr0 |= ev; | ||
315 | else | ||
316 | mmcr1 |= ev; | ||
317 | hwc[event_index[class][i]] = pmc - 1; | ||
318 | } | ||
319 | } | ||
320 | |||
321 | if (pmc_inuse & 1) | ||
322 | mmcr0 |= MMCR0_PMC1CE; | ||
323 | if (pmc_inuse & 0x3e) | ||
324 | mmcr0 |= MMCR0_PMCnCE; | ||
325 | |||
326 | /* Return MMCRx values */ | ||
327 | mmcr[0] = mmcr0; | ||
328 | mmcr[1] = mmcr1; | ||
329 | mmcr[2] = mmcr2; | ||
330 | return 0; | ||
331 | } | ||
332 | |||
333 | /* | ||
334 | * Disable counting by a PMC. | ||
335 | * Note that the pmc argument is 0-based here, not 1-based. | ||
336 | */ | ||
337 | static void mpc7450_disable_pmc(unsigned int pmc, unsigned long mmcr[]) | ||
338 | { | ||
339 | if (pmc <= 1) | ||
340 | mmcr[0] &= ~(pmcsel_mask[pmc] << pmcsel_shift[pmc]); | ||
341 | else | ||
342 | mmcr[1] &= ~(pmcsel_mask[pmc] << pmcsel_shift[pmc]); | ||
343 | } | ||
344 | |||
345 | static int mpc7450_generic_events[] = { | ||
346 | [PERF_COUNT_HW_CPU_CYCLES] = 1, | ||
347 | [PERF_COUNT_HW_INSTRUCTIONS] = 2, | ||
348 | [PERF_COUNT_HW_CACHE_MISSES] = 0x217, /* PM_L1_DCACHE_MISS */ | ||
349 | [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x122, /* PM_BR_CMPL */ | ||
350 | [PERF_COUNT_HW_BRANCH_MISSES] = 0x41c, /* PM_BR_MPRED */ | ||
351 | }; | ||
352 | |||
353 | #define C(x) PERF_COUNT_HW_CACHE_##x | ||
354 | |||
355 | /* | ||
356 | * Table of generalized cache-related events. | ||
357 | * 0 means not supported, -1 means nonsensical, other values | ||
358 | * are event codes. | ||
359 | */ | ||
360 | static int mpc7450_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = { | ||
361 | [C(L1D)] = { /* RESULT_ACCESS RESULT_MISS */ | ||
362 | [C(OP_READ)] = { 0, 0x225 }, | ||
363 | [C(OP_WRITE)] = { 0, 0x227 }, | ||
364 | [C(OP_PREFETCH)] = { 0, 0 }, | ||
365 | }, | ||
366 | [C(L1I)] = { /* RESULT_ACCESS RESULT_MISS */ | ||
367 | [C(OP_READ)] = { 0x129, 0x115 }, | ||
368 | [C(OP_WRITE)] = { -1, -1 }, | ||
369 | [C(OP_PREFETCH)] = { 0x634, 0 }, | ||
370 | }, | ||
371 | [C(LL)] = { /* RESULT_ACCESS RESULT_MISS */ | ||
372 | [C(OP_READ)] = { 0, 0 }, | ||
373 | [C(OP_WRITE)] = { 0, 0 }, | ||
374 | [C(OP_PREFETCH)] = { 0, 0 }, | ||
375 | }, | ||
376 | [C(DTLB)] = { /* RESULT_ACCESS RESULT_MISS */ | ||
377 | [C(OP_READ)] = { 0, 0x312 }, | ||
378 | [C(OP_WRITE)] = { -1, -1 }, | ||
379 | [C(OP_PREFETCH)] = { -1, -1 }, | ||
380 | }, | ||
381 | [C(ITLB)] = { /* RESULT_ACCESS RESULT_MISS */ | ||
382 | [C(OP_READ)] = { 0, 0x223 }, | ||
383 | [C(OP_WRITE)] = { -1, -1 }, | ||
384 | [C(OP_PREFETCH)] = { -1, -1 }, | ||
385 | }, | ||
386 | [C(BPU)] = { /* RESULT_ACCESS RESULT_MISS */ | ||
387 | [C(OP_READ)] = { 0x122, 0x41c }, | ||
388 | [C(OP_WRITE)] = { -1, -1 }, | ||
389 | [C(OP_PREFETCH)] = { -1, -1 }, | ||
390 | }, | ||
391 | }; | ||
392 | |||
393 | struct power_pmu mpc7450_pmu = { | ||
394 | .name = "MPC7450 family", | ||
395 | .n_counter = N_COUNTER, | ||
396 | .max_alternatives = MAX_ALT, | ||
397 | .add_fields = 0x00111555ul, | ||
398 | .test_adder = 0x00301000ul, | ||
399 | .compute_mmcr = mpc7450_compute_mmcr, | ||
400 | .get_constraint = mpc7450_get_constraint, | ||
401 | .get_alternatives = mpc7450_get_alternatives, | ||
402 | .disable_pmc = mpc7450_disable_pmc, | ||
403 | .n_generic = ARRAY_SIZE(mpc7450_generic_events), | ||
404 | .generic_events = mpc7450_generic_events, | ||
405 | .cache_events = &mpc7450_cache_events, | ||
406 | }; | ||
407 | |||
408 | static int init_mpc7450_pmu(void) | ||
409 | { | ||
410 | if (!cur_cpu_spec->oprofile_cpu_type || | ||
411 | strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc/7450")) | ||
412 | return -ENODEV; | ||
413 | |||
414 | return register_power_pmu(&mpc7450_pmu); | ||
415 | } | ||
416 | |||
417 | arch_initcall(init_mpc7450_pmu); | ||
diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c index fa983a59c4ce..a359cb08e900 100644 --- a/arch/powerpc/kernel/of_device.c +++ b/arch/powerpc/kernel/of_device.c | |||
@@ -76,7 +76,7 @@ struct of_device *of_device_alloc(struct device_node *np, | |||
76 | dev->dev.archdata.of_node = np; | 76 | dev->dev.archdata.of_node = np; |
77 | 77 | ||
78 | if (bus_id) | 78 | if (bus_id) |
79 | dev_set_name(&dev->dev, bus_id); | 79 | dev_set_name(&dev->dev, "%s", bus_id); |
80 | else | 80 | else |
81 | of_device_make_bus_id(dev); | 81 | of_device_make_bus_id(dev); |
82 | 82 | ||
diff --git a/arch/powerpc/kernel/perf_counter.c b/arch/powerpc/kernel/perf_counter.c index bb202388170e..70e1f57f7dd8 100644 --- a/arch/powerpc/kernel/perf_counter.c +++ b/arch/powerpc/kernel/perf_counter.c | |||
@@ -29,7 +29,7 @@ struct cpu_hw_counters { | |||
29 | struct perf_counter *counter[MAX_HWCOUNTERS]; | 29 | struct perf_counter *counter[MAX_HWCOUNTERS]; |
30 | u64 events[MAX_HWCOUNTERS]; | 30 | u64 events[MAX_HWCOUNTERS]; |
31 | unsigned int flags[MAX_HWCOUNTERS]; | 31 | unsigned int flags[MAX_HWCOUNTERS]; |
32 | u64 mmcr[3]; | 32 | unsigned long mmcr[3]; |
33 | struct perf_counter *limited_counter[MAX_LIMITED_HWCOUNTERS]; | 33 | struct perf_counter *limited_counter[MAX_LIMITED_HWCOUNTERS]; |
34 | u8 limited_hwidx[MAX_LIMITED_HWCOUNTERS]; | 34 | u8 limited_hwidx[MAX_LIMITED_HWCOUNTERS]; |
35 | }; | 35 | }; |
@@ -46,6 +46,115 @@ struct power_pmu *ppmu; | |||
46 | */ | 46 | */ |
47 | static unsigned int freeze_counters_kernel = MMCR0_FCS; | 47 | static unsigned int freeze_counters_kernel = MMCR0_FCS; |
48 | 48 | ||
49 | /* | ||
50 | * 32-bit doesn't have MMCRA but does have an MMCR2, | ||
51 | * and a few other names are different. | ||
52 | */ | ||
53 | #ifdef CONFIG_PPC32 | ||
54 | |||
55 | #define MMCR0_FCHV 0 | ||
56 | #define MMCR0_PMCjCE MMCR0_PMCnCE | ||
57 | |||
58 | #define SPRN_MMCRA SPRN_MMCR2 | ||
59 | #define MMCRA_SAMPLE_ENABLE 0 | ||
60 | |||
61 | static inline unsigned long perf_ip_adjust(struct pt_regs *regs) | ||
62 | { | ||
63 | return 0; | ||
64 | } | ||
65 | static inline void perf_set_pmu_inuse(int inuse) { } | ||
66 | static inline void perf_get_data_addr(struct pt_regs *regs, u64 *addrp) { } | ||
67 | static inline u32 perf_get_misc_flags(struct pt_regs *regs) | ||
68 | { | ||
69 | return 0; | ||
70 | } | ||
71 | static inline void perf_read_regs(struct pt_regs *regs) { } | ||
72 | static inline int perf_intr_is_nmi(struct pt_regs *regs) | ||
73 | { | ||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | #endif /* CONFIG_PPC32 */ | ||
78 | |||
79 | /* | ||
80 | * Things that are specific to 64-bit implementations. | ||
81 | */ | ||
82 | #ifdef CONFIG_PPC64 | ||
83 | |||
84 | static inline unsigned long perf_ip_adjust(struct pt_regs *regs) | ||
85 | { | ||
86 | unsigned long mmcra = regs->dsisr; | ||
87 | |||
88 | if ((mmcra & MMCRA_SAMPLE_ENABLE) && !(ppmu->flags & PPMU_ALT_SIPR)) { | ||
89 | unsigned long slot = (mmcra & MMCRA_SLOT) >> MMCRA_SLOT_SHIFT; | ||
90 | if (slot > 1) | ||
91 | return 4 * (slot - 1); | ||
92 | } | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | static inline void perf_set_pmu_inuse(int inuse) | ||
97 | { | ||
98 | get_lppaca()->pmcregs_in_use = inuse; | ||
99 | } | ||
100 | |||
101 | /* | ||
102 | * The user wants a data address recorded. | ||
103 | * If we're not doing instruction sampling, give them the SDAR | ||
104 | * (sampled data address). If we are doing instruction sampling, then | ||
105 | * only give them the SDAR if it corresponds to the instruction | ||
106 | * pointed to by SIAR; this is indicated by the [POWER6_]MMCRA_SDSYNC | ||
107 | * bit in MMCRA. | ||
108 | */ | ||
109 | static inline void perf_get_data_addr(struct pt_regs *regs, u64 *addrp) | ||
110 | { | ||
111 | unsigned long mmcra = regs->dsisr; | ||
112 | unsigned long sdsync = (ppmu->flags & PPMU_ALT_SIPR) ? | ||
113 | POWER6_MMCRA_SDSYNC : MMCRA_SDSYNC; | ||
114 | |||
115 | if (!(mmcra & MMCRA_SAMPLE_ENABLE) || (mmcra & sdsync)) | ||
116 | *addrp = mfspr(SPRN_SDAR); | ||
117 | } | ||
118 | |||
119 | static inline u32 perf_get_misc_flags(struct pt_regs *regs) | ||
120 | { | ||
121 | unsigned long mmcra = regs->dsisr; | ||
122 | |||
123 | if (TRAP(regs) != 0xf00) | ||
124 | return 0; /* not a PMU interrupt */ | ||
125 | |||
126 | if (ppmu->flags & PPMU_ALT_SIPR) { | ||
127 | if (mmcra & POWER6_MMCRA_SIHV) | ||
128 | return PERF_EVENT_MISC_HYPERVISOR; | ||
129 | return (mmcra & POWER6_MMCRA_SIPR) ? | ||
130 | PERF_EVENT_MISC_USER : PERF_EVENT_MISC_KERNEL; | ||
131 | } | ||
132 | if (mmcra & MMCRA_SIHV) | ||
133 | return PERF_EVENT_MISC_HYPERVISOR; | ||
134 | return (mmcra & MMCRA_SIPR) ? PERF_EVENT_MISC_USER : | ||
135 | PERF_EVENT_MISC_KERNEL; | ||
136 | } | ||
137 | |||
138 | /* | ||
139 | * Overload regs->dsisr to store MMCRA so we only need to read it once | ||
140 | * on each interrupt. | ||
141 | */ | ||
142 | static inline void perf_read_regs(struct pt_regs *regs) | ||
143 | { | ||
144 | regs->dsisr = mfspr(SPRN_MMCRA); | ||
145 | } | ||
146 | |||
147 | /* | ||
148 | * If interrupts were soft-disabled when a PMU interrupt occurs, treat | ||
149 | * it as an NMI. | ||
150 | */ | ||
151 | static inline int perf_intr_is_nmi(struct pt_regs *regs) | ||
152 | { | ||
153 | return !regs->softe; | ||
154 | } | ||
155 | |||
156 | #endif /* CONFIG_PPC64 */ | ||
157 | |||
49 | static void perf_counter_interrupt(struct pt_regs *regs); | 158 | static void perf_counter_interrupt(struct pt_regs *regs); |
50 | 159 | ||
51 | void perf_counter_print_debug(void) | 160 | void perf_counter_print_debug(void) |
@@ -78,12 +187,14 @@ static unsigned long read_pmc(int idx) | |||
78 | case 6: | 187 | case 6: |
79 | val = mfspr(SPRN_PMC6); | 188 | val = mfspr(SPRN_PMC6); |
80 | break; | 189 | break; |
190 | #ifdef CONFIG_PPC64 | ||
81 | case 7: | 191 | case 7: |
82 | val = mfspr(SPRN_PMC7); | 192 | val = mfspr(SPRN_PMC7); |
83 | break; | 193 | break; |
84 | case 8: | 194 | case 8: |
85 | val = mfspr(SPRN_PMC8); | 195 | val = mfspr(SPRN_PMC8); |
86 | break; | 196 | break; |
197 | #endif /* CONFIG_PPC64 */ | ||
87 | default: | 198 | default: |
88 | printk(KERN_ERR "oops trying to read PMC%d\n", idx); | 199 | printk(KERN_ERR "oops trying to read PMC%d\n", idx); |
89 | val = 0; | 200 | val = 0; |
@@ -115,12 +226,14 @@ static void write_pmc(int idx, unsigned long val) | |||
115 | case 6: | 226 | case 6: |
116 | mtspr(SPRN_PMC6, val); | 227 | mtspr(SPRN_PMC6, val); |
117 | break; | 228 | break; |
229 | #ifdef CONFIG_PPC64 | ||
118 | case 7: | 230 | case 7: |
119 | mtspr(SPRN_PMC7, val); | 231 | mtspr(SPRN_PMC7, val); |
120 | break; | 232 | break; |
121 | case 8: | 233 | case 8: |
122 | mtspr(SPRN_PMC8, val); | 234 | mtspr(SPRN_PMC8, val); |
123 | break; | 235 | break; |
236 | #endif /* CONFIG_PPC64 */ | ||
124 | default: | 237 | default: |
125 | printk(KERN_ERR "oops trying to write PMC%d\n", idx); | 238 | printk(KERN_ERR "oops trying to write PMC%d\n", idx); |
126 | } | 239 | } |
@@ -135,15 +248,15 @@ static void write_pmc(int idx, unsigned long val) | |||
135 | static int power_check_constraints(u64 event[], unsigned int cflags[], | 248 | static int power_check_constraints(u64 event[], unsigned int cflags[], |
136 | int n_ev) | 249 | int n_ev) |
137 | { | 250 | { |
138 | u64 mask, value, nv; | 251 | unsigned long mask, value, nv; |
139 | u64 alternatives[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES]; | 252 | u64 alternatives[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES]; |
140 | u64 amasks[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES]; | 253 | unsigned long amasks[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES]; |
141 | u64 avalues[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES]; | 254 | unsigned long avalues[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES]; |
142 | u64 smasks[MAX_HWCOUNTERS], svalues[MAX_HWCOUNTERS]; | 255 | unsigned long smasks[MAX_HWCOUNTERS], svalues[MAX_HWCOUNTERS]; |
143 | int n_alt[MAX_HWCOUNTERS], choice[MAX_HWCOUNTERS]; | 256 | int n_alt[MAX_HWCOUNTERS], choice[MAX_HWCOUNTERS]; |
144 | int i, j; | 257 | int i, j; |
145 | u64 addf = ppmu->add_fields; | 258 | unsigned long addf = ppmu->add_fields; |
146 | u64 tadd = ppmu->test_adder; | 259 | unsigned long tadd = ppmu->test_adder; |
147 | 260 | ||
148 | if (n_ev > ppmu->n_counter) | 261 | if (n_ev > ppmu->n_counter) |
149 | return -1; | 262 | return -1; |
@@ -283,7 +396,7 @@ static int check_excludes(struct perf_counter **ctrs, unsigned int cflags[], | |||
283 | 396 | ||
284 | static void power_pmu_read(struct perf_counter *counter) | 397 | static void power_pmu_read(struct perf_counter *counter) |
285 | { | 398 | { |
286 | long val, delta, prev; | 399 | s64 val, delta, prev; |
287 | 400 | ||
288 | if (!counter->hw.idx) | 401 | if (!counter->hw.idx) |
289 | return; | 402 | return; |
@@ -403,14 +516,14 @@ static void write_mmcr0(struct cpu_hw_counters *cpuhw, unsigned long mmcr0) | |||
403 | void hw_perf_disable(void) | 516 | void hw_perf_disable(void) |
404 | { | 517 | { |
405 | struct cpu_hw_counters *cpuhw; | 518 | struct cpu_hw_counters *cpuhw; |
406 | unsigned long ret; | ||
407 | unsigned long flags; | 519 | unsigned long flags; |
408 | 520 | ||
521 | if (!ppmu) | ||
522 | return; | ||
409 | local_irq_save(flags); | 523 | local_irq_save(flags); |
410 | cpuhw = &__get_cpu_var(cpu_hw_counters); | 524 | cpuhw = &__get_cpu_var(cpu_hw_counters); |
411 | 525 | ||
412 | ret = cpuhw->disabled; | 526 | if (!cpuhw->disabled) { |
413 | if (!ret) { | ||
414 | cpuhw->disabled = 1; | 527 | cpuhw->disabled = 1; |
415 | cpuhw->n_added = 0; | 528 | cpuhw->n_added = 0; |
416 | 529 | ||
@@ -461,6 +574,8 @@ void hw_perf_enable(void) | |||
461 | int n_lim; | 574 | int n_lim; |
462 | int idx; | 575 | int idx; |
463 | 576 | ||
577 | if (!ppmu) | ||
578 | return; | ||
464 | local_irq_save(flags); | 579 | local_irq_save(flags); |
465 | cpuhw = &__get_cpu_var(cpu_hw_counters); | 580 | cpuhw = &__get_cpu_var(cpu_hw_counters); |
466 | if (!cpuhw->disabled) { | 581 | if (!cpuhw->disabled) { |
@@ -479,7 +594,7 @@ void hw_perf_enable(void) | |||
479 | mtspr(SPRN_MMCRA, cpuhw->mmcr[2] & ~MMCRA_SAMPLE_ENABLE); | 594 | mtspr(SPRN_MMCRA, cpuhw->mmcr[2] & ~MMCRA_SAMPLE_ENABLE); |
480 | mtspr(SPRN_MMCR1, cpuhw->mmcr[1]); | 595 | mtspr(SPRN_MMCR1, cpuhw->mmcr[1]); |
481 | if (cpuhw->n_counters == 0) | 596 | if (cpuhw->n_counters == 0) |
482 | get_lppaca()->pmcregs_in_use = 0; | 597 | perf_set_pmu_inuse(0); |
483 | goto out_enable; | 598 | goto out_enable; |
484 | } | 599 | } |
485 | 600 | ||
@@ -512,7 +627,7 @@ void hw_perf_enable(void) | |||
512 | * bit set and set the hardware counters to their initial values. | 627 | * bit set and set the hardware counters to their initial values. |
513 | * Then unfreeze the counters. | 628 | * Then unfreeze the counters. |
514 | */ | 629 | */ |
515 | get_lppaca()->pmcregs_in_use = 1; | 630 | perf_set_pmu_inuse(1); |
516 | mtspr(SPRN_MMCRA, cpuhw->mmcr[2] & ~MMCRA_SAMPLE_ENABLE); | 631 | mtspr(SPRN_MMCRA, cpuhw->mmcr[2] & ~MMCRA_SAMPLE_ENABLE); |
517 | mtspr(SPRN_MMCR1, cpuhw->mmcr[1]); | 632 | mtspr(SPRN_MMCR1, cpuhw->mmcr[1]); |
518 | mtspr(SPRN_MMCR0, (cpuhw->mmcr[0] & ~(MMCR0_PMC1CE | MMCR0_PMCjCE)) | 633 | mtspr(SPRN_MMCR0, (cpuhw->mmcr[0] & ~(MMCR0_PMC1CE | MMCR0_PMCjCE)) |
@@ -626,6 +741,8 @@ int hw_perf_group_sched_in(struct perf_counter *group_leader, | |||
626 | long i, n, n0; | 741 | long i, n, n0; |
627 | struct perf_counter *sub; | 742 | struct perf_counter *sub; |
628 | 743 | ||
744 | if (!ppmu) | ||
745 | return 0; | ||
629 | cpuhw = &__get_cpu_var(cpu_hw_counters); | 746 | cpuhw = &__get_cpu_var(cpu_hw_counters); |
630 | n0 = cpuhw->n_counters; | 747 | n0 = cpuhw->n_counters; |
631 | n = collect_events(group_leader, ppmu->n_counter - n0, | 748 | n = collect_events(group_leader, ppmu->n_counter - n0, |
@@ -913,6 +1030,8 @@ const struct pmu *hw_perf_counter_init(struct perf_counter *counter) | |||
913 | case PERF_TYPE_RAW: | 1030 | case PERF_TYPE_RAW: |
914 | ev = counter->attr.config; | 1031 | ev = counter->attr.config; |
915 | break; | 1032 | break; |
1033 | default: | ||
1034 | return ERR_PTR(-EINVAL); | ||
916 | } | 1035 | } |
917 | counter->hw.config_base = ev; | 1036 | counter->hw.config_base = ev; |
918 | counter->hw.idx = 0; | 1037 | counter->hw.idx = 0; |
@@ -1007,13 +1126,12 @@ const struct pmu *hw_perf_counter_init(struct perf_counter *counter) | |||
1007 | * things if requested. Note that interrupts are hard-disabled | 1126 | * things if requested. Note that interrupts are hard-disabled |
1008 | * here so there is no possibility of being interrupted. | 1127 | * here so there is no possibility of being interrupted. |
1009 | */ | 1128 | */ |
1010 | static void record_and_restart(struct perf_counter *counter, long val, | 1129 | static void record_and_restart(struct perf_counter *counter, unsigned long val, |
1011 | struct pt_regs *regs, int nmi) | 1130 | struct pt_regs *regs, int nmi) |
1012 | { | 1131 | { |
1013 | u64 period = counter->hw.sample_period; | 1132 | u64 period = counter->hw.sample_period; |
1014 | s64 prev, delta, left; | 1133 | s64 prev, delta, left; |
1015 | int record = 0; | 1134 | int record = 0; |
1016 | u64 addr, mmcra, sdsync; | ||
1017 | 1135 | ||
1018 | /* we don't have to worry about interrupts here */ | 1136 | /* we don't have to worry about interrupts here */ |
1019 | prev = atomic64_read(&counter->hw.prev_count); | 1137 | prev = atomic64_read(&counter->hw.prev_count); |
@@ -1033,8 +1151,8 @@ static void record_and_restart(struct perf_counter *counter, long val, | |||
1033 | left = period; | 1151 | left = period; |
1034 | record = 1; | 1152 | record = 1; |
1035 | } | 1153 | } |
1036 | if (left < 0x80000000L) | 1154 | if (left < 0x80000000LL) |
1037 | val = 0x80000000L - left; | 1155 | val = 0x80000000LL - left; |
1038 | } | 1156 | } |
1039 | 1157 | ||
1040 | /* | 1158 | /* |
@@ -1047,22 +1165,9 @@ static void record_and_restart(struct perf_counter *counter, long val, | |||
1047 | .period = counter->hw.last_period, | 1165 | .period = counter->hw.last_period, |
1048 | }; | 1166 | }; |
1049 | 1167 | ||
1050 | if (counter->attr.sample_type & PERF_SAMPLE_ADDR) { | 1168 | if (counter->attr.sample_type & PERF_SAMPLE_ADDR) |
1051 | /* | 1169 | perf_get_data_addr(regs, &data.addr); |
1052 | * The user wants a data address recorded. | 1170 | |
1053 | * If we're not doing instruction sampling, | ||
1054 | * give them the SDAR (sampled data address). | ||
1055 | * If we are doing instruction sampling, then only | ||
1056 | * give them the SDAR if it corresponds to the | ||
1057 | * instruction pointed to by SIAR; this is indicated | ||
1058 | * by the [POWER6_]MMCRA_SDSYNC bit in MMCRA. | ||
1059 | */ | ||
1060 | mmcra = regs->dsisr; | ||
1061 | sdsync = (ppmu->flags & PPMU_ALT_SIPR) ? | ||
1062 | POWER6_MMCRA_SDSYNC : MMCRA_SDSYNC; | ||
1063 | if (!(mmcra & MMCRA_SAMPLE_ENABLE) || (mmcra & sdsync)) | ||
1064 | data.addr = mfspr(SPRN_SDAR); | ||
1065 | } | ||
1066 | if (perf_counter_overflow(counter, nmi, &data)) { | 1171 | if (perf_counter_overflow(counter, nmi, &data)) { |
1067 | /* | 1172 | /* |
1068 | * Interrupts are coming too fast - throttle them | 1173 | * Interrupts are coming too fast - throttle them |
@@ -1088,25 +1193,12 @@ static void record_and_restart(struct perf_counter *counter, long val, | |||
1088 | */ | 1193 | */ |
1089 | unsigned long perf_misc_flags(struct pt_regs *regs) | 1194 | unsigned long perf_misc_flags(struct pt_regs *regs) |
1090 | { | 1195 | { |
1091 | unsigned long mmcra; | 1196 | u32 flags = perf_get_misc_flags(regs); |
1092 | |||
1093 | if (TRAP(regs) != 0xf00) { | ||
1094 | /* not a PMU interrupt */ | ||
1095 | return user_mode(regs) ? PERF_EVENT_MISC_USER : | ||
1096 | PERF_EVENT_MISC_KERNEL; | ||
1097 | } | ||
1098 | 1197 | ||
1099 | mmcra = regs->dsisr; | 1198 | if (flags) |
1100 | if (ppmu->flags & PPMU_ALT_SIPR) { | 1199 | return flags; |
1101 | if (mmcra & POWER6_MMCRA_SIHV) | 1200 | return user_mode(regs) ? PERF_EVENT_MISC_USER : |
1102 | return PERF_EVENT_MISC_HYPERVISOR; | 1201 | PERF_EVENT_MISC_KERNEL; |
1103 | return (mmcra & POWER6_MMCRA_SIPR) ? PERF_EVENT_MISC_USER : | ||
1104 | PERF_EVENT_MISC_KERNEL; | ||
1105 | } | ||
1106 | if (mmcra & MMCRA_SIHV) | ||
1107 | return PERF_EVENT_MISC_HYPERVISOR; | ||
1108 | return (mmcra & MMCRA_SIPR) ? PERF_EVENT_MISC_USER : | ||
1109 | PERF_EVENT_MISC_KERNEL; | ||
1110 | } | 1202 | } |
1111 | 1203 | ||
1112 | /* | 1204 | /* |
@@ -1115,20 +1207,12 @@ unsigned long perf_misc_flags(struct pt_regs *regs) | |||
1115 | */ | 1207 | */ |
1116 | unsigned long perf_instruction_pointer(struct pt_regs *regs) | 1208 | unsigned long perf_instruction_pointer(struct pt_regs *regs) |
1117 | { | 1209 | { |
1118 | unsigned long mmcra; | ||
1119 | unsigned long ip; | 1210 | unsigned long ip; |
1120 | unsigned long slot; | ||
1121 | 1211 | ||
1122 | if (TRAP(regs) != 0xf00) | 1212 | if (TRAP(regs) != 0xf00) |
1123 | return regs->nip; /* not a PMU interrupt */ | 1213 | return regs->nip; /* not a PMU interrupt */ |
1124 | 1214 | ||
1125 | ip = mfspr(SPRN_SIAR); | 1215 | ip = mfspr(SPRN_SIAR) + perf_ip_adjust(regs); |
1126 | mmcra = regs->dsisr; | ||
1127 | if ((mmcra & MMCRA_SAMPLE_ENABLE) && !(ppmu->flags & PPMU_ALT_SIPR)) { | ||
1128 | slot = (mmcra & MMCRA_SLOT) >> MMCRA_SLOT_SHIFT; | ||
1129 | if (slot > 1) | ||
1130 | ip += 4 * (slot - 1); | ||
1131 | } | ||
1132 | return ip; | 1216 | return ip; |
1133 | } | 1217 | } |
1134 | 1218 | ||
@@ -1140,7 +1224,7 @@ static void perf_counter_interrupt(struct pt_regs *regs) | |||
1140 | int i; | 1224 | int i; |
1141 | struct cpu_hw_counters *cpuhw = &__get_cpu_var(cpu_hw_counters); | 1225 | struct cpu_hw_counters *cpuhw = &__get_cpu_var(cpu_hw_counters); |
1142 | struct perf_counter *counter; | 1226 | struct perf_counter *counter; |
1143 | long val; | 1227 | unsigned long val; |
1144 | int found = 0; | 1228 | int found = 0; |
1145 | int nmi; | 1229 | int nmi; |
1146 | 1230 | ||
@@ -1148,16 +1232,9 @@ static void perf_counter_interrupt(struct pt_regs *regs) | |||
1148 | freeze_limited_counters(cpuhw, mfspr(SPRN_PMC5), | 1232 | freeze_limited_counters(cpuhw, mfspr(SPRN_PMC5), |
1149 | mfspr(SPRN_PMC6)); | 1233 | mfspr(SPRN_PMC6)); |
1150 | 1234 | ||
1151 | /* | 1235 | perf_read_regs(regs); |
1152 | * Overload regs->dsisr to store MMCRA so we only need to read it once. | ||
1153 | */ | ||
1154 | regs->dsisr = mfspr(SPRN_MMCRA); | ||
1155 | 1236 | ||
1156 | /* | 1237 | nmi = perf_intr_is_nmi(regs); |
1157 | * If interrupts were soft-disabled when this PMU interrupt | ||
1158 | * occurred, treat it as an NMI. | ||
1159 | */ | ||
1160 | nmi = !regs->softe; | ||
1161 | if (nmi) | 1238 | if (nmi) |
1162 | nmi_enter(); | 1239 | nmi_enter(); |
1163 | else | 1240 | else |
@@ -1210,54 +1287,28 @@ void hw_perf_counter_setup(int cpu) | |||
1210 | { | 1287 | { |
1211 | struct cpu_hw_counters *cpuhw = &per_cpu(cpu_hw_counters, cpu); | 1288 | struct cpu_hw_counters *cpuhw = &per_cpu(cpu_hw_counters, cpu); |
1212 | 1289 | ||
1290 | if (!ppmu) | ||
1291 | return; | ||
1213 | memset(cpuhw, 0, sizeof(*cpuhw)); | 1292 | memset(cpuhw, 0, sizeof(*cpuhw)); |
1214 | cpuhw->mmcr[0] = MMCR0_FC; | 1293 | cpuhw->mmcr[0] = MMCR0_FC; |
1215 | } | 1294 | } |
1216 | 1295 | ||
1217 | extern struct power_pmu power4_pmu; | 1296 | int register_power_pmu(struct power_pmu *pmu) |
1218 | extern struct power_pmu ppc970_pmu; | ||
1219 | extern struct power_pmu power5_pmu; | ||
1220 | extern struct power_pmu power5p_pmu; | ||
1221 | extern struct power_pmu power6_pmu; | ||
1222 | extern struct power_pmu power7_pmu; | ||
1223 | |||
1224 | static int init_perf_counters(void) | ||
1225 | { | 1297 | { |
1226 | unsigned long pvr; | 1298 | if (ppmu) |
1227 | 1299 | return -EBUSY; /* something's already registered */ | |
1228 | /* XXX should get this from cputable */ | 1300 | |
1229 | pvr = mfspr(SPRN_PVR); | 1301 | ppmu = pmu; |
1230 | switch (PVR_VER(pvr)) { | 1302 | pr_info("%s performance monitor hardware support registered\n", |
1231 | case PV_POWER4: | 1303 | pmu->name); |
1232 | case PV_POWER4p: | ||
1233 | ppmu = &power4_pmu; | ||
1234 | break; | ||
1235 | case PV_970: | ||
1236 | case PV_970FX: | ||
1237 | case PV_970MP: | ||
1238 | ppmu = &ppc970_pmu; | ||
1239 | break; | ||
1240 | case PV_POWER5: | ||
1241 | ppmu = &power5_pmu; | ||
1242 | break; | ||
1243 | case PV_POWER5p: | ||
1244 | ppmu = &power5p_pmu; | ||
1245 | break; | ||
1246 | case 0x3e: | ||
1247 | ppmu = &power6_pmu; | ||
1248 | break; | ||
1249 | case 0x3f: | ||
1250 | ppmu = &power7_pmu; | ||
1251 | break; | ||
1252 | } | ||
1253 | 1304 | ||
1305 | #ifdef MSR_HV | ||
1254 | /* | 1306 | /* |
1255 | * Use FCHV to ignore kernel events if MSR.HV is set. | 1307 | * Use FCHV to ignore kernel events if MSR.HV is set. |
1256 | */ | 1308 | */ |
1257 | if (mfmsr() & MSR_HV) | 1309 | if (mfmsr() & MSR_HV) |
1258 | freeze_counters_kernel = MMCR0_FCHV; | 1310 | freeze_counters_kernel = MMCR0_FCHV; |
1311 | #endif /* CONFIG_PPC64 */ | ||
1259 | 1312 | ||
1260 | return 0; | 1313 | return 0; |
1261 | } | 1314 | } |
1262 | |||
1263 | arch_initcall(init_perf_counters); | ||
diff --git a/arch/powerpc/kernel/power4-pmu.c b/arch/powerpc/kernel/power4-pmu.c index 07bd308a5fa7..3c90a3d9173e 100644 --- a/arch/powerpc/kernel/power4-pmu.c +++ b/arch/powerpc/kernel/power4-pmu.c | |||
@@ -10,7 +10,9 @@ | |||
10 | */ | 10 | */ |
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/perf_counter.h> | 12 | #include <linux/perf_counter.h> |
13 | #include <linux/string.h> | ||
13 | #include <asm/reg.h> | 14 | #include <asm/reg.h> |
15 | #include <asm/cputable.h> | ||
14 | 16 | ||
15 | /* | 17 | /* |
16 | * Bits in event code for POWER4 | 18 | * Bits in event code for POWER4 |
@@ -179,22 +181,22 @@ static short mmcr1_adder_bits[8] = { | |||
179 | */ | 181 | */ |
180 | 182 | ||
181 | static struct unitinfo { | 183 | static struct unitinfo { |
182 | u64 value, mask; | 184 | unsigned long value, mask; |
183 | int unit; | 185 | int unit; |
184 | int lowerbit; | 186 | int lowerbit; |
185 | } p4_unitinfo[16] = { | 187 | } p4_unitinfo[16] = { |
186 | [PM_FPU] = { 0x44000000000000ull, 0x88000000000000ull, PM_FPU, 0 }, | 188 | [PM_FPU] = { 0x44000000000000ul, 0x88000000000000ul, PM_FPU, 0 }, |
187 | [PM_ISU1] = { 0x20080000000000ull, 0x88000000000000ull, PM_ISU1, 0 }, | 189 | [PM_ISU1] = { 0x20080000000000ul, 0x88000000000000ul, PM_ISU1, 0 }, |
188 | [PM_ISU1_ALT] = | 190 | [PM_ISU1_ALT] = |
189 | { 0x20080000000000ull, 0x88000000000000ull, PM_ISU1, 0 }, | 191 | { 0x20080000000000ul, 0x88000000000000ul, PM_ISU1, 0 }, |
190 | [PM_IFU] = { 0x02200000000000ull, 0x08820000000000ull, PM_IFU, 41 }, | 192 | [PM_IFU] = { 0x02200000000000ul, 0x08820000000000ul, PM_IFU, 41 }, |
191 | [PM_IFU_ALT] = | 193 | [PM_IFU_ALT] = |
192 | { 0x02200000000000ull, 0x08820000000000ull, PM_IFU, 41 }, | 194 | { 0x02200000000000ul, 0x08820000000000ul, PM_IFU, 41 }, |
193 | [PM_IDU0] = { 0x10100000000000ull, 0x80840000000000ull, PM_IDU0, 1 }, | 195 | [PM_IDU0] = { 0x10100000000000ul, 0x80840000000000ul, PM_IDU0, 1 }, |
194 | [PM_ISU2] = { 0x10140000000000ull, 0x80840000000000ull, PM_ISU2, 0 }, | 196 | [PM_ISU2] = { 0x10140000000000ul, 0x80840000000000ul, PM_ISU2, 0 }, |
195 | [PM_LSU0] = { 0x01400000000000ull, 0x08800000000000ull, PM_LSU0, 0 }, | 197 | [PM_LSU0] = { 0x01400000000000ul, 0x08800000000000ul, PM_LSU0, 0 }, |
196 | [PM_LSU1] = { 0x00000000000000ull, 0x00010000000000ull, PM_LSU1, 40 }, | 198 | [PM_LSU1] = { 0x00000000000000ul, 0x00010000000000ul, PM_LSU1, 40 }, |
197 | [PM_GPS] = { 0x00000000000000ull, 0x00000000000000ull, PM_GPS, 0 } | 199 | [PM_GPS] = { 0x00000000000000ul, 0x00000000000000ul, PM_GPS, 0 } |
198 | }; | 200 | }; |
199 | 201 | ||
200 | static unsigned char direct_marked_event[8] = { | 202 | static unsigned char direct_marked_event[8] = { |
@@ -249,10 +251,11 @@ static int p4_marked_instr_event(u64 event) | |||
249 | return (mask >> (byte * 8 + bit)) & 1; | 251 | return (mask >> (byte * 8 + bit)) & 1; |
250 | } | 252 | } |
251 | 253 | ||
252 | static int p4_get_constraint(u64 event, u64 *maskp, u64 *valp) | 254 | static int p4_get_constraint(u64 event, unsigned long *maskp, |
255 | unsigned long *valp) | ||
253 | { | 256 | { |
254 | int pmc, byte, unit, lower, sh; | 257 | int pmc, byte, unit, lower, sh; |
255 | u64 mask = 0, value = 0; | 258 | unsigned long mask = 0, value = 0; |
256 | int grp = -1; | 259 | int grp = -1; |
257 | 260 | ||
258 | pmc = (event >> PM_PMC_SH) & PM_PMC_MSK; | 261 | pmc = (event >> PM_PMC_SH) & PM_PMC_MSK; |
@@ -282,14 +285,14 @@ static int p4_get_constraint(u64 event, u64 *maskp, u64 *valp) | |||
282 | value |= p4_unitinfo[unit].value; | 285 | value |= p4_unitinfo[unit].value; |
283 | sh = p4_unitinfo[unit].lowerbit; | 286 | sh = p4_unitinfo[unit].lowerbit; |
284 | if (sh > 1) | 287 | if (sh > 1) |
285 | value |= (u64)lower << sh; | 288 | value |= (unsigned long)lower << sh; |
286 | else if (lower != sh) | 289 | else if (lower != sh) |
287 | return -1; | 290 | return -1; |
288 | unit = p4_unitinfo[unit].unit; | 291 | unit = p4_unitinfo[unit].unit; |
289 | 292 | ||
290 | /* Set byte lane select field */ | 293 | /* Set byte lane select field */ |
291 | mask |= 0xfULL << (28 - 4 * byte); | 294 | mask |= 0xfULL << (28 - 4 * byte); |
292 | value |= (u64)unit << (28 - 4 * byte); | 295 | value |= (unsigned long)unit << (28 - 4 * byte); |
293 | } | 296 | } |
294 | if (grp == 0) { | 297 | if (grp == 0) { |
295 | /* increment PMC1/2/5/6 field */ | 298 | /* increment PMC1/2/5/6 field */ |
@@ -353,9 +356,9 @@ static int p4_get_alternatives(u64 event, unsigned int flags, u64 alt[]) | |||
353 | } | 356 | } |
354 | 357 | ||
355 | static int p4_compute_mmcr(u64 event[], int n_ev, | 358 | static int p4_compute_mmcr(u64 event[], int n_ev, |
356 | unsigned int hwc[], u64 mmcr[]) | 359 | unsigned int hwc[], unsigned long mmcr[]) |
357 | { | 360 | { |
358 | u64 mmcr0 = 0, mmcr1 = 0, mmcra = 0; | 361 | unsigned long mmcr0 = 0, mmcr1 = 0, mmcra = 0; |
359 | unsigned int pmc, unit, byte, psel, lower; | 362 | unsigned int pmc, unit, byte, psel, lower; |
360 | unsigned int ttm, grp; | 363 | unsigned int ttm, grp; |
361 | unsigned int pmc_inuse = 0; | 364 | unsigned int pmc_inuse = 0; |
@@ -429,9 +432,11 @@ static int p4_compute_mmcr(u64 event[], int n_ev, | |||
429 | return -1; | 432 | return -1; |
430 | 433 | ||
431 | /* Set TTMxSEL fields. Note, units 1-3 => TTM0SEL codes 0-2 */ | 434 | /* Set TTMxSEL fields. Note, units 1-3 => TTM0SEL codes 0-2 */ |
432 | mmcr1 |= (u64)(unituse[3] * 2 + unituse[2]) << MMCR1_TTM0SEL_SH; | 435 | mmcr1 |= (unsigned long)(unituse[3] * 2 + unituse[2]) |
433 | mmcr1 |= (u64)(unituse[7] * 3 + unituse[6] * 2) << MMCR1_TTM1SEL_SH; | 436 | << MMCR1_TTM0SEL_SH; |
434 | mmcr1 |= (u64)unituse[9] << MMCR1_TTM2SEL_SH; | 437 | mmcr1 |= (unsigned long)(unituse[7] * 3 + unituse[6] * 2) |
438 | << MMCR1_TTM1SEL_SH; | ||
439 | mmcr1 |= (unsigned long)unituse[9] << MMCR1_TTM2SEL_SH; | ||
435 | 440 | ||
436 | /* Set TTCxSEL fields. */ | 441 | /* Set TTCxSEL fields. */ |
437 | if (unitlower & 0xe) | 442 | if (unitlower & 0xe) |
@@ -456,7 +461,8 @@ static int p4_compute_mmcr(u64 event[], int n_ev, | |||
456 | ttm = unit - 1; /* 2->1, 3->2 */ | 461 | ttm = unit - 1; /* 2->1, 3->2 */ |
457 | else | 462 | else |
458 | ttm = unit >> 2; | 463 | ttm = unit >> 2; |
459 | mmcr1 |= (u64)ttm << (MMCR1_TD_CP_DBG0SEL_SH - 2*byte); | 464 | mmcr1 |= (unsigned long)ttm |
465 | << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte); | ||
460 | } | 466 | } |
461 | } | 467 | } |
462 | 468 | ||
@@ -519,7 +525,7 @@ static int p4_compute_mmcr(u64 event[], int n_ev, | |||
519 | return 0; | 525 | return 0; |
520 | } | 526 | } |
521 | 527 | ||
522 | static void p4_disable_pmc(unsigned int pmc, u64 mmcr[]) | 528 | static void p4_disable_pmc(unsigned int pmc, unsigned long mmcr[]) |
523 | { | 529 | { |
524 | /* | 530 | /* |
525 | * Setting the PMCxSEL field to 0 disables PMC x. | 531 | * Setting the PMCxSEL field to 0 disables PMC x. |
@@ -583,16 +589,28 @@ static int power4_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = { | |||
583 | }, | 589 | }, |
584 | }; | 590 | }; |
585 | 591 | ||
586 | struct power_pmu power4_pmu = { | 592 | static struct power_pmu power4_pmu = { |
587 | .n_counter = 8, | 593 | .name = "POWER4/4+", |
588 | .max_alternatives = 5, | 594 | .n_counter = 8, |
589 | .add_fields = 0x0000001100005555ull, | 595 | .max_alternatives = 5, |
590 | .test_adder = 0x0011083300000000ull, | 596 | .add_fields = 0x0000001100005555ul, |
591 | .compute_mmcr = p4_compute_mmcr, | 597 | .test_adder = 0x0011083300000000ul, |
592 | .get_constraint = p4_get_constraint, | 598 | .compute_mmcr = p4_compute_mmcr, |
593 | .get_alternatives = p4_get_alternatives, | 599 | .get_constraint = p4_get_constraint, |
594 | .disable_pmc = p4_disable_pmc, | 600 | .get_alternatives = p4_get_alternatives, |
595 | .n_generic = ARRAY_SIZE(p4_generic_events), | 601 | .disable_pmc = p4_disable_pmc, |
596 | .generic_events = p4_generic_events, | 602 | .n_generic = ARRAY_SIZE(p4_generic_events), |
597 | .cache_events = &power4_cache_events, | 603 | .generic_events = p4_generic_events, |
604 | .cache_events = &power4_cache_events, | ||
598 | }; | 605 | }; |
606 | |||
607 | static int init_power4_pmu(void) | ||
608 | { | ||
609 | if (!cur_cpu_spec->oprofile_cpu_type || | ||
610 | strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power4")) | ||
611 | return -ENODEV; | ||
612 | |||
613 | return register_power_pmu(&power4_pmu); | ||
614 | } | ||
615 | |||
616 | arch_initcall(init_power4_pmu); | ||
diff --git a/arch/powerpc/kernel/power5+-pmu.c b/arch/powerpc/kernel/power5+-pmu.c index 41e5d2d958d4..31918af3e355 100644 --- a/arch/powerpc/kernel/power5+-pmu.c +++ b/arch/powerpc/kernel/power5+-pmu.c | |||
@@ -10,7 +10,9 @@ | |||
10 | */ | 10 | */ |
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/perf_counter.h> | 12 | #include <linux/perf_counter.h> |
13 | #include <linux/string.h> | ||
13 | #include <asm/reg.h> | 14 | #include <asm/reg.h> |
15 | #include <asm/cputable.h> | ||
14 | 16 | ||
15 | /* | 17 | /* |
16 | * Bits in event code for POWER5+ (POWER5 GS) and POWER5++ (POWER5 GS DD3) | 18 | * Bits in event code for POWER5+ (POWER5 GS) and POWER5++ (POWER5 GS DD3) |
@@ -126,20 +128,21 @@ static const int grsel_shift[8] = { | |||
126 | }; | 128 | }; |
127 | 129 | ||
128 | /* Masks and values for using events from the various units */ | 130 | /* Masks and values for using events from the various units */ |
129 | static u64 unit_cons[PM_LASTUNIT+1][2] = { | 131 | static unsigned long unit_cons[PM_LASTUNIT+1][2] = { |
130 | [PM_FPU] = { 0x3200000000ull, 0x0100000000ull }, | 132 | [PM_FPU] = { 0x3200000000ul, 0x0100000000ul }, |
131 | [PM_ISU0] = { 0x0200000000ull, 0x0080000000ull }, | 133 | [PM_ISU0] = { 0x0200000000ul, 0x0080000000ul }, |
132 | [PM_ISU1] = { 0x3200000000ull, 0x3100000000ull }, | 134 | [PM_ISU1] = { 0x3200000000ul, 0x3100000000ul }, |
133 | [PM_IFU] = { 0x3200000000ull, 0x2100000000ull }, | 135 | [PM_IFU] = { 0x3200000000ul, 0x2100000000ul }, |
134 | [PM_IDU] = { 0x0e00000000ull, 0x0040000000ull }, | 136 | [PM_IDU] = { 0x0e00000000ul, 0x0040000000ul }, |
135 | [PM_GRS] = { 0x0e00000000ull, 0x0c40000000ull }, | 137 | [PM_GRS] = { 0x0e00000000ul, 0x0c40000000ul }, |
136 | }; | 138 | }; |
137 | 139 | ||
138 | static int power5p_get_constraint(u64 event, u64 *maskp, u64 *valp) | 140 | static int power5p_get_constraint(u64 event, unsigned long *maskp, |
141 | unsigned long *valp) | ||
139 | { | 142 | { |
140 | int pmc, byte, unit, sh; | 143 | int pmc, byte, unit, sh; |
141 | int bit, fmask; | 144 | int bit, fmask; |
142 | u64 mask = 0, value = 0; | 145 | unsigned long mask = 0, value = 0; |
143 | 146 | ||
144 | pmc = (event >> PM_PMC_SH) & PM_PMC_MSK; | 147 | pmc = (event >> PM_PMC_SH) & PM_PMC_MSK; |
145 | if (pmc) { | 148 | if (pmc) { |
@@ -171,17 +174,18 @@ static int power5p_get_constraint(u64 event, u64 *maskp, u64 *valp) | |||
171 | bit = event & 7; | 174 | bit = event & 7; |
172 | fmask = (bit == 6)? 7: 3; | 175 | fmask = (bit == 6)? 7: 3; |
173 | sh = grsel_shift[bit]; | 176 | sh = grsel_shift[bit]; |
174 | mask |= (u64)fmask << sh; | 177 | mask |= (unsigned long)fmask << sh; |
175 | value |= (u64)((event >> PM_GRS_SH) & fmask) << sh; | 178 | value |= (unsigned long)((event >> PM_GRS_SH) & fmask) |
179 | << sh; | ||
176 | } | 180 | } |
177 | /* Set byte lane select field */ | 181 | /* Set byte lane select field */ |
178 | mask |= 0xfULL << (24 - 4 * byte); | 182 | mask |= 0xfUL << (24 - 4 * byte); |
179 | value |= (u64)unit << (24 - 4 * byte); | 183 | value |= (unsigned long)unit << (24 - 4 * byte); |
180 | } | 184 | } |
181 | if (pmc < 5) { | 185 | if (pmc < 5) { |
182 | /* need a counter from PMC1-4 set */ | 186 | /* need a counter from PMC1-4 set */ |
183 | mask |= 0x8000000000000ull; | 187 | mask |= 0x8000000000000ul; |
184 | value |= 0x1000000000000ull; | 188 | value |= 0x1000000000000ul; |
185 | } | 189 | } |
186 | *maskp = mask; | 190 | *maskp = mask; |
187 | *valp = value; | 191 | *valp = value; |
@@ -452,10 +456,10 @@ static int power5p_marked_instr_event(u64 event) | |||
452 | } | 456 | } |
453 | 457 | ||
454 | static int power5p_compute_mmcr(u64 event[], int n_ev, | 458 | static int power5p_compute_mmcr(u64 event[], int n_ev, |
455 | unsigned int hwc[], u64 mmcr[]) | 459 | unsigned int hwc[], unsigned long mmcr[]) |
456 | { | 460 | { |
457 | u64 mmcr1 = 0; | 461 | unsigned long mmcr1 = 0; |
458 | u64 mmcra = 0; | 462 | unsigned long mmcra = 0; |
459 | unsigned int pmc, unit, byte, psel; | 463 | unsigned int pmc, unit, byte, psel; |
460 | unsigned int ttm; | 464 | unsigned int ttm; |
461 | int i, isbus, bit, grsel; | 465 | int i, isbus, bit, grsel; |
@@ -517,7 +521,7 @@ static int power5p_compute_mmcr(u64 event[], int n_ev, | |||
517 | continue; | 521 | continue; |
518 | if (ttmuse++) | 522 | if (ttmuse++) |
519 | return -1; | 523 | return -1; |
520 | mmcr1 |= (u64)i << MMCR1_TTM0SEL_SH; | 524 | mmcr1 |= (unsigned long)i << MMCR1_TTM0SEL_SH; |
521 | } | 525 | } |
522 | ttmuse = 0; | 526 | ttmuse = 0; |
523 | for (; i <= PM_GRS; ++i) { | 527 | for (; i <= PM_GRS; ++i) { |
@@ -525,7 +529,7 @@ static int power5p_compute_mmcr(u64 event[], int n_ev, | |||
525 | continue; | 529 | continue; |
526 | if (ttmuse++) | 530 | if (ttmuse++) |
527 | return -1; | 531 | return -1; |
528 | mmcr1 |= (u64)(i & 3) << MMCR1_TTM1SEL_SH; | 532 | mmcr1 |= (unsigned long)(i & 3) << MMCR1_TTM1SEL_SH; |
529 | } | 533 | } |
530 | if (ttmuse > 1) | 534 | if (ttmuse > 1) |
531 | return -1; | 535 | return -1; |
@@ -540,10 +544,11 @@ static int power5p_compute_mmcr(u64 event[], int n_ev, | |||
540 | unit = PM_ISU0_ALT; | 544 | unit = PM_ISU0_ALT; |
541 | } else if (unit == PM_LSU1 + 1) { | 545 | } else if (unit == PM_LSU1 + 1) { |
542 | /* select lower word of LSU1 for this byte */ | 546 | /* select lower word of LSU1 for this byte */ |
543 | mmcr1 |= 1ull << (MMCR1_TTM3SEL_SH + 3 - byte); | 547 | mmcr1 |= 1ul << (MMCR1_TTM3SEL_SH + 3 - byte); |
544 | } | 548 | } |
545 | ttm = unit >> 2; | 549 | ttm = unit >> 2; |
546 | mmcr1 |= (u64)ttm << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte); | 550 | mmcr1 |= (unsigned long)ttm |
551 | << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte); | ||
547 | } | 552 | } |
548 | 553 | ||
549 | /* Second pass: assign PMCs, set PMCxSEL and PMCx_ADDER_SEL fields */ | 554 | /* Second pass: assign PMCs, set PMCxSEL and PMCx_ADDER_SEL fields */ |
@@ -568,7 +573,7 @@ static int power5p_compute_mmcr(u64 event[], int n_ev, | |||
568 | if (isbus && (byte & 2) && | 573 | if (isbus && (byte & 2) && |
569 | (psel == 8 || psel == 0x10 || psel == 0x28)) | 574 | (psel == 8 || psel == 0x10 || psel == 0x28)) |
570 | /* add events on higher-numbered bus */ | 575 | /* add events on higher-numbered bus */ |
571 | mmcr1 |= 1ull << (MMCR1_PMC1_ADDER_SEL_SH - pmc); | 576 | mmcr1 |= 1ul << (MMCR1_PMC1_ADDER_SEL_SH - pmc); |
572 | } else { | 577 | } else { |
573 | /* Instructions or run cycles on PMC5/6 */ | 578 | /* Instructions or run cycles on PMC5/6 */ |
574 | --pmc; | 579 | --pmc; |
@@ -576,7 +581,7 @@ static int power5p_compute_mmcr(u64 event[], int n_ev, | |||
576 | if (isbus && unit == PM_GRS) { | 581 | if (isbus && unit == PM_GRS) { |
577 | bit = psel & 7; | 582 | bit = psel & 7; |
578 | grsel = (event[i] >> PM_GRS_SH) & PM_GRS_MSK; | 583 | grsel = (event[i] >> PM_GRS_SH) & PM_GRS_MSK; |
579 | mmcr1 |= (u64)grsel << grsel_shift[bit]; | 584 | mmcr1 |= (unsigned long)grsel << grsel_shift[bit]; |
580 | } | 585 | } |
581 | if (power5p_marked_instr_event(event[i])) | 586 | if (power5p_marked_instr_event(event[i])) |
582 | mmcra |= MMCRA_SAMPLE_ENABLE; | 587 | mmcra |= MMCRA_SAMPLE_ENABLE; |
@@ -599,7 +604,7 @@ static int power5p_compute_mmcr(u64 event[], int n_ev, | |||
599 | return 0; | 604 | return 0; |
600 | } | 605 | } |
601 | 606 | ||
602 | static void power5p_disable_pmc(unsigned int pmc, u64 mmcr[]) | 607 | static void power5p_disable_pmc(unsigned int pmc, unsigned long mmcr[]) |
603 | { | 608 | { |
604 | if (pmc <= 3) | 609 | if (pmc <= 3) |
605 | mmcr[1] &= ~(0x7fUL << MMCR1_PMCSEL_SH(pmc)); | 610 | mmcr[1] &= ~(0x7fUL << MMCR1_PMCSEL_SH(pmc)); |
@@ -654,18 +659,31 @@ static int power5p_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = { | |||
654 | }, | 659 | }, |
655 | }; | 660 | }; |
656 | 661 | ||
657 | struct power_pmu power5p_pmu = { | 662 | static struct power_pmu power5p_pmu = { |
658 | .n_counter = 6, | 663 | .name = "POWER5+/++", |
659 | .max_alternatives = MAX_ALT, | 664 | .n_counter = 6, |
660 | .add_fields = 0x7000000000055ull, | 665 | .max_alternatives = MAX_ALT, |
661 | .test_adder = 0x3000040000000ull, | 666 | .add_fields = 0x7000000000055ul, |
662 | .compute_mmcr = power5p_compute_mmcr, | 667 | .test_adder = 0x3000040000000ul, |
663 | .get_constraint = power5p_get_constraint, | 668 | .compute_mmcr = power5p_compute_mmcr, |
664 | .get_alternatives = power5p_get_alternatives, | 669 | .get_constraint = power5p_get_constraint, |
665 | .disable_pmc = power5p_disable_pmc, | 670 | .get_alternatives = power5p_get_alternatives, |
666 | .limited_pmc_event = power5p_limited_pmc_event, | 671 | .disable_pmc = power5p_disable_pmc, |
667 | .flags = PPMU_LIMITED_PMC5_6, | 672 | .limited_pmc_event = power5p_limited_pmc_event, |
668 | .n_generic = ARRAY_SIZE(power5p_generic_events), | 673 | .flags = PPMU_LIMITED_PMC5_6, |
669 | .generic_events = power5p_generic_events, | 674 | .n_generic = ARRAY_SIZE(power5p_generic_events), |
670 | .cache_events = &power5p_cache_events, | 675 | .generic_events = power5p_generic_events, |
676 | .cache_events = &power5p_cache_events, | ||
671 | }; | 677 | }; |
678 | |||
679 | static int init_power5p_pmu(void) | ||
680 | { | ||
681 | if (!cur_cpu_spec->oprofile_cpu_type || | ||
682 | (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power5+") | ||
683 | && strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power5++"))) | ||
684 | return -ENODEV; | ||
685 | |||
686 | return register_power_pmu(&power5p_pmu); | ||
687 | } | ||
688 | |||
689 | arch_initcall(init_power5p_pmu); | ||
diff --git a/arch/powerpc/kernel/power5-pmu.c b/arch/powerpc/kernel/power5-pmu.c index 05600b66221a..867f6f663963 100644 --- a/arch/powerpc/kernel/power5-pmu.c +++ b/arch/powerpc/kernel/power5-pmu.c | |||
@@ -10,7 +10,9 @@ | |||
10 | */ | 10 | */ |
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/perf_counter.h> | 12 | #include <linux/perf_counter.h> |
13 | #include <linux/string.h> | ||
13 | #include <asm/reg.h> | 14 | #include <asm/reg.h> |
15 | #include <asm/cputable.h> | ||
14 | 16 | ||
15 | /* | 17 | /* |
16 | * Bits in event code for POWER5 (not POWER5++) | 18 | * Bits in event code for POWER5 (not POWER5++) |
@@ -130,20 +132,21 @@ static const int grsel_shift[8] = { | |||
130 | }; | 132 | }; |
131 | 133 | ||
132 | /* Masks and values for using events from the various units */ | 134 | /* Masks and values for using events from the various units */ |
133 | static u64 unit_cons[PM_LASTUNIT+1][2] = { | 135 | static unsigned long unit_cons[PM_LASTUNIT+1][2] = { |
134 | [PM_FPU] = { 0xc0002000000000ull, 0x00001000000000ull }, | 136 | [PM_FPU] = { 0xc0002000000000ul, 0x00001000000000ul }, |
135 | [PM_ISU0] = { 0x00002000000000ull, 0x00000800000000ull }, | 137 | [PM_ISU0] = { 0x00002000000000ul, 0x00000800000000ul }, |
136 | [PM_ISU1] = { 0xc0002000000000ull, 0xc0001000000000ull }, | 138 | [PM_ISU1] = { 0xc0002000000000ul, 0xc0001000000000ul }, |
137 | [PM_IFU] = { 0xc0002000000000ull, 0x80001000000000ull }, | 139 | [PM_IFU] = { 0xc0002000000000ul, 0x80001000000000ul }, |
138 | [PM_IDU] = { 0x30002000000000ull, 0x00000400000000ull }, | 140 | [PM_IDU] = { 0x30002000000000ul, 0x00000400000000ul }, |
139 | [PM_GRS] = { 0x30002000000000ull, 0x30000400000000ull }, | 141 | [PM_GRS] = { 0x30002000000000ul, 0x30000400000000ul }, |
140 | }; | 142 | }; |
141 | 143 | ||
142 | static int power5_get_constraint(u64 event, u64 *maskp, u64 *valp) | 144 | static int power5_get_constraint(u64 event, unsigned long *maskp, |
145 | unsigned long *valp) | ||
143 | { | 146 | { |
144 | int pmc, byte, unit, sh; | 147 | int pmc, byte, unit, sh; |
145 | int bit, fmask; | 148 | int bit, fmask; |
146 | u64 mask = 0, value = 0; | 149 | unsigned long mask = 0, value = 0; |
147 | int grp = -1; | 150 | int grp = -1; |
148 | 151 | ||
149 | pmc = (event >> PM_PMC_SH) & PM_PMC_MSK; | 152 | pmc = (event >> PM_PMC_SH) & PM_PMC_MSK; |
@@ -178,8 +181,9 @@ static int power5_get_constraint(u64 event, u64 *maskp, u64 *valp) | |||
178 | bit = event & 7; | 181 | bit = event & 7; |
179 | fmask = (bit == 6)? 7: 3; | 182 | fmask = (bit == 6)? 7: 3; |
180 | sh = grsel_shift[bit]; | 183 | sh = grsel_shift[bit]; |
181 | mask |= (u64)fmask << sh; | 184 | mask |= (unsigned long)fmask << sh; |
182 | value |= (u64)((event >> PM_GRS_SH) & fmask) << sh; | 185 | value |= (unsigned long)((event >> PM_GRS_SH) & fmask) |
186 | << sh; | ||
183 | } | 187 | } |
184 | /* | 188 | /* |
185 | * Bus events on bytes 0 and 2 can be counted | 189 | * Bus events on bytes 0 and 2 can be counted |
@@ -188,22 +192,22 @@ static int power5_get_constraint(u64 event, u64 *maskp, u64 *valp) | |||
188 | if (!pmc) | 192 | if (!pmc) |
189 | grp = byte & 1; | 193 | grp = byte & 1; |
190 | /* Set byte lane select field */ | 194 | /* Set byte lane select field */ |
191 | mask |= 0xfULL << (24 - 4 * byte); | 195 | mask |= 0xfUL << (24 - 4 * byte); |
192 | value |= (u64)unit << (24 - 4 * byte); | 196 | value |= (unsigned long)unit << (24 - 4 * byte); |
193 | } | 197 | } |
194 | if (grp == 0) { | 198 | if (grp == 0) { |
195 | /* increment PMC1/2 field */ | 199 | /* increment PMC1/2 field */ |
196 | mask |= 0x200000000ull; | 200 | mask |= 0x200000000ul; |
197 | value |= 0x080000000ull; | 201 | value |= 0x080000000ul; |
198 | } else if (grp == 1) { | 202 | } else if (grp == 1) { |
199 | /* increment PMC3/4 field */ | 203 | /* increment PMC3/4 field */ |
200 | mask |= 0x40000000ull; | 204 | mask |= 0x40000000ul; |
201 | value |= 0x10000000ull; | 205 | value |= 0x10000000ul; |
202 | } | 206 | } |
203 | if (pmc < 5) { | 207 | if (pmc < 5) { |
204 | /* need a counter from PMC1-4 set */ | 208 | /* need a counter from PMC1-4 set */ |
205 | mask |= 0x8000000000000ull; | 209 | mask |= 0x8000000000000ul; |
206 | value |= 0x1000000000000ull; | 210 | value |= 0x1000000000000ul; |
207 | } | 211 | } |
208 | *maskp = mask; | 212 | *maskp = mask; |
209 | *valp = value; | 213 | *valp = value; |
@@ -383,10 +387,10 @@ static int power5_marked_instr_event(u64 event) | |||
383 | } | 387 | } |
384 | 388 | ||
385 | static int power5_compute_mmcr(u64 event[], int n_ev, | 389 | static int power5_compute_mmcr(u64 event[], int n_ev, |
386 | unsigned int hwc[], u64 mmcr[]) | 390 | unsigned int hwc[], unsigned long mmcr[]) |
387 | { | 391 | { |
388 | u64 mmcr1 = 0; | 392 | unsigned long mmcr1 = 0; |
389 | u64 mmcra = 0; | 393 | unsigned long mmcra = 0; |
390 | unsigned int pmc, unit, byte, psel; | 394 | unsigned int pmc, unit, byte, psel; |
391 | unsigned int ttm, grp; | 395 | unsigned int ttm, grp; |
392 | int i, isbus, bit, grsel; | 396 | int i, isbus, bit, grsel; |
@@ -457,7 +461,7 @@ static int power5_compute_mmcr(u64 event[], int n_ev, | |||
457 | continue; | 461 | continue; |
458 | if (ttmuse++) | 462 | if (ttmuse++) |
459 | return -1; | 463 | return -1; |
460 | mmcr1 |= (u64)i << MMCR1_TTM0SEL_SH; | 464 | mmcr1 |= (unsigned long)i << MMCR1_TTM0SEL_SH; |
461 | } | 465 | } |
462 | ttmuse = 0; | 466 | ttmuse = 0; |
463 | for (; i <= PM_GRS; ++i) { | 467 | for (; i <= PM_GRS; ++i) { |
@@ -465,7 +469,7 @@ static int power5_compute_mmcr(u64 event[], int n_ev, | |||
465 | continue; | 469 | continue; |
466 | if (ttmuse++) | 470 | if (ttmuse++) |
467 | return -1; | 471 | return -1; |
468 | mmcr1 |= (u64)(i & 3) << MMCR1_TTM1SEL_SH; | 472 | mmcr1 |= (unsigned long)(i & 3) << MMCR1_TTM1SEL_SH; |
469 | } | 473 | } |
470 | if (ttmuse > 1) | 474 | if (ttmuse > 1) |
471 | return -1; | 475 | return -1; |
@@ -480,10 +484,11 @@ static int power5_compute_mmcr(u64 event[], int n_ev, | |||
480 | unit = PM_ISU0_ALT; | 484 | unit = PM_ISU0_ALT; |
481 | } else if (unit == PM_LSU1 + 1) { | 485 | } else if (unit == PM_LSU1 + 1) { |
482 | /* select lower word of LSU1 for this byte */ | 486 | /* select lower word of LSU1 for this byte */ |
483 | mmcr1 |= 1ull << (MMCR1_TTM3SEL_SH + 3 - byte); | 487 | mmcr1 |= 1ul << (MMCR1_TTM3SEL_SH + 3 - byte); |
484 | } | 488 | } |
485 | ttm = unit >> 2; | 489 | ttm = unit >> 2; |
486 | mmcr1 |= (u64)ttm << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte); | 490 | mmcr1 |= (unsigned long)ttm |
491 | << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte); | ||
487 | } | 492 | } |
488 | 493 | ||
489 | /* Second pass: assign PMCs, set PMCxSEL and PMCx_ADDER_SEL fields */ | 494 | /* Second pass: assign PMCs, set PMCxSEL and PMCx_ADDER_SEL fields */ |
@@ -513,7 +518,7 @@ static int power5_compute_mmcr(u64 event[], int n_ev, | |||
513 | --pmc; | 518 | --pmc; |
514 | if ((psel == 8 || psel == 0x10) && isbus && (byte & 2)) | 519 | if ((psel == 8 || psel == 0x10) && isbus && (byte & 2)) |
515 | /* add events on higher-numbered bus */ | 520 | /* add events on higher-numbered bus */ |
516 | mmcr1 |= 1ull << (MMCR1_PMC1_ADDER_SEL_SH - pmc); | 521 | mmcr1 |= 1ul << (MMCR1_PMC1_ADDER_SEL_SH - pmc); |
517 | } else { | 522 | } else { |
518 | /* Instructions or run cycles on PMC5/6 */ | 523 | /* Instructions or run cycles on PMC5/6 */ |
519 | --pmc; | 524 | --pmc; |
@@ -521,7 +526,7 @@ static int power5_compute_mmcr(u64 event[], int n_ev, | |||
521 | if (isbus && unit == PM_GRS) { | 526 | if (isbus && unit == PM_GRS) { |
522 | bit = psel & 7; | 527 | bit = psel & 7; |
523 | grsel = (event[i] >> PM_GRS_SH) & PM_GRS_MSK; | 528 | grsel = (event[i] >> PM_GRS_SH) & PM_GRS_MSK; |
524 | mmcr1 |= (u64)grsel << grsel_shift[bit]; | 529 | mmcr1 |= (unsigned long)grsel << grsel_shift[bit]; |
525 | } | 530 | } |
526 | if (power5_marked_instr_event(event[i])) | 531 | if (power5_marked_instr_event(event[i])) |
527 | mmcra |= MMCRA_SAMPLE_ENABLE; | 532 | mmcra |= MMCRA_SAMPLE_ENABLE; |
@@ -541,7 +546,7 @@ static int power5_compute_mmcr(u64 event[], int n_ev, | |||
541 | return 0; | 546 | return 0; |
542 | } | 547 | } |
543 | 548 | ||
544 | static void power5_disable_pmc(unsigned int pmc, u64 mmcr[]) | 549 | static void power5_disable_pmc(unsigned int pmc, unsigned long mmcr[]) |
545 | { | 550 | { |
546 | if (pmc <= 3) | 551 | if (pmc <= 3) |
547 | mmcr[1] &= ~(0x7fUL << MMCR1_PMCSEL_SH(pmc)); | 552 | mmcr[1] &= ~(0x7fUL << MMCR1_PMCSEL_SH(pmc)); |
@@ -596,16 +601,28 @@ static int power5_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = { | |||
596 | }, | 601 | }, |
597 | }; | 602 | }; |
598 | 603 | ||
599 | struct power_pmu power5_pmu = { | 604 | static struct power_pmu power5_pmu = { |
600 | .n_counter = 6, | 605 | .name = "POWER5", |
601 | .max_alternatives = MAX_ALT, | 606 | .n_counter = 6, |
602 | .add_fields = 0x7000090000555ull, | 607 | .max_alternatives = MAX_ALT, |
603 | .test_adder = 0x3000490000000ull, | 608 | .add_fields = 0x7000090000555ul, |
604 | .compute_mmcr = power5_compute_mmcr, | 609 | .test_adder = 0x3000490000000ul, |
605 | .get_constraint = power5_get_constraint, | 610 | .compute_mmcr = power5_compute_mmcr, |
606 | .get_alternatives = power5_get_alternatives, | 611 | .get_constraint = power5_get_constraint, |
607 | .disable_pmc = power5_disable_pmc, | 612 | .get_alternatives = power5_get_alternatives, |
608 | .n_generic = ARRAY_SIZE(power5_generic_events), | 613 | .disable_pmc = power5_disable_pmc, |
609 | .generic_events = power5_generic_events, | 614 | .n_generic = ARRAY_SIZE(power5_generic_events), |
610 | .cache_events = &power5_cache_events, | 615 | .generic_events = power5_generic_events, |
616 | .cache_events = &power5_cache_events, | ||
611 | }; | 617 | }; |
618 | |||
619 | static int init_power5_pmu(void) | ||
620 | { | ||
621 | if (!cur_cpu_spec->oprofile_cpu_type || | ||
622 | strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power5")) | ||
623 | return -ENODEV; | ||
624 | |||
625 | return register_power_pmu(&power5_pmu); | ||
626 | } | ||
627 | |||
628 | arch_initcall(init_power5_pmu); | ||
diff --git a/arch/powerpc/kernel/power6-pmu.c b/arch/powerpc/kernel/power6-pmu.c index 46f74bebcfd9..fa21890531da 100644 --- a/arch/powerpc/kernel/power6-pmu.c +++ b/arch/powerpc/kernel/power6-pmu.c | |||
@@ -10,7 +10,9 @@ | |||
10 | */ | 10 | */ |
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/perf_counter.h> | 12 | #include <linux/perf_counter.h> |
13 | #include <linux/string.h> | ||
13 | #include <asm/reg.h> | 14 | #include <asm/reg.h> |
15 | #include <asm/cputable.h> | ||
14 | 16 | ||
15 | /* | 17 | /* |
16 | * Bits in event code for POWER6 | 18 | * Bits in event code for POWER6 |
@@ -41,9 +43,9 @@ | |||
41 | #define MMCR1_NESTSEL_SH 45 | 43 | #define MMCR1_NESTSEL_SH 45 |
42 | #define MMCR1_NESTSEL_MSK 0x7 | 44 | #define MMCR1_NESTSEL_MSK 0x7 |
43 | #define MMCR1_NESTSEL(m) (((m) >> MMCR1_NESTSEL_SH) & MMCR1_NESTSEL_MSK) | 45 | #define MMCR1_NESTSEL(m) (((m) >> MMCR1_NESTSEL_SH) & MMCR1_NESTSEL_MSK) |
44 | #define MMCR1_PMC1_LLA ((u64)1 << 44) | 46 | #define MMCR1_PMC1_LLA (1ul << 44) |
45 | #define MMCR1_PMC1_LLA_VALUE ((u64)1 << 39) | 47 | #define MMCR1_PMC1_LLA_VALUE (1ul << 39) |
46 | #define MMCR1_PMC1_ADDR_SEL ((u64)1 << 35) | 48 | #define MMCR1_PMC1_ADDR_SEL (1ul << 35) |
47 | #define MMCR1_PMC1SEL_SH 24 | 49 | #define MMCR1_PMC1SEL_SH 24 |
48 | #define MMCR1_PMCSEL_SH(n) (MMCR1_PMC1SEL_SH - (n) * 8) | 50 | #define MMCR1_PMCSEL_SH(n) (MMCR1_PMC1SEL_SH - (n) * 8) |
49 | #define MMCR1_PMCSEL_MSK 0xff | 51 | #define MMCR1_PMCSEL_MSK 0xff |
@@ -173,10 +175,10 @@ static int power6_marked_instr_event(u64 event) | |||
173 | * Assign PMC numbers and compute MMCR1 value for a set of events | 175 | * Assign PMC numbers and compute MMCR1 value for a set of events |
174 | */ | 176 | */ |
175 | static int p6_compute_mmcr(u64 event[], int n_ev, | 177 | static int p6_compute_mmcr(u64 event[], int n_ev, |
176 | unsigned int hwc[], u64 mmcr[]) | 178 | unsigned int hwc[], unsigned long mmcr[]) |
177 | { | 179 | { |
178 | u64 mmcr1 = 0; | 180 | unsigned long mmcr1 = 0; |
179 | u64 mmcra = 0; | 181 | unsigned long mmcra = 0; |
180 | int i; | 182 | int i; |
181 | unsigned int pmc, ev, b, u, s, psel; | 183 | unsigned int pmc, ev, b, u, s, psel; |
182 | unsigned int ttmset = 0; | 184 | unsigned int ttmset = 0; |
@@ -215,7 +217,7 @@ static int p6_compute_mmcr(u64 event[], int n_ev, | |||
215 | /* check for conflict on this byte of event bus */ | 217 | /* check for conflict on this byte of event bus */ |
216 | if ((ttmset & (1 << b)) && MMCR1_TTMSEL(mmcr1, b) != u) | 218 | if ((ttmset & (1 << b)) && MMCR1_TTMSEL(mmcr1, b) != u) |
217 | return -1; | 219 | return -1; |
218 | mmcr1 |= (u64)u << MMCR1_TTMSEL_SH(b); | 220 | mmcr1 |= (unsigned long)u << MMCR1_TTMSEL_SH(b); |
219 | ttmset |= 1 << b; | 221 | ttmset |= 1 << b; |
220 | if (u == 5) { | 222 | if (u == 5) { |
221 | /* Nest events have a further mux */ | 223 | /* Nest events have a further mux */ |
@@ -224,7 +226,7 @@ static int p6_compute_mmcr(u64 event[], int n_ev, | |||
224 | MMCR1_NESTSEL(mmcr1) != s) | 226 | MMCR1_NESTSEL(mmcr1) != s) |
225 | return -1; | 227 | return -1; |
226 | ttmset |= 0x10; | 228 | ttmset |= 0x10; |
227 | mmcr1 |= (u64)s << MMCR1_NESTSEL_SH; | 229 | mmcr1 |= (unsigned long)s << MMCR1_NESTSEL_SH; |
228 | } | 230 | } |
229 | if (0x30 <= psel && psel <= 0x3d) { | 231 | if (0x30 <= psel && psel <= 0x3d) { |
230 | /* these need the PMCx_ADDR_SEL bits */ | 232 | /* these need the PMCx_ADDR_SEL bits */ |
@@ -243,7 +245,7 @@ static int p6_compute_mmcr(u64 event[], int n_ev, | |||
243 | if (power6_marked_instr_event(event[i])) | 245 | if (power6_marked_instr_event(event[i])) |
244 | mmcra |= MMCRA_SAMPLE_ENABLE; | 246 | mmcra |= MMCRA_SAMPLE_ENABLE; |
245 | if (pmc < 4) | 247 | if (pmc < 4) |
246 | mmcr1 |= (u64)psel << MMCR1_PMCSEL_SH(pmc); | 248 | mmcr1 |= (unsigned long)psel << MMCR1_PMCSEL_SH(pmc); |
247 | } | 249 | } |
248 | mmcr[0] = 0; | 250 | mmcr[0] = 0; |
249 | if (pmc_inuse & 1) | 251 | if (pmc_inuse & 1) |
@@ -265,10 +267,11 @@ static int p6_compute_mmcr(u64 event[], int n_ev, | |||
265 | * 20-23, 24-27, 28-31 ditto for bytes 1, 2, 3 | 267 | * 20-23, 24-27, 28-31 ditto for bytes 1, 2, 3 |
266 | * 32-34 select field: nest (subunit) event selector | 268 | * 32-34 select field: nest (subunit) event selector |
267 | */ | 269 | */ |
268 | static int p6_get_constraint(u64 event, u64 *maskp, u64 *valp) | 270 | static int p6_get_constraint(u64 event, unsigned long *maskp, |
271 | unsigned long *valp) | ||
269 | { | 272 | { |
270 | int pmc, byte, sh, subunit; | 273 | int pmc, byte, sh, subunit; |
271 | u64 mask = 0, value = 0; | 274 | unsigned long mask = 0, value = 0; |
272 | 275 | ||
273 | pmc = (event >> PM_PMC_SH) & PM_PMC_MSK; | 276 | pmc = (event >> PM_PMC_SH) & PM_PMC_MSK; |
274 | if (pmc) { | 277 | if (pmc) { |
@@ -282,11 +285,11 @@ static int p6_get_constraint(u64 event, u64 *maskp, u64 *valp) | |||
282 | byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK; | 285 | byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK; |
283 | sh = byte * 4 + (16 - PM_UNIT_SH); | 286 | sh = byte * 4 + (16 - PM_UNIT_SH); |
284 | mask |= PM_UNIT_MSKS << sh; | 287 | mask |= PM_UNIT_MSKS << sh; |
285 | value |= (u64)(event & PM_UNIT_MSKS) << sh; | 288 | value |= (unsigned long)(event & PM_UNIT_MSKS) << sh; |
286 | if ((event & PM_UNIT_MSKS) == (5 << PM_UNIT_SH)) { | 289 | if ((event & PM_UNIT_MSKS) == (5 << PM_UNIT_SH)) { |
287 | subunit = (event >> PM_SUBUNIT_SH) & PM_SUBUNIT_MSK; | 290 | subunit = (event >> PM_SUBUNIT_SH) & PM_SUBUNIT_MSK; |
288 | mask |= (u64)PM_SUBUNIT_MSK << 32; | 291 | mask |= (unsigned long)PM_SUBUNIT_MSK << 32; |
289 | value |= (u64)subunit << 32; | 292 | value |= (unsigned long)subunit << 32; |
290 | } | 293 | } |
291 | } | 294 | } |
292 | if (pmc <= 4) { | 295 | if (pmc <= 4) { |
@@ -458,7 +461,7 @@ static int p6_get_alternatives(u64 event, unsigned int flags, u64 alt[]) | |||
458 | return nalt; | 461 | return nalt; |
459 | } | 462 | } |
460 | 463 | ||
461 | static void p6_disable_pmc(unsigned int pmc, u64 mmcr[]) | 464 | static void p6_disable_pmc(unsigned int pmc, unsigned long mmcr[]) |
462 | { | 465 | { |
463 | /* Set PMCxSEL to 0 to disable PMCx */ | 466 | /* Set PMCxSEL to 0 to disable PMCx */ |
464 | if (pmc <= 3) | 467 | if (pmc <= 3) |
@@ -515,18 +518,30 @@ static int power6_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = { | |||
515 | }, | 518 | }, |
516 | }; | 519 | }; |
517 | 520 | ||
518 | struct power_pmu power6_pmu = { | 521 | static struct power_pmu power6_pmu = { |
519 | .n_counter = 6, | 522 | .name = "POWER6", |
520 | .max_alternatives = MAX_ALT, | 523 | .n_counter = 6, |
521 | .add_fields = 0x1555, | 524 | .max_alternatives = MAX_ALT, |
522 | .test_adder = 0x3000, | 525 | .add_fields = 0x1555, |
523 | .compute_mmcr = p6_compute_mmcr, | 526 | .test_adder = 0x3000, |
524 | .get_constraint = p6_get_constraint, | 527 | .compute_mmcr = p6_compute_mmcr, |
525 | .get_alternatives = p6_get_alternatives, | 528 | .get_constraint = p6_get_constraint, |
526 | .disable_pmc = p6_disable_pmc, | 529 | .get_alternatives = p6_get_alternatives, |
527 | .limited_pmc_event = p6_limited_pmc_event, | 530 | .disable_pmc = p6_disable_pmc, |
528 | .flags = PPMU_LIMITED_PMC5_6 | PPMU_ALT_SIPR, | 531 | .limited_pmc_event = p6_limited_pmc_event, |
529 | .n_generic = ARRAY_SIZE(power6_generic_events), | 532 | .flags = PPMU_LIMITED_PMC5_6 | PPMU_ALT_SIPR, |
530 | .generic_events = power6_generic_events, | 533 | .n_generic = ARRAY_SIZE(power6_generic_events), |
531 | .cache_events = &power6_cache_events, | 534 | .generic_events = power6_generic_events, |
535 | .cache_events = &power6_cache_events, | ||
532 | }; | 536 | }; |
537 | |||
538 | static int init_power6_pmu(void) | ||
539 | { | ||
540 | if (!cur_cpu_spec->oprofile_cpu_type || | ||
541 | strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power6")) | ||
542 | return -ENODEV; | ||
543 | |||
544 | return register_power_pmu(&power6_pmu); | ||
545 | } | ||
546 | |||
547 | arch_initcall(init_power6_pmu); | ||
diff --git a/arch/powerpc/kernel/power7-pmu.c b/arch/powerpc/kernel/power7-pmu.c index b72e7a19d054..018d094d92f9 100644 --- a/arch/powerpc/kernel/power7-pmu.c +++ b/arch/powerpc/kernel/power7-pmu.c | |||
@@ -10,7 +10,9 @@ | |||
10 | */ | 10 | */ |
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/perf_counter.h> | 12 | #include <linux/perf_counter.h> |
13 | #include <linux/string.h> | ||
13 | #include <asm/reg.h> | 14 | #include <asm/reg.h> |
15 | #include <asm/cputable.h> | ||
14 | 16 | ||
15 | /* | 17 | /* |
16 | * Bits in event code for POWER7 | 18 | * Bits in event code for POWER7 |
@@ -71,10 +73,11 @@ | |||
71 | * 0-9: Count of events needing PMC1..PMC5 | 73 | * 0-9: Count of events needing PMC1..PMC5 |
72 | */ | 74 | */ |
73 | 75 | ||
74 | static int power7_get_constraint(u64 event, u64 *maskp, u64 *valp) | 76 | static int power7_get_constraint(u64 event, unsigned long *maskp, |
77 | unsigned long *valp) | ||
75 | { | 78 | { |
76 | int pmc, sh; | 79 | int pmc, sh; |
77 | u64 mask = 0, value = 0; | 80 | unsigned long mask = 0, value = 0; |
78 | 81 | ||
79 | pmc = (event >> PM_PMC_SH) & PM_PMC_MSK; | 82 | pmc = (event >> PM_PMC_SH) & PM_PMC_MSK; |
80 | if (pmc) { | 83 | if (pmc) { |
@@ -224,10 +227,10 @@ static int power7_marked_instr_event(u64 event) | |||
224 | } | 227 | } |
225 | 228 | ||
226 | static int power7_compute_mmcr(u64 event[], int n_ev, | 229 | static int power7_compute_mmcr(u64 event[], int n_ev, |
227 | unsigned int hwc[], u64 mmcr[]) | 230 | unsigned int hwc[], unsigned long mmcr[]) |
228 | { | 231 | { |
229 | u64 mmcr1 = 0; | 232 | unsigned long mmcr1 = 0; |
230 | u64 mmcra = 0; | 233 | unsigned long mmcra = 0; |
231 | unsigned int pmc, unit, combine, l2sel, psel; | 234 | unsigned int pmc, unit, combine, l2sel, psel; |
232 | unsigned int pmc_inuse = 0; | 235 | unsigned int pmc_inuse = 0; |
233 | int i; | 236 | int i; |
@@ -265,11 +268,14 @@ static int power7_compute_mmcr(u64 event[], int n_ev, | |||
265 | --pmc; | 268 | --pmc; |
266 | } | 269 | } |
267 | if (pmc <= 3) { | 270 | if (pmc <= 3) { |
268 | mmcr1 |= (u64) unit << (MMCR1_TTM0SEL_SH - 4 * pmc); | 271 | mmcr1 |= (unsigned long) unit |
269 | mmcr1 |= (u64) combine << (MMCR1_PMC1_COMBINE_SH - pmc); | 272 | << (MMCR1_TTM0SEL_SH - 4 * pmc); |
273 | mmcr1 |= (unsigned long) combine | ||
274 | << (MMCR1_PMC1_COMBINE_SH - pmc); | ||
270 | mmcr1 |= psel << MMCR1_PMCSEL_SH(pmc); | 275 | mmcr1 |= psel << MMCR1_PMCSEL_SH(pmc); |
271 | if (unit == 6) /* L2 events */ | 276 | if (unit == 6) /* L2 events */ |
272 | mmcr1 |= (u64) l2sel << MMCR1_L2SEL_SH; | 277 | mmcr1 |= (unsigned long) l2sel |
278 | << MMCR1_L2SEL_SH; | ||
273 | } | 279 | } |
274 | if (power7_marked_instr_event(event[i])) | 280 | if (power7_marked_instr_event(event[i])) |
275 | mmcra |= MMCRA_SAMPLE_ENABLE; | 281 | mmcra |= MMCRA_SAMPLE_ENABLE; |
@@ -287,10 +293,10 @@ static int power7_compute_mmcr(u64 event[], int n_ev, | |||
287 | return 0; | 293 | return 0; |
288 | } | 294 | } |
289 | 295 | ||
290 | static void power7_disable_pmc(unsigned int pmc, u64 mmcr[]) | 296 | static void power7_disable_pmc(unsigned int pmc, unsigned long mmcr[]) |
291 | { | 297 | { |
292 | if (pmc <= 3) | 298 | if (pmc <= 3) |
293 | mmcr[1] &= ~(0xffULL << MMCR1_PMCSEL_SH(pmc)); | 299 | mmcr[1] &= ~(0xffUL << MMCR1_PMCSEL_SH(pmc)); |
294 | } | 300 | } |
295 | 301 | ||
296 | static int power7_generic_events[] = { | 302 | static int power7_generic_events[] = { |
@@ -311,7 +317,7 @@ static int power7_generic_events[] = { | |||
311 | */ | 317 | */ |
312 | static int power7_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = { | 318 | static int power7_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = { |
313 | [C(L1D)] = { /* RESULT_ACCESS RESULT_MISS */ | 319 | [C(L1D)] = { /* RESULT_ACCESS RESULT_MISS */ |
314 | [C(OP_READ)] = { 0x400f0, 0xc880 }, | 320 | [C(OP_READ)] = { 0xc880, 0x400f0 }, |
315 | [C(OP_WRITE)] = { 0, 0x300f0 }, | 321 | [C(OP_WRITE)] = { 0, 0x300f0 }, |
316 | [C(OP_PREFETCH)] = { 0xd8b8, 0 }, | 322 | [C(OP_PREFETCH)] = { 0xd8b8, 0 }, |
317 | }, | 323 | }, |
@@ -321,8 +327,8 @@ static int power7_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = { | |||
321 | [C(OP_PREFETCH)] = { 0x408a, 0 }, | 327 | [C(OP_PREFETCH)] = { 0x408a, 0 }, |
322 | }, | 328 | }, |
323 | [C(LL)] = { /* RESULT_ACCESS RESULT_MISS */ | 329 | [C(LL)] = { /* RESULT_ACCESS RESULT_MISS */ |
324 | [C(OP_READ)] = { 0x6080, 0x6084 }, | 330 | [C(OP_READ)] = { 0x16080, 0x26080 }, |
325 | [C(OP_WRITE)] = { 0x6082, 0x6086 }, | 331 | [C(OP_WRITE)] = { 0x16082, 0x26082 }, |
326 | [C(OP_PREFETCH)] = { 0, 0 }, | 332 | [C(OP_PREFETCH)] = { 0, 0 }, |
327 | }, | 333 | }, |
328 | [C(DTLB)] = { /* RESULT_ACCESS RESULT_MISS */ | 334 | [C(DTLB)] = { /* RESULT_ACCESS RESULT_MISS */ |
@@ -342,16 +348,29 @@ static int power7_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = { | |||
342 | }, | 348 | }, |
343 | }; | 349 | }; |
344 | 350 | ||
345 | struct power_pmu power7_pmu = { | 351 | static struct power_pmu power7_pmu = { |
346 | .n_counter = 6, | 352 | .name = "POWER7", |
347 | .max_alternatives = MAX_ALT + 1, | 353 | .n_counter = 6, |
348 | .add_fields = 0x1555ull, | 354 | .max_alternatives = MAX_ALT + 1, |
349 | .test_adder = 0x3000ull, | 355 | .add_fields = 0x1555ul, |
350 | .compute_mmcr = power7_compute_mmcr, | 356 | .test_adder = 0x3000ul, |
351 | .get_constraint = power7_get_constraint, | 357 | .compute_mmcr = power7_compute_mmcr, |
352 | .get_alternatives = power7_get_alternatives, | 358 | .get_constraint = power7_get_constraint, |
353 | .disable_pmc = power7_disable_pmc, | 359 | .get_alternatives = power7_get_alternatives, |
354 | .n_generic = ARRAY_SIZE(power7_generic_events), | 360 | .disable_pmc = power7_disable_pmc, |
355 | .generic_events = power7_generic_events, | 361 | .flags = PPMU_ALT_SIPR, |
356 | .cache_events = &power7_cache_events, | 362 | .n_generic = ARRAY_SIZE(power7_generic_events), |
363 | .generic_events = power7_generic_events, | ||
364 | .cache_events = &power7_cache_events, | ||
357 | }; | 365 | }; |
366 | |||
367 | static int init_power7_pmu(void) | ||
368 | { | ||
369 | if (!cur_cpu_spec->oprofile_cpu_type || | ||
370 | strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power7")) | ||
371 | return -ENODEV; | ||
372 | |||
373 | return register_power_pmu(&power7_pmu); | ||
374 | } | ||
375 | |||
376 | arch_initcall(init_power7_pmu); | ||
diff --git a/arch/powerpc/kernel/ppc970-pmu.c b/arch/powerpc/kernel/ppc970-pmu.c index ba0a357a89f4..75dccb71a043 100644 --- a/arch/powerpc/kernel/ppc970-pmu.c +++ b/arch/powerpc/kernel/ppc970-pmu.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/string.h> | 11 | #include <linux/string.h> |
12 | #include <linux/perf_counter.h> | 12 | #include <linux/perf_counter.h> |
13 | #include <asm/reg.h> | 13 | #include <asm/reg.h> |
14 | #include <asm/cputable.h> | ||
14 | 15 | ||
15 | /* | 16 | /* |
16 | * Bits in event code for PPC970 | 17 | * Bits in event code for PPC970 |
@@ -183,7 +184,7 @@ static int p970_marked_instr_event(u64 event) | |||
183 | } | 184 | } |
184 | 185 | ||
185 | /* Masks and values for using events from the various units */ | 186 | /* Masks and values for using events from the various units */ |
186 | static u64 unit_cons[PM_LASTUNIT+1][2] = { | 187 | static unsigned long unit_cons[PM_LASTUNIT+1][2] = { |
187 | [PM_FPU] = { 0xc80000000000ull, 0x040000000000ull }, | 188 | [PM_FPU] = { 0xc80000000000ull, 0x040000000000ull }, |
188 | [PM_VPU] = { 0xc80000000000ull, 0xc40000000000ull }, | 189 | [PM_VPU] = { 0xc80000000000ull, 0xc40000000000ull }, |
189 | [PM_ISU] = { 0x080000000000ull, 0x020000000000ull }, | 190 | [PM_ISU] = { 0x080000000000ull, 0x020000000000ull }, |
@@ -192,10 +193,11 @@ static u64 unit_cons[PM_LASTUNIT+1][2] = { | |||
192 | [PM_STS] = { 0x380000000000ull, 0x310000000000ull }, | 193 | [PM_STS] = { 0x380000000000ull, 0x310000000000ull }, |
193 | }; | 194 | }; |
194 | 195 | ||
195 | static int p970_get_constraint(u64 event, u64 *maskp, u64 *valp) | 196 | static int p970_get_constraint(u64 event, unsigned long *maskp, |
197 | unsigned long *valp) | ||
196 | { | 198 | { |
197 | int pmc, byte, unit, sh, spcsel; | 199 | int pmc, byte, unit, sh, spcsel; |
198 | u64 mask = 0, value = 0; | 200 | unsigned long mask = 0, value = 0; |
199 | int grp = -1; | 201 | int grp = -1; |
200 | 202 | ||
201 | pmc = (event >> PM_PMC_SH) & PM_PMC_MSK; | 203 | pmc = (event >> PM_PMC_SH) & PM_PMC_MSK; |
@@ -222,7 +224,7 @@ static int p970_get_constraint(u64 event, u64 *maskp, u64 *valp) | |||
222 | grp = byte & 1; | 224 | grp = byte & 1; |
223 | /* Set byte lane select field */ | 225 | /* Set byte lane select field */ |
224 | mask |= 0xfULL << (28 - 4 * byte); | 226 | mask |= 0xfULL << (28 - 4 * byte); |
225 | value |= (u64)unit << (28 - 4 * byte); | 227 | value |= (unsigned long)unit << (28 - 4 * byte); |
226 | } | 228 | } |
227 | if (grp == 0) { | 229 | if (grp == 0) { |
228 | /* increment PMC1/2/5/6 field */ | 230 | /* increment PMC1/2/5/6 field */ |
@@ -236,7 +238,7 @@ static int p970_get_constraint(u64 event, u64 *maskp, u64 *valp) | |||
236 | spcsel = (event >> PM_SPCSEL_SH) & PM_SPCSEL_MSK; | 238 | spcsel = (event >> PM_SPCSEL_SH) & PM_SPCSEL_MSK; |
237 | if (spcsel) { | 239 | if (spcsel) { |
238 | mask |= 3ull << 48; | 240 | mask |= 3ull << 48; |
239 | value |= (u64)spcsel << 48; | 241 | value |= (unsigned long)spcsel << 48; |
240 | } | 242 | } |
241 | *maskp = mask; | 243 | *maskp = mask; |
242 | *valp = value; | 244 | *valp = value; |
@@ -257,9 +259,9 @@ static int p970_get_alternatives(u64 event, unsigned int flags, u64 alt[]) | |||
257 | } | 259 | } |
258 | 260 | ||
259 | static int p970_compute_mmcr(u64 event[], int n_ev, | 261 | static int p970_compute_mmcr(u64 event[], int n_ev, |
260 | unsigned int hwc[], u64 mmcr[]) | 262 | unsigned int hwc[], unsigned long mmcr[]) |
261 | { | 263 | { |
262 | u64 mmcr0 = 0, mmcr1 = 0, mmcra = 0; | 264 | unsigned long mmcr0 = 0, mmcr1 = 0, mmcra = 0; |
263 | unsigned int pmc, unit, byte, psel; | 265 | unsigned int pmc, unit, byte, psel; |
264 | unsigned int ttm, grp; | 266 | unsigned int ttm, grp; |
265 | unsigned int pmc_inuse = 0; | 267 | unsigned int pmc_inuse = 0; |
@@ -320,7 +322,7 @@ static int p970_compute_mmcr(u64 event[], int n_ev, | |||
320 | continue; | 322 | continue; |
321 | ttm = unitmap[i]; | 323 | ttm = unitmap[i]; |
322 | ++ttmuse[(ttm >> 2) & 1]; | 324 | ++ttmuse[(ttm >> 2) & 1]; |
323 | mmcr1 |= (u64)(ttm & ~4) << MMCR1_TTM1SEL_SH; | 325 | mmcr1 |= (unsigned long)(ttm & ~4) << MMCR1_TTM1SEL_SH; |
324 | } | 326 | } |
325 | /* Check only one unit per TTMx */ | 327 | /* Check only one unit per TTMx */ |
326 | if (ttmuse[0] > 1 || ttmuse[1] > 1) | 328 | if (ttmuse[0] > 1 || ttmuse[1] > 1) |
@@ -340,7 +342,8 @@ static int p970_compute_mmcr(u64 event[], int n_ev, | |||
340 | if (unit == PM_LSU1L && byte >= 2) | 342 | if (unit == PM_LSU1L && byte >= 2) |
341 | mmcr1 |= 1ull << (MMCR1_TTM3SEL_SH + 3 - byte); | 343 | mmcr1 |= 1ull << (MMCR1_TTM3SEL_SH + 3 - byte); |
342 | } | 344 | } |
343 | mmcr1 |= (u64)ttm << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte); | 345 | mmcr1 |= (unsigned long)ttm |
346 | << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte); | ||
344 | } | 347 | } |
345 | 348 | ||
346 | /* Second pass: assign PMCs, set PMCxSEL and PMCx_ADDER_SEL fields */ | 349 | /* Second pass: assign PMCs, set PMCxSEL and PMCx_ADDER_SEL fields */ |
@@ -386,7 +389,8 @@ static int p970_compute_mmcr(u64 event[], int n_ev, | |||
386 | for (pmc = 0; pmc < 2; ++pmc) | 389 | for (pmc = 0; pmc < 2; ++pmc) |
387 | mmcr0 |= pmcsel[pmc] << (MMCR0_PMC1SEL_SH - 7 * pmc); | 390 | mmcr0 |= pmcsel[pmc] << (MMCR0_PMC1SEL_SH - 7 * pmc); |
388 | for (; pmc < 8; ++pmc) | 391 | for (; pmc < 8; ++pmc) |
389 | mmcr1 |= (u64)pmcsel[pmc] << (MMCR1_PMC3SEL_SH - 5 * (pmc - 2)); | 392 | mmcr1 |= (unsigned long)pmcsel[pmc] |
393 | << (MMCR1_PMC3SEL_SH - 5 * (pmc - 2)); | ||
390 | if (pmc_inuse & 1) | 394 | if (pmc_inuse & 1) |
391 | mmcr0 |= MMCR0_PMC1CE; | 395 | mmcr0 |= MMCR0_PMC1CE; |
392 | if (pmc_inuse & 0xfe) | 396 | if (pmc_inuse & 0xfe) |
@@ -401,7 +405,7 @@ static int p970_compute_mmcr(u64 event[], int n_ev, | |||
401 | return 0; | 405 | return 0; |
402 | } | 406 | } |
403 | 407 | ||
404 | static void p970_disable_pmc(unsigned int pmc, u64 mmcr[]) | 408 | static void p970_disable_pmc(unsigned int pmc, unsigned long mmcr[]) |
405 | { | 409 | { |
406 | int shift, i; | 410 | int shift, i; |
407 | 411 | ||
@@ -467,16 +471,29 @@ static int ppc970_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = { | |||
467 | }, | 471 | }, |
468 | }; | 472 | }; |
469 | 473 | ||
470 | struct power_pmu ppc970_pmu = { | 474 | static struct power_pmu ppc970_pmu = { |
471 | .n_counter = 8, | 475 | .name = "PPC970/FX/MP", |
472 | .max_alternatives = 2, | 476 | .n_counter = 8, |
473 | .add_fields = 0x001100005555ull, | 477 | .max_alternatives = 2, |
474 | .test_adder = 0x013300000000ull, | 478 | .add_fields = 0x001100005555ull, |
475 | .compute_mmcr = p970_compute_mmcr, | 479 | .test_adder = 0x013300000000ull, |
476 | .get_constraint = p970_get_constraint, | 480 | .compute_mmcr = p970_compute_mmcr, |
477 | .get_alternatives = p970_get_alternatives, | 481 | .get_constraint = p970_get_constraint, |
478 | .disable_pmc = p970_disable_pmc, | 482 | .get_alternatives = p970_get_alternatives, |
479 | .n_generic = ARRAY_SIZE(ppc970_generic_events), | 483 | .disable_pmc = p970_disable_pmc, |
480 | .generic_events = ppc970_generic_events, | 484 | .n_generic = ARRAY_SIZE(ppc970_generic_events), |
481 | .cache_events = &ppc970_cache_events, | 485 | .generic_events = ppc970_generic_events, |
486 | .cache_events = &ppc970_cache_events, | ||
482 | }; | 487 | }; |
488 | |||
489 | static int init_ppc970_pmu(void) | ||
490 | { | ||
491 | if (!cur_cpu_spec->oprofile_cpu_type || | ||
492 | (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/970") | ||
493 | && strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/970MP"))) | ||
494 | return -ENODEV; | ||
495 | |||
496 | return register_power_pmu(&ppc970_pmu); | ||
497 | } | ||
498 | |||
499 | arch_initcall(init_ppc970_pmu); | ||
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 3e7135bbe40f..892a9f2e6d76 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -528,7 +528,7 @@ void show_regs(struct pt_regs * regs) | |||
528 | 528 | ||
529 | for (i = 0; i < 32; i++) { | 529 | for (i = 0; i < 32; i++) { |
530 | if ((i % REGS_PER_LINE) == 0) | 530 | if ((i % REGS_PER_LINE) == 0) |
531 | printk("\n" KERN_INFO "GPR%02d: ", i); | 531 | printk("\nGPR%02d: ", i); |
532 | printk(REG " ", regs->gpr[i]); | 532 | printk(REG " ", regs->gpr[i]); |
533 | if (i == LAST_VOLATILE && !FULL_REGS(regs)) | 533 | if (i == LAST_VOLATILE && !FULL_REGS(regs)) |
534 | break; | 534 | break; |
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index ef6f64950e9b..a538824616fd 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
@@ -1947,8 +1947,47 @@ static void __init fixup_device_tree_maple(void) | |||
1947 | prom_setprop(isa, name, "ranges", | 1947 | prom_setprop(isa, name, "ranges", |
1948 | isa_ranges, sizeof(isa_ranges)); | 1948 | isa_ranges, sizeof(isa_ranges)); |
1949 | } | 1949 | } |
1950 | |||
1951 | #define CPC925_MC_START 0xf8000000 | ||
1952 | #define CPC925_MC_LENGTH 0x1000000 | ||
1953 | /* The values for memory-controller don't have right number of cells */ | ||
1954 | static void __init fixup_device_tree_maple_memory_controller(void) | ||
1955 | { | ||
1956 | phandle mc; | ||
1957 | u32 mc_reg[4]; | ||
1958 | char *name = "/hostbridge@f8000000"; | ||
1959 | struct prom_t *_prom = &RELOC(prom); | ||
1960 | u32 ac, sc; | ||
1961 | |||
1962 | mc = call_prom("finddevice", 1, 1, ADDR(name)); | ||
1963 | if (!PHANDLE_VALID(mc)) | ||
1964 | return; | ||
1965 | |||
1966 | if (prom_getproplen(mc, "reg") != 8) | ||
1967 | return; | ||
1968 | |||
1969 | prom_getprop(_prom->root, "#address-cells", &ac, sizeof(ac)); | ||
1970 | prom_getprop(_prom->root, "#size-cells", &sc, sizeof(sc)); | ||
1971 | if ((ac != 2) || (sc != 2)) | ||
1972 | return; | ||
1973 | |||
1974 | if (prom_getprop(mc, "reg", mc_reg, sizeof(mc_reg)) == PROM_ERROR) | ||
1975 | return; | ||
1976 | |||
1977 | if (mc_reg[0] != CPC925_MC_START || mc_reg[1] != CPC925_MC_LENGTH) | ||
1978 | return; | ||
1979 | |||
1980 | prom_printf("Fixing up bogus hostbridge on Maple...\n"); | ||
1981 | |||
1982 | mc_reg[0] = 0x0; | ||
1983 | mc_reg[1] = CPC925_MC_START; | ||
1984 | mc_reg[2] = 0x0; | ||
1985 | mc_reg[3] = CPC925_MC_LENGTH; | ||
1986 | prom_setprop(mc, name, "reg", mc_reg, sizeof(mc_reg)); | ||
1987 | } | ||
1950 | #else | 1988 | #else |
1951 | #define fixup_device_tree_maple() | 1989 | #define fixup_device_tree_maple() |
1990 | #define fixup_device_tree_maple_memory_controller() | ||
1952 | #endif | 1991 | #endif |
1953 | 1992 | ||
1954 | #ifdef CONFIG_PPC_CHRP | 1993 | #ifdef CONFIG_PPC_CHRP |
@@ -2189,6 +2228,7 @@ static void __init fixup_device_tree_efika(void) | |||
2189 | static void __init fixup_device_tree(void) | 2228 | static void __init fixup_device_tree(void) |
2190 | { | 2229 | { |
2191 | fixup_device_tree_maple(); | 2230 | fixup_device_tree_maple(); |
2231 | fixup_device_tree_maple_memory_controller(); | ||
2192 | fixup_device_tree_chrp(); | 2232 | fixup_device_tree_chrp(); |
2193 | fixup_device_tree_pmac(); | 2233 | fixup_device_tree_pmac(); |
2194 | fixup_device_tree_efika(); | 2234 | fixup_device_tree_efika(); |
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 9fa2c7dcd05a..ef149880c145 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c | |||
@@ -736,15 +736,16 @@ void user_disable_single_step(struct task_struct *task) | |||
736 | { | 736 | { |
737 | struct pt_regs *regs = task->thread.regs; | 737 | struct pt_regs *regs = task->thread.regs; |
738 | 738 | ||
739 | |||
740 | #if defined(CONFIG_BOOKE) | ||
741 | /* If DAC then do not single step, skip */ | ||
742 | if (task->thread.dabr) | ||
743 | return; | ||
744 | #endif | ||
745 | |||
746 | if (regs != NULL) { | 739 | if (regs != NULL) { |
747 | #if defined(CONFIG_40x) || defined(CONFIG_BOOKE) | 740 | #if defined(CONFIG_BOOKE) |
741 | /* If DAC don't clear DBCRO_IDM or MSR_DE */ | ||
742 | if (task->thread.dabr) | ||
743 | task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT); | ||
744 | else { | ||
745 | task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT | DBCR0_IDM); | ||
746 | regs->msr &= ~MSR_DE; | ||
747 | } | ||
748 | #elif defined(CONFIG_40x) | ||
748 | task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT | DBCR0_IDM); | 749 | task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT | DBCR0_IDM); |
749 | regs->msr &= ~MSR_DE; | 750 | regs->msr &= ~MSR_DE; |
750 | #else | 751 | #else |
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c index 297632cba047..8a6daf4129f6 100644 --- a/arch/powerpc/kernel/ptrace32.c +++ b/arch/powerpc/kernel/ptrace32.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/sched.h> | 21 | #include <linux/sched.h> |
22 | #include <linux/mm.h> | 22 | #include <linux/mm.h> |
23 | #include <linux/smp.h> | 23 | #include <linux/smp.h> |
24 | #include <linux/smp_lock.h> | ||
25 | #include <linux/errno.h> | 24 | #include <linux/errno.h> |
26 | #include <linux/ptrace.h> | 25 | #include <linux/ptrace.h> |
27 | #include <linux/regset.h> | 26 | #include <linux/regset.h> |
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index ee4c7609b649..c434823b8c83 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c | |||
@@ -38,9 +38,10 @@ | |||
38 | #include <asm/syscalls.h> | 38 | #include <asm/syscalls.h> |
39 | #include <asm/smp.h> | 39 | #include <asm/smp.h> |
40 | #include <asm/atomic.h> | 40 | #include <asm/atomic.h> |
41 | #include <asm/time.h> | ||
41 | 42 | ||
42 | struct rtas_t rtas = { | 43 | struct rtas_t rtas = { |
43 | .lock = SPIN_LOCK_UNLOCKED | 44 | .lock = __RAW_SPIN_LOCK_UNLOCKED |
44 | }; | 45 | }; |
45 | EXPORT_SYMBOL(rtas); | 46 | EXPORT_SYMBOL(rtas); |
46 | 47 | ||
@@ -67,6 +68,28 @@ unsigned long rtas_rmo_buf; | |||
67 | void (*rtas_flash_term_hook)(int); | 68 | void (*rtas_flash_term_hook)(int); |
68 | EXPORT_SYMBOL(rtas_flash_term_hook); | 69 | EXPORT_SYMBOL(rtas_flash_term_hook); |
69 | 70 | ||
71 | /* RTAS use home made raw locking instead of spin_lock_irqsave | ||
72 | * because those can be called from within really nasty contexts | ||
73 | * such as having the timebase stopped which would lockup with | ||
74 | * normal locks and spinlock debugging enabled | ||
75 | */ | ||
76 | static unsigned long lock_rtas(void) | ||
77 | { | ||
78 | unsigned long flags; | ||
79 | |||
80 | local_irq_save(flags); | ||
81 | preempt_disable(); | ||
82 | __raw_spin_lock_flags(&rtas.lock, flags); | ||
83 | return flags; | ||
84 | } | ||
85 | |||
86 | static void unlock_rtas(unsigned long flags) | ||
87 | { | ||
88 | __raw_spin_unlock(&rtas.lock); | ||
89 | local_irq_restore(flags); | ||
90 | preempt_enable(); | ||
91 | } | ||
92 | |||
70 | /* | 93 | /* |
71 | * call_rtas_display_status and call_rtas_display_status_delay | 94 | * call_rtas_display_status and call_rtas_display_status_delay |
72 | * are designed only for very early low-level debugging, which | 95 | * are designed only for very early low-level debugging, which |
@@ -79,7 +102,7 @@ static void call_rtas_display_status(char c) | |||
79 | 102 | ||
80 | if (!rtas.base) | 103 | if (!rtas.base) |
81 | return; | 104 | return; |
82 | spin_lock_irqsave(&rtas.lock, s); | 105 | s = lock_rtas(); |
83 | 106 | ||
84 | args->token = 10; | 107 | args->token = 10; |
85 | args->nargs = 1; | 108 | args->nargs = 1; |
@@ -89,7 +112,7 @@ static void call_rtas_display_status(char c) | |||
89 | 112 | ||
90 | enter_rtas(__pa(args)); | 113 | enter_rtas(__pa(args)); |
91 | 114 | ||
92 | spin_unlock_irqrestore(&rtas.lock, s); | 115 | unlock_rtas(s); |
93 | } | 116 | } |
94 | 117 | ||
95 | static void call_rtas_display_status_delay(char c) | 118 | static void call_rtas_display_status_delay(char c) |
@@ -411,8 +434,7 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...) | |||
411 | if (!rtas.entry || token == RTAS_UNKNOWN_SERVICE) | 434 | if (!rtas.entry || token == RTAS_UNKNOWN_SERVICE) |
412 | return -1; | 435 | return -1; |
413 | 436 | ||
414 | /* Gotta do something different here, use global lock for now... */ | 437 | s = lock_rtas(); |
415 | spin_lock_irqsave(&rtas.lock, s); | ||
416 | rtas_args = &rtas.args; | 438 | rtas_args = &rtas.args; |
417 | 439 | ||
418 | rtas_args->token = token; | 440 | rtas_args->token = token; |
@@ -439,8 +461,7 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...) | |||
439 | outputs[i] = rtas_args->rets[i+1]; | 461 | outputs[i] = rtas_args->rets[i+1]; |
440 | ret = (nret > 0)? rtas_args->rets[0]: 0; | 462 | ret = (nret > 0)? rtas_args->rets[0]: 0; |
441 | 463 | ||
442 | /* Gotta do something different here, use global lock for now... */ | 464 | unlock_rtas(s); |
443 | spin_unlock_irqrestore(&rtas.lock, s); | ||
444 | 465 | ||
445 | if (buff_copy) { | 466 | if (buff_copy) { |
446 | log_error(buff_copy, ERR_TYPE_RTAS_LOG, 0); | 467 | log_error(buff_copy, ERR_TYPE_RTAS_LOG, 0); |
@@ -837,7 +858,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) | |||
837 | 858 | ||
838 | buff_copy = get_errorlog_buffer(); | 859 | buff_copy = get_errorlog_buffer(); |
839 | 860 | ||
840 | spin_lock_irqsave(&rtas.lock, flags); | 861 | flags = lock_rtas(); |
841 | 862 | ||
842 | rtas.args = args; | 863 | rtas.args = args; |
843 | enter_rtas(__pa(&rtas.args)); | 864 | enter_rtas(__pa(&rtas.args)); |
@@ -848,7 +869,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) | |||
848 | if (args.rets[0] == -1) | 869 | if (args.rets[0] == -1) |
849 | errbuf = __fetch_rtas_last_error(buff_copy); | 870 | errbuf = __fetch_rtas_last_error(buff_copy); |
850 | 871 | ||
851 | spin_unlock_irqrestore(&rtas.lock, flags); | 872 | unlock_rtas(flags); |
852 | 873 | ||
853 | if (buff_copy) { | 874 | if (buff_copy) { |
854 | if (errbuf) | 875 | if (errbuf) |
@@ -951,3 +972,33 @@ int __init early_init_dt_scan_rtas(unsigned long node, | |||
951 | /* break now */ | 972 | /* break now */ |
952 | return 1; | 973 | return 1; |
953 | } | 974 | } |
975 | |||
976 | static raw_spinlock_t timebase_lock; | ||
977 | static u64 timebase = 0; | ||
978 | |||
979 | void __cpuinit rtas_give_timebase(void) | ||
980 | { | ||
981 | unsigned long flags; | ||
982 | |||
983 | local_irq_save(flags); | ||
984 | hard_irq_disable(); | ||
985 | __raw_spin_lock(&timebase_lock); | ||
986 | rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL); | ||
987 | timebase = get_tb(); | ||
988 | __raw_spin_unlock(&timebase_lock); | ||
989 | |||
990 | while (timebase) | ||
991 | barrier(); | ||
992 | rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL); | ||
993 | local_irq_restore(flags); | ||
994 | } | ||
995 | |||
996 | void __cpuinit rtas_take_timebase(void) | ||
997 | { | ||
998 | while (!timebase) | ||
999 | barrier(); | ||
1000 | __raw_spin_lock(&timebase_lock); | ||
1001 | set_tb(timebase >> 32, timebase & 0xffffffff); | ||
1002 | timebase = 0; | ||
1003 | __raw_spin_unlock(&timebase_lock); | ||
1004 | } | ||
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 1d154248cf40..e1e3059cf34b 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c | |||
@@ -119,6 +119,8 @@ notrace unsigned long __init early_init(unsigned long dt_ptr) | |||
119 | */ | 119 | */ |
120 | notrace void __init machine_init(unsigned long dt_ptr) | 120 | notrace void __init machine_init(unsigned long dt_ptr) |
121 | { | 121 | { |
122 | lockdep_init(); | ||
123 | |||
122 | /* Enable early debugging if any specified (see udbg.h) */ | 124 | /* Enable early debugging if any specified (see udbg.h) */ |
123 | udbg_early_init(); | 125 | udbg_early_init(); |
124 | 126 | ||
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 65484b2200b3..0b47de07302d 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
@@ -68,7 +68,8 @@ EXPORT_PER_CPU_SYMBOL(cpu_core_map); | |||
68 | /* SMP operations for this machine */ | 68 | /* SMP operations for this machine */ |
69 | struct smp_ops_t *smp_ops; | 69 | struct smp_ops_t *smp_ops; |
70 | 70 | ||
71 | static volatile unsigned int cpu_callin_map[NR_CPUS]; | 71 | /* Can't be static due to PowerMac hackery */ |
72 | volatile unsigned int cpu_callin_map[NR_CPUS]; | ||
72 | 73 | ||
73 | int smt_enabled_at_boot = 1; | 74 | int smt_enabled_at_boot = 1; |
74 | 75 | ||
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 15391c2ab013..eae4511ceeac 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -53,6 +53,7 @@ | |||
53 | #include <linux/posix-timers.h> | 53 | #include <linux/posix-timers.h> |
54 | #include <linux/irq.h> | 54 | #include <linux/irq.h> |
55 | #include <linux/delay.h> | 55 | #include <linux/delay.h> |
56 | #include <linux/perf_counter.h> | ||
56 | 57 | ||
57 | #include <asm/io.h> | 58 | #include <asm/io.h> |
58 | #include <asm/processor.h> | 59 | #include <asm/processor.h> |
@@ -525,6 +526,26 @@ void __init iSeries_time_init_early(void) | |||
525 | } | 526 | } |
526 | #endif /* CONFIG_PPC_ISERIES */ | 527 | #endif /* CONFIG_PPC_ISERIES */ |
527 | 528 | ||
529 | #if defined(CONFIG_PERF_COUNTERS) && defined(CONFIG_PPC32) | ||
530 | DEFINE_PER_CPU(u8, perf_counter_pending); | ||
531 | |||
532 | void set_perf_counter_pending(void) | ||
533 | { | ||
534 | get_cpu_var(perf_counter_pending) = 1; | ||
535 | set_dec(1); | ||
536 | put_cpu_var(perf_counter_pending); | ||
537 | } | ||
538 | |||
539 | #define test_perf_counter_pending() __get_cpu_var(perf_counter_pending) | ||
540 | #define clear_perf_counter_pending() __get_cpu_var(perf_counter_pending) = 0 | ||
541 | |||
542 | #else /* CONFIG_PERF_COUNTERS && CONFIG_PPC32 */ | ||
543 | |||
544 | #define test_perf_counter_pending() 0 | ||
545 | #define clear_perf_counter_pending() | ||
546 | |||
547 | #endif /* CONFIG_PERF_COUNTERS && CONFIG_PPC32 */ | ||
548 | |||
528 | /* | 549 | /* |
529 | * For iSeries shared processors, we have to let the hypervisor | 550 | * For iSeries shared processors, we have to let the hypervisor |
530 | * set the hardware decrementer. We set a virtual decrementer | 551 | * set the hardware decrementer. We set a virtual decrementer |
@@ -551,6 +572,10 @@ void timer_interrupt(struct pt_regs * regs) | |||
551 | set_dec(DECREMENTER_MAX); | 572 | set_dec(DECREMENTER_MAX); |
552 | 573 | ||
553 | #ifdef CONFIG_PPC32 | 574 | #ifdef CONFIG_PPC32 |
575 | if (test_perf_counter_pending()) { | ||
576 | clear_perf_counter_pending(); | ||
577 | perf_counter_do_pending(); | ||
578 | } | ||
554 | if (atomic_read(&ppc_n_lost_interrupts) != 0) | 579 | if (atomic_read(&ppc_n_lost_interrupts) != 0) |
555 | do_IRQ(regs); | 580 | do_IRQ(regs); |
556 | #endif | 581 | #endif |
diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c index 0362a891e54e..acb74a17bbbf 100644 --- a/arch/powerpc/kernel/udbg_16550.c +++ b/arch/powerpc/kernel/udbg_16550.c | |||
@@ -219,7 +219,7 @@ void udbg_init_pas_realmode(void) | |||
219 | #ifdef CONFIG_PPC_EARLY_DEBUG_44x | 219 | #ifdef CONFIG_PPC_EARLY_DEBUG_44x |
220 | #include <platforms/44x/44x.h> | 220 | #include <platforms/44x/44x.h> |
221 | 221 | ||
222 | static int udbg_44x_as1_flush(void) | 222 | static void udbg_44x_as1_flush(void) |
223 | { | 223 | { |
224 | if (udbg_comport) { | 224 | if (udbg_comport) { |
225 | while ((as1_readb(&udbg_comport->lsr) & LSR_THRE) == 0) | 225 | while ((as1_readb(&udbg_comport->lsr) & LSR_THRE) == 0) |
diff --git a/arch/powerpc/kernel/vector.S b/arch/powerpc/kernel/vector.S index ef36cbbc5882..ea4d64644d02 100644 --- a/arch/powerpc/kernel/vector.S +++ b/arch/powerpc/kernel/vector.S | |||
@@ -80,10 +80,10 @@ _GLOBAL(load_up_altivec) | |||
80 | mtvscr vr0 | 80 | mtvscr vr0 |
81 | REST_32VRS(0,r4,r5) | 81 | REST_32VRS(0,r4,r5) |
82 | #ifndef CONFIG_SMP | 82 | #ifndef CONFIG_SMP |
83 | /* Update last_task_used_math to 'current' */ | 83 | /* Update last_task_used_altivec to 'current' */ |
84 | subi r4,r5,THREAD /* Back to 'current' */ | 84 | subi r4,r5,THREAD /* Back to 'current' */ |
85 | fromreal(r4) | 85 | fromreal(r4) |
86 | PPC_STL r4,ADDROFF(last_task_used_math)(r3) | 86 | PPC_STL r4,ADDROFF(last_task_used_altivec)(r3) |
87 | #endif /* CONFIG_SMP */ | 87 | #endif /* CONFIG_SMP */ |
88 | /* restore registers and return */ | 88 | /* restore registers and return */ |
89 | blr | 89 | blr |
@@ -172,7 +172,7 @@ _GLOBAL(load_up_vsx) | |||
172 | oris r12,r12,MSR_VSX@h | 172 | oris r12,r12,MSR_VSX@h |
173 | std r12,_MSR(r1) | 173 | std r12,_MSR(r1) |
174 | #ifndef CONFIG_SMP | 174 | #ifndef CONFIG_SMP |
175 | /* Update last_task_used_math to 'current' */ | 175 | /* Update last_task_used_vsx to 'current' */ |
176 | ld r4,PACACURRENT(r13) | 176 | ld r4,PACACURRENT(r13) |
177 | std r4,0(r3) | 177 | std r4,0(r3) |
178 | #endif /* CONFIG_SMP */ | 178 | #endif /* CONFIG_SMP */ |