This patch enables SW based post processing of BHRB captured branches
to be able to meet more user defined branch filtration criteria in perf
branch stack sampling framework. These changes increase the number of
branch filters and their valid combinations on any powerpc64 server
platform with BHRB support. Find the summary of code changes here.
(1) struct cpu_hw_events
Introduced two new variables track various filter values and mask
(a) bhrb_sw_filter Tracks SW implemented branch filter flags
(b) bhrb_filter Tracks both (SW and HW) branch filter flags
(2) Event creation
Kernel will figure out supported BHRB branch filters through a PMU call
back 'bhrb_filter_map'. This function will find out how many of the
requested branch filters can be supported in the PMU HW. It will not
try to invalidate any branch filter combinations. Event creation will not
error out because of lack of HW based branch filters. Meanwhile it will
track the overall supported branch filters in the 'bhrb_filter' variable.
Once the PMU call back returns kernel will process the user branch filter
request against available SW filters (bhrb_sw_filter_map) while looking
at the 'bhrb_filter'. During this phase all the branch filters which are
still pending from the user requested list will have to be supported in
SW failing which the event creation will error out.
(3) SW branch filter
During the BHRB data capture inside the PMU interrupt context, each
of the captured 'perf_branch_entry.from' will be checked for compliance
with applicable SW branch filters. If the entry does not conform to the
filter requirements, it will be discarded from the final perf branch
stack buffer.
(4) Supported SW based branch filters
(a) PERF_SAMPLE_BRANCH_ANY_RETURN
(b) PERF_SAMPLE_BRANCH_IND_CALL
(c) PERF_SAMPLE_BRANCH_ANY_CALL
(d) PERF_SAMPLE_BRANCH_COND
Please refer the patch to understand the classification of instructions
into these branch filter categories.
(5) Multiple branch filter semantics
Book3 sever implementation follows the same OR semantics (as implemented in
x86) while dealing with multiple branch filters at any point of time. SW
branch filter analysis is carried on the data set captured in the PMU HW.
So the resulting set of data (after applying the SW filters) will inherently
be an AND with the HW captured set. Hence any combination of HW and SW branch
filters will be invalid. HW based branch filters are more efficient and faster
compared to SW implemented branch filters. So at first the PMU should decide
whether it can support all the requested branch filters itself or not. In case
it can support all the branch filters in an OR manner, we dont apply any SW
branch filter on top of the HW captured set (which is the final set). This
preserves the OR semantic of multiple branch filters as required. But in case
where the PMU cannot support all the requested branch filters in an OR manner,
it should not apply any it's filters and leave it upto the SW to handle them
all. Its the PMU code's responsibility to uphold this protocol to be able to
conform to the overall OR semantic of perf branch stack sampling framework.
Signed-off-by: Anshuman Khandual <redacted>
---
arch/powerpc/include/asm/perf_event_server.h | 6 +-
arch/powerpc/perf/core-book3s.c | 188 ++++++++++++++++++++++++++-
arch/powerpc/perf/power8-pmu.c | 2 +-
3 files changed, 187 insertions(+), 9 deletions(-)
@@ -474,6 +621,11 @@ void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw)tmp=power_pmu_bhrb_to(addr);update_branch_entry(cpuhw,u_index,addr,tmp,pred);}++/* Apply SW branch filters and drop the entry if required */+if(!keep_branch(cpuhw->bhrb_entries[u_index].from,+cpuhw->bhrb_sw_filter))+u_index--;u_index++;}cpuhw->bhrb_stack.nr=u_index;
@@ -633,7 +633,7 @@ static int power8_generic_events[] = {[PERF_COUNT_HW_CACHE_MISSES]=PM_LD_MISS_L1,};-staticu64power8_bhrb_filter_map(u64branch_sample_type)+staticu64power8_bhrb_filter_map(u64branch_sample_type,u64*bhrb_filter){/* BHRB and regular PMU events share the same privilege state*filterconfiguration.BHRBisalwaysrecordedalongwitha
This patch does some code re-arrangements to make it clear that
it ignores any separate privilege level branch filter request
and does not support any combinations of HW PMU branch filters.
Signed-off-by: Anshuman Khandual <redacted>
---
arch/powerpc/perf/power8-pmu.c | 21 +++++++--------------
1 file changed, 7 insertions(+), 14 deletions(-)
@@ -635,8 +635,6 @@ static int power8_generic_events[] = {staticu64power8_bhrb_filter_map(u64branch_sample_type){-u64pmu_bhrb_filter=0;-/* BHRB and regular PMU events share the same privilege state*filterconfiguration.BHRBisalwaysrecordedalongwitha*regularPMUevent.Astheprivilegestatefilterishandled
@@ -644,20 +642,15 @@ static u64 power8_bhrb_filter_map(u64 branch_sample_type)*PMUevent,weignoreanyseparateBHRBspecificrequest.*/-/* No branch filter requested */-if(branch_sample_type&PERF_SAMPLE_BRANCH_ANY)-returnpmu_bhrb_filter;--/* Invalid branch filter options - HW does not support */-if(branch_sample_type&PERF_SAMPLE_BRANCH_ANY_RETURN)-return-1;+/* Ignore user, kernel, hv bits */+branch_sample_type&=~PERF_SAMPLE_BRANCH_PLM_ALL;-if(branch_sample_type&PERF_SAMPLE_BRANCH_IND_CALL)-return-1;+/* No branch filter requested */+if(branch_sample_type==PERF_SAMPLE_BRANCH_ANY)+return0;-if(branch_sample_type&PERF_SAMPLE_BRANCH_ANY_CALL){-pmu_bhrb_filter|=POWER8_MMCRA_IFM1;-returnpmu_bhrb_filter;+if(branch_sample_type==PERF_SAMPLE_BRANCH_ANY_CALL){+returnPOWER8_MMCRA_IFM1;}/* Every thing else is unsupported */
This patch enables privilege mode SW branch filters. Also modifies
POWER8 PMU branch filter configuration so that the privilege mode
branch filter implemented as part of base PMU event configuration
is reflected in bhrb filter mask. As a result, the SW will skip and
not try to process the privilege mode branch filters itself.
Signed-off-by: Anshuman Khandual <redacted>
---
arch/powerpc/perf/core-book3s.c | 53 +++++++++++++++++++++++++++++++----------
arch/powerpc/perf/power8-pmu.c | 13 ++++++++--
2 files changed, 52 insertions(+), 14 deletions(-)
@@ -624,6 +652,7 @@ void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw)/* Apply SW branch filters and drop the entry if required */if(!keep_branch(cpuhw->bhrb_entries[u_index].from,+cpuhw->bhrb_entries[u_index].to,cpuhw->bhrb_sw_filter))u_index--;u_index++;
@@ -679,7 +689,6 @@ static u64 power8_bhrb_filter_map(u64 branch_sample_type, u64 *bhrb_filter)if(branch_sample_type){/* Multiple branch filters will be processed in SW */pmu_bhrb_filter=0;-*bhrb_filter=0;returnpmu_bhrb_filter;}else{/* Individual branch filter will be processed in PMU */
This patch introduces new branch filter PERF_SAMPLE_BRANCH_COND which
will extend the existing perf ABI. Various architectures can provide
this functionality with either with HW filtering support (if present)
or with SW filtering of captured branch instructions.
Signed-off-by: Anshuman Khandual <redacted>
Reviewed-by: Stephane Eranian <redacted>
Reviewed-by: Andi Kleen <redacted>
---
include/uapi/linux/perf_event.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
This patch simply changes the name of the variable from 'bhrb_filter' to
'bhrb_hw_filter' in order to add one more variable which will track SW
filters in generic powerpc book3s code which will be implemented in the
subsequent patch. This patch does not change any functionality.
Signed-off-by: Anshuman Khandual <redacted>
---
arch/powerpc/perf/core-book3s.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
@@ -184,9 +184,10 @@ following filters are defined: - in_tx: only when the target is in a hardware transaction - no_tx: only when the target is not in a hardware transaction - abort_tx: only when the target is a hardware transaction abort+ - cond: conditional branches +-The option requires at least one branch type among any, any_call, any_ret, ind_call.+The option requires at least one branch type among any, any_call, any_ret, ind_call, cond. The privilege levels may be omitted, in which case, the privilege levels of the associated event are applied to the branch filter. Both kernel (k) and hypervisor (hv) privilege levels are subject to permissions. When sampling on multiple events, branch stack sampling
This patch cleans up some existing indentation problem and
re-organizes the BHRB processing code with an helper function
named `update_branch_entry` making it more readable. This patch
does not change any functionality.
Signed-off-by: Anshuman Khandual <redacted>
---
arch/powerpc/perf/core-book3s.c | 102 ++++++++++++++++++++--------------------
1 file changed, 52 insertions(+), 50 deletions(-)
@@ -417,62 +427,54 @@ void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw)if(!val)/* Terminal marker: End of valid BHRB entries */break;-else{-addr=val&BHRB_EA;-pred=val&BHRB_PREDICTION;-if(!addr)-/* invalid entry */-continue;+addr=val&BHRB_EA;+pred=val&BHRB_PREDICTION;-/* Branches are read most recent first (ie. mfbhrb 0 is-*themostrecentbranch).-*Therearetwotypesofvalidentries:-*1)atargetentrywhichisthetoaddressofa-*computedgotolikeablr,bctr,btar.Thenext-*entryreadfromthebhrbwillbebranch-*correspondingtothistarget(ie.theactual-*blr/bctr/btarinstruction).-*2)afromaddresswhichisanactualbranch.Ifa-*targetentryproceedsthis,thenthisisthe-*matchingbranchforthattarget.Ifthisisnot-*followingatargetentry,thenthisisabranch-*wherethetargetisgivenasanimmediatefield-*intheinstruction(ie.aniorbformbranch).-*Inthiscaseweneedtoreadtheinstructionfrom-*memorytodeterminethetarget/toaddress.+if(!addr)+/* invalid entry */+continue;++/* Branches are read most recent first (ie. mfbhrb 0 is+*themostrecentbranch).+*Therearetwotypesofvalidentries:+*1)atargetentrywhichisthetoaddressofa+*computedgotolikeablr,bctr,btar.Thenext+*entryreadfromthebhrbwillbebranch+*correspondingtothistarget(ie.theactual+*blr/bctr/btarinstruction).+*2)afromaddresswhichisanactualbranch.Ifa+*targetentryproceedsthis,thenthisisthe+*matchingbranchforthattarget.Ifthisisnot+*followingatargetentry,thenthisisabranch+*wherethetargetisgivenasanimmediatefield+*intheinstruction(ie.aniorbformbranch).+*Inthiscaseweneedtoreadtheinstructionfrom+*memorytodeterminethetarget/toaddress.+*/+if(val&BHRB_TARGET){+/* Target branches use two entries+*(ie.computedgotos/XLform)*/+tmp=addr;+/* Get from address in next entry */+val=read_bhrb(r_index++);+addr=val&BHRB_EA;if(val&BHRB_TARGET){-/* Target branches use two entries-*(ie.computedgotos/XLform)-*/-cpuhw->bhrb_entries[u_index].to=addr;-cpuhw->bhrb_entries[u_index].mispred=pred;-cpuhw->bhrb_entries[u_index].predicted=~pred;--/* Get from address in next entry */-val=read_bhrb(r_index++);-addr=val&BHRB_EA;-if(val&BHRB_TARGET){-/* Shouldn't have two targets in a-row..Resetindexandtryagain*/-r_index--;-addr=0;-}-cpuhw->bhrb_entries[u_index].from=addr;-}else{-/* Branches to immediate field -(ieIorBform)*/-cpuhw->bhrb_entries[u_index].from=addr;-cpuhw->bhrb_entries[u_index].to=-power_pmu_bhrb_to(addr);-cpuhw->bhrb_entries[u_index].mispred=pred;-cpuhw->bhrb_entries[u_index].predicted=~pred;+/* Shouldn't have two targets in a+row..Resetindexandtryagain*/+r_index--;+addr=0;}-u_index++;-+update_branch_entry(cpuhw,u_index,addr,tmp,pred);+}else{+/* Branches to immediate field+(ieIorBform)*/+tmp=power_pmu_bhrb_to(addr);+update_branch_entry(cpuhw,u_index,addr,tmp,pred);}+u_index++;}cpuhw->bhrb_stack.nr=u_index;return;
Powerpc kernel now supports SW based branch filters for book3s systems with some
specifc requirements while dealing with HW supported branch filters in order to
achieve overall OR semantics prevailing in perf branch stack sampling framework.
This patch adapts the BHRB branch filter configuration to meet those protocols.
POWER8 PMU can only handle one HW based branch filter request at any point of time.
For all other combinations PMU will pass it on to the SW.
Signed-off-by: Anshuman Khandual <redacted>
---
arch/powerpc/perf/power8-pmu.c | 50 ++++++++++++++++++++++++++++++++++++------
1 file changed, 43 insertions(+), 7 deletions(-)
@@ -635,6 +635,16 @@ static int power8_generic_events[] = {staticu64power8_bhrb_filter_map(u64branch_sample_type,u64*bhrb_filter){+u64x,pmu_bhrb_filter;+pmu_bhrb_filter=0;+*bhrb_filter=0;++/* No branch filter requested */+if(branch_sample_type&PERF_SAMPLE_BRANCH_ANY){+*bhrb_filter=PERF_SAMPLE_BRANCH_ANY;+returnpmu_bhrb_filter;+}+/* BHRB and regular PMU events share the same privilege state*filterconfiguration.BHRBisalwaysrecordedalongwitha*regularPMUevent.Astheprivilegestatefilterishandled
@@ -645,16 +655,42 @@ static u64 power8_bhrb_filter_map(u64 branch_sample_type, u64 *bhrb_filter)/* Ignore user, kernel, hv bits */branch_sample_type&=~PERF_SAMPLE_BRANCH_PLM_ALL;-/* No branch filter requested */-if(branch_sample_type==PERF_SAMPLE_BRANCH_ANY)-return0;+/*+*P8doesnotsupportoringofPMUHWbranchfilters.Hence+*ifmultiplebranchfiltersarerequestedwhichincludesfilters+*supportedinPMU,stillgoaheadandclearthePMUbasedHWbranch+*filtercomponentasinthiscaseallthefilterswillbeprocessed+*inSW.+*/-if(branch_sample_type==PERF_SAMPLE_BRANCH_ANY_CALL){-returnPOWER8_MMCRA_IFM1;+for_each_branch_sample_type(x){+/* Ignore privilege branch filters */+if((x==PERF_SAMPLE_BRANCH_USER)+||(x==PERF_SAMPLE_BRANCH_KERNEL)+||(x==PERF_SAMPLE_BRANCH_HV))+continue;++if(!(branch_sample_type&x))+continue;++/* Supported individual PMU branch filters */+if(branch_sample_type&PERF_SAMPLE_BRANCH_ANY_CALL){+branch_sample_type&=~PERF_SAMPLE_BRANCH_ANY_CALL;+if(branch_sample_type){+/* Multiple branch filters will be processed in SW */+pmu_bhrb_filter=0;+*bhrb_filter=0;+returnpmu_bhrb_filter;+}else{+/* Individual branch filter will be processed in PMU */+pmu_bhrb_filter|=POWER8_MMCRA_IFM1;+*bhrb_filter|=PERF_SAMPLE_BRANCH_ANY_CALL;+returnpmu_bhrb_filter;+}+}}-/* Every thing else is unsupported */-return-1;+returnpmu_bhrb_filter;}staticvoidpower8_config_bhrb(u64pmu_bhrb_filter)
Generic powerpc branch analysis support added in the code patching
library which will help the subsequent patch on SW based filtering
of branch records in perf.
Signed-off-by: Anshuman Khandual <redacted>
---
arch/powerpc/include/asm/code-patching.h | 16 +++++++
arch/powerpc/lib/code-patching.c | 80 ++++++++++++++++++++++++++++++++
2 files changed, 96 insertions(+)
@@ -77,6 +77,7 @@ static unsigned int branch_opcode(unsigned int instr)return(instr>>26)&0x3F;}+/* Forms of branch instruction */staticintinstr_is_branch_iform(unsignedintinstr){returnbranch_opcode(instr)==18;
@@ -87,6 +88,85 @@ static int instr_is_branch_bform(unsigned int instr)returnbranch_opcode(instr)==16;}+staticintinstr_is_branch_xlform(unsignedintinstr)+{+returnbranch_opcode(instr)==19;+}++/* Classification of XL-form instruction */+staticintis_xlform_lr(unsignedintinstr)+{+return(instr&XL_FORM_LR)==XL_FORM_LR;+}++/* BO field analysis (B-form or XL-form) */+staticintis_bo_always(unsignedintinstr)+{+return(instr&BO_ALWAYS)==BO_ALWAYS;+}++/* Link bit is set */+staticintis_branch_link_set(unsignedintinstr)+{+return(instr&BRANCH_SET_LINK)==BRANCH_SET_LINK;+}++/* +*Genericsoftwareimplementedbranchfiltersused+*byperfbranchstacksamplingwhenPMUdoesnot+*processthemforsomereason.+*/++/* PERF_SAMPLE_BRANCH_ANY_RETURN */+boolinstr_is_return_branch(unsignedintinstr)+{+/*+*ConditionalandunconditionalbranchtoLRregister+*withoutsetingthelinkregister.+*/+if(is_xlform_lr(instr)&&!is_branch_link_set(instr))+returntrue;++returnfalse;+}++/* PERF_SAMPLE_BRANCH_COND */+boolinstr_is_conditional_branch(unsignedintinstr)+{+/* I-form instruction - excluded */+if(instr_is_branch_iform(instr))+returnfalse;++/* B-form or XL-form instruction */+if(instr_is_branch_bform(instr)||instr_is_branch_xlform(instr)){++/* Not branch always */+if(!is_bo_always(instr))+returntrue;+}+returnfalse;+}++/* PERF_SAMPLE_BRANCH_ANY_CALL */+boolinstr_is_func_call(unsignedintinstr)+{+/* LR should be set */+if(is_branch_link_set(instr))+returntrue;++returnfalse;+}++/* PERF_SAMPLE_BRANCH_IND_CALL */+boolinstr_is_indirect_func_call(unsignedintinstr)+{+/* XL-form instruction with LR set */+if(instr_is_branch_xlform(instr)&&is_branch_link_set(instr))+returntrue;++returnfalse;+}+intinstr_is_relative_branch(unsignedintinstr){if(instr&BRANCH_ABSOLUTE)
Hi,
On Mon, May 5, 2014 at 11:09 AM, Anshuman Khandual
[off-list ref] wrote:
This patchset is the re-spin of the original branch stack sampling
patchset which introduced new PERF_SAMPLE_BRANCH_COND branch filter. This patchset
also enables SW based branch filtering support for book3s powerpc platforms which
have PMU HW backed branch stack sampling support.
Summary of code changes in this patchset:
(1) Introduces a new PERF_SAMPLE_BRANCH_COND branch filter
(2) Add the "cond" branch filter options in the "perf record" tool
(3) Enable PERF_SAMPLE_BRANCH_COND in X86 platforms
(4) Enable PERF_SAMPLE_BRANCH_COND in POWER8 platform
(5) Update the documentation regarding "perf record" tool
(6) Add some new powerpc instruction analysis functions in code-patching library
(7) Enable SW based branch filter support for powerpc book3s
(8) Changed BHRB configuration in POWER8 to accommodate SW branch filters
I have been looking at those patches and ran some tests.
And I found a few issues so far.
I am running:
$ perf record -j any_ret -e cycles:u test_program
$ perf report -D
Most entries are okay and match the filter, however some do not make sense:
3642586996762 0x15d0 [0x108]: PERF_RECORD_SAMPLE(IP, 2): 17921/17921:
0x10001170 period: 613678 addr: 0
.... branch stack: nr:9
..... 0: 00000000100011cc -> 0000000010000e38
..... 1: 0000000010001150 -> 00000000100011bc
..... 2: 0000000010001208 -> 0000000010000e38
..... 3: 0000000010001160 -> 00000000100011f8
..... 4: 00000000100011cc -> 0000000010000e38
..... 5: 0000000010001150 -> 00000000100011bc
..... 6: 0000000010001208 -> 0000000010000e38
..... 7: 0000000010001160 -> 00000000100011f8
..... 8: 0000000000000000 -> 0000000010001160
^^^^^^
Entry 8 does not make sense, unless 0x0 is a valid return branch
instruction address.
If an address is invalid, the whole entry needs to be eliminated. It
is okay to have
less than the max number of entries supported by HW.
I also had cases where monitoring only at the user level, got me
branch addresses in the
0xc0000000...... range. My test program is linked statically.
when eliminating the bogus entries, my tests yielded only return
branch instruction addresses
which is good. Will run more tests.
I have been looking at those patches and ran some tests.
And I found a few issues so far.
I am running:
$ perf record -j any_ret -e cycles:u test_program
$ perf report -D
Most entries are okay and match the filter, however some do not make sense:
3642586996762 0x15d0 [0x108]: PERF_RECORD_SAMPLE(IP, 2): 17921/17921:
0x10001170 period: 613678 addr: 0
.... branch stack: nr:9
..... 0: 00000000100011cc -> 0000000010000e38
..... 1: 0000000010001150 -> 00000000100011bc
..... 2: 0000000010001208 -> 0000000010000e38
..... 3: 0000000010001160 -> 00000000100011f8
..... 4: 00000000100011cc -> 0000000010000e38
..... 5: 0000000010001150 -> 00000000100011bc
..... 6: 0000000010001208 -> 0000000010000e38
..... 7: 0000000010001160 -> 00000000100011f8
..... 8: 0000000000000000 -> 0000000010001160
^^^^^^
Entry 8 does not make sense, unless 0x0 is a valid return branch
instruction address.
If an address is invalid, the whole entry needs to be eliminated. It
is okay to have
less than the max number of entries supported by HW.
Hey Stephane,
Okay. The same behaviour is also reflected in the test results what I have
shared in the patchset. Here is that section.
(3) perf record -j any_ret -e branch-misses:u ./cprog
# Overhead Command Source Shared Object Source Symbol Target Shared Object Target Symbol
# ........ ....... .................... ..................... .................... .....................
#
15.61% cprog [unknown] [.] 00000000 cprog [.] sw_3_1
6.28% cprog cprog [.] symbol2 cprog [.] hw_1_2
6.28% cprog cprog [.] ctr_addr cprog [.] sw_4_1
6.26% cprog cprog [.] success_3_1_3 cprog [.] sw_3_1
6.24% cprog cprog [.] symbol1 cprog [.] hw_1_1
6.24% cprog cprog [.] sw_4_2 cprog [.] callme
6.21% cprog [unknown] [.] 00000000 cprog [.] callme
6.19% cprog cprog [.] lr_addr cprog [.] sw_4_2
3.16% cprog cprog [.] hw_1_2 cprog [.] callme
3.15% cprog cprog [.] success_3_1_1 cprog [.] sw_3_1
3.15% cprog cprog [.] sw_4_1 cprog [.] callme
3.14% cprog cprog [.] callme cprog [.] main
3.13% cprog cprog [.] hw_1_1 cprog [.] callme
So a lot of samples above have 0x0 as the "from" address. This originates from the code
section here inside the function "power_pmu_bhrb_read", where we hit two back to back
target addresses. So we zero out the from address for the first target address and re-read
the second address over again. So thats how we get zero as the from address. This is how the
HW capture the samples. I was reluctant to drop these samples but I agree that these kind of
samples can be dropped if we need to.
if (val & BHRB_TARGET) {
/* Shouldn't have two targets in a
row.. Reset index and try again */
r_index--;
addr = 0;
}
I also had cases where monitoring only at the user level, got me
branch addresses in the
0xc0000000...... range. My test program is linked statically.
Thats weird. I would need more information and details on this. BTW
what is the system you are running on ? Could you please share the
/proc/cpuinfo details of the same ?
when eliminating the bogus entries, my tests yielded only return
branch instruction addresses
which is good. Will run more tests.
On Wed, May 28, 2014 at 10:04 AM, Anshuman Khandual
[off-list ref] wrote:
On 05/27/2014 05:39 PM, Stephane Eranian wrote:
quoted
I have been looking at those patches and ran some tests.
And I found a few issues so far.
I am running:
$ perf record -j any_ret -e cycles:u test_program
$ perf report -D
Most entries are okay and match the filter, however some do not make sense:
3642586996762 0x15d0 [0x108]: PERF_RECORD_SAMPLE(IP, 2): 17921/17921:
0x10001170 period: 613678 addr: 0
.... branch stack: nr:9
..... 0: 00000000100011cc -> 0000000010000e38
..... 1: 0000000010001150 -> 00000000100011bc
..... 2: 0000000010001208 -> 0000000010000e38
..... 3: 0000000010001160 -> 00000000100011f8
..... 4: 00000000100011cc -> 0000000010000e38
..... 5: 0000000010001150 -> 00000000100011bc
..... 6: 0000000010001208 -> 0000000010000e38
..... 7: 0000000010001160 -> 00000000100011f8
..... 8: 0000000000000000 -> 0000000010001160
^^^^^^
Entry 8 does not make sense, unless 0x0 is a valid return branch
instruction address.
If an address is invalid, the whole entry needs to be eliminated. It
is okay to have
less than the max number of entries supported by HW.
Hey Stephane,
Okay. The same behaviour is also reflected in the test results what I have
shared in the patchset. Here is that section.
(3) perf record -j any_ret -e branch-misses:u ./cprog
# Overhead Command Source Shared Object Source Symbol Target Shared Object Target Symbol
# ........ ....... .................... ..................... .................... .....................
#
15.61% cprog [unknown] [.] 00000000 cprog [.] sw_3_1
6.28% cprog cprog [.] symbol2 cprog [.] hw_1_2
6.28% cprog cprog [.] ctr_addr cprog [.] sw_4_1
6.26% cprog cprog [.] success_3_1_3 cprog [.] sw_3_1
6.24% cprog cprog [.] symbol1 cprog [.] hw_1_1
6.24% cprog cprog [.] sw_4_2 cprog [.] callme
6.21% cprog [unknown] [.] 00000000 cprog [.] callme
6.19% cprog cprog [.] lr_addr cprog [.] sw_4_2
3.16% cprog cprog [.] hw_1_2 cprog [.] callme
3.15% cprog cprog [.] success_3_1_1 cprog [.] sw_3_1
3.15% cprog cprog [.] sw_4_1 cprog [.] callme
3.14% cprog cprog [.] callme cprog [.] main
3.13% cprog cprog [.] hw_1_1 cprog [.] callme
So a lot of samples above have 0x0 as the "from" address. This originates from the code
section here inside the function "power_pmu_bhrb_read", where we hit two back to back
Could you explain the back-to-back case a bit more here?
Back-to-back returns to me means something like:
int foo()
{
...
return bar();
}
int bar()
{
return 0;
}
Not counting the leaf optimization here, bar return to foo which
immediately returns: 2 back-2-back returns.
Is that the case you're talking about here?
target addresses. So we zero out the from address for the first target address and re-read
the second address over again. So thats how we get zero as the from address. This is how the
HW capture the samples. I was reluctant to drop these samples but I agree that these kind of
samples can be dropped if we need to.
I think we need to make it as simple as possible for tools, i.e.,
avoid having to decode the
disassembly to figure out what happened. Here address 0 is not exploitable.
if (val & BHRB_TARGET) {
/* Shouldn't have two targets in a
row.. Reset index and try again */
r_index--;
addr = 0;
}
On Wed, May 28, 2014 at 10:04 AM, Anshuman Khandual
[off-list ref] wrote:
quoted
On 05/27/2014 05:39 PM, Stephane Eranian wrote:
quoted
I have been looking at those patches and ran some tests.
And I found a few issues so far.
I am running:
$ perf record -j any_ret -e cycles:u test_program
$ perf report -D
Most entries are okay and match the filter, however some do not make sense:
3642586996762 0x15d0 [0x108]: PERF_RECORD_SAMPLE(IP, 2): 17921/17921:
0x10001170 period: 613678 addr: 0
.... branch stack: nr:9
..... 0: 00000000100011cc -> 0000000010000e38
..... 1: 0000000010001150 -> 00000000100011bc
..... 2: 0000000010001208 -> 0000000010000e38
..... 3: 0000000010001160 -> 00000000100011f8
..... 4: 00000000100011cc -> 0000000010000e38
..... 5: 0000000010001150 -> 00000000100011bc
..... 6: 0000000010001208 -> 0000000010000e38
..... 7: 0000000010001160 -> 00000000100011f8
..... 8: 0000000000000000 -> 0000000010001160
^^^^^^
Entry 8 does not make sense, unless 0x0 is a valid return branch
instruction address.
If an address is invalid, the whole entry needs to be eliminated. It
is okay to have
less than the max number of entries supported by HW.
Hey Stephane,
Okay. The same behaviour is also reflected in the test results what I have
shared in the patchset. Here is that section.
(3) perf record -j any_ret -e branch-misses:u ./cprog
# Overhead Command Source Shared Object Source Symbol Target Shared Object Target Symbol
# ........ ....... .................... ..................... .................... .....................
#
15.61% cprog [unknown] [.] 00000000 cprog [.] sw_3_1
6.28% cprog cprog [.] symbol2 cprog [.] hw_1_2
6.28% cprog cprog [.] ctr_addr cprog [.] sw_4_1
6.26% cprog cprog [.] success_3_1_3 cprog [.] sw_3_1
6.24% cprog cprog [.] symbol1 cprog [.] hw_1_1
6.24% cprog cprog [.] sw_4_2 cprog [.] callme
6.21% cprog [unknown] [.] 00000000 cprog [.] callme
6.19% cprog cprog [.] lr_addr cprog [.] sw_4_2
3.16% cprog cprog [.] hw_1_2 cprog [.] callme
3.15% cprog cprog [.] success_3_1_1 cprog [.] sw_3_1
3.15% cprog cprog [.] sw_4_1 cprog [.] callme
3.14% cprog cprog [.] callme cprog [.] main
3.13% cprog cprog [.] hw_1_1 cprog [.] callme
So a lot of samples above have 0x0 as the "from" address. This originates from the code
section here inside the function "power_pmu_bhrb_read", where we hit two back to back
Could you explain the back-to-back case a bit more here?
Back-to-back returns to me means something like:
int foo()
{
...
return bar();
}
int bar()
{
return 0;
}
Not counting the leaf optimization here, bar return to foo which
immediately returns: 2 back-2-back returns.
Is that the case you're talking about here?
No. Filtering of return branches has been implemented in SW only. So PMU as such does not capture
return only branches. It captures all the branches what it encounters. During the capture process
PMU might *record* two back to back "target addresses" (without capturing the from address for the
first one) for which we are unable to figure out the "from address". This leaves us with one branch
record where we have the target address not from address and so we make it zero. With the current
logic all branch records with "from address" as zero get filtered through and become the part of the
final set. I was not too sure how to deal with these cases.
quoted
target addresses. So we zero out the from address for the first target address and re-read
the second address over again. So thats how we get zero as the from address. This is how the
HW capture the samples. I was reluctant to drop these samples but I agree that these kind of
samples can be dropped if we need to.
I think we need to make it as simple as possible for tools, i.e.,
avoid having to decode the
disassembly to figure out what happened. Here address 0 is not exploitable.
Thats right. Dropping the branch record where we have only the target address not the from address
might just solve this problem.
On Mon, Jun 2, 2014 at 6:04 PM, Anshuman Khandual
[off-list ref] wrote:
On 06/02/2014 06:29 PM, Stephane Eranian wrote:
quoted
On Wed, May 28, 2014 at 10:04 AM, Anshuman Khandual
[off-list ref] wrote:
quoted
On 05/27/2014 05:39 PM, Stephane Eranian wrote:
quoted
I have been looking at those patches and ran some tests.
And I found a few issues so far.
I am running:
$ perf record -j any_ret -e cycles:u test_program
$ perf report -D
Most entries are okay and match the filter, however some do not make sense:
3642586996762 0x15d0 [0x108]: PERF_RECORD_SAMPLE(IP, 2): 17921/17921:
0x10001170 period: 613678 addr: 0
.... branch stack: nr:9
..... 0: 00000000100011cc -> 0000000010000e38
..... 1: 0000000010001150 -> 00000000100011bc
..... 2: 0000000010001208 -> 0000000010000e38
..... 3: 0000000010001160 -> 00000000100011f8
..... 4: 00000000100011cc -> 0000000010000e38
..... 5: 0000000010001150 -> 00000000100011bc
..... 6: 0000000010001208 -> 0000000010000e38
..... 7: 0000000010001160 -> 00000000100011f8
..... 8: 0000000000000000 -> 0000000010001160
^^^^^^
Entry 8 does not make sense, unless 0x0 is a valid return branch
instruction address.
If an address is invalid, the whole entry needs to be eliminated. It
is okay to have
less than the max number of entries supported by HW.
Hey Stephane,
Okay. The same behaviour is also reflected in the test results what I have
shared in the patchset. Here is that section.
(3) perf record -j any_ret -e branch-misses:u ./cprog
# Overhead Command Source Shared Object Source Symbol Target Shared Object Target Symbol
# ........ ....... .................... ..................... .................... .....................
#
15.61% cprog [unknown] [.] 00000000 cprog [.] sw_3_1
6.28% cprog cprog [.] symbol2 cprog [.] hw_1_2
6.28% cprog cprog [.] ctr_addr cprog [.] sw_4_1
6.26% cprog cprog [.] success_3_1_3 cprog [.] sw_3_1
6.24% cprog cprog [.] symbol1 cprog [.] hw_1_1
6.24% cprog cprog [.] sw_4_2 cprog [.] callme
6.21% cprog [unknown] [.] 00000000 cprog [.] callme
6.19% cprog cprog [.] lr_addr cprog [.] sw_4_2
3.16% cprog cprog [.] hw_1_2 cprog [.] callme
3.15% cprog cprog [.] success_3_1_1 cprog [.] sw_3_1
3.15% cprog cprog [.] sw_4_1 cprog [.] callme
3.14% cprog cprog [.] callme cprog [.] main
3.13% cprog cprog [.] hw_1_1 cprog [.] callme
So a lot of samples above have 0x0 as the "from" address. This originates from the code
section here inside the function "power_pmu_bhrb_read", where we hit two back to back
Could you explain the back-to-back case a bit more here?
Back-to-back returns to me means something like:
int foo()
{
...
return bar();
}
int bar()
{
return 0;
}
Not counting the leaf optimization here, bar return to foo which
immediately returns: 2 back-2-back returns.
Is that the case you're talking about here?
No. Filtering of return branches has been implemented in SW only. So PMU as such does not capture
return only branches. It captures all the branches what it encounters. During the capture process
PMU might *record* two back to back "target addresses" (without capturing the from address for the
first one) for which we are unable to figure out the "from address". This leaves us with one branch
record where we have the target address not from address and so we make it zero. With the current
logic all branch records with "from address" as zero get filtered through and become the part of the
final set. I was not too sure how to deal with these cases.
So PPC8 captures all branches, no HW filter. But then in SW you filter
out non return branches.
Given you're description, I have to believe that sometimes the HW does
not even capture the
from address. If so, then in that case, I think it is best to drop the
sample. Because the target
address may be the target of an indirect branch for which there is no
way to find the source.
In other words, the record cannot be exploited.
But why does the HW not capture some from addresses?
I am worried this might create some bias in the samples.
quoted
quoted
target addresses. So we zero out the from address for the first target address and re-read
the second address over again. So thats how we get zero as the from address. This is how the
HW capture the samples. I was reluctant to drop these samples but I agree that these kind of
samples can be dropped if we need to.
I think we need to make it as simple as possible for tools, i.e.,
avoid having to decode the
disassembly to figure out what happened. Here address 0 is not exploitable.
Thats right. Dropping the branch record where we have only the target address not the from address
might just solve this problem.
From: Michael Neuling <hidden> Date: 2014-06-02 22:52:18
On Mon, 2014-06-02 at 14:59 +0200, Stephane Eranian wrote:
On Wed, May 28, 2014 at 10:04 AM, Anshuman Khandual
[off-list ref] wrote:
quoted
On 05/27/2014 05:39 PM, Stephane Eranian wrote:
quoted
I have been looking at those patches and ran some tests.
And I found a few issues so far.
I am running:
$ perf record -j any_ret -e cycles:u test_program
$ perf report -D
Most entries are okay and match the filter, however some do not make s=
ense:
quoted
quoted
3642586996762 0x15d0 [0x108]: PERF_RECORD_SAMPLE(IP, 2): 17921/17921:
0x10001170 period: 613678 addr: 0
.... branch stack: nr:9
..... 0: 00000000100011cc -> 0000000010000e38
..... 1: 0000000010001150 -> 00000000100011bc
..... 2: 0000000010001208 -> 0000000010000e38
..... 3: 0000000010001160 -> 00000000100011f8
..... 4: 00000000100011cc -> 0000000010000e38
..... 5: 0000000010001150 -> 00000000100011bc
..... 6: 0000000010001208 -> 0000000010000e38
..... 7: 0000000010001160 -> 00000000100011f8
..... 8: 0000000000000000 -> 0000000010001160
^^^^^^
Entry 8 does not make sense, unless 0x0 is a valid return branch
instruction address.
If an address is invalid, the whole entry needs to be eliminated. It
is okay to have
less than the max number of entries supported by HW.
Hey Stephane,
Okay. The same behaviour is also reflected in the test results what I h=
ave
quoted
shared in the patchset. Here is that section.
(3) perf record -j any_ret -e branch-misses:u ./cprog
# Overhead Command Source Shared Object Source Symbol Targe=
So a lot of samples above have 0x0 as the "from" address. This originat=
es from the code
quoted
section here inside the function "power_pmu_bhrb_read", where we hit tw=
o back to back
=20
Could you explain the back-to-back case a bit more here?
Back-to-back returns to me means something like:
=20
int foo()
{
...
return bar();
}
=20
int bar()
{
return 0;
}
=20
Not counting the leaf optimization here, bar return to foo which
immediately returns: 2 back-2-back returns.
Is that the case you're talking about here?
=20
quoted
target addresses. So we zero out the from address for the first target =
address and re-read
quoted
the second address over again. So thats how we get zero as the from add=
ress. This is how the
quoted
HW capture the samples. I was reluctant to drop these samples but I agr=
ee that these kind of
quoted
samples can be dropped if we need to.
I think we need to make it as simple as possible for tools, i.e.,
avoid having to decode the
disassembly to figure out what happened. Here address 0 is not exploitabl=
e.
This was my fault. I figured if we only had partial information from
the hardware, it was best to at least export that to the tools. If you
disagree then we can we remove them. There was a discussion a while
back on this here:
https://lkml.org/lkml/2013/5/8/543
Because of the way the branch buffer is structured, we can certainly
lose the from address of the oldest branch in the buffer. I've not seen
the hardware lose the from branches in the middle of the buffer but I
guess it's possible. We'll have to get back to you on how or why this
would occur (and associated bias) after talking to some hardware folk.
FWIW, there was some discussion on how the POWER8 branch buffer works a
while back here (same thread as before):
https://lkml.org/lkml/2013/5/8/541
Mikey