LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v11 2/3] DMA: Freescale: Add new 8-channel DMA engine device tree nodes
From: Hongbo Zhang @ 2013-10-16  1:59 UTC (permalink / raw)
  To: Mark Rutland
  Cc: devicetree@vger.kernel.org, ian.campbell@citrix.com, Pawel Moll,
	swarren@wwwdotorg.org, vinod.koul@intel.com,
	linux-kernel@vger.kernel.org, rob.herring@calxeda.com,
	djbw@fb.com, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <20131015133849.GH19196@e106331-lin.cambridge.arm.com>

On 10/15/2013 09:38 PM, Mark Rutland wrote:
> On Tue, Oct 08, 2013 at 04:22:07AM +0100, Hongbo Zhang wrote:
>> Hi Mark, Stephen and other DT maintainers?
>>
>> The 1/3 had already been acked by Mark, and please have a further look
>> at this patch 2/3.
>> The DMA maintainer Vinod  needs ack for the DT related patches so that
>> he can take all this patch set.
> Sorry for the delay.
>
> This looks ok to me.
>
> Acked-by: Mark Rutland <mark.rutland@arm.com>

Thanks, Mark.

>> On 09/26/2013 05:33 PM, hongbo.zhang@freescale.com wrote:
>>> From: Hongbo Zhang <hongbo.zhang@freescale.com>
>>>
>>> Freescale QorIQ T4 and B4 introduce new 8-channel DMA engines, this patch adds
>>> the device tree nodes for them.
>>>
>>> Signed-off-by: Hongbo Zhang <hongbo.zhang@freescale.com>
>>> ---
>>>    .../devicetree/bindings/powerpc/fsl/dma.txt        |   70 +++++++++++++++++
>>>    arch/powerpc/boot/dts/fsl/b4si-post.dtsi           |    4 +-
>>>    arch/powerpc/boot/dts/fsl/elo3-dma-0.dtsi          |   82 ++++++++++++++++++++
>>>    arch/powerpc/boot/dts/fsl/elo3-dma-1.dtsi          |   82 ++++++++++++++++++++
>>>    arch/powerpc/boot/dts/fsl/t4240si-post.dtsi        |    4 +-
>>>    5 files changed, 238 insertions(+), 4 deletions(-)
>>>    create mode 100644 arch/powerpc/boot/dts/fsl/elo3-dma-0.dtsi
>>>    create mode 100644 arch/powerpc/boot/dts/fsl/elo3-dma-1.dtsi
>>>
>>> diff --git a/Documentation/devicetree/bindings/powerpc/fsl/dma.txt b/Documentation/devicetree/bindings/powerpc/fsl/dma.txt
>>> index 0584168..7fc1b01 100644
>>> --- a/Documentation/devicetree/bindings/powerpc/fsl/dma.txt
>>> +++ b/Documentation/devicetree/bindings/powerpc/fsl/dma.txt
>>> @@ -128,6 +128,76 @@ Example:
>>>                };
>>>        };
>>>
>>> +** Freescale Elo3 DMA Controller
>>> +   DMA controller which has same function as EloPlus except that Elo3 has 8
>>> +   channels while EloPlus has only 4, it is used in Freescale Txxx and Bxxx
>>> +   series chips, such as t1040, t4240, b4860.
>>> +
>>> +Required properties:
>>> +
>>> +- compatible        : must include "fsl,elo3-dma"
>>> +- reg               : contains two entries for DMA General Status Registers,
>>> +                      i.e. DGSR0 which includes status for channel 1~4, and
>>> +                      DGSR1 for channel 5~8
>>> +- ranges            : describes the mapping between the address space of the
>>> +                      DMA channels and the address space of the DMA controller
>>> +
>>> +- DMA channel nodes:
>>> +        - compatible        : must include "fsl,eloplus-dma-channel"
>>> +        - reg               : DMA channel specific registers
>>> +        - interrupts        : interrupt specifier for DMA channel IRQ
>>> +        - interrupt-parent  : optional, if needed for interrupt mapping
>>> +
>>> +Example:
>>> +dma@100300 {
>>> +     #address-cells = <1>;
>>> +     #size-cells = <1>;
>>> +     compatible = "fsl,elo3-dma";
>>> +     reg = <0x100300 0x4>,
>>> +           <0x100600 0x4>;
>>> +     ranges = <0x0 0x100100 0x500>;
>>> +     dma-channel@0 {
>>> +             compatible = "fsl,eloplus-dma-channel";
>>> +             reg = <0x0 0x80>;
>>> +             interrupts = <28 2 0 0>;
>>> +     };
>>> +     dma-channel@80 {
>>> +             compatible = "fsl,eloplus-dma-channel";
>>> +             reg = <0x80 0x80>;
>>> +             interrupts = <29 2 0 0>;
>>> +     };
>>> +     dma-channel@100 {
>>> +             compatible = "fsl,eloplus-dma-channel";
>>> +             reg = <0x100 0x80>;
>>> +             interrupts = <30 2 0 0>;
>>> +     };
>>> +     dma-channel@180 {
>>> +             compatible = "fsl,eloplus-dma-channel";
>>> +             reg = <0x180 0x80>;
>>> +             interrupts = <31 2 0 0>;
>>> +     };
>>> +     dma-channel@300 {
>>> +             compatible = "fsl,eloplus-dma-channel";
>>> +             reg = <0x300 0x80>;
>>> +             interrupts = <76 2 0 0>;
>>> +     };
>>> +     dma-channel@380 {
>>> +             compatible = "fsl,eloplus-dma-channel";
>>> +             reg = <0x380 0x80>;
>>> +             interrupts = <77 2 0 0>;
>>> +     };
>>> +     dma-channel@400 {
>>> +             compatible = "fsl,eloplus-dma-channel";
>>> +             reg = <0x400 0x80>;
>>> +             interrupts = <78 2 0 0>;
>>> +     };
>>> +     dma-channel@480 {
>>> +             compatible = "fsl,eloplus-dma-channel";
>>> +             reg = <0x480 0x80>;
>>> +             interrupts = <79 2 0 0>;
>>> +     };
>>> +};
>>> +
>>>    Note on DMA channel compatible properties: The compatible property must say
>>>    "fsl,elo-dma-channel" or "fsl,eloplus-dma-channel" to be used by the Elo DMA
>>>    driver (fsldma).  Any DMA channel used by fsldma cannot be used by another
>>> diff --git a/arch/powerpc/boot/dts/fsl/b4si-post.dtsi b/arch/powerpc/boot/dts/fsl/b4si-post.dtsi
>>> index 7399154..ea53ea1 100644
>>> --- a/arch/powerpc/boot/dts/fsl/b4si-post.dtsi
>>> +++ b/arch/powerpc/boot/dts/fsl/b4si-post.dtsi
>>> @@ -223,13 +223,13 @@
>>>                reg = <0xe2000 0x1000>;
>>>        };
>>>
>>> -/include/ "qoriq-dma-0.dtsi"
>>> +/include/ "elo3-dma-0.dtsi"
>>>        dma@100300 {
>>>                fsl,iommu-parent = <&pamu0>;
>>>                fsl,liodn-reg = <&guts 0x580>; /* DMA1LIODNR */
>>>        };
>>>
>>> -/include/ "qoriq-dma-1.dtsi"
>>> +/include/ "elo3-dma-1.dtsi"
>>>        dma@101300 {
>>>                fsl,iommu-parent = <&pamu0>;
>>>                fsl,liodn-reg = <&guts 0x584>; /* DMA2LIODNR */
>>> diff --git a/arch/powerpc/boot/dts/fsl/elo3-dma-0.dtsi b/arch/powerpc/boot/dts/fsl/elo3-dma-0.dtsi
>>> new file mode 100644
>>> index 0000000..3c210e0
>>> --- /dev/null
>>> +++ b/arch/powerpc/boot/dts/fsl/elo3-dma-0.dtsi
>>> @@ -0,0 +1,82 @@
>>> +/*
>>> + * QorIQ Elo3 DMA device tree stub [ controller @ offset 0x100000 ]
>>> + *
>>> + * Copyright 2013 Freescale Semiconductor Inc.
>>> + *
>>> + * Redistribution and use in source and binary forms, with or without
>>> + * modification, are permitted provided that the following conditions are met:
>>> + *     * Redistributions of source code must retain the above copyright
>>> + *       notice, this list of conditions and the following disclaimer.
>>> + *     * Redistributions in binary form must reproduce the above copyright
>>> + *       notice, this list of conditions and the following disclaimer in the
>>> + *       documentation and/or other materials provided with the distribution.
>>> + *     * Neither the name of Freescale Semiconductor nor the
>>> + *       names of its contributors may be used to endorse or promote products
>>> + *       derived from this software without specific prior written permission.
>>> + *
>>> + *
>>> + * ALTERNATIVELY, this software may be distributed under the terms of the
>>> + * GNU General Public License ("GPL") as published by the Free Software
>>> + * Foundation, either version 2 of that License or (at your option) any
>>> + * later version.
>>> + *
>>> + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
>>> + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
>>> + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
>>> + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
>>> + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
>>> + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
>>> + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
>>> + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
>>> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
>>> + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
>>> + */
>>> +
>>> +dma0: dma@100300 {
>>> +     #address-cells = <1>;
>>> +     #size-cells = <1>;
>>> +     compatible = "fsl,elo3-dma";
>>> +     reg = <0x100300 0x4>,
>>> +           <0x100600 0x4>;
>>> +     ranges = <0x0 0x100100 0x500>;
>>> +     dma-channel@0 {
>>> +             compatible = "fsl,eloplus-dma-channel";
>>> +             reg = <0x0 0x80>;
>>> +             interrupts = <28 2 0 0>;
>>> +     };
>>> +     dma-channel@80 {
>>> +             compatible = "fsl,eloplus-dma-channel";
>>> +             reg = <0x80 0x80>;
>>> +             interrupts = <29 2 0 0>;
>>> +     };
>>> +     dma-channel@100 {
>>> +             compatible = "fsl,eloplus-dma-channel";
>>> +             reg = <0x100 0x80>;
>>> +             interrupts = <30 2 0 0>;
>>> +     };
>>> +     dma-channel@180 {
>>> +             compatible = "fsl,eloplus-dma-channel";
>>> +             reg = <0x180 0x80>;
>>> +             interrupts = <31 2 0 0>;
>>> +     };
>>> +     dma-channel@300 {
>>> +             compatible = "fsl,eloplus-dma-channel";
>>> +             reg = <0x300 0x80>;
>>> +             interrupts = <76 2 0 0>;
>>> +     };
>>> +     dma-channel@380 {
>>> +             compatible = "fsl,eloplus-dma-channel";
>>> +             reg = <0x380 0x80>;
>>> +             interrupts = <77 2 0 0>;
>>> +     };
>>> +     dma-channel@400 {
>>> +             compatible = "fsl,eloplus-dma-channel";
>>> +             reg = <0x400 0x80>;
>>> +             interrupts = <78 2 0 0>;
>>> +     };
>>> +     dma-channel@480 {
>>> +             compatible = "fsl,eloplus-dma-channel";
>>> +             reg = <0x480 0x80>;
>>> +             interrupts = <79 2 0 0>;
>>> +     };
>>> +};
>>> diff --git a/arch/powerpc/boot/dts/fsl/elo3-dma-1.dtsi b/arch/powerpc/boot/dts/fsl/elo3-dma-1.dtsi
>>> new file mode 100644
>>> index 0000000..cccf3bb
>>> --- /dev/null
>>> +++ b/arch/powerpc/boot/dts/fsl/elo3-dma-1.dtsi
>>> @@ -0,0 +1,82 @@
>>> +/*
>>> + * QorIQ Elo3 DMA device tree stub [ controller @ offset 0x101000 ]
>>> + *
>>> + * Copyright 2013 Freescale Semiconductor Inc.
>>> + *
>>> + * Redistribution and use in source and binary forms, with or without
>>> + * modification, are permitted provided that the following conditions are met:
>>> + *     * Redistributions of source code must retain the above copyright
>>> + *       notice, this list of conditions and the following disclaimer.
>>> + *     * Redistributions in binary form must reproduce the above copyright
>>> + *       notice, this list of conditions and the following disclaimer in the
>>> + *       documentation and/or other materials provided with the distribution.
>>> + *     * Neither the name of Freescale Semiconductor nor the
>>> + *       names of its contributors may be used to endorse or promote products
>>> + *       derived from this software without specific prior written permission.
>>> + *
>>> + *
>>> + * ALTERNATIVELY, this software may be distributed under the terms of the
>>> + * GNU General Public License ("GPL") as published by the Free Software
>>> + * Foundation, either version 2 of that License or (at your option) any
>>> + * later version.
>>> + *
>>> + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
>>> + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
>>> + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
>>> + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
>>> + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
>>> + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
>>> + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
>>> + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
>>> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
>>> + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
>>> + */
>>> +
>>> +dma1: dma@101300 {
>>> +     #address-cells = <1>;
>>> +     #size-cells = <1>;
>>> +     compatible = "fsl,elo3-dma";
>>> +     reg = <0x101300 0x4>,
>>> +           <0x101600 0x4>;
>>> +     ranges = <0x0 0x101100 0x500>;
>>> +     dma-channel@0 {
>>> +             compatible = "fsl,eloplus-dma-channel";
>>> +             reg = <0x0 0x80>;
>>> +             interrupts = <32 2 0 0>;
>>> +     };
>>> +     dma-channel@80 {
>>> +             compatible = "fsl,eloplus-dma-channel";
>>> +             reg = <0x80 0x80>;
>>> +             interrupts = <33 2 0 0>;
>>> +     };
>>> +     dma-channel@100 {
>>> +             compatible = "fsl,eloplus-dma-channel";
>>> +             reg = <0x100 0x80>;
>>> +             interrupts = <34 2 0 0>;
>>> +     };
>>> +     dma-channel@180 {
>>> +             compatible = "fsl,eloplus-dma-channel";
>>> +             reg = <0x180 0x80>;
>>> +             interrupts = <35 2 0 0>;
>>> +     };
>>> +     dma-channel@300 {
>>> +             compatible = "fsl,eloplus-dma-channel";
>>> +             reg = <0x300 0x80>;
>>> +             interrupts = <80 2 0 0>;
>>> +     };
>>> +     dma-channel@380 {
>>> +             compatible = "fsl,eloplus-dma-channel";
>>> +             reg = <0x380 0x80>;
>>> +             interrupts = <81 2 0 0>;
>>> +     };
>>> +     dma-channel@400 {
>>> +             compatible = "fsl,eloplus-dma-channel";
>>> +             reg = <0x400 0x80>;
>>> +             interrupts = <82 2 0 0>;
>>> +     };
>>> +     dma-channel@480 {
>>> +             compatible = "fsl,eloplus-dma-channel";
>>> +             reg = <0x480 0x80>;
>>> +             interrupts = <83 2 0 0>;
>>> +     };
>>> +};
>>> diff --git a/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi b/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi
>>> index bd611a9..ec95c60 100644
>>> --- a/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi
>>> +++ b/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi
>>> @@ -387,8 +387,8 @@
>>>                reg        = <0xea000 0x4000>;
>>>        };
>>>
>>> -/include/ "qoriq-dma-0.dtsi"
>>> -/include/ "qoriq-dma-1.dtsi"
>>> +/include/ "elo3-dma-0.dtsi"
>>> +/include/ "elo3-dma-1.dtsi"
>>>
>>>    /include/ "qoriq-espi-0.dtsi"
>>>        spi@110000 {
>>
>>
>>

^ permalink raw reply

* [PATCH 01/10][v6] powerpc: Rename branch_opcode() to instr_opcode()
From: Sukadev Bhattiprolu @ 2013-10-16  2:06 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Michael Ellerman, linux-kernel, Stephane Eranian, linuxppc-dev,
	Paul Mackerras, Anshuman Khandual
In-Reply-To: <1381889202-16826-1-git-send-email-sukadev@linux.vnet.ibm.com>

The logic used in branch_opcode() to extract the opcode for an instruction
applies to non branch instructions also. So rename to instr_opcode().

Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
 arch/powerpc/lib/code-patching.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index 17e5b23..2bc9db3 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -72,19 +72,19 @@ unsigned int create_cond_branch(const unsigned int *addr,
 	return instruction;
 }
 
-static unsigned int branch_opcode(unsigned int instr)
+static unsigned int instr_opcode(unsigned int instr)
 {
 	return (instr >> 26) & 0x3F;
 }
 
 static int instr_is_branch_iform(unsigned int instr)
 {
-	return branch_opcode(instr) == 18;
+	return instr_opcode(instr) == 18;
 }
 
 static int instr_is_branch_bform(unsigned int instr)
 {
-	return branch_opcode(instr) == 16;
+	return instr_opcode(instr) == 16;
 }
 
 int instr_is_relative_branch(unsigned int instr)
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 00/10][v6] powerpc/perf: Export memory hierarchy level in Power7/8.
From: Sukadev Bhattiprolu @ 2013-10-16  2:06 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Michael Ellerman, linux-kernel, Stephane Eranian, linuxppc-dev,
	Paul Mackerras, Anshuman Khandual

Power7 and Power8 processors save the memory hierarchy level (eg: L2, L3)
from which a load or store instruction was satisfied. Export this hierarchy
information to the user via the perf_mem_data_src object.

Thanks to input from Stephane Eranian, Michael Ellerman, Michael Neuling
and Anshuman Khandual.

Sukadev Bhattiprolu (10):
  powerpc: Rename branch_opcode() to instr_opcode()
  powerpc/Power7: detect load/store instructions
  tools/perf: silence compiler warnings
  tools/perf: Remove local byteorder.h.
  powerpc/perf: Remove PME_ prefix for power7 events
  powerpc/perf: Export Power8 generic events in sysfs
  powerpc/perf: Add Power8 event PM_MRK_GRP_CMPL to sysfs.
  powerpc/perf: Define big-endian version of perf_mem_data_src
  powerpc/perf: Export Power8 memory hierarchy info to user space.
  powerpc/perf: Export Power7 memory hierarchy info to user space.

 arch/powerpc/include/asm/code-patching.h     |    1 +
 arch/powerpc/include/asm/perf_event_server.h |    4 +-
 arch/powerpc/lib/code-patching.c             |   51 +++++++++++-
 arch/powerpc/perf/core-book3s.c              |   11 +++
 arch/powerpc/perf/power7-pmu.c               |  112 +++++++++++++++++++++++---
 arch/powerpc/perf/power8-events-list.h       |   21 +++++
 arch/powerpc/perf/power8-pmu.c               |   97 ++++++++++++++++++++--
 include/uapi/linux/perf_event.h              |   16 ++++
 tools/perf/Makefile                          |    1 -
 tools/perf/util/include/asm/byteorder.h      |    2 -
 tools/perf/util/include/linux/types.h        |   20 +++++
 tools/perf/util/srcline.c                    |    4 +-
 12 files changed, 316 insertions(+), 24 deletions(-)
 create mode 100644 arch/powerpc/perf/power8-events-list.h
 delete mode 100644 tools/perf/util/include/asm/byteorder.h

-- 
1.7.9.5

^ permalink raw reply

* [PATCH 02/10][v6] powerpc/Power7: detect load/store instructions
From: Sukadev Bhattiprolu @ 2013-10-16  2:06 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Michael Ellerman, linux-kernel, Stephane Eranian, linuxppc-dev,
	Paul Mackerras, Anshuman Khandual
In-Reply-To: <1381889202-16826-1-git-send-email-sukadev@linux.vnet.ibm.com>

Implement instr_is_load_store_2_06() to detect whether a given instruction
is one of the fixed-point or floating-point load/store instructions in the
POWER Instruction Set Architecture v2.06.

This function will be used in a follow-on patch to save memory hierarchy
information of the load/store on a Power7 system. (Power8 systems set some
bits in the SIER to identify load/store operations and hence don't need a
similar functionality).

Based on optimized code from Michael Ellerman and comments from Tom Musta.

Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
Changelog[v6]
	- [Michael Ellerman, Tom Musta]: Optmize the implementation to
	  avoid for loop.

 arch/powerpc/include/asm/code-patching.h |    1 +
 arch/powerpc/lib/code-patching.c         |   45 ++++++++++++++++++++++++++++++
 2 files changed, 46 insertions(+)

diff --git a/arch/powerpc/include/asm/code-patching.h b/arch/powerpc/include/asm/code-patching.h
index a6f8c7a..9cc3ef1 100644
--- a/arch/powerpc/include/asm/code-patching.h
+++ b/arch/powerpc/include/asm/code-patching.h
@@ -34,6 +34,7 @@ int instr_is_branch_to_addr(const unsigned int *instr, unsigned long addr);
 unsigned long branch_target(const unsigned int *instr);
 unsigned int translate_branch(const unsigned int *dest,
 			      const unsigned int *src);
+int instr_is_load_store_2_06(const unsigned int *instr);
 
 static inline unsigned long ppc_function_entry(void *func)
 {
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index 2bc9db3..49fb9d7 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -159,6 +159,51 @@ unsigned int translate_branch(const unsigned int *dest, const unsigned int *src)
 	return 0;
 }
 
+/*
+ * Determine if the op code in the instruction corresponds to a load or
+ * store instruction. Ignore the vector load instructions like evlddepx,
+ * evstddepx for now.
+ *
+ * This function is valid for POWER ISA 2.06.
+ *
+ * Reference:	PowerISA_V2.06B_Public.pdf, Sections 3.3.2 through 3.3.6
+ *		and 4.6.2 through 4.6.4, Appendix F (Opcode Maps).
+ */
+int instr_is_load_store_2_06(const unsigned int *instr)
+{
+	unsigned int op, upper, lower;
+
+	op = instr_opcode(*instr);
+
+	if ((op >= 32 && op <= 58) || (op == 61 || op == 62))
+		return true;
+
+	if (op != 31)
+		return false;
+
+	upper = op >> 5;
+	lower = op & 0x1f;
+
+	/* Short circuit as many misses as we can */
+	if (lower < 3 || lower > 23)
+		return false;
+
+	if (lower == 3) {
+		if (upper >= 16)
+			return true;
+
+		return false;
+	}
+
+	if (lower == 7 || lower == 12)
+		return true;
+
+	if (lower >= 20) /* && lower <= 23 (implicit) */
+		return true;
+
+	return false;
+}
+
 
 #ifdef CONFIG_CODE_PATCHING_SELFTEST
 
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 04/10][v6] tools/perf: Remove local byteorder.h.
From: Sukadev Bhattiprolu @ 2013-10-16  2:06 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Michael Ellerman, linux-kernel, Stephane Eranian, linuxppc-dev,
	Paul Mackerras, Anshuman Khandual
In-Reply-To: <1381889202-16826-1-git-send-email-sukadev@linux.vnet.ibm.com>

Remove the local tools/perf/util/include/asm/byteorder.h and add
a few missing typedefs to tools/perf/util/include/linux/types.h.

The local byteorder.h complicates defining big/little endian versions
of data structures in include/uapi/linux/perf_event.h.

Fix proposed by Michael Ellerman.

Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
 tools/perf/Makefile                     |    1 -
 tools/perf/util/include/asm/byteorder.h |    2 --
 tools/perf/util/include/linux/types.h   |   20 ++++++++++++++++++++
 3 files changed, 20 insertions(+), 3 deletions(-)
 delete mode 100644 tools/perf/util/include/asm/byteorder.h

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index b62e12d..3c4a7d9 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -225,7 +225,6 @@ LIB_H += util/include/linux/types.h
 LIB_H += util/include/linux/linkage.h
 LIB_H += util/include/asm/asm-offsets.h
 LIB_H += util/include/asm/bug.h
-LIB_H += util/include/asm/byteorder.h
 LIB_H += util/include/asm/hweight.h
 LIB_H += util/include/asm/swab.h
 LIB_H += util/include/asm/system.h
diff --git a/tools/perf/util/include/asm/byteorder.h b/tools/perf/util/include/asm/byteorder.h
deleted file mode 100644
index 2a9bdc0..0000000
--- a/tools/perf/util/include/asm/byteorder.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#include <asm/types.h>
-#include "../../../../include/uapi/linux/swab.h"
diff --git a/tools/perf/util/include/linux/types.h b/tools/perf/util/include/linux/types.h
index eb46478..775f68e 100644
--- a/tools/perf/util/include/linux/types.h
+++ b/tools/perf/util/include/linux/types.h
@@ -7,10 +7,30 @@
 #define __bitwise
 #endif
 
+#ifndef __le16
+typedef __u16 __bitwise __le16;
+#endif
+
 #ifndef __le32
 typedef __u32 __bitwise __le32;
 #endif
 
+#ifndef __be16
+typedef __u16 __bitwise __be16;
+#endif
+
+#ifndef __le64
+typedef __u64 __bitwise __le64;
+#endif
+
+#ifndef __be32
+typedef __u32 __bitwise __be32;
+#endif
+
+#ifndef __be64
+typedef __u64 __bitwise __be64;
+#endif
+
 #define DECLARE_BITMAP(name,bits) \
 	unsigned long name[BITS_TO_LONGS(bits)]
 
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 03/10][v6] tools/perf: silence compiler warnings
From: Sukadev Bhattiprolu @ 2013-10-16  2:06 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Michael Ellerman, linux-kernel, Stephane Eranian, linuxppc-dev,
	Paul Mackerras, Anshuman Khandual
In-Reply-To: <1381889202-16826-1-git-send-email-sukadev@linux.vnet.ibm.com>

The uninitialized variables cause warnings which are treated as errors
during build (without WERROR=0).

Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
 tools/perf/util/srcline.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c
index 10983a9..0477055 100644
--- a/tools/perf/util/srcline.c
+++ b/tools/perf/util/srcline.c
@@ -223,8 +223,8 @@ out:
 
 char *get_srcline(struct dso *dso, unsigned long addr)
 {
-	char *file;
-	unsigned line;
+	char *file = NULL;
+	unsigned line = 0;
 	char *srcline;
 	char *dso_name = dso->long_name;
 	size_t size;
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 05/10][v6] powerpc/perf: Remove PME_ prefix for power7 events
From: Sukadev Bhattiprolu @ 2013-10-16  2:06 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Michael Ellerman, linux-kernel, Stephane Eranian, linuxppc-dev,
	Paul Mackerras, Anshuman Khandual
In-Reply-To: <1381889202-16826-1-git-send-email-sukadev@linux.vnet.ibm.com>

We used the PME_ prefix earlier to avoid some macro/variable name
collisions.  We have since changed the way we define/use the event
macros so we no longer need the prefix.

By dropping the prefix, we keep the the event macros consistent with
their official names.

Reported-by: Michael Ellerman <ellerman@au1.ibm.com>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/perf_event_server.h |    2 +-
 arch/powerpc/perf/power7-pmu.c               |   18 +++++++++---------
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/arch/powerpc/include/asm/perf_event_server.h b/arch/powerpc/include/asm/perf_event_server.h
index 3fd2f1b..d7b3419 100644
--- a/arch/powerpc/include/asm/perf_event_server.h
+++ b/arch/powerpc/include/asm/perf_event_server.h
@@ -138,7 +138,7 @@ extern ssize_t power_events_sysfs_show(struct device *dev,
 #define	EVENT_PTR(_id, _suffix)		&EVENT_VAR(_id, _suffix).attr.attr
 
 #define	EVENT_ATTR(_name, _id, _suffix)					\
-	PMU_EVENT_ATTR(_name, EVENT_VAR(_id, _suffix), PME_##_id,	\
+	PMU_EVENT_ATTR(_name, EVENT_VAR(_id, _suffix), _id,		\
 			power_events_sysfs_show)
 
 #define	GENERIC_EVENT_ATTR(_name, _id)	EVENT_ATTR(_name, _id, _g)
diff --git a/arch/powerpc/perf/power7-pmu.c b/arch/powerpc/perf/power7-pmu.c
index 56c67bc..ae24dfc 100644
--- a/arch/powerpc/perf/power7-pmu.c
+++ b/arch/powerpc/perf/power7-pmu.c
@@ -54,7 +54,7 @@
  * Power7 event codes.
  */
 #define EVENT(_name, _code) \
-	PME_##_name = _code,
+	_name = _code,
 
 enum {
 #include "power7-events-list.h"
@@ -318,14 +318,14 @@ static void power7_disable_pmc(unsigned int pmc, unsigned long mmcr[])
 }
 
 static int power7_generic_events[] = {
-	[PERF_COUNT_HW_CPU_CYCLES] =			PME_PM_CYC,
-	[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] =	PME_PM_GCT_NOSLOT_CYC,
-	[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] =	PME_PM_CMPLU_STALL,
-	[PERF_COUNT_HW_INSTRUCTIONS] =			PME_PM_INST_CMPL,
-	[PERF_COUNT_HW_CACHE_REFERENCES] =		PME_PM_LD_REF_L1,
-	[PERF_COUNT_HW_CACHE_MISSES] =			PME_PM_LD_MISS_L1,
-	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] =		PME_PM_BRU_FIN,
-	[PERF_COUNT_HW_BRANCH_MISSES] =			PME_PM_BR_MPRED,
+	[PERF_COUNT_HW_CPU_CYCLES] =			PM_CYC,
+	[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] =	PM_GCT_NOSLOT_CYC,
+	[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] =	PM_CMPLU_STALL,
+	[PERF_COUNT_HW_INSTRUCTIONS] =			PM_INST_CMPL,
+	[PERF_COUNT_HW_CACHE_REFERENCES] =		PM_LD_REF_L1,
+	[PERF_COUNT_HW_CACHE_MISSES] =			PM_LD_MISS_L1,
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] =		PM_BRU_FIN,
+	[PERF_COUNT_HW_BRANCH_MISSES] =			PM_BR_MPRED,
 };
 
 #define C(x)	PERF_COUNT_HW_CACHE_##x
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 06/10][v6] powerpc/perf: Export Power8 generic events in sysfs
From: Sukadev Bhattiprolu @ 2013-10-16  2:06 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Michael Ellerman, linux-kernel, Stephane Eranian, linuxppc-dev,
	Paul Mackerras, Anshuman Khandual
In-Reply-To: <1381889202-16826-1-git-send-email-sukadev@linux.vnet.ibm.com>

Export generic perf events for Power8 in sysfs.

Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
Changelog[v6]:
	[Michael Ellerman] Drop PME_ prefix in macros

 arch/powerpc/perf/power8-events-list.h |   20 +++++++++++++++
 arch/powerpc/perf/power8-pmu.c         |   44 +++++++++++++++++++++++++++-----
 2 files changed, 58 insertions(+), 6 deletions(-)
 create mode 100644 arch/powerpc/perf/power8-events-list.h

diff --git a/arch/powerpc/perf/power8-events-list.h b/arch/powerpc/perf/power8-events-list.h
new file mode 100644
index 0000000..1368547
--- /dev/null
+++ b/arch/powerpc/perf/power8-events-list.h
@@ -0,0 +1,20 @@
+/*
+ * Performance counter support for POWER8 processors.
+ *
+ * Copyright 2013 Sukadev Bhattiprolu, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+/*
+ * Some power8 event codes.
+ */
+EVENT(PM_CYC,				0x0001e)
+EVENT(PM_GCT_NOSLOT_CYC,		0x100f8)
+EVENT(PM_CMPLU_STALL,			0x4000a)
+EVENT(PM_INST_CMPL,			0x00002)
+EVENT(PM_BRU_FIN,			0x10068)
+EVENT(PM_BR_MPRED_CMPL,			0x400f6)
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index 2ee4a70..5141d97 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -18,13 +18,13 @@
 /*
  * Some power8 event codes.
  */
-#define PM_CYC				0x0001e
-#define PM_GCT_NOSLOT_CYC		0x100f8
-#define PM_CMPLU_STALL			0x4000a
-#define PM_INST_CMPL			0x00002
-#define PM_BRU_FIN			0x10068
-#define PM_BR_MPRED_CMPL		0x400f6
+#define EVENT(_name, _code)	_name = _code,
 
+enum {
+#include "power8-events-list.h"
+};
+
+#undef EVENT
 
 /*
  * Raw event encoding for POWER8:
@@ -510,6 +510,37 @@ static void power8_disable_pmc(unsigned int pmc, unsigned long mmcr[])
 		mmcr[1] &= ~(0xffUL << MMCR1_PMCSEL_SHIFT(pmc + 1));
 }
 
+GENERIC_EVENT_ATTR(cpu-cyles,			PM_CYC);
+GENERIC_EVENT_ATTR(stalled-cycles-frontend,	PM_GCT_NOSLOT_CYC);
+GENERIC_EVENT_ATTR(stalled-cycles-backend,	PM_CMPLU_STALL);
+GENERIC_EVENT_ATTR(instructions,		PM_INST_CMPL);
+GENERIC_EVENT_ATTR(branch-instructions,		PM_BRU_FIN);
+GENERIC_EVENT_ATTR(branch-misses,		PM_BR_MPRED_CMPL);
+
+#define EVENT(_name, _code)	POWER_EVENT_ATTR(_name, _name);
+#include "power8-events-list.h"
+#undef EVENT
+
+#define EVENT(_name, _code)	POWER_EVENT_PTR(_name),
+
+static struct attribute *power8_events_attr[] = {
+	GENERIC_EVENT_PTR(PM_CYC),
+	GENERIC_EVENT_PTR(PM_GCT_NOSLOT_CYC),
+	GENERIC_EVENT_PTR(PM_CMPLU_STALL),
+	GENERIC_EVENT_PTR(PM_INST_CMPL),
+	GENERIC_EVENT_PTR(PM_BRU_FIN),
+	GENERIC_EVENT_PTR(PM_BR_MPRED_CMPL),
+
+	#include "power8-events-list.h"
+	#undef EVENT
+	NULL
+};
+
+static struct attribute_group power8_pmu_events_group = {
+	.name = "events",
+	.attrs = power8_events_attr,
+};
+
 PMU_FORMAT_ATTR(event,		"config:0-49");
 PMU_FORMAT_ATTR(pmcxsel,	"config:0-7");
 PMU_FORMAT_ATTR(mark,		"config:8");
@@ -546,6 +577,7 @@ struct attribute_group power8_pmu_format_group = {
 
 static const struct attribute_group *power8_pmu_attr_groups[] = {
 	&power8_pmu_format_group,
+	&power8_pmu_events_group,
 	NULL,
 };
 
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 08/10][v6] powerpc/perf: Define big-endian version of perf_mem_data_src
From: Sukadev Bhattiprolu @ 2013-10-16  2:06 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Michael Ellerman, linux-kernel, Stephane Eranian, linuxppc-dev,
	Paul Mackerras, Anshuman Khandual
In-Reply-To: <1381889202-16826-1-git-send-email-sukadev@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: Stephane Eranian <eranian@google.com>
Cc: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
Changelog [v6]
	- [Michael Ellerman] Use __BIG_ENDIAN_BITFIELD to simplify the
	  endian check.

Changelog [v5]:
	- perf_event.h includes <byteorder.h> which pulls in the local
	  byteorder.h when building the perf tool. This local byteorder.h
	  leaves __LITTLE_ENDIAN and __BIG_ENDIAN undefined.
	  Include <endian.h> explicitly in the local byteorder.h.

Changelog [v2]:
	- [Vince Weaver, Michael Ellerman] No __KERNEL__ in uapi headers.

 include/uapi/linux/perf_event.h |   16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index ca1d90b..383052b7 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -695,6 +695,7 @@ enum perf_callchain_context {
 #define PERF_FLAG_FD_OUTPUT		(1U << 1)
 #define PERF_FLAG_PID_CGROUP		(1U << 2) /* pid=cgroup id, per-cpu mode only */
 
+#if defined(__LITTLE_ENDIAN_BITFIELD)
 union perf_mem_data_src {
 	__u64 val;
 	struct {
@@ -706,6 +707,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 */
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 07/10][v6] powerpc/perf: Add Power8 event PM_MRK_GRP_CMPL to sysfs.
From: Sukadev Bhattiprolu @ 2013-10-16  2:06 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Michael Ellerman, linux-kernel, Stephane Eranian, linuxppc-dev,
	Paul Mackerras, Anshuman Khandual
In-Reply-To: <1381889202-16826-1-git-send-email-sukadev@linux.vnet.ibm.com>

The perf event PM_MRK_GRP_CMPL is useful in analyzing memory hierarchy
of applications.

Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
Changelog[v6]:
	- [Michael Ellerman]: Drop redundant PME_ prefix from event name.

 arch/powerpc/perf/power8-events-list.h |    1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/powerpc/perf/power8-events-list.h b/arch/powerpc/perf/power8-events-list.h
index 1368547..b39e117 100644
--- a/arch/powerpc/perf/power8-events-list.h
+++ b/arch/powerpc/perf/power8-events-list.h
@@ -18,3 +18,4 @@ EVENT(PM_CMPLU_STALL,			0x4000a)
 EVENT(PM_INST_CMPL,			0x00002)
 EVENT(PM_BRU_FIN,			0x10068)
 EVENT(PM_BR_MPRED_CMPL,			0x400f6)
+EVENT(PM_MRK_GRP_CMPL,			0x40130)
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 09/10][v6] powerpc/perf: Export Power8 memory hierarchy info to user space.
From: Sukadev Bhattiprolu @ 2013-10-16  2:06 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Michael Ellerman, linux-kernel, Stephane Eranian, linuxppc-dev,
	Paul Mackerras, Anshuman Khandual
In-Reply-To: <1381889202-16826-1-git-send-email-sukadev@linux.vnet.ibm.com>

On Power8, the LDST field 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. Fortunately, the memory hierarchy levels in Power8 map fairly easily
into the arch-neutral levels as described by the ldst_src_map[] table.

Usage:

	perf record -d -e 'cpu/PM_MRK_GRP_CMPL/' <application>
	perf report -n --mem-mode --sort=mem,sym,dso,symbol_daddr,dso_daddr"

		For samples involving load/store instructions, the memory
		hierarchy level is shown as "L1 hit", "Remote RAM hit" etc.
	# or

	perf record --data <application>
	perf report -D

		Sample records contain a 'data_src' field which encodes the
		memory hierarchy level: Eg: data_src 0x442 indicates
		MEM_OP_LOAD, MEM_LVL_HIT, MEM_LVL_L2 (i.e load hit L2).

Note that the PMU event PM_MRK_GRP_CMPL tracks all marked group completions
events. While some of these are loads and stores, others like 'add'
instructions may also be sampled. One alternative of sampling on
PM_MRK_GRP_CMPL and throwing away non-loads and non-store samples could
yield an inconsistent profile of the application.

As the precise semantics of 'perf mem -t load' or 'perf mem -t store' (which
require sampling only loads or only stores) cannot be implemented on Power,
we don't implement 'perf mem' on Power for now.

Thanks to input from Stephane Eranian, Michael Ellerman and Michael Neuling.

Cc: Stephane Eranian <eranian@google.com>
Cc: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
Changelog[v2]:
	Drop support for 'perf mem' for Power (use perf-record and perf-report
	directly)

 arch/powerpc/include/asm/perf_event_server.h |    2 +
 arch/powerpc/perf/core-book3s.c              |   11 ++++++
 arch/powerpc/perf/power8-pmu.c               |   53 ++++++++++++++++++++++++++
 3 files changed, 66 insertions(+)

diff --git a/arch/powerpc/include/asm/perf_event_server.h b/arch/powerpc/include/asm/perf_event_server.h
index d7b3419..5f2c449 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 {
 	void            (*config_bhrb)(u64 pmu_bhrb_filter);
 	void		(*disable_pmc)(unsigned int pmc, unsigned long mmcr[]);
 	int		(*limited_pmc_event)(u64 event_id);
+	void		(*get_mem_data_src)(union perf_mem_data_src *dsrc,
+				struct pt_regs *regs);
 	u32		flags;
 	const struct attribute_group	**attr_groups;
 	int		n_generic;
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index eeae308..5221ba1 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -1696,6 +1696,13 @@ ssize_t power_events_sysfs_show(struct device *dev,
 	return sprintf(page, "event=0x%02llx\n", pmu_attr->id);
 }
 
+static inline void power_get_mem_data_src(union perf_mem_data_src *dsrc,
+				struct pt_regs *regs)
+{
+	if  (ppmu->get_mem_data_src)
+		ppmu->get_mem_data_src(dsrc, regs);
+}
+
 struct pmu power_pmu = {
 	.pmu_enable	= power_pmu_enable,
 	.pmu_disable	= power_pmu_disable,
@@ -1777,6 +1784,10 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
 			data.br_stack = &cpuhw->bhrb_stack;
 		}
 
+		if (event->attr.sample_type & PERF_SAMPLE_DATA_SRC &&
+						ppmu->get_mem_data_src)
+			ppmu->get_mem_data_src(&data.data_src, regs);
+
 		if (perf_event_overflow(event, &data, regs))
 			power_pmu_stop(event, 0);
 	}
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index 5141d97..c25b5c3 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -541,6 +541,58 @@ static struct attribute_group power8_pmu_events_group = {
 	.attrs = power8_events_attr,
 };
 
+#define POWER8_SIER_TYPE_SHIFT	15
+#define POWER8_SIER_TYPE_MASK	(0x7LL << POWER8_SIER_TYPE_SHIFT)
+
+#define POWER8_SIER_LDST_SHIFT	1
+#define POWER8_SIER_LDST_MASK	(0x7LL << POWER8_SIER_LDST_SHIFT)
+
+#define P(a, b)			PERF_MEM_S(a, b)
+#define PLH(a, b)		(P(OP, LOAD) | P(LVL, HIT) | P(a, b))
+#define PSM(a, b)		(P(OP, STORE) | P(LVL, MISS) | P(a, b))
+
+/*
+ * Power8 interpretations:
+ * REM_CCE1: 1-hop indicates L2/L3 cache of a different core on same chip
+ * REM_CCE2: 2-hop indicates different chip or different node.
+ */
+static u64 ldst_src_map[] = {
+	/* 000 */	P(LVL, NA),
+
+	/* 001 */	PLH(LVL, L1),
+	/* 010 */	PLH(LVL, L2),
+	/* 011 */	PLH(LVL, L3),
+	/* 100 */	PLH(LVL, LOC_RAM),
+	/* 101 */	PLH(LVL, REM_CCE1),
+	/* 110 */	PLH(LVL, REM_CCE2),
+
+	/* 111 */	PSM(LVL, L1),
+};
+
+static inline bool is_load_store_inst(u64 sier)
+{
+	u64 val;
+	val = (sier & POWER8_SIER_TYPE_MASK) >> POWER8_SIER_TYPE_SHIFT;
+
+	/* 1 = load, 2 = store */
+	return val == 1 || val == 2;
+}
+
+static void power8_get_mem_data_src(union perf_mem_data_src *dsrc,
+			struct pt_regs *regs)
+{
+	u64 idx;
+	u64 sier;
+
+	sier = mfspr(SPRN_SIER);
+
+	if (is_load_store_inst(sier)) {
+		idx = (sier & POWER8_SIER_LDST_MASK) >> POWER8_SIER_LDST_SHIFT;
+
+		dsrc->val |= ldst_src_map[idx];
+	}
+}
+
 PMU_FORMAT_ATTR(event,		"config:0-49");
 PMU_FORMAT_ATTR(pmcxsel,	"config:0-7");
 PMU_FORMAT_ATTR(mark,		"config:8");
@@ -639,6 +691,7 @@ static struct power_pmu power8_pmu = {
 	.get_constraint		= power8_get_constraint,
 	.get_alternatives	= power8_get_alternatives,
 	.disable_pmc		= power8_disable_pmc,
+	.get_mem_data_src	= power8_get_mem_data_src,
 	.flags			= PPMU_HAS_SSLOT | PPMU_HAS_SIER | PPMU_BHRB | PPMU_EBB,
 	.n_generic		= ARRAY_SIZE(power8_generic_events),
 	.generic_events		= power8_generic_events,
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 10/10][v6] powerpc/perf: Export Power7 memory hierarchy info to user space.
From: Sukadev Bhattiprolu @ 2013-10-16  2:06 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Michael Ellerman, linux-kernel, Stephane Eranian, linuxppc-dev,
	Paul Mackerras, Anshuman Khandual
In-Reply-To: <1381889202-16826-1-git-send-email-sukadev@linux.vnet.ibm.com>

On Power7, the DCACHE_SRC field in MMCRA register identifies the memory
hierarchy level (eg: L2, L3 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. Some memory hierarchy levels in Power7 don't map into the arch-neutral
levels. However, since newer generation of the processor (i.e. Power8) uses
fewer levels than in Power7, we don't really need to define new hierarchy
levels just for Power7.

We instead, map as many levels as possible and approximate the rest. See
comments near dcache-src_map[] in the patch.

Usage:

	perf record -d -e 'cpu/PM_MRK_GRP_CMPL/' <application>
	perf report -n --mem-mode --sort=mem,sym,dso,symbol_daddr,dso_daddr"

		For samples involving load/store instructions, the memory
		hierarchy level is shown as "L1 hit", "Remote RAM hit" etc.
	# or

	perf record --data <application>
	perf report -D

		Sample records contain a 'data_src' field which encodes the
		memory hierarchy level: Eg: data_src 0x442 indicates
		MEM_OP_LOAD, MEM_LVL_HIT, MEM_LVL_L2 (i.e load hit L2).

Note that the PMU event PM_MRK_GRP_CMPL tracks all marked group completions
events. While some of these are loads and stores, others like 'add'
instructions may also be sampled.

As such, the precise semantics of 'perf mem -t load' or 'perf mem -t store'
(which require sampling only loads or only stores cannot be implemented on
Power. (Sampling on PM_MRK_GRP_CMPL and throwing away non-loads and non-store
samples could yield an inconsistent profile of the application).

Thanks to input from Stephane Eranian, Michael Ellerman and Michael Neuling.

Cc: Stephane Eranian <eranian@google.com>
Cc: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
Changelog[v4]:
	Drop support for 'perf mem' for Power (use perf-record and perf-report
	directly)

Changelog[v3]:
	[Michael Ellerman] If newer levels that we defined in [v2] are not
	needed for Power8, ignore the new levels for Power7 also, and
	approximate them.
	Separate the TLB level mapping to a separate patchset.

Changelog[v2]:
        [Stephane Eranian] Define new levels rather than ORing the L2 and L3
        with REM_CCE1 and REM_CCE2.
        [Stephane Eranian] allocate a bit PERF_MEM_XLVL_NA for architectures
        that don't use the ->mem_xlvl field.
        Insert the TLB patch ahead so the new TLB bits are contigous with
        existing TLB bits.

 arch/powerpc/perf/power7-pmu.c |   94 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 94 insertions(+)

diff --git a/arch/powerpc/perf/power7-pmu.c b/arch/powerpc/perf/power7-pmu.c
index ae24dfc..3e86bb8 100644
--- a/arch/powerpc/perf/power7-pmu.c
+++ b/arch/powerpc/perf/power7-pmu.c
@@ -11,8 +11,10 @@
 #include <linux/kernel.h>
 #include <linux/perf_event.h>
 #include <linux/string.h>
+#include <linux/uaccess.h>
 #include <asm/reg.h>
 #include <asm/cputable.h>
+#include <asm/code-patching.h>
 
 /*
  * Bits in event code for POWER7
@@ -317,6 +319,97 @@ static void power7_disable_pmc(unsigned int pmc, unsigned long mmcr[])
 		mmcr[1] &= ~(0xffUL << MMCR1_PMCSEL_SH(pmc));
 }
 
+#define POWER7_MMCRA_DCACHE_MISS	(0x1LL << 55)
+#define POWER7_MMCRA_DCACHE_SRC_SHIFT	51
+#define POWER7_MMCRA_DCACHE_SRC_MASK	(0xFLL << POWER7_MMCRA_DCACHE_SRC_SHIFT)
+
+#define P(a, b)		PERF_MEM_S(a, b)
+#define PLH(a, b)	(P(OP, LOAD) | P(LVL, HIT) | P(a, b))
+/*
+ * Map the Power7 DCACHE_SRC field (bits 9..12) in MMCRA register to the
+ * architecture-neutral memory hierarchy levels. For the levels in Power7
+ * that don't map to the arch-neutral levels, approximate to nearest
+ * level.
+ *
+ *	1-hop:	indicates another core on the same chip (2.1 and 3.1 levels).
+ *	2-hops:	indicates a different chip on same or different node (remote
+ *		and distant levels).
+ *
+ * For consistency with this interpretation of the hops, we dont use
+ * the REM_RAM1 level below.
+ *
+ * The *SHR and *MOD states of the cache are ignored/not exported to user.
+ *
+ * ### Levels marked with ### in comments below are approximated
+ */
+static u64 dcache_src_map[] = {
+	PLH(LVL, L2),			/* 00: FROM_L2 */
+	PLH(LVL, L3),			/* 01: FROM_L3 */
+
+	P(LVL, NA),			/* 02: Reserved */
+	P(LVL, NA),			/* 03: Reserved */
+
+	PLH(LVL, REM_CCE1),		/* 04: FROM_L2.1_SHR ### */
+	PLH(LVL, REM_CCE1),		/* 05: FROM_L2.1_MOD ### */
+
+	PLH(LVL, REM_CCE1),		/* 06: FROM_L3.1_SHR ### */
+	PLH(LVL, REM_CCE1),		/* 07: FROM_L3.1_MOD ### */
+
+	PLH(LVL, REM_CCE2),		/* 08: FROM_RL2L3_SHR ### */
+	PLH(LVL, REM_CCE2),		/* 09: FROM_RL2L3_MOD ### */
+
+	PLH(LVL, REM_CCE2),		/* 10: FROM_DL2L3_SHR ### */
+	PLH(LVL, REM_CCE2),		/* 11: FROM_DL2L3_MOD ### */
+
+	PLH(LVL, LOC_RAM),		/* 12: FROM_LMEM */
+	PLH(LVL, REM_RAM2),		/* 13: FROM_RMEM ### */
+	PLH(LVL, REM_RAM2),		/* 14: FROM_DMEM */
+
+	P(LVL, NA),			/* 15: Reserved */
+};
+
+/*
+ * Determine the memory-hierarchy information (if applicable) for the
+ * instruction/address we are sampling. If we encountered a DCACHE_MISS,
+ * mmcra[DCACHE_SRC_MASK] specifies the memory level from which the operand
+ * was loaded.
+ *
+ * Otherwise, it is an L1-hit, provided the instruction was a load/store.
+ */
+static void power7_get_mem_data_src(union perf_mem_data_src *dsrc,
+			struct pt_regs *regs)
+{
+	u64 idx;
+	u64 mmcra = regs->dsisr;
+	u64 addr;
+	int ret;
+	unsigned int instr;
+
+	if (mmcra & POWER7_MMCRA_DCACHE_MISS) {
+		idx = mmcra & POWER7_MMCRA_DCACHE_SRC_MASK;
+		idx >>= POWER7_MMCRA_DCACHE_SRC_SHIFT;
+
+		dsrc->val |= dcache_src_map[idx];
+		return;
+	}
+
+	instr = 0;
+	addr = perf_instruction_pointer(regs);
+
+	if (is_kernel_addr(addr))
+		instr = *(unsigned int *)addr;
+	else {
+		pagefault_disable();
+		ret = __get_user_inatomic(instr, (unsigned int __user *)addr);
+		pagefault_enable();
+		if (ret)
+			instr = 0;
+	}
+	if (instr && instr_is_load_store_2_06(&instr))
+		dsrc->val |= PLH(LVL, L1);
+}
+
+
 static int power7_generic_events[] = {
 	[PERF_COUNT_HW_CPU_CYCLES] =			PM_CYC,
 	[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] =	PM_GCT_NOSLOT_CYC,
@@ -437,6 +530,7 @@ static struct power_pmu power7_pmu = {
 	.get_constraint		= power7_get_constraint,
 	.get_alternatives	= power7_get_alternatives,
 	.disable_pmc		= power7_disable_pmc,
+	.get_mem_data_src	= power7_get_mem_data_src,
 	.flags			= PPMU_ALT_SIPR,
 	.attr_groups		= power7_pmu_attr_groups,
 	.n_generic		= ARRAY_SIZE(power7_generic_events),
-- 
1.7.9.5

^ permalink raw reply related

* RE: [PATCH v5] powerpc/mpc85xx: Update the clock nodes in device tree
From: Tang Yuantian-B29983 @ 2013-10-16  2:57 UTC (permalink / raw)
  To: Wood Scott-B07421
  Cc: Mark Rutland, devicetree@vger.kernel.org,
	linuxppc-dev@lists.ozlabs.org, Li Yang-Leo-R58472
In-Reply-To: <1381858855.7979.693.camel@snotra.buserror.net>

PiA+ID4gPiA+DQo+ID4gPiA+IFRoZSBkZXZpY2UgdHJlZSBtYWtlcyB0aGF0IHF1aXRlIGNsZWFy
Lg0KPiA+ID4NCj4gPiA+IFlvdSBjaG9zZSB0byBtb2RlbCBpdCB0aGF0IHdheSBpbiB0aGUgZGV2
aWNlIHRyZWU7IHRoYXQgZG9lc24ndCBtYWtlDQo+ID4gPiBpdCBjbGVhciB0aGF0IHRoZSBoYXJk
d2FyZSB3b3JrcyB0aGF0IHdheSBvciB0aGF0IGl0J3MgYSBnb29kIHdheSB0bw0KPiA+ID4gbW9k
ZWwgaXQuDQo+ID4gPg0KPiA+ID4gPiBFYWNoIFBMTCBoYXMgc2V2ZXJhbCBvdXRwdXQgd2hpY2gg
TVVYIG5vZGUgY2FuIHRha2UgZnJvbS4NCj4gPiA+DQo+ID4gPiBQb2ludCBvdXQgd2hlcmUgaW4g
dGhlIGhhcmR3YXJlIGRvY3VtZW50YXRpb24gaXQgc2F5cyB0aGlzLiAgV2hhdCBJDQo+ID4gPiBz
ZWUgaXMgYSBQTEwgdGhhdCBoYXMgb25lIG91dHB1dCwgYW5kIGEgTVVYIHJlZ2lzdGVyIHRoYXQg
Y2FuIGNob29zZQ0KPiA+ID4gZnJvbSBtdWx0aXBsZSBQTEwgYW5kIGRpdmlkZXIgb3B0aW9ucy4N
Cj4gPiA+DQo+ID4gVGFrZSBUNDI0MCBmb3IgZXhhbXBsZTogc2VlIHNlY3Rpb24gNC42LjUuMSAs
IChQYWdlIDE0MSkgaW4gVDQyNDBSTSBSZXYuDQo+IEQsIDA5LzIwMTIuDQo+IA0KPiBUaGF0IHNo
b3dzIHRoZSBkaXZpZGVycyBhcyBiZWluZyBzb21ld2hlcmUgaW4gYmV0d2VlbiB0aGUgUExMIGFu
ZCB0aGUgTVVYLg0KPiBUaGUgTVVYIGlzIHdoZXJlIHRoZSBkaXZpZGVyIGlzIHNlbGVjdGVkLiAg
VGhlcmUncyBub3RoaW5nIGluIHRoZSBQTEwncw0KPiBwcm9ncmFtbWluZyBpbnRlcmZhY2UgdGhh
dCByZWxhdGVzIHRvIHRoZSBkaXZpZGVycy4gIEFzIHN1Y2ggaXQncyBzaW1wbGVyDQo+IHRvIG1v
ZGVsIGl0IGFzIGJlaW5nIHBhcnQgb2YgdGhlIE1VWC4NCj4gDQo+IC1TY290dA0KPiANCkkgZG9u
J3Qga25vdyB3aGV0aGVyIGl0IGlzIHNpbXBsZXIsIGJ1dCAibW9kZWxpbmcgZGl2aWRlciBhcyBi
ZWluZyBwYXJ0IG9mIHRoZSBNVVgiDQppcyB5b3VyIGd1ZXNzLCByaWdodD8NCklmIHRoZSAiZGl2
aWRlciIgaXMgaW5jbHVkZWQgaW4gTVVYLCB0aGUgTVVYIHdvdWxkIG5vdCBiZSBjYWxsZWQgIk1V
WCIuDQpJIGRvbid0IGtub3cgd2hldGhlciAiZGl2aWRlciIgbW9kdWxlIGV4aXN0cyBvciBub3Qu
IElmIGl0IGV4aXN0cywgaXQgc2hvdWxkIGJlIHBhcnQNCm9mIFBMTCBvciBiZXR3ZWVuIFBMTCBh
bmQgTVVYLiB3aGVyZXZlciBpdCB3YXMsIHRoZSBkZXZpY2UgdHJlZSBiaW5kaW5nIGlzIGFwcHJv
cHJpYXRlLg0KVGhlIFAzMDQxUk0gc2hvd3MgZXhhY3RseSBlYWNoIFBMTCBoYXMgMiBvdXRwdXRz
IHdoaWNoIGRlZmluaXRlbHkgaGF2ZSBubyAiZGl2aWRlciIgYXQgYWxsLg0KDQpSZWdhcmRzLA0K
WXVhbnRpYW4NCg==

^ permalink raw reply

* Re: [PATCH] powerpc, perf: Configure BHRB filter before enabling PMU interrupts
From: Anshuman Khandual @ 2013-10-16  4:30 UTC (permalink / raw)
  To: Michael Ellerman; +Cc: linuxppc-dev, mikey
In-Reply-To: <20131014061958.GA8300@concordia>

On 10/14/2013 11:49 AM, Michael Ellerman wrote:
> On Fri, Oct 11, 2013 at 10:02:28AM +0530, Anshuman Khandual wrote:
>> On 10/11/2013 07:41 AM, Michael Ellerman wrote:
>>> On Thu, Oct 10, 2013 at 02:20:22PM +0530, Anshuman Khandual wrote:
>>>
>>>> Even I think this is not right. Instruction sampling should have been
>>>> enabled before we enable PMU interrupts. Else there is a small window
>>>> of time where we could have the PMU enabled with events (which requires
>>>> sampling) without the sampling itself being enabled in MMCRA.
>>>
>>> Yes I agree. That's a separate bug, which we'll need to test on all the book3s
>>> platforms we have perf support for.
>>
>> Okay, I guess any platform which supports sampling will definitely want to have
>> it enabled before we can set the events to count on PMU. Can you think of any
>> problem which can arise if we move it before the enabling the PMU back ? Else
>> we can fix this easily.
> 
> In theory it should be a trivial change. But hardware can behave in
> strange ways, it's possible on some old chip we need to do it the
> current way for some reason.
> 
> So although I don't think it will be a problem, it could be, so we
> will need to test it thoroughly.

So which are the HW chips, you would like to test this fix for possible problems ? 

^ permalink raw reply

* Re: [PATCH] powerpc 8xx: Fixing memory init issue with CONFIG_PIN_TLB
From: leroy christophe @ 2013-10-16  5:45 UTC (permalink / raw)
  To: Scott Wood; +Cc: Paul Mackerras, linuxppc-dev, linux-kernel
In-Reply-To: <1381869216.7979.718.camel@snotra.buserror.net>

[-- Attachment #1: Type: text/plain, Size: 3347 bytes --]


Le 15/10/2013 22:33, Scott Wood a écrit :
> On Tue, 2013-10-15 at 18:27 +0200, leroy christophe wrote:
>> Le 11/10/2013 17:13, Joakim Tjernlund a écrit :
>>> "Linuxppc-dev"
>>> <linuxppc-dev-bounces+joakim.tjernlund=transmode.se@lists.ozlabs.org>
>>> wrote on 2013/10/11 14:56:40:
>>>> Activating CONFIG_PIN_TLB allows access to the 24 first Mbytes of memory
>>> at
>>>> bootup instead of 8. It is needed for "big" kernels for instance when
>>> activating
>>>> CONFIG_LOCKDEP_SUPPORT. This needs to be taken into account in init_32
>>> too,
>>>> otherwise memory allocation soon fails after startup.
>>>>
>>>> Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
>>>>
>>>> diff -ur linux-3.11.org/arch/powerpc/kernel/head_8xx.S
>>> linux-3.11/arch/powerpc/kernel/head_8xx.S
>>>> --- linux-3.11.org/arch/powerpc/mm/init_32.c   2013-09-02
>>> 22:46:10.000000000 +0200
>>>> +++ linux-3.11/arch/powerpc/mm/init_32.c   2013-09-09 11:28:54.000000000
>>> +0200
>>>> @@ -213,7 +213,12 @@
>>>>        */
>>>>       BUG_ON(first_memblock_base != 0);
>>>>
>>>> +#ifdef CONFIG_PIN_TLB
>>>> +   /* 8xx can only access 24MB at the moment */
>>>> +   memblock_set_current_limit(min_t(u64, first_memblock_size,
>>> 0x01800000));
>>>> +#else
>>>>       /* 8xx can only access 8MB at the moment */
>>>>       memblock_set_current_limit(min_t(u64, first_memblock_size,
>>> 0x00800000));
>>>> +#endif
>>>>    }
>>>>    #endif /* CONFIG_8xx */
>>> hmm, I think you should always map 24 MB (or less if RAM < 24 MB) and do
>>> the same
>>> in head_8xx.S.
>>>
>>> Or to keep it simple, just always map at least 16 MB here and in
>>> head_8xx.S, assuming
>>> that 16 MB is min RAM for any 8xx system running 3.x kernels.
>> Yes we could do a more elaborated modification in the future. However it
>> also has an impact on the boot loader, so I'm not sure we should make it
>> the default without thinking twice.
>>
>> In the meantime, my patch does take into account the existing situation
>> where you have 8Mb by default and 24Mb when you activate CONFIG_PIN_TLB.
>> I see it as a bug fix and I believe we should include it at least in
>> order to allow including in the stable releases.
>>
>> Do you see any issue with this approach ?
> The patch is fine, but I don't think it's stable material (BTW, if it
> were, you should have marked it as such when submitting).  If I
> understand the situation correctly, there's no regression, and nothing
> fails to work with CONFIG_PIN_TLB that would have worked without it.
> It's just making CONFIG_PIN_TLB more useful.
>
>
Yes the patch is definitly stable. How should I have mark it ?

The situation is that in 2010, I discovered that I was not able to start 
a big Kernel because of the 8Mb limit.
You told me (see attached mail) that in order to get rid of that limit I 
shall use CONFIG_PIN_TLB: it was the first step, it helped pass the 
memory zeroize at init, but it was not enough as I then got problems 
with the Device Tree being erased because being put inside the first 8Mb 
area too. Then I temporarely gave up at that time.

Recently I started again. After fixing my bootloader to get the device 
tree somewhere else, I discovered this 8Mb limit hardcoded in 
mm/init_32.c for the 8xx
With the patch I submitted I can now boot a kernel which is bigger than 8Mb.

So, I'm a bit lost here on what to do.

[-- Attachment #2: Message joint --]
[-- Type: message/rfc822, Size: 6767 bytes --]

From: Scott Wood <scottwood@freescale.com>
To: leroy christophe <christophe.leroy@c-s.fr>
Cc: Joakim Tjernlund <joakim.tjernlund@transmode.se>, <linuxppc-dev@lists.ozlabs.org>, <linux-kernel@vger.kernel.org>, Paul Mackerras <paulus@samba.org>
Subject: Re: [PATCH] powerpc 8xx: Fixing memory init issue with CONFIG_PIN_TLB
Date: Tue, 15 Oct 2013 15:33:36 -0500
Message-ID: <1381869216.7979.718.camel@snotra.buserror.net>

On Tue, 2013-10-15 at 18:27 +0200, leroy christophe wrote:
> Le 11/10/2013 17:13, Joakim Tjernlund a écrit :
> > "Linuxppc-dev"
> > <linuxppc-dev-bounces+joakim.tjernlund=transmode.se@lists.ozlabs.org>
> > wrote on 2013/10/11 14:56:40:
> >> Activating CONFIG_PIN_TLB allows access to the 24 first Mbytes of memory
> > at
> >> bootup instead of 8. It is needed for "big" kernels for instance when
> > activating
> >> CONFIG_LOCKDEP_SUPPORT. This needs to be taken into account in init_32
> > too,
> >> otherwise memory allocation soon fails after startup.
> >>
> >> Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
> >>
> >> diff -ur linux-3.11.org/arch/powerpc/kernel/head_8xx.S
> > linux-3.11/arch/powerpc/kernel/head_8xx.S
> >> --- linux-3.11.org/arch/powerpc/mm/init_32.c   2013-09-02
> > 22:46:10.000000000 +0200
> >> +++ linux-3.11/arch/powerpc/mm/init_32.c   2013-09-09 11:28:54.000000000
> > +0200
> >> @@ -213,7 +213,12 @@
> >>       */
> >>      BUG_ON(first_memblock_base != 0);
> >>
> >> +#ifdef CONFIG_PIN_TLB
> >> +   /* 8xx can only access 24MB at the moment */
> >> +   memblock_set_current_limit(min_t(u64, first_memblock_size,
> > 0x01800000));
> >> +#else
> >>      /* 8xx can only access 8MB at the moment */
> >>      memblock_set_current_limit(min_t(u64, first_memblock_size,
> > 0x00800000));
> >> +#endif
> >>   }
> >>   #endif /* CONFIG_8xx */
> > hmm, I think you should always map 24 MB (or less if RAM < 24 MB) and do
> > the same
> > in head_8xx.S.
> >
> > Or to keep it simple, just always map at least 16 MB here and in
> > head_8xx.S, assuming
> > that 16 MB is min RAM for any 8xx system running 3.x kernels.
> Yes we could do a more elaborated modification in the future. However it 
> also has an impact on the boot loader, so I'm not sure we should make it 
> the default without thinking twice.
> 
> In the meantime, my patch does take into account the existing situation 
> where you have 8Mb by default and 24Mb when you activate CONFIG_PIN_TLB.
> I see it as a bug fix and I believe we should include it at least in 
> order to allow including in the stable releases.
> 
> Do you see any issue with this approach ?

The patch is fine, but I don't think it's stable material (BTW, if it
were, you should have marked it as such when submitting).  If I
understand the situation correctly, there's no regression, and nothing
fails to work with CONFIG_PIN_TLB that would have worked without it.
It's just making CONFIG_PIN_TLB more useful.

-Scott


^ permalink raw reply

* [PATCH 0/2] Export POWER8 PMU raw event codes through sysfs
From: Anshuman Khandual @ 2013-10-16  5:52 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: mikey, sukadev, michaele

	This patchset adds some missing event list for POWER7 PMU raw
events which are exported through sysfs interface. Also adds a new
set of raw PMU events list for POWER8. I have completed some amount
of initial testing to verify the working of POWER8 raw event codes
through sysfs.

Before the patch
================
directory contents: /sys/bus/event_source/devices/cpu/
format  perf_event_mux_interval_ms power  subsystem  type  uevent

After the patch
===============
(1) directory contents: /sys/bus/event_source/devices/cpu/
'events'  format  perf_event_mux_interval_ms power  subsystem  type  uevent

(2) contents inside new directory: /sys/bus/event_source/devices/cpu/events/
............................
............................
............................
PM_ANY_THRD_RUN_CYC
PM_BR_2PATH
PM_BR_CMPL
PM_BR_MRK_2PATH
PM_BR_TAKEN_CMPL
PM_CMPLU_STALL_BRU
PM_CMPLU_STALL_BRU_CRU
PM_CMPLU_STALL_COQ_FULL
PM_CMPLU_STALL_DCACHE_MISS
PM_CMPLU_STALL_DMISS_L21_L31
PM_CMPLU_STALL_DMISS_L2L3
PM_CMPLU_STALL_DMISS_L2L3_CONFLICT
PM_CMPLU_STALL_DMISS_L3MISS
PM_CMPLU_STALL_DMISS_LMEM
PM_CMPLU_STALL_DMISS_REMOTE
PM_CMPLU_STALL_ERAT_MISS
PM_CMPLU_STALL_FLUSH
PM_CMPLU_STALL_FXLONG
PM_CMPLU_STALL_FXU
PM_CMPLU_STALL_HWSYNC
PM_CMPLU_STALL_LOAD_FINISH
...........................
............................
............................

Sample tests:
================================================================
perf stat -e 'cpu/PM_CMPLU_STALL_ERAT_MISS/'  ls

 Performance counter stats for 'ls':

             56762 cpu/PM_CMPLU_STALL_ERAT_MISS/                                   

       0.003643785 seconds time elapsed
       
perf stat -e 'cpu/PM_CMPLU_STALL_BRU/' ls

 Performance counter stats for 'ls':

            208615 cpu/PM_CMPLU_STALL_BRU/                                     

       0.003600713 seconds time elapsed
=================================================================

Anshuman Khandual (2):
  power7, perf: Make some new raw event codes available in sysfs
  power8, perf: Export raw event codes through sysfs interface

 arch/powerpc/perf/power7-events-list.h |  10 +++
 arch/powerpc/perf/power8-events-list.h | 146 +++++++++++++++++++++++++++++++++
 arch/powerpc/perf/power8-pmu.c         |  30 +++++++
 3 files changed, 186 insertions(+)
 create mode 100644 arch/powerpc/perf/power8-events-list.h

-- 
1.7.11.7

^ permalink raw reply

* [PATCH 2/2] power8, perf: Export raw event codes through sysfs interface
From: Anshuman Khandual @ 2013-10-16  5:53 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: mikey, sukadev, michaele
In-Reply-To: <1381902780-2719-1-git-send-email-khandual@linux.vnet.ibm.com>

This patch exports a set of POWER8 PMU raw event codes through
sysfs interface. Right now the raw event set matches the entire
set of POWER8 events found in libpfm4 library.

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 arch/powerpc/perf/power8-events-list.h | 146 +++++++++++++++++++++++++++++++++
 arch/powerpc/perf/power8-pmu.c         |  30 +++++++
 2 files changed, 176 insertions(+)
 create mode 100644 arch/powerpc/perf/power8-events-list.h

diff --git a/arch/powerpc/perf/power8-events-list.h b/arch/powerpc/perf/power8-events-list.h
new file mode 100644
index 0000000..ee5b40e
--- /dev/null
+++ b/arch/powerpc/perf/power8-events-list.h
@@ -0,0 +1,146 @@
+/*
+ * Performance counter support for POWER8 processors.
+ *
+ * Copyright 2013 Anshuman Khandual, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+EVENT(PM_1PLUS_PPC_CMPL,                      0x04898)
+EVENT(PM_1PLUS_PPC_DISP,                      0x400f2)
+EVENT(PM_ANY_THRD_RUN_CYC,                    0x100fa)
+EVENT(PM_BR_TAKEN_CMPL,                       0x200fa)
+EVENT(PM_DATA_FROM_L2MISS,                    0x200fe)
+EVENT(PM_DATA_FROM_L3MISS,                    0x300fe)
+EVENT(PM_DATA_FROM_MEM,                       0x400fe)
+EVENT(PM_DTLB_MISS,                           0x300fc)
+EVENT(PM_EXT_INT,                             0x200f8)
+EVENT(PM_FLOP,                                0x100f4)
+EVENT(PM_FLUSH,                               0x400f8)
+EVENT(PM_IERAT_MISS,                          0x100f6)
+EVENT(PM_INST_DISP,                           0x200f2)
+EVENT(PM_INST_FROM_L3MISS,                    0x300fa)
+EVENT(PM_ITLB_MISS,                           0x400fc)
+EVENT(PM_L1_DCACHE_RELOAD_VALID,              0x300f6)
+EVENT(PM_L1_ICACHE_MISS,                      0x200fc)
+EVENT(PM_LD_MISS_L1,                          0x400f0)
+EVENT(PM_LSU_DERAT_MISS,                      0x200f6)
+EVENT(PM_MRK_BR_MPRED_CMPL,                   0x300e4)
+EVENT(PM_MRK_BR_TAKEN_CMPL,                   0x100e2)
+EVENT(PM_MRK_DATA_FROM_L2MISS,                0x400e8)
+EVENT(PM_MRK_DATA_FROM_L3MISS,                0x200e4)
+EVENT(PM_MRK_DATA_FROM_MEM,                   0x200e0)
+EVENT(PM_MRK_DERAT_MISS,                      0x300e6)
+EVENT(PM_MRK_DTLB_MISS,                       0x400e4)
+EVENT(PM_MRK_INST_CMPL,                       0x400e0)
+EVENT(PM_MRK_INST_DISP,                       0x100e0)
+EVENT(PM_MRK_INST_FROM_L3MISS,                0x400e6)
+EVENT(PM_MRK_L1_ICACHE_MISS,                  0x100e4)
+EVENT(PM_MRK_L1_RELOAD_VALID,                 0x100ea)
+EVENT(PM_MRK_LD_MISS_L1,                      0x200e2)
+EVENT(PM_MRK_ST_CMPL,                         0x300e2)
+EVENT(PM_RUN_CYC,                             0x600f4)
+EVENT(PM_RUN_INST_CMPL,                       0x500fa)
+EVENT(PM_RUN_PURR,                            0x400f4)
+EVENT(PM_ST_FIN,                              0x200f0)
+EVENT(PM_ST_MISS_L1,                          0x300f0)
+EVENT(PM_TB_BIT_TRANS,                        0x300f8)
+EVENT(PM_THRD_CONC_RUN_INST,                  0x300f4)
+EVENT(PM_THRESH_EXC_1024,                     0x300ea)
+EVENT(PM_THRESH_EXC_128,                      0x400ea)
+EVENT(PM_THRESH_EXC_2048,                     0x400ec)
+EVENT(PM_THRESH_EXC_256,                      0x100e8)
+EVENT(PM_THRESH_EXC_32,                       0x200e6)
+EVENT(PM_THRESH_EXC_4096,                     0x100e6)
+EVENT(PM_THRESH_EXC_512,                      0x200e8)
+EVENT(PM_THRESH_EXC_64,                       0x300e8)
+EVENT(PM_THRESH_MET,                          0x100ec)
+EVENT(PM_BR_2PATH,                            0x40036)
+EVENT(PM_BR_CMPL,                             0x40060)
+EVENT(PM_BR_MRK_2PATH,                        0x40138)
+EVENT(PM_CMPLU_STALL_BRU,                     0x4d018)
+EVENT(PM_CMPLU_STALL_BRU_CRU,                 0x2d018)
+EVENT(PM_CMPLU_STALL_COQ_FULL,                0x30026)
+EVENT(PM_CMPLU_STALL_DCACHE_MISS,             0x2c012)
+EVENT(PM_CMPLU_STALL_DMISS_L21_L31,           0x2c018)
+EVENT(PM_CMPLU_STALL_DMISS_L2L3,              0x2c016)
+EVENT(PM_CMPLU_STALL_DMISS_L2L3_CONFLICT,     0x4c016)
+EVENT(PM_CMPLU_STALL_DMISS_L3MISS,            0x4c01a)
+EVENT(PM_CMPLU_STALL_DMISS_LMEM,              0x4c018)
+EVENT(PM_CMPLU_STALL_DMISS_REMOTE,            0x2c01c)
+EVENT(PM_CMPLU_STALL_ERAT_MISS,               0x4c012)
+EVENT(PM_CMPLU_STALL_FLUSH,                   0x30038)
+EVENT(PM_CMPLU_STALL_FXLONG,                  0x4d016)
+EVENT(PM_CMPLU_STALL_FXU,                     0x2d016)
+EVENT(PM_CMPLU_STALL_HWSYNC,                  0x30036)
+EVENT(PM_CMPLU_STALL_LOAD_FINISH,             0x4d014)
+EVENT(PM_CMPLU_STALL_LSU,                     0x2c010)
+EVENT(PM_CMPLU_STALL_LWSYNC,                  0x10036)
+EVENT(PM_CMPLU_STALL_MEM_ECC_DELAY,           0x30028)
+EVENT(PM_CMPLU_STALL_NTCG_FLUSH,              0x2e01e)
+EVENT(PM_CMPLU_STALL_OTHER_CMPL,              0x30006)
+EVENT(PM_CMPLU_STALL_REJECT,                  0x4c010)
+EVENT(PM_CMPLU_STALL_REJECT_LHS,              0x2c01a)
+EVENT(PM_CMPLU_STALL_REJ_LMQ_FULL,            0x4c014)
+EVENT(PM_CMPLU_STALL_SCALAR,                  0x4d010)
+EVENT(PM_CMPLU_STALL_SCALAR_LONG,             0x2d010)
+EVENT(PM_CMPLU_STALL_STORE,                   0x2c014)
+EVENT(PM_CMPLU_STALL_ST_FWD,                  0x4c01c)
+EVENT(PM_CMPLU_STALL_THRD,                    0x1001c)
+EVENT(PM_CMPLU_STALL_VECTOR,                  0x2d014)
+EVENT(PM_CMPLU_STALL_VECTOR_LONG,             0x4d012)
+EVENT(PM_CMPLU_STALL_VSU,                     0x2d012)
+EVENT(PM_DATA_FROM_L2,                        0x1c042)
+EVENT(PM_DATA_FROM_L2_NO_CONFLICT,            0x1c040)
+EVENT(PM_DATA_FROM_L3,                        0x4c042)
+EVENT(PM_DATA_FROM_L3MISS_MOD,                0x4c04e)
+EVENT(PM_DATA_FROM_L3_NO_CONFLICT,            0x1c044)
+EVENT(PM_DATA_FROM_LMEM,                      0x2c048)
+EVENT(PM_DATA_FROM_MEMORY,                    0x2c04c)
+EVENT(PM_DC_PREF_STREAM_STRIDED_CONF,         0x3e050)
+EVENT(PM_GCT_NOSLOT_BR_MPRED,                 0x4d01e)
+EVENT(PM_GCT_NOSLOT_BR_MPRED_ICMISS,          0x4d01a)
+EVENT(PM_GCT_NOSLOT_DISP_HELD_ISSQ,           0x2d01e)
+EVENT(PM_GCT_NOSLOT_DISP_HELD_OTHER,          0x2e010)
+EVENT(PM_GCT_NOSLOT_DISP_HELD_SRQ,            0x2d01c)
+EVENT(PM_GCT_NOSLOT_IC_L3MISS,                0x4e010)
+EVENT(PM_GCT_NOSLOT_IC_MISS,                  0x2d01a)
+EVENT(PM_GRP_DISP,                            0x3000a)
+EVENT(PM_GRP_MRK,                             0x10130)
+EVENT(PM_HV_CYC,                              0x2000a)
+EVENT(PM_IOPS_CMPL,                           0x10014)
+EVENT(PM_LD_CMPL,                             0x1002e)
+EVENT(PM_LD_L3MISS_PEND_CYC,                  0x10062)
+EVENT(PM_MRK_DATA_FROM_L2,                    0x1d142)
+EVENT(PM_MRK_DATA_FROM_L2MISS_CYC,            0x4c12e)
+EVENT(PM_MRK_DATA_FROM_L2_CYC,                0x4c122)
+EVENT(PM_MRK_DATA_FROM_L2_NO_CONFLICT,        0x1d140)
+EVENT(PM_MRK_DATA_FROM_L2_NO_CONFLICT_CYC,    0x4c120)
+EVENT(PM_MRK_DATA_FROM_L3,                    0x4d142)
+EVENT(PM_MRK_DATA_FROM_L3MISS_CYC,            0x2d12e)
+EVENT(PM_MRK_DATA_FROM_L3_CYC,                0x2d122)
+EVENT(PM_MRK_DATA_FROM_L3_NO_CONFLICT,        0x1d144)
+EVENT(PM_MRK_DATA_FROM_L3_NO_CONFLICT_CYC,    0x4c124)
+EVENT(PM_MRK_DATA_FROM_LL4,                   0x1d14c)
+EVENT(PM_MRK_DATA_FROM_LL4_CYC,               0x4c12c)
+EVENT(PM_MRK_DATA_FROM_LMEM,                  0x2d148)
+EVENT(PM_MRK_DATA_FROM_LMEM_CYC,              0x4d128)
+EVENT(PM_MRK_DATA_FROM_MEMORY,                0x2d14c)
+EVENT(PM_MRK_DATA_FROM_MEMORY_CYC,            0x4d12c)
+EVENT(PM_MRK_GRP_CMPL,                        0x40130)
+EVENT(PM_MRK_INST_DECODED,                    0x20130)
+EVENT(PM_MRK_L2_RC_DISP,                      0x20114)
+EVENT(PM_MRK_LD_MISS_L1_CYC,                  0x4013e)
+EVENT(PM_MRK_STALL_CMPLU_CYC,                 0x3013e)
+EVENT(PM_NEST_REF_CLK,                        0x3006e)
+EVENT(PM_PMC1_OVERFLOW,                       0x20010)
+EVENT(PM_PMC2_OVERFLOW,                       0x30010)
+EVENT(PM_PMC3_OVERFLOW,                       0x40010)
+EVENT(PM_PMC4_OVERFLOW,                       0x10010)
+EVENT(PM_PMC6_OVERFLOW,                       0x30024)
+EVENT(PM_PPC_CMPL,                            0x40002)
+EVENT(PM_THRD_ALL_RUN_CYC,                    0x2000c)
+EVENT(PM_THRESH_NOT_MET,                      0x4016e)
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index a3f7abd..6897cc3 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -25,6 +25,16 @@
 #define PM_BRU_FIN			0x10068
 #define PM_BR_MPRED_CMPL		0x400f6
 
+/*
+ * Power8 event codes.
+ */
+#define EVENT(_name, _code) \
+	PME_##_name = _code,
+enum {
+	#include "power8-events-list.h"
+};
+#undef EVENT
+
 
 /*
  * Raw event encoding for POWER8:
@@ -540,6 +550,25 @@ static struct attribute *power8_pmu_format_attr[] = {
 	NULL,
 };
 
+
+#define EVENT(_name, _code)     POWER_EVENT_ATTR(_name, _name);
+#include "power8-events-list.h"
+#undef EVENT
+
+#define EVENT(_name, _code)     POWER_EVENT_PTR(_name),
+
+static struct attribute *power8_events_attr[] = {
+        #include "power8-events-list.h"
+        #undef EVENT
+        NULL
+};
+
+
+static struct attribute_group power8_pmu_events_group = {
+        .name = "events",
+        .attrs = power8_events_attr,
+};
+
 struct attribute_group power8_pmu_format_group = {
 	.name = "format",
 	.attrs = power8_pmu_format_attr,
@@ -547,6 +576,7 @@ struct attribute_group power8_pmu_format_group = {
 
 static const struct attribute_group *power8_pmu_attr_groups[] = {
 	&power8_pmu_format_group,
+	&power8_pmu_events_group,
 	NULL,
 };
 
-- 
1.7.11.7

^ permalink raw reply related

* [PATCH 1/2] power7, perf: Make some new raw event codes available in sysfs
From: Anshuman Khandual @ 2013-10-16  5:52 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: mikey, sukadev, michaele
In-Reply-To: <1381902780-2719-1-git-send-email-khandual@linux.vnet.ibm.com>

This patch adds some more raw event codes into the existing list
of event codes present in power7-events-list.h file. This tries
to complete the list of events supported in Power7 and matches
the raw event list with libpfm4 library.

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 arch/powerpc/perf/power7-events-list.h | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/powerpc/perf/power7-events-list.h b/arch/powerpc/perf/power7-events-list.h
index 687790a..64f13d9 100644
--- a/arch/powerpc/perf/power7-events-list.h
+++ b/arch/powerpc/perf/power7-events-list.h
@@ -546,3 +546,13 @@ EVENT(PM_MRK_DATA_FROM_RL2L3_SHR,             0x1d04c)
 EVENT(PM_DTLB_MISS_16M,                       0x4c05e)
 EVENT(PM_LSU1_LMQ_LHR_MERGE,                  0x0d09a)
 EVENT(PM_IFU_FIN,                             0x40066)
+EVENT(PM_1THRD_CON_RUN_INSTR,                 0x30062)
+EVENT(PM_CMPLU_STALL_COUNT,                   0x4000B)
+EVENT(PM_MEM0_PB_RD_CL,                       0x30083)
+EVENT(PM_THRD_1_RUN_CYC,                      0x10060)
+EVENT(PM_THRD_2_CONC_RUN_INSTR,               0x40062)
+EVENT(PM_THRD_2_RUN_CYC,                      0x20060)
+EVENT(PM_THRD_3_CONC_RUN_INST,                0x10062)
+EVENT(PM_THRD_3_RUN_CYC,                      0x30060)
+EVENT(PM_THRD_4_CONC_RUN_INST,                0x20062)
+EVENT(PM_THRD_4_RUN_CYC,                      0x40060)
-- 
1.7.11.7

^ permalink raw reply related

* [V3 08/10] powerpc, perf: Enable SW filtering in branch stack sampling framework
From: Anshuman Khandual @ 2013-10-16  6:56 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel; +Cc: mikey, sukadev, michaele, eranian
In-Reply-To: <1381906617-11392-1-git-send-email-khandual@linux.vnet.ibm.com>

This patch enables SW based post processing of BHRB captured branches
to be able to meet more user defined branch filtration criteria in perf
branch stack sampling framework. These changes increase the number of
branch filters and their valid combinations on any powerpc64 server
platform with BHRB support. Find the summary of code changes here.

(1) struct cpu_hw_events

	Introduced two new variables track various filter values and mask

	(a) bhrb_sw_filter	Tracks SW implemented branch filter flags
	(b) filter_mask		Tracks both (SW and HW) branch filter flags

(2) Event creation

	Kernel will figure out supported BHRB branch filters through a PMU call
	back 'bhrb_filter_map'. This function will find out how many of the
	requested branch filters can be supported in the PMU HW. It will not
	try to invalidate any branch filter combinations. Event creation will not
	error out because of lack of HW based branch filters. Meanwhile it will
	track the overall supported branch filters in the "filter_mask" variable.

	Once the PMU call back returns kernel will process the user branch filter
	request against available SW filters while looking at the "filter_mask".
	During this phase all the branch filters which are still pending from the
	user requested list will have to be supported in SW failing which the
	event creation will error out.

(3) SW branch filter

	During the BHRB data capture inside the PMU interrupt context, each
	of the captured 'perf_branch_entry.from' will be checked for compliance
	with applicable SW branch filters. If the entry does not conform to the
	filter requirements, it will be discarded from the final perf branch
	stack buffer.

(4) Supported SW based branch filters

	(a) PERF_SAMPLE_BRANCH_ANY_RETURN
	(b) PERF_SAMPLE_BRANCH_IND_CALL
	(c) PERF_SAMPLE_BRANCH_ANY_CALL
	(d) PERF_SAMPLE_BRANCH_COND

	Please refer patch to understand the classification of instructions into
	these branch filter categories.

(5) Multiple branch filter semantics

	Book3 sever implementation follows the same OR semantics (as implemented in
	x86) while dealing with multiple branch filters at any point of time. SW
	branch filter analysis is carried on the data set captured in the PMU HW.
	So the resulting set of data (after applying the SW filters) will inherently
	be an AND with the HW captured set. Hence any combination of HW and SW branch
	filters will be invalid. HW based branch filters are more efficient and faster
	compared to SW implemented branch filters. So at first the PMU should decide
	whether it can support all the requested branch filters itself or not. In case
	it can support all the branch filters in an OR manner, we dont apply any SW
	branch filter on top of the HW captured set (which is the final set). This
	preserves the OR semantic of multiple branch filters as required. But in case
	where the PMU cannot support all the requested branch filters in an OR manner,
	it should not apply any it's filters and leave it upto the SW to handle them
	all. Its the PMU code's responsibility to uphold this protocol to be able to
	conform to the overall OR semantic of perf branch stack sampling framework.

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/perf_event_server.h |   6 +-
 arch/powerpc/perf/core-book3s.c              | 266 ++++++++++++++++++++++++++-
 arch/powerpc/perf/power8-pmu.c               |   2 +-
 3 files changed, 262 insertions(+), 12 deletions(-)

diff --git a/arch/powerpc/include/asm/perf_event_server.h b/arch/powerpc/include/asm/perf_event_server.h
index 8b24926..7314085 100644
--- a/arch/powerpc/include/asm/perf_event_server.h
+++ b/arch/powerpc/include/asm/perf_event_server.h
@@ -18,6 +18,10 @@
 #define MAX_EVENT_ALTERNATIVES	8
 #define MAX_LIMITED_HWCOUNTERS	2
 
+#define for_each_branch_sample_type(x) \
+        for ((x) = PERF_SAMPLE_BRANCH_USER; \
+             (x) < PERF_SAMPLE_BRANCH_MAX; (x) <<= 1)
+
 /*
  * This struct provides the constants and functions needed to
  * describe the PMU on a particular POWER-family CPU.
@@ -34,7 +38,7 @@ struct power_pmu {
 				unsigned long *valp);
 	int		(*get_alternatives)(u64 event_id, unsigned int flags,
 				u64 alt[]);
-	u64             (*bhrb_filter_map)(u64 branch_sample_type);
+	u64             (*bhrb_filter_map)(u64 branch_sample_type, u64 *filter_mask);
 	void            (*config_bhrb)(u64 pmu_bhrb_filter);
 	void		(*disable_pmc)(unsigned int pmc, unsigned long mmcr[]);
 	int		(*limited_pmc_event)(u64 event_id);
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index bc4dac7..f983334 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -48,6 +48,8 @@ struct cpu_hw_events {
 
 	/* BHRB bits */
 	u64				bhrb_hw_filter;	/* BHRB HW branch filter */
+	u64				bhrb_sw_filter;	/* BHRB SW branch filter */
+	u64				filter_mask;	/* Branch filter mask */
 	int				bhrb_users;
 	void				*bhrb_context;
 	struct	perf_branch_stack	bhrb_stack;
@@ -400,6 +402,228 @@ static __u64 power_pmu_bhrb_to(u64 addr)
 	return target - (unsigned long)&instr + addr;
 }
 
+/*
+ * Instruction opcode analysis
+ *
+ * Analyse instruction opcodes and classify them
+ * into various branch filter options available.
+ * This follows the standard semantics of OR which
+ * means that instructions which conforms to `any`
+ * of the requested branch filters get picked up.
+ */
+static bool validate_instruction(unsigned int *addr, u64 bhrb_sw_filter)
+{
+	bool result = false;
+
+	if (bhrb_sw_filter & PERF_SAMPLE_BRANCH_ANY_RETURN) {
+
+		/* XL-form instruction */
+		if (instr_is_branch_xlform(*addr)) {
+
+			/* LR should not be set */
+			if (!is_branch_link_set(*addr)) {
+				/*
+			 	 * Conditional and unconditional
+			 	 * branch to LR register.
+			 	 */
+				if (is_xlform_lr(*addr))
+					result = true;
+			}
+		}
+	}
+
+	if (bhrb_sw_filter & PERF_SAMPLE_BRANCH_IND_CALL) {
+		/* XL-form instruction */
+		if (instr_is_branch_xlform(*addr)) {
+
+			/* LR should be set */
+			if (is_branch_link_set(*addr)) {
+				/*
+			 	 * Conditional and unconditional
+			 	 * branch to CTR.
+			 	 */
+				if (is_xlform_ctr(*addr))
+					result = true;
+
+				/*
+			 	 * Conditional and unconditional
+			 	 * branch to LR.
+			 	 */
+				if (is_xlform_lr(*addr))
+					result = true;
+
+				/*
+			 	 * Conditional and unconditional
+			 	 * branch to TAR.
+			 	 */
+				if (is_xlform_tar(*addr))
+					result = true;
+			}
+		}
+	}
+
+	/* Any-form branch */
+	if (bhrb_sw_filter & PERF_SAMPLE_BRANCH_ANY_CALL) {
+		/* LR should be set */
+		if (is_branch_link_set(*addr))
+			result = true;
+	}
+
+	if (bhrb_sw_filter & PERF_SAMPLE_BRANCH_COND) {
+
+		/* I-form instruction - excluded */
+		if (instr_is_branch_iform(*addr))
+			goto out;
+
+		/* B-form or XL-form instruction */
+		if (instr_is_branch_bform(*addr) || instr_is_branch_xlform(*addr))  {
+
+			/* Not branch always  */
+			if (!is_bo_always(*addr)) {
+
+				/* Conditional branch to CTR register */
+				if (is_bo_ctr(*addr))
+					goto out;
+
+				/* CR[BI] conditional branch with static hint */
+				if (is_bo_crbi_off(*addr) || is_bo_crbi_on(*addr)) {
+					if (is_bo_crbi_hint(*addr))
+						goto out;
+				}
+
+				result = true;
+			}
+		}
+	}
+out:
+	return result;
+}
+
+static bool check_instruction(u64 addr, u64 bhrb_sw_filter)
+{
+	unsigned int instr;
+	bool ret;
+
+	if (bhrb_sw_filter == 0)
+		return true;
+
+	if (is_kernel_addr(addr)) {
+		ret = validate_instruction((unsigned int *) addr, bhrb_sw_filter);
+	} else {
+		/*
+		 * Userspace address needs to be
+		 * copied first before analysis.
+		 */
+		pagefault_disable();
+		ret =  __get_user_inatomic(instr, (unsigned int __user *)addr);
+
+		/*
+		 * If the instruction could not be accessible
+		 * from user space, we still 'okay' the entry.
+		 */
+		if (ret) {
+			pagefault_enable();
+			return true;
+		}
+		pagefault_enable();
+		ret = validate_instruction(&instr, bhrb_sw_filter);
+	}
+	return ret;
+}
+
+/*
+ * Validate whether all requested branch filters
+ * are getting processed either in the PMU or in SW.
+ */
+static int match_filters(u64 branch_sample_type, u64 filter_mask)
+{
+	u64 x;
+
+	if (filter_mask == PERF_SAMPLE_BRANCH_ANY)
+		return true;
+
+	for_each_branch_sample_type(x) {
+		if (!(branch_sample_type & x))
+			continue;
+		/*
+		 * Privilege filter requests have been already
+		 * taken care during the base PMU configuration.
+		 */
+		if (x == PERF_SAMPLE_BRANCH_USER)
+			continue;
+		if (x == PERF_SAMPLE_BRANCH_KERNEL)
+			continue;
+		if (x == PERF_SAMPLE_BRANCH_HV)
+			continue;
+
+		/*
+		 * Requested filter not available either
+		 * in PMU or in SW.
+		 */
+		if (!(filter_mask & x))
+			return false;
+	}
+	return true;
+}
+
+/*
+ * Required SW based branch filters
+ *
+ * This is called after figuring out what all branch filters the
+ * PMU HW supports for the requested branch filter set. Here we
+ * will go through all the SW implemented branch filters one by
+ * one and pick them up if its not already supported in the PMU.
+ */
+static u64 branch_filter_map(u64 branch_sample_type, u64 pmu_bhrb_filter,
+			     					u64 *filter_mask)
+{
+	u64 branch_sw_filter = 0;
+
+	/* No branch filter requested */
+	if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY) {
+		WARN_ON(pmu_bhrb_filter != 0);
+		WARN_ON(*filter_mask != PERF_SAMPLE_BRANCH_ANY);
+		return branch_sw_filter;
+	}
+
+	/*
+	 * PMU supported branch filters must also be implemented in SW
+	 * in the event when the PMU is unable to process them for some
+	 * reason. This all those branch filters can be satisfied with
+	 * SW implemented filters. But right now, there is now way to
+	 * initimate the user about this decision.
+	 */
+	if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY_CALL) {
+		if (!(pmu_bhrb_filter & PERF_SAMPLE_BRANCH_ANY_CALL)) {
+			branch_sw_filter |= PERF_SAMPLE_BRANCH_ANY_CALL;
+			*filter_mask |= PERF_SAMPLE_BRANCH_ANY_CALL;
+		}
+	}
+
+	if (branch_sample_type & PERF_SAMPLE_BRANCH_COND) {
+		if (!(pmu_bhrb_filter & PERF_SAMPLE_BRANCH_COND)) {
+			branch_sw_filter |= PERF_SAMPLE_BRANCH_COND;
+			*filter_mask |= PERF_SAMPLE_BRANCH_COND;
+		}
+	}
+
+	if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY_RETURN) {
+		if (!(pmu_bhrb_filter & PERF_SAMPLE_BRANCH_ANY_RETURN)) {
+			branch_sw_filter |= PERF_SAMPLE_BRANCH_ANY_RETURN;
+			*filter_mask |= PERF_SAMPLE_BRANCH_ANY_RETURN;
+		}
+	}
+
+	if (branch_sample_type & PERF_SAMPLE_BRANCH_IND_CALL) {
+		if (!(pmu_bhrb_filter & PERF_SAMPLE_BRANCH_IND_CALL)) {
+			branch_sw_filter |= PERF_SAMPLE_BRANCH_IND_CALL;
+			*filter_mask |= PERF_SAMPLE_BRANCH_IND_CALL;
+		}
+	}
+
+	return branch_sw_filter;
+}
+
 /* Processing BHRB entries */
 void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw)
 {
@@ -459,17 +683,29 @@ void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw)
 					addr = 0;
 				}
 				cpuhw->bhrb_entries[u_index].from = addr;
+
+				if (!check_instruction(cpuhw->
+						bhrb_entries[u_index].from,
+							cpuhw->bhrb_sw_filter))
+					u_index--;
 			} else {
 				/* Branches to immediate field 
 				   (ie I or B form) */
 				cpuhw->bhrb_entries[u_index].from = addr;
-				cpuhw->bhrb_entries[u_index].to =
-					power_pmu_bhrb_to(addr);
-				cpuhw->bhrb_entries[u_index].mispred = pred;
-				cpuhw->bhrb_entries[u_index].predicted = ~pred;
+				if (check_instruction(cpuhw->
+						bhrb_entries[u_index].from,
+						cpuhw->bhrb_sw_filter)) {
+					cpuhw->bhrb_entries[u_index].
+						to = power_pmu_bhrb_to(addr);
+					cpuhw->bhrb_entries[u_index].
+						mispred = pred;
+					cpuhw->bhrb_entries[u_index].
+						predicted = ~pred;
+				} else {
+					u_index--;
+				}
 			}
 			u_index++;
-
 		}
 	}
 	cpuhw->bhrb_stack.nr = u_index;
@@ -1255,7 +1491,11 @@ nocheck:
 	if (has_branch_stack(event)) {
 		power_pmu_bhrb_enable(event);
 		cpuhw->bhrb_hw_filter = ppmu->bhrb_filter_map(
-					event->attr.branch_sample_type);
+					event->attr.branch_sample_type,
+					&cpuhw->filter_mask);
+		cpuhw->bhrb_sw_filter = branch_filter_map
+					(event->attr.branch_sample_type,
+					cpuhw->bhrb_hw_filter, &cpuhw->filter_mask);
 	}
 
 	perf_pmu_enable(event->pmu);
@@ -1637,10 +1877,16 @@ static int power_pmu_event_init(struct perf_event *event)
 	err = power_check_constraints(cpuhw, events, cflags, n + 1);
 
 	if (has_branch_stack(event)) {
-		cpuhw->bhrb_hw_filter = ppmu->bhrb_filter_map(
-					event->attr.branch_sample_type);
-
-		if(cpuhw->bhrb_hw_filter == -1)
+		cpuhw->bhrb_hw_filter = ppmu->bhrb_filter_map
+				(event->attr.branch_sample_type,
+				&cpuhw->filter_mask);
+		cpuhw->bhrb_sw_filter = branch_filter_map
+				(event->attr.branch_sample_type,
+				cpuhw->bhrb_hw_filter,
+				&cpuhw->filter_mask);
+
+		if(!match_filters(event->attr.branch_sample_type,
+						cpuhw->filter_mask))
 			return -EOPNOTSUPP;
 	}
 
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index 6e28587..94460bc 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -558,7 +558,7 @@ static int power8_generic_events[] = {
 	[PERF_COUNT_HW_BRANCH_MISSES] =			PM_BR_MPRED_CMPL,
 };
 
-static u64 power8_bhrb_filter_map(u64 branch_sample_type)
+static u64 power8_bhrb_filter_map(u64 branch_sample_type, u64 *filter_mask)
 {
 	u64 pmu_bhrb_filter = 0;
 
-- 
1.7.11.7

^ permalink raw reply related

* [V3 02/10] powerpc, perf: Enable conditional branch filter for POWER8
From: Anshuman Khandual @ 2013-10-16  6:56 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel; +Cc: mikey, sukadev, michaele, eranian
In-Reply-To: <1381906617-11392-1-git-send-email-khandual@linux.vnet.ibm.com>

Enables conditional branch filter support for POWER8
utilizing MMCRA register based filter and also invalidates
a BHRB branch filter combination involving conditional
branches.

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 arch/powerpc/perf/power8-pmu.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index 2ee4a70..6e28587 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -580,11 +580,21 @@ static u64 power8_bhrb_filter_map(u64 branch_sample_type)
 	if (branch_sample_type & PERF_SAMPLE_BRANCH_IND_CALL)
 		return -1;
 
+	/* Invalid branch filter combination - HW does not support */
+	if ((branch_sample_type & PERF_SAMPLE_BRANCH_ANY_CALL) &&
+			(branch_sample_type & PERF_SAMPLE_BRANCH_COND))
+		return -1;
+
 	if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY_CALL) {
 		pmu_bhrb_filter |= POWER8_MMCRA_IFM1;
 		return pmu_bhrb_filter;
 	}
 
+	if (branch_sample_type & PERF_SAMPLE_BRANCH_COND) {
+		pmu_bhrb_filter |= POWER8_MMCRA_IFM3;
+		return pmu_bhrb_filter;
+	}
+
 	/* Every thing else is unsupported */
 	return -1;
 }
-- 
1.7.11.7

^ permalink raw reply related

* [V3 07/10] powerpc, lib: Add new branch instruction analysis support functions
From: Anshuman Khandual @ 2013-10-16  6:56 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel; +Cc: mikey, sukadev, michaele, eranian
In-Reply-To: <1381906617-11392-1-git-send-email-khandual@linux.vnet.ibm.com>

Generic powerpc branch instruction analysis support added in the code
patching library which will help the subsequent patch on SW based
filtering of branch records in perf. This patch also converts and
exports some of the existing local static functions through the header
file to be used else where.

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/code-patching.h | 30 ++++++++++++++++++
 arch/powerpc/lib/code-patching.c         | 54 ++++++++++++++++++++++++++++++--
 2 files changed, 82 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/include/asm/code-patching.h b/arch/powerpc/include/asm/code-patching.h
index a6f8c7a..8bab417 100644
--- a/arch/powerpc/include/asm/code-patching.h
+++ b/arch/powerpc/include/asm/code-patching.h
@@ -22,6 +22,36 @@
 #define BRANCH_SET_LINK	0x1
 #define BRANCH_ABSOLUTE	0x2
 
+#define XL_FORM_LR  0x4C000020
+#define XL_FORM_CTR 0x4C000420
+#define XL_FORM_TAR 0x4C000460
+
+#define BO_ALWAYS    0x02800000
+#define BO_CTR       0x02000000
+#define BO_CRBI_OFF  0x00800000
+#define BO_CRBI_ON   0x01800000
+#define BO_CRBI_HINT 0x00400000
+
+/* Forms of branch instruction */
+int instr_is_branch_iform(unsigned int instr);
+int instr_is_branch_bform(unsigned int instr);
+int instr_is_branch_xlform(unsigned int instr);
+
+/* Classification of XL-form instruction */
+int is_xlform_lr(unsigned int instr);
+int is_xlform_ctr(unsigned int instr);
+int is_xlform_tar(unsigned int instr);
+
+/* Branch instruction is a call */
+int is_branch_link_set(unsigned int instr);
+
+/* BO field analysis (B-form or XL-form) */
+int is_bo_always(unsigned int instr);
+int is_bo_ctr(unsigned int instr);
+int is_bo_crbi_off(unsigned int instr);
+int is_bo_crbi_on(unsigned int instr);
+int is_bo_crbi_hint(unsigned int instr);
+
 unsigned int create_branch(const unsigned int *addr,
 			   unsigned long target, int flags);
 unsigned int create_cond_branch(const unsigned int *addr,
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index 17e5b23..cb62bd8 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -77,16 +77,66 @@ static unsigned int branch_opcode(unsigned int instr)
 	return (instr >> 26) & 0x3F;
 }
 
-static int instr_is_branch_iform(unsigned int instr)
+int instr_is_branch_iform(unsigned int instr)
 {
 	return branch_opcode(instr) == 18;
 }
 
-static int instr_is_branch_bform(unsigned int instr)
+int instr_is_branch_bform(unsigned int instr)
 {
 	return branch_opcode(instr) == 16;
 }
 
+int instr_is_branch_xlform(unsigned int instr)
+{
+	return branch_opcode(instr) == 19;
+}
+
+int is_xlform_lr(unsigned int instr)
+{
+	return (instr & XL_FORM_LR) == XL_FORM_LR;
+}
+
+int is_xlform_ctr(unsigned int instr)
+{
+	return (instr & XL_FORM_CTR) == XL_FORM_CTR;
+}
+
+int is_xlform_tar(unsigned int instr)
+{
+	return (instr & XL_FORM_TAR) == XL_FORM_TAR;
+}
+
+int is_branch_link_set(unsigned int instr)
+{
+	return (instr & BRANCH_SET_LINK) == BRANCH_SET_LINK;
+}
+
+int is_bo_always(unsigned int instr)
+{
+	return (instr & BO_ALWAYS) == BO_ALWAYS;
+}
+
+int is_bo_ctr(unsigned int instr)
+{
+	return (instr & BO_CTR) == BO_CTR;
+}
+
+int is_bo_crbi_off(unsigned int instr)
+{
+	return (instr & BO_CRBI_OFF) == BO_CRBI_OFF;
+}
+
+int is_bo_crbi_on(unsigned int instr)
+{
+	return (instr & BO_CRBI_ON) == BO_CRBI_ON;
+}
+
+int is_bo_crbi_hint(unsigned int instr)
+{
+	return (instr & BO_CRBI_HINT) == BO_CRBI_HINT;
+}
+
 int instr_is_relative_branch(unsigned int instr)
 {
 	if (instr & BRANCH_ABSOLUTE)
-- 
1.7.11.7

^ permalink raw reply related

* [V3 09/10] power8, perf: Change BHRB branch filter configuration
From: Anshuman Khandual @ 2013-10-16  6:56 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel; +Cc: mikey, sukadev, michaele, eranian
In-Reply-To: <1381906617-11392-1-git-send-email-khandual@linux.vnet.ibm.com>

Powerpc kernel now supports SW based branch filters for book3s systems with some
specifc requirements while dealing with HW supported branch filters in order to
achieve overall OR semantics prevailing in perf branch stack sampling framework.
This patch adapts the BHRB branch filter configuration to meet those protocols.
POWER8 PMU does support 3 branch filters (out of which two are getting used in
perf branch stack) which are mutually exclussive and cannot be ORed with each
other. This implies that PMU can only handle one HW based branch filter request
at any point of time. For all other combinations PMU will pass it on to the SW.

Also the combination of PERF_SAMPLE_BRANCH_ANY_CALL and PERF_SAMPLE_BRANCH_COND
can now be handled in SW, hence we dont error them out anymore.

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 arch/powerpc/perf/power8-pmu.c | 73 +++++++++++++++++++++++++++++++-----------
 1 file changed, 54 insertions(+), 19 deletions(-)

diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index 94460bc..7b82725 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -560,7 +560,56 @@ static int power8_generic_events[] = {
 
 static u64 power8_bhrb_filter_map(u64 branch_sample_type, u64 *filter_mask)
 {
-	u64 pmu_bhrb_filter = 0;
+	u64 x, tmp, pmu_bhrb_filter = 0;
+	*filter_mask = 0;
+
+	/* No branch filter requested */
+	if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY) {
+		*filter_mask = PERF_SAMPLE_BRANCH_ANY;
+		return pmu_bhrb_filter;
+	}
+
+	/*
+	 * P8 does not support oring of PMU HW branch filters. Hence
+	 * if multiple branch filters are requested which includes filters
+	 * supported in PMU, still go ahead and clear the PMU based HW branch
+	 * filter component as in this case all the filters will be processed
+ 	 * in SW.
+	 */
+	tmp = branch_sample_type;
+
+	/* Remove privilege filters before comparison */
+	tmp &= ~PERF_SAMPLE_BRANCH_USER;
+	tmp &= ~PERF_SAMPLE_BRANCH_KERNEL;
+	tmp &= ~PERF_SAMPLE_BRANCH_HV;
+
+	for_each_branch_sample_type(x) {
+		/* Ignore privilege requests */
+		if ((x == PERF_SAMPLE_BRANCH_USER) || (x == PERF_SAMPLE_BRANCH_KERNEL) || (x == PERF_SAMPLE_BRANCH_HV))
+			continue;
+
+		if (!(tmp & x))
+			continue;
+
+               /* Supported HW PMU filters */
+		if (tmp & PERF_SAMPLE_BRANCH_ANY_CALL) {
+			tmp &= ~PERF_SAMPLE_BRANCH_ANY_CALL;
+			if (tmp) {
+				pmu_bhrb_filter = 0;
+				*filter_mask = 0;
+				return pmu_bhrb_filter;
+			}
+		}
+
+		if (tmp & PERF_SAMPLE_BRANCH_COND) {
+			tmp &= ~PERF_SAMPLE_BRANCH_COND;
+			if (tmp) {
+				pmu_bhrb_filter = 0;
+				*filter_mask = 0;
+				return pmu_bhrb_filter;
+			}
+		}
+	}
 
 	/* BHRB and regular PMU events share the same privilege state
 	 * filter configuration. BHRB is always recorded along with a
@@ -569,34 +618,20 @@ static u64 power8_bhrb_filter_map(u64 branch_sample_type, u64 *filter_mask)
 	 * PMU event, we ignore any separate BHRB specific request.
 	 */
 
-	/* No branch filter requested */
-	if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY)
-		return pmu_bhrb_filter;
-
-	/* Invalid branch filter options - HW does not support */
-	if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY_RETURN)
-		return -1;
-
-	if (branch_sample_type & PERF_SAMPLE_BRANCH_IND_CALL)
-		return -1;
-
-	/* Invalid branch filter combination - HW does not support */
-	if ((branch_sample_type & PERF_SAMPLE_BRANCH_ANY_CALL) &&
-			(branch_sample_type & PERF_SAMPLE_BRANCH_COND))
-		return -1;
-
+	/* Supported individual branch filters */
 	if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY_CALL) {
 		pmu_bhrb_filter |= POWER8_MMCRA_IFM1;
+		*filter_mask    |= PERF_SAMPLE_BRANCH_ANY_CALL;
 		return pmu_bhrb_filter;
 	}
 
 	if (branch_sample_type & PERF_SAMPLE_BRANCH_COND) {
 		pmu_bhrb_filter |= POWER8_MMCRA_IFM3;
+		*filter_mask    |= PERF_SAMPLE_BRANCH_COND;
 		return pmu_bhrb_filter;
 	}
 
-	/* Every thing else is unsupported */
-	return -1;
+	return pmu_bhrb_filter;
 }
 
 static void power8_config_bhrb(u64 pmu_bhrb_filter)
-- 
1.7.11.7

^ permalink raw reply related

* [V3 10/10] powerpc, perf: Cleanup SW branch filter list look up
From: Anshuman Khandual @ 2013-10-16  6:56 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel; +Cc: mikey, sukadev, michaele, eranian
In-Reply-To: <1381906617-11392-1-git-send-email-khandual@linux.vnet.ibm.com>

This patch adds enumeration for all available SW branch filters
in powerpc book3s code and also streamlines the look for the
SW branch filter entries while trying to figure out which all
branch filters can be supported in SW.

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 arch/powerpc/perf/core-book3s.c | 38 +++++++++++++-------------------------
 1 file changed, 13 insertions(+), 25 deletions(-)

diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index f983334..ec2dd61 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -566,6 +566,12 @@ static int match_filters(u64 branch_sample_type, u64 filter_mask)
 	return true;
 }
 
+/* SW implemented branch filters */
+static unsigned int power_sw_filter[] =	      { PERF_SAMPLE_BRANCH_ANY_CALL,
+						PERF_SAMPLE_BRANCH_COND,
+						PERF_SAMPLE_BRANCH_ANY_RETURN,
+						PERF_SAMPLE_BRANCH_IND_CALL };
+
 /*
  * Required SW based branch filters
  *
@@ -578,6 +584,7 @@ static u64 branch_filter_map(u64 branch_sample_type, u64 pmu_bhrb_filter,
 			     					u64 *filter_mask)
 {
 	u64 branch_sw_filter = 0;
+	unsigned int i;
 
 	/* No branch filter requested */
 	if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY) {
@@ -593,34 +600,15 @@ static u64 branch_filter_map(u64 branch_sample_type, u64 pmu_bhrb_filter,
 	 * SW implemented filters. But right now, there is now way to
 	 * initimate the user about this decision.
 	 */
-	if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY_CALL) {
-		if (!(pmu_bhrb_filter & PERF_SAMPLE_BRANCH_ANY_CALL)) {
-			branch_sw_filter |= PERF_SAMPLE_BRANCH_ANY_CALL;
-			*filter_mask |= PERF_SAMPLE_BRANCH_ANY_CALL;
-		}
-	}
-
-	if (branch_sample_type & PERF_SAMPLE_BRANCH_COND) {
-		if (!(pmu_bhrb_filter & PERF_SAMPLE_BRANCH_COND)) {
-			branch_sw_filter |= PERF_SAMPLE_BRANCH_COND;
-			*filter_mask |= PERF_SAMPLE_BRANCH_COND;
-		}
-	}
 
-	if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY_RETURN) {
-		if (!(pmu_bhrb_filter & PERF_SAMPLE_BRANCH_ANY_RETURN)) {
-			branch_sw_filter |= PERF_SAMPLE_BRANCH_ANY_RETURN;
-			*filter_mask |= PERF_SAMPLE_BRANCH_ANY_RETURN;
-		}
-	}
-
-	if (branch_sample_type & PERF_SAMPLE_BRANCH_IND_CALL) {
-		if (!(pmu_bhrb_filter & PERF_SAMPLE_BRANCH_IND_CALL)) {
-			branch_sw_filter |= PERF_SAMPLE_BRANCH_IND_CALL;
-			*filter_mask |= PERF_SAMPLE_BRANCH_IND_CALL;
+	for (i = 0; i < ARRAY_SIZE(power_sw_filter); i++) {
+		if (branch_sample_type & power_sw_filter[i]) {
+			if (!(pmu_bhrb_filter & power_sw_filter[i])) {
+				branch_sw_filter |= power_sw_filter[i];
+				*filter_mask |= power_sw_filter[i];
+			}
 		}
 	}
-
 	return branch_sw_filter;
 }
 
-- 
1.7.11.7

^ permalink raw reply related

* [V3 04/10] x86, perf: Add conditional branch filtering support
From: Anshuman Khandual @ 2013-10-16  6:56 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel; +Cc: mikey, sukadev, michaele, eranian
In-Reply-To: <1381906617-11392-1-git-send-email-khandual@linux.vnet.ibm.com>

This patch adds conditional branch filtering support,
enabling it for PERF_SAMPLE_BRANCH_COND in perf branch
stack sampling framework by utilizing an available
software filter X86_BR_JCC.

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
Reviewed-by: Stephane Eranian <eranian@google.com>
---
 arch/x86/kernel/cpu/perf_event_intel_lbr.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
index d5be06a..9723773 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
@@ -371,6 +371,9 @@ static void intel_pmu_setup_sw_lbr_filter(struct perf_event *event)
 	if (br_type & PERF_SAMPLE_BRANCH_NO_TX)
 		mask |= X86_BR_NO_TX;
 
+	if (br_type & PERF_SAMPLE_BRANCH_COND)
+		mask |= X86_BR_JCC;
+
 	/*
 	 * stash actual user request into reg, it may
 	 * be used by fixup code for some CPU
@@ -665,6 +668,7 @@ static const int nhm_lbr_sel_map[PERF_SAMPLE_BRANCH_MAX] = {
 	 * NHM/WSM erratum: must include IND_JMP to capture IND_CALL
 	 */
 	[PERF_SAMPLE_BRANCH_IND_CALL] = LBR_IND_CALL | LBR_IND_JMP,
+	[PERF_SAMPLE_BRANCH_COND]     = LBR_JCC,
 };
 
 static const int snb_lbr_sel_map[PERF_SAMPLE_BRANCH_MAX] = {
@@ -676,6 +680,7 @@ static const int snb_lbr_sel_map[PERF_SAMPLE_BRANCH_MAX] = {
 	[PERF_SAMPLE_BRANCH_ANY_CALL]	= LBR_REL_CALL | LBR_IND_CALL
 					| LBR_FAR,
 	[PERF_SAMPLE_BRANCH_IND_CALL]	= LBR_IND_CALL,
+	[PERF_SAMPLE_BRANCH_COND]       = LBR_JCC,
 };
 
 /* core */
-- 
1.7.11.7

^ permalink raw reply related

* [V3 05/10] perf, documentation: Description for conditional branch filter
From: Anshuman Khandual @ 2013-10-16  6:56 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel; +Cc: mikey, sukadev, michaele, eranian
In-Reply-To: <1381906617-11392-1-git-send-email-khandual@linux.vnet.ibm.com>

Adding documentation support for conditional branch filter.

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
Reviewed-by: Stephane Eranian <eranian@google.com>
---
 tools/perf/Documentation/perf-record.txt | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index e297b74..59ca8d0 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -163,12 +163,13 @@ following filters are defined:
         - any_call: any function call or system call
         - any_ret: any function return or system call return
         - ind_call: any indirect branch
+        - cond: conditional branches
         - u:  only when the branch target is at the user level
         - k: only when the branch target is in the kernel
         - hv: only when the target is at the hypervisor level
 
 +
-The option requires at least one branch type among any, any_call, any_ret, ind_call.
+The option requires at least one branch type among any, any_call, any_ret, ind_call, cond.
 The privilege levels may be omitted, in which case, the privilege levels of the associated
 event are applied to the branch filter. Both kernel (k) and hypervisor (hv) privilege
 levels are subject to permissions.  When sampling on multiple events, branch stack sampling
-- 
1.7.11.7

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox