[PATCH v5 00/13] IMC Instrumentation Support

2017-03-16 Thread Madhavan Srinivasan
Power9 has In-Memory-Collection (IMC) infrastructure which contains
various Performance Monitoring Units (PMUs) at Nest level (these are
on-chip but off-core), Core level and Thread level.

The Nest PMU counters are handled by a Nest IMC microcode which runs
in the OCC (On-Chip Controller) complex. The microcode collects the
counter data and moves the nest IMC counter data to memory.

The Core and Thread IMC PMU counters are handled in the core. Core
level PMU counters give us the IMC counters' data per core and thread
level PMU counters give us the IMC counters' data per CPU thread.

This patchset enables the nest IMC, core IMC and thread IMC
PMUs and is based on the initial work done by Madhavan Srinivasan.
"Nest Instrumentation Support" :
https://lists.ozlabs.org/pipermail/linuxppc-dev/2015-August/132078.html

v1 for this patchset can be found here :
https://lwn.net/Articles/705475/

Nest events:
Per-chip nest instrumentation provides various per-chip metrics
such as memory, powerbus, Xlink and Alink bandwidth.

Core events:
Per-core IMC instrumentation provides various per-core metrics
such as non-idle cycles, non-idle instructions, various cache and
memory related metrics etc.

Thread events:
All the events for thread level are same as core level with the
difference being in the domain. These are per-cpu metrics.

PMU Events' Information:
OPAL obtains the IMC PMU and event information from the IMC Catalog
and passes on to the kernel via the device tree. The events' information
contains :
 - Event name
 - Event Offset
 - Event description
and, maybe :
 - Event scale
 - Event unit

Some PMUs may have a common scale and unit values for all their
supported events. For those cases, the scale and unit properties for
those events must be inherited from the PMU.

The event offset in the memory is where the counter data gets
accumulated.

The OPAL-side patches are posted upstream :
https://lists.ozlabs.org/pipermail/skiboot/2017-March/006531.html

The kernel discovers the IMC counters information in the device tree
at the "imc-counters" device node which has a compatible field
"ibm,opal-in-memory-counters".

Parsing of the Events' information:
To parse the IMC PMUs and events information, the kernel has to
discover the "imc-counters" node and walk through the pmu and event
nodes.

Here is an excerpt of the dt showing the imc-counters with
mcs0 (nest), core and thread node:

https://github.com/open-power/ima-catalog/blob/master/81E00612.4E0100.dts

/dts-v1/;

[...]

/dts-v1/;

/ {
name = "";
compatible = "ibm,opal-in-memory-counters";
#address-cells = <0x1>;
#size-cells = <0x1>;
imc-nest-offset = <0x32>;
imc-nest-size = <0x3>;
version-id = "";

NEST_MCS: nest-mcs-events {
#address-cells = <0x1>;
#size-cells = <0x1>;

event@0 {
event-name = "RRTO_QFULL_NO_DISP" ;
reg = <0x0 0x8>;
desc = "RRTO not dispatched in MCS0 due to capacity - 
pulses once for each time a valid RRTO op is not dispatched due to a command 
list full condition" ;
};
event@8 {
event-name = "WRTO_QFULL_NO_DISP" ;
reg = <0x8 0x8>;
desc = "WRTO not dispatched in MCS0 due to capacity - 
pulses once for each time a valid WRTO op is not dispatched due to a command 
list full condition" ;
};
[...]
mcs0 {
compatible = "ibm,imc-counters-nest";
events-prefix = "PM_MCS0_";
unit = "";
scale = "";
reg = <0x118 0x8>;
events = < _MCS >;
};

mcs1 {
compatible = "ibm,imc-counters-nest";
events-prefix = "PM_MCS1_";
unit = "";
scale = "";
reg = <0x198 0x8>;
events = < _MCS >;
};
[...]

CORE_EVENTS: core-events {
#address-cells = <0x1>;
#size-cells = <0x1>;

event@e0 {
event-name = "0THRD_NON_IDLE_PCYC" ;
reg = <0xe0 0x8>;
desc = "The number of processor cycles when all threads 
are idle" ;
};
event@120 {
event-name = "1THRD_NON_IDLE_PCYC" ;
reg = <0x120 0x8>;
desc = "The number of processor cycles when exactly one 
SMT thread is executing non-idle code" ;

Re: [PATCH v2 1/6] powerpc/perf: Define big-endian version of perf_mem_data_src

2017-03-15 Thread Madhavan Srinivasan



On Wednesday 15 March 2017 05:53 PM, Peter Zijlstra wrote:

On Wed, Mar 15, 2017 at 05:20:15PM +1100, Michael Ellerman wrote:


I see no implementation; so why are you poking at it.

Maddy has posted an implementation of the kernel part for powerpc in
patch 2 of this series, but maybe you're not on Cc?

I am not indeed. That and a completely inadequate Changelog have lead to
great confusion.


Yes. my bad. I will send out a v3 today and will CC. Also will add
ellerman's explanation to the commit message.

Sorry for the confusion.

Maddy




Re: [PATCH v2 1/6] powerpc/perf: Define big-endian version of perf_mem_data_src

2017-03-15 Thread Madhavan Srinivasan



On Wednesday 15 March 2017 05:53 PM, Peter Zijlstra wrote:

On Wed, Mar 15, 2017 at 05:20:15PM +1100, Michael Ellerman wrote:


I see no implementation; so why are you poking at it.

Maddy has posted an implementation of the kernel part for powerpc in
patch 2 of this series, but maybe you're not on Cc?

I am not indeed. That and a completely inadequate Changelog have lead to
great confusion.


Yes. my bad. I will send out a v3 today and will CC. Also will add
ellerman's explanation to the commit message.

Sorry for the confusion.

Maddy




Re: [PATCH v2 1/6] powerpc/perf: Define big-endian version of perf_mem_data_src

2017-03-15 Thread Madhavan Srinivasan



On Wednesday 15 March 2017 11:50 AM, Michael Ellerman wrote:

Hi Peter,

Peter Zijlstra <pet...@infradead.org> writes:

On Tue, Mar 14, 2017 at 02:31:51PM +0530, Madhavan Srinivasan wrote:


Huh? PPC hasn't yet implemented this? Then why are you fixing it?

yes, PPC hasn't implemented this (until now).

until now where?

On powerpc there is currently no kernel support for filling the data_src
value with anything meaningful.

A user can still request PERF_SAMPLE_DATA_SRC (perf report -d), but they
just get the default value from perf_sample_data_init(), which is
PERF_MEM_NA.

Though even that is currently broken with a big endian perf tool.


And did not understand "Then why are you fixing it?"

I see no implementation; so why are you poking at it.

Maddy has posted an implementation of the kernel part for powerpc in
patch 2 of this series, but maybe you're not on Cc?


Sorry, was out yesterday.

Yes my bad. I CCed lkml and ppcdev and took the emails
from get_maintainer script and added to each file.

I will send out a v3 with peterz and others in all patch.



Regardless of us wanting to do the kernel side on powerpc, the current
API is broken on big endian.

That's because in the kernel the PERF_MEM_NA value is constructed using
shifts:

   /* TLB access */
   #define PERF_MEM_TLB_NA  0x01 /* not available */
   ...
   #define PERF_MEM_TLB_SHIFT   26
   
   #define PERF_MEM_S(a, s) \

(((__u64)PERF_MEM_##a##_##s) << PERF_MEM_##a##_SHIFT)
   
   #define PERF_MEM_NA (PERF_MEM_S(OP, NA)   |\

PERF_MEM_S(LVL, NA)   |\
PERF_MEM_S(SNOOP, NA) |\
PERF_MEM_S(LOCK, NA)  |\
PERF_MEM_S(TLB, NA))

Which works out as:

   ((0x01 << 0) | (0x01 << 5) | (0x01 << 19) | (0x01 << 24) | (0x01 << 26))


Which means the PERF_MEM_NA value comes out of the kernel as 0x5080021
in CPU endian.

But then in the perf tool, the code uses the bitfields to inspect the
value, and currently the bitfields are defined using little endian
ordering.

So eg. in perf_mem__tlb_scnprintf() we see:
   data_src->val = 0x5080021
  op = 0x0
 lvl = 0x0
   snoop = 0x0
lock = 0x0
dtlb = 0x0
rsvd = 0x5080021


So this patch does what I think is the minimal fix, of changing the
definition of the bitfields to match the values that are already
exported by the kernel on big endian. And it makes no change on little
endian.


Thanks for the detailed explanation. I will add this to the patch
commit message in the v3.

Maddy



cheers





Re: [PATCH v2 1/6] powerpc/perf: Define big-endian version of perf_mem_data_src

2017-03-15 Thread Madhavan Srinivasan



On Wednesday 15 March 2017 11:50 AM, Michael Ellerman wrote:

Hi Peter,

Peter Zijlstra  writes:

On Tue, Mar 14, 2017 at 02:31:51PM +0530, Madhavan Srinivasan wrote:


Huh? PPC hasn't yet implemented this? Then why are you fixing it?

yes, PPC hasn't implemented this (until now).

until now where?

On powerpc there is currently no kernel support for filling the data_src
value with anything meaningful.

A user can still request PERF_SAMPLE_DATA_SRC (perf report -d), but they
just get the default value from perf_sample_data_init(), which is
PERF_MEM_NA.

Though even that is currently broken with a big endian perf tool.


And did not understand "Then why are you fixing it?"

I see no implementation; so why are you poking at it.

Maddy has posted an implementation of the kernel part for powerpc in
patch 2 of this series, but maybe you're not on Cc?


Sorry, was out yesterday.

Yes my bad. I CCed lkml and ppcdev and took the emails
from get_maintainer script and added to each file.

I will send out a v3 with peterz and others in all patch.



Regardless of us wanting to do the kernel side on powerpc, the current
API is broken on big endian.

That's because in the kernel the PERF_MEM_NA value is constructed using
shifts:

   /* TLB access */
   #define PERF_MEM_TLB_NA  0x01 /* not available */
   ...
   #define PERF_MEM_TLB_SHIFT   26
   
   #define PERF_MEM_S(a, s) \

(((__u64)PERF_MEM_##a##_##s) << PERF_MEM_##a##_SHIFT)
   
   #define PERF_MEM_NA (PERF_MEM_S(OP, NA)   |\

PERF_MEM_S(LVL, NA)   |\
PERF_MEM_S(SNOOP, NA) |\
PERF_MEM_S(LOCK, NA)  |\
PERF_MEM_S(TLB, NA))

Which works out as:

   ((0x01 << 0) | (0x01 << 5) | (0x01 << 19) | (0x01 << 24) | (0x01 << 26))


Which means the PERF_MEM_NA value comes out of the kernel as 0x5080021
in CPU endian.

But then in the perf tool, the code uses the bitfields to inspect the
value, and currently the bitfields are defined using little endian
ordering.

So eg. in perf_mem__tlb_scnprintf() we see:
   data_src->val = 0x5080021
  op = 0x0
 lvl = 0x0
   snoop = 0x0
lock = 0x0
dtlb = 0x0
rsvd = 0x5080021


So this patch does what I think is the minimal fix, of changing the
definition of the bitfields to match the values that are already
exported by the kernel on big endian. And it makes no change on little
endian.


Thanks for the detailed explanation. I will add this to the patch
commit message in the v3.

Maddy



cheers





Re: [PATCH v2 1/6] powerpc/perf: Define big-endian version of perf_mem_data_src

2017-03-14 Thread Madhavan Srinivasan



On Monday 13 March 2017 06:20 PM, Peter Zijlstra wrote:

On Mon, Mar 13, 2017 at 04:45:51PM +0530, Madhavan Srinivasan wrote:

  - should you not have fixed this in the tool only? This patch
effectively breaks ABI on big-endian architectures.

IIUC, we are the first BE user for this feature
(Kindly correct me if I am wrong), so technically we
are not breaking ABI here :) .  But let me also look  at
the dynamic conversion part.

Huh? PPC hasn't yet implemented this? Then why are you fixing it?


yes, PPC hasn't implemented this (until now).
And did not understand "Then why are you fixing it?"

Maddy






Re: [PATCH v2 1/6] powerpc/perf: Define big-endian version of perf_mem_data_src

2017-03-14 Thread Madhavan Srinivasan



On Monday 13 March 2017 06:20 PM, Peter Zijlstra wrote:

On Mon, Mar 13, 2017 at 04:45:51PM +0530, Madhavan Srinivasan wrote:

  - should you not have fixed this in the tool only? This patch
effectively breaks ABI on big-endian architectures.

IIUC, we are the first BE user for this feature
(Kindly correct me if I am wrong), so technically we
are not breaking ABI here :) .  But let me also look  at
the dynamic conversion part.

Huh? PPC hasn't yet implemented this? Then why are you fixing it?


yes, PPC hasn't implemented this (until now).
And did not understand "Then why are you fixing it?"

Maddy






Re: [PATCH v2 1/6] powerpc/perf: Define big-endian version of perf_mem_data_src

2017-03-13 Thread Madhavan Srinivasan



On Tuesday 07 March 2017 03:53 PM, Peter Zijlstra wrote:

On Tue, Mar 07, 2017 at 03:28:17PM +0530, Madhavan Srinivasan wrote:


On Monday 06 March 2017 04:52 PM, Peter Zijlstra wrote:

On Mon, Mar 06, 2017 at 04:13:08PM +0530, Madhavan Srinivasan wrote:

From: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>

perf_mem_data_src is an union that is initialized via the ->val field
and accessed via the bitmap fields. For this to work on big endian
platforms, we also need a big-endian represenation of perf_mem_data_src.

Doesn't this break interpreting the data on a different endian machine?

IIUC, we will need this patch to not to break the interpreting data
on a different endian machine. Data collected from power8 LE/BE
guests with this patchset applied. Kindly correct me if I missed
your question here.

So your patch adds compile time bitfield differences. My worry was that
there was no dynamic conversion routine in the tools (it has for a lot
of other places).

This yields two questions:

  - are these two static layouts identical? (seeing that you illustrate
cross-endian things working this seems likely).

  - should you not have fixed this in the tool only? This patch
effectively breaks ABI on big-endian architectures.


IIUC, we are the first BE user for this feature
(Kindly correct me if I am wrong), so technically we
are not breaking ABI here :) .  But let me also look  at
the dynamic conversion part.

Maddy







Re: [PATCH v2 1/6] powerpc/perf: Define big-endian version of perf_mem_data_src

2017-03-13 Thread Madhavan Srinivasan



On Tuesday 07 March 2017 03:53 PM, Peter Zijlstra wrote:

On Tue, Mar 07, 2017 at 03:28:17PM +0530, Madhavan Srinivasan wrote:


On Monday 06 March 2017 04:52 PM, Peter Zijlstra wrote:

On Mon, Mar 06, 2017 at 04:13:08PM +0530, Madhavan Srinivasan wrote:

From: Sukadev Bhattiprolu 

perf_mem_data_src is an union that is initialized via the ->val field
and accessed via the bitmap fields. For this to work on big endian
platforms, we also need a big-endian represenation of perf_mem_data_src.

Doesn't this break interpreting the data on a different endian machine?

IIUC, we will need this patch to not to break the interpreting data
on a different endian machine. Data collected from power8 LE/BE
guests with this patchset applied. Kindly correct me if I missed
your question here.

So your patch adds compile time bitfield differences. My worry was that
there was no dynamic conversion routine in the tools (it has for a lot
of other places).

This yields two questions:

  - are these two static layouts identical? (seeing that you illustrate
cross-endian things working this seems likely).

  - should you not have fixed this in the tool only? This patch
effectively breaks ABI on big-endian architectures.


IIUC, we are the first BE user for this feature
(Kindly correct me if I am wrong), so technically we
are not breaking ABI here :) .  But let me also look  at
the dynamic conversion part.

Maddy







Re: [PATCH v2 1/6] powerpc/perf: Define big-endian version of perf_mem_data_src

2017-03-07 Thread Madhavan Srinivasan



On Monday 06 March 2017 04:52 PM, Peter Zijlstra wrote:

On Mon, Mar 06, 2017 at 04:13:08PM +0530, Madhavan Srinivasan wrote:

From: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>

perf_mem_data_src is an union that is initialized via the ->val field
and accessed via the bitmap fields. For this to work on big endian
platforms, we also need a big-endian represenation of perf_mem_data_src.

Doesn't this break interpreting the data on a different endian machine?


IIUC, we will need this patch to not to break the interpreting data
on a different endian machine. Data collected from power8 LE/BE
guests with this patchset applied. Kindly correct me if I missed
your question here.


With this patchset applied, perf.data from a power8 BigEndian guest:
==

$ sudo ./perf record -d -e mem_access ls
  [ perf record: Woken up 1 times to write data ]
  [ perf record: Captured and wrote 0.007 MB perf.data (8 samples) ]

$ sudo ./perf report --mem-mode --stdio
  # To display the perf.data header info, please use 
--header/--header-only options.

  #
  #
  # Total Lost Samples: 0
  #
  # Samples: 8  of event 'mem_access'
  # Total weight : 8
  # Sort order   : 
local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked

  #
  # Overhead  Local Weight  Memory access Symbol   
Shared Object Data Symbol Data 
Object Snoop TLB access  Locked
  #      
...   
.. 
..   ..  
..

  #
  25.00%  0 L2 hit[H] 
0xc000c910   [unknown] [H] 0xc00f170e5310 
[unknown]   N/A N/A No
  12.50%  0 L2 hit[k] 
.idle_cpu[kernel.vmlinux]  [k] __per_cpu_offset+0x68 
[kernel.vmlinux].data..read_mostly  N/A N/A No
  12.50%  0 L2 hit[H] 
0xc000ca58   [unknown] [H] 0xc00f170e5200 
[unknown]   N/A N/A No
  12.50%  0 L3 hit[k] 
.copypage_power7 [kernel.vmlinux]  [k] 0xc0002f6fc600 
[kernel.vmlinux].bssN/A N/A No
  12.50%  0 L3 hit[k] 
.copypage_power7 [kernel.vmlinux]  [k] 0xc0003f8b1980 
[kernel.vmlinux].bssN/A N/A No
  12.50%  0 Local RAM hit [k] 
._raw_spin_lock_irqsave  [kernel.vmlinux]  [k] 0xc00033b5bdf4 
[kernel.vmlinux].bssMiss N/A No
  12.50%  0 Remote Cache (1 hop) hit  [k] 
.perf_iterate_ctx[kernel.vmlinux]  [k] 0xc0e88648 
[kernel.vmlinux]HitM N/A No



perf report from power8 LittleEndian guest (with this patch applied to 
perf tool):

==

$ ./perf report --mem-mode --stdio -i perf.data.p8be.withpatch
  No kallsyms or vmlinux with build-id 
ca8a1a9d4b62b2a67ee01050afb1dfa03565a655 was found
  /boot/vmlinux with build id ca8a1a9d4b62b2a67ee01050afb1dfa03565a655 
not found, continuing without symbols
  No kallsyms or vmlinux with build-id 
ca8a1a9d4b62b2a67ee01050afb1dfa03565a655 was found
  /boot/vmlinux with build id ca8a1a9d4b62b2a67ee01050afb1dfa03565a655 
not found, continuing without symbols
  # To display the perf.data header info, please use 
--header/--header-only options.

  #
  #
  # Total Lost Samples: 0
  #
  # Samples: 8  of event 'mem_access'
  # Total weight : 8
  # Sort order   : 
local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked

  #
  # Overhead  Local Weight  Memory access Symbol  
Shared Object Data Symbol Data Object   Snoop TLB 
access  Locked
  #      
..    .. 
    ..  ..

  #
  25.00%  0 L2 hit[H] 
0xc000c910  [unknown] [H] 0xc00f170e5310 
[unknown] N/A   N/A No
  12.50%  0 L2 hit[k] 
0xc00f4d0c  [kernel.vmlinux]  [k] 0xc0f2dac8 
[kernel.vmlinux]  N/A   N/A No
  12.50%  0 L2 hit[H] 
0xc000ca58  [unknown] [H] 0xc00f170e5200 
[unknown] N/A   N/A No
  12.50%  0 L3 hit[k] 
0xc006b560  [kernel.vml

Re: [PATCH v2 1/6] powerpc/perf: Define big-endian version of perf_mem_data_src

2017-03-07 Thread Madhavan Srinivasan



On Monday 06 March 2017 04:52 PM, Peter Zijlstra wrote:

On Mon, Mar 06, 2017 at 04:13:08PM +0530, Madhavan Srinivasan wrote:

From: Sukadev Bhattiprolu 

perf_mem_data_src is an union that is initialized via the ->val field
and accessed via the bitmap fields. For this to work on big endian
platforms, we also need a big-endian represenation of perf_mem_data_src.

Doesn't this break interpreting the data on a different endian machine?


IIUC, we will need this patch to not to break the interpreting data
on a different endian machine. Data collected from power8 LE/BE
guests with this patchset applied. Kindly correct me if I missed
your question here.


With this patchset applied, perf.data from a power8 BigEndian guest:
==

$ sudo ./perf record -d -e mem_access ls
  [ perf record: Woken up 1 times to write data ]
  [ perf record: Captured and wrote 0.007 MB perf.data (8 samples) ]

$ sudo ./perf report --mem-mode --stdio
  # To display the perf.data header info, please use 
--header/--header-only options.

  #
  #
  # Total Lost Samples: 0
  #
  # Samples: 8  of event 'mem_access'
  # Total weight : 8
  # Sort order   : 
local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked

  #
  # Overhead  Local Weight  Memory access Symbol   
Shared Object Data Symbol Data 
Object Snoop TLB access  Locked
  #      
...   
.. 
..   ..  
..

  #
  25.00%  0 L2 hit[H] 
0xc000c910   [unknown] [H] 0xc00f170e5310 
[unknown]   N/A N/A No
  12.50%  0 L2 hit[k] 
.idle_cpu[kernel.vmlinux]  [k] __per_cpu_offset+0x68 
[kernel.vmlinux].data..read_mostly  N/A N/A No
  12.50%  0 L2 hit[H] 
0xc000ca58   [unknown] [H] 0xc00f170e5200 
[unknown]   N/A N/A No
  12.50%  0 L3 hit[k] 
.copypage_power7 [kernel.vmlinux]  [k] 0xc0002f6fc600 
[kernel.vmlinux].bssN/A N/A No
  12.50%  0 L3 hit[k] 
.copypage_power7 [kernel.vmlinux]  [k] 0xc0003f8b1980 
[kernel.vmlinux].bssN/A N/A No
  12.50%  0 Local RAM hit [k] 
._raw_spin_lock_irqsave  [kernel.vmlinux]  [k] 0xc00033b5bdf4 
[kernel.vmlinux].bssMiss N/A No
  12.50%  0 Remote Cache (1 hop) hit  [k] 
.perf_iterate_ctx[kernel.vmlinux]  [k] 0xc0e88648 
[kernel.vmlinux]HitM N/A No



perf report from power8 LittleEndian guest (with this patch applied to 
perf tool):

==

$ ./perf report --mem-mode --stdio -i perf.data.p8be.withpatch
  No kallsyms or vmlinux with build-id 
ca8a1a9d4b62b2a67ee01050afb1dfa03565a655 was found
  /boot/vmlinux with build id ca8a1a9d4b62b2a67ee01050afb1dfa03565a655 
not found, continuing without symbols
  No kallsyms or vmlinux with build-id 
ca8a1a9d4b62b2a67ee01050afb1dfa03565a655 was found
  /boot/vmlinux with build id ca8a1a9d4b62b2a67ee01050afb1dfa03565a655 
not found, continuing without symbols
  # To display the perf.data header info, please use 
--header/--header-only options.

  #
  #
  # Total Lost Samples: 0
  #
  # Samples: 8  of event 'mem_access'
  # Total weight : 8
  # Sort order   : 
local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked

  #
  # Overhead  Local Weight  Memory access Symbol  
Shared Object Data Symbol Data Object   Snoop TLB 
access  Locked
  #      
..    .. 
    ..  ..

  #
  25.00%  0 L2 hit[H] 
0xc000c910  [unknown] [H] 0xc00f170e5310 
[unknown] N/A   N/A No
  12.50%  0 L2 hit[k] 
0xc00f4d0c  [kernel.vmlinux]  [k] 0xc0f2dac8 
[kernel.vmlinux]  N/A   N/A No
  12.50%  0 L2 hit[H] 
0xc000ca58  [unknown] [H] 0xc00f170e5200 
[unknown] N/A   N/A No
  12.50%  0 L3 hit[k] 
0xc006b560  [kernel.vmlinux]  [k] 0xc0002f6fc

[PATCH v2 4/6] powerpc/perf: Support to export SIERs bit in Power8

2017-03-06 Thread Madhavan Srinivasan
Patch to export SIER bits to userspace via
perf_mem_data_src and perf_sample_data struct.

Cc: Benjamin Herrenschmidt <b...@kernel.crashing.org>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Daniel Axtens <d...@axtens.net>
Cc: Andrew Donnellan <andrew.donnel...@au1.ibm.com>
Signed-off-by: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>
Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
 arch/powerpc/perf/power8-pmu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index ce15b19a7962..932d7536f0eb 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -325,6 +325,8 @@ static struct power_pmu power8_pmu = {
.bhrb_filter_map= power8_bhrb_filter_map,
.get_constraint = isa207_get_constraint,
.get_alternatives   = power8_get_alternatives,
+   .get_mem_data_src   = isa207_get_mem_data_src,
+   .get_mem_weight = isa207_get_mem_weight,
.disable_pmc= isa207_disable_pmc,
.flags  = PPMU_HAS_SIER | PPMU_ARCH_207S,
.n_generic  = ARRAY_SIZE(power8_generic_events),
-- 
2.7.4



[PATCH v2 4/6] powerpc/perf: Support to export SIERs bit in Power8

2017-03-06 Thread Madhavan Srinivasan
Patch to export SIER bits to userspace via
perf_mem_data_src and perf_sample_data struct.

Cc: Benjamin Herrenschmidt 
Cc: Paul Mackerras 
Cc: Daniel Axtens 
Cc: Andrew Donnellan 
Signed-off-by: Sukadev Bhattiprolu 
Signed-off-by: Madhavan Srinivasan 
---
 arch/powerpc/perf/power8-pmu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index ce15b19a7962..932d7536f0eb 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -325,6 +325,8 @@ static struct power_pmu power8_pmu = {
.bhrb_filter_map= power8_bhrb_filter_map,
.get_constraint = isa207_get_constraint,
.get_alternatives   = power8_get_alternatives,
+   .get_mem_data_src   = isa207_get_mem_data_src,
+   .get_mem_weight = isa207_get_mem_weight,
.disable_pmc= isa207_disable_pmc,
.flags  = PPMU_HAS_SIER | PPMU_ARCH_207S,
.n_generic  = ARRAY_SIZE(power8_generic_events),
-- 
2.7.4



[PATCH v2 6/6] powerpc/perf: Add Power8 mem_access event to sysfs

2017-03-06 Thread Madhavan Srinivasan
Patch add "mem_access" event to sysfs. This as-is not a raw event
supported by Power8 pmu. Instead, it is formed based on
raw event encoding specificed in isa207-common.h.

Primary PMU event used here is PM_MRK_INST_CMPL.
This event tracks only the completed marked instructions.

Random sampling mode (MMCRA[SM]) with Random Instruction
Sampling (RIS) is enabled to mark type of instructions.

With Random sampling in RLS mode with PM_MRK_INST_CMPL event,
the LDST /DATA_SRC fields in SIER identifies the memory
hierarchy level (eg: L1, L2 etc) statisfied a data-cache
miss for a marked instruction.

Cc: Benjamin Herrenschmidt <b...@kernel.crashing.org>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>
Cc: Daniel Axtens <d...@axtens.net>
Cc: Andrew Donnellan <andrew.donnel...@au1.ibm.com>
Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
 arch/powerpc/perf/power8-events-list.h | 6 ++
 arch/powerpc/perf/power8-pmu.c | 2 ++
 2 files changed, 8 insertions(+)

diff --git a/arch/powerpc/perf/power8-events-list.h 
b/arch/powerpc/perf/power8-events-list.h
index 3a2e6e8ebb92..0f1d184627cc 100644
--- a/arch/powerpc/perf/power8-events-list.h
+++ b/arch/powerpc/perf/power8-events-list.h
@@ -89,3 +89,9 @@ EVENT(PM_MRK_FILT_MATCH,  0x2013c)
 EVENT(PM_MRK_FILT_MATCH_ALT,   0x3012e)
 /* Alternate event code for PM_LD_MISS_L1 */
 EVENT(PM_LD_MISS_L1_ALT,   0x400f0)
+/*
+ * Memory Access Event -- mem_access
+ * Primary PMU event used here is PM_MRK_INST_CMPL, along with
+ * Random Load/Store Facility Sampling (RIS) in Random sampling mode 
(MMCRA[SM]).
+ */
+EVENT(MEM_ACCESS,  0x10401e0)
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index 932d7536f0eb..5463516e369b 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -90,6 +90,7 @@ GENERIC_EVENT_ATTR(branch-instructions,   
PM_BRU_FIN);
 GENERIC_EVENT_ATTR(branch-misses,  PM_BR_MPRED_CMPL);
 GENERIC_EVENT_ATTR(cache-references,   PM_LD_REF_L1);
 GENERIC_EVENT_ATTR(cache-misses,   PM_LD_MISS_L1);
+GENERIC_EVENT_ATTR(mem_access, MEM_ACCESS);
 
 CACHE_EVENT_ATTR(L1-dcache-load-misses,PM_LD_MISS_L1);
 CACHE_EVENT_ATTR(L1-dcache-loads,  PM_LD_REF_L1);
@@ -120,6 +121,7 @@ static struct attribute *power8_events_attr[] = {
GENERIC_EVENT_PTR(PM_BR_MPRED_CMPL),
GENERIC_EVENT_PTR(PM_LD_REF_L1),
GENERIC_EVENT_PTR(PM_LD_MISS_L1),
+   GENERIC_EVENT_PTR(MEM_ACCESS),
 
CACHE_EVENT_PTR(PM_LD_MISS_L1),
CACHE_EVENT_PTR(PM_LD_REF_L1),
-- 
2.7.4



[PATCH v2 6/6] powerpc/perf: Add Power8 mem_access event to sysfs

2017-03-06 Thread Madhavan Srinivasan
Patch add "mem_access" event to sysfs. This as-is not a raw event
supported by Power8 pmu. Instead, it is formed based on
raw event encoding specificed in isa207-common.h.

Primary PMU event used here is PM_MRK_INST_CMPL.
This event tracks only the completed marked instructions.

Random sampling mode (MMCRA[SM]) with Random Instruction
Sampling (RIS) is enabled to mark type of instructions.

With Random sampling in RLS mode with PM_MRK_INST_CMPL event,
the LDST /DATA_SRC fields in SIER identifies the memory
hierarchy level (eg: L1, L2 etc) statisfied a data-cache
miss for a marked instruction.

Cc: Benjamin Herrenschmidt 
Cc: Paul Mackerras 
Cc: Sukadev Bhattiprolu 
Cc: Daniel Axtens 
Cc: Andrew Donnellan 
Signed-off-by: Madhavan Srinivasan 
---
 arch/powerpc/perf/power8-events-list.h | 6 ++
 arch/powerpc/perf/power8-pmu.c | 2 ++
 2 files changed, 8 insertions(+)

diff --git a/arch/powerpc/perf/power8-events-list.h 
b/arch/powerpc/perf/power8-events-list.h
index 3a2e6e8ebb92..0f1d184627cc 100644
--- a/arch/powerpc/perf/power8-events-list.h
+++ b/arch/powerpc/perf/power8-events-list.h
@@ -89,3 +89,9 @@ EVENT(PM_MRK_FILT_MATCH,  0x2013c)
 EVENT(PM_MRK_FILT_MATCH_ALT,   0x3012e)
 /* Alternate event code for PM_LD_MISS_L1 */
 EVENT(PM_LD_MISS_L1_ALT,   0x400f0)
+/*
+ * Memory Access Event -- mem_access
+ * Primary PMU event used here is PM_MRK_INST_CMPL, along with
+ * Random Load/Store Facility Sampling (RIS) in Random sampling mode 
(MMCRA[SM]).
+ */
+EVENT(MEM_ACCESS,  0x10401e0)
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index 932d7536f0eb..5463516e369b 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -90,6 +90,7 @@ GENERIC_EVENT_ATTR(branch-instructions,   
PM_BRU_FIN);
 GENERIC_EVENT_ATTR(branch-misses,  PM_BR_MPRED_CMPL);
 GENERIC_EVENT_ATTR(cache-references,   PM_LD_REF_L1);
 GENERIC_EVENT_ATTR(cache-misses,   PM_LD_MISS_L1);
+GENERIC_EVENT_ATTR(mem_access, MEM_ACCESS);
 
 CACHE_EVENT_ATTR(L1-dcache-load-misses,PM_LD_MISS_L1);
 CACHE_EVENT_ATTR(L1-dcache-loads,  PM_LD_REF_L1);
@@ -120,6 +121,7 @@ static struct attribute *power8_events_attr[] = {
GENERIC_EVENT_PTR(PM_BR_MPRED_CMPL),
GENERIC_EVENT_PTR(PM_LD_REF_L1),
GENERIC_EVENT_PTR(PM_LD_MISS_L1),
+   GENERIC_EVENT_PTR(MEM_ACCESS),
 
CACHE_EVENT_PTR(PM_LD_MISS_L1),
CACHE_EVENT_PTR(PM_LD_REF_L1),
-- 
2.7.4



[PATCH v2 2/6] powerpc/perf: Export memory hierarchy info to user space

2017-03-06 Thread Madhavan Srinivasan
The LDST field and DATA_SRC in SIER identifies the memory hierarchy level
(eg: L1, L2 etc), from which a data-cache miss for a marked instruction
was satisfied. Use the 'perf_mem_data_src' object to export this
hierarchy level to user space.

Cc: Benjamin Herrenschmidt <b...@kernel.crashing.org>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Sebastian Andrzej Siewior <bige...@linutronix.de>
Cc: Anna-Maria Gleixner <anna-ma...@linutronix.de>
Cc: Daniel Axtens <d...@axtens.net>
Signed-off-by: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>
Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/perf_event_server.h |  2 +
 arch/powerpc/perf/core-book3s.c  |  4 ++
 arch/powerpc/perf/isa207-common.c| 78 
 arch/powerpc/perf/isa207-common.h| 16 +-
 4 files changed, 99 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/include/asm/perf_event_server.h 
b/arch/powerpc/include/asm/perf_event_server.h
index ae0a23091a9b..446cdcd9b7f5 100644
--- a/arch/powerpc/include/asm/perf_event_server.h
+++ b/arch/powerpc/include/asm/perf_event_server.h
@@ -38,6 +38,8 @@ struct power_pmu {
unsigned long *valp);
int (*get_alternatives)(u64 event_id, unsigned int flags,
u64 alt[]);
+   void(*get_mem_data_src)(union perf_mem_data_src *dsrc,
+   u32 flags, struct pt_regs *regs);
u64 (*bhrb_filter_map)(u64 branch_sample_type);
void(*config_bhrb)(u64 pmu_bhrb_filter);
void(*disable_pmc)(unsigned int pmc, unsigned long mmcr[]);
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 595dd718ea87..d644c5ab4d2f 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -2047,6 +2047,10 @@ static void record_and_restart(struct perf_event *event, 
unsigned long val,
data.br_stack = >bhrb_stack;
}
 
+   if (event->attr.sample_type & PERF_SAMPLE_DATA_SRC &&
+   ppmu->get_mem_data_src)
+   ppmu->get_mem_data_src(_src, ppmu->flags, 
regs);
+
if (perf_event_overflow(event, , regs))
power_pmu_stop(event, 0);
}
diff --git a/arch/powerpc/perf/isa207-common.c 
b/arch/powerpc/perf/isa207-common.c
index e79fb5fb817d..08bb62454a2e 100644
--- a/arch/powerpc/perf/isa207-common.c
+++ b/arch/powerpc/perf/isa207-common.c
@@ -119,6 +119,84 @@ static bool is_thresh_cmp_valid(u64 event)
return true;
 }
 
+static inline u64 isa207_find_source(u64 idx, u32 sub_idx)
+{
+   u64 ret = 0;
+
+   switch(idx) {
+   case 0:
+   ret = P(LVL, NA);
+   break;
+   case 1:
+   ret = PLH(LVL, L1);
+   break;
+   case 2:
+   ret = PLH(LVL, L2);
+   break;
+   case 3:
+   ret = PLH(LVL, L3);
+   break;
+   case 4:
+   if (sub_idx <= 1)
+   ret = PLH(LVL, LOC_RAM);
+   else if (sub_idx > 1 && sub_idx <= 2)
+   ret = PLH(LVL, REM_RAM1);
+   else
+   ret = PLH(LVL, REM_RAM2);
+   ret |= P(SNOOP, HIT);
+   break;
+   case 5:
+   if ((sub_idx == 0) || (sub_idx == 2) || (sub_idx == 4))
+   ret = (PLH(LVL, REM_CCE1) | P(SNOOP, HIT));
+   else if ((sub_idx == 1) || (sub_idx == 3) || (sub_idx == 5))
+   ret = (PLH(LVL, REM_CCE1) | P(SNOOP, HITM));
+   break;
+   case 6:
+   if ((sub_idx == 0) || (sub_idx == 2))
+   ret = (PLH(LVL, REM_CCE2) | P(SNOOP, HIT));
+   else if ((sub_idx == 1) || (sub_idx == 3))
+   ret = (PLH(LVL, REM_CCE2) | P(SNOOP, HITM));
+   break;
+   case 7:
+   ret = PSM(LVL, L1);
+   break;
+   }
+
+   return ret;
+}
+
+static inline bool is_load_store_inst(u64 sier)
+{
+   u64 val;
+   val = (sier & ISA207_SIER_TYPE_MASK) >> ISA207_SIER_TYPE_SHIFT;
+
+   /* 1 = load, 2 = store */
+   return val == 1 || val == 2;
+}
+
+void isa207_get_mem_data_src(union perf_mem_data_src *dsrc, u32 flags,
+   struct pt_regs *regs)
+{
+   u64 idx;
+   u32 sub_idx;
+   u64 sier;
+
+   /* Skip if no SIER support */
+   if (!(flags & PPMU_HAS_SIER)) {
+   dsrc->val = 0;
+   return;
+   }
+
+   sier = mfspr(SPRN_SIER);
+   if (is_load_store_inst(sier)) {
+ 

[PATCH v2 2/6] powerpc/perf: Export memory hierarchy info to user space

2017-03-06 Thread Madhavan Srinivasan
The LDST field and DATA_SRC in SIER identifies the memory hierarchy level
(eg: L1, L2 etc), from which a data-cache miss for a marked instruction
was satisfied. Use the 'perf_mem_data_src' object to export this
hierarchy level to user space.

Cc: Benjamin Herrenschmidt 
Cc: Paul Mackerras 
Cc: Thomas Gleixner 
Cc: Sebastian Andrzej Siewior 
Cc: Anna-Maria Gleixner 
Cc: Daniel Axtens 
Signed-off-by: Sukadev Bhattiprolu 
Signed-off-by: Madhavan Srinivasan 
---
 arch/powerpc/include/asm/perf_event_server.h |  2 +
 arch/powerpc/perf/core-book3s.c  |  4 ++
 arch/powerpc/perf/isa207-common.c| 78 
 arch/powerpc/perf/isa207-common.h| 16 +-
 4 files changed, 99 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/include/asm/perf_event_server.h 
b/arch/powerpc/include/asm/perf_event_server.h
index ae0a23091a9b..446cdcd9b7f5 100644
--- a/arch/powerpc/include/asm/perf_event_server.h
+++ b/arch/powerpc/include/asm/perf_event_server.h
@@ -38,6 +38,8 @@ struct power_pmu {
unsigned long *valp);
int (*get_alternatives)(u64 event_id, unsigned int flags,
u64 alt[]);
+   void(*get_mem_data_src)(union perf_mem_data_src *dsrc,
+   u32 flags, struct pt_regs *regs);
u64 (*bhrb_filter_map)(u64 branch_sample_type);
void(*config_bhrb)(u64 pmu_bhrb_filter);
void(*disable_pmc)(unsigned int pmc, unsigned long mmcr[]);
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 595dd718ea87..d644c5ab4d2f 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -2047,6 +2047,10 @@ static void record_and_restart(struct perf_event *event, 
unsigned long val,
data.br_stack = >bhrb_stack;
}
 
+   if (event->attr.sample_type & PERF_SAMPLE_DATA_SRC &&
+   ppmu->get_mem_data_src)
+   ppmu->get_mem_data_src(_src, ppmu->flags, 
regs);
+
if (perf_event_overflow(event, , regs))
power_pmu_stop(event, 0);
}
diff --git a/arch/powerpc/perf/isa207-common.c 
b/arch/powerpc/perf/isa207-common.c
index e79fb5fb817d..08bb62454a2e 100644
--- a/arch/powerpc/perf/isa207-common.c
+++ b/arch/powerpc/perf/isa207-common.c
@@ -119,6 +119,84 @@ static bool is_thresh_cmp_valid(u64 event)
return true;
 }
 
+static inline u64 isa207_find_source(u64 idx, u32 sub_idx)
+{
+   u64 ret = 0;
+
+   switch(idx) {
+   case 0:
+   ret = P(LVL, NA);
+   break;
+   case 1:
+   ret = PLH(LVL, L1);
+   break;
+   case 2:
+   ret = PLH(LVL, L2);
+   break;
+   case 3:
+   ret = PLH(LVL, L3);
+   break;
+   case 4:
+   if (sub_idx <= 1)
+   ret = PLH(LVL, LOC_RAM);
+   else if (sub_idx > 1 && sub_idx <= 2)
+   ret = PLH(LVL, REM_RAM1);
+   else
+   ret = PLH(LVL, REM_RAM2);
+   ret |= P(SNOOP, HIT);
+   break;
+   case 5:
+   if ((sub_idx == 0) || (sub_idx == 2) || (sub_idx == 4))
+   ret = (PLH(LVL, REM_CCE1) | P(SNOOP, HIT));
+   else if ((sub_idx == 1) || (sub_idx == 3) || (sub_idx == 5))
+   ret = (PLH(LVL, REM_CCE1) | P(SNOOP, HITM));
+   break;
+   case 6:
+   if ((sub_idx == 0) || (sub_idx == 2))
+   ret = (PLH(LVL, REM_CCE2) | P(SNOOP, HIT));
+   else if ((sub_idx == 1) || (sub_idx == 3))
+   ret = (PLH(LVL, REM_CCE2) | P(SNOOP, HITM));
+   break;
+   case 7:
+   ret = PSM(LVL, L1);
+   break;
+   }
+
+   return ret;
+}
+
+static inline bool is_load_store_inst(u64 sier)
+{
+   u64 val;
+   val = (sier & ISA207_SIER_TYPE_MASK) >> ISA207_SIER_TYPE_SHIFT;
+
+   /* 1 = load, 2 = store */
+   return val == 1 || val == 2;
+}
+
+void isa207_get_mem_data_src(union perf_mem_data_src *dsrc, u32 flags,
+   struct pt_regs *regs)
+{
+   u64 idx;
+   u32 sub_idx;
+   u64 sier;
+
+   /* Skip if no SIER support */
+   if (!(flags & PPMU_HAS_SIER)) {
+   dsrc->val = 0;
+   return;
+   }
+
+   sier = mfspr(SPRN_SIER);
+   if (is_load_store_inst(sier)) {
+   idx = (sier & ISA207_SIER_LDST_MASK) >> ISA207_SIER_LDST_SHIFT;
+   sub_idx = (sier & ISA207_SIER_DATA_SRC_MASK) >> 
ISA207_SIER_DATA_SRC_SHIFT;
+
+   dsrc->val = isa207_find_source(idx, s

[PATCH v2 3/6] powerpc/perf: Support to export MMCRA[TEC*] field to userspace

2017-03-06 Thread Madhavan Srinivasan
Threshold feature when used with MMCRA [Threshold Event Counter Event],
MMCRA[Threshold Start event] and MMCRA[Threshold End event] will update
MMCRA[Threashold Event Counter Exponent] and MMCRA[Threshold Event
Counter Multiplier] with the corresponding threshold event count values.
Patch to export MMCRA[TECX/TECM] to userspace in 'weight' field of
struct perf_sample_data.

Cc: Benjamin Herrenschmidt <b...@kernel.crashing.org>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Sebastian Andrzej Siewior <bige...@linutronix.de>
Cc: Anna-Maria Gleixner <anna-ma...@linutronix.de>
Cc: Daniel Axtens <d...@axtens.net>
Cc: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>
Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/perf_event_server.h |  1 +
 arch/powerpc/perf/core-book3s.c  |  4 
 arch/powerpc/perf/isa207-common.c|  8 
 arch/powerpc/perf/isa207-common.h| 10 ++
 4 files changed, 23 insertions(+)

diff --git a/arch/powerpc/include/asm/perf_event_server.h 
b/arch/powerpc/include/asm/perf_event_server.h
index 446cdcd9b7f5..723bf48e7494 100644
--- a/arch/powerpc/include/asm/perf_event_server.h
+++ b/arch/powerpc/include/asm/perf_event_server.h
@@ -40,6 +40,7 @@ struct power_pmu {
u64 alt[]);
void(*get_mem_data_src)(union perf_mem_data_src *dsrc,
u32 flags, struct pt_regs *regs);
+   void(*get_mem_weight)(u64 *weight);
u64 (*bhrb_filter_map)(u64 branch_sample_type);
void(*config_bhrb)(u64 pmu_bhrb_filter);
void(*disable_pmc)(unsigned int pmc, unsigned long mmcr[]);
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index d644c5ab4d2f..a6b265e31663 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -2051,6 +2051,10 @@ static void record_and_restart(struct perf_event *event, 
unsigned long val,
ppmu->get_mem_data_src)
ppmu->get_mem_data_src(_src, ppmu->flags, 
regs);
 
+   if (event->attr.sample_type & PERF_SAMPLE_WEIGHT &&
+   ppmu->get_mem_weight)
+   ppmu->get_mem_weight();
+
if (perf_event_overflow(event, , regs))
power_pmu_stop(event, 0);
}
diff --git a/arch/powerpc/perf/isa207-common.c 
b/arch/powerpc/perf/isa207-common.c
index 08bb62454a2e..42e999da934e 100644
--- a/arch/powerpc/perf/isa207-common.c
+++ b/arch/powerpc/perf/isa207-common.c
@@ -196,6 +196,14 @@ void isa207_get_mem_data_src(union perf_mem_data_src 
*dsrc, u32 flags,
}
 }
 
+void isa207_get_mem_weight(u64 *weight)
+{
+   u64 mmcra = mfspr(SPRN_MMCRA);
+   u64 exp = MMCRA_THR_CTR_EXP(mmcra);
+   u64 mantissa = MMCRA_THR_CTR_MANT(mmcra);
+
+   *weight = mantissa << (2 * exp);
+}
 
 int isa207_get_constraint(u64 event, unsigned long *maskp, unsigned long *valp)
 {
diff --git a/arch/powerpc/perf/isa207-common.h 
b/arch/powerpc/perf/isa207-common.h
index 982542cce991..b4d02ae3a6e0 100644
--- a/arch/powerpc/perf/isa207-common.h
+++ b/arch/powerpc/perf/isa207-common.h
@@ -247,6 +247,15 @@
 #define MMCRA_SDAR_MODE_SHIFT  42
 #define MMCRA_SDAR_MODE_TLB(1ull << MMCRA_SDAR_MODE_SHIFT)
 #define MMCRA_IFM_SHIFT30
+#define MMCRA_THR_CTR_MANT_SHIFT   19
+#define MMCRA_THR_CTR_MANT_MASK0x7Ful
+#define MMCRA_THR_CTR_MANT(v)  (((v) >> MMCRA_THR_CTR_MANT_SHIFT) &\
+   MMCRA_THR_CTR_MANT_MASK)
+
+#define MMCRA_THR_CTR_EXP_SHIFT27
+#define MMCRA_THR_CTR_EXP_MASK 0x7ul
+#define MMCRA_THR_CTR_EXP(v)   (((v) >> MMCRA_THR_CTR_EXP_SHIFT) &\
+   MMCRA_THR_CTR_EXP_MASK)
 
 /* MMCR1 Threshold Compare bit constant for power9 */
 #define p9_MMCRA_THR_CMP_SHIFT 45
@@ -281,5 +290,6 @@ int isa207_get_alternatives(u64 event, u64 alt[],
const unsigned int ev_alt[][MAX_ALT], int size);
 void isa207_get_mem_data_src(union perf_mem_data_src *dsrc, u32 flags,
struct pt_regs *regs);
+void isa207_get_mem_weight(u64 *weight);
 
 #endif
-- 
2.7.4



[PATCH v2 3/6] powerpc/perf: Support to export MMCRA[TEC*] field to userspace

2017-03-06 Thread Madhavan Srinivasan
Threshold feature when used with MMCRA [Threshold Event Counter Event],
MMCRA[Threshold Start event] and MMCRA[Threshold End event] will update
MMCRA[Threashold Event Counter Exponent] and MMCRA[Threshold Event
Counter Multiplier] with the corresponding threshold event count values.
Patch to export MMCRA[TECX/TECM] to userspace in 'weight' field of
struct perf_sample_data.

Cc: Benjamin Herrenschmidt 
Cc: Paul Mackerras 
Cc: Thomas Gleixner 
Cc: Sebastian Andrzej Siewior 
Cc: Anna-Maria Gleixner 
Cc: Daniel Axtens 
Cc: Sukadev Bhattiprolu 
Signed-off-by: Madhavan Srinivasan 
---
 arch/powerpc/include/asm/perf_event_server.h |  1 +
 arch/powerpc/perf/core-book3s.c  |  4 
 arch/powerpc/perf/isa207-common.c|  8 
 arch/powerpc/perf/isa207-common.h| 10 ++
 4 files changed, 23 insertions(+)

diff --git a/arch/powerpc/include/asm/perf_event_server.h 
b/arch/powerpc/include/asm/perf_event_server.h
index 446cdcd9b7f5..723bf48e7494 100644
--- a/arch/powerpc/include/asm/perf_event_server.h
+++ b/arch/powerpc/include/asm/perf_event_server.h
@@ -40,6 +40,7 @@ struct power_pmu {
u64 alt[]);
void(*get_mem_data_src)(union perf_mem_data_src *dsrc,
u32 flags, struct pt_regs *regs);
+   void(*get_mem_weight)(u64 *weight);
u64 (*bhrb_filter_map)(u64 branch_sample_type);
void(*config_bhrb)(u64 pmu_bhrb_filter);
void(*disable_pmc)(unsigned int pmc, unsigned long mmcr[]);
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index d644c5ab4d2f..a6b265e31663 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -2051,6 +2051,10 @@ static void record_and_restart(struct perf_event *event, 
unsigned long val,
ppmu->get_mem_data_src)
ppmu->get_mem_data_src(_src, ppmu->flags, 
regs);
 
+   if (event->attr.sample_type & PERF_SAMPLE_WEIGHT &&
+   ppmu->get_mem_weight)
+   ppmu->get_mem_weight();
+
if (perf_event_overflow(event, , regs))
power_pmu_stop(event, 0);
}
diff --git a/arch/powerpc/perf/isa207-common.c 
b/arch/powerpc/perf/isa207-common.c
index 08bb62454a2e..42e999da934e 100644
--- a/arch/powerpc/perf/isa207-common.c
+++ b/arch/powerpc/perf/isa207-common.c
@@ -196,6 +196,14 @@ void isa207_get_mem_data_src(union perf_mem_data_src 
*dsrc, u32 flags,
}
 }
 
+void isa207_get_mem_weight(u64 *weight)
+{
+   u64 mmcra = mfspr(SPRN_MMCRA);
+   u64 exp = MMCRA_THR_CTR_EXP(mmcra);
+   u64 mantissa = MMCRA_THR_CTR_MANT(mmcra);
+
+   *weight = mantissa << (2 * exp);
+}
 
 int isa207_get_constraint(u64 event, unsigned long *maskp, unsigned long *valp)
 {
diff --git a/arch/powerpc/perf/isa207-common.h 
b/arch/powerpc/perf/isa207-common.h
index 982542cce991..b4d02ae3a6e0 100644
--- a/arch/powerpc/perf/isa207-common.h
+++ b/arch/powerpc/perf/isa207-common.h
@@ -247,6 +247,15 @@
 #define MMCRA_SDAR_MODE_SHIFT  42
 #define MMCRA_SDAR_MODE_TLB(1ull << MMCRA_SDAR_MODE_SHIFT)
 #define MMCRA_IFM_SHIFT30
+#define MMCRA_THR_CTR_MANT_SHIFT   19
+#define MMCRA_THR_CTR_MANT_MASK0x7Ful
+#define MMCRA_THR_CTR_MANT(v)  (((v) >> MMCRA_THR_CTR_MANT_SHIFT) &\
+   MMCRA_THR_CTR_MANT_MASK)
+
+#define MMCRA_THR_CTR_EXP_SHIFT27
+#define MMCRA_THR_CTR_EXP_MASK 0x7ul
+#define MMCRA_THR_CTR_EXP(v)   (((v) >> MMCRA_THR_CTR_EXP_SHIFT) &\
+   MMCRA_THR_CTR_EXP_MASK)
 
 /* MMCR1 Threshold Compare bit constant for power9 */
 #define p9_MMCRA_THR_CMP_SHIFT 45
@@ -281,5 +290,6 @@ int isa207_get_alternatives(u64 event, u64 alt[],
const unsigned int ev_alt[][MAX_ALT], int size);
 void isa207_get_mem_data_src(union perf_mem_data_src *dsrc, u32 flags,
struct pt_regs *regs);
+void isa207_get_mem_weight(u64 *weight);
 
 #endif
-- 
2.7.4



[PATCH v2 1/6] powerpc/perf: Define big-endian version of perf_mem_data_src

2017-03-06 Thread Madhavan Srinivasan
From: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>

perf_mem_data_src is an union that is initialized via the ->val field
and accessed via the bitmap fields. For this to work on big endian
platforms, we also need a big-endian represenation of perf_mem_data_src.

Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Ingo Molnar <mi...@redhat.com>
Cc: Arnaldo Carvalho de Melo <a...@kernel.org>
Cc: Alexander Shishkin <alexander.shish...@linux.intel.com>
Cc: Wang Nan <wangn...@huawei.com>
Cc: Alexei Starovoitov <a...@kernel.org>
Cc: Stephane Eranian <eran...@google.com>
Signed-off-by: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>
Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
 include/uapi/linux/perf_event.h   | 16 
 tools/include/uapi/linux/perf_event.h | 16 
 2 files changed, 32 insertions(+)

diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index c66a485a24ac..c4af1159a200 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -891,6 +891,7 @@ enum perf_callchain_context {
 #define PERF_FLAG_PID_CGROUP   (1UL << 2) /* pid=cgroup id, per-cpu 
mode only */
 #define PERF_FLAG_FD_CLOEXEC   (1UL << 3) /* O_CLOEXEC */
 
+#if defined(__LITTLE_ENDIAN_BITFIELD)
 union perf_mem_data_src {
__u64 val;
struct {
@@ -902,6 +903,21 @@ union perf_mem_data_src {
mem_rsvd:31;
};
 };
+#elif defined(__BIG_ENDIAN_BITFIELD)
+union perf_mem_data_src {
+   __u64 val;
+   struct {
+   __u64   mem_rsvd:31,
+   mem_dtlb:7, /* tlb access */
+   mem_lock:2, /* lock instr */
+   mem_snoop:5,/* snoop mode */
+   mem_lvl:14, /* memory hierarchy level */
+   mem_op:5;   /* type of opcode */
+   };
+};
+#else
+#error "Unknown endianness"
+#endif
 
 /* type of opcode (load/store/prefetch,code) */
 #define PERF_MEM_OP_NA 0x01 /* not available */
diff --git a/tools/include/uapi/linux/perf_event.h 
b/tools/include/uapi/linux/perf_event.h
index c66a485a24ac..c4af1159a200 100644
--- a/tools/include/uapi/linux/perf_event.h
+++ b/tools/include/uapi/linux/perf_event.h
@@ -891,6 +891,7 @@ enum perf_callchain_context {
 #define PERF_FLAG_PID_CGROUP   (1UL << 2) /* pid=cgroup id, per-cpu 
mode only */
 #define PERF_FLAG_FD_CLOEXEC   (1UL << 3) /* O_CLOEXEC */
 
+#if defined(__LITTLE_ENDIAN_BITFIELD)
 union perf_mem_data_src {
__u64 val;
struct {
@@ -902,6 +903,21 @@ union perf_mem_data_src {
mem_rsvd:31;
};
 };
+#elif defined(__BIG_ENDIAN_BITFIELD)
+union perf_mem_data_src {
+   __u64 val;
+   struct {
+   __u64   mem_rsvd:31,
+   mem_dtlb:7, /* tlb access */
+   mem_lock:2, /* lock instr */
+   mem_snoop:5,/* snoop mode */
+   mem_lvl:14, /* memory hierarchy level */
+   mem_op:5;   /* type of opcode */
+   };
+};
+#else
+#error "Unknown endianness"
+#endif
 
 /* type of opcode (load/store/prefetch,code) */
 #define PERF_MEM_OP_NA 0x01 /* not available */
-- 
2.7.4



[PATCH v2 0/6] powerpc/perf: Export memory hierarchy level

2017-03-06 Thread Madhavan Srinivasan
Power8/Power9 Perforence Monitoring Unit (PMU) supports
different sampling modes (SM) such as Random Instruction
Sampling (RIS), Random Load/Store Facility Sampling (RLS)
and Random Branch Sampling (RBS). Sample mode RLS updates
Sampled Instruction Event Register [SIER] bits with memory
hierarchy information for a cache reload. Patchset exports
the hierarchy information to the user via the perf_mem_data_src
object from SIER.

Patchset is a rebase of the work posted previously with minor
updates to it.

https://lkml.org/lkml/2015/6/11/92

Changelog v1:
- Fixed author-ship for the first patch and added suka's "Signed-off-by:".

Madhavan Srinivasan (5):
  powerpc/perf: Export memory hierarchy info to user space
  powerpc/perf: Support to export MMCRA[TEC*] field to userspace
  powerpc/perf: Support to export SIERs bit in Power8
  powerpc/perf: Support to export SIERs bit in Power9
  powerpc/perf: Add Power8 mem_access event to sysfs

Sukadev Bhattiprolu (1):
  powerpc/perf: Define big-endian version of perf_mem_data_src

 arch/powerpc/include/asm/perf_event_server.h |  3 +
 arch/powerpc/perf/core-book3s.c  |  8 +++
 arch/powerpc/perf/isa207-common.c| 86 
 arch/powerpc/perf/isa207-common.h| 26 -
 arch/powerpc/perf/power8-events-list.h   |  6 ++
 arch/powerpc/perf/power8-pmu.c   |  4 ++
 arch/powerpc/perf/power9-pmu.c   |  2 +
 include/uapi/linux/perf_event.h  | 16 ++
 tools/include/uapi/linux/perf_event.h| 16 ++
 9 files changed, 166 insertions(+), 1 deletion(-)

-- 
2.7.4



[PATCH v2 5/6] powerpc/perf: Support to export SIERs bit in Power9

2017-03-06 Thread Madhavan Srinivasan
Patch to export SIER bits to userspace via
perf_mem_data_src and perf_sample_data struct.

Cc: Benjamin Herrenschmidt <b...@kernel.crashing.org>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>
Cc: Daniel Axtens <d...@axtens.net>
Cc: Andrew Donnellan <andrew.donnel...@au1.ibm.com>
Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
 arch/powerpc/perf/power9-pmu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/powerpc/perf/power9-pmu.c b/arch/powerpc/perf/power9-pmu.c
index 7f6582708e06..018f8e90ac35 100644
--- a/arch/powerpc/perf/power9-pmu.c
+++ b/arch/powerpc/perf/power9-pmu.c
@@ -427,6 +427,8 @@ static struct power_pmu power9_pmu = {
.bhrb_filter_map= power9_bhrb_filter_map,
.get_constraint = isa207_get_constraint,
.get_alternatives   = power9_get_alternatives,
+   .get_mem_data_src   = isa207_get_mem_data_src,
+   .get_mem_weight = isa207_get_mem_weight,
.disable_pmc= isa207_disable_pmc,
.flags  = PPMU_HAS_SIER | PPMU_ARCH_207S,
.n_generic  = ARRAY_SIZE(power9_generic_events),
-- 
2.7.4



[PATCH v2 5/6] powerpc/perf: Support to export SIERs bit in Power9

2017-03-06 Thread Madhavan Srinivasan
Patch to export SIER bits to userspace via
perf_mem_data_src and perf_sample_data struct.

Cc: Benjamin Herrenschmidt 
Cc: Paul Mackerras 
Cc: Sukadev Bhattiprolu 
Cc: Daniel Axtens 
Cc: Andrew Donnellan 
Signed-off-by: Madhavan Srinivasan 
---
 arch/powerpc/perf/power9-pmu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/powerpc/perf/power9-pmu.c b/arch/powerpc/perf/power9-pmu.c
index 7f6582708e06..018f8e90ac35 100644
--- a/arch/powerpc/perf/power9-pmu.c
+++ b/arch/powerpc/perf/power9-pmu.c
@@ -427,6 +427,8 @@ static struct power_pmu power9_pmu = {
.bhrb_filter_map= power9_bhrb_filter_map,
.get_constraint = isa207_get_constraint,
.get_alternatives   = power9_get_alternatives,
+   .get_mem_data_src   = isa207_get_mem_data_src,
+   .get_mem_weight = isa207_get_mem_weight,
.disable_pmc= isa207_disable_pmc,
.flags  = PPMU_HAS_SIER | PPMU_ARCH_207S,
.n_generic  = ARRAY_SIZE(power9_generic_events),
-- 
2.7.4



[PATCH v2 1/6] powerpc/perf: Define big-endian version of perf_mem_data_src

2017-03-06 Thread Madhavan Srinivasan
From: Sukadev Bhattiprolu 

perf_mem_data_src is an union that is initialized via the ->val field
and accessed via the bitmap fields. For this to work on big endian
platforms, we also need a big-endian represenation of perf_mem_data_src.

Cc: Peter Zijlstra 
Cc: Ingo Molnar 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexander Shishkin 
Cc: Wang Nan 
Cc: Alexei Starovoitov 
Cc: Stephane Eranian 
Signed-off-by: Sukadev Bhattiprolu 
Signed-off-by: Madhavan Srinivasan 
---
 include/uapi/linux/perf_event.h   | 16 
 tools/include/uapi/linux/perf_event.h | 16 
 2 files changed, 32 insertions(+)

diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index c66a485a24ac..c4af1159a200 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -891,6 +891,7 @@ enum perf_callchain_context {
 #define PERF_FLAG_PID_CGROUP   (1UL << 2) /* pid=cgroup id, per-cpu 
mode only */
 #define PERF_FLAG_FD_CLOEXEC   (1UL << 3) /* O_CLOEXEC */
 
+#if defined(__LITTLE_ENDIAN_BITFIELD)
 union perf_mem_data_src {
__u64 val;
struct {
@@ -902,6 +903,21 @@ union perf_mem_data_src {
mem_rsvd:31;
};
 };
+#elif defined(__BIG_ENDIAN_BITFIELD)
+union perf_mem_data_src {
+   __u64 val;
+   struct {
+   __u64   mem_rsvd:31,
+   mem_dtlb:7, /* tlb access */
+   mem_lock:2, /* lock instr */
+   mem_snoop:5,/* snoop mode */
+   mem_lvl:14, /* memory hierarchy level */
+   mem_op:5;   /* type of opcode */
+   };
+};
+#else
+#error "Unknown endianness"
+#endif
 
 /* type of opcode (load/store/prefetch,code) */
 #define PERF_MEM_OP_NA 0x01 /* not available */
diff --git a/tools/include/uapi/linux/perf_event.h 
b/tools/include/uapi/linux/perf_event.h
index c66a485a24ac..c4af1159a200 100644
--- a/tools/include/uapi/linux/perf_event.h
+++ b/tools/include/uapi/linux/perf_event.h
@@ -891,6 +891,7 @@ enum perf_callchain_context {
 #define PERF_FLAG_PID_CGROUP   (1UL << 2) /* pid=cgroup id, per-cpu 
mode only */
 #define PERF_FLAG_FD_CLOEXEC   (1UL << 3) /* O_CLOEXEC */
 
+#if defined(__LITTLE_ENDIAN_BITFIELD)
 union perf_mem_data_src {
__u64 val;
struct {
@@ -902,6 +903,21 @@ union perf_mem_data_src {
mem_rsvd:31;
};
 };
+#elif defined(__BIG_ENDIAN_BITFIELD)
+union perf_mem_data_src {
+   __u64 val;
+   struct {
+   __u64   mem_rsvd:31,
+   mem_dtlb:7, /* tlb access */
+   mem_lock:2, /* lock instr */
+   mem_snoop:5,/* snoop mode */
+   mem_lvl:14, /* memory hierarchy level */
+   mem_op:5;   /* type of opcode */
+   };
+};
+#else
+#error "Unknown endianness"
+#endif
 
 /* type of opcode (load/store/prefetch,code) */
 #define PERF_MEM_OP_NA 0x01 /* not available */
-- 
2.7.4



[PATCH v2 0/6] powerpc/perf: Export memory hierarchy level

2017-03-06 Thread Madhavan Srinivasan
Power8/Power9 Perforence Monitoring Unit (PMU) supports
different sampling modes (SM) such as Random Instruction
Sampling (RIS), Random Load/Store Facility Sampling (RLS)
and Random Branch Sampling (RBS). Sample mode RLS updates
Sampled Instruction Event Register [SIER] bits with memory
hierarchy information for a cache reload. Patchset exports
the hierarchy information to the user via the perf_mem_data_src
object from SIER.

Patchset is a rebase of the work posted previously with minor
updates to it.

https://lkml.org/lkml/2015/6/11/92

Changelog v1:
- Fixed author-ship for the first patch and added suka's "Signed-off-by:".

Madhavan Srinivasan (5):
  powerpc/perf: Export memory hierarchy info to user space
  powerpc/perf: Support to export MMCRA[TEC*] field to userspace
  powerpc/perf: Support to export SIERs bit in Power8
  powerpc/perf: Support to export SIERs bit in Power9
  powerpc/perf: Add Power8 mem_access event to sysfs

Sukadev Bhattiprolu (1):
  powerpc/perf: Define big-endian version of perf_mem_data_src

 arch/powerpc/include/asm/perf_event_server.h |  3 +
 arch/powerpc/perf/core-book3s.c  |  8 +++
 arch/powerpc/perf/isa207-common.c| 86 
 arch/powerpc/perf/isa207-common.h| 26 -
 arch/powerpc/perf/power8-events-list.h   |  6 ++
 arch/powerpc/perf/power8-pmu.c   |  4 ++
 arch/powerpc/perf/power9-pmu.c   |  2 +
 include/uapi/linux/perf_event.h  | 16 ++
 tools/include/uapi/linux/perf_event.h| 16 ++
 9 files changed, 166 insertions(+), 1 deletion(-)

-- 
2.7.4



[PATCH 5/6] powerpc/perf: Support to export SIERs bit in Power9

2017-03-05 Thread Madhavan Srinivasan
Patch to export SIER bits to userspace via
perf_mem_data_src and perf_sample_data struct.

Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
Cc: Benjamin Herrenschmidt <b...@kernel.crashing.org>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>
Cc: Daniel Axtens <d...@axtens.net>
Cc: Andrew Donnellan <andrew.donnel...@au1.ibm.com>
---
 arch/powerpc/perf/power9-pmu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/powerpc/perf/power9-pmu.c b/arch/powerpc/perf/power9-pmu.c
index 7f6582708e06..018f8e90ac35 100644
--- a/arch/powerpc/perf/power9-pmu.c
+++ b/arch/powerpc/perf/power9-pmu.c
@@ -427,6 +427,8 @@ static struct power_pmu power9_pmu = {
.bhrb_filter_map= power9_bhrb_filter_map,
.get_constraint = isa207_get_constraint,
.get_alternatives   = power9_get_alternatives,
+   .get_mem_data_src   = isa207_get_mem_data_src,
+   .get_mem_weight = isa207_get_mem_weight,
.disable_pmc= isa207_disable_pmc,
.flags  = PPMU_HAS_SIER | PPMU_ARCH_207S,
.n_generic  = ARRAY_SIZE(power9_generic_events),
-- 
2.7.4



[PATCH 5/6] powerpc/perf: Support to export SIERs bit in Power9

2017-03-05 Thread Madhavan Srinivasan
Patch to export SIER bits to userspace via
perf_mem_data_src and perf_sample_data struct.

Signed-off-by: Madhavan Srinivasan 
Cc: Benjamin Herrenschmidt 
Cc: Paul Mackerras 
Cc: Sukadev Bhattiprolu 
Cc: Daniel Axtens 
Cc: Andrew Donnellan 
---
 arch/powerpc/perf/power9-pmu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/powerpc/perf/power9-pmu.c b/arch/powerpc/perf/power9-pmu.c
index 7f6582708e06..018f8e90ac35 100644
--- a/arch/powerpc/perf/power9-pmu.c
+++ b/arch/powerpc/perf/power9-pmu.c
@@ -427,6 +427,8 @@ static struct power_pmu power9_pmu = {
.bhrb_filter_map= power9_bhrb_filter_map,
.get_constraint = isa207_get_constraint,
.get_alternatives   = power9_get_alternatives,
+   .get_mem_data_src   = isa207_get_mem_data_src,
+   .get_mem_weight = isa207_get_mem_weight,
.disable_pmc= isa207_disable_pmc,
.flags  = PPMU_HAS_SIER | PPMU_ARCH_207S,
.n_generic  = ARRAY_SIZE(power9_generic_events),
-- 
2.7.4



[PATCH 2/6] powerpc/perf: Export memory hierarchy info to user space

2017-03-05 Thread Madhavan Srinivasan
The LDST field and DATA_SRC in SIER identifies the memory hierarchy level
(eg: L1, L2 etc), from which a data-cache miss for a marked instruction
was satisfied. Use the 'perf_mem_data_src' object to export this
hierarchy level to user space.

Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
Cc: Benjamin Herrenschmidt <b...@kernel.crashing.org>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>
Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Sebastian Andrzej Siewior <bige...@linutronix.de>
Cc: Anna-Maria Gleixner <anna-ma...@linutronix.de>
Cc: Daniel Axtens <d...@axtens.net>
---
 arch/powerpc/include/asm/perf_event_server.h |  2 +
 arch/powerpc/perf/core-book3s.c  |  4 ++
 arch/powerpc/perf/isa207-common.c| 78 
 arch/powerpc/perf/isa207-common.h| 16 +-
 4 files changed, 99 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/include/asm/perf_event_server.h 
b/arch/powerpc/include/asm/perf_event_server.h
index ae0a23091a9b..446cdcd9b7f5 100644
--- a/arch/powerpc/include/asm/perf_event_server.h
+++ b/arch/powerpc/include/asm/perf_event_server.h
@@ -38,6 +38,8 @@ struct power_pmu {
unsigned long *valp);
int (*get_alternatives)(u64 event_id, unsigned int flags,
u64 alt[]);
+   void(*get_mem_data_src)(union perf_mem_data_src *dsrc,
+   u32 flags, struct pt_regs *regs);
u64 (*bhrb_filter_map)(u64 branch_sample_type);
void(*config_bhrb)(u64 pmu_bhrb_filter);
void(*disable_pmc)(unsigned int pmc, unsigned long mmcr[]);
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 595dd718ea87..d644c5ab4d2f 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -2047,6 +2047,10 @@ static void record_and_restart(struct perf_event *event, 
unsigned long val,
data.br_stack = >bhrb_stack;
}
 
+   if (event->attr.sample_type & PERF_SAMPLE_DATA_SRC &&
+   ppmu->get_mem_data_src)
+   ppmu->get_mem_data_src(_src, ppmu->flags, 
regs);
+
if (perf_event_overflow(event, , regs))
power_pmu_stop(event, 0);
}
diff --git a/arch/powerpc/perf/isa207-common.c 
b/arch/powerpc/perf/isa207-common.c
index e79fb5fb817d..08bb62454a2e 100644
--- a/arch/powerpc/perf/isa207-common.c
+++ b/arch/powerpc/perf/isa207-common.c
@@ -119,6 +119,84 @@ static bool is_thresh_cmp_valid(u64 event)
return true;
 }
 
+static inline u64 isa207_find_source(u64 idx, u32 sub_idx)
+{
+   u64 ret = 0;
+
+   switch(idx) {
+   case 0:
+   ret = P(LVL, NA);
+   break;
+   case 1:
+   ret = PLH(LVL, L1);
+   break;
+   case 2:
+   ret = PLH(LVL, L2);
+   break;
+   case 3:
+   ret = PLH(LVL, L3);
+   break;
+   case 4:
+   if (sub_idx <= 1)
+   ret = PLH(LVL, LOC_RAM);
+   else if (sub_idx > 1 && sub_idx <= 2)
+   ret = PLH(LVL, REM_RAM1);
+   else
+   ret = PLH(LVL, REM_RAM2);
+   ret |= P(SNOOP, HIT);
+   break;
+   case 5:
+   if ((sub_idx == 0) || (sub_idx == 2) || (sub_idx == 4))
+   ret = (PLH(LVL, REM_CCE1) | P(SNOOP, HIT));
+   else if ((sub_idx == 1) || (sub_idx == 3) || (sub_idx == 5))
+   ret = (PLH(LVL, REM_CCE1) | P(SNOOP, HITM));
+   break;
+   case 6:
+   if ((sub_idx == 0) || (sub_idx == 2))
+   ret = (PLH(LVL, REM_CCE2) | P(SNOOP, HIT));
+   else if ((sub_idx == 1) || (sub_idx == 3))
+   ret = (PLH(LVL, REM_CCE2) | P(SNOOP, HITM));
+   break;
+   case 7:
+   ret = PSM(LVL, L1);
+   break;
+   }
+
+   return ret;
+}
+
+static inline bool is_load_store_inst(u64 sier)
+{
+   u64 val;
+   val = (sier & ISA207_SIER_TYPE_MASK) >> ISA207_SIER_TYPE_SHIFT;
+
+   /* 1 = load, 2 = store */
+   return val == 1 || val == 2;
+}
+
+void isa207_get_mem_data_src(union perf_mem_data_src *dsrc, u32 flags,
+   struct pt_regs *regs)
+{
+   u64 idx;
+   u32 sub_idx;
+   u64 sier;
+
+   /* Skip if no SIER support */
+   if (!(flags & PPMU_HAS_SIER)) {
+   dsrc->val = 0;
+   return;
+   }
+
+   sier = mfspr(SPRN_SIER);
+   if (is_load_store_inst(sier)) {
+   idx = (sier &a

[PATCH 2/6] powerpc/perf: Export memory hierarchy info to user space

2017-03-05 Thread Madhavan Srinivasan
The LDST field and DATA_SRC in SIER identifies the memory hierarchy level
(eg: L1, L2 etc), from which a data-cache miss for a marked instruction
was satisfied. Use the 'perf_mem_data_src' object to export this
hierarchy level to user space.

Signed-off-by: Madhavan Srinivasan 
Cc: Benjamin Herrenschmidt 
Cc: Paul Mackerras 
Cc: Sukadev Bhattiprolu 
Cc: Thomas Gleixner 
Cc: Sebastian Andrzej Siewior 
Cc: Anna-Maria Gleixner 
Cc: Daniel Axtens 
---
 arch/powerpc/include/asm/perf_event_server.h |  2 +
 arch/powerpc/perf/core-book3s.c  |  4 ++
 arch/powerpc/perf/isa207-common.c| 78 
 arch/powerpc/perf/isa207-common.h| 16 +-
 4 files changed, 99 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/include/asm/perf_event_server.h 
b/arch/powerpc/include/asm/perf_event_server.h
index ae0a23091a9b..446cdcd9b7f5 100644
--- a/arch/powerpc/include/asm/perf_event_server.h
+++ b/arch/powerpc/include/asm/perf_event_server.h
@@ -38,6 +38,8 @@ struct power_pmu {
unsigned long *valp);
int (*get_alternatives)(u64 event_id, unsigned int flags,
u64 alt[]);
+   void(*get_mem_data_src)(union perf_mem_data_src *dsrc,
+   u32 flags, struct pt_regs *regs);
u64 (*bhrb_filter_map)(u64 branch_sample_type);
void(*config_bhrb)(u64 pmu_bhrb_filter);
void(*disable_pmc)(unsigned int pmc, unsigned long mmcr[]);
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 595dd718ea87..d644c5ab4d2f 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -2047,6 +2047,10 @@ static void record_and_restart(struct perf_event *event, 
unsigned long val,
data.br_stack = >bhrb_stack;
}
 
+   if (event->attr.sample_type & PERF_SAMPLE_DATA_SRC &&
+   ppmu->get_mem_data_src)
+   ppmu->get_mem_data_src(_src, ppmu->flags, 
regs);
+
if (perf_event_overflow(event, , regs))
power_pmu_stop(event, 0);
}
diff --git a/arch/powerpc/perf/isa207-common.c 
b/arch/powerpc/perf/isa207-common.c
index e79fb5fb817d..08bb62454a2e 100644
--- a/arch/powerpc/perf/isa207-common.c
+++ b/arch/powerpc/perf/isa207-common.c
@@ -119,6 +119,84 @@ static bool is_thresh_cmp_valid(u64 event)
return true;
 }
 
+static inline u64 isa207_find_source(u64 idx, u32 sub_idx)
+{
+   u64 ret = 0;
+
+   switch(idx) {
+   case 0:
+   ret = P(LVL, NA);
+   break;
+   case 1:
+   ret = PLH(LVL, L1);
+   break;
+   case 2:
+   ret = PLH(LVL, L2);
+   break;
+   case 3:
+   ret = PLH(LVL, L3);
+   break;
+   case 4:
+   if (sub_idx <= 1)
+   ret = PLH(LVL, LOC_RAM);
+   else if (sub_idx > 1 && sub_idx <= 2)
+   ret = PLH(LVL, REM_RAM1);
+   else
+   ret = PLH(LVL, REM_RAM2);
+   ret |= P(SNOOP, HIT);
+   break;
+   case 5:
+   if ((sub_idx == 0) || (sub_idx == 2) || (sub_idx == 4))
+   ret = (PLH(LVL, REM_CCE1) | P(SNOOP, HIT));
+   else if ((sub_idx == 1) || (sub_idx == 3) || (sub_idx == 5))
+   ret = (PLH(LVL, REM_CCE1) | P(SNOOP, HITM));
+   break;
+   case 6:
+   if ((sub_idx == 0) || (sub_idx == 2))
+   ret = (PLH(LVL, REM_CCE2) | P(SNOOP, HIT));
+   else if ((sub_idx == 1) || (sub_idx == 3))
+   ret = (PLH(LVL, REM_CCE2) | P(SNOOP, HITM));
+   break;
+   case 7:
+   ret = PSM(LVL, L1);
+   break;
+   }
+
+   return ret;
+}
+
+static inline bool is_load_store_inst(u64 sier)
+{
+   u64 val;
+   val = (sier & ISA207_SIER_TYPE_MASK) >> ISA207_SIER_TYPE_SHIFT;
+
+   /* 1 = load, 2 = store */
+   return val == 1 || val == 2;
+}
+
+void isa207_get_mem_data_src(union perf_mem_data_src *dsrc, u32 flags,
+   struct pt_regs *regs)
+{
+   u64 idx;
+   u32 sub_idx;
+   u64 sier;
+
+   /* Skip if no SIER support */
+   if (!(flags & PPMU_HAS_SIER)) {
+   dsrc->val = 0;
+   return;
+   }
+
+   sier = mfspr(SPRN_SIER);
+   if (is_load_store_inst(sier)) {
+   idx = (sier & ISA207_SIER_LDST_MASK) >> ISA207_SIER_LDST_SHIFT;
+   sub_idx = (sier & ISA207_SIER_DATA_SRC_MASK) >> 
ISA207_SIER_DATA_SRC_SHIFT;
+
+   dsrc->val = isa207_find_source(idx, sub_idx);
+ 

[PATCH 4/6] powerpc/perf: Support to export SIERs bit in Power8

2017-03-05 Thread Madhavan Srinivasan
Patch to export SIER bits to userspace via
perf_mem_data_src and perf_sample_data struct.

Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
Cc: Benjamin Herrenschmidt <b...@kernel.crashing.org>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>
Cc: Daniel Axtens <d...@axtens.net>
Cc: Andrew Donnellan <andrew.donnel...@au1.ibm.com>
---
 arch/powerpc/perf/power8-pmu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index ce15b19a7962..932d7536f0eb 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -325,6 +325,8 @@ static struct power_pmu power8_pmu = {
.bhrb_filter_map= power8_bhrb_filter_map,
.get_constraint = isa207_get_constraint,
.get_alternatives   = power8_get_alternatives,
+   .get_mem_data_src   = isa207_get_mem_data_src,
+   .get_mem_weight = isa207_get_mem_weight,
.disable_pmc= isa207_disable_pmc,
.flags  = PPMU_HAS_SIER | PPMU_ARCH_207S,
.n_generic  = ARRAY_SIZE(power8_generic_events),
-- 
2.7.4



[PATCH 4/6] powerpc/perf: Support to export SIERs bit in Power8

2017-03-05 Thread Madhavan Srinivasan
Patch to export SIER bits to userspace via
perf_mem_data_src and perf_sample_data struct.

Signed-off-by: Madhavan Srinivasan 
Cc: Benjamin Herrenschmidt 
Cc: Paul Mackerras 
Cc: Sukadev Bhattiprolu 
Cc: Daniel Axtens 
Cc: Andrew Donnellan 
---
 arch/powerpc/perf/power8-pmu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index ce15b19a7962..932d7536f0eb 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -325,6 +325,8 @@ static struct power_pmu power8_pmu = {
.bhrb_filter_map= power8_bhrb_filter_map,
.get_constraint = isa207_get_constraint,
.get_alternatives   = power8_get_alternatives,
+   .get_mem_data_src   = isa207_get_mem_data_src,
+   .get_mem_weight = isa207_get_mem_weight,
.disable_pmc= isa207_disable_pmc,
.flags  = PPMU_HAS_SIER | PPMU_ARCH_207S,
.n_generic  = ARRAY_SIZE(power8_generic_events),
-- 
2.7.4



[PATCH 3/6] powerpc/perf: Support to export MMCRA[TEC*] field to userspace

2017-03-05 Thread Madhavan Srinivasan
Threshold feature when used with MMCRA [Threshold Event Counter Event],
MMCRA[Threshold Start event] and MMCRA[Threshold End event] will update
MMCRA[Threashold Event Counter Exponent] and MMCRA[Threshold Event
Counter Multiplier] with the corresponding threshold event count values.
Patch to export MMCRA[TECX/TECM] to userspace in 'weight' field of
struct perf_sample_data.

Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
Cc: Benjamin Herrenschmidt <b...@kernel.crashing.org>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>
Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Sebastian Andrzej Siewior <bige...@linutronix.de>
Cc: Anna-Maria Gleixner <anna-ma...@linutronix.de>
Cc: Daniel Axtens <d...@axtens.net>
---
 arch/powerpc/include/asm/perf_event_server.h |  1 +
 arch/powerpc/perf/core-book3s.c  |  4 
 arch/powerpc/perf/isa207-common.c|  8 
 arch/powerpc/perf/isa207-common.h| 10 ++
 4 files changed, 23 insertions(+)

diff --git a/arch/powerpc/include/asm/perf_event_server.h 
b/arch/powerpc/include/asm/perf_event_server.h
index 446cdcd9b7f5..723bf48e7494 100644
--- a/arch/powerpc/include/asm/perf_event_server.h
+++ b/arch/powerpc/include/asm/perf_event_server.h
@@ -40,6 +40,7 @@ struct power_pmu {
u64 alt[]);
void(*get_mem_data_src)(union perf_mem_data_src *dsrc,
u32 flags, struct pt_regs *regs);
+   void(*get_mem_weight)(u64 *weight);
u64 (*bhrb_filter_map)(u64 branch_sample_type);
void(*config_bhrb)(u64 pmu_bhrb_filter);
void(*disable_pmc)(unsigned int pmc, unsigned long mmcr[]);
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index d644c5ab4d2f..a6b265e31663 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -2051,6 +2051,10 @@ static void record_and_restart(struct perf_event *event, 
unsigned long val,
ppmu->get_mem_data_src)
ppmu->get_mem_data_src(_src, ppmu->flags, 
regs);
 
+   if (event->attr.sample_type & PERF_SAMPLE_WEIGHT &&
+   ppmu->get_mem_weight)
+   ppmu->get_mem_weight();
+
if (perf_event_overflow(event, , regs))
power_pmu_stop(event, 0);
}
diff --git a/arch/powerpc/perf/isa207-common.c 
b/arch/powerpc/perf/isa207-common.c
index 08bb62454a2e..42e999da934e 100644
--- a/arch/powerpc/perf/isa207-common.c
+++ b/arch/powerpc/perf/isa207-common.c
@@ -196,6 +196,14 @@ void isa207_get_mem_data_src(union perf_mem_data_src 
*dsrc, u32 flags,
}
 }
 
+void isa207_get_mem_weight(u64 *weight)
+{
+   u64 mmcra = mfspr(SPRN_MMCRA);
+   u64 exp = MMCRA_THR_CTR_EXP(mmcra);
+   u64 mantissa = MMCRA_THR_CTR_MANT(mmcra);
+
+   *weight = mantissa << (2 * exp);
+}
 
 int isa207_get_constraint(u64 event, unsigned long *maskp, unsigned long *valp)
 {
diff --git a/arch/powerpc/perf/isa207-common.h 
b/arch/powerpc/perf/isa207-common.h
index 982542cce991..b4d02ae3a6e0 100644
--- a/arch/powerpc/perf/isa207-common.h
+++ b/arch/powerpc/perf/isa207-common.h
@@ -247,6 +247,15 @@
 #define MMCRA_SDAR_MODE_SHIFT  42
 #define MMCRA_SDAR_MODE_TLB(1ull << MMCRA_SDAR_MODE_SHIFT)
 #define MMCRA_IFM_SHIFT30
+#define MMCRA_THR_CTR_MANT_SHIFT   19
+#define MMCRA_THR_CTR_MANT_MASK0x7Ful
+#define MMCRA_THR_CTR_MANT(v)  (((v) >> MMCRA_THR_CTR_MANT_SHIFT) &\
+   MMCRA_THR_CTR_MANT_MASK)
+
+#define MMCRA_THR_CTR_EXP_SHIFT27
+#define MMCRA_THR_CTR_EXP_MASK 0x7ul
+#define MMCRA_THR_CTR_EXP(v)   (((v) >> MMCRA_THR_CTR_EXP_SHIFT) &\
+   MMCRA_THR_CTR_EXP_MASK)
 
 /* MMCR1 Threshold Compare bit constant for power9 */
 #define p9_MMCRA_THR_CMP_SHIFT 45
@@ -281,5 +290,6 @@ int isa207_get_alternatives(u64 event, u64 alt[],
const unsigned int ev_alt[][MAX_ALT], int size);
 void isa207_get_mem_data_src(union perf_mem_data_src *dsrc, u32 flags,
struct pt_regs *regs);
+void isa207_get_mem_weight(u64 *weight);
 
 #endif
-- 
2.7.4



[PATCH 6/6] powerpc/perf: Add Power8 mem_access event to sysfs

2017-03-05 Thread Madhavan Srinivasan
Patch add "mem_access" event to sysfs. This as-is not a raw event
supported by Power8 pmu. Instead, it is formed based on
raw event encoding specificed in isa207-common.h.

Primary PMU event used here is PM_MRK_INST_CMPL.
This event tracks only the completed marked instructions.

Random sampling mode (MMCRA[SM]) with Random Instruction
Sampling (RIS) is enabled to mark type of instructions.

With Random sampling in RLS mode with PM_MRK_INST_CMPL event,
the LDST /DATA_SRC fields in SIER identifies the memory
hierarchy level (eg: L1, L2 etc) statisfied a data-cache
miss for a marked instruction.

Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
Cc: Benjamin Herrenschmidt <b...@kernel.crashing.org>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>
Cc: Daniel Axtens <d...@axtens.net>
Cc: Andrew Donnellan <andrew.donnel...@au1.ibm.com>
---
 arch/powerpc/perf/power8-events-list.h | 6 ++
 arch/powerpc/perf/power8-pmu.c | 2 ++
 2 files changed, 8 insertions(+)

diff --git a/arch/powerpc/perf/power8-events-list.h 
b/arch/powerpc/perf/power8-events-list.h
index 3a2e6e8ebb92..0f1d184627cc 100644
--- a/arch/powerpc/perf/power8-events-list.h
+++ b/arch/powerpc/perf/power8-events-list.h
@@ -89,3 +89,9 @@ EVENT(PM_MRK_FILT_MATCH,  0x2013c)
 EVENT(PM_MRK_FILT_MATCH_ALT,   0x3012e)
 /* Alternate event code for PM_LD_MISS_L1 */
 EVENT(PM_LD_MISS_L1_ALT,   0x400f0)
+/*
+ * Memory Access Event -- mem_access
+ * Primary PMU event used here is PM_MRK_INST_CMPL, along with
+ * Random Load/Store Facility Sampling (RIS) in Random sampling mode 
(MMCRA[SM]).
+ */
+EVENT(MEM_ACCESS,  0x10401e0)
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index 932d7536f0eb..5463516e369b 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -90,6 +90,7 @@ GENERIC_EVENT_ATTR(branch-instructions,   
PM_BRU_FIN);
 GENERIC_EVENT_ATTR(branch-misses,  PM_BR_MPRED_CMPL);
 GENERIC_EVENT_ATTR(cache-references,   PM_LD_REF_L1);
 GENERIC_EVENT_ATTR(cache-misses,   PM_LD_MISS_L1);
+GENERIC_EVENT_ATTR(mem_access, MEM_ACCESS);
 
 CACHE_EVENT_ATTR(L1-dcache-load-misses,PM_LD_MISS_L1);
 CACHE_EVENT_ATTR(L1-dcache-loads,  PM_LD_REF_L1);
@@ -120,6 +121,7 @@ static struct attribute *power8_events_attr[] = {
GENERIC_EVENT_PTR(PM_BR_MPRED_CMPL),
GENERIC_EVENT_PTR(PM_LD_REF_L1),
GENERIC_EVENT_PTR(PM_LD_MISS_L1),
+   GENERIC_EVENT_PTR(MEM_ACCESS),
 
CACHE_EVENT_PTR(PM_LD_MISS_L1),
CACHE_EVENT_PTR(PM_LD_REF_L1),
-- 
2.7.4




[PATCH 3/6] powerpc/perf: Support to export MMCRA[TEC*] field to userspace

2017-03-05 Thread Madhavan Srinivasan
Threshold feature when used with MMCRA [Threshold Event Counter Event],
MMCRA[Threshold Start event] and MMCRA[Threshold End event] will update
MMCRA[Threashold Event Counter Exponent] and MMCRA[Threshold Event
Counter Multiplier] with the corresponding threshold event count values.
Patch to export MMCRA[TECX/TECM] to userspace in 'weight' field of
struct perf_sample_data.

Signed-off-by: Madhavan Srinivasan 
Cc: Benjamin Herrenschmidt 
Cc: Paul Mackerras 
Cc: Sukadev Bhattiprolu 
Cc: Thomas Gleixner 
Cc: Sebastian Andrzej Siewior 
Cc: Anna-Maria Gleixner 
Cc: Daniel Axtens 
---
 arch/powerpc/include/asm/perf_event_server.h |  1 +
 arch/powerpc/perf/core-book3s.c  |  4 
 arch/powerpc/perf/isa207-common.c|  8 
 arch/powerpc/perf/isa207-common.h| 10 ++
 4 files changed, 23 insertions(+)

diff --git a/arch/powerpc/include/asm/perf_event_server.h 
b/arch/powerpc/include/asm/perf_event_server.h
index 446cdcd9b7f5..723bf48e7494 100644
--- a/arch/powerpc/include/asm/perf_event_server.h
+++ b/arch/powerpc/include/asm/perf_event_server.h
@@ -40,6 +40,7 @@ struct power_pmu {
u64 alt[]);
void(*get_mem_data_src)(union perf_mem_data_src *dsrc,
u32 flags, struct pt_regs *regs);
+   void(*get_mem_weight)(u64 *weight);
u64 (*bhrb_filter_map)(u64 branch_sample_type);
void(*config_bhrb)(u64 pmu_bhrb_filter);
void(*disable_pmc)(unsigned int pmc, unsigned long mmcr[]);
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index d644c5ab4d2f..a6b265e31663 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -2051,6 +2051,10 @@ static void record_and_restart(struct perf_event *event, 
unsigned long val,
ppmu->get_mem_data_src)
ppmu->get_mem_data_src(_src, ppmu->flags, 
regs);
 
+   if (event->attr.sample_type & PERF_SAMPLE_WEIGHT &&
+   ppmu->get_mem_weight)
+   ppmu->get_mem_weight();
+
if (perf_event_overflow(event, , regs))
power_pmu_stop(event, 0);
}
diff --git a/arch/powerpc/perf/isa207-common.c 
b/arch/powerpc/perf/isa207-common.c
index 08bb62454a2e..42e999da934e 100644
--- a/arch/powerpc/perf/isa207-common.c
+++ b/arch/powerpc/perf/isa207-common.c
@@ -196,6 +196,14 @@ void isa207_get_mem_data_src(union perf_mem_data_src 
*dsrc, u32 flags,
}
 }
 
+void isa207_get_mem_weight(u64 *weight)
+{
+   u64 mmcra = mfspr(SPRN_MMCRA);
+   u64 exp = MMCRA_THR_CTR_EXP(mmcra);
+   u64 mantissa = MMCRA_THR_CTR_MANT(mmcra);
+
+   *weight = mantissa << (2 * exp);
+}
 
 int isa207_get_constraint(u64 event, unsigned long *maskp, unsigned long *valp)
 {
diff --git a/arch/powerpc/perf/isa207-common.h 
b/arch/powerpc/perf/isa207-common.h
index 982542cce991..b4d02ae3a6e0 100644
--- a/arch/powerpc/perf/isa207-common.h
+++ b/arch/powerpc/perf/isa207-common.h
@@ -247,6 +247,15 @@
 #define MMCRA_SDAR_MODE_SHIFT  42
 #define MMCRA_SDAR_MODE_TLB(1ull << MMCRA_SDAR_MODE_SHIFT)
 #define MMCRA_IFM_SHIFT30
+#define MMCRA_THR_CTR_MANT_SHIFT   19
+#define MMCRA_THR_CTR_MANT_MASK0x7Ful
+#define MMCRA_THR_CTR_MANT(v)  (((v) >> MMCRA_THR_CTR_MANT_SHIFT) &\
+   MMCRA_THR_CTR_MANT_MASK)
+
+#define MMCRA_THR_CTR_EXP_SHIFT27
+#define MMCRA_THR_CTR_EXP_MASK 0x7ul
+#define MMCRA_THR_CTR_EXP(v)   (((v) >> MMCRA_THR_CTR_EXP_SHIFT) &\
+   MMCRA_THR_CTR_EXP_MASK)
 
 /* MMCR1 Threshold Compare bit constant for power9 */
 #define p9_MMCRA_THR_CMP_SHIFT 45
@@ -281,5 +290,6 @@ int isa207_get_alternatives(u64 event, u64 alt[],
const unsigned int ev_alt[][MAX_ALT], int size);
 void isa207_get_mem_data_src(union perf_mem_data_src *dsrc, u32 flags,
struct pt_regs *regs);
+void isa207_get_mem_weight(u64 *weight);
 
 #endif
-- 
2.7.4



[PATCH 6/6] powerpc/perf: Add Power8 mem_access event to sysfs

2017-03-05 Thread Madhavan Srinivasan
Patch add "mem_access" event to sysfs. This as-is not a raw event
supported by Power8 pmu. Instead, it is formed based on
raw event encoding specificed in isa207-common.h.

Primary PMU event used here is PM_MRK_INST_CMPL.
This event tracks only the completed marked instructions.

Random sampling mode (MMCRA[SM]) with Random Instruction
Sampling (RIS) is enabled to mark type of instructions.

With Random sampling in RLS mode with PM_MRK_INST_CMPL event,
the LDST /DATA_SRC fields in SIER identifies the memory
hierarchy level (eg: L1, L2 etc) statisfied a data-cache
miss for a marked instruction.

Signed-off-by: Madhavan Srinivasan 
Cc: Benjamin Herrenschmidt 
Cc: Paul Mackerras 
Cc: Sukadev Bhattiprolu 
Cc: Daniel Axtens 
Cc: Andrew Donnellan 
---
 arch/powerpc/perf/power8-events-list.h | 6 ++
 arch/powerpc/perf/power8-pmu.c | 2 ++
 2 files changed, 8 insertions(+)

diff --git a/arch/powerpc/perf/power8-events-list.h 
b/arch/powerpc/perf/power8-events-list.h
index 3a2e6e8ebb92..0f1d184627cc 100644
--- a/arch/powerpc/perf/power8-events-list.h
+++ b/arch/powerpc/perf/power8-events-list.h
@@ -89,3 +89,9 @@ EVENT(PM_MRK_FILT_MATCH,  0x2013c)
 EVENT(PM_MRK_FILT_MATCH_ALT,   0x3012e)
 /* Alternate event code for PM_LD_MISS_L1 */
 EVENT(PM_LD_MISS_L1_ALT,   0x400f0)
+/*
+ * Memory Access Event -- mem_access
+ * Primary PMU event used here is PM_MRK_INST_CMPL, along with
+ * Random Load/Store Facility Sampling (RIS) in Random sampling mode 
(MMCRA[SM]).
+ */
+EVENT(MEM_ACCESS,  0x10401e0)
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index 932d7536f0eb..5463516e369b 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -90,6 +90,7 @@ GENERIC_EVENT_ATTR(branch-instructions,   
PM_BRU_FIN);
 GENERIC_EVENT_ATTR(branch-misses,  PM_BR_MPRED_CMPL);
 GENERIC_EVENT_ATTR(cache-references,   PM_LD_REF_L1);
 GENERIC_EVENT_ATTR(cache-misses,   PM_LD_MISS_L1);
+GENERIC_EVENT_ATTR(mem_access, MEM_ACCESS);
 
 CACHE_EVENT_ATTR(L1-dcache-load-misses,PM_LD_MISS_L1);
 CACHE_EVENT_ATTR(L1-dcache-loads,  PM_LD_REF_L1);
@@ -120,6 +121,7 @@ static struct attribute *power8_events_attr[] = {
GENERIC_EVENT_PTR(PM_BR_MPRED_CMPL),
GENERIC_EVENT_PTR(PM_LD_REF_L1),
GENERIC_EVENT_PTR(PM_LD_MISS_L1),
+   GENERIC_EVENT_PTR(MEM_ACCESS),
 
CACHE_EVENT_PTR(PM_LD_MISS_L1),
CACHE_EVENT_PTR(PM_LD_REF_L1),
-- 
2.7.4




[PATCH 1/6] powerpc/perf: Define big-endian version of perf_mem_data_src

2017-03-05 Thread Madhavan Srinivasan
perf_mem_data_src is an union that is initialized via the ->val field
and accessed via the bitmap fields. For this to work on big endian
platforms, we also need a big-endian represenation of perf_mem_data_src.

Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Ingo Molnar <mi...@redhat.com>
Cc: Arnaldo Carvalho de Melo <a...@kernel.org>
Cc: Alexander Shishkin <alexander.shish...@linux.intel.com>
Cc: Wang Nan <wangn...@huawei.com>
Cc: Alexei Starovoitov <a...@kernel.org>
Cc: Stephane Eranian <eran...@google.com>
Cc: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>
---
 include/uapi/linux/perf_event.h   | 16 
 tools/include/uapi/linux/perf_event.h | 16 
 2 files changed, 32 insertions(+)

diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index c66a485a24ac..c4af1159a200 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -891,6 +891,7 @@ enum perf_callchain_context {
 #define PERF_FLAG_PID_CGROUP   (1UL << 2) /* pid=cgroup id, per-cpu 
mode only */
 #define PERF_FLAG_FD_CLOEXEC   (1UL << 3) /* O_CLOEXEC */
 
+#if defined(__LITTLE_ENDIAN_BITFIELD)
 union perf_mem_data_src {
__u64 val;
struct {
@@ -902,6 +903,21 @@ union perf_mem_data_src {
mem_rsvd:31;
};
 };
+#elif defined(__BIG_ENDIAN_BITFIELD)
+union perf_mem_data_src {
+   __u64 val;
+   struct {
+   __u64   mem_rsvd:31,
+   mem_dtlb:7, /* tlb access */
+   mem_lock:2, /* lock instr */
+   mem_snoop:5,/* snoop mode */
+   mem_lvl:14, /* memory hierarchy level */
+   mem_op:5;   /* type of opcode */
+   };
+};
+#else
+#error "Unknown endianness"
+#endif
 
 /* type of opcode (load/store/prefetch,code) */
 #define PERF_MEM_OP_NA 0x01 /* not available */
diff --git a/tools/include/uapi/linux/perf_event.h 
b/tools/include/uapi/linux/perf_event.h
index c66a485a24ac..c4af1159a200 100644
--- a/tools/include/uapi/linux/perf_event.h
+++ b/tools/include/uapi/linux/perf_event.h
@@ -891,6 +891,7 @@ enum perf_callchain_context {
 #define PERF_FLAG_PID_CGROUP   (1UL << 2) /* pid=cgroup id, per-cpu 
mode only */
 #define PERF_FLAG_FD_CLOEXEC   (1UL << 3) /* O_CLOEXEC */
 
+#if defined(__LITTLE_ENDIAN_BITFIELD)
 union perf_mem_data_src {
__u64 val;
struct {
@@ -902,6 +903,21 @@ union perf_mem_data_src {
mem_rsvd:31;
};
 };
+#elif defined(__BIG_ENDIAN_BITFIELD)
+union perf_mem_data_src {
+   __u64 val;
+   struct {
+   __u64   mem_rsvd:31,
+   mem_dtlb:7, /* tlb access */
+   mem_lock:2, /* lock instr */
+   mem_snoop:5,/* snoop mode */
+   mem_lvl:14, /* memory hierarchy level */
+   mem_op:5;   /* type of opcode */
+   };
+};
+#else
+#error "Unknown endianness"
+#endif
 
 /* type of opcode (load/store/prefetch,code) */
 #define PERF_MEM_OP_NA 0x01 /* not available */
-- 
2.7.4



[PATCH 0/6] powerpc/perf: Export memory hierarchy level

2017-03-05 Thread Madhavan Srinivasan
Power8/Power9 Perforence Monitoring Unit (PMU) supports
different sampling modes (SM) such as Random Instruction
Sampling (RIS), Random Load/Store Facility Sampling (RLS)
and Random Branch Sampling (RBS). Sample mode RLS updates
Sampled Instruction Event Register [SIER] bits with memory
hierarchy information for a cache reload. Patchset exports
the hierarchy information to the user via the perf_mem_data_src
object from SIER.

Patchset is a rebase of the work posted previously with minor
updates to it.

https://lkml.org/lkml/2015/6/11/92

Madhavan Srinivasan (6):
  powerpc/perf: Define big-endian version of perf_mem_data_src
  powerpc/perf: Export memory hierarchy info to user space
  powerpc/perf: Support to export MMCRA[TEC*] field to userspace
  powerpc/perf: Support to export SIERs bit in Power8
  powerpc/perf: Support to export SIERs bit in Power9
  powerpc/perf: Add Power8 mem_access event to sysfs

 arch/powerpc/include/asm/perf_event_server.h |  3 +
 arch/powerpc/perf/core-book3s.c  |  8 +++
 arch/powerpc/perf/isa207-common.c| 86 
 arch/powerpc/perf/isa207-common.h| 26 -
 arch/powerpc/perf/power8-events-list.h   |  6 ++
 arch/powerpc/perf/power8-pmu.c   |  4 ++
 arch/powerpc/perf/power9-pmu.c   |  2 +
 include/uapi/linux/perf_event.h  | 16 ++
 tools/include/uapi/linux/perf_event.h| 16 ++
 9 files changed, 166 insertions(+), 1 deletion(-)

-- 
2.7.4



[PATCH 1/6] powerpc/perf: Define big-endian version of perf_mem_data_src

2017-03-05 Thread Madhavan Srinivasan
perf_mem_data_src is an union that is initialized via the ->val field
and accessed via the bitmap fields. For this to work on big endian
platforms, we also need a big-endian represenation of perf_mem_data_src.

Signed-off-by: Madhavan Srinivasan 
Cc: Peter Zijlstra 
Cc: Ingo Molnar 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexander Shishkin 
Cc: Wang Nan 
Cc: Alexei Starovoitov 
Cc: Stephane Eranian 
Cc: Sukadev Bhattiprolu 
---
 include/uapi/linux/perf_event.h   | 16 
 tools/include/uapi/linux/perf_event.h | 16 
 2 files changed, 32 insertions(+)

diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index c66a485a24ac..c4af1159a200 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -891,6 +891,7 @@ enum perf_callchain_context {
 #define PERF_FLAG_PID_CGROUP   (1UL << 2) /* pid=cgroup id, per-cpu 
mode only */
 #define PERF_FLAG_FD_CLOEXEC   (1UL << 3) /* O_CLOEXEC */
 
+#if defined(__LITTLE_ENDIAN_BITFIELD)
 union perf_mem_data_src {
__u64 val;
struct {
@@ -902,6 +903,21 @@ union perf_mem_data_src {
mem_rsvd:31;
};
 };
+#elif defined(__BIG_ENDIAN_BITFIELD)
+union perf_mem_data_src {
+   __u64 val;
+   struct {
+   __u64   mem_rsvd:31,
+   mem_dtlb:7, /* tlb access */
+   mem_lock:2, /* lock instr */
+   mem_snoop:5,/* snoop mode */
+   mem_lvl:14, /* memory hierarchy level */
+   mem_op:5;   /* type of opcode */
+   };
+};
+#else
+#error "Unknown endianness"
+#endif
 
 /* type of opcode (load/store/prefetch,code) */
 #define PERF_MEM_OP_NA 0x01 /* not available */
diff --git a/tools/include/uapi/linux/perf_event.h 
b/tools/include/uapi/linux/perf_event.h
index c66a485a24ac..c4af1159a200 100644
--- a/tools/include/uapi/linux/perf_event.h
+++ b/tools/include/uapi/linux/perf_event.h
@@ -891,6 +891,7 @@ enum perf_callchain_context {
 #define PERF_FLAG_PID_CGROUP   (1UL << 2) /* pid=cgroup id, per-cpu 
mode only */
 #define PERF_FLAG_FD_CLOEXEC   (1UL << 3) /* O_CLOEXEC */
 
+#if defined(__LITTLE_ENDIAN_BITFIELD)
 union perf_mem_data_src {
__u64 val;
struct {
@@ -902,6 +903,21 @@ union perf_mem_data_src {
mem_rsvd:31;
};
 };
+#elif defined(__BIG_ENDIAN_BITFIELD)
+union perf_mem_data_src {
+   __u64 val;
+   struct {
+   __u64   mem_rsvd:31,
+   mem_dtlb:7, /* tlb access */
+   mem_lock:2, /* lock instr */
+   mem_snoop:5,/* snoop mode */
+   mem_lvl:14, /* memory hierarchy level */
+   mem_op:5;   /* type of opcode */
+   };
+};
+#else
+#error "Unknown endianness"
+#endif
 
 /* type of opcode (load/store/prefetch,code) */
 #define PERF_MEM_OP_NA 0x01 /* not available */
-- 
2.7.4



[PATCH 0/6] powerpc/perf: Export memory hierarchy level

2017-03-05 Thread Madhavan Srinivasan
Power8/Power9 Perforence Monitoring Unit (PMU) supports
different sampling modes (SM) such as Random Instruction
Sampling (RIS), Random Load/Store Facility Sampling (RLS)
and Random Branch Sampling (RBS). Sample mode RLS updates
Sampled Instruction Event Register [SIER] bits with memory
hierarchy information for a cache reload. Patchset exports
the hierarchy information to the user via the perf_mem_data_src
object from SIER.

Patchset is a rebase of the work posted previously with minor
updates to it.

https://lkml.org/lkml/2015/6/11/92

Madhavan Srinivasan (6):
  powerpc/perf: Define big-endian version of perf_mem_data_src
  powerpc/perf: Export memory hierarchy info to user space
  powerpc/perf: Support to export MMCRA[TEC*] field to userspace
  powerpc/perf: Support to export SIERs bit in Power8
  powerpc/perf: Support to export SIERs bit in Power9
  powerpc/perf: Add Power8 mem_access event to sysfs

 arch/powerpc/include/asm/perf_event_server.h |  3 +
 arch/powerpc/perf/core-book3s.c  |  8 +++
 arch/powerpc/perf/isa207-common.c| 86 
 arch/powerpc/perf/isa207-common.h| 26 -
 arch/powerpc/perf/power8-events-list.h   |  6 ++
 arch/powerpc/perf/power8-pmu.c   |  4 ++
 arch/powerpc/perf/power9-pmu.c   |  2 +
 include/uapi/linux/perf_event.h  | 16 ++
 tools/include/uapi/linux/perf_event.h| 16 ++
 9 files changed, 166 insertions(+), 1 deletion(-)

-- 
2.7.4



[tip:perf/core] perf vendor events: Support couple more POWER8 PVRs in mapfile

2016-10-19 Thread tip-bot for Madhavan Srinivasan
Commit-ID:  46b627a25f228adca952b8691e6aed32011cc3cf
Gitweb: http://git.kernel.org/tip/46b627a25f228adca952b8691e6aed32011cc3cf
Author: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
AuthorDate: Mon, 8 Jun 2015 13:35:16 +0530
Committer:  Arnaldo Carvalho de Melo <a...@redhat.com>
CommitDate: Mon, 17 Oct 2016 13:39:47 -0300

perf vendor events: Support couple more POWER8 PVRs in mapfile

Add support for Power8 PVR 004b0201 for tuleta and 0x004d0200 for
firestone.

Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
CC: Andi Kleen <a...@linux.intel.com>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>
Link: http://lkml.kernel.org/n/tip-wr6rf3d3vvggy8180ftt2...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <a...@redhat.com>
---
 tools/perf/pmu-events/arch/powerpc/mapfile.csv | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/perf/pmu-events/arch/powerpc/mapfile.csv 
b/tools/perf/pmu-events/arch/powerpc/mapfile.csv
index 8a7b6b4..e925baa 100644
--- a/tools/perf/pmu-events/arch/powerpc/mapfile.csv
+++ b/tools/perf/pmu-events/arch/powerpc/mapfile.csv
@@ -14,6 +14,8 @@
 
 # Power8 entries
 004b,1,power8.json,core
+004b0201,1,power8.json,core
 004c,1,power8.json,core
 004d,1,power8.json,core
 004d0100,1,power8.json,core
+004d0200,1,power8.json,core


[tip:perf/core] perf vendor events: Support couple more POWER8 PVRs in mapfile

2016-10-19 Thread tip-bot for Madhavan Srinivasan
Commit-ID:  46b627a25f228adca952b8691e6aed32011cc3cf
Gitweb: http://git.kernel.org/tip/46b627a25f228adca952b8691e6aed32011cc3cf
Author: Madhavan Srinivasan 
AuthorDate: Mon, 8 Jun 2015 13:35:16 +0530
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Mon, 17 Oct 2016 13:39:47 -0300

perf vendor events: Support couple more POWER8 PVRs in mapfile

Add support for Power8 PVR 004b0201 for tuleta and 0x004d0200 for
firestone.

Signed-off-by: Madhavan Srinivasan 
CC: Andi Kleen 
Cc: Jiri Olsa 
Cc: Sukadev Bhattiprolu 
Link: http://lkml.kernel.org/n/tip-wr6rf3d3vvggy8180ftt2...@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo 
---
 tools/perf/pmu-events/arch/powerpc/mapfile.csv | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/perf/pmu-events/arch/powerpc/mapfile.csv 
b/tools/perf/pmu-events/arch/powerpc/mapfile.csv
index 8a7b6b4..e925baa 100644
--- a/tools/perf/pmu-events/arch/powerpc/mapfile.csv
+++ b/tools/perf/pmu-events/arch/powerpc/mapfile.csv
@@ -14,6 +14,8 @@
 
 # Power8 entries
 004b,1,power8.json,core
+004b0201,1,power8.json,core
 004c,1,power8.json,core
 004d,1,power8.json,core
 004d0100,1,power8.json,core
+004d0200,1,power8.json,core


Re: [PATCH 01/13] perf/core: Add perf_arch_regs and mask to perf_regs structure

2016-09-08 Thread Madhavan Srinivasan



On Tuesday 06 September 2016 02:40 PM, Peter Zijlstra wrote:

On Tue, Sep 06, 2016 at 09:55:43AM +0530, Madhavan Srinivasan wrote:


On Thursday 01 September 2016 12:56 PM, Peter Zijlstra wrote:

On Mon, Aug 29, 2016 at 02:30:46AM +0530, Madhavan Srinivasan wrote:

It's a perennial request from hardware folks to be able to
see the raw values of the pmu registers. Partly it's so that
they can verify perf is doing what they want, and some
of it is that they're interested in some of the more obscure
info that isn't plumbed out through other perf interfaces.

How much and what is that? Can't we try and get interfaces sorted?

We have bunch of registers which exports information regarding the
sampled instruction like SIER/SIAR/SDAR/MMCRA. Lot of bits in these
registers are not yet architected and incase of SIER register, some of
the bits are not plumbed out and we are working on getting some these
exposed via perf.

What kind of information is this? I'm not familiar with the Power PMU
all that much, so you'll have to spell it out, not just mention the
registers its stuffed in.



Sure. When we profile for sample events,
SIER (Sampled Instruction Event Register) provides additional
information about the sampled event when PMI occurred.

SIER [41:42] indicates whether the SIAR(Sampled instruction address 
registers)

and SDAR (Sampled data address register) are valid for the sampled event.

SIER [46:48] indicates the type of intructions,

001 Load Instruction
010 Store instruction
011 Branch Instruction
100 Floating Point Instruction other than a Load or Store instruction
101 Fixed Point Instruction other than a Load or Store instruction
110 Condition Register or System Call Instruction

SIER[49:51] gives information on the source of the sampled
instruction like instruction came from primary, secondary,
tertiary cache or beyond.

SIER[52:55] provide information on branch type instructions
Like mispredict and cause of it.

SIER[56:59] provides information on translation and also
source of translation like TLB, secondary cache, tertiary
or beyond

SIER[60:62] provides the interesting data on the storage
access like L1/l2/L3... so on.

Most of these could be plumbed out through standard mechanisms
and it's all the other bits that are more interesting, but
these are not architected and not public.

Like wise, MMCRA (Monitor Mode Control Register A) is a
configuration register for sampling and thresholding events.
Provide data on various event configuration information.

Link to the PowerISA v2.07 and Chapters 9 describes in
detail on these registers.

https://www.power.org/wp-content/uploads/2013/05/PowerISA_V2.07_PUBLIC.pdf

Maddy








Re: [PATCH 01/13] perf/core: Add perf_arch_regs and mask to perf_regs structure

2016-09-08 Thread Madhavan Srinivasan



On Tuesday 06 September 2016 02:40 PM, Peter Zijlstra wrote:

On Tue, Sep 06, 2016 at 09:55:43AM +0530, Madhavan Srinivasan wrote:


On Thursday 01 September 2016 12:56 PM, Peter Zijlstra wrote:

On Mon, Aug 29, 2016 at 02:30:46AM +0530, Madhavan Srinivasan wrote:

It's a perennial request from hardware folks to be able to
see the raw values of the pmu registers. Partly it's so that
they can verify perf is doing what they want, and some
of it is that they're interested in some of the more obscure
info that isn't plumbed out through other perf interfaces.

How much and what is that? Can't we try and get interfaces sorted?

We have bunch of registers which exports information regarding the
sampled instruction like SIER/SIAR/SDAR/MMCRA. Lot of bits in these
registers are not yet architected and incase of SIER register, some of
the bits are not plumbed out and we are working on getting some these
exposed via perf.

What kind of information is this? I'm not familiar with the Power PMU
all that much, so you'll have to spell it out, not just mention the
registers its stuffed in.



Sure. When we profile for sample events,
SIER (Sampled Instruction Event Register) provides additional
information about the sampled event when PMI occurred.

SIER [41:42] indicates whether the SIAR(Sampled instruction address 
registers)

and SDAR (Sampled data address register) are valid for the sampled event.

SIER [46:48] indicates the type of intructions,

001 Load Instruction
010 Store instruction
011 Branch Instruction
100 Floating Point Instruction other than a Load or Store instruction
101 Fixed Point Instruction other than a Load or Store instruction
110 Condition Register or System Call Instruction

SIER[49:51] gives information on the source of the sampled
instruction like instruction came from primary, secondary,
tertiary cache or beyond.

SIER[52:55] provide information on branch type instructions
Like mispredict and cause of it.

SIER[56:59] provides information on translation and also
source of translation like TLB, secondary cache, tertiary
or beyond

SIER[60:62] provides the interesting data on the storage
access like L1/l2/L3... so on.

Most of these could be plumbed out through standard mechanisms
and it's all the other bits that are more interesting, but
these are not architected and not public.

Like wise, MMCRA (Monitor Mode Control Register A) is a
configuration register for sampling and thresholding events.
Provide data on various event configuration information.

Link to the PowerISA v2.07 and Chapters 9 describes in
detail on these registers.

https://www.power.org/wp-content/uploads/2013/05/PowerISA_V2.07_PUBLIC.pdf

Maddy








Re: [PATCH 01/13] perf/core: Add perf_arch_regs and mask to perf_regs structure

2016-09-05 Thread Madhavan Srinivasan



On Thursday 01 September 2016 12:56 PM, Peter Zijlstra wrote:

On Mon, Aug 29, 2016 at 02:30:46AM +0530, Madhavan Srinivasan wrote:

It's a perennial request from hardware folks to be able to
see the raw values of the pmu registers. Partly it's so that
they can verify perf is doing what they want, and some
of it is that they're interested in some of the more obscure
info that isn't plumbed out through other perf interfaces.

How much and what is that? Can't we try and get interfaces sorted?


We have bunch of registers which exports information regarding the
sampled instruction like SIER/SIAR/SDAR/MMCRA. Lot of bits in these
registers are not yet architected and incase of SIER register, some of
the bits are not plumbed out and we are working on getting some these
exposed via perf.




Over the years internally have used various hack to get
the requested data out but this is an attempt to use a
somewhat standard mechanism (using PERF_SAMPLE_REGS_INTR).

Not really liking that. It assumes too much and doesn't seem to cover
about half the perf use-cases.

It assumes the machine state can be captured by registers (this is false
for things like Intel DS/PT, which have state in memory), it might
assume <= 64 registers but I didn't look that closely, this too might
become somewhat restrictive.

Worse, it doesn't work for !sampling workloads, of which you also very
much want to verify programming etc.


Yes, I agree, my bad. I did assume and implemented considering
pmu registers primarily, but we can extend with additional flags
on the content being copied. Good point that patchset not handling
!sampling case. Let me explore on this and also the tracing options.

Thanks for the comments.
Maddy




This would also be helpful for those of us working on the perf
hardware backends, to be able to verify that we're programming
things correctly, without resorting to debug printks etc.

On x86 we can trace the MSR writes. No need to add debug printk()s.
We could (and I have on occasion) added tracepoints (well trace_printk)
to the Intel DS memory stores to see what was written there.

Tracing is much more flexible for debugging this stuff.

Can't you do something along those lines?





Re: [PATCH 01/13] perf/core: Add perf_arch_regs and mask to perf_regs structure

2016-09-05 Thread Madhavan Srinivasan



On Thursday 01 September 2016 12:56 PM, Peter Zijlstra wrote:

On Mon, Aug 29, 2016 at 02:30:46AM +0530, Madhavan Srinivasan wrote:

It's a perennial request from hardware folks to be able to
see the raw values of the pmu registers. Partly it's so that
they can verify perf is doing what they want, and some
of it is that they're interested in some of the more obscure
info that isn't plumbed out through other perf interfaces.

How much and what is that? Can't we try and get interfaces sorted?


We have bunch of registers which exports information regarding the
sampled instruction like SIER/SIAR/SDAR/MMCRA. Lot of bits in these
registers are not yet architected and incase of SIER register, some of
the bits are not plumbed out and we are working on getting some these
exposed via perf.




Over the years internally have used various hack to get
the requested data out but this is an attempt to use a
somewhat standard mechanism (using PERF_SAMPLE_REGS_INTR).

Not really liking that. It assumes too much and doesn't seem to cover
about half the perf use-cases.

It assumes the machine state can be captured by registers (this is false
for things like Intel DS/PT, which have state in memory), it might
assume <= 64 registers but I didn't look that closely, this too might
become somewhat restrictive.

Worse, it doesn't work for !sampling workloads, of which you also very
much want to verify programming etc.


Yes, I agree, my bad. I did assume and implemented considering
pmu registers primarily, but we can extend with additional flags
on the content being copied. Good point that patchset not handling
!sampling case. Let me explore on this and also the tracing options.

Thanks for the comments.
Maddy




This would also be helpful for those of us working on the perf
hardware backends, to be able to verify that we're programming
things correctly, without resorting to debug printks etc.

On x86 we can trace the MSR writes. No need to add debug printk()s.
We could (and I have on occasion) added tracepoints (well trace_printk)
to the Intel DS memory stores to see what was written there.

Tracing is much more flexible for debugging this stuff.

Can't you do something along those lines?





Re: [PATCH 04/13] perf/core: Extend perf_output_sample_regs() to include perf_arch_regs

2016-08-31 Thread Madhavan Srinivasan



On Tuesday 30 August 2016 09:41 PM, Nilay Vaish wrote:

On 28 August 2016 at 16:00, Madhavan Srinivasan
<ma...@linux.vnet.ibm.com> wrote:

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 274288819829..e16bf4d057d1 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5371,16 +5371,24 @@ u64 __attribute__((weak)) perf_arch_reg_value(struct 
perf_arch_regs *regs,

  static void
  perf_output_sample_regs(struct perf_output_handle *handle,
-   struct pt_regs *regs, u64 mask)
+   struct perf_regs *regs, u64 mask)
  {
 int bit;
 DECLARE_BITMAP(_mask, 64);
+   u64 arch_regs_mask = regs->arch_regs_mask;

 bitmap_from_u64(_mask, mask);
 for_each_set_bit(bit, _mask, sizeof(mask) * BITS_PER_BYTE) {
 u64 val;

-   val = perf_reg_value(regs, bit);
+   val = perf_reg_value(regs->regs, bit);
+   perf_output_put(handle, val);
+   }
+
+   bitmap_from_u64(_mask, arch_regs_mask);
+   for_each_set_bit(bit, _mask, sizeof(mask) * BITS_PER_BYTE) {
+   u64 val;
+   val = perf_arch_reg_value(regs->arch_regs, bit);
 perf_output_put(handle, val);
 }
  }
@@ -5792,7 +5800,7 @@ void perf_output_sample(struct perf_output_handle *handle,
 if (abi) {
 u64 mask = event->attr.sample_regs_user;
 perf_output_sample_regs(handle,
-   data->regs_user.regs,
+   >regs_user,
 mask);
 }
 }
@@ -5827,7 +5835,7 @@ void perf_output_sample(struct perf_output_handle *handle,
 u64 mask = event->attr.sample_regs_intr;

 perf_output_sample_regs(handle,
-   data->regs_intr.regs,
+   >regs_intr,
 mask);
 }
 }
--
2.7.4


I would like to suggest a slightly different version.  Would it make
more sense to have something like following:


I agree we are outputting two different structures, but since we use the
INTR_REG infrastructure to dump the arch pmu registers, I preferred to
extend perf_output_sample_regs. But I guess I can break it up.

Maddy



@@ -5792,7 +5800,7 @@ void perf_output_sample(struct perf_output_handle *handle,
  if (abi) {
 u64 mask = event->attr.sample_regs_user;
 perf_output_sample_regs(handle,
 data->regs_user.regs,
 mask);
 }
+
+  if (arch_regs_mask) {
+   perf_output_pmu_regs(handle,
data->regs_users.arch_regs, arch_regs_mask);
+  }
 }


Somehow I don't like outputting the two sets of registers through the
same function call.

--
Nilay





Re: [PATCH 04/13] perf/core: Extend perf_output_sample_regs() to include perf_arch_regs

2016-08-31 Thread Madhavan Srinivasan



On Tuesday 30 August 2016 09:41 PM, Nilay Vaish wrote:

On 28 August 2016 at 16:00, Madhavan Srinivasan
 wrote:

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 274288819829..e16bf4d057d1 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5371,16 +5371,24 @@ u64 __attribute__((weak)) perf_arch_reg_value(struct 
perf_arch_regs *regs,

  static void
  perf_output_sample_regs(struct perf_output_handle *handle,
-   struct pt_regs *regs, u64 mask)
+   struct perf_regs *regs, u64 mask)
  {
 int bit;
 DECLARE_BITMAP(_mask, 64);
+   u64 arch_regs_mask = regs->arch_regs_mask;

 bitmap_from_u64(_mask, mask);
 for_each_set_bit(bit, _mask, sizeof(mask) * BITS_PER_BYTE) {
 u64 val;

-   val = perf_reg_value(regs, bit);
+   val = perf_reg_value(regs->regs, bit);
+   perf_output_put(handle, val);
+   }
+
+   bitmap_from_u64(_mask, arch_regs_mask);
+   for_each_set_bit(bit, _mask, sizeof(mask) * BITS_PER_BYTE) {
+   u64 val;
+   val = perf_arch_reg_value(regs->arch_regs, bit);
 perf_output_put(handle, val);
 }
  }
@@ -5792,7 +5800,7 @@ void perf_output_sample(struct perf_output_handle *handle,
 if (abi) {
 u64 mask = event->attr.sample_regs_user;
 perf_output_sample_regs(handle,
-   data->regs_user.regs,
+   >regs_user,
 mask);
 }
 }
@@ -5827,7 +5835,7 @@ void perf_output_sample(struct perf_output_handle *handle,
 u64 mask = event->attr.sample_regs_intr;

 perf_output_sample_regs(handle,
-   data->regs_intr.regs,
+   >regs_intr,
 mask);
 }
 }
--
2.7.4


I would like to suggest a slightly different version.  Would it make
more sense to have something like following:


I agree we are outputting two different structures, but since we use the
INTR_REG infrastructure to dump the arch pmu registers, I preferred to
extend perf_output_sample_regs. But I guess I can break it up.

Maddy



@@ -5792,7 +5800,7 @@ void perf_output_sample(struct perf_output_handle *handle,
  if (abi) {
 u64 mask = event->attr.sample_regs_user;
 perf_output_sample_regs(handle,
 data->regs_user.regs,
 mask);
 }
+
+  if (arch_regs_mask) {
+   perf_output_pmu_regs(handle,
data->regs_users.arch_regs, arch_regs_mask);
+  }
 }


Somehow I don't like outputting the two sets of registers through the
same function call.

--
Nilay





Re: [PATCH 00/13] Add support for perf_arch_regs

2016-08-31 Thread Madhavan Srinivasan



On Tuesday 30 August 2016 09:31 PM, Nilay Vaish wrote:

On 28 August 2016 at 16:00, Madhavan Srinivasan
<ma...@linux.vnet.ibm.com> wrote:

Patchset to extend PERF_SAMPLE_REGS_INTR to include
platform specific PMU registers.

Patchset applies cleanly on tip:perf/core branch

It's a perennial request from hardware folks to be able to
see the raw values of the pmu registers. Partly it's so that
they can verify perf is doing what they want, and some
of it is that they're interested in some of the more obscure
info that isn't plumbed out through other perf interfaces.

Over the years internally we have used various hack to get
the requested data out but this is an attempt to use a
somewhat standard mechanism (using PERF_SAMPLE_REGS_INTR).

This would also be helpful for those of us working on the perf
hardware backends, to be able to verify that we're programming
things correctly, without resorting to debug printks etc.

Mechanism proposed:

1)perf_regs structure is extended with a perf_arch_regs structure
which each arch/ can populate with their specific platform
registers to sample on each perf interrupt and an arch_regs_mask
variable, which is for perf tool to know about the perf_arch_regs
that are supported.

2)perf/core func perf_sample_regs_intr() extended to update
the perf_arch_regs structure and the perf_arch_reg_mask. Set of new
support functions added perf_get_arch_regs_mask() and
perf_get_arch_reg() to aid the updates from arch/ side.

3) perf/core funcs perf_prepare_sample() and perf_output_sample()
are extended to support the update for the perf_arch_regs_mask and
perf_arch_regs in the sample

4)perf/core func perf_output_sample_regs() extended to dump
the arch_regs to the output sample.

5)Finally, perf tool side is updated to include a new element
"arch_regs_mask" in the "struct regs_dump", event sample funcs
and print functions are updated to support perf_arch_regs.


I read the patch series and I have one suggestion to make.  I think we
should not use 'arch regs' to refer to these pmu registers.  I think

Reason is that they are arch specific pmu regs. But I guess we can go with
pmu_regs also. And having a "pregs" as option to list in -I? will be fine?
(patch 13 in the patch series)


Maddy


architectural registers typically refer to the ones that hold the
state of the process.  Can we replace arch_regs by pmu_regs, or some
other choice?

Thanks
Nilay





Re: [PATCH 00/13] Add support for perf_arch_regs

2016-08-31 Thread Madhavan Srinivasan



On Tuesday 30 August 2016 09:31 PM, Nilay Vaish wrote:

On 28 August 2016 at 16:00, Madhavan Srinivasan
 wrote:

Patchset to extend PERF_SAMPLE_REGS_INTR to include
platform specific PMU registers.

Patchset applies cleanly on tip:perf/core branch

It's a perennial request from hardware folks to be able to
see the raw values of the pmu registers. Partly it's so that
they can verify perf is doing what they want, and some
of it is that they're interested in some of the more obscure
info that isn't plumbed out through other perf interfaces.

Over the years internally we have used various hack to get
the requested data out but this is an attempt to use a
somewhat standard mechanism (using PERF_SAMPLE_REGS_INTR).

This would also be helpful for those of us working on the perf
hardware backends, to be able to verify that we're programming
things correctly, without resorting to debug printks etc.

Mechanism proposed:

1)perf_regs structure is extended with a perf_arch_regs structure
which each arch/ can populate with their specific platform
registers to sample on each perf interrupt and an arch_regs_mask
variable, which is for perf tool to know about the perf_arch_regs
that are supported.

2)perf/core func perf_sample_regs_intr() extended to update
the perf_arch_regs structure and the perf_arch_reg_mask. Set of new
support functions added perf_get_arch_regs_mask() and
perf_get_arch_reg() to aid the updates from arch/ side.

3) perf/core funcs perf_prepare_sample() and perf_output_sample()
are extended to support the update for the perf_arch_regs_mask and
perf_arch_regs in the sample

4)perf/core func perf_output_sample_regs() extended to dump
the arch_regs to the output sample.

5)Finally, perf tool side is updated to include a new element
"arch_regs_mask" in the "struct regs_dump", event sample funcs
and print functions are updated to support perf_arch_regs.


I read the patch series and I have one suggestion to make.  I think we
should not use 'arch regs' to refer to these pmu registers.  I think

Reason is that they are arch specific pmu regs. But I guess we can go with
pmu_regs also. And having a "pregs" as option to list in -I? will be fine?
(patch 13 in the patch series)


Maddy


architectural registers typically refer to the ones that hold the
state of the process.  Can we replace arch_regs by pmu_regs, or some
other choice?

Thanks
Nilay





[PATCH 13/13] powerpc/perf: Add support to dump only arch_regs

2016-08-28 Thread Madhavan Srinivasan
perf tool provides us an option to selective dump intr_regs.
Add arch_regs option to it.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Arnaldo Carvalho de Melo <a...@kernel.org>
Cc: Stephane Eranian <eran...@gmail.com>
Cc: Russell King <li...@arm.linux.org.uk>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
Cc: Benjamin Herrenschmidt <b...@kernel.crashing.org>
Cc: Michael Ellerman <m...@ellerman.id.au>
Cc: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>
Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
 arch/powerpc/include/uapi/asm/perf_regs.h   | 1 +
 arch/powerpc/perf/perf_regs.c   | 3 +++
 tools/arch/powerpc/include/uapi/asm/perf_regs.h | 1 +
 tools/perf/arch/powerpc/include/perf_regs.h | 3 ++-
 tools/perf/arch/powerpc/util/perf_regs.c| 1 +
 5 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/include/uapi/asm/perf_regs.h 
b/arch/powerpc/include/uapi/asm/perf_regs.h
index e8f5553a61d1..cbf1c7521ea5 100644
--- a/arch/powerpc/include/uapi/asm/perf_regs.h
+++ b/arch/powerpc/include/uapi/asm/perf_regs.h
@@ -45,6 +45,7 @@ enum perf_event_powerpc_regs {
PERF_REG_POWERPC_TRAP,
PERF_REG_POWERPC_DAR,
PERF_REG_POWERPC_DSISR,
+   PERF_REG_POWERPC_ARCH_REGS,
PERF_REG_POWERPC_MAX,
 };
 
diff --git a/arch/powerpc/perf/perf_regs.c b/arch/powerpc/perf/perf_regs.c
index d24a8a3668fa..eb51f47276ac 100644
--- a/arch/powerpc/perf/perf_regs.c
+++ b/arch/powerpc/perf/perf_regs.c
@@ -75,6 +75,9 @@ u64 perf_reg_value(struct pt_regs *regs, int idx)
if (WARN_ON_ONCE(idx >= PERF_REG_POWERPC_MAX))
return 0;
 
+   if (idx == PERF_REG_POWERPC_ARCH_REGS)
+   return perf_get_arch_regs_mask();
+
return regs_get_register(regs, pt_regs_offset[idx]);
 }
 
diff --git a/tools/arch/powerpc/include/uapi/asm/perf_regs.h 
b/tools/arch/powerpc/include/uapi/asm/perf_regs.h
index bf249a27aa36..d4ae8458af3d 100644
--- a/tools/arch/powerpc/include/uapi/asm/perf_regs.h
+++ b/tools/arch/powerpc/include/uapi/asm/perf_regs.h
@@ -45,6 +45,7 @@ enum perf_event_powerpc_regs {
PERF_REG_POWERPC_TRAP,
PERF_REG_POWERPC_DAR,
PERF_REG_POWERPC_DSISR,
+   PERF_REG_POWERPC_ARCH_REGS,
PERF_REG_POWERPC_MAX,
 };
 
diff --git a/tools/perf/arch/powerpc/include/perf_regs.h 
b/tools/perf/arch/powerpc/include/perf_regs.h
index 801de6def8da..699376afa77f 100644
--- a/tools/perf/arch/powerpc/include/perf_regs.h
+++ b/tools/perf/arch/powerpc/include/perf_regs.h
@@ -60,7 +60,8 @@ static const char *reg_names[] = {
[PERF_REG_POWERPC_SOFTE] = "softe",
[PERF_REG_POWERPC_TRAP] = "trap",
[PERF_REG_POWERPC_DAR] = "dar",
-   [PERF_REG_POWERPC_DSISR] = "dsisr"
+   [PERF_REG_POWERPC_DSISR] = "dsisr",
+   [PERF_REG_POWERPC_ARCH_REGS] = "arch_regs"
 };
 
 static inline const char *perf_reg_name(int id)
diff --git a/tools/perf/arch/powerpc/util/perf_regs.c 
b/tools/perf/arch/powerpc/util/perf_regs.c
index a3c3e1ce6807..bd5afa8506e5 100644
--- a/tools/perf/arch/powerpc/util/perf_regs.c
+++ b/tools/perf/arch/powerpc/util/perf_regs.c
@@ -45,5 +45,6 @@ const struct sample_reg sample_reg_masks[] = {
SMPL_REG(trap, PERF_REG_POWERPC_TRAP),
SMPL_REG(dar, PERF_REG_POWERPC_DAR),
SMPL_REG(dsisr, PERF_REG_POWERPC_DSISR),
+   SMPL_REG(arch_regs, PERF_REG_POWERPC_ARCH_REGS),
SMPL_REG_END
 };
-- 
2.7.4



[PATCH 11/13] tools/perf: Fix the mask in regs_dump__printf and print_sample_iregs

2016-08-28 Thread Madhavan Srinivasan
When decoding the perf_regs mask in regs_dump__printf(),
we loop through the mask using find_first_bit and find_next_bit functions.
"mask" is of type "u64", but sent as a "unsigned long *" to
lib functions along with sizeof().

While the exisitng code works fine in most of the case,
the logic is broken when using a 32bit perf on a 64bit kernel (Big Endian).
When reading u64 using (u32 *)()[0], perf (lib/find_*_bit()) assumes it gets
lower 32bits of u64 which is wrong. Proposed fix is to swap the words
of the u64 to handle this case. This is _not_ endianess swap.

Suggested-by: Yury Norov <yno...@caviumnetworks.com>
Reviewed-by: Yury Norov <yno...@caviumnetworks.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Yury Norov <yno...@caviumnetworks.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Ingo Molnar <mi...@redhat.com>
Cc: Arnaldo Carvalho de Melo <a...@kernel.org>
Cc: Alexander Shishkin <alexander.shish...@linux.intel.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Adrian Hunter <adrian.hun...@intel.com>
Cc: Kan Liang <kan.li...@intel.com>
Cc: Wang Nan <wangn...@huawei.com>
Cc: Michael Ellerman <m...@ellerman.id.au>
Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
Fix already posted, but yet to be pulled in. This is needed
for the subsequent patches.

https://patchwork.kernel.org/patch/9285421/

 tools/include/linux/bitmap.h |  2 ++
 tools/lib/bitmap.c   | 18 ++
 tools/perf/builtin-script.c  |  4 +++-
 tools/perf/util/session.c|  4 +++-
 4 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/tools/include/linux/bitmap.h b/tools/include/linux/bitmap.h
index 43c1c5021e4b..998ac95a8ddd 100644
--- a/tools/include/linux/bitmap.h
+++ b/tools/include/linux/bitmap.h
@@ -4,10 +4,12 @@
 #include 
 #include 
 #include 
+#include 
 
 #define DECLARE_BITMAP(name,bits) \
unsigned long name[BITS_TO_LONGS(bits)]
 
+void bitmap_from_u64(unsigned long *dst, u64 mask);
 int __bitmap_weight(const unsigned long *bitmap, int bits);
 void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
 const unsigned long *bitmap2, int bits);
diff --git a/tools/lib/bitmap.c b/tools/lib/bitmap.c
index 38748b0e342f..21e17730c35f 100644
--- a/tools/lib/bitmap.c
+++ b/tools/lib/bitmap.c
@@ -73,3 +73,21 @@ int __bitmap_and(unsigned long *dst, const unsigned long 
*bitmap1,
   BITMAP_LAST_WORD_MASK(bits));
return result != 0;
 }
+
+/*
+ * bitmap_from_u64 - Check and swap words within u64.
+ *  @mask: source bitmap
+ *  @dst:  destination bitmap
+ *
+ * In 32 bit big endian userspace on a 64bit kernel, 'unsigned long' is 32 
bits.
+ * When reading u64 using (u32 *)()[0] and (u32 *)()[1],
+ * we will get wrong value for the mask. That is "(u32 *)()[0]"
+ * gets upper 32 bits of u64, but perf may expect lower 32bits of u64.
+ */
+void bitmap_from_u64(unsigned long *dst, u64 mask)
+{
+   dst[0] = mask & ULONG_MAX;
+
+   if (sizeof(mask) > sizeof(unsigned long))
+   dst[1] = mask >> 32;
+}
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 6b3c8b0d3276..db270b4f892a 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -421,11 +421,13 @@ static void print_sample_iregs(struct perf_sample *sample,
struct regs_dump *regs = >intr_regs;
uint64_t mask = attr->sample_regs_intr;
unsigned i = 0, r;
+   DECLARE_BITMAP(_mask, 64);
 
if (!regs)
return;
 
-   for_each_set_bit(r, (unsigned long *) , sizeof(mask) * 8) {
+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(r, _mask, sizeof(mask) * 8) {
u64 val = regs->regs[i++];
printf("%5s:0x%"PRIx64" ", perf_reg_name(r), val);
}
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 5d61242a6e64..440a9fb2a6fb 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -944,8 +944,10 @@ static void branch_stack__printf(struct perf_sample 
*sample)
 static void regs_dump__printf(u64 mask, u64 *regs)
 {
unsigned rid, i = 0;
+   DECLARE_BITMAP(_mask, 64);
 
-   for_each_set_bit(rid, (unsigned long *) , sizeof(mask) * 8) {
+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(rid, _mask, sizeof(mask) * 8) {
u64 val = regs[i++];
 
printf(" %-5s 0x%" PRIx64 "\n",
-- 
2.7.4



[PATCH 13/13] powerpc/perf: Add support to dump only arch_regs

2016-08-28 Thread Madhavan Srinivasan
perf tool provides us an option to selective dump intr_regs.
Add arch_regs option to it.

Cc: Thomas Gleixner 
Cc: Ingo Molnar 
Cc: Peter Zijlstra 
Cc: Jiri Olsa 
Cc: Arnaldo Carvalho de Melo 
Cc: Stephane Eranian 
Cc: Russell King 
Cc: Catalin Marinas 
Cc: Will Deacon 
Cc: Benjamin Herrenschmidt 
Cc: Michael Ellerman 
Cc: Sukadev Bhattiprolu 
Signed-off-by: Madhavan Srinivasan 
---
 arch/powerpc/include/uapi/asm/perf_regs.h   | 1 +
 arch/powerpc/perf/perf_regs.c   | 3 +++
 tools/arch/powerpc/include/uapi/asm/perf_regs.h | 1 +
 tools/perf/arch/powerpc/include/perf_regs.h | 3 ++-
 tools/perf/arch/powerpc/util/perf_regs.c| 1 +
 5 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/include/uapi/asm/perf_regs.h 
b/arch/powerpc/include/uapi/asm/perf_regs.h
index e8f5553a61d1..cbf1c7521ea5 100644
--- a/arch/powerpc/include/uapi/asm/perf_regs.h
+++ b/arch/powerpc/include/uapi/asm/perf_regs.h
@@ -45,6 +45,7 @@ enum perf_event_powerpc_regs {
PERF_REG_POWERPC_TRAP,
PERF_REG_POWERPC_DAR,
PERF_REG_POWERPC_DSISR,
+   PERF_REG_POWERPC_ARCH_REGS,
PERF_REG_POWERPC_MAX,
 };
 
diff --git a/arch/powerpc/perf/perf_regs.c b/arch/powerpc/perf/perf_regs.c
index d24a8a3668fa..eb51f47276ac 100644
--- a/arch/powerpc/perf/perf_regs.c
+++ b/arch/powerpc/perf/perf_regs.c
@@ -75,6 +75,9 @@ u64 perf_reg_value(struct pt_regs *regs, int idx)
if (WARN_ON_ONCE(idx >= PERF_REG_POWERPC_MAX))
return 0;
 
+   if (idx == PERF_REG_POWERPC_ARCH_REGS)
+   return perf_get_arch_regs_mask();
+
return regs_get_register(regs, pt_regs_offset[idx]);
 }
 
diff --git a/tools/arch/powerpc/include/uapi/asm/perf_regs.h 
b/tools/arch/powerpc/include/uapi/asm/perf_regs.h
index bf249a27aa36..d4ae8458af3d 100644
--- a/tools/arch/powerpc/include/uapi/asm/perf_regs.h
+++ b/tools/arch/powerpc/include/uapi/asm/perf_regs.h
@@ -45,6 +45,7 @@ enum perf_event_powerpc_regs {
PERF_REG_POWERPC_TRAP,
PERF_REG_POWERPC_DAR,
PERF_REG_POWERPC_DSISR,
+   PERF_REG_POWERPC_ARCH_REGS,
PERF_REG_POWERPC_MAX,
 };
 
diff --git a/tools/perf/arch/powerpc/include/perf_regs.h 
b/tools/perf/arch/powerpc/include/perf_regs.h
index 801de6def8da..699376afa77f 100644
--- a/tools/perf/arch/powerpc/include/perf_regs.h
+++ b/tools/perf/arch/powerpc/include/perf_regs.h
@@ -60,7 +60,8 @@ static const char *reg_names[] = {
[PERF_REG_POWERPC_SOFTE] = "softe",
[PERF_REG_POWERPC_TRAP] = "trap",
[PERF_REG_POWERPC_DAR] = "dar",
-   [PERF_REG_POWERPC_DSISR] = "dsisr"
+   [PERF_REG_POWERPC_DSISR] = "dsisr",
+   [PERF_REG_POWERPC_ARCH_REGS] = "arch_regs"
 };
 
 static inline const char *perf_reg_name(int id)
diff --git a/tools/perf/arch/powerpc/util/perf_regs.c 
b/tools/perf/arch/powerpc/util/perf_regs.c
index a3c3e1ce6807..bd5afa8506e5 100644
--- a/tools/perf/arch/powerpc/util/perf_regs.c
+++ b/tools/perf/arch/powerpc/util/perf_regs.c
@@ -45,5 +45,6 @@ const struct sample_reg sample_reg_masks[] = {
SMPL_REG(trap, PERF_REG_POWERPC_TRAP),
SMPL_REG(dar, PERF_REG_POWERPC_DAR),
SMPL_REG(dsisr, PERF_REG_POWERPC_DSISR),
+   SMPL_REG(arch_regs, PERF_REG_POWERPC_ARCH_REGS),
SMPL_REG_END
 };
-- 
2.7.4



[PATCH 11/13] tools/perf: Fix the mask in regs_dump__printf and print_sample_iregs

2016-08-28 Thread Madhavan Srinivasan
When decoding the perf_regs mask in regs_dump__printf(),
we loop through the mask using find_first_bit and find_next_bit functions.
"mask" is of type "u64", but sent as a "unsigned long *" to
lib functions along with sizeof().

While the exisitng code works fine in most of the case,
the logic is broken when using a 32bit perf on a 64bit kernel (Big Endian).
When reading u64 using (u32 *)()[0], perf (lib/find_*_bit()) assumes it gets
lower 32bits of u64 which is wrong. Proposed fix is to swap the words
of the u64 to handle this case. This is _not_ endianess swap.

Suggested-by: Yury Norov 
Reviewed-by: Yury Norov 
Acked-by: Jiri Olsa 
Cc: Yury Norov 
Cc: Peter Zijlstra 
Cc: Ingo Molnar 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexander Shishkin 
Cc: Jiri Olsa 
Cc: Adrian Hunter 
Cc: Kan Liang 
Cc: Wang Nan 
Cc: Michael Ellerman 
Signed-off-by: Madhavan Srinivasan 
---
Fix already posted, but yet to be pulled in. This is needed
for the subsequent patches.

https://patchwork.kernel.org/patch/9285421/

 tools/include/linux/bitmap.h |  2 ++
 tools/lib/bitmap.c   | 18 ++
 tools/perf/builtin-script.c  |  4 +++-
 tools/perf/util/session.c|  4 +++-
 4 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/tools/include/linux/bitmap.h b/tools/include/linux/bitmap.h
index 43c1c5021e4b..998ac95a8ddd 100644
--- a/tools/include/linux/bitmap.h
+++ b/tools/include/linux/bitmap.h
@@ -4,10 +4,12 @@
 #include 
 #include 
 #include 
+#include 
 
 #define DECLARE_BITMAP(name,bits) \
unsigned long name[BITS_TO_LONGS(bits)]
 
+void bitmap_from_u64(unsigned long *dst, u64 mask);
 int __bitmap_weight(const unsigned long *bitmap, int bits);
 void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
 const unsigned long *bitmap2, int bits);
diff --git a/tools/lib/bitmap.c b/tools/lib/bitmap.c
index 38748b0e342f..21e17730c35f 100644
--- a/tools/lib/bitmap.c
+++ b/tools/lib/bitmap.c
@@ -73,3 +73,21 @@ int __bitmap_and(unsigned long *dst, const unsigned long 
*bitmap1,
   BITMAP_LAST_WORD_MASK(bits));
return result != 0;
 }
+
+/*
+ * bitmap_from_u64 - Check and swap words within u64.
+ *  @mask: source bitmap
+ *  @dst:  destination bitmap
+ *
+ * In 32 bit big endian userspace on a 64bit kernel, 'unsigned long' is 32 
bits.
+ * When reading u64 using (u32 *)()[0] and (u32 *)()[1],
+ * we will get wrong value for the mask. That is "(u32 *)()[0]"
+ * gets upper 32 bits of u64, but perf may expect lower 32bits of u64.
+ */
+void bitmap_from_u64(unsigned long *dst, u64 mask)
+{
+   dst[0] = mask & ULONG_MAX;
+
+   if (sizeof(mask) > sizeof(unsigned long))
+   dst[1] = mask >> 32;
+}
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 6b3c8b0d3276..db270b4f892a 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -421,11 +421,13 @@ static void print_sample_iregs(struct perf_sample *sample,
struct regs_dump *regs = >intr_regs;
uint64_t mask = attr->sample_regs_intr;
unsigned i = 0, r;
+   DECLARE_BITMAP(_mask, 64);
 
if (!regs)
return;
 
-   for_each_set_bit(r, (unsigned long *) , sizeof(mask) * 8) {
+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(r, _mask, sizeof(mask) * 8) {
u64 val = regs->regs[i++];
printf("%5s:0x%"PRIx64" ", perf_reg_name(r), val);
}
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 5d61242a6e64..440a9fb2a6fb 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -944,8 +944,10 @@ static void branch_stack__printf(struct perf_sample 
*sample)
 static void regs_dump__printf(u64 mask, u64 *regs)
 {
unsigned rid, i = 0;
+   DECLARE_BITMAP(_mask, 64);
 
-   for_each_set_bit(rid, (unsigned long *) , sizeof(mask) * 8) {
+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(rid, _mask, sizeof(mask) * 8) {
u64 val = regs[i++];
 
printf(" %-5s 0x%" PRIx64 "\n",
-- 
2.7.4



[PATCH 08/13] powerpc/perf: Add support for perf_arch_regs for newer Power processor

2016-08-28 Thread Madhavan Srinivasan
Add code to define support functions and registers mask for
Power8 and later processor.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Arnaldo Carvalho de Melo <a...@kernel.org>
Cc: Stephane Eranian <eran...@gmail.com>
Cc: Russell King <li...@arm.linux.org.uk>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
Cc: Benjamin Herrenschmidt <b...@kernel.crashing.org>
Cc: Michael Ellerman <m...@ellerman.id.au>
Cc: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>
Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
 arch/powerpc/perf/isa207-common.c | 18 ++
 arch/powerpc/perf/isa207-common.h | 10 ++
 arch/powerpc/perf/power8-pmu.c|  2 ++
 arch/powerpc/perf/power9-pmu.c|  2 ++
 4 files changed, 32 insertions(+)

diff --git a/arch/powerpc/perf/isa207-common.c 
b/arch/powerpc/perf/isa207-common.c
index 6143c99f3ec5..43931c695ecb 100644
--- a/arch/powerpc/perf/isa207-common.c
+++ b/arch/powerpc/perf/isa207-common.c
@@ -261,3 +261,21 @@ void isa207_disable_pmc(unsigned int pmc, unsigned long 
mmcr[])
if (pmc <= 3)
mmcr[1] &= ~(0xffUL << MMCR1_PMCSEL_SHIFT(pmc + 1));
 }
+
+void isa207_get_arch_regs(struct perf_arch_regs *regs)
+{
+   regs->regs[PERF_ARCH_REG_POWERPC_PVR] = mfspr(SPRN_PVR);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC1] = mfspr(SPRN_PMC1);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC2] = mfspr(SPRN_PMC2);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC3] = mfspr(SPRN_PMC3);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC4] = mfspr(SPRN_PMC4);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC5] = mfspr(SPRN_PMC5);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC6] = mfspr(SPRN_PMC6);
+   regs->regs[PERF_ARCH_REG_POWERPC_MMCR0] = mfspr(SPRN_MMCR0);
+   regs->regs[PERF_ARCH_REG_POWERPC_MMCR1] = mfspr(SPRN_MMCR1);
+   regs->regs[PERF_ARCH_REG_POWERPC_SIER] = mfspr(SPRN_SIER);
+   regs->regs[PERF_ARCH_REG_POWERPC_SIAR] = mfspr(SPRN_SIAR);
+   regs->regs[PERF_ARCH_REG_POWERPC_SDAR] = mfspr(SPRN_SDAR);
+   regs->regs[PERF_ARCH_REG_POWERPC_MMCRA] = mfspr(SPRN_MMCRA);
+   regs->regs[PERF_ARCH_REG_POWERPC_MMCR2] = mfspr(SPRN_MMCR2);
+}
diff --git a/arch/powerpc/perf/isa207-common.h 
b/arch/powerpc/perf/isa207-common.h
index 4d0a4e5017c2..94bf8dd548ac 100644
--- a/arch/powerpc/perf/isa207-common.h
+++ b/arch/powerpc/perf/isa207-common.h
@@ -16,6 +16,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /*
  * Raw event encoding for PowerISA v2.07:
@@ -227,10 +228,19 @@
 #define MAX_ALT2
 #define MAX_PMU_COUNTERS   6
 
+#defineISA207_ARCH_REGS_MASK  (PERF_ARCH_REG_PVR |\
+   PERF_ARCH_REG_PMC1 | PERF_ARCH_REG_PMC2 |\
+   PERF_ARCH_REG_PMC3 | PERF_ARCH_REG_PMC4 |\
+   PERF_ARCH_REG_PMC5 | PERF_ARCH_REG_PMC6 |\
+   PERF_ARCH_REG_MMCR0 | PERF_ARCH_REG_MMCR1 |\
+   PERF_ARCH_REG_SIER | PERF_ARCH_REG_SIAR |\
+   PERF_ARCH_REG_SDAR | PERF_ARCH_REG_MMCRA | PERF_ARCH_REG_MMCR2)
+
 int isa207_get_constraint(u64 event, unsigned long *maskp, unsigned long 
*valp);
 int isa207_compute_mmcr(u64 event[], int n_ev,
unsigned int hwc[], unsigned long mmcr[],
struct perf_event *pevents[]);
 void isa207_disable_pmc(unsigned int pmc, unsigned long mmcr[]);
+void isa207_get_arch_regs(struct perf_arch_regs *regs);
 
 #endif
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index 5fde2b192fec..8c8bc5083eb2 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -394,6 +394,8 @@ static struct power_pmu power8_pmu = {
.cache_events   = _cache_events,
.attr_groups= power8_pmu_attr_groups,
.bhrb_nr= 32,
+   .ar_mask= ISA207_ARCH_REGS_MASK,
+   .get_arch_regs  = isa207_get_arch_regs,
 };
 
 static int __init init_power8_pmu(void)
diff --git a/arch/powerpc/perf/power9-pmu.c b/arch/powerpc/perf/power9-pmu.c
index 788346303852..1e66ec36b90f 100644
--- a/arch/powerpc/perf/power9-pmu.c
+++ b/arch/powerpc/perf/power9-pmu.c
@@ -307,6 +307,8 @@ static struct power_pmu power9_pmu = {
.cache_events   = _cache_events,
.attr_groups= power9_pmu_attr_groups,
.bhrb_nr= 32,
+   .ar_mask= ISA207_ARCH_REGS_MASK,
+   .get_arch_regs  = isa207_get_arch_regs,
 };
 
 static int __init init_power9_pmu(void)
-- 
2.7.4



[PATCH 07/13] powerpc/perf: Add support for perf_arch_regs for Power7 processor

2016-08-28 Thread Madhavan Srinivasan
Add code to define support functions and registers mask for
Power7 processor.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Arnaldo Carvalho de Melo <a...@kernel.org>
Cc: Stephane Eranian <eran...@gmail.com>
Cc: Russell King <li...@arm.linux.org.uk>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
Cc: Benjamin Herrenschmidt <b...@kernel.crashing.org>
Cc: Michael Ellerman <m...@ellerman.id.au>
Cc: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>
Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
 arch/powerpc/perf/power7-pmu.c | 28 
 1 file changed, 28 insertions(+)

diff --git a/arch/powerpc/perf/power7-pmu.c b/arch/powerpc/perf/power7-pmu.c
index a383c23a9070..1eac466d4881 100644
--- a/arch/powerpc/perf/power7-pmu.c
+++ b/arch/powerpc/perf/power7-pmu.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /*
  * Bits in event code for POWER7
@@ -427,6 +428,31 @@ static const struct attribute_group 
*power7_pmu_attr_groups[] = {
NULL,
 };
 
+#define POWER7_ARCH_REGS_MASK  (PERF_ARCH_REG_PVR |\
+   PERF_ARCH_REG_PMC1 | PERF_ARCH_REG_PMC2 |\
+   PERF_ARCH_REG_PMC3 | PERF_ARCH_REG_PMC4 |\
+   PERF_ARCH_REG_PMC5 | PERF_ARCH_REG_PMC6 |\
+   PERF_ARCH_REG_MMCR0 | PERF_ARCH_REG_MMCR1 |\
+   PERF_ARCH_REG_SIER | PERF_ARCH_REG_SIAR |\
+   PERF_ARCH_REG_SDAR | PERF_ARCH_REG_MMCRA)
+
+static void power7_get_arch_regs(struct perf_arch_regs *regs)
+{
+   regs->regs[PERF_ARCH_REG_POWERPC_PVR] = mfspr(SPRN_PVR);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC1] = mfspr(SPRN_PMC1);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC2] = mfspr(SPRN_PMC2);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC3] = mfspr(SPRN_PMC3);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC4] = mfspr(SPRN_PMC4);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC5] = mfspr(SPRN_PMC5);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC6] = mfspr(SPRN_PMC6);
+   regs->regs[PERF_ARCH_REG_POWERPC_MMCR0] = mfspr(SPRN_MMCR0);
+   regs->regs[PERF_ARCH_REG_POWERPC_MMCR1] = mfspr(SPRN_MMCR1);
+   regs->regs[PERF_ARCH_REG_POWERPC_SIER] = mfspr(SPRN_SIER);
+   regs->regs[PERF_ARCH_REG_POWERPC_SIAR] = mfspr(SPRN_SIAR);
+   regs->regs[PERF_ARCH_REG_POWERPC_SDAR] = mfspr(SPRN_SDAR);
+   regs->regs[PERF_ARCH_REG_POWERPC_MMCRA] = mfspr(SPRN_MMCRA);
+}
+
 static struct power_pmu power7_pmu = {
.name   = "POWER7",
.n_counter  = 6,
@@ -442,6 +468,8 @@ static struct power_pmu power7_pmu = {
.n_generic  = ARRAY_SIZE(power7_generic_events),
.generic_events = power7_generic_events,
.cache_events   = _cache_events,
+   .ar_mask= POWER7_ARCH_REGS_MASK,
+   .get_arch_regs  = power7_get_arch_regs,
 };
 
 static int __init init_power7_pmu(void)
-- 
2.7.4



[PATCH 08/13] powerpc/perf: Add support for perf_arch_regs for newer Power processor

2016-08-28 Thread Madhavan Srinivasan
Add code to define support functions and registers mask for
Power8 and later processor.

Cc: Thomas Gleixner 
Cc: Ingo Molnar 
Cc: Peter Zijlstra 
Cc: Jiri Olsa 
Cc: Arnaldo Carvalho de Melo 
Cc: Stephane Eranian 
Cc: Russell King 
Cc: Catalin Marinas 
Cc: Will Deacon 
Cc: Benjamin Herrenschmidt 
Cc: Michael Ellerman 
Cc: Sukadev Bhattiprolu 
Signed-off-by: Madhavan Srinivasan 
---
 arch/powerpc/perf/isa207-common.c | 18 ++
 arch/powerpc/perf/isa207-common.h | 10 ++
 arch/powerpc/perf/power8-pmu.c|  2 ++
 arch/powerpc/perf/power9-pmu.c|  2 ++
 4 files changed, 32 insertions(+)

diff --git a/arch/powerpc/perf/isa207-common.c 
b/arch/powerpc/perf/isa207-common.c
index 6143c99f3ec5..43931c695ecb 100644
--- a/arch/powerpc/perf/isa207-common.c
+++ b/arch/powerpc/perf/isa207-common.c
@@ -261,3 +261,21 @@ void isa207_disable_pmc(unsigned int pmc, unsigned long 
mmcr[])
if (pmc <= 3)
mmcr[1] &= ~(0xffUL << MMCR1_PMCSEL_SHIFT(pmc + 1));
 }
+
+void isa207_get_arch_regs(struct perf_arch_regs *regs)
+{
+   regs->regs[PERF_ARCH_REG_POWERPC_PVR] = mfspr(SPRN_PVR);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC1] = mfspr(SPRN_PMC1);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC2] = mfspr(SPRN_PMC2);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC3] = mfspr(SPRN_PMC3);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC4] = mfspr(SPRN_PMC4);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC5] = mfspr(SPRN_PMC5);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC6] = mfspr(SPRN_PMC6);
+   regs->regs[PERF_ARCH_REG_POWERPC_MMCR0] = mfspr(SPRN_MMCR0);
+   regs->regs[PERF_ARCH_REG_POWERPC_MMCR1] = mfspr(SPRN_MMCR1);
+   regs->regs[PERF_ARCH_REG_POWERPC_SIER] = mfspr(SPRN_SIER);
+   regs->regs[PERF_ARCH_REG_POWERPC_SIAR] = mfspr(SPRN_SIAR);
+   regs->regs[PERF_ARCH_REG_POWERPC_SDAR] = mfspr(SPRN_SDAR);
+   regs->regs[PERF_ARCH_REG_POWERPC_MMCRA] = mfspr(SPRN_MMCRA);
+   regs->regs[PERF_ARCH_REG_POWERPC_MMCR2] = mfspr(SPRN_MMCR2);
+}
diff --git a/arch/powerpc/perf/isa207-common.h 
b/arch/powerpc/perf/isa207-common.h
index 4d0a4e5017c2..94bf8dd548ac 100644
--- a/arch/powerpc/perf/isa207-common.h
+++ b/arch/powerpc/perf/isa207-common.h
@@ -16,6 +16,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /*
  * Raw event encoding for PowerISA v2.07:
@@ -227,10 +228,19 @@
 #define MAX_ALT2
 #define MAX_PMU_COUNTERS   6
 
+#defineISA207_ARCH_REGS_MASK  (PERF_ARCH_REG_PVR |\
+   PERF_ARCH_REG_PMC1 | PERF_ARCH_REG_PMC2 |\
+   PERF_ARCH_REG_PMC3 | PERF_ARCH_REG_PMC4 |\
+   PERF_ARCH_REG_PMC5 | PERF_ARCH_REG_PMC6 |\
+   PERF_ARCH_REG_MMCR0 | PERF_ARCH_REG_MMCR1 |\
+   PERF_ARCH_REG_SIER | PERF_ARCH_REG_SIAR |\
+   PERF_ARCH_REG_SDAR | PERF_ARCH_REG_MMCRA | PERF_ARCH_REG_MMCR2)
+
 int isa207_get_constraint(u64 event, unsigned long *maskp, unsigned long 
*valp);
 int isa207_compute_mmcr(u64 event[], int n_ev,
unsigned int hwc[], unsigned long mmcr[],
struct perf_event *pevents[]);
 void isa207_disable_pmc(unsigned int pmc, unsigned long mmcr[]);
+void isa207_get_arch_regs(struct perf_arch_regs *regs);
 
 #endif
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index 5fde2b192fec..8c8bc5083eb2 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -394,6 +394,8 @@ static struct power_pmu power8_pmu = {
.cache_events   = _cache_events,
.attr_groups= power8_pmu_attr_groups,
.bhrb_nr= 32,
+   .ar_mask= ISA207_ARCH_REGS_MASK,
+   .get_arch_regs  = isa207_get_arch_regs,
 };
 
 static int __init init_power8_pmu(void)
diff --git a/arch/powerpc/perf/power9-pmu.c b/arch/powerpc/perf/power9-pmu.c
index 788346303852..1e66ec36b90f 100644
--- a/arch/powerpc/perf/power9-pmu.c
+++ b/arch/powerpc/perf/power9-pmu.c
@@ -307,6 +307,8 @@ static struct power_pmu power9_pmu = {
.cache_events   = _cache_events,
.attr_groups= power9_pmu_attr_groups,
.bhrb_nr= 32,
+   .ar_mask= ISA207_ARCH_REGS_MASK,
+   .get_arch_regs  = isa207_get_arch_regs,
 };
 
 static int __init init_power9_pmu(void)
-- 
2.7.4



[PATCH 07/13] powerpc/perf: Add support for perf_arch_regs for Power7 processor

2016-08-28 Thread Madhavan Srinivasan
Add code to define support functions and registers mask for
Power7 processor.

Cc: Thomas Gleixner 
Cc: Ingo Molnar 
Cc: Peter Zijlstra 
Cc: Jiri Olsa 
Cc: Arnaldo Carvalho de Melo 
Cc: Stephane Eranian 
Cc: Russell King 
Cc: Catalin Marinas 
Cc: Will Deacon 
Cc: Benjamin Herrenschmidt 
Cc: Michael Ellerman 
Cc: Sukadev Bhattiprolu 
Signed-off-by: Madhavan Srinivasan 
---
 arch/powerpc/perf/power7-pmu.c | 28 
 1 file changed, 28 insertions(+)

diff --git a/arch/powerpc/perf/power7-pmu.c b/arch/powerpc/perf/power7-pmu.c
index a383c23a9070..1eac466d4881 100644
--- a/arch/powerpc/perf/power7-pmu.c
+++ b/arch/powerpc/perf/power7-pmu.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /*
  * Bits in event code for POWER7
@@ -427,6 +428,31 @@ static const struct attribute_group 
*power7_pmu_attr_groups[] = {
NULL,
 };
 
+#define POWER7_ARCH_REGS_MASK  (PERF_ARCH_REG_PVR |\
+   PERF_ARCH_REG_PMC1 | PERF_ARCH_REG_PMC2 |\
+   PERF_ARCH_REG_PMC3 | PERF_ARCH_REG_PMC4 |\
+   PERF_ARCH_REG_PMC5 | PERF_ARCH_REG_PMC6 |\
+   PERF_ARCH_REG_MMCR0 | PERF_ARCH_REG_MMCR1 |\
+   PERF_ARCH_REG_SIER | PERF_ARCH_REG_SIAR |\
+   PERF_ARCH_REG_SDAR | PERF_ARCH_REG_MMCRA)
+
+static void power7_get_arch_regs(struct perf_arch_regs *regs)
+{
+   regs->regs[PERF_ARCH_REG_POWERPC_PVR] = mfspr(SPRN_PVR);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC1] = mfspr(SPRN_PMC1);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC2] = mfspr(SPRN_PMC2);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC3] = mfspr(SPRN_PMC3);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC4] = mfspr(SPRN_PMC4);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC5] = mfspr(SPRN_PMC5);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC6] = mfspr(SPRN_PMC6);
+   regs->regs[PERF_ARCH_REG_POWERPC_MMCR0] = mfspr(SPRN_MMCR0);
+   regs->regs[PERF_ARCH_REG_POWERPC_MMCR1] = mfspr(SPRN_MMCR1);
+   regs->regs[PERF_ARCH_REG_POWERPC_SIER] = mfspr(SPRN_SIER);
+   regs->regs[PERF_ARCH_REG_POWERPC_SIAR] = mfspr(SPRN_SIAR);
+   regs->regs[PERF_ARCH_REG_POWERPC_SDAR] = mfspr(SPRN_SDAR);
+   regs->regs[PERF_ARCH_REG_POWERPC_MMCRA] = mfspr(SPRN_MMCRA);
+}
+
 static struct power_pmu power7_pmu = {
.name   = "POWER7",
.n_counter  = 6,
@@ -442,6 +468,8 @@ static struct power_pmu power7_pmu = {
.n_generic  = ARRAY_SIZE(power7_generic_events),
.generic_events = power7_generic_events,
.cache_events   = _cache_events,
+   .ar_mask= POWER7_ARCH_REGS_MASK,
+   .get_arch_regs  = power7_get_arch_regs,
 };
 
 static int __init init_power7_pmu(void)
-- 
2.7.4



[PATCH 05/13] powerpc/perf: Define enums for perf_arch_regs registers

2016-08-28 Thread Madhavan Srinivasan
Patch creates a perf_event_powerpc_arch_regs enum and macros
to include some of the powerpc pmu registers.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Arnaldo Carvalho de Melo <a...@kernel.org>
Cc: Stephane Eranian <eran...@gmail.com>
Cc: Russell King <li...@arm.linux.org.uk>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
Cc: Benjamin Herrenschmidt <b...@kernel.crashing.org>
Cc: Michael Ellerman <m...@ellerman.id.au>
Cc: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>
Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
 arch/powerpc/include/uapi/asm/perf_regs.h   | 38 
 tools/arch/powerpc/include/uapi/asm/perf_regs.h | 39 +
 2 files changed, 77 insertions(+)

diff --git a/arch/powerpc/include/uapi/asm/perf_regs.h 
b/arch/powerpc/include/uapi/asm/perf_regs.h
index 6a93209748a1..e8f5553a61d1 100644
--- a/arch/powerpc/include/uapi/asm/perf_regs.h
+++ b/arch/powerpc/include/uapi/asm/perf_regs.h
@@ -47,4 +47,42 @@ enum perf_event_powerpc_regs {
PERF_REG_POWERPC_DSISR,
PERF_REG_POWERPC_MAX,
 };
+
+enum perf_event_powerpc_arch_regs {
+   PERF_ARCH_REG_POWERPC_PVR,
+   PERF_ARCH_REG_POWERPC_PMC1,
+   PERF_ARCH_REG_POWERPC_PMC2,
+   PERF_ARCH_REG_POWERPC_PMC3,
+   PERF_ARCH_REG_POWERPC_PMC4,
+   PERF_ARCH_REG_POWERPC_PMC5,
+   PERF_ARCH_REG_POWERPC_PMC6,
+   PERF_ARCH_REG_POWERPC_PMC7,
+   PERF_ARCH_REG_POWERPC_PMC8,
+   PERF_ARCH_REG_POWERPC_MMCR0,
+   PERF_ARCH_REG_POWERPC_MMCR1,
+   PERF_ARCH_REG_POWERPC_SIER,
+   PERF_ARCH_REG_POWERPC_SIAR,
+   PERF_ARCH_REG_POWERPC_SDAR,
+   PERF_ARCH_REG_POWERPC_MMCRA,
+   PERF_ARCH_REG_POWERPC_MMCR2,
+   PERF_ARCH_REG_POWERPC_MAX,
+};
+
+#define PERF_ARCH_REG_PVR  (1ULL<<PERF_ARCH_REG_POWERPC_PVR)
+#define PERF_ARCH_REG_PMC1 (1ULL<<PERF_ARCH_REG_POWERPC_PMC1)
+#define PERF_ARCH_REG_PMC2 (1ULL<<PERF_ARCH_REG_POWERPC_PMC2)
+#define PERF_ARCH_REG_PMC3 (1ULL<<PERF_ARCH_REG_POWERPC_PMC3)
+#define PERF_ARCH_REG_PMC4 (1ULL<<PERF_ARCH_REG_POWERPC_PMC4)
+#define PERF_ARCH_REG_PMC5 (1ULL<<PERF_ARCH_REG_POWERPC_PMC5)
+#define PERF_ARCH_REG_PMC6 (1ULL<<PERF_ARCH_REG_POWERPC_PMC6)
+#define PERF_ARCH_REG_PMC7 (1ULL<<PERF_ARCH_REG_POWERPC_PMC7)
+#define PERF_ARCH_REG_PMC8 (1ULL<<PERF_ARCH_REG_POWERPC_PMC8)
+#define PERF_ARCH_REG_MMCR0(1ULL<<PERF_ARCH_REG_POWERPC_MMCR0)
+#define PERF_ARCH_REG_MMCR1(1ULL<<PERF_ARCH_REG_POWERPC_MMCR1)
+#define PERF_ARCH_REG_SIER (1ULL<<PERF_ARCH_REG_POWERPC_SIER)
+#define PERF_ARCH_REG_SIAR (1ULL<<PERF_ARCH_REG_POWERPC_SIAR)
+#define PERF_ARCH_REG_SDAR (1ULL<<PERF_ARCH_REG_POWERPC_SDAR)
+#define PERF_ARCH_REG_MMCRA(1ULL<<PERF_ARCH_REG_POWERPC_MMCRA)
+#define PERF_ARCH_REG_MMCR2(1ULL<<PERF_ARCH_REG_POWERPC_MMCR2)
+
 #endif /* _UAPI_ASM_POWERPC_PERF_REGS_H */
diff --git a/tools/arch/powerpc/include/uapi/asm/perf_regs.h 
b/tools/arch/powerpc/include/uapi/asm/perf_regs.h
index 6a93209748a1..bf249a27aa36 100644
--- a/tools/arch/powerpc/include/uapi/asm/perf_regs.h
+++ b/tools/arch/powerpc/include/uapi/asm/perf_regs.h
@@ -47,4 +47,43 @@ enum perf_event_powerpc_regs {
PERF_REG_POWERPC_DSISR,
PERF_REG_POWERPC_MAX,
 };
+
+enum perf_event_powerpc_arch_regs {
+   PERF_ARCH_REG_POWERPC_PVR,
+   PERF_ARCH_REG_POWERPC_PMC1,
+   PERF_ARCH_REG_POWERPC_PMC2,
+   PERF_ARCH_REG_POWERPC_PMC3,
+   PERF_ARCH_REG_POWERPC_PMC4,
+   PERF_ARCH_REG_POWERPC_PMC5,
+   PERF_ARCH_REG_POWERPC_PMC6,
+   PERF_ARCH_REG_POWERPC_PMC7,
+   PERF_ARCH_REG_POWERPC_PMC8,
+   PERF_ARCH_REG_POWERPC_MMCR0,
+   PERF_ARCH_REG_POWERPC_MMCR1,
+   PERF_ARCH_REG_POWERPC_SIER,
+   PERF_ARCH_REG_POWERPC_SIAR,
+   PERF_ARCH_REG_POWERPC_SDAR,
+   PERF_ARCH_REG_POWERPC_MMCRA,
+   PERF_ARCH_REG_POWERPC_MMCR2,
+   PERF_ARCH_REG_POWERPC_MAX,
+};
+
+#define PERF_ARCH_REG_PVR  1ULL<

[PATCH 12/13] tool/perf: Add perf_arch_reg mask and arch_reg_names structure

2016-08-28 Thread Madhavan Srinivasan
Add arch_reg_names structure and define perf_arch_reg_name() function
to aid the printing of arch_regs values. Also, extend regs_dump__printf()
to include perf_arch_regs_mask to enable printing support.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Arnaldo Carvalho de Melo <a...@kernel.org>
Cc: Stephane Eranian <eran...@gmail.com>
Cc: Russell King <li...@arm.linux.org.uk>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
Cc: Benjamin Herrenschmidt <b...@kernel.crashing.org>
Cc: Michael Ellerman <m...@ellerman.id.au>
Cc: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>
Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
 tools/perf/arch/arm/include/perf_regs.h |  5 +
 tools/perf/arch/arm64/include/perf_regs.h   |  5 +
 tools/perf/arch/powerpc/include/perf_regs.h | 25 +
 tools/perf/arch/x86/include/perf_regs.h |  5 +
 tools/perf/builtin-script.c |  7 +++
 tools/perf/util/perf_regs.h |  5 +
 tools/perf/util/session.c   | 12 ++--
 7 files changed, 62 insertions(+), 2 deletions(-)

diff --git a/tools/perf/arch/arm/include/perf_regs.h 
b/tools/perf/arch/arm/include/perf_regs.h
index f619c9c5a4bf..db5a5f0ad439 100644
--- a/tools/perf/arch/arm/include/perf_regs.h
+++ b/tools/perf/arch/arm/include/perf_regs.h
@@ -56,4 +56,9 @@ static inline const char *perf_reg_name(int id)
return NULL;
 }
 
+static inline const char *perf_arch_reg_name(int id __maybe_unused)
+{
+   return NULL;
+}
+
 #endif /* ARCH_PERF_REGS_H */
diff --git a/tools/perf/arch/arm64/include/perf_regs.h 
b/tools/perf/arch/arm64/include/perf_regs.h
index 4e5af27e3fbf..20f8067b3e93 100644
--- a/tools/perf/arch/arm64/include/perf_regs.h
+++ b/tools/perf/arch/arm64/include/perf_regs.h
@@ -90,4 +90,9 @@ static inline const char *perf_reg_name(int id)
return NULL;
 }
 
+static inline const char *perf_arch_reg_name(int id __maybe_unused)
+{
+   return NULL;
+}
+
 #endif /* ARCH_PERF_REGS_H */
diff --git a/tools/perf/arch/powerpc/include/perf_regs.h 
b/tools/perf/arch/powerpc/include/perf_regs.h
index 75de0e92e71e..801de6def8da 100644
--- a/tools/perf/arch/powerpc/include/perf_regs.h
+++ b/tools/perf/arch/powerpc/include/perf_regs.h
@@ -4,6 +4,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define PERF_REGS_MASK  ((1ULL << PERF_REG_POWERPC_MAX) - 1)
 #define PERF_REGS_MAX   PERF_REG_POWERPC_MAX
@@ -66,4 +67,28 @@ static inline const char *perf_reg_name(int id)
 {
return reg_names[id];
 }
+
+static const char *arch_reg_names[] = {
+   [PERF_ARCH_REG_POWERPC_PVR] = "pvr",
+   [PERF_ARCH_REG_POWERPC_PMC1] = "pmc1",
+   [PERF_ARCH_REG_POWERPC_PMC2] = "pmc2",
+   [PERF_ARCH_REG_POWERPC_PMC3] = "pmc3",
+   [PERF_ARCH_REG_POWERPC_PMC4] = "pmc4",
+   [PERF_ARCH_REG_POWERPC_PMC5] = "pmc5",
+   [PERF_ARCH_REG_POWERPC_PMC6] = "pmc6",
+   [PERF_ARCH_REG_POWERPC_PMC7] = "pmc7",
+   [PERF_ARCH_REG_POWERPC_PMC8] = "pmc8",
+   [PERF_ARCH_REG_POWERPC_MMCR0] = "mmcr0",
+   [PERF_ARCH_REG_POWERPC_MMCR1] = "mmcr1",
+   [PERF_ARCH_REG_POWERPC_SIER] = "sier",
+   [PERF_ARCH_REG_POWERPC_SIAR] = "siar",
+   [PERF_ARCH_REG_POWERPC_SDAR] = "sdar",
+   [PERF_ARCH_REG_POWERPC_MMCRA] = "mmcra",
+   [PERF_ARCH_REG_POWERPC_MMCR2] = "mmcr2"
+};
+
+static inline const char *perf_arch_reg_name(int id)
+{
+   return arch_reg_names[id];
+}
 #endif /* ARCH_PERF_REGS_H */
diff --git a/tools/perf/arch/x86/include/perf_regs.h 
b/tools/perf/arch/x86/include/perf_regs.h
index 7df517acfef8..a41697b3 100644
--- a/tools/perf/arch/x86/include/perf_regs.h
+++ b/tools/perf/arch/x86/include/perf_regs.h
@@ -83,4 +83,9 @@ static inline const char *perf_reg_name(int id)
return NULL;
 }
 
+static inline const char *perf_arch_reg_name(int id __maybe_unused)
+{
+   return NULL;
+}
+
 #endif /* ARCH_PERF_REGS_H */
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index db270b4f892a..c2a84484b95b 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -420,6 +420,7 @@ static void print_sample_iregs(struct perf_sample *sample,
 {
struct regs_dump *regs = >intr_regs;
uint64_t mask = attr->sample_regs_intr;
+   uint64_t arch_regs_mask = regs->arch_regs_mask;
unsigned i = 0, r;
DECLARE_BITMAP(_mask, 64);
 
@@ -431,6 +432,12 @@ static void print_sample_iregs(struct perf_sample *sample,
u64 val = regs->regs[i++];
printf("%5s:0x%"PRIx64" ", perf_

[PATCH 10/13] tool/perf: Add support for perf_arch_regs

2016-08-28 Thread Madhavan Srinivasan
Update the structure regs_dump with the arch_regs_mask
variable. Update perf_evsel__parse_sample() and
perf_event__sample_event_size() to include arch_regs_mask variable.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Arnaldo Carvalho de Melo <a...@kernel.org>
Cc: Stephane Eranian <eran...@gmail.com>
Cc: Russell King <li...@arm.linux.org.uk>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
Cc: Benjamin Herrenschmidt <b...@kernel.crashing.org>
Cc: Michael Ellerman <m...@ellerman.id.au>
Cc: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>
Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
 tools/perf/util/event.h |  1 +
 tools/perf/util/evsel.c | 11 +++
 2 files changed, 12 insertions(+)

diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 8d363d5e65a2..aee0ff536e29 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -94,6 +94,7 @@ struct sample_event {
 struct regs_dump {
u64 abi;
u64 mask;
+   u64 arch_regs_mask;
u64 *regs;
 
/* Cached values/mask filled by first register access. */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 21fd573106ed..aac8820b3bd5 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1902,6 +1902,8 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, 
union perf_event *event,
OVERFLOW_CHECK_u64(array);
data->user_regs.abi = *array;
array++;
+   data->user_regs.arch_regs_mask = *array;
+   array++;
 
if (data->user_regs.abi) {
u64 mask = evsel->attr.sample_regs_user;
@@ -1961,11 +1963,14 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, 
union perf_event *event,
OVERFLOW_CHECK_u64(array);
data->intr_regs.abi = *array;
array++;
+   data->intr_regs.arch_regs_mask = *array;
+   array++;
 
if (data->intr_regs.abi != PERF_SAMPLE_REGS_ABI_NONE) {
u64 mask = evsel->attr.sample_regs_intr;
 
sz = hweight_long(mask) * sizeof(u64);
+   sz += hweight_long(data->intr_regs.arch_regs_mask) * 
sizeof(u64);
OVERFLOW_CHECK(array, sz, max_size);
data->intr_regs.mask = mask;
data->intr_regs.regs = (u64 *)array;
@@ -2044,6 +2049,7 @@ size_t perf_event__sample_event_size(const struct 
perf_sample *sample, u64 type,
if (sample->user_regs.abi) {
result += sizeof(u64);
sz = hweight_long(sample->user_regs.mask) * sizeof(u64);
+   sz += hweight_long(sample->user_regs.arch_regs_mask) * 
sizeof(u64);
result += sz;
} else {
result += sizeof(u64);
@@ -2072,6 +2078,7 @@ size_t perf_event__sample_event_size(const struct 
perf_sample *sample, u64 type,
if (sample->intr_regs.abi) {
result += sizeof(u64);
sz = hweight_long(sample->intr_regs.mask) * sizeof(u64);
+   sz += hweight_long(sample->intr_regs.arch_regs_mask) * 
sizeof(u64);
result += sz;
} else {
result += sizeof(u64);
@@ -2223,7 +2230,9 @@ int perf_event__synthesize_sample(union perf_event 
*event, u64 type,
if (type & PERF_SAMPLE_REGS_USER) {
if (sample->user_regs.abi) {
*array++ = sample->user_regs.abi;
+   *array++ = sample->user_regs.arch_regs_mask;
sz = hweight_long(sample->user_regs.mask) * sizeof(u64);
+   sz += hweight_long(sample->user_regs.arch_regs_mask) * 
sizeof(u64);
memcpy(array, sample->user_regs.regs, sz);
array = (void *)array + sz;
} else {
@@ -2259,7 +2268,9 @@ int perf_event__synthesize_sample(union perf_event 
*event, u64 type,
if (type & PERF_SAMPLE_REGS_INTR) {
if (sample->intr_regs.abi) {
*array++ = sample->intr_regs.abi;
+   *array++ = sample->intr_regs.arch_regs_mask;
sz = hweight_long(sample->intr_regs.mask) * sizeof(u64);
+   sz += hweight_long(sample->intr_regs.arch_regs_mask) * 
sizeof(u64);
memcpy(array, sample->intr_regs.regs, sz);
array = (void *)array + sz;
} else {
-- 
2.7.4



[PATCH 05/13] powerpc/perf: Define enums for perf_arch_regs registers

2016-08-28 Thread Madhavan Srinivasan
Patch creates a perf_event_powerpc_arch_regs enum and macros
to include some of the powerpc pmu registers.

Cc: Thomas Gleixner 
Cc: Ingo Molnar 
Cc: Peter Zijlstra 
Cc: Jiri Olsa 
Cc: Arnaldo Carvalho de Melo 
Cc: Stephane Eranian 
Cc: Russell King 
Cc: Catalin Marinas 
Cc: Will Deacon 
Cc: Benjamin Herrenschmidt 
Cc: Michael Ellerman 
Cc: Sukadev Bhattiprolu 
Signed-off-by: Madhavan Srinivasan 
---
 arch/powerpc/include/uapi/asm/perf_regs.h   | 38 
 tools/arch/powerpc/include/uapi/asm/perf_regs.h | 39 +
 2 files changed, 77 insertions(+)

diff --git a/arch/powerpc/include/uapi/asm/perf_regs.h 
b/arch/powerpc/include/uapi/asm/perf_regs.h
index 6a93209748a1..e8f5553a61d1 100644
--- a/arch/powerpc/include/uapi/asm/perf_regs.h
+++ b/arch/powerpc/include/uapi/asm/perf_regs.h
@@ -47,4 +47,42 @@ enum perf_event_powerpc_regs {
PERF_REG_POWERPC_DSISR,
PERF_REG_POWERPC_MAX,
 };
+
+enum perf_event_powerpc_arch_regs {
+   PERF_ARCH_REG_POWERPC_PVR,
+   PERF_ARCH_REG_POWERPC_PMC1,
+   PERF_ARCH_REG_POWERPC_PMC2,
+   PERF_ARCH_REG_POWERPC_PMC3,
+   PERF_ARCH_REG_POWERPC_PMC4,
+   PERF_ARCH_REG_POWERPC_PMC5,
+   PERF_ARCH_REG_POWERPC_PMC6,
+   PERF_ARCH_REG_POWERPC_PMC7,
+   PERF_ARCH_REG_POWERPC_PMC8,
+   PERF_ARCH_REG_POWERPC_MMCR0,
+   PERF_ARCH_REG_POWERPC_MMCR1,
+   PERF_ARCH_REG_POWERPC_SIER,
+   PERF_ARCH_REG_POWERPC_SIAR,
+   PERF_ARCH_REG_POWERPC_SDAR,
+   PERF_ARCH_REG_POWERPC_MMCRA,
+   PERF_ARCH_REG_POWERPC_MMCR2,
+   PERF_ARCH_REG_POWERPC_MAX,
+};
+
+#define PERF_ARCH_REG_PVR  (1ULL<

[PATCH 12/13] tool/perf: Add perf_arch_reg mask and arch_reg_names structure

2016-08-28 Thread Madhavan Srinivasan
Add arch_reg_names structure and define perf_arch_reg_name() function
to aid the printing of arch_regs values. Also, extend regs_dump__printf()
to include perf_arch_regs_mask to enable printing support.

Cc: Thomas Gleixner 
Cc: Ingo Molnar 
Cc: Peter Zijlstra 
Cc: Jiri Olsa 
Cc: Arnaldo Carvalho de Melo 
Cc: Stephane Eranian 
Cc: Russell King 
Cc: Catalin Marinas 
Cc: Will Deacon 
Cc: Benjamin Herrenschmidt 
Cc: Michael Ellerman 
Cc: Sukadev Bhattiprolu 
Signed-off-by: Madhavan Srinivasan 
---
 tools/perf/arch/arm/include/perf_regs.h |  5 +
 tools/perf/arch/arm64/include/perf_regs.h   |  5 +
 tools/perf/arch/powerpc/include/perf_regs.h | 25 +
 tools/perf/arch/x86/include/perf_regs.h |  5 +
 tools/perf/builtin-script.c |  7 +++
 tools/perf/util/perf_regs.h |  5 +
 tools/perf/util/session.c   | 12 ++--
 7 files changed, 62 insertions(+), 2 deletions(-)

diff --git a/tools/perf/arch/arm/include/perf_regs.h 
b/tools/perf/arch/arm/include/perf_regs.h
index f619c9c5a4bf..db5a5f0ad439 100644
--- a/tools/perf/arch/arm/include/perf_regs.h
+++ b/tools/perf/arch/arm/include/perf_regs.h
@@ -56,4 +56,9 @@ static inline const char *perf_reg_name(int id)
return NULL;
 }
 
+static inline const char *perf_arch_reg_name(int id __maybe_unused)
+{
+   return NULL;
+}
+
 #endif /* ARCH_PERF_REGS_H */
diff --git a/tools/perf/arch/arm64/include/perf_regs.h 
b/tools/perf/arch/arm64/include/perf_regs.h
index 4e5af27e3fbf..20f8067b3e93 100644
--- a/tools/perf/arch/arm64/include/perf_regs.h
+++ b/tools/perf/arch/arm64/include/perf_regs.h
@@ -90,4 +90,9 @@ static inline const char *perf_reg_name(int id)
return NULL;
 }
 
+static inline const char *perf_arch_reg_name(int id __maybe_unused)
+{
+   return NULL;
+}
+
 #endif /* ARCH_PERF_REGS_H */
diff --git a/tools/perf/arch/powerpc/include/perf_regs.h 
b/tools/perf/arch/powerpc/include/perf_regs.h
index 75de0e92e71e..801de6def8da 100644
--- a/tools/perf/arch/powerpc/include/perf_regs.h
+++ b/tools/perf/arch/powerpc/include/perf_regs.h
@@ -4,6 +4,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define PERF_REGS_MASK  ((1ULL << PERF_REG_POWERPC_MAX) - 1)
 #define PERF_REGS_MAX   PERF_REG_POWERPC_MAX
@@ -66,4 +67,28 @@ static inline const char *perf_reg_name(int id)
 {
return reg_names[id];
 }
+
+static const char *arch_reg_names[] = {
+   [PERF_ARCH_REG_POWERPC_PVR] = "pvr",
+   [PERF_ARCH_REG_POWERPC_PMC1] = "pmc1",
+   [PERF_ARCH_REG_POWERPC_PMC2] = "pmc2",
+   [PERF_ARCH_REG_POWERPC_PMC3] = "pmc3",
+   [PERF_ARCH_REG_POWERPC_PMC4] = "pmc4",
+   [PERF_ARCH_REG_POWERPC_PMC5] = "pmc5",
+   [PERF_ARCH_REG_POWERPC_PMC6] = "pmc6",
+   [PERF_ARCH_REG_POWERPC_PMC7] = "pmc7",
+   [PERF_ARCH_REG_POWERPC_PMC8] = "pmc8",
+   [PERF_ARCH_REG_POWERPC_MMCR0] = "mmcr0",
+   [PERF_ARCH_REG_POWERPC_MMCR1] = "mmcr1",
+   [PERF_ARCH_REG_POWERPC_SIER] = "sier",
+   [PERF_ARCH_REG_POWERPC_SIAR] = "siar",
+   [PERF_ARCH_REG_POWERPC_SDAR] = "sdar",
+   [PERF_ARCH_REG_POWERPC_MMCRA] = "mmcra",
+   [PERF_ARCH_REG_POWERPC_MMCR2] = "mmcr2"
+};
+
+static inline const char *perf_arch_reg_name(int id)
+{
+   return arch_reg_names[id];
+}
 #endif /* ARCH_PERF_REGS_H */
diff --git a/tools/perf/arch/x86/include/perf_regs.h 
b/tools/perf/arch/x86/include/perf_regs.h
index 7df517acfef8..a41697b3 100644
--- a/tools/perf/arch/x86/include/perf_regs.h
+++ b/tools/perf/arch/x86/include/perf_regs.h
@@ -83,4 +83,9 @@ static inline const char *perf_reg_name(int id)
return NULL;
 }
 
+static inline const char *perf_arch_reg_name(int id __maybe_unused)
+{
+   return NULL;
+}
+
 #endif /* ARCH_PERF_REGS_H */
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index db270b4f892a..c2a84484b95b 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -420,6 +420,7 @@ static void print_sample_iregs(struct perf_sample *sample,
 {
struct regs_dump *regs = >intr_regs;
uint64_t mask = attr->sample_regs_intr;
+   uint64_t arch_regs_mask = regs->arch_regs_mask;
unsigned i = 0, r;
DECLARE_BITMAP(_mask, 64);
 
@@ -431,6 +432,12 @@ static void print_sample_iregs(struct perf_sample *sample,
u64 val = regs->regs[i++];
printf("%5s:0x%"PRIx64" ", perf_reg_name(r), val);
}
+
+   bitmap_from_u64(_mask, arch_regs_mask);
+   for_each_set_bit(r, _mask, sizeof(mask) * 8) {
+   u64 val = regs->regs[i++];
+   printf("%5s:0x%"PRIx64" ", perf_arch_reg_name(r), val);
+   }
 }
 
 static void print_sample_start(struct perf_sample *sample,
diff --git a/tools/perf

[PATCH 10/13] tool/perf: Add support for perf_arch_regs

2016-08-28 Thread Madhavan Srinivasan
Update the structure regs_dump with the arch_regs_mask
variable. Update perf_evsel__parse_sample() and
perf_event__sample_event_size() to include arch_regs_mask variable.

Cc: Thomas Gleixner 
Cc: Ingo Molnar 
Cc: Peter Zijlstra 
Cc: Jiri Olsa 
Cc: Arnaldo Carvalho de Melo 
Cc: Stephane Eranian 
Cc: Russell King 
Cc: Catalin Marinas 
Cc: Will Deacon 
Cc: Benjamin Herrenschmidt 
Cc: Michael Ellerman 
Cc: Sukadev Bhattiprolu 
Signed-off-by: Madhavan Srinivasan 
---
 tools/perf/util/event.h |  1 +
 tools/perf/util/evsel.c | 11 +++
 2 files changed, 12 insertions(+)

diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 8d363d5e65a2..aee0ff536e29 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -94,6 +94,7 @@ struct sample_event {
 struct regs_dump {
u64 abi;
u64 mask;
+   u64 arch_regs_mask;
u64 *regs;
 
/* Cached values/mask filled by first register access. */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 21fd573106ed..aac8820b3bd5 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1902,6 +1902,8 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, 
union perf_event *event,
OVERFLOW_CHECK_u64(array);
data->user_regs.abi = *array;
array++;
+   data->user_regs.arch_regs_mask = *array;
+   array++;
 
if (data->user_regs.abi) {
u64 mask = evsel->attr.sample_regs_user;
@@ -1961,11 +1963,14 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, 
union perf_event *event,
OVERFLOW_CHECK_u64(array);
data->intr_regs.abi = *array;
array++;
+   data->intr_regs.arch_regs_mask = *array;
+   array++;
 
if (data->intr_regs.abi != PERF_SAMPLE_REGS_ABI_NONE) {
u64 mask = evsel->attr.sample_regs_intr;
 
sz = hweight_long(mask) * sizeof(u64);
+   sz += hweight_long(data->intr_regs.arch_regs_mask) * 
sizeof(u64);
OVERFLOW_CHECK(array, sz, max_size);
data->intr_regs.mask = mask;
data->intr_regs.regs = (u64 *)array;
@@ -2044,6 +2049,7 @@ size_t perf_event__sample_event_size(const struct 
perf_sample *sample, u64 type,
if (sample->user_regs.abi) {
result += sizeof(u64);
sz = hweight_long(sample->user_regs.mask) * sizeof(u64);
+   sz += hweight_long(sample->user_regs.arch_regs_mask) * 
sizeof(u64);
result += sz;
} else {
result += sizeof(u64);
@@ -2072,6 +2078,7 @@ size_t perf_event__sample_event_size(const struct 
perf_sample *sample, u64 type,
if (sample->intr_regs.abi) {
result += sizeof(u64);
sz = hweight_long(sample->intr_regs.mask) * sizeof(u64);
+   sz += hweight_long(sample->intr_regs.arch_regs_mask) * 
sizeof(u64);
result += sz;
} else {
result += sizeof(u64);
@@ -2223,7 +2230,9 @@ int perf_event__synthesize_sample(union perf_event 
*event, u64 type,
if (type & PERF_SAMPLE_REGS_USER) {
if (sample->user_regs.abi) {
*array++ = sample->user_regs.abi;
+   *array++ = sample->user_regs.arch_regs_mask;
sz = hweight_long(sample->user_regs.mask) * sizeof(u64);
+   sz += hweight_long(sample->user_regs.arch_regs_mask) * 
sizeof(u64);
memcpy(array, sample->user_regs.regs, sz);
array = (void *)array + sz;
} else {
@@ -2259,7 +2268,9 @@ int perf_event__synthesize_sample(union perf_event 
*event, u64 type,
if (type & PERF_SAMPLE_REGS_INTR) {
if (sample->intr_regs.abi) {
*array++ = sample->intr_regs.abi;
+   *array++ = sample->intr_regs.arch_regs_mask;
sz = hweight_long(sample->intr_regs.mask) * sizeof(u64);
+   sz += hweight_long(sample->intr_regs.arch_regs_mask) * 
sizeof(u64);
memcpy(array, sample->intr_regs.regs, sz);
array = (void *)array + sz;
} else {
-- 
2.7.4



[PATCH 03/13] perf/core: Update perf_*_sample() to include perf_arch_regs

2016-08-28 Thread Madhavan Srinivasan
perf_prepare_sample is extended to include the perf_arch_regs_mask
in the sample header size calculation. Update perf_output_sample() to dump
the perf_arch_regs_mask to sample output.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Arnaldo Carvalho de Melo <a...@kernel.org>
Cc: Stephane Eranian <eran...@gmail.com>
Cc: Russell King <li...@arm.linux.org.uk>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
Cc: Benjamin Herrenschmidt <b...@kernel.crashing.org>
Cc: Michael Ellerman <m...@ellerman.id.au>
Cc: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>
Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
 kernel/events/core.c | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 8cf540275c34..274288819829 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5780,12 +5780,14 @@ void perf_output_sample(struct perf_output_handle 
*handle,
 
if (sample_type & PERF_SAMPLE_REGS_USER) {
u64 abi = data->regs_user.abi;
+   u64 arch_regs_mask = data->regs_user.arch_regs_mask;
 
/*
 * If there are no regs to dump, notice it through
 * first u64 being zero (PERF_SAMPLE_REGS_ABI_NONE).
 */
perf_output_put(handle, abi);
+   perf_output_put(handle, arch_regs_mask);
 
if (abi) {
u64 mask = event->attr.sample_regs_user;
@@ -5812,11 +5814,14 @@ void perf_output_sample(struct perf_output_handle 
*handle,
 
if (sample_type & PERF_SAMPLE_REGS_INTR) {
u64 abi = data->regs_intr.abi;
+   u64 arch_regs_mask = data->regs_intr.arch_regs_mask;
+
/*
 * If there are no regs to dump, notice it through
 * first u64 being zero (PERF_SAMPLE_REGS_ABI_NONE).
 */
perf_output_put(handle, abi);
+   perf_output_put(handle, arch_regs_mask);
 
if (abi) {
u64 mask = event->attr.sample_regs_intr;
@@ -5910,8 +5915,8 @@ void perf_prepare_sample(struct perf_event_header *header,
  >regs_user_copy);
 
if (sample_type & PERF_SAMPLE_REGS_USER) {
-   /* regs dump ABI info */
-   int size = sizeof(u64);
+   /* regs dump ABI info and arch_regs_mask */
+   int size = sizeof(u64) * 2;
 
if (data->regs_user.regs) {
u64 mask = event->attr.sample_regs_user;
@@ -5947,8 +5952,8 @@ void perf_prepare_sample(struct perf_event_header *header,
}
 
if (sample_type & PERF_SAMPLE_REGS_INTR) {
-   /* regs dump ABI info */
-   int size = sizeof(u64);
+   /* regs dump ABI info and arch_regs_mask */
+   int size = sizeof(u64) * 2;
 
perf_sample_regs_intr(>regs_intr, regs);
 
@@ -5956,6 +5961,9 @@ void perf_prepare_sample(struct perf_event_header *header,
u64 mask = event->attr.sample_regs_intr;
 
size += hweight64(mask) * sizeof(u64);
+
+   mask = data->regs_intr.arch_regs_mask;
+   size += hweight64(mask) * sizeof(u64);
}
 
header->size += size;
-- 
2.7.4



[PATCH 06/13] powerpc/perf: Add support for perf_arch_regs in powerpc

2016-08-28 Thread Madhavan Srinivasan
Patch defines struct perf_arch_regs{} for powerpc and
update the per-cpu perf pmu structure to include
perf_arch_regs bits. perf_arch_reg_value(), perf_get_arch_reg()
and perf_get_arch_regs_mask() are implemented to return
proper values for powerpc. Finally adds code to call the
processor specific function to update the arch_regs register
values.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Arnaldo Carvalho de Melo <a...@kernel.org>
Cc: Stephane Eranian <eran...@gmail.com>
Cc: Russell King <li...@arm.linux.org.uk>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
Cc: Benjamin Herrenschmidt <b...@kernel.crashing.org>
Cc: Michael Ellerman <m...@ellerman.id.au>
Cc: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>
Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/perf_event_server.h | 11 
 arch/powerpc/perf/core-book3s.c  | 38 
 2 files changed, 49 insertions(+)

diff --git a/arch/powerpc/include/asm/perf_event_server.h 
b/arch/powerpc/include/asm/perf_event_server.h
index e157489ee7a1..65699fefb5a8 100644
--- a/arch/powerpc/include/asm/perf_event_server.h
+++ b/arch/powerpc/include/asm/perf_event_server.h
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 /* Update perf_event_print_debug() if this changes */
@@ -21,6 +22,12 @@
 
 struct perf_event;
 
+struct perf_arch_regs {
+   unsigned long regs[PERF_ARCH_REG_POWERPC_MAX];
+};
+
+#define perf_arch_regs perf_arch_regs
+
 /*
  * This struct provides the constants and functions needed to
  * describe the PMU on a particular POWER-family CPU.
@@ -52,6 +59,10 @@ struct power_pmu {
 
/* BHRB entries in the PMU */
int bhrb_nr;
+
+   /* perf_arch_regs bits */
+   u64 ar_mask;
+   void(*get_arch_regs)(struct perf_arch_regs *regs);
 };
 
 /*
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 4ed377f0f7b2..6acf086f31b3 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -57,6 +57,9 @@ struct cpu_hw_events {
void*bhrb_context;
struct  perf_branch_stack   bhrb_stack;
struct  perf_branch_entry   bhrb_entries[BHRB_MAX_ENTRIES];
+
+   /* perf_arch_regs bits */
+   struct perf_arch_regs   ar_regs;
 };
 
 static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
@@ -1928,6 +1931,33 @@ ssize_t power_events_sysfs_show(struct device *dev,
return sprintf(page, "event=0x%02llx\n", pmu_attr->id);
 }
 
+u64 perf_get_arch_regs_mask(void)
+{
+   return ppmu->ar_mask;
+}
+
+struct perf_arch_regs *perf_get_arch_reg()
+{
+   struct cpu_hw_events *cpuhw;
+
+   cpuhw = this_cpu_ptr(_hw_events);
+   if (!ppmu->ar_mask)
+   return NULL;
+
+   return >ar_regs;
+}
+
+u64 perf_arch_reg_value(struct perf_arch_regs *regs, int idx)
+{
+   struct cpu_hw_events *cpuhw;
+
+   cpuhw = this_cpu_ptr(_hw_events);
+   if (WARN_ON_ONCE(idx >= PERF_ARCH_REG_POWERPC_MAX))
+   return 0;
+
+   return cpuhw->ar_regs.regs[idx];
+}
+
 static struct pmu power_pmu = {
.pmu_enable = power_pmu_enable,
.pmu_disable= power_pmu_disable,
@@ -2009,6 +2039,14 @@ static void record_and_restart(struct perf_event *event, 
unsigned long val,
data.br_stack = >bhrb_stack;
}
 
+   if (event->attr.sample_type & PERF_SAMPLE_REGS_INTR) {
+   struct cpu_hw_events *cpuhw;
+   cpuhw = this_cpu_ptr(_hw_events);
+
+   if (ppmu->get_arch_regs)
+   ppmu->get_arch_regs(>ar_regs);
+   }
+
if (perf_event_overflow(event, , regs))
power_pmu_stop(event, 0);
}
-- 
2.7.4



[PATCH 09/13] powerpc/perf: Add support for perf_arch_regs for PPC970 processor

2016-08-28 Thread Madhavan Srinivasan
Add code to define support functions and registers mask for
PPC970 processor.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Arnaldo Carvalho de Melo <a...@kernel.org>
Cc: Stephane Eranian <eran...@gmail.com>
Cc: Russell King <li...@arm.linux.org.uk>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
Cc: Benjamin Herrenschmidt <b...@kernel.crashing.org>
Cc: Michael Ellerman <m...@ellerman.id.au>
Cc: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>
Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
 arch/powerpc/perf/ppc970-pmu.c | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/arch/powerpc/perf/ppc970-pmu.c b/arch/powerpc/perf/ppc970-pmu.c
index 8b6a8a36fa38..0b3121335bf0 100644
--- a/arch/powerpc/perf/ppc970-pmu.c
+++ b/arch/powerpc/perf/ppc970-pmu.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /*
  * Bits in event code for PPC970
@@ -474,6 +475,26 @@ static int 
ppc970_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
},
 };
 
+#define PPC970_ARCH_REGS_MASK  (PERF_ARCH_REG_PVR |\
+   PERF_ARCH_REG_PMC1 | PERF_ARCH_REG_PMC2 |\
+   PERF_ARCH_REG_PMC3 | PERF_ARCH_REG_PMC4 |\
+   PERF_ARCH_REG_PMC5 | PERF_ARCH_REG_PMC6 |\
+   PERF_ARCH_REG_MMCR0 | PERF_ARCH_REG_MMCR1 | PERF_ARCH_REG_MMCRA)
+
+static void ppc970_get_arch_regs(struct perf_arch_regs *regs)
+{
+   regs->regs[PERF_ARCH_REG_POWERPC_PVR] = mfspr(SPRN_PVR);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC1] = mfspr(SPRN_PMC1);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC2] = mfspr(SPRN_PMC2);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC3] = mfspr(SPRN_PMC3);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC4] = mfspr(SPRN_PMC4);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC5] = mfspr(SPRN_PMC5);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC6] = mfspr(SPRN_PMC6);
+   regs->regs[PERF_ARCH_REG_POWERPC_MMCR0] = mfspr(SPRN_MMCR0);
+   regs->regs[PERF_ARCH_REG_POWERPC_MMCR1] = mfspr(SPRN_MMCR1);
+   regs->regs[PERF_ARCH_REG_POWERPC_MMCRA] = mfspr(SPRN_MMCRA);
+}
+
 static struct power_pmu ppc970_pmu = {
.name   = "PPC970/FX/MP",
.n_counter  = 8,
@@ -488,6 +509,8 @@ static struct power_pmu ppc970_pmu = {
.generic_events = ppc970_generic_events,
.cache_events   = _cache_events,
.flags  = PPMU_NO_SIPR | PPMU_NO_CONT_SAMPLING,
+   .ar_mask= PPC970_ARCH_REGS_MASK,
+   .get_arch_regs  = ppc970_get_arch_regs,
 };
 
 static int __init init_ppc970_pmu(void)
-- 
2.7.4



[PATCH 04/13] perf/core: Extend perf_output_sample_regs() to include perf_arch_regs

2016-08-28 Thread Madhavan Srinivasan
Extend perf_output_sample_regs() to take in perf_regs structure as
a parameter instead of pt_regs. Add code to check for arch_regs_mask
and dump the arch registers to the output sample.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Arnaldo Carvalho de Melo <a...@kernel.org>
Cc: Stephane Eranian <eran...@gmail.com>
Cc: Russell King <li...@arm.linux.org.uk>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
Cc: Benjamin Herrenschmidt <b...@kernel.crashing.org>
Cc: Michael Ellerman <m...@ellerman.id.au>
Cc: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>
Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
 kernel/events/core.c | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 274288819829..e16bf4d057d1 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5371,16 +5371,24 @@ u64 __attribute__((weak)) perf_arch_reg_value(struct 
perf_arch_regs *regs,
 
 static void
 perf_output_sample_regs(struct perf_output_handle *handle,
-   struct pt_regs *regs, u64 mask)
+   struct perf_regs *regs, u64 mask)
 {
int bit;
DECLARE_BITMAP(_mask, 64);
+   u64 arch_regs_mask = regs->arch_regs_mask;
 
bitmap_from_u64(_mask, mask);
for_each_set_bit(bit, _mask, sizeof(mask) * BITS_PER_BYTE) {
u64 val;
 
-   val = perf_reg_value(regs, bit);
+   val = perf_reg_value(regs->regs, bit);
+   perf_output_put(handle, val);
+   }
+
+   bitmap_from_u64(_mask, arch_regs_mask);
+   for_each_set_bit(bit, _mask, sizeof(mask) * BITS_PER_BYTE) {
+   u64 val;
+   val = perf_arch_reg_value(regs->arch_regs, bit);
perf_output_put(handle, val);
}
 }
@@ -5792,7 +5800,7 @@ void perf_output_sample(struct perf_output_handle *handle,
if (abi) {
u64 mask = event->attr.sample_regs_user;
perf_output_sample_regs(handle,
-   data->regs_user.regs,
+   >regs_user,
mask);
}
}
@@ -5827,7 +5835,7 @@ void perf_output_sample(struct perf_output_handle *handle,
u64 mask = event->attr.sample_regs_intr;
 
perf_output_sample_regs(handle,
-   data->regs_intr.regs,
+   >regs_intr,
mask);
}
}
-- 
2.7.4



[PATCH 03/13] perf/core: Update perf_*_sample() to include perf_arch_regs

2016-08-28 Thread Madhavan Srinivasan
perf_prepare_sample is extended to include the perf_arch_regs_mask
in the sample header size calculation. Update perf_output_sample() to dump
the perf_arch_regs_mask to sample output.

Cc: Thomas Gleixner 
Cc: Ingo Molnar 
Cc: Peter Zijlstra 
Cc: Jiri Olsa 
Cc: Arnaldo Carvalho de Melo 
Cc: Stephane Eranian 
Cc: Russell King 
Cc: Catalin Marinas 
Cc: Will Deacon 
Cc: Benjamin Herrenschmidt 
Cc: Michael Ellerman 
Cc: Sukadev Bhattiprolu 
Signed-off-by: Madhavan Srinivasan 
---
 kernel/events/core.c | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 8cf540275c34..274288819829 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5780,12 +5780,14 @@ void perf_output_sample(struct perf_output_handle 
*handle,
 
if (sample_type & PERF_SAMPLE_REGS_USER) {
u64 abi = data->regs_user.abi;
+   u64 arch_regs_mask = data->regs_user.arch_regs_mask;
 
/*
 * If there are no regs to dump, notice it through
 * first u64 being zero (PERF_SAMPLE_REGS_ABI_NONE).
 */
perf_output_put(handle, abi);
+   perf_output_put(handle, arch_regs_mask);
 
if (abi) {
u64 mask = event->attr.sample_regs_user;
@@ -5812,11 +5814,14 @@ void perf_output_sample(struct perf_output_handle 
*handle,
 
if (sample_type & PERF_SAMPLE_REGS_INTR) {
u64 abi = data->regs_intr.abi;
+   u64 arch_regs_mask = data->regs_intr.arch_regs_mask;
+
/*
 * If there are no regs to dump, notice it through
 * first u64 being zero (PERF_SAMPLE_REGS_ABI_NONE).
 */
perf_output_put(handle, abi);
+   perf_output_put(handle, arch_regs_mask);
 
if (abi) {
u64 mask = event->attr.sample_regs_intr;
@@ -5910,8 +5915,8 @@ void perf_prepare_sample(struct perf_event_header *header,
  >regs_user_copy);
 
if (sample_type & PERF_SAMPLE_REGS_USER) {
-   /* regs dump ABI info */
-   int size = sizeof(u64);
+   /* regs dump ABI info and arch_regs_mask */
+   int size = sizeof(u64) * 2;
 
if (data->regs_user.regs) {
u64 mask = event->attr.sample_regs_user;
@@ -5947,8 +5952,8 @@ void perf_prepare_sample(struct perf_event_header *header,
}
 
if (sample_type & PERF_SAMPLE_REGS_INTR) {
-   /* regs dump ABI info */
-   int size = sizeof(u64);
+   /* regs dump ABI info and arch_regs_mask */
+   int size = sizeof(u64) * 2;
 
perf_sample_regs_intr(>regs_intr, regs);
 
@@ -5956,6 +5961,9 @@ void perf_prepare_sample(struct perf_event_header *header,
u64 mask = event->attr.sample_regs_intr;
 
size += hweight64(mask) * sizeof(u64);
+
+   mask = data->regs_intr.arch_regs_mask;
+   size += hweight64(mask) * sizeof(u64);
}
 
header->size += size;
-- 
2.7.4



[PATCH 06/13] powerpc/perf: Add support for perf_arch_regs in powerpc

2016-08-28 Thread Madhavan Srinivasan
Patch defines struct perf_arch_regs{} for powerpc and
update the per-cpu perf pmu structure to include
perf_arch_regs bits. perf_arch_reg_value(), perf_get_arch_reg()
and perf_get_arch_regs_mask() are implemented to return
proper values for powerpc. Finally adds code to call the
processor specific function to update the arch_regs register
values.

Cc: Thomas Gleixner 
Cc: Ingo Molnar 
Cc: Peter Zijlstra 
Cc: Jiri Olsa 
Cc: Arnaldo Carvalho de Melo 
Cc: Stephane Eranian 
Cc: Russell King 
Cc: Catalin Marinas 
Cc: Will Deacon 
Cc: Benjamin Herrenschmidt 
Cc: Michael Ellerman 
Cc: Sukadev Bhattiprolu 
Signed-off-by: Madhavan Srinivasan 
---
 arch/powerpc/include/asm/perf_event_server.h | 11 
 arch/powerpc/perf/core-book3s.c  | 38 
 2 files changed, 49 insertions(+)

diff --git a/arch/powerpc/include/asm/perf_event_server.h 
b/arch/powerpc/include/asm/perf_event_server.h
index e157489ee7a1..65699fefb5a8 100644
--- a/arch/powerpc/include/asm/perf_event_server.h
+++ b/arch/powerpc/include/asm/perf_event_server.h
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 /* Update perf_event_print_debug() if this changes */
@@ -21,6 +22,12 @@
 
 struct perf_event;
 
+struct perf_arch_regs {
+   unsigned long regs[PERF_ARCH_REG_POWERPC_MAX];
+};
+
+#define perf_arch_regs perf_arch_regs
+
 /*
  * This struct provides the constants and functions needed to
  * describe the PMU on a particular POWER-family CPU.
@@ -52,6 +59,10 @@ struct power_pmu {
 
/* BHRB entries in the PMU */
int bhrb_nr;
+
+   /* perf_arch_regs bits */
+   u64 ar_mask;
+   void(*get_arch_regs)(struct perf_arch_regs *regs);
 };
 
 /*
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 4ed377f0f7b2..6acf086f31b3 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -57,6 +57,9 @@ struct cpu_hw_events {
void*bhrb_context;
struct  perf_branch_stack   bhrb_stack;
struct  perf_branch_entry   bhrb_entries[BHRB_MAX_ENTRIES];
+
+   /* perf_arch_regs bits */
+   struct perf_arch_regs   ar_regs;
 };
 
 static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
@@ -1928,6 +1931,33 @@ ssize_t power_events_sysfs_show(struct device *dev,
return sprintf(page, "event=0x%02llx\n", pmu_attr->id);
 }
 
+u64 perf_get_arch_regs_mask(void)
+{
+   return ppmu->ar_mask;
+}
+
+struct perf_arch_regs *perf_get_arch_reg()
+{
+   struct cpu_hw_events *cpuhw;
+
+   cpuhw = this_cpu_ptr(_hw_events);
+   if (!ppmu->ar_mask)
+   return NULL;
+
+   return >ar_regs;
+}
+
+u64 perf_arch_reg_value(struct perf_arch_regs *regs, int idx)
+{
+   struct cpu_hw_events *cpuhw;
+
+   cpuhw = this_cpu_ptr(_hw_events);
+   if (WARN_ON_ONCE(idx >= PERF_ARCH_REG_POWERPC_MAX))
+   return 0;
+
+   return cpuhw->ar_regs.regs[idx];
+}
+
 static struct pmu power_pmu = {
.pmu_enable = power_pmu_enable,
.pmu_disable= power_pmu_disable,
@@ -2009,6 +2039,14 @@ static void record_and_restart(struct perf_event *event, 
unsigned long val,
data.br_stack = >bhrb_stack;
}
 
+   if (event->attr.sample_type & PERF_SAMPLE_REGS_INTR) {
+   struct cpu_hw_events *cpuhw;
+   cpuhw = this_cpu_ptr(_hw_events);
+
+   if (ppmu->get_arch_regs)
+   ppmu->get_arch_regs(>ar_regs);
+   }
+
if (perf_event_overflow(event, , regs))
power_pmu_stop(event, 0);
}
-- 
2.7.4



[PATCH 09/13] powerpc/perf: Add support for perf_arch_regs for PPC970 processor

2016-08-28 Thread Madhavan Srinivasan
Add code to define support functions and registers mask for
PPC970 processor.

Cc: Thomas Gleixner 
Cc: Ingo Molnar 
Cc: Peter Zijlstra 
Cc: Jiri Olsa 
Cc: Arnaldo Carvalho de Melo 
Cc: Stephane Eranian 
Cc: Russell King 
Cc: Catalin Marinas 
Cc: Will Deacon 
Cc: Benjamin Herrenschmidt 
Cc: Michael Ellerman 
Cc: Sukadev Bhattiprolu 
Signed-off-by: Madhavan Srinivasan 
---
 arch/powerpc/perf/ppc970-pmu.c | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/arch/powerpc/perf/ppc970-pmu.c b/arch/powerpc/perf/ppc970-pmu.c
index 8b6a8a36fa38..0b3121335bf0 100644
--- a/arch/powerpc/perf/ppc970-pmu.c
+++ b/arch/powerpc/perf/ppc970-pmu.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /*
  * Bits in event code for PPC970
@@ -474,6 +475,26 @@ static int 
ppc970_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
},
 };
 
+#define PPC970_ARCH_REGS_MASK  (PERF_ARCH_REG_PVR |\
+   PERF_ARCH_REG_PMC1 | PERF_ARCH_REG_PMC2 |\
+   PERF_ARCH_REG_PMC3 | PERF_ARCH_REG_PMC4 |\
+   PERF_ARCH_REG_PMC5 | PERF_ARCH_REG_PMC6 |\
+   PERF_ARCH_REG_MMCR0 | PERF_ARCH_REG_MMCR1 | PERF_ARCH_REG_MMCRA)
+
+static void ppc970_get_arch_regs(struct perf_arch_regs *regs)
+{
+   regs->regs[PERF_ARCH_REG_POWERPC_PVR] = mfspr(SPRN_PVR);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC1] = mfspr(SPRN_PMC1);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC2] = mfspr(SPRN_PMC2);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC3] = mfspr(SPRN_PMC3);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC4] = mfspr(SPRN_PMC4);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC5] = mfspr(SPRN_PMC5);
+   regs->regs[PERF_ARCH_REG_POWERPC_PMC6] = mfspr(SPRN_PMC6);
+   regs->regs[PERF_ARCH_REG_POWERPC_MMCR0] = mfspr(SPRN_MMCR0);
+   regs->regs[PERF_ARCH_REG_POWERPC_MMCR1] = mfspr(SPRN_MMCR1);
+   regs->regs[PERF_ARCH_REG_POWERPC_MMCRA] = mfspr(SPRN_MMCRA);
+}
+
 static struct power_pmu ppc970_pmu = {
.name   = "PPC970/FX/MP",
.n_counter  = 8,
@@ -488,6 +509,8 @@ static struct power_pmu ppc970_pmu = {
.generic_events = ppc970_generic_events,
.cache_events   = _cache_events,
.flags  = PPMU_NO_SIPR | PPMU_NO_CONT_SAMPLING,
+   .ar_mask= PPC970_ARCH_REGS_MASK,
+   .get_arch_regs  = ppc970_get_arch_regs,
 };
 
 static int __init init_ppc970_pmu(void)
-- 
2.7.4



[PATCH 04/13] perf/core: Extend perf_output_sample_regs() to include perf_arch_regs

2016-08-28 Thread Madhavan Srinivasan
Extend perf_output_sample_regs() to take in perf_regs structure as
a parameter instead of pt_regs. Add code to check for arch_regs_mask
and dump the arch registers to the output sample.

Cc: Thomas Gleixner 
Cc: Ingo Molnar 
Cc: Peter Zijlstra 
Cc: Jiri Olsa 
Cc: Arnaldo Carvalho de Melo 
Cc: Stephane Eranian 
Cc: Russell King 
Cc: Catalin Marinas 
Cc: Will Deacon 
Cc: Benjamin Herrenschmidt 
Cc: Michael Ellerman 
Cc: Sukadev Bhattiprolu 
Signed-off-by: Madhavan Srinivasan 
---
 kernel/events/core.c | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 274288819829..e16bf4d057d1 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5371,16 +5371,24 @@ u64 __attribute__((weak)) perf_arch_reg_value(struct 
perf_arch_regs *regs,
 
 static void
 perf_output_sample_regs(struct perf_output_handle *handle,
-   struct pt_regs *regs, u64 mask)
+   struct perf_regs *regs, u64 mask)
 {
int bit;
DECLARE_BITMAP(_mask, 64);
+   u64 arch_regs_mask = regs->arch_regs_mask;
 
bitmap_from_u64(_mask, mask);
for_each_set_bit(bit, _mask, sizeof(mask) * BITS_PER_BYTE) {
u64 val;
 
-   val = perf_reg_value(regs, bit);
+   val = perf_reg_value(regs->regs, bit);
+   perf_output_put(handle, val);
+   }
+
+   bitmap_from_u64(_mask, arch_regs_mask);
+   for_each_set_bit(bit, _mask, sizeof(mask) * BITS_PER_BYTE) {
+   u64 val;
+   val = perf_arch_reg_value(regs->arch_regs, bit);
perf_output_put(handle, val);
}
 }
@@ -5792,7 +5800,7 @@ void perf_output_sample(struct perf_output_handle *handle,
if (abi) {
u64 mask = event->attr.sample_regs_user;
perf_output_sample_regs(handle,
-   data->regs_user.regs,
+   >regs_user,
mask);
}
}
@@ -5827,7 +5835,7 @@ void perf_output_sample(struct perf_output_handle *handle,
u64 mask = event->attr.sample_regs_intr;
 
perf_output_sample_regs(handle,
-   data->regs_intr.regs,
+   >regs_intr,
mask);
}
}
-- 
2.7.4



[PATCH 02/13] perf/core: Extend perf_sample_regs_intr() to include perf_arch_regs update

2016-08-28 Thread Madhavan Srinivasan
Extend perf_sample_regs_intr() to support the updates needed for
perf_arch_reg structure and perf_arch_regs_mask. Also add code to
init the arch_regs_mask to zero incase of regs_user in
perf_sample_regs_user(). Ideally this should be done in perf_sample_data_init,
but due to commit 2565711fb7d7 ("perf: Improve the perf_sample_data struct 
layout")
moving it to this function.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Arnaldo Carvalho de Melo <a...@kernel.org>
Cc: Stephane Eranian <eran...@gmail.com>
Cc: Russell King <li...@arm.linux.org.uk>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
Cc: Benjamin Herrenschmidt <b...@kernel.crashing.org>
Cc: Michael Ellerman <m...@ellerman.id.au>
Cc: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>
Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
 kernel/events/core.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 2f6e6a16b117..8cf540275c34 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5398,6 +5398,9 @@ static void perf_sample_regs_user(struct perf_regs 
*regs_user,
regs_user->abi = PERF_SAMPLE_REGS_ABI_NONE;
regs_user->regs = NULL;
}
+
+   /* Init arch_regs_mask to zero */
+   regs_user->arch_regs_mask = 0;
 }
 
 static void perf_sample_regs_intr(struct perf_regs *regs_intr,
@@ -5405,6 +5408,8 @@ static void perf_sample_regs_intr(struct perf_regs 
*regs_intr,
 {
regs_intr->regs = regs;
regs_intr->abi  = perf_reg_abi(current);
+   regs_intr->arch_regs_mask = perf_get_arch_regs_mask();
+   regs_intr->arch_regs = perf_get_arch_reg();
 }
 
 
-- 
2.7.4



[PATCH 00/13] Add support for perf_arch_regs

2016-08-28 Thread Madhavan Srinivasan
Patchset to extend PERF_SAMPLE_REGS_INTR to include
platform specific PMU registers.

Patchset applies cleanly on tip:perf/core branch

It's a perennial request from hardware folks to be able to
see the raw values of the pmu registers. Partly it's so that
they can verify perf is doing what they want, and some
of it is that they're interested in some of the more obscure
info that isn't plumbed out through other perf interfaces.

Over the years internally we have used various hack to get
the requested data out but this is an attempt to use a
somewhat standard mechanism (using PERF_SAMPLE_REGS_INTR).

This would also be helpful for those of us working on the perf
hardware backends, to be able to verify that we're programming
things correctly, without resorting to debug printks etc.

Mechanism proposed:

1)perf_regs structure is extended with a perf_arch_regs structure
which each arch/ can populate with their specific platform
registers to sample on each perf interrupt and an arch_regs_mask
variable, which is for perf tool to know about the perf_arch_regs
that are supported.

2)perf/core func perf_sample_regs_intr() extended to update
the perf_arch_regs structure and the perf_arch_reg_mask. Set of new
support functions added perf_get_arch_regs_mask() and
perf_get_arch_reg() to aid the updates from arch/ side.

3) perf/core funcs perf_prepare_sample() and perf_output_sample()
are extended to support the update for the perf_arch_regs_mask and
perf_arch_regs in the sample

4)perf/core func perf_output_sample_regs() extended to dump
the arch_regs to the output sample.

5)Finally, perf tool side is updated to include a new element
"arch_regs_mask" in the "struct regs_dump", event sample funcs
and print functions are updated to support perf_arch_regs.

example usage:

$./perf record -I ls
.
builtin-data.o   builtin-list.obuiltin-stat.cDocumentation  
  perf.h
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.009 MB perf.data (12 samples) ]
$./perf script -D

0x980 [0x200]: event: 9
.
. ... raw event: size 512 bytes
.  :  00 00 00 09 00 01 02 00 00 00 00 00 00 08 fb 4c  ...L
.  0010:  00 00 16 cb 00 00 16 cb 00 00 01 1d ca 45 9f 52  .E.R
.  0020:  00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 02  
...
 dsisr 0x6000
 arch_regs 0x7e7f
 pvr   0x4a0201
 pmc1  0x7fff
 pmc2  0x0
 pmc3  0x0
 pmc4  0x0
 pmc5  0xa03
 pmc6  0x38df
 mmcr0 0x82008080
 mmcr1 0x1e00
 sier  0x1e00
 siar  0x8fb4c
 sdar  0xc0241b195100
 mmcra 0x6000
 ... thread: perf:5835
 .. dso: 
perf  5835  1227.459239:  1 cycles:ppp: 8fb4c 
[unknown] ([unknown])


Option to get only perf_arch_regs values:

$ ./perf record -I?
available registers: r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15 r16 
r17 r18 r19 r20 r21 r22 r23 r24 r25 r26 r27 r28 r29 r30 r31 nip msr orig_r3 ctr 
link xer ccr softe trap dar dsisr arch_regs

 Usage: perf record [] []
or: perf record [] --  []

-I, --intr-regs[=]
  sample selected machine registers on interrupt, use 
-I ? to list register names

$./perf record -Iarch_regs ls
.
$./perf script -D
.
104621404208 0xa28 [0xa8]: PERF_RECORD_SAMPLE(IP, 0x1): 5823/5823: 
0xc008fb4c period: 1 addr: 0
... intr regs: mask 0x800 ABI 64-bit
 arch_regs 0x7e7f
 pvr   0x4a0201
 pmc1  0x7fff
 pmc2  0x0
 pmc3  0x0
 pmc4  0x0
 pmc5  0x39551
 pmc6  0xe6d99
 mmcr0 0x82008080
 mmcr1 0x1e00
 sier  0x1e00
 siar  0xc008fb4c
 sdar  0xc0235f592500
 mmcra 0x6000
 ... thread: perf:5823
 .. dso: /boot/vmlinux
perf  5823   104.621404:  1 cycles:ppp:  c008fb4c 
.power_check_constraints (/boot/vmlinux)


RFC:

https://lkml.org/lkml/2015/11/4/530
https://lkml.org/lkml/2015/11/4/531
https://lkml.org/lkml/2015/11/4/532
https://lkml.org/lkml/2015/11/4/533

Patch 11 in this patchset is a fix which is already posted, but not yet
to be pulled in. So I have added that to this patchset.

https://patchwork.kernel.org/patch/9285421/

Kindly let me know you comments and feedbacks.
Madhavan Srinivasan (13):
  perf/core: Add perf_arch_regs and mask to perf_regs structure
  perf/core: Extend perf_sample_regs_intr() to include perf_arch_regs
update
  perf/core: Update perf_*_sample() to include perf_arch_regs
  perf/core: Extend perf_output_sample_regs() to include perf_arch_regs
  powerpc/perf: Define enums for perf_arch_regs registers
  powerpc/perf: Add support for perf_arch_regs in powerpc
  powerpc/perf: Add support for perf_arch_regs for Power7 processor
  powerpc/perf: Add support for perf_arch_regs for newer Power processor
  powerpc/perf: Add support for perf_arch_regs for PPC970 processor
  tool/perf: Add support for perf_arch_regs
  tool

[PATCH 01/13] perf/core: Add perf_arch_regs and mask to perf_regs structure

2016-08-28 Thread Madhavan Srinivasan
It's a perennial request from hardware folks to be able to
see the raw values of the pmu registers. Partly it's so that
they can verify perf is doing what they want, and some
of it is that they're interested in some of the more obscure
info that isn't plumbed out through other perf interfaces.

Over the years internally have used various hack to get
the requested data out but this is an attempt to use a
somewhat standard mechanism (using PERF_SAMPLE_REGS_INTR).

This would also be helpful for those of us working on the perf
hardware backends, to be able to verify that we're programming
things correctly, without resorting to debug printks etc.

Mechanism proposed:

1)perf_regs structure is extended with a perf_arch_regs structure
which each arch/ can populate with their specific platform
registers to sample on each perf interrupt and an arch_regs_mask
variable, which is for perf tool to know about the perf_arch_regs
that are supported.

2)perf/core func perf_sample_regs_intr() extended to update
the perf_arch_regs structure and the perf_arch_reg_mask. Set of new
support functions added perf_get_arch_regs_mask() and
perf_get_arch_reg() to aid the updates from arch/ side.

3) perf/core funcs perf_prepare_sample() and perf_output_sample()
are extended to support the update for the perf_arch_regs_mask and
perf_arch_regs in the sample

4)perf/core func perf_output_sample_regs() extended to dump
the arch_regs to the output sample.

5)Finally, perf tool side is updated a) to include a new element
"arch_regs_mask" in the "struct regs_dump", b) event sample funcs
to updated to include "arch_regs_mask" and c) print functions
are updated.

This foundation patch just extends the perf_regs structure, defines
support function and subsequent patches completes the implimentation
for powerpc arch.

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Ingo Molnar <mi...@kernel.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Arnaldo Carvalho de Melo <a...@kernel.org>
Cc: Stephane Eranian <eran...@gmail.com>
Cc: Russell King <li...@arm.linux.org.uk>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
Cc: Benjamin Herrenschmidt <b...@kernel.crashing.org>
Cc: Michael Ellerman <m...@ellerman.id.au>
Cc: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com>
Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
 include/linux/perf_regs.h | 26 ++
 kernel/events/core.c  | 16 
 2 files changed, 42 insertions(+)

diff --git a/include/linux/perf_regs.h b/include/linux/perf_regs.h
index a5f98d53d732..bd19b15703e2 100644
--- a/include/linux/perf_regs.h
+++ b/include/linux/perf_regs.h
@@ -4,8 +4,14 @@
 struct perf_regs {
__u64   abi;
struct pt_regs  *regs;
+   struct perf_arch_regs   *arch_regs;
+   u64 arch_regs_mask;
 };
 
+#ifndef perf_arch_regs
+struct perf_arch_regs { };
+#endif
+
 #ifdef CONFIG_HAVE_PERF_REGS
 #include 
 u64 perf_reg_value(struct pt_regs *regs, int idx);
@@ -14,6 +20,11 @@ u64 perf_reg_abi(struct task_struct *task);
 void perf_get_regs_user(struct perf_regs *regs_user,
struct pt_regs *regs,
struct pt_regs *regs_user_copy);
+
+u64 perf_get_arch_regs_mask(void);
+struct perf_arch_regs *perf_get_arch_reg(void);
+u64 perf_arch_reg_value(struct perf_arch_regs *regs, int idx);
+
 #else
 static inline u64 perf_reg_value(struct pt_regs *regs, int idx)
 {
@@ -37,5 +48,20 @@ static inline void perf_get_regs_user(struct perf_regs 
*regs_user,
regs_user->regs = task_pt_regs(current);
regs_user->abi = perf_reg_abi(current);
 }
+
+u64 perf_get_arch_regs_mask(void)
+{
+   return 0;
+}
+
+struct perf_arch_regs *perf_get_arch_reg(void)
+{
+   return 0;
+}
+
+u64 perf_arch_reg_value(struct perf_arch_regs *regs, int idx)
+{
+   return 0;
+}
 #endif /* CONFIG_HAVE_PERF_REGS */
 #endif /* _LINUX_PERF_REGS_H */
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 3f07e6cfc1b6..2f6e6a16b117 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5353,6 +5353,22 @@ int perf_unregister_guest_info_callbacks(struct 
perf_guest_info_callbacks *cbs)
 }
 EXPORT_SYMBOL_GPL(perf_unregister_guest_info_callbacks);
 
+u64 __attribute__((weak)) perf_get_arch_regs_mask()
+{
+   return 0;
+}
+
+struct perf_arch_regs *__attribute__((weak)) perf_get_arch_reg()
+{
+   return 0;
+}
+
+u64 __attribute__((weak)) perf_arch_reg_value(struct perf_arch_regs *regs,
+   int idx)
+{
+   return 0;
+}
+
 static void
 perf_output_sample_regs(struct perf_output_handle *handle,
struct pt_regs *regs, u64 mask)
-- 
2.7.4



[PATCH 02/13] perf/core: Extend perf_sample_regs_intr() to include perf_arch_regs update

2016-08-28 Thread Madhavan Srinivasan
Extend perf_sample_regs_intr() to support the updates needed for
perf_arch_reg structure and perf_arch_regs_mask. Also add code to
init the arch_regs_mask to zero incase of regs_user in
perf_sample_regs_user(). Ideally this should be done in perf_sample_data_init,
but due to commit 2565711fb7d7 ("perf: Improve the perf_sample_data struct 
layout")
moving it to this function.

Cc: Thomas Gleixner 
Cc: Ingo Molnar 
Cc: Peter Zijlstra 
Cc: Jiri Olsa 
Cc: Arnaldo Carvalho de Melo 
Cc: Stephane Eranian 
Cc: Russell King 
Cc: Catalin Marinas 
Cc: Will Deacon 
Cc: Benjamin Herrenschmidt 
Cc: Michael Ellerman 
Cc: Sukadev Bhattiprolu 
Signed-off-by: Madhavan Srinivasan 
---
 kernel/events/core.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 2f6e6a16b117..8cf540275c34 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5398,6 +5398,9 @@ static void perf_sample_regs_user(struct perf_regs 
*regs_user,
regs_user->abi = PERF_SAMPLE_REGS_ABI_NONE;
regs_user->regs = NULL;
}
+
+   /* Init arch_regs_mask to zero */
+   regs_user->arch_regs_mask = 0;
 }
 
 static void perf_sample_regs_intr(struct perf_regs *regs_intr,
@@ -5405,6 +5408,8 @@ static void perf_sample_regs_intr(struct perf_regs 
*regs_intr,
 {
regs_intr->regs = regs;
regs_intr->abi  = perf_reg_abi(current);
+   regs_intr->arch_regs_mask = perf_get_arch_regs_mask();
+   regs_intr->arch_regs = perf_get_arch_reg();
 }
 
 
-- 
2.7.4



[PATCH 00/13] Add support for perf_arch_regs

2016-08-28 Thread Madhavan Srinivasan
Patchset to extend PERF_SAMPLE_REGS_INTR to include
platform specific PMU registers.

Patchset applies cleanly on tip:perf/core branch

It's a perennial request from hardware folks to be able to
see the raw values of the pmu registers. Partly it's so that
they can verify perf is doing what they want, and some
of it is that they're interested in some of the more obscure
info that isn't plumbed out through other perf interfaces.

Over the years internally we have used various hack to get
the requested data out but this is an attempt to use a
somewhat standard mechanism (using PERF_SAMPLE_REGS_INTR).

This would also be helpful for those of us working on the perf
hardware backends, to be able to verify that we're programming
things correctly, without resorting to debug printks etc.

Mechanism proposed:

1)perf_regs structure is extended with a perf_arch_regs structure
which each arch/ can populate with their specific platform
registers to sample on each perf interrupt and an arch_regs_mask
variable, which is for perf tool to know about the perf_arch_regs
that are supported.

2)perf/core func perf_sample_regs_intr() extended to update
the perf_arch_regs structure and the perf_arch_reg_mask. Set of new
support functions added perf_get_arch_regs_mask() and
perf_get_arch_reg() to aid the updates from arch/ side.

3) perf/core funcs perf_prepare_sample() and perf_output_sample()
are extended to support the update for the perf_arch_regs_mask and
perf_arch_regs in the sample

4)perf/core func perf_output_sample_regs() extended to dump
the arch_regs to the output sample.

5)Finally, perf tool side is updated to include a new element
"arch_regs_mask" in the "struct regs_dump", event sample funcs
and print functions are updated to support perf_arch_regs.

example usage:

$./perf record -I ls
.
builtin-data.o   builtin-list.obuiltin-stat.cDocumentation  
  perf.h
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.009 MB perf.data (12 samples) ]
$./perf script -D

0x980 [0x200]: event: 9
.
. ... raw event: size 512 bytes
.  :  00 00 00 09 00 01 02 00 00 00 00 00 00 08 fb 4c  ...L
.  0010:  00 00 16 cb 00 00 16 cb 00 00 01 1d ca 45 9f 52  .E.R
.  0020:  00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 02  
...
 dsisr 0x6000
 arch_regs 0x7e7f
 pvr   0x4a0201
 pmc1  0x7fff
 pmc2  0x0
 pmc3  0x0
 pmc4  0x0
 pmc5  0xa03
 pmc6  0x38df
 mmcr0 0x82008080
 mmcr1 0x1e00
 sier  0x1e00
 siar  0x8fb4c
 sdar  0xc0241b195100
 mmcra 0x6000
 ... thread: perf:5835
 .. dso: 
perf  5835  1227.459239:  1 cycles:ppp: 8fb4c 
[unknown] ([unknown])


Option to get only perf_arch_regs values:

$ ./perf record -I?
available registers: r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15 r16 
r17 r18 r19 r20 r21 r22 r23 r24 r25 r26 r27 r28 r29 r30 r31 nip msr orig_r3 ctr 
link xer ccr softe trap dar dsisr arch_regs

 Usage: perf record [] []
or: perf record [] --  []

-I, --intr-regs[=]
  sample selected machine registers on interrupt, use 
-I ? to list register names

$./perf record -Iarch_regs ls
.
$./perf script -D
.
104621404208 0xa28 [0xa8]: PERF_RECORD_SAMPLE(IP, 0x1): 5823/5823: 
0xc008fb4c period: 1 addr: 0
... intr regs: mask 0x800 ABI 64-bit
 arch_regs 0x7e7f
 pvr   0x4a0201
 pmc1  0x7fff
 pmc2  0x0
 pmc3  0x0
 pmc4  0x0
 pmc5  0x39551
 pmc6  0xe6d99
 mmcr0 0x82008080
 mmcr1 0x1e00
 sier  0x1e00
 siar  0xc008fb4c
 sdar  0xc0235f592500
 mmcra 0x6000
 ... thread: perf:5823
 .. dso: /boot/vmlinux
perf  5823   104.621404:  1 cycles:ppp:  c008fb4c 
.power_check_constraints (/boot/vmlinux)


RFC:

https://lkml.org/lkml/2015/11/4/530
https://lkml.org/lkml/2015/11/4/531
https://lkml.org/lkml/2015/11/4/532
https://lkml.org/lkml/2015/11/4/533

Patch 11 in this patchset is a fix which is already posted, but not yet
to be pulled in. So I have added that to this patchset.

https://patchwork.kernel.org/patch/9285421/

Kindly let me know you comments and feedbacks.
Madhavan Srinivasan (13):
  perf/core: Add perf_arch_regs and mask to perf_regs structure
  perf/core: Extend perf_sample_regs_intr() to include perf_arch_regs
update
  perf/core: Update perf_*_sample() to include perf_arch_regs
  perf/core: Extend perf_output_sample_regs() to include perf_arch_regs
  powerpc/perf: Define enums for perf_arch_regs registers
  powerpc/perf: Add support for perf_arch_regs in powerpc
  powerpc/perf: Add support for perf_arch_regs for Power7 processor
  powerpc/perf: Add support for perf_arch_regs for newer Power processor
  powerpc/perf: Add support for perf_arch_regs for PPC970 processor
  tool/perf: Add support for perf_arch_regs
  tool

[PATCH 01/13] perf/core: Add perf_arch_regs and mask to perf_regs structure

2016-08-28 Thread Madhavan Srinivasan
It's a perennial request from hardware folks to be able to
see the raw values of the pmu registers. Partly it's so that
they can verify perf is doing what they want, and some
of it is that they're interested in some of the more obscure
info that isn't plumbed out through other perf interfaces.

Over the years internally have used various hack to get
the requested data out but this is an attempt to use a
somewhat standard mechanism (using PERF_SAMPLE_REGS_INTR).

This would also be helpful for those of us working on the perf
hardware backends, to be able to verify that we're programming
things correctly, without resorting to debug printks etc.

Mechanism proposed:

1)perf_regs structure is extended with a perf_arch_regs structure
which each arch/ can populate with their specific platform
registers to sample on each perf interrupt and an arch_regs_mask
variable, which is for perf tool to know about the perf_arch_regs
that are supported.

2)perf/core func perf_sample_regs_intr() extended to update
the perf_arch_regs structure and the perf_arch_reg_mask. Set of new
support functions added perf_get_arch_regs_mask() and
perf_get_arch_reg() to aid the updates from arch/ side.

3) perf/core funcs perf_prepare_sample() and perf_output_sample()
are extended to support the update for the perf_arch_regs_mask and
perf_arch_regs in the sample

4)perf/core func perf_output_sample_regs() extended to dump
the arch_regs to the output sample.

5)Finally, perf tool side is updated a) to include a new element
"arch_regs_mask" in the "struct regs_dump", b) event sample funcs
to updated to include "arch_regs_mask" and c) print functions
are updated.

This foundation patch just extends the perf_regs structure, defines
support function and subsequent patches completes the implimentation
for powerpc arch.

Cc: Thomas Gleixner 
Cc: Ingo Molnar 
Cc: Peter Zijlstra 
Cc: Jiri Olsa 
Cc: Arnaldo Carvalho de Melo 
Cc: Stephane Eranian 
Cc: Russell King 
Cc: Catalin Marinas 
Cc: Will Deacon 
Cc: Benjamin Herrenschmidt 
Cc: Michael Ellerman 
Cc: Sukadev Bhattiprolu 
Signed-off-by: Madhavan Srinivasan 
---
 include/linux/perf_regs.h | 26 ++
 kernel/events/core.c  | 16 
 2 files changed, 42 insertions(+)

diff --git a/include/linux/perf_regs.h b/include/linux/perf_regs.h
index a5f98d53d732..bd19b15703e2 100644
--- a/include/linux/perf_regs.h
+++ b/include/linux/perf_regs.h
@@ -4,8 +4,14 @@
 struct perf_regs {
__u64   abi;
struct pt_regs  *regs;
+   struct perf_arch_regs   *arch_regs;
+   u64 arch_regs_mask;
 };
 
+#ifndef perf_arch_regs
+struct perf_arch_regs { };
+#endif
+
 #ifdef CONFIG_HAVE_PERF_REGS
 #include 
 u64 perf_reg_value(struct pt_regs *regs, int idx);
@@ -14,6 +20,11 @@ u64 perf_reg_abi(struct task_struct *task);
 void perf_get_regs_user(struct perf_regs *regs_user,
struct pt_regs *regs,
struct pt_regs *regs_user_copy);
+
+u64 perf_get_arch_regs_mask(void);
+struct perf_arch_regs *perf_get_arch_reg(void);
+u64 perf_arch_reg_value(struct perf_arch_regs *regs, int idx);
+
 #else
 static inline u64 perf_reg_value(struct pt_regs *regs, int idx)
 {
@@ -37,5 +48,20 @@ static inline void perf_get_regs_user(struct perf_regs 
*regs_user,
regs_user->regs = task_pt_regs(current);
regs_user->abi = perf_reg_abi(current);
 }
+
+u64 perf_get_arch_regs_mask(void)
+{
+   return 0;
+}
+
+struct perf_arch_regs *perf_get_arch_reg(void)
+{
+   return 0;
+}
+
+u64 perf_arch_reg_value(struct perf_arch_regs *regs, int idx)
+{
+   return 0;
+}
 #endif /* CONFIG_HAVE_PERF_REGS */
 #endif /* _LINUX_PERF_REGS_H */
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 3f07e6cfc1b6..2f6e6a16b117 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5353,6 +5353,22 @@ int perf_unregister_guest_info_callbacks(struct 
perf_guest_info_callbacks *cbs)
 }
 EXPORT_SYMBOL_GPL(perf_unregister_guest_info_callbacks);
 
+u64 __attribute__((weak)) perf_get_arch_regs_mask()
+{
+   return 0;
+}
+
+struct perf_arch_regs *__attribute__((weak)) perf_get_arch_reg()
+{
+   return 0;
+}
+
+u64 __attribute__((weak)) perf_arch_reg_value(struct perf_arch_regs *regs,
+   int idx)
+{
+   return 0;
+}
+
 static void
 perf_output_sample_regs(struct perf_output_handle *handle,
struct pt_regs *regs, u64 mask)
-- 
2.7.4



[tip:perf/core] bitmap.h, perf/core: Fix the mask in perf_output_sample_regs()

2016-08-18 Thread tip-bot for Madhavan Srinivasan
Commit-ID:  29dd3288705f26cc27663e79061209dabce2d5b9
Gitweb: http://git.kernel.org/tip/29dd3288705f26cc27663e79061209dabce2d5b9
Author: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
AuthorDate: Wed, 17 Aug 2016 15:06:08 +0530
Committer:  Ingo Molnar <mi...@kernel.org>
CommitDate: Thu, 18 Aug 2016 10:44:20 +0200

bitmap.h, perf/core: Fix the mask in perf_output_sample_regs()

When decoding the perf_regs mask in perf_output_sample_regs(),
we loop through the mask using find_first_bit and find_next_bit functions.

While the exisiting code works fine in most of the case, the logic
is broken for big-endian 32-bit kernels.

When reading a u64 mask using (u32 *)()[0], find_*_bit() assumes
that it gets the lower 32 bits of u64, but instead it gets the upper
32 bits - which is wrong.

The fix is to swap the words of the u64 to handle this case.
This is _not_ a regular endianness swap.

Suggested-by: Yury Norov <yno...@caviumnetworks.com>
Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
Signed-off-by: Peter Zijlstra (Intel) <pet...@infradead.org>
Reviewed-by: Yury Norov <yno...@caviumnetworks.com>
Cc: Alexander Shishkin <alexander.shish...@linux.intel.com>
Cc: Arnaldo Carvalho de Melo <a...@kernel.org>
Cc: Arnaldo Carvalho de Melo <a...@redhat.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Jiri Olsa <jo...@redhat.com>
Cc: Linus Torvalds <torva...@linux-foundation.org>
Cc: Michael Ellerman <m...@ellerman.id.au>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Stephane Eranian <eran...@google.com>
Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Vince Weaver <vincent.wea...@maine.edu>
Cc: linuxppc-...@lists.ozlabs.org
Link: 
http://lkml.kernel.org/r/1471426568-31051-2-git-send-email-ma...@linux.vnet.ibm.com
Signed-off-by: Ingo Molnar <mi...@kernel.org>
---
 include/linux/bitmap.h | 18 ++
 kernel/events/core.c   |  5 +++--
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index 598bc99..3b77588 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -339,6 +339,24 @@ static inline int bitmap_parse(const char *buf, unsigned 
int buflen,
return __bitmap_parse(buf, buflen, 0, maskp, nmaskbits);
 }
 
+/*
+ * bitmap_from_u64 - Check and swap words within u64.
+ *  @mask: source bitmap
+ *  @dst:  destination bitmap
+ *
+ * In 32-bit Big Endian kernel, when using (u32 *)()[*]
+ * to read u64 mask, we will get the wrong word.
+ * That is "(u32 *)()[0]" gets the upper 32 bits,
+ * but we expect the lower 32-bits of u64.
+ */
+static inline void bitmap_from_u64(unsigned long *dst, u64 mask)
+{
+   dst[0] = mask & ULONG_MAX;
+
+   if (sizeof(mask) > sizeof(unsigned long))
+   dst[1] = mask >> 32;
+}
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __LINUX_BITMAP_H */
diff --git a/kernel/events/core.c b/kernel/events/core.c
index ca4fde5..849919c 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5340,9 +5340,10 @@ perf_output_sample_regs(struct perf_output_handle 
*handle,
struct pt_regs *regs, u64 mask)
 {
int bit;
+   DECLARE_BITMAP(_mask, 64);
 
-   for_each_set_bit(bit, (const unsigned long *) ,
-sizeof(mask) * BITS_PER_BYTE) {
+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(bit, _mask, sizeof(mask) * BITS_PER_BYTE) {
u64 val;
 
val = perf_reg_value(regs, bit);


[tip:perf/core] bitmap.h, perf/core: Fix the mask in perf_output_sample_regs()

2016-08-18 Thread tip-bot for Madhavan Srinivasan
Commit-ID:  29dd3288705f26cc27663e79061209dabce2d5b9
Gitweb: http://git.kernel.org/tip/29dd3288705f26cc27663e79061209dabce2d5b9
Author: Madhavan Srinivasan 
AuthorDate: Wed, 17 Aug 2016 15:06:08 +0530
Committer:  Ingo Molnar 
CommitDate: Thu, 18 Aug 2016 10:44:20 +0200

bitmap.h, perf/core: Fix the mask in perf_output_sample_regs()

When decoding the perf_regs mask in perf_output_sample_regs(),
we loop through the mask using find_first_bit and find_next_bit functions.

While the exisiting code works fine in most of the case, the logic
is broken for big-endian 32-bit kernels.

When reading a u64 mask using (u32 *)()[0], find_*_bit() assumes
that it gets the lower 32 bits of u64, but instead it gets the upper
32 bits - which is wrong.

The fix is to swap the words of the u64 to handle this case.
This is _not_ a regular endianness swap.

Suggested-by: Yury Norov 
Signed-off-by: Madhavan Srinivasan 
Signed-off-by: Peter Zijlstra (Intel) 
Reviewed-by: Yury Norov 
Cc: Alexander Shishkin 
Cc: Arnaldo Carvalho de Melo 
Cc: Arnaldo Carvalho de Melo 
Cc: Jiri Olsa 
Cc: Jiri Olsa 
Cc: Linus Torvalds 
Cc: Michael Ellerman 
Cc: Peter Zijlstra 
Cc: Stephane Eranian 
Cc: Thomas Gleixner 
Cc: Vince Weaver 
Cc: linuxppc-...@lists.ozlabs.org
Link: 
http://lkml.kernel.org/r/1471426568-31051-2-git-send-email-ma...@linux.vnet.ibm.com
Signed-off-by: Ingo Molnar 
---
 include/linux/bitmap.h | 18 ++
 kernel/events/core.c   |  5 +++--
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index 598bc99..3b77588 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -339,6 +339,24 @@ static inline int bitmap_parse(const char *buf, unsigned 
int buflen,
return __bitmap_parse(buf, buflen, 0, maskp, nmaskbits);
 }
 
+/*
+ * bitmap_from_u64 - Check and swap words within u64.
+ *  @mask: source bitmap
+ *  @dst:  destination bitmap
+ *
+ * In 32-bit Big Endian kernel, when using (u32 *)()[*]
+ * to read u64 mask, we will get the wrong word.
+ * That is "(u32 *)()[0]" gets the upper 32 bits,
+ * but we expect the lower 32-bits of u64.
+ */
+static inline void bitmap_from_u64(unsigned long *dst, u64 mask)
+{
+   dst[0] = mask & ULONG_MAX;
+
+   if (sizeof(mask) > sizeof(unsigned long))
+   dst[1] = mask >> 32;
+}
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __LINUX_BITMAP_H */
diff --git a/kernel/events/core.c b/kernel/events/core.c
index ca4fde5..849919c 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5340,9 +5340,10 @@ perf_output_sample_regs(struct perf_output_handle 
*handle,
struct pt_regs *regs, u64 mask)
 {
int bit;
+   DECLARE_BITMAP(_mask, 64);
 
-   for_each_set_bit(bit, (const unsigned long *) ,
-sizeof(mask) * BITS_PER_BYTE) {
+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(bit, _mask, sizeof(mask) * BITS_PER_BYTE) {
u64 val;
 
val = perf_reg_value(regs, bit);


[PATCH v6 1/2] tools/perf: Fix the mask in regs_dump__printf and print_sample_iregs

2016-08-17 Thread Madhavan Srinivasan
When decoding the perf_regs mask in regs_dump__printf(),
we loop through the mask using find_first_bit and find_next_bit functions.
"mask" is of type "u64", but sent as a "unsigned long *" to
lib functions along with sizeof().

While the exisitng code works fine in most of the case,
the logic is broken when using a 32bit perf on a 64bit kernel (Big Endian).
When reading u64 using (u32 *)()[0], perf (lib/find_*_bit()) assumes it gets
lower 32bits of u64 which is wrong. Proposed fix is to swap the words
of the u64 to handle this case. This is _not_ endianess swap.

Suggested-by: Yury Norov <yno...@caviumnetworks.com>
Reviewed-by: Yury Norov <yno...@caviumnetworks.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Yury Norov <yno...@caviumnetworks.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Ingo Molnar <mi...@redhat.com>
Cc: Arnaldo Carvalho de Melo <a...@kernel.org>
Cc: Alexander Shishkin <alexander.shish...@linux.intel.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Adrian Hunter <adrian.hun...@intel.com>
Cc: Kan Liang <kan.li...@intel.com>
Cc: Wang Nan <wangn...@huawei.com>
Cc: Michael Ellerman <m...@ellerman.id.au>
Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
Changelog v5:
1)No logic change, just upstream rebasing

Changelog v4:
1) Removed the new macro and resued the DECLARE_BITMAP

Changelog v3:
1)Moved the swap function to lib/bitmap.c
2)Added a macro for declaration
3)Added the comments

Changelog v2:
1)Moved the swap code to a common function
2)Added more comments in the code

Changelog v1:
1)updated commit message and patch subject
2)Add the fix to print_sample_iregs() in builtin-script.c

 tools/include/linux/bitmap.h |  2 ++
 tools/lib/bitmap.c   | 18 ++
 tools/perf/builtin-script.c  |  4 +++-
 tools/perf/util/session.c|  4 +++-
 4 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/tools/include/linux/bitmap.h b/tools/include/linux/bitmap.h
index 43c1c5021e4b..998ac95a8ddd 100644
--- a/tools/include/linux/bitmap.h
+++ b/tools/include/linux/bitmap.h
@@ -4,10 +4,12 @@
 #include 
 #include 
 #include 
+#include 
 
 #define DECLARE_BITMAP(name,bits) \
unsigned long name[BITS_TO_LONGS(bits)]
 
+void bitmap_from_u64(unsigned long *dst, u64 mask);
 int __bitmap_weight(const unsigned long *bitmap, int bits);
 void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
 const unsigned long *bitmap2, int bits);
diff --git a/tools/lib/bitmap.c b/tools/lib/bitmap.c
index 38748b0e342f..21e17730c35f 100644
--- a/tools/lib/bitmap.c
+++ b/tools/lib/bitmap.c
@@ -73,3 +73,21 @@ int __bitmap_and(unsigned long *dst, const unsigned long 
*bitmap1,
   BITMAP_LAST_WORD_MASK(bits));
return result != 0;
 }
+
+/*
+ * bitmap_from_u64 - Check and swap words within u64.
+ *  @mask: source bitmap
+ *  @dst:  destination bitmap
+ *
+ * In 32 bit big endian userspace on a 64bit kernel, 'unsigned long' is 32 
bits.
+ * When reading u64 using (u32 *)()[0] and (u32 *)()[1],
+ * we will get wrong value for the mask. That is "(u32 *)()[0]"
+ * gets upper 32 bits of u64, but perf may expect lower 32bits of u64.
+ */
+void bitmap_from_u64(unsigned long *dst, u64 mask)
+{
+   dst[0] = mask & ULONG_MAX;
+
+   if (sizeof(mask) > sizeof(unsigned long))
+   dst[1] = mask >> 32;
+}
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 9c640a8081c7..4b8de4f99a11 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -418,11 +418,13 @@ static void print_sample_iregs(struct perf_sample *sample,
struct regs_dump *regs = >intr_regs;
uint64_t mask = attr->sample_regs_intr;
unsigned i = 0, r;
+   DECLARE_BITMAP(_mask, 64);
 
if (!regs)
return;
 
-   for_each_set_bit(r, (unsigned long *) , sizeof(mask) * 8) {
+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(r, _mask, sizeof(mask) * 8) {
u64 val = regs->regs[i++];
printf("%5s:0x%"PRIx64" ", perf_reg_name(r), val);
}
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 5d61242a6e64..440a9fb2a6fb 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -944,8 +944,10 @@ static void branch_stack__printf(struct perf_sample 
*sample)
 static void regs_dump__printf(u64 mask, u64 *regs)
 {
unsigned rid, i = 0;
+   DECLARE_BITMAP(_mask, 64);
 
-   for_each_set_bit(rid, (unsigned long *) , sizeof(mask) * 8) {
+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(rid, _mask, sizeof(mask) * 8) {
u64 val = regs[i++];
 
printf(" %-5s 0x%" PRIx64 "\n",
-- 
2.7.4



[PATCH v6 1/2] tools/perf: Fix the mask in regs_dump__printf and print_sample_iregs

2016-08-17 Thread Madhavan Srinivasan
When decoding the perf_regs mask in regs_dump__printf(),
we loop through the mask using find_first_bit and find_next_bit functions.
"mask" is of type "u64", but sent as a "unsigned long *" to
lib functions along with sizeof().

While the exisitng code works fine in most of the case,
the logic is broken when using a 32bit perf on a 64bit kernel (Big Endian).
When reading u64 using (u32 *)()[0], perf (lib/find_*_bit()) assumes it gets
lower 32bits of u64 which is wrong. Proposed fix is to swap the words
of the u64 to handle this case. This is _not_ endianess swap.

Suggested-by: Yury Norov 
Reviewed-by: Yury Norov 
Acked-by: Jiri Olsa 
Cc: Yury Norov 
Cc: Peter Zijlstra 
Cc: Ingo Molnar 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexander Shishkin 
Cc: Jiri Olsa 
Cc: Adrian Hunter 
Cc: Kan Liang 
Cc: Wang Nan 
Cc: Michael Ellerman 
Signed-off-by: Madhavan Srinivasan 
---
Changelog v5:
1)No logic change, just upstream rebasing

Changelog v4:
1) Removed the new macro and resued the DECLARE_BITMAP

Changelog v3:
1)Moved the swap function to lib/bitmap.c
2)Added a macro for declaration
3)Added the comments

Changelog v2:
1)Moved the swap code to a common function
2)Added more comments in the code

Changelog v1:
1)updated commit message and patch subject
2)Add the fix to print_sample_iregs() in builtin-script.c

 tools/include/linux/bitmap.h |  2 ++
 tools/lib/bitmap.c   | 18 ++
 tools/perf/builtin-script.c  |  4 +++-
 tools/perf/util/session.c|  4 +++-
 4 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/tools/include/linux/bitmap.h b/tools/include/linux/bitmap.h
index 43c1c5021e4b..998ac95a8ddd 100644
--- a/tools/include/linux/bitmap.h
+++ b/tools/include/linux/bitmap.h
@@ -4,10 +4,12 @@
 #include 
 #include 
 #include 
+#include 
 
 #define DECLARE_BITMAP(name,bits) \
unsigned long name[BITS_TO_LONGS(bits)]
 
+void bitmap_from_u64(unsigned long *dst, u64 mask);
 int __bitmap_weight(const unsigned long *bitmap, int bits);
 void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
 const unsigned long *bitmap2, int bits);
diff --git a/tools/lib/bitmap.c b/tools/lib/bitmap.c
index 38748b0e342f..21e17730c35f 100644
--- a/tools/lib/bitmap.c
+++ b/tools/lib/bitmap.c
@@ -73,3 +73,21 @@ int __bitmap_and(unsigned long *dst, const unsigned long 
*bitmap1,
   BITMAP_LAST_WORD_MASK(bits));
return result != 0;
 }
+
+/*
+ * bitmap_from_u64 - Check and swap words within u64.
+ *  @mask: source bitmap
+ *  @dst:  destination bitmap
+ *
+ * In 32 bit big endian userspace on a 64bit kernel, 'unsigned long' is 32 
bits.
+ * When reading u64 using (u32 *)()[0] and (u32 *)()[1],
+ * we will get wrong value for the mask. That is "(u32 *)()[0]"
+ * gets upper 32 bits of u64, but perf may expect lower 32bits of u64.
+ */
+void bitmap_from_u64(unsigned long *dst, u64 mask)
+{
+   dst[0] = mask & ULONG_MAX;
+
+   if (sizeof(mask) > sizeof(unsigned long))
+   dst[1] = mask >> 32;
+}
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 9c640a8081c7..4b8de4f99a11 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -418,11 +418,13 @@ static void print_sample_iregs(struct perf_sample *sample,
struct regs_dump *regs = >intr_regs;
uint64_t mask = attr->sample_regs_intr;
unsigned i = 0, r;
+   DECLARE_BITMAP(_mask, 64);
 
if (!regs)
return;
 
-   for_each_set_bit(r, (unsigned long *) , sizeof(mask) * 8) {
+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(r, _mask, sizeof(mask) * 8) {
u64 val = regs->regs[i++];
printf("%5s:0x%"PRIx64" ", perf_reg_name(r), val);
}
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 5d61242a6e64..440a9fb2a6fb 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -944,8 +944,10 @@ static void branch_stack__printf(struct perf_sample 
*sample)
 static void regs_dump__printf(u64 mask, u64 *regs)
 {
unsigned rid, i = 0;
+   DECLARE_BITMAP(_mask, 64);
 
-   for_each_set_bit(rid, (unsigned long *) , sizeof(mask) * 8) {
+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(rid, _mask, sizeof(mask) * 8) {
u64 val = regs[i++];
 
printf(" %-5s 0x%" PRIx64 "\n",
-- 
2.7.4



[PATCH v2 2/2] perf/core: Fix the mask in perf_output_sample_regs

2016-08-17 Thread Madhavan Srinivasan
When decoding the perf_regs mask in perf_output_sample_regs(),
we loop through the mask using find_first_bit and find_next_bit functions.
While the exisitng code works fine in most of the case,
the logic is broken for 32bit kernel (Big Endian).
When reading u64 mask using (u32 *)()[0], find_*_bit() assumes it gets
lower 32bits of u64 but instead gets upper 32bits which is wrong.
Proposed fix is to swap the words of the u64 to handle this case.
This is _not_ endianness swap.

Suggested-by: Yury Norov <yno...@caviumnetworks.com>
Reviewed-by: Yury Norov <yno...@caviumnetworks.com>
Cc: Yury Norov <yno...@caviumnetworks.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Ingo Molnar <mi...@redhat.com>
Cc: Arnaldo Carvalho de Melo <a...@kernel.org>
Cc: Alexander Shishkin <alexander.shish...@linux.intel.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Michael Ellerman <m...@ellerman.id.au>
Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
Changelog v1:
1)bitmap_from_u64() is inline now

 include/linux/bitmap.h | 18 ++
 kernel/events/core.c   |  5 +++--
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index 598bc999f4c2..a9ea992161a1 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -339,6 +339,24 @@ static inline int bitmap_parse(const char *buf, unsigned 
int buflen,
return __bitmap_parse(buf, buflen, 0, maskp, nmaskbits);
 }
 
+/*
+ * bitmap_from_u64 - Check and swap words within u64.
+ *  @mask: source bitmap
+ *  @dst:  destination bitmap
+ *
+ * In 32bit Big Endian kernel, when using (u32 *)()[*]
+ * to read u64 mask, we will get wrong word.
+ * That is "(u32 *)()[0]" gets upper 32 bits,
+ * but expected could be lower 32bits of u64.
+ */
+static inline void bitmap_from_u64(unsigned long *dst, u64 mask)
+{
+   dst[0] = mask & ULONG_MAX;
+
+   if (sizeof(mask) > sizeof(unsigned long))
+   dst[1] = mask >> 32;
+}
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __LINUX_BITMAP_H */
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 1903b8f3a705..de32e9bd8189 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5292,9 +5292,10 @@ perf_output_sample_regs(struct perf_output_handle 
*handle,
struct pt_regs *regs, u64 mask)
 {
int bit;
+   DECLARE_BITMAP(_mask, 64);
 
-   for_each_set_bit(bit, (const unsigned long *) ,
-sizeof(mask) * BITS_PER_BYTE) {
+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(bit, _mask, sizeof(mask) * BITS_PER_BYTE) {
u64 val;
 
val = perf_reg_value(regs, bit);
-- 
2.7.4



[PATCH v2 2/2] perf/core: Fix the mask in perf_output_sample_regs

2016-08-17 Thread Madhavan Srinivasan
When decoding the perf_regs mask in perf_output_sample_regs(),
we loop through the mask using find_first_bit and find_next_bit functions.
While the exisitng code works fine in most of the case,
the logic is broken for 32bit kernel (Big Endian).
When reading u64 mask using (u32 *)()[0], find_*_bit() assumes it gets
lower 32bits of u64 but instead gets upper 32bits which is wrong.
Proposed fix is to swap the words of the u64 to handle this case.
This is _not_ endianness swap.

Suggested-by: Yury Norov 
Reviewed-by: Yury Norov 
Cc: Yury Norov 
Cc: Peter Zijlstra 
Cc: Ingo Molnar 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexander Shishkin 
Cc: Jiri Olsa 
Cc: Michael Ellerman 
Signed-off-by: Madhavan Srinivasan 
---
Changelog v1:
1)bitmap_from_u64() is inline now

 include/linux/bitmap.h | 18 ++
 kernel/events/core.c   |  5 +++--
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index 598bc999f4c2..a9ea992161a1 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -339,6 +339,24 @@ static inline int bitmap_parse(const char *buf, unsigned 
int buflen,
return __bitmap_parse(buf, buflen, 0, maskp, nmaskbits);
 }
 
+/*
+ * bitmap_from_u64 - Check and swap words within u64.
+ *  @mask: source bitmap
+ *  @dst:  destination bitmap
+ *
+ * In 32bit Big Endian kernel, when using (u32 *)()[*]
+ * to read u64 mask, we will get wrong word.
+ * That is "(u32 *)()[0]" gets upper 32 bits,
+ * but expected could be lower 32bits of u64.
+ */
+static inline void bitmap_from_u64(unsigned long *dst, u64 mask)
+{
+   dst[0] = mask & ULONG_MAX;
+
+   if (sizeof(mask) > sizeof(unsigned long))
+   dst[1] = mask >> 32;
+}
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __LINUX_BITMAP_H */
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 1903b8f3a705..de32e9bd8189 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5292,9 +5292,10 @@ perf_output_sample_regs(struct perf_output_handle 
*handle,
struct pt_regs *regs, u64 mask)
 {
int bit;
+   DECLARE_BITMAP(_mask, 64);
 
-   for_each_set_bit(bit, (const unsigned long *) ,
-sizeof(mask) * BITS_PER_BYTE) {
+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(bit, _mask, sizeof(mask) * BITS_PER_BYTE) {
u64 val;
 
val = perf_reg_value(regs, bit);
-- 
2.7.4



Re: [PATCH] perf/core: Fix the mask in perf_output_sample_regs

2016-08-15 Thread Madhavan Srinivasan



On Thursday 11 August 2016 05:57 PM, Peter Zijlstra wrote:

Sorry, found it in my inbox while clearing out backlog..

On Sun, Jul 03, 2016 at 11:31:58PM +0530, Madhavan Srinivasan wrote:

When decoding the perf_regs mask in perf_output_sample_regs(),
we loop through the mask using find_first_bit and find_next_bit functions.
While the exisitng code works fine in most of the case,
the logic is broken for 32bit kernel (Big Endian).
When reading u64 mask using (u32 *)()[0], find_*_bit() assumes it gets
lower 32bits of u64 but instead gets upper 32bits which is wrong.
Proposed fix is to swap the words of the u64 to handle this case.
This is _not_ endianness swap.

But it looks an awful lot like it..

Hit this issue when testing my perf_arch_regs patchset. Yep exactly
the reason for adding that comment in the commit message.





+++ b/kernel/events/core.c
@@ -5205,8 +5205,10 @@ perf_output_sample_regs(struct perf_output_handle 
*handle,
struct pt_regs *regs, u64 mask)
  {
int bit;
+   DECLARE_BITMAP(_mask, 64);
  
-	for_each_set_bit(bit, (const unsigned long *) ,

+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(bit, _mask,
 sizeof(mask) * BITS_PER_BYTE) {
u64 val;
+++ b/lib/bitmap.c
+void bitmap_from_u64(unsigned long *dst, u64 mask)
+{
+   dst[0] = mask & ULONG_MAX;
+
+   if (sizeof(mask) > sizeof(unsigned long))
+   dst[1] = mask >> 32;
+}
+EXPORT_SYMBOL(bitmap_from_u64);

Looks small enough for an inline.

Alternatively you can go all the way and add bitmap_from_u64array(), but
that seems massive overkill.


Ok will make it inline and resend.

Maddy



Tedious stuff.. I can't come up with anything prettier :/





Re: [PATCH] perf/core: Fix the mask in perf_output_sample_regs

2016-08-15 Thread Madhavan Srinivasan



On Thursday 11 August 2016 05:57 PM, Peter Zijlstra wrote:

Sorry, found it in my inbox while clearing out backlog..

On Sun, Jul 03, 2016 at 11:31:58PM +0530, Madhavan Srinivasan wrote:

When decoding the perf_regs mask in perf_output_sample_regs(),
we loop through the mask using find_first_bit and find_next_bit functions.
While the exisitng code works fine in most of the case,
the logic is broken for 32bit kernel (Big Endian).
When reading u64 mask using (u32 *)()[0], find_*_bit() assumes it gets
lower 32bits of u64 but instead gets upper 32bits which is wrong.
Proposed fix is to swap the words of the u64 to handle this case.
This is _not_ endianness swap.

But it looks an awful lot like it..

Hit this issue when testing my perf_arch_regs patchset. Yep exactly
the reason for adding that comment in the commit message.





+++ b/kernel/events/core.c
@@ -5205,8 +5205,10 @@ perf_output_sample_regs(struct perf_output_handle 
*handle,
struct pt_regs *regs, u64 mask)
  {
int bit;
+   DECLARE_BITMAP(_mask, 64);
  
-	for_each_set_bit(bit, (const unsigned long *) ,

+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(bit, _mask,
 sizeof(mask) * BITS_PER_BYTE) {
u64 val;
+++ b/lib/bitmap.c
+void bitmap_from_u64(unsigned long *dst, u64 mask)
+{
+   dst[0] = mask & ULONG_MAX;
+
+   if (sizeof(mask) > sizeof(unsigned long))
+   dst[1] = mask >> 32;
+}
+EXPORT_SYMBOL(bitmap_from_u64);

Looks small enough for an inline.

Alternatively you can go all the way and add bitmap_from_u64array(), but
that seems massive overkill.


Ok will make it inline and resend.

Maddy



Tedious stuff.. I can't come up with anything prettier :/





[RESENT PATCH v5 1/2] tools/perf: Fix the mask in regs_dump__printf and print_sample_iregs

2016-08-03 Thread Madhavan Srinivasan
When decoding the perf_regs mask in regs_dump__printf(),
we loop through the mask using find_first_bit and find_next_bit functions.
"mask" is of type "u64", but sent as a "unsigned long *" to
lib functions along with sizeof().

While the exisitng code works fine in most of the case,
the logic is broken when using a 32bit perf on a 64bit kernel (Big Endian).
When reading u64 using (u32 *)()[0], perf (lib/find_*_bit()) assumes it gets
lower 32bits of u64 which is wrong. Proposed fix is to swap the words
of the u64 to handle this case. This is _not_ endianess swap.

Suggested-by: Yury Norov <yno...@caviumnetworks.com>
Reviewed-by: Yury Norov <yno...@caviumnetworks.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Yury Norov <yno...@caviumnetworks.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Ingo Molnar <mi...@redhat.com>
Cc: Arnaldo Carvalho de Melo <a...@kernel.org>
Cc: Alexander Shishkin <alexander.shish...@linux.intel.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Adrian Hunter <adrian.hun...@intel.com>
Cc: Kan Liang <kan.li...@intel.com>
Cc: Wang Nan <wangn...@huawei.com>
Cc: Michael Ellerman <m...@ellerman.id.au>
Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
 tools/include/linux/bitmap.h |  2 ++
 tools/lib/bitmap.c   | 18 ++
 tools/perf/builtin-script.c  |  4 +++-
 tools/perf/util/session.c|  4 +++-
 4 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/tools/include/linux/bitmap.h b/tools/include/linux/bitmap.h
index 28f5493da491..5e98525387dc 100644
--- a/tools/include/linux/bitmap.h
+++ b/tools/include/linux/bitmap.h
@@ -2,6 +2,7 @@
 #define _PERF_BITOPS_H
 
 #include 
+#include 
 #include 
 
 #define DECLARE_BITMAP(name,bits) \
@@ -10,6 +11,7 @@
 int __bitmap_weight(const unsigned long *bitmap, int bits);
 void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
 const unsigned long *bitmap2, int bits);
+void bitmap_from_u64(unsigned long *dst, u64 mask);
 
 #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
 
diff --git a/tools/lib/bitmap.c b/tools/lib/bitmap.c
index 0a1adcfd..464a0cc63e6a 100644
--- a/tools/lib/bitmap.c
+++ b/tools/lib/bitmap.c
@@ -29,3 +29,21 @@ void __bitmap_or(unsigned long *dst, const unsigned long 
*bitmap1,
for (k = 0; k < nr; k++)
dst[k] = bitmap1[k] | bitmap2[k];
 }
+
+/*
+ * bitmap_from_u64 - Check and swap words within u64.
+ *  @mask: source bitmap
+ *  @dst:  destination bitmap
+ *
+ * In 32 bit big endian userspace on a 64bit kernel, 'unsigned long' is 32 
bits.
+ * When reading u64 using (u32 *)()[0] and (u32 *)()[1],
+ * we will get wrong value for the mask. That is "(u32 *)()[0]"
+ * gets upper 32 bits of u64, but perf may expect lower 32bits of u64.
+ */
+void bitmap_from_u64(unsigned long *dst, u64 mask)
+{
+   dst[0] = mask & ULONG_MAX;
+
+   if (sizeof(mask) > sizeof(unsigned long))
+   dst[1] = mask >> 32;
+}
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 971ff91b16cb..20d7988a1636 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -418,11 +418,13 @@ static void print_sample_iregs(struct perf_sample *sample,
struct regs_dump *regs = >intr_regs;
uint64_t mask = attr->sample_regs_intr;
unsigned i = 0, r;
+   DECLARE_BITMAP(_mask, 64);
 
if (!regs)
return;
 
-   for_each_set_bit(r, (unsigned long *) , sizeof(mask) * 8) {
+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(r, _mask, sizeof(mask) * 8) {
u64 val = regs->regs[i++];
printf("%5s:0x%"PRIx64" ", perf_reg_name(r), val);
}
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 5d61242a6e64..440a9fb2a6fb 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -944,8 +944,10 @@ static void branch_stack__printf(struct perf_sample 
*sample)
 static void regs_dump__printf(u64 mask, u64 *regs)
 {
unsigned rid, i = 0;
+   DECLARE_BITMAP(_mask, 64);
 
-   for_each_set_bit(rid, (unsigned long *) , sizeof(mask) * 8) {
+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(rid, _mask, sizeof(mask) * 8) {
u64 val = regs[i++];
 
printf(" %-5s 0x%" PRIx64 "\n",
-- 
2.7.4



[RESEND PATCH 2/2] perf/core: Fix the mask in perf_output_sample_regs

2016-08-03 Thread Madhavan Srinivasan
When decoding the perf_regs mask in perf_output_sample_regs(),
we loop through the mask using find_first_bit and find_next_bit functions.
While the exisitng code works fine in most of the case,
the logic is broken for 32bit kernel (Big Endian).
When reading u64 mask using (u32 *)()[0], find_*_bit() assumes it gets
lower 32bits of u64 but instead gets upper 32bits which is wrong.
Proposed fix is to swap the words of the u64 to handle this case.
This is _not_ endianness swap.

Suggested-by: Yury Norov <yno...@caviumnetworks.com>
Reviewed-by: Yury Norov <yno...@caviumnetworks.com>
Cc: Yury Norov <yno...@caviumnetworks.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Ingo Molnar <mi...@redhat.com>
Cc: Arnaldo Carvalho de Melo <a...@kernel.org>
Cc: Alexander Shishkin <alexander.shish...@linux.intel.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Michael Ellerman <m...@ellerman.id.au>
Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
 include/linux/bitmap.h |  2 ++
 kernel/events/core.c   |  4 +++-
 lib/bitmap.c   | 19 +++
 3 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index 27bfc0b631a9..6f2cc9eb12d9 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -188,6 +188,8 @@ extern int bitmap_print_to_pagebuf(bool list, char *buf,
 #define small_const_nbits(nbits) \
(__builtin_constant_p(nbits) && (nbits) <= BITS_PER_LONG)
 
+extern void bitmap_from_u64(unsigned long *dst, u64 mask);
+
 static inline void bitmap_zero(unsigned long *dst, unsigned int nbits)
 {
if (small_const_nbits(nbits))
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 356a6c7cb52a..f5ed20a63a5e 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5269,8 +5269,10 @@ perf_output_sample_regs(struct perf_output_handle 
*handle,
struct pt_regs *regs, u64 mask)
 {
int bit;
+   DECLARE_BITMAP(_mask, 64);
 
-   for_each_set_bit(bit, (const unsigned long *) ,
+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(bit, _mask,
 sizeof(mask) * BITS_PER_BYTE) {
u64 val;
 
diff --git a/lib/bitmap.c b/lib/bitmap.c
index eca88087fa8a..2b9bda507645 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -1170,3 +1170,22 @@ void bitmap_copy_le(unsigned long *dst, const unsigned 
long *src, unsigned int n
 }
 EXPORT_SYMBOL(bitmap_copy_le);
 #endif
+
+/*
+ * bitmap_from_u64 - Check and swap words within u64.
+ *  @mask: source bitmap
+ *  @dst:  destination bitmap
+ *
+ * In 32bit Big Endian kernel, when using (u32 *)()[*]
+ * to read u64 mask, we will get wrong word.
+ * That is "(u32 *)()[0]" gets upper 32 bits,
+ * but expected could be lower 32bits of u64.
+ */
+void bitmap_from_u64(unsigned long *dst, u64 mask)
+{
+   dst[0] = mask & ULONG_MAX;
+
+   if (sizeof(mask) > sizeof(unsigned long))
+   dst[1] = mask >> 32;
+}
+EXPORT_SYMBOL(bitmap_from_u64);
-- 
2.7.4



[RESENT PATCH v5 1/2] tools/perf: Fix the mask in regs_dump__printf and print_sample_iregs

2016-08-03 Thread Madhavan Srinivasan
When decoding the perf_regs mask in regs_dump__printf(),
we loop through the mask using find_first_bit and find_next_bit functions.
"mask" is of type "u64", but sent as a "unsigned long *" to
lib functions along with sizeof().

While the exisitng code works fine in most of the case,
the logic is broken when using a 32bit perf on a 64bit kernel (Big Endian).
When reading u64 using (u32 *)()[0], perf (lib/find_*_bit()) assumes it gets
lower 32bits of u64 which is wrong. Proposed fix is to swap the words
of the u64 to handle this case. This is _not_ endianess swap.

Suggested-by: Yury Norov 
Reviewed-by: Yury Norov 
Acked-by: Jiri Olsa 
Cc: Yury Norov 
Cc: Peter Zijlstra 
Cc: Ingo Molnar 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexander Shishkin 
Cc: Jiri Olsa 
Cc: Adrian Hunter 
Cc: Kan Liang 
Cc: Wang Nan 
Cc: Michael Ellerman 
Signed-off-by: Madhavan Srinivasan 
---
 tools/include/linux/bitmap.h |  2 ++
 tools/lib/bitmap.c   | 18 ++
 tools/perf/builtin-script.c  |  4 +++-
 tools/perf/util/session.c|  4 +++-
 4 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/tools/include/linux/bitmap.h b/tools/include/linux/bitmap.h
index 28f5493da491..5e98525387dc 100644
--- a/tools/include/linux/bitmap.h
+++ b/tools/include/linux/bitmap.h
@@ -2,6 +2,7 @@
 #define _PERF_BITOPS_H
 
 #include 
+#include 
 #include 
 
 #define DECLARE_BITMAP(name,bits) \
@@ -10,6 +11,7 @@
 int __bitmap_weight(const unsigned long *bitmap, int bits);
 void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
 const unsigned long *bitmap2, int bits);
+void bitmap_from_u64(unsigned long *dst, u64 mask);
 
 #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
 
diff --git a/tools/lib/bitmap.c b/tools/lib/bitmap.c
index 0a1adcfd..464a0cc63e6a 100644
--- a/tools/lib/bitmap.c
+++ b/tools/lib/bitmap.c
@@ -29,3 +29,21 @@ void __bitmap_or(unsigned long *dst, const unsigned long 
*bitmap1,
for (k = 0; k < nr; k++)
dst[k] = bitmap1[k] | bitmap2[k];
 }
+
+/*
+ * bitmap_from_u64 - Check and swap words within u64.
+ *  @mask: source bitmap
+ *  @dst:  destination bitmap
+ *
+ * In 32 bit big endian userspace on a 64bit kernel, 'unsigned long' is 32 
bits.
+ * When reading u64 using (u32 *)()[0] and (u32 *)()[1],
+ * we will get wrong value for the mask. That is "(u32 *)()[0]"
+ * gets upper 32 bits of u64, but perf may expect lower 32bits of u64.
+ */
+void bitmap_from_u64(unsigned long *dst, u64 mask)
+{
+   dst[0] = mask & ULONG_MAX;
+
+   if (sizeof(mask) > sizeof(unsigned long))
+   dst[1] = mask >> 32;
+}
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 971ff91b16cb..20d7988a1636 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -418,11 +418,13 @@ static void print_sample_iregs(struct perf_sample *sample,
struct regs_dump *regs = >intr_regs;
uint64_t mask = attr->sample_regs_intr;
unsigned i = 0, r;
+   DECLARE_BITMAP(_mask, 64);
 
if (!regs)
return;
 
-   for_each_set_bit(r, (unsigned long *) , sizeof(mask) * 8) {
+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(r, _mask, sizeof(mask) * 8) {
u64 val = regs->regs[i++];
printf("%5s:0x%"PRIx64" ", perf_reg_name(r), val);
}
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 5d61242a6e64..440a9fb2a6fb 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -944,8 +944,10 @@ static void branch_stack__printf(struct perf_sample 
*sample)
 static void regs_dump__printf(u64 mask, u64 *regs)
 {
unsigned rid, i = 0;
+   DECLARE_BITMAP(_mask, 64);
 
-   for_each_set_bit(rid, (unsigned long *) , sizeof(mask) * 8) {
+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(rid, _mask, sizeof(mask) * 8) {
u64 val = regs[i++];
 
printf(" %-5s 0x%" PRIx64 "\n",
-- 
2.7.4



[RESEND PATCH 2/2] perf/core: Fix the mask in perf_output_sample_regs

2016-08-03 Thread Madhavan Srinivasan
When decoding the perf_regs mask in perf_output_sample_regs(),
we loop through the mask using find_first_bit and find_next_bit functions.
While the exisitng code works fine in most of the case,
the logic is broken for 32bit kernel (Big Endian).
When reading u64 mask using (u32 *)()[0], find_*_bit() assumes it gets
lower 32bits of u64 but instead gets upper 32bits which is wrong.
Proposed fix is to swap the words of the u64 to handle this case.
This is _not_ endianness swap.

Suggested-by: Yury Norov 
Reviewed-by: Yury Norov 
Cc: Yury Norov 
Cc: Peter Zijlstra 
Cc: Ingo Molnar 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexander Shishkin 
Cc: Jiri Olsa 
Cc: Michael Ellerman 
Signed-off-by: Madhavan Srinivasan 
---
 include/linux/bitmap.h |  2 ++
 kernel/events/core.c   |  4 +++-
 lib/bitmap.c   | 19 +++
 3 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index 27bfc0b631a9..6f2cc9eb12d9 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -188,6 +188,8 @@ extern int bitmap_print_to_pagebuf(bool list, char *buf,
 #define small_const_nbits(nbits) \
(__builtin_constant_p(nbits) && (nbits) <= BITS_PER_LONG)
 
+extern void bitmap_from_u64(unsigned long *dst, u64 mask);
+
 static inline void bitmap_zero(unsigned long *dst, unsigned int nbits)
 {
if (small_const_nbits(nbits))
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 356a6c7cb52a..f5ed20a63a5e 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5269,8 +5269,10 @@ perf_output_sample_regs(struct perf_output_handle 
*handle,
struct pt_regs *regs, u64 mask)
 {
int bit;
+   DECLARE_BITMAP(_mask, 64);
 
-   for_each_set_bit(bit, (const unsigned long *) ,
+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(bit, _mask,
 sizeof(mask) * BITS_PER_BYTE) {
u64 val;
 
diff --git a/lib/bitmap.c b/lib/bitmap.c
index eca88087fa8a..2b9bda507645 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -1170,3 +1170,22 @@ void bitmap_copy_le(unsigned long *dst, const unsigned 
long *src, unsigned int n
 }
 EXPORT_SYMBOL(bitmap_copy_le);
 #endif
+
+/*
+ * bitmap_from_u64 - Check and swap words within u64.
+ *  @mask: source bitmap
+ *  @dst:  destination bitmap
+ *
+ * In 32bit Big Endian kernel, when using (u32 *)()[*]
+ * to read u64 mask, we will get wrong word.
+ * That is "(u32 *)()[0]" gets upper 32 bits,
+ * but expected could be lower 32bits of u64.
+ */
+void bitmap_from_u64(unsigned long *dst, u64 mask)
+{
+   dst[0] = mask & ULONG_MAX;
+
+   if (sizeof(mask) > sizeof(unsigned long))
+   dst[1] = mask >> 32;
+}
+EXPORT_SYMBOL(bitmap_from_u64);
-- 
2.7.4



Re: [PATCH v5] tools/perf: Fix the mask in regs_dump__printf and print_sample_iregs

2016-07-11 Thread Madhavan Srinivasan
Hi Arnaldo,

Any updates for this fix. Kindly let me know.

Maddy

On Tuesday 28 June 2016 02:24 PM, Jiri Olsa wrote:
> On Thu, Jun 23, 2016 at 11:19:27AM +0530, Madhavan Srinivasan wrote:
>
> SNIP
>
>> Changelog v1:
>> 1)updated commit message and patch subject
>> 2)Add the fix to print_sample_iregs() in builtin-script.c
>>
>>  tools/include/linux/bitmap.h |  2 ++
>>  tools/lib/bitmap.c   | 18 ++
>>  tools/perf/builtin-script.c  |  4 +++-
>>  tools/perf/util/session.c|  4 +++-
>>  4 files changed, 26 insertions(+), 2 deletions(-)
>>
>> diff --git a/tools/include/linux/bitmap.h b/tools/include/linux/bitmap.h
>> index 28f5493da491..5e98525387dc 100644
>> --- a/tools/include/linux/bitmap.h
>> +++ b/tools/include/linux/bitmap.h
>> @@ -2,6 +2,7 @@
>>  #define _PERF_BITOPS_H
>>  
>>  #include 
>> +#include 
> this could go in the bitmap.c file, but anyway:
>
> Acked-by: Jiri Olsa <jo...@kernel.org>
>
> thanks,
> jirka
>
>>  #include 
>>  
>>  #define DECLARE_BITMAP(name,bits) \
>> @@ -10,6 +11,7 @@
>>  int __bitmap_weight(const unsigned long *bitmap, int bits);
>>  void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
>>   const unsigned long *bitmap2, int bits);
>> +void bitmap_from_u64(unsigned long *dst, u64 mask);
>>  
>>  #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 
>> 1)))
>>  
> SNIP
>



Re: [PATCH v5] tools/perf: Fix the mask in regs_dump__printf and print_sample_iregs

2016-07-11 Thread Madhavan Srinivasan
Hi Arnaldo,

Any updates for this fix. Kindly let me know.

Maddy

On Tuesday 28 June 2016 02:24 PM, Jiri Olsa wrote:
> On Thu, Jun 23, 2016 at 11:19:27AM +0530, Madhavan Srinivasan wrote:
>
> SNIP
>
>> Changelog v1:
>> 1)updated commit message and patch subject
>> 2)Add the fix to print_sample_iregs() in builtin-script.c
>>
>>  tools/include/linux/bitmap.h |  2 ++
>>  tools/lib/bitmap.c   | 18 ++
>>  tools/perf/builtin-script.c  |  4 +++-
>>  tools/perf/util/session.c|  4 +++-
>>  4 files changed, 26 insertions(+), 2 deletions(-)
>>
>> diff --git a/tools/include/linux/bitmap.h b/tools/include/linux/bitmap.h
>> index 28f5493da491..5e98525387dc 100644
>> --- a/tools/include/linux/bitmap.h
>> +++ b/tools/include/linux/bitmap.h
>> @@ -2,6 +2,7 @@
>>  #define _PERF_BITOPS_H
>>  
>>  #include 
>> +#include 
> this could go in the bitmap.c file, but anyway:
>
> Acked-by: Jiri Olsa 
>
> thanks,
> jirka
>
>>  #include 
>>  
>>  #define DECLARE_BITMAP(name,bits) \
>> @@ -10,6 +11,7 @@
>>  int __bitmap_weight(const unsigned long *bitmap, int bits);
>>  void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
>>   const unsigned long *bitmap2, int bits);
>> +void bitmap_from_u64(unsigned long *dst, u64 mask);
>>  
>>  #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 
>> 1)))
>>  
> SNIP
>



[PATCH] perf/core: Fix the mask in perf_output_sample_regs

2016-07-03 Thread Madhavan Srinivasan
When decoding the perf_regs mask in perf_output_sample_regs(),
we loop through the mask using find_first_bit and find_next_bit functions.
While the exisitng code works fine in most of the case,
the logic is broken for 32bit kernel (Big Endian).
When reading u64 mask using (u32 *)()[0], find_*_bit() assumes it gets
lower 32bits of u64 but instead gets upper 32bits which is wrong.
Proposed fix is to swap the words of the u64 to handle this case.
This is _not_ endianness swap.

Suggested-by: Yury Norov <yno...@caviumnetworks.com>
Cc: Yury Norov <yno...@caviumnetworks.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Ingo Molnar <mi...@redhat.com>
Cc: Arnaldo Carvalho de Melo <a...@kernel.org>
Cc: Alexander Shishkin <alexander.shish...@linux.intel.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Michael Ellerman <m...@ellerman.id.au>
Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
 include/linux/bitmap.h |  2 ++
 kernel/events/core.c   |  4 +++-
 lib/bitmap.c   | 19 +++
 3 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index e9b0b9ab07e5..d95b422db183 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -188,6 +188,8 @@ extern int bitmap_print_to_pagebuf(bool list, char *buf,
 #define small_const_nbits(nbits) \
(__builtin_constant_p(nbits) && (nbits) <= BITS_PER_LONG)
 
+extern void bitmap_from_u64(unsigned long *dst, u64 mask);
+
 static inline void bitmap_zero(unsigned long *dst, unsigned int nbits)
 {
if (small_const_nbits(nbits))
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 9c51ec3f0f44..613fec95ea4c 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5205,8 +5205,10 @@ perf_output_sample_regs(struct perf_output_handle 
*handle,
struct pt_regs *regs, u64 mask)
 {
int bit;
+   DECLARE_BITMAP(_mask, 64);
 
-   for_each_set_bit(bit, (const unsigned long *) ,
+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(bit, _mask,
 sizeof(mask) * BITS_PER_BYTE) {
u64 val;
 
diff --git a/lib/bitmap.c b/lib/bitmap.c
index c66da508cbf7..522f1b4c6078 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -1170,3 +1170,22 @@ void bitmap_copy_le(unsigned long *dst, const unsigned 
long *src, unsigned int n
 }
 EXPORT_SYMBOL(bitmap_copy_le);
 #endif
+
+/*
+ * bitmap_from_u64 - Check and swap words within u64.
+ *  @mask: source bitmap
+ *  @dst:  destination bitmap
+ *
+ * In 32bit Big Endian kernel, when using (u32 *)()[*]
+ * to read u64 mask, we will get wrong word.
+ * That is "(u32 *)()[0]" gets upper 32 bits,
+ * but expected could be lower 32bits of u64.
+ */
+void bitmap_from_u64(unsigned long *dst, u64 mask)
+{
+   dst[0] = mask & ULONG_MAX;
+
+   if (sizeof(mask) > sizeof(unsigned long))
+   dst[1] = mask >> 32;
+}
+EXPORT_SYMBOL(bitmap_from_u64);
-- 
1.9.1



[PATCH] perf/core: Fix the mask in perf_output_sample_regs

2016-07-03 Thread Madhavan Srinivasan
When decoding the perf_regs mask in perf_output_sample_regs(),
we loop through the mask using find_first_bit and find_next_bit functions.
While the exisitng code works fine in most of the case,
the logic is broken for 32bit kernel (Big Endian).
When reading u64 mask using (u32 *)()[0], find_*_bit() assumes it gets
lower 32bits of u64 but instead gets upper 32bits which is wrong.
Proposed fix is to swap the words of the u64 to handle this case.
This is _not_ endianness swap.

Suggested-by: Yury Norov 
Cc: Yury Norov 
Cc: Peter Zijlstra 
Cc: Ingo Molnar 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexander Shishkin 
Cc: Jiri Olsa 
Cc: Michael Ellerman 
Signed-off-by: Madhavan Srinivasan 
---
 include/linux/bitmap.h |  2 ++
 kernel/events/core.c   |  4 +++-
 lib/bitmap.c   | 19 +++
 3 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index e9b0b9ab07e5..d95b422db183 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -188,6 +188,8 @@ extern int bitmap_print_to_pagebuf(bool list, char *buf,
 #define small_const_nbits(nbits) \
(__builtin_constant_p(nbits) && (nbits) <= BITS_PER_LONG)
 
+extern void bitmap_from_u64(unsigned long *dst, u64 mask);
+
 static inline void bitmap_zero(unsigned long *dst, unsigned int nbits)
 {
if (small_const_nbits(nbits))
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 9c51ec3f0f44..613fec95ea4c 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5205,8 +5205,10 @@ perf_output_sample_regs(struct perf_output_handle 
*handle,
struct pt_regs *regs, u64 mask)
 {
int bit;
+   DECLARE_BITMAP(_mask, 64);
 
-   for_each_set_bit(bit, (const unsigned long *) ,
+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(bit, _mask,
 sizeof(mask) * BITS_PER_BYTE) {
u64 val;
 
diff --git a/lib/bitmap.c b/lib/bitmap.c
index c66da508cbf7..522f1b4c6078 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -1170,3 +1170,22 @@ void bitmap_copy_le(unsigned long *dst, const unsigned 
long *src, unsigned int n
 }
 EXPORT_SYMBOL(bitmap_copy_le);
 #endif
+
+/*
+ * bitmap_from_u64 - Check and swap words within u64.
+ *  @mask: source bitmap
+ *  @dst:  destination bitmap
+ *
+ * In 32bit Big Endian kernel, when using (u32 *)()[*]
+ * to read u64 mask, we will get wrong word.
+ * That is "(u32 *)()[0]" gets upper 32 bits,
+ * but expected could be lower 32bits of u64.
+ */
+void bitmap_from_u64(unsigned long *dst, u64 mask)
+{
+   dst[0] = mask & ULONG_MAX;
+
+   if (sizeof(mask) > sizeof(unsigned long))
+   dst[1] = mask >> 32;
+}
+EXPORT_SYMBOL(bitmap_from_u64);
-- 
1.9.1



[PATCH v5] tools/perf: Fix the mask in regs_dump__printf and print_sample_iregs

2016-06-22 Thread Madhavan Srinivasan
When decoding the perf_regs mask in regs_dump__printf(),
we loop through the mask using find_first_bit and find_next_bit functions.
"mask" is of type "u64", but sent as a "unsigned long *" to
lib functions along with sizeof().

While the exisitng code works fine in most of the case,
the logic is broken when using a 32bit perf on a 64bit kernel (Big Endian).
When reading u64 using (u32 *)()[0], perf (lib/find_*_bit()) assumes it gets
lower 32bits of u64 which is wrong. Proposed fix is to swap the words
of the u64 to handle this case. This is _not_ endianess swap.

Suggested-by: Yury Norov <yno...@caviumnetworks.com>
Cc: Yury Norov <yno...@caviumnetworks.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Ingo Molnar <mi...@redhat.com>
Cc: Arnaldo Carvalho de Melo <a...@kernel.org>
Cc: Alexander Shishkin <alexander.shish...@linux.intel.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Adrian Hunter <adrian.hun...@intel.com>
Cc: Kan Liang <kan.li...@intel.com>
Cc: Wang Nan <wangn...@huawei.com>
Cc: Michael Ellerman <m...@ellerman.id.au>
Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
Changelog v4:
1) Removed the new macro and resued the DECLARE_BITMAP

Changelog v3:
1)Moved the swap function to lib/bitmap.c
2)Added a macro for declaration
3)Added the comments

Changelog v2:
1)Moved the swap code to a common function
2)Added more comments in the code

Changelog v1:
1)updated commit message and patch subject
2)Add the fix to print_sample_iregs() in builtin-script.c

 tools/include/linux/bitmap.h |  2 ++
 tools/lib/bitmap.c   | 18 ++
 tools/perf/builtin-script.c  |  4 +++-
 tools/perf/util/session.c|  4 +++-
 4 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/tools/include/linux/bitmap.h b/tools/include/linux/bitmap.h
index 28f5493da491..5e98525387dc 100644
--- a/tools/include/linux/bitmap.h
+++ b/tools/include/linux/bitmap.h
@@ -2,6 +2,7 @@
 #define _PERF_BITOPS_H
 
 #include 
+#include 
 #include 
 
 #define DECLARE_BITMAP(name,bits) \
@@ -10,6 +11,7 @@
 int __bitmap_weight(const unsigned long *bitmap, int bits);
 void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
 const unsigned long *bitmap2, int bits);
+void bitmap_from_u64(unsigned long *dst, u64 mask);
 
 #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
 
diff --git a/tools/lib/bitmap.c b/tools/lib/bitmap.c
index 0a1adcfd..464a0cc63e6a 100644
--- a/tools/lib/bitmap.c
+++ b/tools/lib/bitmap.c
@@ -29,3 +29,21 @@ void __bitmap_or(unsigned long *dst, const unsigned long 
*bitmap1,
for (k = 0; k < nr; k++)
dst[k] = bitmap1[k] | bitmap2[k];
 }
+
+/*
+ * bitmap_from_u64 - Check and swap words within u64.
+ *  @mask: source bitmap
+ *  @dst:  destination bitmap
+ *
+ * In 32 bit big endian userspace on a 64bit kernel, 'unsigned long' is 32 
bits.
+ * When reading u64 using (u32 *)()[0] and (u32 *)()[1],
+ * we will get wrong value for the mask. That is "(u32 *)()[0]"
+ * gets upper 32 bits of u64, but perf may expect lower 32bits of u64.
+ */
+void bitmap_from_u64(unsigned long *dst, u64 mask)
+{
+   dst[0] = mask & ULONG_MAX;
+
+   if (sizeof(mask) > sizeof(unsigned long))
+   dst[1] = mask >> 32;
+}
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index e3ce2f34d3ad..132a4bb70c31 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -412,11 +412,13 @@ static void print_sample_iregs(struct perf_sample *sample,
struct regs_dump *regs = >intr_regs;
uint64_t mask = attr->sample_regs_intr;
unsigned i = 0, r;
+   DECLARE_BITMAP(_mask, 64);
 
if (!regs)
return;
 
-   for_each_set_bit(r, (unsigned long *) , sizeof(mask) * 8) {
+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(r, _mask, sizeof(mask) * 8) {
u64 val = regs->regs[i++];
printf("%5s:0x%"PRIx64" ", perf_reg_name(r), val);
}
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 5214974e841a..3576bf13 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -940,8 +940,10 @@ static void branch_stack__printf(struct perf_sample 
*sample)
 static void regs_dump__printf(u64 mask, u64 *regs)
 {
unsigned rid, i = 0;
+   DECLARE_BITMAP(_mask, 64);
 
-   for_each_set_bit(rid, (unsigned long *) , sizeof(mask) * 8) {
+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(rid, _mask, sizeof(mask) * 8) {
u64 val = regs[i++];
 
printf(" %-5s 0x%" PRIx64 "\n",
-- 
1.9.1



[PATCH v5] tools/perf: Fix the mask in regs_dump__printf and print_sample_iregs

2016-06-22 Thread Madhavan Srinivasan
When decoding the perf_regs mask in regs_dump__printf(),
we loop through the mask using find_first_bit and find_next_bit functions.
"mask" is of type "u64", but sent as a "unsigned long *" to
lib functions along with sizeof().

While the exisitng code works fine in most of the case,
the logic is broken when using a 32bit perf on a 64bit kernel (Big Endian).
When reading u64 using (u32 *)()[0], perf (lib/find_*_bit()) assumes it gets
lower 32bits of u64 which is wrong. Proposed fix is to swap the words
of the u64 to handle this case. This is _not_ endianess swap.

Suggested-by: Yury Norov 
Cc: Yury Norov 
Cc: Peter Zijlstra 
Cc: Ingo Molnar 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexander Shishkin 
Cc: Jiri Olsa 
Cc: Adrian Hunter 
Cc: Kan Liang 
Cc: Wang Nan 
Cc: Michael Ellerman 
Signed-off-by: Madhavan Srinivasan 
---
Changelog v4:
1) Removed the new macro and resued the DECLARE_BITMAP

Changelog v3:
1)Moved the swap function to lib/bitmap.c
2)Added a macro for declaration
3)Added the comments

Changelog v2:
1)Moved the swap code to a common function
2)Added more comments in the code

Changelog v1:
1)updated commit message and patch subject
2)Add the fix to print_sample_iregs() in builtin-script.c

 tools/include/linux/bitmap.h |  2 ++
 tools/lib/bitmap.c   | 18 ++
 tools/perf/builtin-script.c  |  4 +++-
 tools/perf/util/session.c|  4 +++-
 4 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/tools/include/linux/bitmap.h b/tools/include/linux/bitmap.h
index 28f5493da491..5e98525387dc 100644
--- a/tools/include/linux/bitmap.h
+++ b/tools/include/linux/bitmap.h
@@ -2,6 +2,7 @@
 #define _PERF_BITOPS_H
 
 #include 
+#include 
 #include 
 
 #define DECLARE_BITMAP(name,bits) \
@@ -10,6 +11,7 @@
 int __bitmap_weight(const unsigned long *bitmap, int bits);
 void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
 const unsigned long *bitmap2, int bits);
+void bitmap_from_u64(unsigned long *dst, u64 mask);
 
 #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
 
diff --git a/tools/lib/bitmap.c b/tools/lib/bitmap.c
index 0a1adcfd..464a0cc63e6a 100644
--- a/tools/lib/bitmap.c
+++ b/tools/lib/bitmap.c
@@ -29,3 +29,21 @@ void __bitmap_or(unsigned long *dst, const unsigned long 
*bitmap1,
for (k = 0; k < nr; k++)
dst[k] = bitmap1[k] | bitmap2[k];
 }
+
+/*
+ * bitmap_from_u64 - Check and swap words within u64.
+ *  @mask: source bitmap
+ *  @dst:  destination bitmap
+ *
+ * In 32 bit big endian userspace on a 64bit kernel, 'unsigned long' is 32 
bits.
+ * When reading u64 using (u32 *)()[0] and (u32 *)()[1],
+ * we will get wrong value for the mask. That is "(u32 *)()[0]"
+ * gets upper 32 bits of u64, but perf may expect lower 32bits of u64.
+ */
+void bitmap_from_u64(unsigned long *dst, u64 mask)
+{
+   dst[0] = mask & ULONG_MAX;
+
+   if (sizeof(mask) > sizeof(unsigned long))
+   dst[1] = mask >> 32;
+}
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index e3ce2f34d3ad..132a4bb70c31 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -412,11 +412,13 @@ static void print_sample_iregs(struct perf_sample *sample,
struct regs_dump *regs = >intr_regs;
uint64_t mask = attr->sample_regs_intr;
unsigned i = 0, r;
+   DECLARE_BITMAP(_mask, 64);
 
if (!regs)
return;
 
-   for_each_set_bit(r, (unsigned long *) , sizeof(mask) * 8) {
+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(r, _mask, sizeof(mask) * 8) {
u64 val = regs->regs[i++];
printf("%5s:0x%"PRIx64" ", perf_reg_name(r), val);
}
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 5214974e841a..3576bf13 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -940,8 +940,10 @@ static void branch_stack__printf(struct perf_sample 
*sample)
 static void regs_dump__printf(u64 mask, u64 *regs)
 {
unsigned rid, i = 0;
+   DECLARE_BITMAP(_mask, 64);
 
-   for_each_set_bit(rid, (unsigned long *) , sizeof(mask) * 8) {
+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(rid, _mask, sizeof(mask) * 8) {
u64 val = regs[i++];
 
printf(" %-5s 0x%" PRIx64 "\n",
-- 
1.9.1



Re: [PATCH v4] tools/perf: Fix the mask in regs_dump__printf and print_sample_iregs

2016-06-22 Thread Madhavan Srinivasan


On Thursday 23 June 2016 10:48 AM, Yury Norov wrote:
> On Thu, Jun 23, 2016 at 10:31:16AM +0530, Madhavan Srinivasan wrote:
>> When decoding the perf_regs mask in regs_dump__printf(),
>> we loop through the mask using find_first_bit and find_next_bit functions.
>> "mask" is of type "u64", but sent as a "unsigned long *" to
>> lib functions along with sizeof().
>>
>> While the exisitng code works fine in most of the case,
>> the logic is broken when using a 32bit perf on a 64bit kernel (Big Endian).
>> When reading u64 using (u32 *)()[0], perf (lib/find_*_bit()) assumes it 
>> gets
>> lower 32bits of u64 which is wrong. Proposed fix is to swap the words
>> of the u64 to handle this case. This is _not_ endianess swap.
>>
>> Suggested-by: Yury Norov <yno...@caviumnetworks.com>
>> Cc: Yury Norov <yno...@caviumnetworks.com>
>> Cc: Peter Zijlstra <pet...@infradead.org>
>> Cc: Ingo Molnar <mi...@redhat.com>
>> Cc: Arnaldo Carvalho de Melo <a...@kernel.org>
>> Cc: Alexander Shishkin <alexander.shish...@linux.intel.com>
>> Cc: Jiri Olsa <jo...@kernel.org>
>> Cc: Adrian Hunter <adrian.hun...@intel.com>
>> Cc: Kan Liang <kan.li...@intel.com>
>> Cc: Wang Nan <wangn...@huawei.com>
>> Cc: Michael Ellerman <m...@ellerman.id.au>
>> Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
>> ---
>> Changelog v3:
>> 1)Moved the swap function to lib/bitmap.c
>> 2)Added a macro for declaration
>> 3)Added the comments
>>
>> Changelog v2:
>> 1)Moved the swap code to a common function
>> 2)Added more comments in the code
>>
>> Changelog v1:
>> 1)updated commit message and patch subject
>> 2)Add the fix to print_sample_iregs() in builtin-script.c
>>
>>  tools/include/linux/bitmap.h |  5 +
>>  tools/lib/bitmap.c   | 18 ++
>>  tools/perf/builtin-script.c  |  4 +++-
>>  tools/perf/util/session.c|  4 +++-
>>  4 files changed, 29 insertions(+), 2 deletions(-)
>>
>> diff --git a/tools/include/linux/bitmap.h b/tools/include/linux/bitmap.h
>> index 28f5493da491..6be9a7ddcb03 100644
>> --- a/tools/include/linux/bitmap.h
>> +++ b/tools/include/linux/bitmap.h
>> @@ -2,14 +2,19 @@
>>  #define _PERF_BITOPS_H
>>  
>>  #include 
>> +#include 
>>  #include 
>>  
>>  #define DECLARE_BITMAP(name,bits) \
>>  unsigned long name[BITS_TO_LONGS(bits)]
>>  
>> +#define DECLARE_U64_BITMAP(__name) \
>> +unsigned long __name[sizeof(u64)/sizeof(unsigned long)]
>> +
>>  int __bitmap_weight(const unsigned long *bitmap, int bits);
>>  void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
>>   const unsigned long *bitmap2, int bits);
>> +void bitmap_from_u64(unsigned long *dst, u64 mask);
>>  
>>  #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 
>> 1)))
>>  
>> diff --git a/tools/lib/bitmap.c b/tools/lib/bitmap.c
>> index 0a1adcfd..464a0cc63e6a 100644
>> --- a/tools/lib/bitmap.c
>> +++ b/tools/lib/bitmap.c
>> @@ -29,3 +29,21 @@ void __bitmap_or(unsigned long *dst, const unsigned long 
>> *bitmap1,
>>  for (k = 0; k < nr; k++)
>>  dst[k] = bitmap1[k] | bitmap2[k];
>>  }
>> +
>> +/*
>> + * bitmap_from_u64 - Check and swap words within u64.
>> + *  @mask: source bitmap
>> + *  @dst:  destination bitmap
>> + *
>> + * In 32 bit big endian userspace on a 64bit kernel, 'unsigned long' is 32 
>> bits.
>> + * When reading u64 using (u32 *)()[0] and (u32 *)()[1],
>> + * we will get wrong value for the mask. That is "(u32 *)()[0]"
>> + * gets upper 32 bits of u64, but perf may expect lower 32bits of u64.
>> + */
>> +void bitmap_from_u64(unsigned long *dst, u64 mask)
>> +{
>> +dst[0] = mask & ULONG_MAX;
>> +
>> +if (sizeof(mask) > sizeof(unsigned long))
>> +dst[1] = mask >> 32;
>> +}
>> diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
>> index e3ce2f34d3ad..1120ca117071 100644
>> --- a/tools/perf/builtin-script.c
>> +++ b/tools/perf/builtin-script.c
>> @@ -412,11 +412,13 @@ static void print_sample_iregs(struct perf_sample 
>> *sample,
>>  struct regs_dump *regs = >intr_regs;
>>  uint64_t mask = attr->sample_regs_intr;
>>  unsigned i = 0, r;
>> +DECLARE_U64_BITMAP(_mask);
> I thought again, and realized that it 

Re: [PATCH v4] tools/perf: Fix the mask in regs_dump__printf and print_sample_iregs

2016-06-22 Thread Madhavan Srinivasan


On Thursday 23 June 2016 10:48 AM, Yury Norov wrote:
> On Thu, Jun 23, 2016 at 10:31:16AM +0530, Madhavan Srinivasan wrote:
>> When decoding the perf_regs mask in regs_dump__printf(),
>> we loop through the mask using find_first_bit and find_next_bit functions.
>> "mask" is of type "u64", but sent as a "unsigned long *" to
>> lib functions along with sizeof().
>>
>> While the exisitng code works fine in most of the case,
>> the logic is broken when using a 32bit perf on a 64bit kernel (Big Endian).
>> When reading u64 using (u32 *)()[0], perf (lib/find_*_bit()) assumes it 
>> gets
>> lower 32bits of u64 which is wrong. Proposed fix is to swap the words
>> of the u64 to handle this case. This is _not_ endianess swap.
>>
>> Suggested-by: Yury Norov 
>> Cc: Yury Norov 
>> Cc: Peter Zijlstra 
>> Cc: Ingo Molnar 
>> Cc: Arnaldo Carvalho de Melo 
>> Cc: Alexander Shishkin 
>> Cc: Jiri Olsa 
>> Cc: Adrian Hunter 
>> Cc: Kan Liang 
>> Cc: Wang Nan 
>> Cc: Michael Ellerman 
>> Signed-off-by: Madhavan Srinivasan 
>> ---
>> Changelog v3:
>> 1)Moved the swap function to lib/bitmap.c
>> 2)Added a macro for declaration
>> 3)Added the comments
>>
>> Changelog v2:
>> 1)Moved the swap code to a common function
>> 2)Added more comments in the code
>>
>> Changelog v1:
>> 1)updated commit message and patch subject
>> 2)Add the fix to print_sample_iregs() in builtin-script.c
>>
>>  tools/include/linux/bitmap.h |  5 +
>>  tools/lib/bitmap.c   | 18 ++
>>  tools/perf/builtin-script.c  |  4 +++-
>>  tools/perf/util/session.c|  4 +++-
>>  4 files changed, 29 insertions(+), 2 deletions(-)
>>
>> diff --git a/tools/include/linux/bitmap.h b/tools/include/linux/bitmap.h
>> index 28f5493da491..6be9a7ddcb03 100644
>> --- a/tools/include/linux/bitmap.h
>> +++ b/tools/include/linux/bitmap.h
>> @@ -2,14 +2,19 @@
>>  #define _PERF_BITOPS_H
>>  
>>  #include 
>> +#include 
>>  #include 
>>  
>>  #define DECLARE_BITMAP(name,bits) \
>>  unsigned long name[BITS_TO_LONGS(bits)]
>>  
>> +#define DECLARE_U64_BITMAP(__name) \
>> +unsigned long __name[sizeof(u64)/sizeof(unsigned long)]
>> +
>>  int __bitmap_weight(const unsigned long *bitmap, int bits);
>>  void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
>>   const unsigned long *bitmap2, int bits);
>> +void bitmap_from_u64(unsigned long *dst, u64 mask);
>>  
>>  #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 
>> 1)))
>>  
>> diff --git a/tools/lib/bitmap.c b/tools/lib/bitmap.c
>> index 0a1adcfd..464a0cc63e6a 100644
>> --- a/tools/lib/bitmap.c
>> +++ b/tools/lib/bitmap.c
>> @@ -29,3 +29,21 @@ void __bitmap_or(unsigned long *dst, const unsigned long 
>> *bitmap1,
>>  for (k = 0; k < nr; k++)
>>  dst[k] = bitmap1[k] | bitmap2[k];
>>  }
>> +
>> +/*
>> + * bitmap_from_u64 - Check and swap words within u64.
>> + *  @mask: source bitmap
>> + *  @dst:  destination bitmap
>> + *
>> + * In 32 bit big endian userspace on a 64bit kernel, 'unsigned long' is 32 
>> bits.
>> + * When reading u64 using (u32 *)()[0] and (u32 *)()[1],
>> + * we will get wrong value for the mask. That is "(u32 *)()[0]"
>> + * gets upper 32 bits of u64, but perf may expect lower 32bits of u64.
>> + */
>> +void bitmap_from_u64(unsigned long *dst, u64 mask)
>> +{
>> +dst[0] = mask & ULONG_MAX;
>> +
>> +if (sizeof(mask) > sizeof(unsigned long))
>> +dst[1] = mask >> 32;
>> +}
>> diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
>> index e3ce2f34d3ad..1120ca117071 100644
>> --- a/tools/perf/builtin-script.c
>> +++ b/tools/perf/builtin-script.c
>> @@ -412,11 +412,13 @@ static void print_sample_iregs(struct perf_sample 
>> *sample,
>>  struct regs_dump *regs = >intr_regs;
>>  uint64_t mask = attr->sample_regs_intr;
>>  unsigned i = 0, r;
>> +DECLARE_U64_BITMAP(_mask);
> I thought again, and realized that it may be just
>   DECLARE_BITMAP(_mask, 64);
>
> I think it's better than introduce new macro and I'd recommend you to
> send v5 doing this. But this version is OK to me as well. So it's up
> to you.

Yeah. Make sense. My bad did not look close at DECLARE_BITMAP.
Will send out a v5 now with that change.

Maddy
>
> Reviewed-

[PATCH v4] tools/perf: Fix the mask in regs_dump__printf and print_sample_iregs

2016-06-22 Thread Madhavan Srinivasan
When decoding the perf_regs mask in regs_dump__printf(),
we loop through the mask using find_first_bit and find_next_bit functions.
"mask" is of type "u64", but sent as a "unsigned long *" to
lib functions along with sizeof().

While the exisitng code works fine in most of the case,
the logic is broken when using a 32bit perf on a 64bit kernel (Big Endian).
When reading u64 using (u32 *)()[0], perf (lib/find_*_bit()) assumes it gets
lower 32bits of u64 which is wrong. Proposed fix is to swap the words
of the u64 to handle this case. This is _not_ endianess swap.

Suggested-by: Yury Norov <yno...@caviumnetworks.com>
Cc: Yury Norov <yno...@caviumnetworks.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Ingo Molnar <mi...@redhat.com>
Cc: Arnaldo Carvalho de Melo <a...@kernel.org>
Cc: Alexander Shishkin <alexander.shish...@linux.intel.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Adrian Hunter <adrian.hun...@intel.com>
Cc: Kan Liang <kan.li...@intel.com>
Cc: Wang Nan <wangn...@huawei.com>
Cc: Michael Ellerman <m...@ellerman.id.au>
Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
---
Changelog v3:
1)Moved the swap function to lib/bitmap.c
2)Added a macro for declaration
3)Added the comments

Changelog v2:
1)Moved the swap code to a common function
2)Added more comments in the code

Changelog v1:
1)updated commit message and patch subject
2)Add the fix to print_sample_iregs() in builtin-script.c

 tools/include/linux/bitmap.h |  5 +
 tools/lib/bitmap.c   | 18 ++
 tools/perf/builtin-script.c  |  4 +++-
 tools/perf/util/session.c|  4 +++-
 4 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/tools/include/linux/bitmap.h b/tools/include/linux/bitmap.h
index 28f5493da491..6be9a7ddcb03 100644
--- a/tools/include/linux/bitmap.h
+++ b/tools/include/linux/bitmap.h
@@ -2,14 +2,19 @@
 #define _PERF_BITOPS_H
 
 #include 
+#include 
 #include 
 
 #define DECLARE_BITMAP(name,bits) \
unsigned long name[BITS_TO_LONGS(bits)]
 
+#define DECLARE_U64_BITMAP(__name) \
+   unsigned long __name[sizeof(u64)/sizeof(unsigned long)]
+
 int __bitmap_weight(const unsigned long *bitmap, int bits);
 void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
 const unsigned long *bitmap2, int bits);
+void bitmap_from_u64(unsigned long *dst, u64 mask);
 
 #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
 
diff --git a/tools/lib/bitmap.c b/tools/lib/bitmap.c
index 0a1adcfd..464a0cc63e6a 100644
--- a/tools/lib/bitmap.c
+++ b/tools/lib/bitmap.c
@@ -29,3 +29,21 @@ void __bitmap_or(unsigned long *dst, const unsigned long 
*bitmap1,
for (k = 0; k < nr; k++)
dst[k] = bitmap1[k] | bitmap2[k];
 }
+
+/*
+ * bitmap_from_u64 - Check and swap words within u64.
+ *  @mask: source bitmap
+ *  @dst:  destination bitmap
+ *
+ * In 32 bit big endian userspace on a 64bit kernel, 'unsigned long' is 32 
bits.
+ * When reading u64 using (u32 *)()[0] and (u32 *)()[1],
+ * we will get wrong value for the mask. That is "(u32 *)()[0]"
+ * gets upper 32 bits of u64, but perf may expect lower 32bits of u64.
+ */
+void bitmap_from_u64(unsigned long *dst, u64 mask)
+{
+   dst[0] = mask & ULONG_MAX;
+
+   if (sizeof(mask) > sizeof(unsigned long))
+   dst[1] = mask >> 32;
+}
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index e3ce2f34d3ad..1120ca117071 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -412,11 +412,13 @@ static void print_sample_iregs(struct perf_sample *sample,
struct regs_dump *regs = >intr_regs;
uint64_t mask = attr->sample_regs_intr;
unsigned i = 0, r;
+   DECLARE_U64_BITMAP(_mask);
 
if (!regs)
return;
 
-   for_each_set_bit(r, (unsigned long *) , sizeof(mask) * 8) {
+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(r, _mask, sizeof(mask) * 8) {
u64 val = regs->regs[i++];
printf("%5s:0x%"PRIx64" ", perf_reg_name(r), val);
}
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 5214974e841a..fab1f9c1e0f5 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -940,8 +940,10 @@ static void branch_stack__printf(struct perf_sample 
*sample)
 static void regs_dump__printf(u64 mask, u64 *regs)
 {
unsigned rid, i = 0;
+   DECLARE_U64_BITMAP(_mask);
 
-   for_each_set_bit(rid, (unsigned long *) , sizeof(mask) * 8) {
+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(rid, _mask, sizeof(mask) * 8) {
u64 val = regs[i++];
 
printf(" %-5s 0x%" PRIx64 "\n",
-- 
1.9.1



[PATCH v4] tools/perf: Fix the mask in regs_dump__printf and print_sample_iregs

2016-06-22 Thread Madhavan Srinivasan
When decoding the perf_regs mask in regs_dump__printf(),
we loop through the mask using find_first_bit and find_next_bit functions.
"mask" is of type "u64", but sent as a "unsigned long *" to
lib functions along with sizeof().

While the exisitng code works fine in most of the case,
the logic is broken when using a 32bit perf on a 64bit kernel (Big Endian).
When reading u64 using (u32 *)()[0], perf (lib/find_*_bit()) assumes it gets
lower 32bits of u64 which is wrong. Proposed fix is to swap the words
of the u64 to handle this case. This is _not_ endianess swap.

Suggested-by: Yury Norov 
Cc: Yury Norov 
Cc: Peter Zijlstra 
Cc: Ingo Molnar 
Cc: Arnaldo Carvalho de Melo 
Cc: Alexander Shishkin 
Cc: Jiri Olsa 
Cc: Adrian Hunter 
Cc: Kan Liang 
Cc: Wang Nan 
Cc: Michael Ellerman 
Signed-off-by: Madhavan Srinivasan 
---
Changelog v3:
1)Moved the swap function to lib/bitmap.c
2)Added a macro for declaration
3)Added the comments

Changelog v2:
1)Moved the swap code to a common function
2)Added more comments in the code

Changelog v1:
1)updated commit message and patch subject
2)Add the fix to print_sample_iregs() in builtin-script.c

 tools/include/linux/bitmap.h |  5 +
 tools/lib/bitmap.c   | 18 ++
 tools/perf/builtin-script.c  |  4 +++-
 tools/perf/util/session.c|  4 +++-
 4 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/tools/include/linux/bitmap.h b/tools/include/linux/bitmap.h
index 28f5493da491..6be9a7ddcb03 100644
--- a/tools/include/linux/bitmap.h
+++ b/tools/include/linux/bitmap.h
@@ -2,14 +2,19 @@
 #define _PERF_BITOPS_H
 
 #include 
+#include 
 #include 
 
 #define DECLARE_BITMAP(name,bits) \
unsigned long name[BITS_TO_LONGS(bits)]
 
+#define DECLARE_U64_BITMAP(__name) \
+   unsigned long __name[sizeof(u64)/sizeof(unsigned long)]
+
 int __bitmap_weight(const unsigned long *bitmap, int bits);
 void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
 const unsigned long *bitmap2, int bits);
+void bitmap_from_u64(unsigned long *dst, u64 mask);
 
 #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
 
diff --git a/tools/lib/bitmap.c b/tools/lib/bitmap.c
index 0a1adcfd..464a0cc63e6a 100644
--- a/tools/lib/bitmap.c
+++ b/tools/lib/bitmap.c
@@ -29,3 +29,21 @@ void __bitmap_or(unsigned long *dst, const unsigned long 
*bitmap1,
for (k = 0; k < nr; k++)
dst[k] = bitmap1[k] | bitmap2[k];
 }
+
+/*
+ * bitmap_from_u64 - Check and swap words within u64.
+ *  @mask: source bitmap
+ *  @dst:  destination bitmap
+ *
+ * In 32 bit big endian userspace on a 64bit kernel, 'unsigned long' is 32 
bits.
+ * When reading u64 using (u32 *)()[0] and (u32 *)()[1],
+ * we will get wrong value for the mask. That is "(u32 *)()[0]"
+ * gets upper 32 bits of u64, but perf may expect lower 32bits of u64.
+ */
+void bitmap_from_u64(unsigned long *dst, u64 mask)
+{
+   dst[0] = mask & ULONG_MAX;
+
+   if (sizeof(mask) > sizeof(unsigned long))
+   dst[1] = mask >> 32;
+}
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index e3ce2f34d3ad..1120ca117071 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -412,11 +412,13 @@ static void print_sample_iregs(struct perf_sample *sample,
struct regs_dump *regs = >intr_regs;
uint64_t mask = attr->sample_regs_intr;
unsigned i = 0, r;
+   DECLARE_U64_BITMAP(_mask);
 
if (!regs)
return;
 
-   for_each_set_bit(r, (unsigned long *) , sizeof(mask) * 8) {
+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(r, _mask, sizeof(mask) * 8) {
u64 val = regs->regs[i++];
printf("%5s:0x%"PRIx64" ", perf_reg_name(r), val);
}
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 5214974e841a..fab1f9c1e0f5 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -940,8 +940,10 @@ static void branch_stack__printf(struct perf_sample 
*sample)
 static void regs_dump__printf(u64 mask, u64 *regs)
 {
unsigned rid, i = 0;
+   DECLARE_U64_BITMAP(_mask);
 
-   for_each_set_bit(rid, (unsigned long *) , sizeof(mask) * 8) {
+   bitmap_from_u64(_mask, mask);
+   for_each_set_bit(rid, _mask, sizeof(mask) * 8) {
u64 val = regs[i++];
 
printf(" %-5s 0x%" PRIx64 "\n",
-- 
1.9.1



Re: [PATCH v3] tools/perf: Fix the mask in regs_dump__printf and print_sample_iregs

2016-06-21 Thread Madhavan Srinivasan


On Tuesday 21 June 2016 09:05 PM, Yury Norov wrote:
> On Tue, Jun 21, 2016 at 08:26:40PM +0530, Madhavan Srinivasan wrote:
>> When decoding the perf_regs mask in regs_dump__printf(),
>> we loop through the mask using find_first_bit and find_next_bit functions.
>> "mask" is of type "u64", but sent as a "unsigned long *" to
>> lib functions along with sizeof().
>>
>> While the exisitng code works fine in most of the case,
>> the logic is broken when using a 32bit perf on a 64bit kernel (Big Endian).
>> When reading u64 using (u32 *)()[0], perf (lib/find_*_bit()) assumes it 
>> gets
>> lower 32bits of u64 which is wrong. Proposed fix is to swap the words
>> of the u64 to handle this case. This is _not_ endianess swap.
>>
>> Suggested-by: Yury Norov <yno...@caviumnetworks.com>
>> Cc: Yury Norov <yno...@caviumnetworks.com>
>> Cc: Peter Zijlstra <pet...@infradead.org>
>> Cc: Ingo Molnar <mi...@redhat.com>
>> Cc: Arnaldo Carvalho de Melo <a...@kernel.org>
>> Cc: Alexander Shishkin <alexander.shish...@linux.intel.com>
>> Cc: Jiri Olsa <jo...@kernel.org>
>> Cc: Adrian Hunter <adrian.hun...@intel.com>
>> Cc: Kan Liang <kan.li...@intel.com>
>> Cc: Wang Nan <wangn...@huawei.com>
>> Cc: Michael Ellerman <m...@ellerman.id.au>
>> Signed-off-by: Madhavan Srinivasan <ma...@linux.vnet.ibm.com>
>> ---
>> Changelog v2:
>> 1)Moved the swap code to a common function
>> 2)Added more comments in the code
>>
>> Changelog v1:
>> 1)updated commit message and patch subject
>> 2)Add the fix to print_sample_iregs() in builtin-script.c
>>
>>  tools/include/linux/bitmap.h |  9 +
> What about include/linux/bitmap.h? I think we'd place it there first.

Wanted to handle that separately.

>
>>  tools/perf/builtin-script.c  | 16 +++-
>>  tools/perf/util/session.c| 16 +++-
>>  3 files changed, 39 insertions(+), 2 deletions(-)
>>
>> diff --git a/tools/include/linux/bitmap.h b/tools/include/linux/bitmap.h
>> index 28f5493da491..79998b26eb04 100644
>> --- a/tools/include/linux/bitmap.h
>> +++ b/tools/include/linux/bitmap.h
>> @@ -2,6 +2,7 @@
>>  #define _PERF_BITOPS_H
>>  
>>  #include 
>> +#include 
>>  #include 
>>  
>>  #define DECLARE_BITMAP(name,bits) \
>> @@ -22,6 +23,14 @@ void __bitmap_or(unsigned long *dst, const unsigned long 
>> *bitmap1,
>>  #define small_const_nbits(nbits) \
>>  (__builtin_constant_p(nbits) && (nbits) <= BITS_PER_LONG)
>>  
>> +static inline void bitmap_from_u64(unsigned long *_mask, u64 mask)
> Inline is not required. Some people don't not like it. Underscored parameter 
> in

Not sure why you say that. IIUC we can avoid a function call overhead,
also rest of the functions in the file likes it.

> function declaration is not the best idea as well. Try:
> static void bitmap_from_u64(unsigned long *bitmap, u64 mask)
>
>> +{
>> +_mask[0] = mask & ULONG_MAX;
>> +
>> +if (sizeof(mask) > sizeof(unsigned long))
>> +_mask[1] = mask >> 32;
>> +}
>> +
>>  static inline void bitmap_zero(unsigned long *dst, int nbits)
>>  {
>>  if (small_const_nbits(nbits))
>> diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
>> index e3ce2f34d3ad..73928310fd91 100644
>> --- a/tools/perf/builtin-script.c
>> +++ b/tools/perf/builtin-script.c
>> @@ -412,11 +412,25 @@ static void print_sample_iregs(struct perf_sample 
>> *sample,
>>  struct regs_dump *regs = >intr_regs;
>>  uint64_t mask = attr->sample_regs_intr;
>>  unsigned i = 0, r;
>> +unsigned long _mask[sizeof(mask)/sizeof(unsigned long)];
> If we start with it, I think we'd hide declaration machinery as well:
>
> #define DECLARE_L64_BITMAP(__name) unsigned long 
> __name[sizeof(u64)/sizeof(unsigned long)]
> or
> #define L64_BITMAP_SIZE (sizeof(u64)/sizeof(unsigned long))
>
> Or both :) Whatever you prefer.

ok

>
>>  
>>  if (!regs)
>>  return;
>>  
>> -for_each_set_bit(r, (unsigned long *) , sizeof(mask) * 8) {
>> +/*
>> + * Since u64 is passed as 'unsigned long *', check
>> + * to see whether we need to swap words within u64.
>> + * Reason being, in 32 bit big endian userspace on a
>> + * 64bit kernel, 'unsigned long' is 32 bits.
>> + * When reading u64 using (u32 *)()[0] and (u32 *)()[1],
>> + * we will get wrong value for th

<    1   2   3   4   5   6   7   >