Skip to content

Commit

Permalink
oprofile, powerpc: Handle events that raise an exception without over…
Browse files Browse the repository at this point in the history
…flowing

Commit 0837e32 fixes a situation on POWER7
where events can roll back if a specualtive event doesn't actually complete.
This can raise a performance monitor exception.  We need to catch this to ensure
that we reset the PMC.  In all cases the PMC will be less than 256 cycles from
overflow.

This patch lifts Anton's fix for the problem in perf and applies it to oprofile
as well.

Signed-off-by: Eric B Munson <emunson@mgebm.net>
Cc: <stable@kernel.org> # as far back as it applies cleanly
Tested-by: Maynard Johnson <maynardj@us.ibm.com>
Signed-off-by: Robert Richter <robert.richter@amd.com>
  • Loading branch information
Eric B Munson authored and Robert Richter committed May 24, 2011
1 parent 3d2606f commit d819437
Showing 1 changed file with 23 additions and 1 deletion.
24 changes: 23 additions & 1 deletion arch/powerpc/oprofile/op_model_power4.c
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,28 @@ static int get_kernel(unsigned long pc, unsigned long mmcra)
return is_kernel;
}

static bool pmc_overflow(unsigned long val)
{
if ((int)val < 0)
return true;

/*
* Events on POWER7 can roll back if a speculative event doesn't
* eventually complete. Unfortunately in some rare cases they will
* raise a performance monitor exception. We need to catch this to
* ensure we reset the PMC. In all cases the PMC will be 256 or less
* cycles from overflow.
*
* We only do this if the first pass fails to find any overflowing
* PMCs because a user might set a period of less than 256 and we
* don't want to mistakenly reset them.
*/
if (__is_processor(PV_POWER7) && ((0x80000000 - val) <= 256))
return true;

return false;
}

static void power4_handle_interrupt(struct pt_regs *regs,
struct op_counter_config *ctr)
{
Expand All @@ -281,7 +303,7 @@ static void power4_handle_interrupt(struct pt_regs *regs,

for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) {
val = classic_ctr_read(i);
if (val < 0) {
if (pmc_overflow(val)) {
if (oprofile_running && ctr[i].enabled) {
oprofile_add_ext_sample(pc, regs, i, is_kernel);
classic_ctr_write(i, reset_value[i]);
Expand Down

0 comments on commit d819437

Please sign in to comment.