diff options
| -rw-r--r-- | arch/powerpc/include/asm/perf_event_server.h | 2 | ||||
| -rw-r--r-- | arch/powerpc/perf/core-book3s.c | 46 | ||||
| -rw-r--r-- | arch/powerpc/perf/power4-pmu.c | 1 | ||||
| -rw-r--r-- | arch/powerpc/perf/ppc970-pmu.c | 1 |
4 files changed, 45 insertions, 5 deletions
diff --git a/arch/powerpc/include/asm/perf_event_server.h b/arch/powerpc/include/asm/perf_event_server.h index 1a8093fa8f71..078019b5b353 100644 --- a/arch/powerpc/include/asm/perf_event_server.h +++ b/arch/powerpc/include/asm/perf_event_server.h | |||
| @@ -47,6 +47,8 @@ struct power_pmu { | |||
| 47 | */ | 47 | */ |
| 48 | #define PPMU_LIMITED_PMC5_6 1 /* PMC5/6 have limited function */ | 48 | #define PPMU_LIMITED_PMC5_6 1 /* PMC5/6 have limited function */ |
| 49 | #define PPMU_ALT_SIPR 2 /* uses alternate posn for SIPR/HV */ | 49 | #define PPMU_ALT_SIPR 2 /* uses alternate posn for SIPR/HV */ |
| 50 | #define PPMU_NO_SIPR 4 /* no SIPR/HV in MMCRA at all */ | ||
| 51 | #define PPMU_NO_CONT_SAMPLING 8 /* no continuous sampling */ | ||
| 50 | 52 | ||
| 51 | /* | 53 | /* |
| 52 | * Values for flags to get_alternatives() | 54 | * Values for flags to get_alternatives() |
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 | ||
| 119 | static 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 | |||
| 119 | static inline u32 perf_get_misc_flags(struct pt_regs *regs) | 128 | static 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 | */ |
| 1300 | unsigned long perf_instruction_pointer(struct pt_regs *regs) | 1331 | unsigned 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 | ||
| 1311 | static bool pmc_overflow(unsigned long val) | 1347 | static 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 | ||
| 612 | static int __init init_power4_pmu(void) | 613 | static 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 | ||
| 492 | static int __init init_ppc970_pmu(void) | 493 | static int __init init_ppc970_pmu(void) |
