Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 330268
b: refs/heads/master
c: adbf115
h: refs/heads/master
v: v3
  • Loading branch information
Carl E. Love authored and Benjamin Herrenschmidt committed Sep 7, 2012
1 parent b2a5568 commit 85e02e2
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 22d8ce887991f8f70a68fb68972f187ec79d44b7
refs/heads/master: adbf115d66649b3a52e6875f93c9f131ba690cce
100 changes: 99 additions & 1 deletion trunk/arch/powerpc/oprofile/op_model_power4.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@
#include <asm/reg.h>

#define dbg(args...)
#define OPROFILE_PM_PMCSEL_MSK 0xffULL
#define OPROFILE_PM_UNIT_SHIFT 60
#define OPROFILE_PM_UNIT_MSK 0xfULL
#define OPROFILE_MAX_PMC_NUM 3
#define OPROFILE_PMSEL_FIELD_WIDTH 8
#define OPROFILE_UNIT_FIELD_WIDTH 4
#define MMCRA_SIAR_VALID_MASK 0x10000000ULL

static unsigned long reset_value[OP_MAX_COUNTER];

Expand All @@ -31,6 +38,61 @@ static int use_slot_nums;
static u32 mmcr0_val;
static u64 mmcr1_val;
static u64 mmcra_val;
static u32 cntr_marked_events;

static int power7_marked_instr_event(u64 mmcr1)
{
u64 psel, unit;
int pmc, cntr_marked_events = 0;

/* Given the MMCR1 value, look at the field for each counter to
* determine if it is a marked event. Code based on the function
* power7_marked_instr_event() in file arch/powerpc/perf/power7-pmu.c.
*/
for (pmc = 0; pmc < 4; pmc++) {
psel = mmcr1 & (OPROFILE_PM_PMCSEL_MSK
<< (OPROFILE_MAX_PMC_NUM - pmc)
* OPROFILE_MAX_PMC_NUM);
psel = (psel >> ((OPROFILE_MAX_PMC_NUM - pmc)
* OPROFILE_PMSEL_FIELD_WIDTH)) & ~1ULL;
unit = mmcr1 & (OPROFILE_PM_UNIT_MSK
<< (OPROFILE_PM_UNIT_SHIFT
- (pmc * OPROFILE_PMSEL_FIELD_WIDTH )));
unit = unit >> (OPROFILE_PM_UNIT_SHIFT
- (pmc * OPROFILE_PMSEL_FIELD_WIDTH));

switch (psel >> 4) {
case 2:
cntr_marked_events |= (pmc == 1 || pmc == 3) << pmc;
break;
case 3:
if (psel == 0x3c) {
cntr_marked_events |= (pmc == 0) << pmc;
break;
}

if (psel == 0x3e) {
cntr_marked_events |= (pmc != 1) << pmc;
break;
}

cntr_marked_events |= 1 << pmc;
break;
case 4:
case 5:
cntr_marked_events |= (unit == 0xd) << pmc;
break;
case 6:
if (psel == 0x64)
cntr_marked_events |= (pmc >= 2) << pmc;
break;
case 8:
cntr_marked_events |= (unit == 0xd) << pmc;
break;
}
}
return cntr_marked_events;
}

static int power4_reg_setup(struct op_counter_config *ctr,
struct op_system_config *sys,
Expand All @@ -47,6 +109,23 @@ static int power4_reg_setup(struct op_counter_config *ctr,
mmcr1_val = sys->mmcr1;
mmcra_val = sys->mmcra;

/* Power 7+ and newer architectures:
* Determine which counter events in the group (the group of events is
* specified by the bit settings in the MMCR1 register) are marked
* events for use in the interrupt handler. Do the calculation once
* before OProfile starts. Information is used in the interrupt
* handler. Starting with Power 7+ we only record the sample for
* marked events if the SIAR valid bit is set. For non marked events
* the sample is always recorded.
*/
if (pvr_version_is(PVR_POWER7p))
cntr_marked_events = power7_marked_instr_event(mmcr1_val);
else
cntr_marked_events = 0; /* For older processors, set the bit map
* to zero so the sample will always be
* be recorded.
*/

for (i = 0; i < cur_cpu_spec->num_pmcs; ++i)
reset_value[i] = 0x80000000UL - ctr[i].count;

Expand Down Expand Up @@ -291,6 +370,7 @@ static void power4_handle_interrupt(struct pt_regs *regs,
int i;
unsigned int mmcr0;
unsigned long mmcra;
bool siar_valid = false;

mmcra = mfspr(SPRN_MMCRA);

Expand All @@ -300,11 +380,29 @@ static void power4_handle_interrupt(struct pt_regs *regs,
/* set the PMM bit (see comment below) */
mtmsrd(mfmsr() | MSR_PMM);

/* Check that the SIAR valid bit in MMCRA is set to 1. */
if ((mmcra & MMCRA_SIAR_VALID_MASK) == MMCRA_SIAR_VALID_MASK)
siar_valid = true;

for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) {
val = classic_ctr_read(i);
if (pmc_overflow(val)) {
if (oprofile_running && ctr[i].enabled) {
oprofile_add_ext_sample(pc, regs, i, is_kernel);
/* Power 7+ and newer architectures:
* If the event is a marked event, then only
* save the sample if the SIAR valid bit is
* set. If the event is not marked, then
* always save the sample.
* Note, the Sample enable bit in the MMCRA
* register must be set to 1 if the group
* contains a marked event.
*/
if ((siar_valid &&
(cntr_marked_events & (1 << i)))
|| !(cntr_marked_events & (1 << i)))
oprofile_add_ext_sample(pc, regs, i,
is_kernel);

classic_ctr_write(i, reset_value[i]);
} else {
classic_ctr_write(i, 0);
Expand Down

0 comments on commit 85e02e2

Please sign in to comment.