forked from Minki/linux
powerpc/perf: Use Instruction Counter value
Since PM_INST_DISP include speculative instruction, based on the workload the dispatch count could vary considerably. Hence as an alternative, for completed instruction counting, program the PM_INST_DISP event to the MMCR* but use Instruction Counter register value. Signed-off-by: Madhavan Srinivasan <maddy@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
parent
8a088542c8
commit
356d8ce3d0
@ -57,6 +57,7 @@ struct cpu_hw_events {
|
|||||||
void *bhrb_context;
|
void *bhrb_context;
|
||||||
struct perf_branch_stack bhrb_stack;
|
struct perf_branch_stack bhrb_stack;
|
||||||
struct perf_branch_entry bhrb_entries[BHRB_MAX_ENTRIES];
|
struct perf_branch_entry bhrb_entries[BHRB_MAX_ENTRIES];
|
||||||
|
u64 ic_init;
|
||||||
};
|
};
|
||||||
|
|
||||||
static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
|
static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
|
||||||
@ -127,6 +128,10 @@ static inline void power_pmu_bhrb_disable(struct perf_event *event) {}
|
|||||||
static void power_pmu_sched_task(struct perf_event_context *ctx, bool sched_in) {}
|
static void power_pmu_sched_task(struct perf_event_context *ctx, bool sched_in) {}
|
||||||
static inline void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw) {}
|
static inline void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw) {}
|
||||||
static void pmao_restore_workaround(bool ebb) { }
|
static void pmao_restore_workaround(bool ebb) { }
|
||||||
|
static bool use_ic(u64 event)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
#endif /* CONFIG_PPC32 */
|
#endif /* CONFIG_PPC32 */
|
||||||
|
|
||||||
static bool regs_use_siar(struct pt_regs *regs)
|
static bool regs_use_siar(struct pt_regs *regs)
|
||||||
@ -688,6 +693,15 @@ static void pmao_restore_workaround(bool ebb)
|
|||||||
mtspr(SPRN_PMC5, pmcs[4]);
|
mtspr(SPRN_PMC5, pmcs[4]);
|
||||||
mtspr(SPRN_PMC6, pmcs[5]);
|
mtspr(SPRN_PMC6, pmcs[5]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool use_ic(u64 event)
|
||||||
|
{
|
||||||
|
if (cpu_has_feature(CPU_FTR_POWER9_DD1) &&
|
||||||
|
(event == 0x200f2 || event == 0x300f2))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
#endif /* CONFIG_PPC64 */
|
#endif /* CONFIG_PPC64 */
|
||||||
|
|
||||||
static void perf_event_interrupt(struct pt_regs *regs);
|
static void perf_event_interrupt(struct pt_regs *regs);
|
||||||
@ -1007,6 +1021,7 @@ static u64 check_and_compute_delta(u64 prev, u64 val)
|
|||||||
static void power_pmu_read(struct perf_event *event)
|
static void power_pmu_read(struct perf_event *event)
|
||||||
{
|
{
|
||||||
s64 val, delta, prev;
|
s64 val, delta, prev;
|
||||||
|
struct cpu_hw_events *cpuhw = this_cpu_ptr(&cpu_hw_events);
|
||||||
|
|
||||||
if (event->hw.state & PERF_HES_STOPPED)
|
if (event->hw.state & PERF_HES_STOPPED)
|
||||||
return;
|
return;
|
||||||
@ -1016,6 +1031,13 @@ static void power_pmu_read(struct perf_event *event)
|
|||||||
|
|
||||||
if (is_ebb_event(event)) {
|
if (is_ebb_event(event)) {
|
||||||
val = read_pmc(event->hw.idx);
|
val = read_pmc(event->hw.idx);
|
||||||
|
if (use_ic(event->attr.config)) {
|
||||||
|
val = mfspr(SPRN_IC);
|
||||||
|
if (val > cpuhw->ic_init)
|
||||||
|
val = val - cpuhw->ic_init;
|
||||||
|
else
|
||||||
|
val = val + (0 - cpuhw->ic_init);
|
||||||
|
}
|
||||||
local64_set(&event->hw.prev_count, val);
|
local64_set(&event->hw.prev_count, val);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1029,6 +1051,13 @@ static void power_pmu_read(struct perf_event *event)
|
|||||||
prev = local64_read(&event->hw.prev_count);
|
prev = local64_read(&event->hw.prev_count);
|
||||||
barrier();
|
barrier();
|
||||||
val = read_pmc(event->hw.idx);
|
val = read_pmc(event->hw.idx);
|
||||||
|
if (use_ic(event->attr.config)) {
|
||||||
|
val = mfspr(SPRN_IC);
|
||||||
|
if (val > cpuhw->ic_init)
|
||||||
|
val = val - cpuhw->ic_init;
|
||||||
|
else
|
||||||
|
val = val + (0 - cpuhw->ic_init);
|
||||||
|
}
|
||||||
delta = check_and_compute_delta(prev, val);
|
delta = check_and_compute_delta(prev, val);
|
||||||
if (!delta)
|
if (!delta)
|
||||||
return;
|
return;
|
||||||
@ -1466,6 +1495,13 @@ nocheck:
|
|||||||
event->attr.branch_sample_type);
|
event->attr.branch_sample_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Workaround for POWER9 DD1 to use the Instruction Counter
|
||||||
|
* register value for instruction counting
|
||||||
|
*/
|
||||||
|
if (use_ic(event->attr.config))
|
||||||
|
cpuhw->ic_init = mfspr(SPRN_IC);
|
||||||
|
|
||||||
perf_pmu_enable(event->pmu);
|
perf_pmu_enable(event->pmu);
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
return ret;
|
return ret;
|
||||||
|
Loading…
Reference in New Issue
Block a user