aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/perf
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/perf')
-rw-r--r--arch/powerpc/perf/core-book3s.c46
-rw-r--r--arch/powerpc/perf/power4-pmu.c1
-rw-r--r--arch/powerpc/perf/ppc970-pmu.c1
3 files changed, 43 insertions, 5 deletions
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index c2e27ede07ec..02aee03e713c 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -116,14 +116,45 @@ static inline void perf_get_data_addr(struct pt_regs *regs, u64 *addrp)
116 *addrp = mfspr(SPRN_SDAR); 116 *addrp = mfspr(SPRN_SDAR);
117} 117}
118 118
119static inline u32 perf_flags_from_msr(struct pt_regs *regs)
120{
121 if (regs->msr & MSR_PR)
122 return PERF_RECORD_MISC_USER;
123 if ((regs->msr & MSR_HV) && freeze_events_kernel != MMCR0_FCHV)
124 return PERF_RECORD_MISC_HYPERVISOR;
125 return PERF_RECORD_MISC_KERNEL;
126}
127
119static inline u32 perf_get_misc_flags(struct pt_regs *regs) 128static inline u32 perf_get_misc_flags(struct pt_regs *regs)
120{ 129{
121 unsigned long mmcra = regs->dsisr; 130 unsigned long mmcra = regs->dsisr;
122 unsigned long sihv = MMCRA_SIHV; 131 unsigned long sihv = MMCRA_SIHV;
123 unsigned long sipr = MMCRA_SIPR; 132 unsigned long sipr = MMCRA_SIPR;
124 133
134 /* Not a PMU interrupt: Make up flags from regs->msr */
125 if (TRAP(regs) != 0xf00) 135 if (TRAP(regs) != 0xf00)
126 return 0; /* not a PMU interrupt */ 136 return perf_flags_from_msr(regs);
137
138 /*
139 * If we don't support continuous sampling and this
140 * is not a marked event, same deal
141 */
142 if ((ppmu->flags & PPMU_NO_CONT_SAMPLING) &&
143 !(mmcra & MMCRA_SAMPLE_ENABLE))
144 return perf_flags_from_msr(regs);
145
146 /*
147 * If we don't have flags in MMCRA, rather than using
148 * the MSR, we intuit the flags from the address in
149 * SIAR which should give slightly more reliable
150 * results
151 */
152 if (ppmu->flags & PPMU_NO_SIPR) {
153 unsigned long siar = mfspr(SPRN_SIAR);
154 if (siar >= PAGE_OFFSET)
155 return PERF_RECORD_MISC_KERNEL;
156 return PERF_RECORD_MISC_USER;
157 }
127 158
128 if (ppmu->flags & PPMU_ALT_SIPR) { 159 if (ppmu->flags & PPMU_ALT_SIPR) {
129 sihv = POWER6_MMCRA_SIHV; 160 sihv = POWER6_MMCRA_SIHV;
@@ -1299,13 +1330,18 @@ unsigned long perf_misc_flags(struct pt_regs *regs)
1299 */ 1330 */
1300unsigned long perf_instruction_pointer(struct pt_regs *regs) 1331unsigned long perf_instruction_pointer(struct pt_regs *regs)
1301{ 1332{
1302 unsigned long ip; 1333 unsigned long mmcra = regs->dsisr;
1303 1334
1335 /* Not a PMU interrupt */
1304 if (TRAP(regs) != 0xf00) 1336 if (TRAP(regs) != 0xf00)
1305 return regs->nip; /* not a PMU interrupt */ 1337 return regs->nip;
1338
1339 /* Processor doesn't support sampling non marked events */
1340 if ((ppmu->flags & PPMU_NO_CONT_SAMPLING) &&
1341 !(mmcra & MMCRA_SAMPLE_ENABLE))
1342 return regs->nip;
1306 1343
1307 ip = mfspr(SPRN_SIAR) + perf_ip_adjust(regs); 1344 return mfspr(SPRN_SIAR) + perf_ip_adjust(regs);
1308 return ip;
1309} 1345}
1310 1346
1311static bool pmc_overflow(unsigned long val) 1347static bool pmc_overflow(unsigned long val)
diff --git a/arch/powerpc/perf/power4-pmu.c b/arch/powerpc/perf/power4-pmu.c
index b4f1dda4d089..9103a1de864d 100644
--- a/arch/powerpc/perf/power4-pmu.c
+++ b/arch/powerpc/perf/power4-pmu.c
@@ -607,6 +607,7 @@ static struct power_pmu power4_pmu = {
607 .n_generic = ARRAY_SIZE(p4_generic_events), 607 .n_generic = ARRAY_SIZE(p4_generic_events),
608 .generic_events = p4_generic_events, 608 .generic_events = p4_generic_events,
609 .cache_events = &power4_cache_events, 609 .cache_events = &power4_cache_events,
610 .flags = PPMU_NO_SIPR | PPMU_NO_CONT_SAMPLING,
610}; 611};
611 612
612static int __init init_power4_pmu(void) 613static int __init init_power4_pmu(void)
diff --git a/arch/powerpc/perf/ppc970-pmu.c b/arch/powerpc/perf/ppc970-pmu.c
index 111eb25bb0b6..20139ceeacf6 100644
--- a/arch/powerpc/perf/ppc970-pmu.c
+++ b/arch/powerpc/perf/ppc970-pmu.c
@@ -487,6 +487,7 @@ static struct power_pmu ppc970_pmu = {
487 .n_generic = ARRAY_SIZE(ppc970_generic_events), 487 .n_generic = ARRAY_SIZE(ppc970_generic_events),
488 .generic_events = ppc970_generic_events, 488 .generic_events = ppc970_generic_events,
489 .cache_events = &ppc970_cache_events, 489 .cache_events = &ppc970_cache_events,
490 .flags = PPMU_NO_SIPR | PPMU_NO_CONT_SAMPLING,
490}; 491};
491 492
492static int __init init_ppc970_pmu(void) 493static int __init init_ppc970_pmu(void)