Skip to content

Commit

Permalink
powerpc/perf: Move BHRB code into CONFIG_PPC64 region
Browse files Browse the repository at this point in the history
The new Branch History Rolling buffer (BHRB) code is only useful on 64bit
processors, so move it into the #ifdef CONFIG_PPC64 region.

This avoids code bloat on 32bit systems.

Signed-off-by: Michael Neuling <[email protected]>
Signed-off-by: Benjamin Herrenschmidt <[email protected]>
  • Loading branch information
mikey authored and ozbenh committed May 14, 2013
1 parent a1797b2 commit d52f2dc
Showing 1 changed file with 127 additions and 121 deletions.
248 changes: 127 additions & 121 deletions arch/powerpc/perf/core-book3s.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ static inline int siar_valid(struct pt_regs *regs)
return 1;
}

static inline void power_pmu_bhrb_enable(struct perf_event *event) {}
static inline void power_pmu_bhrb_disable(struct perf_event *event) {}
void power_pmu_flush_branch_stack(void) {}
static inline void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw) {}
#endif /* CONFIG_PPC32 */

static bool regs_use_siar(struct pt_regs *regs)
Expand Down Expand Up @@ -308,6 +312,129 @@ static inline int siar_valid(struct pt_regs *regs)
return 1;
}


/* Reset all possible BHRB entries */
static void power_pmu_bhrb_reset(void)
{
asm volatile(PPC_CLRBHRB);
}

static void power_pmu_bhrb_enable(struct perf_event *event)
{
struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);

if (!ppmu->bhrb_nr)
return;

/* Clear BHRB if we changed task context to avoid data leaks */
if (event->ctx->task && cpuhw->bhrb_context != event->ctx) {
power_pmu_bhrb_reset();
cpuhw->bhrb_context = event->ctx;
}
cpuhw->bhrb_users++;
}

static void power_pmu_bhrb_disable(struct perf_event *event)
{
struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);

if (!ppmu->bhrb_nr)
return;

cpuhw->bhrb_users--;
WARN_ON_ONCE(cpuhw->bhrb_users < 0);

if (!cpuhw->disabled && !cpuhw->bhrb_users) {
/* BHRB cannot be turned off when other
* events are active on the PMU.
*/

/* avoid stale pointer */
cpuhw->bhrb_context = NULL;
}
}

/* Called from ctxsw to prevent one process's branch entries to
* mingle with the other process's entries during context switch.
*/
void power_pmu_flush_branch_stack(void)
{
if (ppmu->bhrb_nr)
power_pmu_bhrb_reset();
}


/* Processing BHRB entries */
static void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw)
{
u64 val;
u64 addr;
int r_index, u_index, target, pred;

r_index = 0;
u_index = 0;
while (r_index < ppmu->bhrb_nr) {
/* Assembly read function */
val = read_bhrb(r_index);

/* Terminal marker: End of valid BHRB entries */
if (val == 0) {
break;
} else {
/* BHRB field break up */
addr = val & BHRB_EA;
pred = val & BHRB_PREDICTION;
target = val & BHRB_TARGET;

/* Probable Missed entry: Not applicable for POWER8 */
if ((addr == 0) && (target == 0) && (pred == 1)) {
r_index++;
continue;
}

/* Real Missed entry: Power8 based missed entry */
if ((addr == 0) && (target == 1) && (pred == 1)) {
r_index++;
continue;
}

/* Reserved condition: Not a valid entry */
if ((addr == 0) && (target == 1) && (pred == 0)) {
r_index++;
continue;
}

/* Is a target address */
if (val & BHRB_TARGET) {
/* First address cannot be a target address */
if (r_index == 0) {
r_index++;
continue;
}

/* Update target address for the previous entry */
cpuhw->bhrb_entries[u_index - 1].to = addr;
cpuhw->bhrb_entries[u_index - 1].mispred = pred;
cpuhw->bhrb_entries[u_index - 1].predicted = ~pred;

/* Dont increment u_index */
r_index++;
} else {
/* Update address, flags for current entry */
cpuhw->bhrb_entries[u_index].from = addr;
cpuhw->bhrb_entries[u_index].mispred = pred;
cpuhw->bhrb_entries[u_index].predicted = ~pred;

/* Successfully popullated one entry */
u_index++;
r_index++;
}
}
}
cpuhw->bhrb_stack.nr = u_index;
return;
}

#endif /* CONFIG_PPC64 */

static void perf_event_interrupt(struct pt_regs *regs);
Expand Down Expand Up @@ -904,47 +1031,6 @@ static int collect_events(struct perf_event *group, int max_count,
return n;
}

/* Reset all possible BHRB entries */
static void power_pmu_bhrb_reset(void)
{
asm volatile(PPC_CLRBHRB);
}

void power_pmu_bhrb_enable(struct perf_event *event)
{
struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);

if (!ppmu->bhrb_nr)
return;

/* Clear BHRB if we changed task context to avoid data leaks */
if (event->ctx->task && cpuhw->bhrb_context != event->ctx) {
power_pmu_bhrb_reset();
cpuhw->bhrb_context = event->ctx;
}
cpuhw->bhrb_users++;
}

void power_pmu_bhrb_disable(struct perf_event *event)
{
struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);

if (!ppmu->bhrb_nr)
return;

cpuhw->bhrb_users--;
WARN_ON_ONCE(cpuhw->bhrb_users < 0);

if (!cpuhw->disabled && !cpuhw->bhrb_users) {
/* BHRB cannot be turned off when other
* events are active on the PMU.
*/

/* avoid stale pointer */
cpuhw->bhrb_context = NULL;
}
}

/*
* Add a event to the PMU.
* If all events are not already frozen, then we disable and
Expand Down Expand Up @@ -1180,15 +1266,6 @@ int power_pmu_commit_txn(struct pmu *pmu)
return 0;
}

/* Called from ctxsw to prevent one process's branch entries to
* mingle with the other process's entries during context switch.
*/
void power_pmu_flush_branch_stack(void)
{
if (ppmu->bhrb_nr)
power_pmu_bhrb_reset();
}

/*
* Return 1 if we might be able to put event on a limited PMC,
* or 0 if not.
Expand Down Expand Up @@ -1458,77 +1535,6 @@ struct pmu power_pmu = {
.flush_branch_stack = power_pmu_flush_branch_stack,
};

/* Processing BHRB entries */
void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw)
{
u64 val;
u64 addr;
int r_index, u_index, target, pred;

r_index = 0;
u_index = 0;
while (r_index < ppmu->bhrb_nr) {
/* Assembly read function */
val = read_bhrb(r_index);

/* Terminal marker: End of valid BHRB entries */
if (val == 0) {
break;
} else {
/* BHRB field break up */
addr = val & BHRB_EA;
pred = val & BHRB_PREDICTION;
target = val & BHRB_TARGET;

/* Probable Missed entry: Not applicable for POWER8 */
if ((addr == 0) && (target == 0) && (pred == 1)) {
r_index++;
continue;
}

/* Real Missed entry: Power8 based missed entry */
if ((addr == 0) && (target == 1) && (pred == 1)) {
r_index++;
continue;
}

/* Reserved condition: Not a valid entry */
if ((addr == 0) && (target == 1) && (pred == 0)) {
r_index++;
continue;
}

/* Is a target address */
if (val & BHRB_TARGET) {
/* First address cannot be a target address */
if (r_index == 0) {
r_index++;
continue;
}

/* Update target address for the previous entry */
cpuhw->bhrb_entries[u_index - 1].to = addr;
cpuhw->bhrb_entries[u_index - 1].mispred = pred;
cpuhw->bhrb_entries[u_index - 1].predicted = ~pred;

/* Dont increment u_index */
r_index++;
} else {
/* Update address, flags for current entry */
cpuhw->bhrb_entries[u_index].from = addr;
cpuhw->bhrb_entries[u_index].mispred = pred;
cpuhw->bhrb_entries[u_index].predicted = ~pred;

/* Successfully popullated one entry */
u_index++;
r_index++;
}
}
}
cpuhw->bhrb_stack.nr = u_index;
return;
}

/*
* A counter has overflowed; update its count and record
* things if requested. Note that interrupts are hard-disabled
Expand Down

0 comments on commit d52f2dc

Please sign in to comment.