aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorMichael Neuling <mikey@neuling.org>2013-05-13 14:44:57 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-05-14 02:00:22 -0400
commit506e70d13236dfdb0bc15e0914298ab0a7b7f4df (patch)
tree08bf7cf0c04256df0cf5c1f100bc4778ec928fba /arch/powerpc
parentd52f2dc40b52201700001e868093c5ec827a8f33 (diff)
powerpc/pmu: Fix order of interpreting BHRB target entries
The current Branch History Rolling Buffer (BHRB) code misinterprets the order of entries in the hardware buffer. It assumes that a branch target address will be read _after_ its corresponding branch. In reality the branch target comes before (lower mfbhrb entry) it's corresponding branch. This is a rewrite of the code to take this into account. Signed-off-by: Michael Neuling <mikey@neuling.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/perf/core-book3s.c89
1 files changed, 46 insertions, 43 deletions
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 843bb8be8380..3fdfe4575b8f 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -363,72 +363,75 @@ void power_pmu_flush_branch_stack(void)
363 power_pmu_bhrb_reset(); 363 power_pmu_bhrb_reset();
364} 364}
365 365
366
367/* Processing BHRB entries */ 366/* Processing BHRB entries */
368static void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw) 367void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw)
369{ 368{
370 u64 val; 369 u64 val;
371 u64 addr; 370 u64 addr;
372 int r_index, u_index, target, pred; 371 int r_index, u_index, pred;
373 372
374 r_index = 0; 373 r_index = 0;
375 u_index = 0; 374 u_index = 0;
376 while (r_index < ppmu->bhrb_nr) { 375 while (r_index < ppmu->bhrb_nr) {
377 /* Assembly read function */ 376 /* Assembly read function */
378 val = read_bhrb(r_index); 377 val = read_bhrb(r_index++);
379 378 if (!val)
380 /* Terminal marker: End of valid BHRB entries */ 379 /* Terminal marker: End of valid BHRB entries */
381 if (val == 0) {
382 break; 380 break;
383 } else { 381 else {
384 /* BHRB field break up */
385 addr = val & BHRB_EA; 382 addr = val & BHRB_EA;
386 pred = val & BHRB_PREDICTION; 383 pred = val & BHRB_PREDICTION;
387 target = val & BHRB_TARGET;
388 384
389 /* Probable Missed entry: Not applicable for POWER8 */ 385 if (!addr)
390 if ((addr == 0) && (target == 0) && (pred == 1)) { 386 /* invalid entry */
391 r_index++;
392 continue; 387 continue;
393 }
394 388
395 /* Real Missed entry: Power8 based missed entry */ 389 /* Branches are read most recent first (ie. mfbhrb 0 is
396 if ((addr == 0) && (target == 1) && (pred == 1)) { 390 * the most recent branch).
397 r_index++; 391 * There are two types of valid entries:
398 continue; 392 * 1) a target entry which is the to address of a
399 } 393 * computed goto like a blr,bctr,btar. The next
400 394 * entry read from the bhrb will be branch
401 /* Reserved condition: Not a valid entry */ 395 * corresponding to this target (ie. the actual
402 if ((addr == 0) && (target == 1) && (pred == 0)) { 396 * blr/bctr/btar instruction).
403 r_index++; 397 * 2) a from address which is an actual branch. If a
404 continue; 398 * target entry proceeds this, then this is the
405 } 399 * matching branch for that target. If this is not
400 * following a target entry, then this is a branch
401 * where the target is given as an immediate field
402 * in the instruction (ie. an i or b form branch).
403 * In this case we need to read the instruction from
404 * memory to determine the target/to address.
405 */
406 406
407 /* Is a target address */
408 if (val & BHRB_TARGET) { 407 if (val & BHRB_TARGET) {
409 /* First address cannot be a target address */ 408 /* Target branches use two entries
410 if (r_index == 0) { 409 * (ie. computed gotos/XL form)
411 r_index++; 410 */
412 continue; 411 cpuhw->bhrb_entries[u_index].to = addr;
413 } 412 cpuhw->bhrb_entries[u_index].mispred = pred;
414 413 cpuhw->bhrb_entries[u_index].predicted = ~pred;
415 /* Update target address for the previous entry */
416 cpuhw->bhrb_entries[u_index - 1].to = addr;
417 cpuhw->bhrb_entries[u_index - 1].mispred = pred;
418 cpuhw->bhrb_entries[u_index - 1].predicted = ~pred;
419 414
420 /* Dont increment u_index */ 415 /* Get from address in next entry */
421 r_index++; 416 val = read_bhrb(r_index++);
417 addr = val & BHRB_EA;
418 if (val & BHRB_TARGET) {
419 /* Shouldn't have two targets in a
420 row.. Reset index and try again */
421 r_index--;
422 addr = 0;
423 }
424 cpuhw->bhrb_entries[u_index].from = addr;
422 } else { 425 } else {
423 /* Update address, flags for current entry */ 426 /* Branches to immediate field
427 (ie I or B form) */
424 cpuhw->bhrb_entries[u_index].from = addr; 428 cpuhw->bhrb_entries[u_index].from = addr;
429 cpuhw->bhrb_entries[u_index].to = 0;
425 cpuhw->bhrb_entries[u_index].mispred = pred; 430 cpuhw->bhrb_entries[u_index].mispred = pred;
426 cpuhw->bhrb_entries[u_index].predicted = ~pred; 431 cpuhw->bhrb_entries[u_index].predicted = ~pred;
427
428 /* Successfully popullated one entry */
429 u_index++;
430 r_index++;
431 } 432 }
433 u_index++;
434
432 } 435 }
433 } 436 }
434 cpuhw->bhrb_stack.nr = u_index; 437 cpuhw->bhrb_stack.nr = u_index;