LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2 V2] powerpc: Move opcode definitions from kvm/emulate.c to asm/ppc-opcode.h
From: Jia Hongtao @ 2013-04-28  5:20 UTC (permalink / raw)
  To: linuxppc-dev, galak, B07421, segher; +Cc: hongtao.jia

Opcode and xopcode are useful definitions not just for KVM. Move these
definitions to asm/ppc-opcode.h for public use.

Signed-off-by: Jia Hongtao <hongtao.jia@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
---
V2:
* Add LHAUX definition.

 arch/powerpc/include/asm/ppc-opcode.h | 46 +++++++++++++++++++++++++++++++++++
 arch/powerpc/kvm/emulate.c            | 44 +--------------------------------
 2 files changed, 47 insertions(+), 43 deletions(-)

diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
index 8752bc8..79057f7 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -81,6 +81,52 @@
 #define	__REGA0_R30	30
 #define	__REGA0_R31	31
 
+/* opcode and xopcode for instructions */
+#define OP_TRAP 3
+#define OP_TRAP_64 2
+
+#define OP_31_XOP_TRAP      4
+#define OP_31_XOP_LWZX      23
+#define OP_31_XOP_LWZUX     55
+#define OP_31_XOP_TRAP_64   68
+#define OP_31_XOP_DCBF      86
+#define OP_31_XOP_LBZX      87
+#define OP_31_XOP_STWX      151
+#define OP_31_XOP_STBX      215
+#define OP_31_XOP_LBZUX     119
+#define OP_31_XOP_STBUX     247
+#define OP_31_XOP_LHZX      279
+#define OP_31_XOP_LHZUX     311
+#define OP_31_XOP_MFSPR     339
+#define OP_31_XOP_LHAX      343
+#define OP_31_XOP_LHAUX     375
+#define OP_31_XOP_STHX      407
+#define OP_31_XOP_STHUX     439
+#define OP_31_XOP_MTSPR     467
+#define OP_31_XOP_DCBI      470
+#define OP_31_XOP_LWBRX     534
+#define OP_31_XOP_TLBSYNC   566
+#define OP_31_XOP_STWBRX    662
+#define OP_31_XOP_LHBRX     790
+#define OP_31_XOP_STHBRX    918
+
+#define OP_LWZ  32
+#define OP_LD   58
+#define OP_LWZU 33
+#define OP_LBZ  34
+#define OP_LBZU 35
+#define OP_STW  36
+#define OP_STWU 37
+#define OP_STD  62
+#define OP_STB  38
+#define OP_STBU 39
+#define OP_LHZ  40
+#define OP_LHZU 41
+#define OP_LHA  42
+#define OP_LHAU 43
+#define OP_STH  44
+#define OP_STHU 45
+
 /* sorted alphabetically */
 #define PPC_INST_DCBA			0x7c0005ec
 #define PPC_INST_DCBA_MASK		0xfc0007fe
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
index 7a73b6f..426d3f5 100644
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -30,52 +30,10 @@
 #include <asm/byteorder.h>
 #include <asm/kvm_ppc.h>
 #include <asm/disassemble.h>
+#include <asm/ppc-opcode.h>
 #include "timing.h"
 #include "trace.h"
 
-#define OP_TRAP 3
-#define OP_TRAP_64 2
-
-#define OP_31_XOP_TRAP      4
-#define OP_31_XOP_LWZX      23
-#define OP_31_XOP_TRAP_64   68
-#define OP_31_XOP_DCBF      86
-#define OP_31_XOP_LBZX      87
-#define OP_31_XOP_STWX      151
-#define OP_31_XOP_STBX      215
-#define OP_31_XOP_LBZUX     119
-#define OP_31_XOP_STBUX     247
-#define OP_31_XOP_LHZX      279
-#define OP_31_XOP_LHZUX     311
-#define OP_31_XOP_MFSPR     339
-#define OP_31_XOP_LHAX      343
-#define OP_31_XOP_STHX      407
-#define OP_31_XOP_STHUX     439
-#define OP_31_XOP_MTSPR     467
-#define OP_31_XOP_DCBI      470
-#define OP_31_XOP_LWBRX     534
-#define OP_31_XOP_TLBSYNC   566
-#define OP_31_XOP_STWBRX    662
-#define OP_31_XOP_LHBRX     790
-#define OP_31_XOP_STHBRX    918
-
-#define OP_LWZ  32
-#define OP_LD   58
-#define OP_LWZU 33
-#define OP_LBZ  34
-#define OP_LBZU 35
-#define OP_STW  36
-#define OP_STWU 37
-#define OP_STD  62
-#define OP_STB  38
-#define OP_STBU 39
-#define OP_LHZ  40
-#define OP_LHZU 41
-#define OP_LHA  42
-#define OP_LHAU 43
-#define OP_STH  44
-#define OP_STHU 45
-
 void kvmppc_emulate_dec(struct kvm_vcpu *vcpu)
 {
 	unsigned long dec_nsec;
-- 
1.8.0

^ permalink raw reply related

* RE: [PATCH 2/2 V7] powerpc/85xx: Add machine check handler to fix PCIe erratum on mpc85xx
From: Jia Hongtao-B38951 @ 2013-04-28  2:20 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: Wood Scott-B07421, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <C8615FAE-3DFA-4086-88AE-2EA9EA700D15@kernel.crashing.org>



> -----Original Message-----
> From: Segher Boessenkool [mailto:segher@kernel.crashing.org]
> Sent: Saturday, April 27, 2013 9:32 PM
> To: Jia Hongtao-B38951
> Cc: Wood Scott-B07421; linuxppc-dev@lists.ozlabs.org;
> galak@kernel.crashing.org
> Subject: Re: [PATCH 2/2 V7] powerpc/85xx: Add machine check handler to
> fix PCIe erratum on mpc85xx
>=20
> > In former email you doubt whether we need A variant or not.
> > Any particular reason for that?
> > If not should I emulate all the A ARX AU AUX and AX variant?
>=20
> A/AU/AX/AUX are just normal loads, sign-extended instead of zero-extended
> (so assign -1 to the register loaded).
>=20
> The ARX thing is load-locked, you do not want that one.
>=20
>=20
> Segher

Thanks, very helpful.
-Hongtao

^ permalink raw reply

* Re: [PATCH 2/2 V7] powerpc/85xx: Add machine check handler to fix PCIe erratum on mpc85xx
From: Segher Boessenkool @ 2013-04-27 13:31 UTC (permalink / raw)
  To: Jia Hongtao-B38951; +Cc: Wood Scott-B07421, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <412C8208B4A0464FA894C5F0C278CD5D01C4C76D@039-SN1MPN1-002.039d.mgd.msft.net>

> In former email you doubt whether we need A variant or not.
> Any particular reason for that?
> If not should I emulate all the A ARX AU AUX and AX variant?

A/AU/AX/AUX are just normal loads, sign-extended instead of
zero-extended (so assign -1 to the register loaded).

The ARX thing is load-locked, you do not want that one.


Segher

^ permalink raw reply

* Re: [PATCH] powerpc: Fix "attempt to move .org backwards" error
From: Mike Qiu @ 2013-04-27  9:34 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev, Chen Gang
In-Reply-To: <20130426035140.GA5796@drongo>

于 2013/4/26 11:51, Paul Mackerras 写道:
> Building a 64-bit powerpc kernel with PR KVM enabled currently gives
> this error:
>
>    AS      arch/powerpc/kernel/head_64.o
> arch/powerpc/kernel/exceptions-64s.S: Assembler messages:
> arch/powerpc/kernel/exceptions-64s.S:258: Error: attempt to move .org backwards
> make[2]: *** [arch/powerpc/kernel/head_64.o] Error 1
>
> This happens because the MASKABLE_EXCEPTION_PSERIES macro turns into
> 33 instructions, but we only have space for 32 at the decrementer
> interrupt vector (from 0x900 to 0x980).
>
> In the code generated by the MASKABLE_EXCEPTION_PSERIES macro, we
> currently have two instances of the HMT_MEDIUM macro, which has the
> effect of setting the SMT thread priority to medium.  One is the
> first instruction, and is overwritten by a no-op on processors where
> we save the PPR (processor priority register), that is, POWER7 or
> later.  The other is after we have saved the PPR.
>
> In order to reduce the code at 0x900 by one instruction, we omit the
> first HMT_MEDIUM.  On processors without SMT this will have no effect
> since HMT_MEDIUM is a no-op there.  On POWER5 and RS64 machines this
> will mean that the first few instructions take a little longer in the
> case where a decrementer interrupt occurs when the hardware thread is
> running at low SMT priority.  On POWER6 and later machines, the
> hardware automatically boosts the thread priority when a decrementer
> interrupt is taken if the thread priority was below medium, so this
> change won't make any difference.
>
> The alternative would be to branch out of line after saving the CFAR.
> However, that would incur an extra overhead on all processors, whereas
> the approach adopted here only adds overhead on older threaded processors.
>
> Signed-off-by: Paul Mackerras <paulus@samba.org>
> ---
>   arch/powerpc/include/asm/exception-64s.h |    2 +-
>   arch/powerpc/kernel/exceptions-64s.S     |    7 ++++++-
>   2 files changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h
> index 05e6d2e..8e5fae8 100644
> --- a/arch/powerpc/include/asm/exception-64s.h
> +++ b/arch/powerpc/include/asm/exception-64s.h
> @@ -414,7 +414,6 @@ label##_relon_hv:						\
>   #define SOFTEN_NOTEST_HV(vec)		_SOFTEN_TEST(EXC_HV, vec)
>
>   #define __MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra)		\
> -	HMT_MEDIUM_PPR_DISCARD;						\
>   	SET_SCRATCH0(r13);    /* save r13 */				\
>   	EXCEPTION_PROLOG_0(PACA_EXGEN);					\
>   	__EXCEPTION_PROLOG_1(PACA_EXGEN, extra, vec);			\
> @@ -427,6 +426,7 @@ label##_relon_hv:						\
>   	. = loc;							\
>   	.globl label##_pSeries;						\
>   label##_pSeries:							\
> +	HMT_MEDIUM_PPR_DISCARD;						\
>   	_MASKABLE_EXCEPTION_PSERIES(vec, label,				\
>   				    EXC_STD, SOFTEN_TEST_PR)
>
> diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
> index 56bd923..574db3f 100644
> --- a/arch/powerpc/kernel/exceptions-64s.S
> +++ b/arch/powerpc/kernel/exceptions-64s.S
> @@ -235,6 +235,7 @@ instruction_access_slb_pSeries:
>   	.globl hardware_interrupt_hv;
>   hardware_interrupt_pSeries:
>   hardware_interrupt_hv:
> +	HMT_MEDIUM_PPR_DISCARD
>   	BEGIN_FTR_SECTION
>   		_MASKABLE_EXCEPTION_PSERIES(0x502, hardware_interrupt,
>   					    EXC_HV, SOFTEN_TEST_HV)
> @@ -254,7 +255,11 @@ hardware_interrupt_hv:
>   	STD_EXCEPTION_PSERIES(0x800, 0x800, fp_unavailable)
>   	KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x800)
>
> -	MASKABLE_EXCEPTION_PSERIES(0x900, 0x900, decrementer)
> +	. = 0x900
> +	.globl decrementer_pSeries
> +decrementer_pSeries:
> +	_MASKABLE_EXCEPTION_PSERIES(0x900, decrementer, EXC_STD, SOFTEN_TEST_PR)
> +
>   	STD_EXCEPTION_HV(0x980, 0x982, hdecrementer)
>
>   	MASKABLE_EXCEPTION_PSERIES(0xa00, 0xa00, doorbell_super)
test-by: Mike Qiu <qiudayu@linux.vnet.ibm.com>
It's workable for me. but I just use this patch to compile and boot up 
the machine. not do any performance test:)

^ permalink raw reply

* Re: [PATCH v2] PowerPC: kernel: compiling issue, make additional room in exception vector area
From: Chen Gang @ 2013-04-27  9:33 UTC (permalink / raw)
  To: Mike Qiu
  Cc: sfr, Michael Neuling, matt, linux-kernel, Paul Mackerras,
	Aneesh Kumar K.V, Chen Gang F T, linuxppc-dev
In-Reply-To: <517B9B2B.30007@linux.vnet.ibm.com>

On 2013年04月27日 17:32, Mike Qiu wrote:
>>>
>> I think the diff v2 is correct, but is not the best one for this issue.
>>
>> I prefer the Paul's patch for this issue which has better performance
>>
>> :-)
> yes, I use your patch and it can work, also Paul's patch can work too.

Good news.

Bye !

:-)

-- 
Chen Gang

Asianux Corporation

^ permalink raw reply

* Re: [PATCH v2] PowerPC: kernel: compiling issue, make additional room in exception vector area
From: Mike Qiu @ 2013-04-27  9:32 UTC (permalink / raw)
  To: Chen Gang F T
  Cc: sfr, Michael Neuling, matt, Chen Gang, linux-kernel,
	Paul Mackerras, Aneesh Kumar K.V, linuxppc-dev
In-Reply-To: <517B9A4D.1020502@gmail.com>

于 2013/4/27 17:28, Chen Gang F T 写道:
> On 2013年04月26日 11:54, Mike Qiu wrote:
>> 于 2013/4/26 11:42, Chen Gang 写道:
>>> On 2013年04月26日 11:25, Chen Gang wrote:
>>>> On 2013年04月26日 11:08, Mike Qiu wrote:
>>>>> 于 2013/4/26 10:06, Chen Gang 写道:
>>>>>> On 2013年04月26日 10:03, Mike Qiu wrote:
>>>>>>> �� 2013/4/26 9:36, Chen Gang �:
>>>>>>>>> On 2013��04��26�� 09:18, Chen Gang wrote:
>>>>>>>>>>> On 2013��04��26�� 09:06, Chen Gang wrote:
>>>>>>>>>>>>>>> CFAR is the Come From Register.  It saves the location of the
>>>>>>>>>>>>>>> last
>>>>>>>>>>>>>>>>> branch and is hence overwritten by any branch.
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>> Do we process it just like others done (e.g. 0x300, 0xe00,
>>>>>>>>>>>>> 0xe20 ...) ?
>>>>>>>>>>>>>       . = 0x900
>>>>>>>>>>>>>       .globl decrementer_pSeries
>>>>>>>>>>>>> decrementer_pSeries:
>>>>>>>>>>>>>         HMT_MEDIUM_PPR_DISCARD
>>>>>>>>>>>>>       SET_SCRATCH0(r13)
>>>>>>>>>>>>>       b decrementer_pSeries_0
>>>>>>>>>>>>>
>>>>>>>>>>>>>       ...
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>> Oh, it seems EXCEPTION_PROLOG_1 will save the regesters which
>>>>>>>>> related
>>>>>>>>> with CFAR, so I think need move EXCEPTION_PROLOG_1 to near 0x900.
>>>>>>> I will try your diff V2, to see if the machine can boot up
>>>>>> OK, thanks. (hope it can work)
>>>>> It seems that the machine can be bootup in powernv mode, but I'm not
>>>>> sure if my machine call that module.
>>>>>
>>>>> At lease my machine can boot up
>>> Please reference commit number: 1707dd161349e6c54170c88d94fed012e3d224e3
>>> (1707dd1 powerpc: Save CFAR before branching in interrupt entry paths)
>>>
>>> What our diff v2 has done is just the fix for our patch v2 (just like
>>> the commit 1707dd1 has done).
>>>
>>> Please check, thanks.
>>>
>>> :-)
>> I will check this evening or tomorrow, I have something else to do this
>> afteroon.
> I think the diff v2 is correct, but is not the best one for this issue.
>
> I prefer the Paul's patch for this issue which has better performance
>
> :-)
yes, I use your patch and it can work, also Paul's patch can work too.
>
> Thanks.
>

^ permalink raw reply

* Re: [PATCH v2] PowerPC: kernel: compiling issue, make additional room in exception vector area
From: Chen Gang F T @ 2013-04-27  9:28 UTC (permalink / raw)
  To: Mike Qiu
  Cc: sfr, Michael Neuling, matt, Chen Gang, linux-kernel,
	Paul Mackerras, Aneesh Kumar K.V, linuxppc-dev
In-Reply-To: <5179FA8E.9090501@linux.vnet.ibm.com>

On 2013年04月26日 11:54, Mike Qiu wrote:
> 于 2013/4/26 11:42, Chen Gang 写道:
>> On 2013年04月26日 11:25, Chen Gang wrote:
>>> On 2013年04月26日 11:08, Mike Qiu wrote:
>>>> 于 2013/4/26 10:06, Chen Gang 写道:
>>>>> On 2013年04月26日 10:03, Mike Qiu wrote:
>>>>>> �� 2013/4/26 9:36, Chen Gang �:
>>>>>>>> On 2013��04��26�� 09:18, Chen Gang wrote:
>>>>>>>>>> On 2013��04��26�� 09:06, Chen Gang wrote:
>>>>>>>>>>>>>> CFAR is the Come From Register.  It saves the location of the
>>>>>>>>>>>>>> last
>>>>>>>>>>>>>>>> branch and is hence overwritten by any branch.
>>>>>>>>>>>>>>>>
>>>>>>>>>>>> Do we process it just like others done (e.g. 0x300, 0xe00,
>>>>>>>>>>>> 0xe20 ...) ?
>>>>>>>>>>>>      . = 0x900
>>>>>>>>>>>>      .globl decrementer_pSeries
>>>>>>>>>>>> decrementer_pSeries:
>>>>>>>>>>>>        HMT_MEDIUM_PPR_DISCARD
>>>>>>>>>>>>      SET_SCRATCH0(r13)
>>>>>>>>>>>>      b decrementer_pSeries_0
>>>>>>>>>>>>
>>>>>>>>>>>>      ...
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>> Oh, it seems EXCEPTION_PROLOG_1 will save the regesters which
>>>>>>>> related
>>>>>>>> with CFAR, so I think need move EXCEPTION_PROLOG_1 to near 0x900.
>>>>>> I will try your diff V2, to see if the machine can boot up
>>>>> OK, thanks. (hope it can work)
>>>> It seems that the machine can be bootup in powernv mode, but I'm not
>>>> sure if my machine call that module.
>>>>
>>>> At lease my machine can boot up
>> Please reference commit number: 1707dd161349e6c54170c88d94fed012e3d224e3
>> (1707dd1 powerpc: Save CFAR before branching in interrupt entry paths)
>>
>> What our diff v2 has done is just the fix for our patch v2 (just like
>> the commit 1707dd1 has done).
>>
>> Please check, thanks.
>>
>> :-)
> I will check this evening or tomorrow, I have something else to do this
> afteroon.

I think the diff v2 is correct, but is not the best one for this issue.

I prefer the Paul's patch for this issue which has better performance

:-)


Thanks.

-- 
Chen Gang

Flying Transformer

^ permalink raw reply

* RE: [PATCH 2/2 V7] powerpc/85xx: Add machine check handler to fix PCIe erratum on mpc85xx
From: Jia Hongtao-B38951 @ 2013-04-27  2:26 UTC (permalink / raw)
  To: Wood Scott-B07421, Segher Boessenkool; +Cc: linuxppc-dev@lists.ozlabs.org
In-Reply-To: <1366909096.30341.3@snotra>

> -----Original Message-----
> From: Wood Scott-B07421
> Sent: Friday, April 26, 2013 12:58 AM
> To: Segher Boessenkool
> Cc: Jia Hongtao-B38951; linuxppc-dev@lists.ozlabs.org;
> galak@kernel.crashing.org; Wood Scott-B07421
> Subject: Re: [PATCH 2/2 V7] powerpc/85xx: Add machine check handler to
> fix PCIe erratum on mpc85xx
>=20
> On 04/25/2013 10:31:51 AM, Segher Boessenkool wrote:
> >> * Remove A variant of load instruction emulation
> >
> > Why is this?  You handle all other simple load insns, there is nothing
> > special about LHA.  (I reviewed the V4 email thread, no reason for the
> > chance is given there).
>=20
> The LHA implementation in V5 was incorrect (didn't sign-extend).
>=20
> -Scott

In former email you doubt whether we need A variant or not.
Any particular reason for that?
If not should I emulate all the A ARX AU AUX and AX variant?

Thanks.
-Hongtao.

^ permalink raw reply

* Re: [PATCH 1/3] rapidio: make enumeration/discovery configurable
From: Andrew Morton @ 2013-04-26 22:53 UTC (permalink / raw)
  To: Alexandre Bounine
  Cc: Micha Nelissen, linux-kernel, Andre van Herk, linuxppc-dev
In-Reply-To: <1366813919-13766-2-git-send-email-alexandre.bounine@idt.com>

On Wed, 24 Apr 2013 10:31:57 -0400 Alexandre Bounine <alexandre.bounine@idt.com> wrote:

> Rework to implement RapidIO enumeration/discovery method selection
> combined with ability to use enumeration/discovery as a kernel module.
> 
> This patch adds ability to introduce new RapidIO enumeration/discovery methods
> using kernel configuration options or loadable modules. Configuration option
> mechanism allows to select built-in or modular enumeration/discovery method from
> the list of existing methods or use external modules.
> If a modular enumeration/discovery is selected each RapidIO mport device can
> have its own method attached to it.
> 
> The currently existing enumeration/discovery code was updated to be used
> as built-in or modular method. This configuration option is named "Basic
> enumeration/discovery" method.
> 
> Several common routines have been moved from rio-scan.c to make them available
> to other enumeration methods and reduce number of exported symbols.
> 
> ...
>
> --- a/drivers/rapidio/Kconfig
> +++ b/drivers/rapidio/Kconfig
> @@ -47,4 +47,23 @@ config RAPIDIO_DEBUG
>  
>  	  If you are unsure about this, say N here.
>  
> +choice
> +	prompt "Enumeration method"
> +	depends on RAPIDIO
> +	help
> +	  There are different enumeration and discovery mechanisms offered
> +	  for RapidIO subsystem. You may select single built-in method or
> +	  or any number of methods to be built as modules.
> +	  Selecting a built-in method disables use of loadable methods.
> +
> +	  If unsure, select Basic built-in.
> +
> +config RAPIDIO_ENUM_BASIC
> +	tristate "Basic"
> +	help
> +	  This option includes basic RapidIO fabric enumeration and discovery
> +	  mechanism similar to one described in RapidIO specification Annex 1.
> +
> +endchoice

This Kconfig change makes my kbuild do Weird Things.

make mrproper ; yes "" | make allmodconfig ; make 2>/tmp/x

: scripts/kconfig/conf --silentoldconfig Kconfig
: *
: * Restart config...
: *
: *
: * Bus options (PCI etc.)
: *
: PCI support (PCI) [Y/n/?] y
:   Support mmconfig PCI config space access (PCI_MMCONFIG) [Y/n] y
:   Read CNB20LE Host Bridge Windows (PCI_CNB20LE_QUIRK) [Y/n/?] y
:   PCI Express support (PCIEPORTBUS) [Y/n/?] y
:     PCI Express Hotplug driver (HOTPLUG_PCI_PCIE) [M/n/?] m
:     Root Port Advanced Error Reporting support (PCIEAER) [Y/n/?] y
:       PCI Express ECRC settings control (PCIE_ECRC) [Y/n/?] y
:       PCIe AER error injector support (PCIEAER_INJECT) [M/n/y/?] m
:     PCI Express ASPM control (PCIEASPM) [Y/n/?] y
:       Debug PCI Express ASPM (PCIEASPM_DEBUG) [Y/n/?] y
:       Default ASPM policy
:       > 1. BIOS default (PCIEASPM_DEFAULT)
:         2. Powersave (PCIEASPM_POWERSAVE)
:         3. Performance (PCIEASPM_PERFORMANCE)
:       choice[1-3]: 1
: Message Signaled Interrupts (MSI and MSI-X) (PCI_MSI) [Y/?] y
: PCI Debugging (PCI_DEBUG) [Y/n/?] y
: Enable PCI resource re-allocation detection (PCI_REALLOC_ENABLE_AUTO) [Y/n/?] y
: PCI Stub driver (PCI_STUB) [M/n/y/?] m
: Xen PCI Frontend (XEN_PCIDEV_FRONTEND) [M/n/y/?] m
: Interrupts on hypertransport devices (HT_IRQ) [Y/n/?] y
: PCI IOV support (PCI_IOV) [Y/n/?] y
: PCI PRI support (PCI_PRI) [Y/?] y
: PCI PASID support (PCI_PASID) [Y/?] y
: PCI IO-APIC hotplug support (PCI_IOAPIC) [M/n/y] m
: ISA-style DMA support (ISA_DMA_API) [Y/n/?] y
: RapidIO support (RAPIDIO) [Y/n/?] y
:   IDT Tsi721 PCI Express SRIO Controller support (RAPIDIO_TSI721) [Y/n/?] y
:   Discovery timeout duration (seconds) (RAPIDIO_DISC_TIMEOUT) [30] 30
:   Enable RapidIO Input/Output Ports (RAPIDIO_ENABLE_RX_TX_PORTS) [Y/n/?] y
:   DMA Engine support for RapidIO (RAPIDIO_DMA_ENGINE) [Y/n/?] y
:   RapidIO subsystem debug messages (RAPIDIO_DEBUG) [Y/n/?] y
:   Enumeration method [M/y/?] (NEW) aborted!
: 
: Console input/output is redirected. Run 'make oldconfig' to update configuration.
: 
:   SYSHDR  arch/x86/syscalls/../include/generated/uapi/asm/unistd_32.h
:   SYSHDR  arch/x86/syscalls/../include/generated/uapi/asm/unistd_64.h
:   SYSHDR  arch/x86/syscalls/../include/generated/uapi/asm/unistd_x32.h


See the "Enumeration method [M/y/?] (NEW) aborted!"

Note that this only happens when make's stderr is redirected.

I've no idea what's going on here.  This appears to fix things:

--- a/drivers/rapidio/Kconfig~rapidio-make-enumeration-discovery-configurable-fix
+++ a/drivers/rapidio/Kconfig
@@ -59,7 +59,7 @@ choice
 	  If unsure, select Basic built-in.
 
 config RAPIDIO_ENUM_BASIC
-	tristate "Basic"
+	bool "Basic"
 	help
 	  This option includes basic RapidIO fabric enumeration and discovery
 	  mechanism similar to one described in RapidIO specification Annex 1.

but doesn't appear to be what you intended.

^ permalink raw reply

* [PATCH] powerpc: Bring all threads online prior to migration/hibernation
From: Robert Jennings @ 2013-04-26 21:32 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: stable

With this patch before a migration/hibernation all threads present but
not online will be brought online.  After migration/hibernation those
threads are taken back offline.

During migration/hibernation all online CPUs must call H_JOIN, this is
required by the hypervisor.  Without this patch, threads that are offline
(H_CEDE'd) will not be woken to make the H_JOIN call and the OS will be
deadlocked (all threads either JOIN'd or CEDE'd).

Cc: <stable@kernel.org>
Signed-off-by: Robert Jennings <rcj@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/rtas.h          |    2 +
 arch/powerpc/kernel/rtas.c               |   95 ++++++++++++++++++++++++++++++
 arch/powerpc/platforms/pseries/suspend.c |   22 +++++++
 3 files changed, 119 insertions(+)

diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h
index aef00c6..ee38f29 100644
--- a/arch/powerpc/include/asm/rtas.h
+++ b/arch/powerpc/include/asm/rtas.h
@@ -262,6 +262,8 @@ extern void rtas_progress(char *s, unsigned short hex);
 extern void rtas_initialize(void);
 extern int rtas_suspend_cpu(struct rtas_suspend_me_data *data);
 extern int rtas_suspend_last_cpu(struct rtas_suspend_me_data *data);
+extern int rtas_online_cpus_mask(cpumask_var_t cpus);
+extern int rtas_offline_cpus_mask(cpumask_var_t cpus);
 extern int rtas_ibm_suspend_me(struct rtas_args *);
 
 struct rtc_time;
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 1fd6e7b..855ee98 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -19,6 +19,7 @@
 #include <linux/init.h>
 #include <linux/capability.h>
 #include <linux/delay.h>
+#include <linux/cpu.h>
 #include <linux/smp.h>
 #include <linux/completion.h>
 #include <linux/cpumask.h>
@@ -807,6 +808,77 @@ static void rtas_percpu_suspend_me(void *info)
 	__rtas_suspend_cpu((struct rtas_suspend_me_data *)info, 1);
 }
 
+enum rtas_cpu_state {
+	DOWN,
+	UP,
+};
+
+/* On return cpumask will be altered to indicate CPUs changed */
+static int rtas_cpu_state_change_mask(enum rtas_cpu_state state,
+				cpumask_var_t cpus)
+{
+	int cpu;
+	int cpuret = 0;
+	int ret = 0;
+
+	if (cpumask_empty(cpus))
+		return 0;
+
+	for_each_cpu(cpu, cpus) {
+		switch (state) {
+		case DOWN:
+			cpuret = cpu_down(cpu);
+			break;
+		case UP:
+			cpuret = cpu_up(cpu);
+			break;
+		}
+		if (cpuret) {
+			pr_debug("%s: cpu_%s for cpu#%d returned %d.\n",
+					__func__,
+					((state == UP) ? "up" : "down"),
+					cpu, cpuret);
+			if (!ret)
+				ret = cpuret;
+			if (state == UP) {
+				cpumask_shift_right(cpus, cpus, cpu);
+				cpumask_shift_left(cpus, cpus, cpu);
+				break;
+			} else
+				cpumask_clear_cpu(cpu, cpus);
+		}
+	}
+
+	return ret;
+}
+
+int rtas_online_cpus_mask(cpumask_var_t cpus)
+{
+	int ret;
+
+	ret = rtas_cpu_state_change_mask(UP, cpus);
+
+	if (ret) {
+		cpumask_var_t tmp_mask;
+
+		if (!alloc_cpumask_var(&tmp_mask, GFP_TEMPORARY))
+			return ret;
+
+		cpumask_copy(tmp_mask, cpus);
+		rtas_offline_cpus_mask(tmp_mask);
+		free_cpumask_var(tmp_mask);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(rtas_online_cpus_mask);
+
+int rtas_offline_cpus_mask(cpumask_var_t cpus)
+{
+	return rtas_cpu_state_change_mask(DOWN, cpus);
+}
+EXPORT_SYMBOL(rtas_offline_cpus_mask);
+
 int rtas_ibm_suspend_me(struct rtas_args *args)
 {
 	long state;
@@ -814,6 +886,8 @@ int rtas_ibm_suspend_me(struct rtas_args *args)
 	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
 	struct rtas_suspend_me_data data;
 	DECLARE_COMPLETION_ONSTACK(done);
+	cpumask_var_t offline_mask;
+	int cpuret;
 
 	if (!rtas_service_present("ibm,suspend-me"))
 		return -ENOSYS;
@@ -837,11 +911,24 @@ int rtas_ibm_suspend_me(struct rtas_args *args)
 		return 0;
 	}
 
+	if (!alloc_cpumask_var(&offline_mask, GFP_TEMPORARY))
+		return -ENOMEM;
+
 	atomic_set(&data.working, 0);
 	atomic_set(&data.done, 0);
 	atomic_set(&data.error, 0);
 	data.token = rtas_token("ibm,suspend-me");
 	data.complete = &done;
+
+	/* All present CPUs must be online */
+	cpumask_andnot(offline_mask, cpu_present_mask, cpu_online_mask);
+	cpuret = rtas_online_cpus_mask(offline_mask);
+	if (cpuret) {
+		pr_err("%s: Could not bring present CPUs online.\n", __func__);
+		atomic_set(&data.error, cpuret);
+		goto out;
+	}
+
 	stop_topology_update();
 
 	/* Call function on all CPUs.  One of us will make the
@@ -857,6 +944,14 @@ int rtas_ibm_suspend_me(struct rtas_args *args)
 
 	start_topology_update();
 
+	/* Take down CPUs not online prior to suspend */
+	cpuret = rtas_offline_cpus_mask(offline_mask);
+	if (cpuret)
+		pr_warn("%s: Could not restore CPUs to offline state.\n",
+				__func__);
+
+out:
+	free_cpumask_var(offline_mask);
 	return atomic_read(&data.error);
 }
 #else /* CONFIG_PPC_PSERIES */
diff --git a/arch/powerpc/platforms/pseries/suspend.c b/arch/powerpc/platforms/pseries/suspend.c
index 47226e0..5f997e7 100644
--- a/arch/powerpc/platforms/pseries/suspend.c
+++ b/arch/powerpc/platforms/pseries/suspend.c
@@ -16,6 +16,7 @@
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   */
 
+#include <linux/cpu.h>
 #include <linux/delay.h>
 #include <linux/suspend.h>
 #include <linux/stat.h>
@@ -126,11 +127,15 @@ static ssize_t store_hibernate(struct device *dev,
 			       struct device_attribute *attr,
 			       const char *buf, size_t count)
 {
+	cpumask_var_t offline_mask;
 	int rc;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
+	if (!alloc_cpumask_var(&offline_mask, GFP_TEMPORARY))
+		return -ENOMEM;
+
 	stream_id = simple_strtoul(buf, NULL, 16);
 
 	do {
@@ -140,15 +145,32 @@ static ssize_t store_hibernate(struct device *dev,
 	} while (rc == -EAGAIN);
 
 	if (!rc) {
+		/* All present CPUs must be online */
+		cpumask_andnot(offline_mask, cpu_present_mask,
+				cpu_online_mask);
+		rc = rtas_online_cpus_mask(offline_mask);
+		if (rc) {
+			pr_err("%s: Could not bring present CPUs online.\n",
+					__func__);
+			goto out;
+		}
+
 		stop_topology_update();
 		rc = pm_suspend(PM_SUSPEND_MEM);
 		start_topology_update();
+
+		/* Take down CPUs not online prior to suspend */
+		if (!rtas_offline_cpus_mask(offline_mask))
+			pr_warn("%s: Could not restore CPUs to offline "
+					"state.\n", __func__);
 	}
 
 	stream_id = 0;
 
 	if (!rc)
 		rc = count;
+out:
+	free_cpumask_var(offline_mask);
 	return rc;
 }
 
-- 
1.7.10.4

^ permalink raw reply related

* Status of I2C mac-drivers needing attach_adapter?
From: Wolfram Sang @ 2013-04-26 15:31 UTC (permalink / raw)
  To: linux-i2c; +Cc: linuxppc-dev

Hi Ben,

because I will push a patch to get rid of detach_adapter() from the I2C
core in the next merge window, I was curious to find out about the
status of attach_adapter().

I found commit 6cd3209967469f6e89d329deda6bb0b4700e7b62
(powerpc/powermac: New windfarm driver for PowerMac G5 (AGP) and Xserve
G5) which should get rid of therm_pm72 if I understand correctly? Or is
it still needed? Can you give me an overview if there is/was progress
regarding the other two drivers therm_windtunnel and sound/ppc/keywest?

Thanks,

   Wolfram

^ permalink raw reply

* Re: [PATCH 0/8 v3] KVM: PPC: e500: Enable FSL e6500 core
From: Alexander Graf @ 2013-04-26 13:48 UTC (permalink / raw)
  To: Mihai Caraman; +Cc: linuxppc-dev, kvm, kvm-ppc
In-Reply-To: <1365674594-17410-1-git-send-email-mihai.caraman@freescale.com>


On 11.04.2013, at 12:03, Mihai Caraman wrote:

> Enable basic support for Freescale e6500 core, adding MAV 2.0 support.
> Validated on T4240QDS platfrom. Altivec, Multithreading and HW =
Tablewalk
> are not addressed by this patchset.

Thanks, applied all to kvm-ppc-queue.


Alex

>=20
> Mihai Caraman (8):
>  KVM: PPC: Book3E: Refactor ONE_REG ioctl implementation
>  KVM: PPC: e500: Expose MMU registers via ONE_REG
>  KVM: PPC: e500: Move vcpu's MMU configuration to dedicated functions
>  KVM: PPC: e500: Add support for TLBnPS registers
>  KVM: PPC: e500: Add support for EPTCFG register
>  KVM: PPC: e500: Remove E.PT and E.HV.LRAT categories from VCPUs
>  KVM: PPC: e500mc: Enable e6500 cores
>  KVM: PPC: e500: Add e6500 core to Kconfig description
>=20
> Documentation/virtual/kvm/api.txt   |   16 +++
> arch/powerpc/include/asm/kvm_host.h |    2 +
> arch/powerpc/include/uapi/asm/kvm.h |   22 ++++
> arch/powerpc/kvm/44x.c              |   12 ++
> arch/powerpc/kvm/Kconfig            |    6 +-
> arch/powerpc/kvm/booke.c            |  102 ++++++++++---------
> arch/powerpc/kvm/e500.c             |   14 +++
> arch/powerpc/kvm/e500.h             |   22 ++++
> arch/powerpc/kvm/e500_emulate.c     |   19 ++++
> arch/powerpc/kvm/e500_mmu.c         |  192 =
+++++++++++++++++++++++++++++++----
> arch/powerpc/kvm/e500mc.c           |   16 +++
> 11 files changed, 351 insertions(+), 72 deletions(-)
>=20
> --=20
> 1.7.4.1
>=20
>=20
> --
> To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH 3/3] powerpc/pseries: Support compression of oops text via pstore
From: Aruna Balakrishnaiah @ 2013-04-26  9:56 UTC (permalink / raw)
  To: linuxppc-dev, paulus, linux-kernel, benh
  Cc: jkenisto, tony.luck, mahesh, cbouatmailru, anton, ccross,
	keescook
In-Reply-To: <20130426094923.14323.80567.stgit@aruna-ThinkPad-T420>

The patch set supports compression of oops messages while writing to NVRAM,
this helps in capturing more of oops data to lnx,oops-log. The pstore file
for oops messages will be in decompressed format making it readable.

In case compression fails, the patch takes care of copying the header added
by pstore and last oops_data_sz bytes of big_oops_buf to NVRAM so that we
have recent oops messages in lnx,oops-log.

In case decompression fails, it will result in absence of oops file but still
have files (in /dev/pstore) for other partitions.

Signed-off-by: Aruna Balakrishnaiah <aruna@linux.vnet.ibm.com>
---
 arch/powerpc/platforms/pseries/nvram.c |  132 +++++++++++++++++++++++++++++---
 1 file changed, 118 insertions(+), 14 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
index 0159d74..b5ba5e2 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -539,6 +539,65 @@ static int zip_oops(size_t text_len)
 }
 
 #ifdef CONFIG_PSTORE
+/* Derived from logfs_uncompress */
+int nvram_decompress(void *in, void *out, size_t inlen, size_t outlen)
+{
+	int err, ret;
+
+	ret = -EIO;
+	err = zlib_inflateInit(&stream);
+	if (err != Z_OK)
+		goto error;
+
+	stream.next_in = in;
+	stream.avail_in = inlen;
+	stream.total_in = 0;
+	stream.next_out = out;
+	stream.avail_out = outlen;
+	stream.total_out = 0;
+
+	err = zlib_inflate(&stream, Z_FINISH);
+	if (err != Z_STREAM_END)
+		goto error;
+
+	err = zlib_inflateEnd(&stream);
+	if (err != Z_OK)
+		goto error;
+
+	ret = stream.total_out;
+error:
+	return ret;
+}
+
+static int unzip_oops(char *oops_buf, char *big_buf)
+{
+	struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
+	u64 timestamp = oops_hdr->timestamp;
+	char *big_oops_data = NULL;
+	char *oops_data_buf = NULL;
+	size_t big_oops_data_sz;
+	int unzipped_len;
+
+	big_oops_data = big_buf + sizeof(struct oops_log_info);
+	big_oops_data_sz = big_oops_buf_sz - sizeof(struct oops_log_info);
+	oops_data_buf = oops_buf + sizeof(struct oops_log_info);
+
+	unzipped_len = nvram_decompress(oops_data_buf, big_oops_data,
+					oops_hdr->report_length,
+					big_oops_data_sz);
+
+	if (unzipped_len < 0) {
+		pr_err("nvram: decompression failed; returned %d\n",
+								unzipped_len);
+		return -1;
+	}
+	oops_hdr = (struct oops_log_info *)big_buf;
+	oops_hdr->version = OOPS_HDR_VERSION;
+	oops_hdr->report_length = (u16) unzipped_len;
+	oops_hdr->timestamp = timestamp;
+	return 0;
+}
+
 static int nvram_pstore_open(struct pstore_info *psi)
 {
 	/* Reset the iterator to start reading partitions again */
@@ -567,6 +626,7 @@ static int nvram_pstore_write(enum pstore_type_id type,
 				size_t size, struct pstore_info *psi)
 {
 	int rc;
+	unsigned int err_type = ERR_TYPE_KERNEL_PANIC;
 	struct oops_log_info *oops_hdr = (struct oops_log_info *) oops_buf;
 
 	/* part 1 has the recent messages from printk buffer */
@@ -577,8 +637,31 @@ static int nvram_pstore_write(enum pstore_type_id type,
 	oops_hdr->version = OOPS_HDR_VERSION;
 	oops_hdr->report_length = (u16) size;
 	oops_hdr->timestamp = get_seconds();
+
+	if (big_oops_buf) {
+		rc = zip_oops(size);
+		/*
+		 * If compression fails copy recent log messages from
+		 * big_oops_buf to oops_data.
+		 */
+		if (rc != 0) {
+			int hsize = pstore_get_header_size();
+			size_t diff = size - oops_data_sz + hsize;
+
+			if (size > oops_data_sz) {
+				memcpy(oops_data, big_oops_buf, hsize);
+				memcpy(oops_data + hsize, big_oops_buf + diff,
+					oops_data_sz - hsize);
+
+				oops_hdr->report_length = (u16) oops_data_sz;
+			} else
+				memcpy(oops_data, big_oops_buf, size);
+		} else
+			err_type = ERR_TYPE_KERNEL_PANIC_GZ;
+	}
+
 	rc = nvram_write_os_partition(&oops_log_partition, oops_buf,
-		(int) (sizeof(*oops_hdr) + size), ERR_TYPE_KERNEL_PANIC,
+		(int) (sizeof(*oops_hdr) + oops_hdr->report_length), err_type,
 		count);
 
 	if (rc != 0)
@@ -600,10 +683,11 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type,
 	struct oops_log_info *oops_hdr;
 	unsigned int err_type, id_no, size = 0;
 	struct nvram_os_partition *part = NULL;
-	char *buff = NULL;
-	int sig = 0;
+	char *buff = NULL, *big_buff = NULL;
+	int rc, sig = 0;
 	loff_t p;
 
+read_partition:
 	read_type++;
 
 	switch (nvram_type_ids[read_type]) {
@@ -666,6 +750,25 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type,
 	if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) {
 		oops_hdr = (struct oops_log_info *)buff;
 		*buf = buff + sizeof(*oops_hdr);
+
+		if (err_type == ERR_TYPE_KERNEL_PANIC_GZ) {
+			big_buff = kmalloc(big_oops_buf_sz, GFP_KERNEL);
+			if (!big_buff)
+				return -ENOMEM;
+
+			rc = unzip_oops(buff, big_buff);
+
+			if (rc != 0) {
+				kfree(buff);
+				kfree(big_buff);
+				goto read_partition;
+			}
+
+			oops_hdr = (struct oops_log_info *)big_buff;
+			*buf = big_buff + sizeof(*oops_hdr);
+			kfree(buff);
+		}
+
 		time->tv_sec = oops_hdr->timestamp;
 		time->tv_nsec = 0;
 		return oops_hdr->report_length;
@@ -687,17 +790,18 @@ static int nvram_pstore_init(void)
 {
 	int rc = 0;
 
-	nvram_pstore_info.buf = oops_data;
-	nvram_pstore_info.bufsize = oops_data_sz;
+	if (big_oops_buf) {
+		nvram_pstore_info.buf = big_oops_buf;
+		nvram_pstore_info.bufsize = big_oops_buf_sz;
+	} else {
+		nvram_pstore_info.buf = oops_data;
+		nvram_pstore_info.bufsize = oops_data_sz;
+	}
 
 	rc = pstore_register(&nvram_pstore_info);
 	if (rc != 0)
 		pr_err("nvram: pstore_register() failed, defaults to "
 				"kmsg_dump; returned %d\n", rc);
-	else
-		/*TODO: Support compression when pstore is configured */
-		pr_info("nvram: Compression of oops text supported only when "
-				"pstore is not configured");
 
 	return rc;
 }
@@ -731,11 +835,6 @@ static void __init nvram_init_oops_partition(int rtas_partition_exists)
 	oops_data = oops_buf + sizeof(struct oops_log_info);
 	oops_data_sz = oops_log_partition.size - sizeof(struct oops_log_info);
 
-	rc = nvram_pstore_init();
-
-	if (!rc)
-		return;
-
 	/*
 	 * Figure compression (preceded by elimination of each line's <n>
 	 * severity prefix) will reduce the oops/panic report to at most
@@ -759,6 +858,11 @@ static void __init nvram_init_oops_partition(int rtas_partition_exists)
 		stream.workspace = NULL;
 	}
 
+	rc = nvram_pstore_init();
+
+	if (!rc)
+		return;
+
 	rc = kmsg_dump_register(&nvram_kmsg_dumper);
 	if (rc != 0) {
 		pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc);

^ permalink raw reply related

* [PATCH 2/3] powerpc/pseries: Re-organise the oops compression code
From: Aruna Balakrishnaiah @ 2013-04-26  9:56 UTC (permalink / raw)
  To: linuxppc-dev, paulus, linux-kernel, benh
  Cc: jkenisto, tony.luck, mahesh, cbouatmailru, anton, ccross,
	keescook
In-Reply-To: <20130426094923.14323.80567.stgit@aruna-ThinkPad-T420>

nvram_compress() and zip_oops() is used by the nvram_pstore_write
API to compress oops messages hence re-organise the functions
accordingly to avoid forward declarations.

Signed-off-by: Aruna Balakrishnaiah <aruna@linux.vnet.ibm.com>
---
 arch/powerpc/platforms/pseries/nvram.c |  104 ++++++++++++++++----------------
 1 file changed, 52 insertions(+), 52 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
index 14cc486..0159d74 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -486,6 +486,58 @@ static int clobbering_unread_rtas_event(void)
 						NVRAM_RTAS_READ_TIMEOUT);
 }
 
+/* Derived from logfs_compress() */
+static int nvram_compress(const void *in, void *out, size_t inlen,
+							size_t outlen)
+{
+	int err, ret;
+
+	ret = -EIO;
+	err = zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS,
+						MEM_LEVEL, Z_DEFAULT_STRATEGY);
+	if (err != Z_OK)
+		goto error;
+
+	stream.next_in = in;
+	stream.avail_in = inlen;
+	stream.total_in = 0;
+	stream.next_out = out;
+	stream.avail_out = outlen;
+	stream.total_out = 0;
+
+	err = zlib_deflate(&stream, Z_FINISH);
+	if (err != Z_STREAM_END)
+		goto error;
+
+	err = zlib_deflateEnd(&stream);
+	if (err != Z_OK)
+		goto error;
+
+	if (stream.total_out >= stream.total_in)
+		goto error;
+
+	ret = stream.total_out;
+error:
+	return ret;
+}
+
+/* Compress the text from big_oops_buf into oops_buf. */
+static int zip_oops(size_t text_len)
+{
+	struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
+	int zipped_len = nvram_compress(big_oops_buf, oops_data, text_len,
+								oops_data_sz);
+	if (zipped_len < 0) {
+		pr_err("nvram: compression failed; returned %d\n", zipped_len);
+		pr_err("nvram: logging uncompressed oops/panic report\n");
+		return -1;
+	}
+	oops_hdr->version = OOPS_HDR_VERSION;
+	oops_hdr->report_length = (u16) zipped_len;
+	oops_hdr->timestamp = get_seconds();
+	return 0;
+}
+
 #ifdef CONFIG_PSTORE
 static int nvram_pstore_open(struct pstore_info *psi)
 {
@@ -757,58 +809,6 @@ int __init pSeries_nvram_init(void)
 }
 
 
-/* Derived from logfs_compress() */
-static int nvram_compress(const void *in, void *out, size_t inlen,
-							size_t outlen)
-{
-	int err, ret;
-
-	ret = -EIO;
-	err = zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS,
-						MEM_LEVEL, Z_DEFAULT_STRATEGY);
-	if (err != Z_OK)
-		goto error;
-
-	stream.next_in = in;
-	stream.avail_in = inlen;
-	stream.total_in = 0;
-	stream.next_out = out;
-	stream.avail_out = outlen;
-	stream.total_out = 0;
-
-	err = zlib_deflate(&stream, Z_FINISH);
-	if (err != Z_STREAM_END)
-		goto error;
-
-	err = zlib_deflateEnd(&stream);
-	if (err != Z_OK)
-		goto error;
-
-	if (stream.total_out >= stream.total_in)
-		goto error;
-
-	ret = stream.total_out;
-error:
-	return ret;
-}
-
-/* Compress the text from big_oops_buf into oops_buf. */
-static int zip_oops(size_t text_len)
-{
-	struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
-	int zipped_len = nvram_compress(big_oops_buf, oops_data, text_len,
-								oops_data_sz);
-	if (zipped_len < 0) {
-		pr_err("nvram: compression failed; returned %d\n", zipped_len);
-		pr_err("nvram: logging uncompressed oops/panic report\n");
-		return -1;
-	}
-	oops_hdr->version = OOPS_HDR_VERSION;
-	oops_hdr->report_length = (u16) zipped_len;
-	oops_hdr->timestamp = get_seconds();
-	return 0;
-}
-
 /*
  * This is our kmsg_dump callback, called after an oops or panic report
  * has been written to the printk buffer.  We want to capture as much

^ permalink raw reply related

* [PATCH 1/3] Retreive header size from pstore.
From: Aruna Balakrishnaiah @ 2013-04-26  9:55 UTC (permalink / raw)
  To: linuxppc-dev, paulus, linux-kernel, benh
  Cc: jkenisto, tony.luck, mahesh, cbouatmailru, anton, ccross,
	keescook
In-Reply-To: <20130426094923.14323.80567.stgit@aruna-ThinkPad-T420>

pstore_get_header_size will return the size of the header added by pstore
while logging messages to the registered buffer.

Signed-off-by: Aruna Balakrishnaiah <aruna@linux.vnet.ibm.com>
---
 fs/pstore/platform.c   |    7 ++++++-
 include/linux/pstore.h |    6 ++++++
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index 86d1038..e8260ea 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -49,6 +49,7 @@ MODULE_PARM_DESC(update_ms, "milliseconds before pstore updates its content "
 		 "corruption on Oopses)");
 
 static int pstore_new_entry;
+static int hsize;
 
 static void pstore_timefunc(unsigned long);
 static DEFINE_TIMER(pstore_timer, pstore_timefunc, 0, 0);
@@ -68,6 +69,11 @@ static char *backend;
 /* How much of the console log to snapshot */
 static unsigned long kmsg_bytes = 10240;
 
+int pstore_get_header_size(void)
+{
+	return hsize;
+}
+
 void pstore_set_kmsg_bytes(int bytes)
 {
 	kmsg_bytes = bytes;
@@ -147,7 +153,6 @@ static void pstore_dump(struct kmsg_dumper *dumper,
 	while (total < kmsg_bytes) {
 		char *dst;
 		unsigned long size;
-		int hsize;
 		size_t len;
 
 		dst = psinfo->buf;
diff --git a/include/linux/pstore.h b/include/linux/pstore.h
index 656699f..f43b64f 100644
--- a/include/linux/pstore.h
+++ b/include/linux/pstore.h
@@ -73,6 +73,7 @@ struct pstore_info {
 #ifdef CONFIG_PSTORE
 extern int pstore_register(struct pstore_info *);
 extern bool pstore_cannot_block_path(enum kmsg_dump_reason reason);
+extern int pstore_get_header_size(void);
 #else
 static inline int
 pstore_register(struct pstore_info *psi)
@@ -84,6 +85,11 @@ pstore_cannot_block_path(enum kmsg_dump_reason reason)
 {
 	return false;
 }
+static inline int
+pstore_get_header_size(void)
+{
+	return 0;
+}
 #endif
 
 #endif /*_LINUX_PSTORE_H*/

^ permalink raw reply related

* [RFC PATCH 0/3] Nvram-to-pstore: compression support for oops data
From: Aruna Balakrishnaiah @ 2013-04-26  9:55 UTC (permalink / raw)
  To: linuxppc-dev, paulus, linux-kernel, benh
  Cc: jkenisto, tony.luck, mahesh, cbouatmailru, anton, ccross,
	keescook

The patchset takes care of compressing oops messages while writing to NVRAM,
so that more oops data can be captured in the given space.

big_oops_buf (2.22 * oops_data_sz) is allocated for compression.
oops_data_sz is oops header size less of oops partition size.

Pstore will internally call kmsg_dump to capture messages from printk
buffer. While returning the data to nvram it adds is own header.

For compression:
	Register pstore with big_oops_buf. 

In case compression fails, copy header added by pstore and
last oops_data_sz bytes (recent messages) of big_oops_buf to
nvram for which we need to know header size. 
	
patch 01/03 will add a function in pstore to return the header size.

pstore read callback of nvram will read the compressed data and return the
decompressed data so that dmesg file (under /dev/pstore) is readable.

In case decompression fails, instead of having the compressed data (junk) in the
dmesg file it will skip and continue reading other partitions. This results in
absence of dmesg file but will still have files relating to other parititons.


---

Aruna Balakrishnaiah (3):
      Retreive header size from pstore.
      powerpc/pseries: Re-organise the oops compression code
      powerpc/pseries: Support compression of oops text via pstore


 arch/powerpc/platforms/pseries/nvram.c |  236 +++++++++++++++++++++++---------
 fs/pstore/platform.c                   |    7 +
 include/linux/pstore.h                 |    6 +
 3 files changed, 182 insertions(+), 67 deletions(-)

-- 

^ permalink raw reply

* Re: [PATCH v8 2/3] of/pci: Provide support for parsing PCI DT ranges property
From: 한진구 @ 2013-04-26  9:33 UTC (permalink / raw)
  To: 'Andrew Murray'
  Cc: linux-mips, siva.kallam, linux-pci, linus.walleij, thierry.reding,
	Liviu.Dudau, juhosg, paulus, linux-samsung-soc, linux, Jingoo Han,
	jgunthorpe, thomas.abraham, arnd, devicetree-discuss, rob.herring,
	kgene.kim, bhelgaas, linux-arm-kernel, thomas.petazzoni, monstr,
	linux-kernel, suren.reddy, linuxppc-dev
In-Reply-To: <1366627295-16964-3-git-send-email-Andrew.Murray@arm.com>

On Monday, April 22, 2013 7:42 PM, Andrew Murray wrote:
> 
> This patch factors out common implementation patterns to reduce overall kernel
> code and provide a means for host bridge drivers to directly obtain struct
> resources from the DT's ranges property without relying on architecture specific
> DT handling. This will make it easier to write archiecture independent host bridge
> drivers and mitigate against further duplication of DT parsing code.
> 
> This patch can be used in the following way:
> 
> 	struct of_pci_range_parser parser;
> 	struct of_pci_range range;
> 
> 	if (of_pci_range_parser_init(&parser, np))
> 		; //no ranges property
> 
> 	for_each_of_pci_range(&parser, &range) {
> 
> 		/*
> 			directly access properties of the address range, e.g.:
> 			range.pci_space, range.pci_addr, range.cpu_addr,
> 			range.size, range.flags
> 
> 			alternatively obtain a struct resource, e.g.:
> 			struct resource res;
> 			of_pci_range_to_resource(&range, np, &res);
> 		*/
> 	}
> 
> Additionally the implementation takes care of adjacent ranges and merges them
> into a single range (as was the case with powerpc and microblaze).
> 
> Signed-off-by: Andrew Murray <Andrew.Murray@arm.com>
> Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> Reviewed-by: Rob Herring <rob.herring@calxeda.com>
> Tested-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> Tested-by: Linus Walleij <linus.walleij@linaro.org>
> Acked-by: Grant Likely <grant.likely@secretlab.ca>


Tested-by: Jingoo Han <jg1.han@samsung.com>

Hi Andrew,

I tested this patch with Exynos5440.
It works properly.
Thank you.

Best regards,
Jingoo Han

> ---
>  drivers/of/address.c       |   67 ++++++++++++++++++++++++++
>  drivers/of/of_pci.c        |  113 +++++++++++++++++---------------------------
>  include/linux/of_address.h |   48 +++++++++++++++++++
>  3 files changed, 158 insertions(+), 70 deletions(-)
> 
> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 04da786..fdd0636 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -227,6 +227,73 @@ int of_pci_address_to_resource(struct device_node *dev, int bar,
>  	return __of_address_to_resource(dev, addrp, size, flags, NULL, r);
>  }
>  EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
> +
> +int of_pci_range_parser_init(struct of_pci_range_parser *parser,
> +				struct device_node *node)
> +{
> +	const int na = 3, ns = 2;
> +	int rlen;
> +
> +	parser->node = node;
> +	parser->pna = of_n_addr_cells(node);
> +	parser->np = parser->pna + na + ns;
> +
> +	parser->range = of_get_property(node, "ranges", &rlen);
> +	if (parser->range == NULL)
> +		return -ENOENT;
> +
> +	parser->end = parser->range + rlen / sizeof(__be32);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(of_pci_range_parser_init);
> +
> +struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
> +						struct of_pci_range *range)
> +{
> +	const int na = 3, ns = 2;
> +
> +	if (!range)
> +		return NULL;
> +
> +	if (!parser->range || parser->range + parser->np > parser->end)
> +		return NULL;
> +
> +	range->pci_space = parser->range[0];
> +	range->flags = of_bus_pci_get_flags(parser->range);
> +	range->pci_addr = of_read_number(parser->range + 1, ns);
> +	range->cpu_addr = of_translate_address(parser->node,
> +				parser->range + na);
> +	range->size = of_read_number(parser->range + parser->pna + na, ns);
> +
> +	parser->range += parser->np;
> +
> +	/* Now consume following elements while they are contiguous */
> +	while (parser->range + parser->np <= parser->end) {
> +		u32 flags, pci_space;
> +		u64 pci_addr, cpu_addr, size;
> +
> +		pci_space = be32_to_cpup(parser->range);
> +		flags = of_bus_pci_get_flags(parser->range);
> +		pci_addr = of_read_number(parser->range + 1, ns);
> +		cpu_addr = of_translate_address(parser->node,
> +				parser->range + na);
> +		size = of_read_number(parser->range + parser->pna + na, ns);
> +
> +		if (flags != range->flags)
> +			break;
> +		if (pci_addr != range->pci_addr + range->size ||
> +		    cpu_addr != range->cpu_addr + range->size)
> +			break;
> +
> +		range->size += size;
> +		parser->range += parser->np;
> +	}
> +
> +	return range;
> +}
> +EXPORT_SYMBOL_GPL(of_pci_range_parser_one);
> +
>  #endif /* CONFIG_PCI */
> 
>  /*
> diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
> index 1626172..3c49ab2 100644
> --- a/drivers/of/of_pci.c
> +++ b/drivers/of/of_pci.c
> @@ -2,6 +2,7 @@
>  #include <linux/export.h>
>  #include <linux/of.h>
>  #include <linux/of_pci.h>
> +#include <linux/of_address.h>
>  #include <asm/prom.h>
> 
>  #if defined(CONFIG_PPC32) || defined(CONFIG_PPC64) || defined(CONFIG_MICROBLAZE)
> @@ -82,67 +83,42 @@ EXPORT_SYMBOL_GPL(of_pci_find_child_device);
>  void pci_process_bridge_OF_ranges(struct pci_controller *hose,
>  				  struct device_node *dev, int primary)
>  {
> -	const u32 *ranges;
> -	int rlen;
> -	int pna = of_n_addr_cells(dev);
> -	int np = pna + 5;
>  	int memno = 0, isa_hole = -1;
> -	u32 pci_space;
> -	unsigned long long pci_addr, cpu_addr, pci_next, cpu_next, size;
>  	unsigned long long isa_mb = 0;
>  	struct resource *res;
> +	struct of_pci_range range;
> +	struct of_pci_range_parser parser;
> 
>  	pr_info("PCI host bridge %s %s ranges:\n",
>  	       dev->full_name, primary ? "(primary)" : "");
> 
> -	/* Get ranges property */
> -	ranges = of_get_property(dev, "ranges", &rlen);
> -	if (ranges == NULL)
> +	/* Check for ranges property */
> +	if (of_pci_range_parser_init(&parser, dev))
>  		return;
> 
> -	/* Parse it */
>  	pr_debug("Parsing ranges property...\n");
> -	while ((rlen -= np * 4) >= 0) {
> +	for_each_of_pci_range(&parser, &range) {
>  		/* Read next ranges element */
> -		pci_space = ranges[0];
> -		pci_addr = of_read_number(ranges + 1, 2);
> -		cpu_addr = of_translate_address(dev, ranges + 3);
> -		size = of_read_number(ranges + pna + 3, 2);
> -
> -		pr_debug("pci_space: 0x%08x pci_addr:0x%016llx ",
> -				pci_space, pci_addr);
> -		pr_debug("cpu_addr:0x%016llx size:0x%016llx\n",
> -					cpu_addr, size);
> -
> -		ranges += np;
> +		pr_debug("pci_space: 0x%08x pci_addr: 0x%016llx ",
> +				range.pci_space, range.pci_addr);
> +		pr_debug("cpu_addr: 0x%016llx size: 0x%016llx\n",
> +				range.cpu_addr, range.size);
> 
>  		/* If we failed translation or got a zero-sized region
>  		 * (some FW try to feed us with non sensical zero sized regions
>  		 * such as power3 which look like some kind of attempt
>  		 * at exposing the VGA memory hole)
>  		 */
> -		if (cpu_addr == OF_BAD_ADDR || size == 0)
> +		if (range.cpu_addr == OF_BAD_ADDR || range.size == 0)
>  			continue;
> 
> -		/* Now consume following elements while they are contiguous */
> -		for (; rlen >= np * sizeof(u32);
> -		     ranges += np, rlen -= np * 4) {
> -			if (ranges[0] != pci_space)
> -				break;
> -			pci_next = of_read_number(ranges + 1, 2);
> -			cpu_next = of_translate_address(dev, ranges + 3);
> -			if (pci_next != pci_addr + size ||
> -			    cpu_next != cpu_addr + size)
> -				break;
> -			size += of_read_number(ranges + pna + 3, 2);
> -		}
> -
>  		/* Act based on address space type */
>  		res = NULL;
> -		switch ((pci_space >> 24) & 0x3) {
> -		case 1:		/* PCI IO space */
> +		switch (range.flags & IORESOURCE_TYPE_BITS) {
> +		case IORESOURCE_IO:
>  			pr_info("  IO 0x%016llx..0x%016llx -> 0x%016llx\n",
> -			       cpu_addr, cpu_addr + size - 1, pci_addr);
> +				range.cpu_addr, range.cpu_addr + range.size - 1,
> +				range.pci_addr);
> 
>  			/* We support only one IO range */
>  			if (hose->pci_io_size) {
> @@ -151,11 +127,12 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
>  			}
>  #if (!IS_ENABLED(CONFIG_64BIT))
>  			/* On 32 bits, limit I/O space to 16MB */
> -			if (size > 0x01000000)
> -				size = 0x01000000;
> +			if (range.size > 0x01000000)
> +				range.size = 0x01000000;
> 
>  			/* 32 bits needs to map IOs here */
> -			hose->io_base_virt = ioremap(cpu_addr, size);
> +			hose->io_base_virt = ioremap(range.cpu_addr,
> +						range.size);
> 
>  			/* Expect trouble if pci_addr is not 0 */
>  			if (primary)
> @@ -165,19 +142,21 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
>  			/* pci_io_size and io_base_phys always represent IO
>  			 * space starting at 0 so we factor in pci_addr
>  			 */
> -			hose->pci_io_size = pci_addr + size;
> -			hose->io_base_phys = cpu_addr - pci_addr;
> +			hose->pci_io_size = range.pci_addr + range.size;
> +			hose->io_base_phys = range.cpu_addr - range.pci_addr;
> 
>  			/* Build resource */
>  			res = &hose->io_resource;
> -			res->flags = IORESOURCE_IO;
> -			res->start = pci_addr;
> +			range.cpu_addr = range.pci_addr;
> +
>  			break;
> -		case 2:		/* PCI Memory space */
> -		case 3:		/* PCI 64 bits Memory space */
> +
> +		case IORESOURCE_MEM:
>  			pr_info(" MEM 0x%016llx..0x%016llx -> 0x%016llx %s\n",
> -			       cpu_addr, cpu_addr + size - 1, pci_addr,
> -			       (pci_space & 0x40000000) ? "Prefetch" : "");
> +				range.cpu_addr, range.cpu_addr + range.size - 1,
> +				range.pci_addr,
> +				(range.pci_space & 0x40000000) ?
> +				"Prefetch" : "");
> 
>  			/* We support only 3 memory ranges */
>  			if (memno >= 3) {
> @@ -185,13 +164,13 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
>  				continue;
>  			}
>  			/* Handles ISA memory hole space here */
> -			if (pci_addr == 0) {
> -				isa_mb = cpu_addr;
> +			if (range.pci_addr == 0) {
> +				isa_mb = range.cpu_addr;
>  				isa_hole = memno;
>  				if (primary || isa_mem_base == 0)
> -					isa_mem_base = cpu_addr;
> -				hose->isa_mem_phys = cpu_addr;
> -				hose->isa_mem_size = size;
> +					isa_mem_base = range.cpu_addr;
> +				hose->isa_mem_phys = range.cpu_addr;
> +				hose->isa_mem_size = range.size;
>  			}
> 
>  			/* We get the PCI/Mem offset from the first range or
> @@ -199,30 +178,24 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
>  			 * hole. If they don't match, bugger.
>  			 */
>  			if (memno == 0 ||
> -			    (isa_hole >= 0 && pci_addr != 0 &&
> +			(isa_hole >= 0 && range.pci_addr != 0 &&
>  			     hose->pci_mem_offset == isa_mb))
> -				hose->pci_mem_offset = cpu_addr - pci_addr;
> -			else if (pci_addr != 0 &&
> -				 hose->pci_mem_offset != cpu_addr - pci_addr) {
> +				hose->pci_mem_offset = range.cpu_addr -
> +							range.pci_addr;
> +			else if (range.pci_addr != 0 &&
> +				hose->pci_mem_offset != range.cpu_addr -
> +							range.pci_addr) {
>  				pr_info(" \\--> Skipped (offset mismatch) !\n");
>  				continue;
>  			}
> 
>  			/* Build resource */
>  			res = &hose->mem_resources[memno++];
> -			res->flags = IORESOURCE_MEM;
> -			if (pci_space & 0x40000000)
> -				res->flags |= IORESOURCE_PREFETCH;
> -			res->start = cpu_addr;
> +
>  			break;
>  		}
> -		if (res != NULL) {
> -			res->name = dev->full_name;
> -			res->end = res->start + size - 1;
> -			res->parent = NULL;
> -			res->sibling = NULL;
> -			res->child = NULL;
> -		}
> +		if (res != NULL)
> +			of_pci_range_to_resource(&range, dev, res);
>  	}
> 
>  	/* If there's an ISA hole and the pci_mem_offset is -not- matching
> diff --git a/include/linux/of_address.h b/include/linux/of_address.h
> index 0506eb5..4c2e6f2 100644
> --- a/include/linux/of_address.h
> +++ b/include/linux/of_address.h
> @@ -4,6 +4,36 @@
>  #include <linux/errno.h>
>  #include <linux/of.h>
> 
> +struct of_pci_range_parser {
> +	struct device_node *node;
> +	const __be32 *range;
> +	const __be32 *end;
> +	int np;
> +	int pna;
> +};
> +
> +struct of_pci_range {
> +	u32 pci_space;
> +	u64 pci_addr;
> +	u64 cpu_addr;
> +	u64 size;
> +	u32 flags;
> +};
> +
> +#define for_each_of_pci_range(parser, range) \
> +	for (; of_pci_range_parser_one(parser, range);)
> +
> +static inline void of_pci_range_to_resource(struct of_pci_range *range,
> +					    struct device_node *np,
> +					    struct resource *res)
> +{
> +	res->flags = range->flags;
> +	res->start = range->cpu_addr;
> +	res->end = range->cpu_addr + range->size - 1;
> +	res->parent = res->child = res->sibling = NULL;
> +	res->name = np->full_name;
> +}
> +
>  #ifdef CONFIG_OF_ADDRESS
>  extern u64 of_translate_address(struct device_node *np, const __be32 *addr);
>  extern bool of_can_translate_address(struct device_node *dev);
> @@ -27,6 +57,11 @@ static inline unsigned long pci_address_to_pio(phys_addr_t addr) { return -1; }
>  #define pci_address_to_pio pci_address_to_pio
>  #endif
> 
> +extern int of_pci_range_parser_init(struct of_pci_range_parser *parser,
> +			struct device_node *node);
> +extern struct of_pci_range *of_pci_range_parser_one(
> +					struct of_pci_range_parser *parser,
> +					struct of_pci_range *range);
>  #else /* CONFIG_OF_ADDRESS */
>  #ifndef of_address_to_resource
>  static inline int of_address_to_resource(struct device_node *dev, int index,
> @@ -53,6 +88,19 @@ static inline const __be32 *of_get_address(struct device_node *dev, int index,
>  {
>  	return NULL;
>  }
> +
> +static inline int of_pci_range_parser_init(struct of_pci_range_parser *parser,
> +			struct device_node *node)
> +{
> +	return -1;
> +}
> +
> +static inline struct of_pci_range *of_pci_range_parser_one(
> +					struct of_pci_range_parser *parser,
> +					struct of_pci_range *range)
> +{
> +	return NULL;
> +}
>  #endif /* CONFIG_OF_ADDRESS */
> 
> 
> --
> 1.7.0.4

^ permalink raw reply

* [PATCH] powerpc: Setup BHRB instructions facility in HFSCR for POWER8
From: Anshuman Khandual @ 2013-04-26  6:54 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: mikey

Make BHRB instructions available in problem and privileged states.

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/reg.h        | 1 +
 arch/powerpc/kernel/cpu_setup_power.S | 3 ++-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 0bee933..e8afd35 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -271,6 +271,7 @@
 #define SPRN_HFSCR	0xbe	/* HV=1 Facility Status & Control Register */
 #define   HFSCR_TAR	(1 << (63-55)) /* Enable Target Address Register */
 #define   HFSCR_TM	(1 << (63-58)) /* Enable Transactional Memory */
+#define   HFSCR_BHRB	(1 << (63-59)) /* Enable Branch History Rolling Buffer */
 #define   HFSCR_DSCR	(1 << (63-61)) /* Enable Data Stream Control Register */
 #define   HFSCR_VECVSX	(1 << (63-62)) /* Enable VMX/VSX  */
 #define   HFSCR_FP	(1 << (63-63)) /* Enable Floating Point */
diff --git a/arch/powerpc/kernel/cpu_setup_power.S b/arch/powerpc/kernel/cpu_setup_power.S
index be0c12d..e673429 100644
--- a/arch/powerpc/kernel/cpu_setup_power.S
+++ b/arch/powerpc/kernel/cpu_setup_power.S
@@ -125,7 +125,8 @@ __init_FSCR:
 
 __init_HFSCR:
 	mfspr	r3,SPRN_HFSCR
-	ori	r3,r3,HFSCR_TAR|HFSCR_TM|HFSCR_DSCR|HFSCR_VECVSX|HFSCR_FP
+	ori	r3,r3,HFSCR_TAR|HFSCR_TM|HFSCR_BHRB|\
+				HFSCR_DSCR|HFSCR_VECVSX|HFSCR_FP
 	mtspr	SPRN_HFSCR,r3
 	blr
 
-- 
1.7.11.7

^ permalink raw reply related

* [PATCH 7/7] powerpc/perf: Power8 PMU support
From: Michael Ellerman @ 2013-04-26  5:28 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1366954108-27081-1-git-send-email-michael@ellerman.id.au>

This patch adds support for the power8 PMU to perf.

Work is ongoing to add generic cache events.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/perf/Makefile     |    3 +-
 arch/powerpc/perf/power8-pmu.c |  537 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 539 insertions(+), 1 deletion(-)
 create mode 100644 arch/powerpc/perf/power8-pmu.c

diff --git a/arch/powerpc/perf/Makefile b/arch/powerpc/perf/Makefile
index af3fac2..472db18 100644
--- a/arch/powerpc/perf/Makefile
+++ b/arch/powerpc/perf/Makefile
@@ -4,7 +4,8 @@ obj-$(CONFIG_PERF_EVENTS)	+= callchain.o
 
 obj-$(CONFIG_PPC_PERF_CTRS)	+= core-book3s.o
 obj64-$(CONFIG_PPC_PERF_CTRS)	+= power4-pmu.o ppc970-pmu.o power5-pmu.o \
-				   power5+-pmu.o power6-pmu.o power7-pmu.o
+				   power5+-pmu.o power6-pmu.o power7-pmu.o \
+				   power8-pmu.o
 obj32-$(CONFIG_PPC_PERF_CTRS)	+= mpc7450-pmu.o
 
 obj-$(CONFIG_FSL_EMB_PERF_EVENT) += core-fsl-emb.o
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
new file mode 100644
index 0000000..c6aa713
--- /dev/null
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -0,0 +1,537 @@
+/*
+ * Performance counter support for POWER8 processors.
+ *
+ * Copyright 2009 Paul Mackerras, IBM Corporation.
+ * Copyright 2013 Michael Ellerman, 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/perf_event.h>
+#include <asm/firmware.h>
+
+
+/*
+ * 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
+
+
+/*
+ * Raw event encoding for POWER8:
+ *
+ *        60        56        52        48        44        40        36        32
+ * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
+ *                                     [      thresh_cmp     ]   [  thresh_ctl   ]
+ *                                                                       |
+ *                                       thresh start/stop OR FAB match -*
+ *
+ *        28        24        20        16        12         8         4         0
+ * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
+ *   [   ] [  sample ]   [cache]   [ pmc ]   [unit ]   c     m   [    pmcxsel    ]
+ *     |        |           |                          |     |
+ *     |        |           |                          |     *- mark
+ *     |        |           *- L1/L2/L3 cache_sel      |
+ *     |        |                                      |
+ *     |        *- sampling mode for marked events     *- combine
+ *     |
+ *     *- thresh_sel
+ *
+ * Below uses IBM bit numbering.
+ *
+ * MMCR1[x:y] = unit    (PMCxUNIT)
+ * MMCR1[x]   = combine (PMCxCOMB)
+ *
+ * if pmc == 3 and unit == 0 and pmcxsel[0:6] == 0b0101011
+ *	# PM_MRK_FAB_RSP_MATCH
+ *	MMCR1[20:27] = thresh_ctl   (FAB_CRESP_MATCH / FAB_TYPE_MATCH)
+ * else if pmc == 4 and unit == 0xf and pmcxsel[0:6] == 0b0101001
+ *	# PM_MRK_FAB_RSP_MATCH_CYC
+ *	MMCR1[20:27] = thresh_ctl   (FAB_CRESP_MATCH / FAB_TYPE_MATCH)
+ * else
+ *	MMCRA[48:55] = thresh_ctl   (THRESH START/END)
+ *
+ * if thresh_sel:
+ *	MMCRA[45:47] = thresh_sel
+ *
+ * if thresh_cmp:
+ *	MMCRA[22:24] = thresh_cmp[0:2]
+ *	MMCRA[25:31] = thresh_cmp[3:9]
+ *
+ * if unit == 6 or unit == 7
+ *	MMCRC[53:55] = cache_sel[1:3]      (L2EVENT_SEL)
+ * else if unit == 8 or unit == 9:
+ *	if cache_sel[0] == 0: # L3 bank
+ *		MMCRC[47:49] = cache_sel[1:3]  (L3EVENT_SEL0)
+ *	else if cache_sel[0] == 1:
+ *		MMCRC[50:51] = cache_sel[2:3]  (L3EVENT_SEL1)
+ * else if cache_sel[1]: # L1 event
+ *	MMCR1[16] = cache_sel[2]
+ *	MMCR1[17] = cache_sel[3]
+ *
+ * if mark:
+ *	MMCRA[63]    = 1		(SAMPLE_ENABLE)
+ *	MMCRA[57:59] = sample[0:2]	(RAND_SAMP_ELIG)
+ *	MMCRA[61:62] = sample[3:4]	(RAND_SAMP_MODE)
+ *
+ */
+
+#define EVENT_THR_CMP_SHIFT	40	/* Threshold CMP value */
+#define EVENT_THR_CMP_MASK	0x3ff
+#define EVENT_THR_CTL_SHIFT	32	/* Threshold control value (start/stop) */
+#define EVENT_THR_CTL_MASK	0xffull
+#define EVENT_THR_SEL_SHIFT	29	/* Threshold select value */
+#define EVENT_THR_SEL_MASK	0x7
+#define EVENT_THRESH_SHIFT	29	/* All threshold bits */
+#define EVENT_THRESH_MASK	0x1fffffull
+#define EVENT_SAMPLE_SHIFT	24	/* Sampling mode & eligibility */
+#define EVENT_SAMPLE_MASK	0x1f
+#define EVENT_CACHE_SEL_SHIFT	20	/* L2/L3 cache select */
+#define EVENT_CACHE_SEL_MASK	0xf
+#define EVENT_IS_L1		(4 << EVENT_CACHE_SEL_SHIFT)
+#define EVENT_PMC_SHIFT		16	/* PMC number (1-based) */
+#define EVENT_PMC_MASK		0xf
+#define EVENT_UNIT_SHIFT	12	/* Unit */
+#define EVENT_UNIT_MASK		0xf
+#define EVENT_COMBINE_SHIFT	11	/* Combine bit */
+#define EVENT_COMBINE_MASK	0x1
+#define EVENT_MARKED_SHIFT	8	/* Marked bit */
+#define EVENT_MARKED_MASK	0x1
+#define EVENT_IS_MARKED		(EVENT_MARKED_MASK << EVENT_MARKED_SHIFT)
+#define EVENT_PSEL_MASK		0xff	/* PMCxSEL value */
+
+/*
+ * Layout of constraint bits:
+ *
+ *        60        56        52        48        44        40        36        32
+ * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
+ *   [   fab_match   ]         [       thresh_cmp      ] [   thresh_ctl    ] [   ]
+ *                                                                             |
+ *                                                                 thresh_sel -*
+ *
+ *        28        24        20        16        12         8         4         0
+ * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
+ *                       [ ]   [  sample ]   [     ]   [6] [5]   [4] [3]   [2] [1]
+ *                        |                     |
+ *      L1 I/D qualifier -*                     |      Count of events for each PMC.
+ *                                              |        p1, p2, p3, p4, p5, p6.
+ *                     nc - number of counters -*
+ *
+ * The PMC fields P1..P6, and NC, are adder fields. As we accumulate constraints
+ * we want the low bit of each field to be added to any existing value.
+ *
+ * Everything else is a value field.
+ */
+
+#define CNST_FAB_MATCH_VAL(v)	(((v) & EVENT_THR_CTL_MASK) << 56)
+#define CNST_FAB_MATCH_MASK	CNST_FAB_MATCH_VAL(EVENT_THR_CTL_MASK)
+
+/* We just throw all the threshold bits into the constraint */
+#define CNST_THRESH_VAL(v)	(((v) & EVENT_THRESH_MASK) << 32)
+#define CNST_THRESH_MASK	CNST_THRESH_VAL(EVENT_THRESH_MASK)
+
+#define CNST_L1_QUAL_VAL(v)	(((v) & 3) << 22)
+#define CNST_L1_QUAL_MASK	CNST_L1_QUAL_VAL(3)
+
+#define CNST_SAMPLE_VAL(v)	(((v) & EVENT_SAMPLE_MASK) << 16)
+#define CNST_SAMPLE_MASK	CNST_SAMPLE_VAL(EVENT_SAMPLE_MASK)
+
+/*
+ * For NC we are counting up to 4 events. This requires three bits, and we need
+ * the fifth event to overflow and set the 4th bit. To achieve that we bias the
+ * fields by 3 in test_adder.
+ */
+#define CNST_NC_SHIFT		12
+#define CNST_NC_VAL		(1 << CNST_NC_SHIFT)
+#define CNST_NC_MASK		(8 << CNST_NC_SHIFT)
+#define POWER8_TEST_ADDER	(3 << CNST_NC_SHIFT)
+
+/*
+ * For the per-PMC fields we have two bits. The low bit is added, so if two
+ * events ask for the same PMC the sum will overflow, setting the high bit,
+ * indicating an error. So our mask sets the high bit.
+ */
+#define CNST_PMC_SHIFT(pmc)	((pmc - 1) * 2)
+#define CNST_PMC_VAL(pmc)	(1 << CNST_PMC_SHIFT(pmc))
+#define CNST_PMC_MASK(pmc)	(2 << CNST_PMC_SHIFT(pmc))
+
+/* Our add_fields is defined as: */
+#define POWER8_ADD_FIELDS	\
+	CNST_PMC_VAL(1) | CNST_PMC_VAL(2) | CNST_PMC_VAL(3) | \
+	CNST_PMC_VAL(4) | CNST_PMC_VAL(5) | CNST_PMC_VAL(6) | CNST_NC_VAL
+
+
+/* Bits in MMCR1 for POWER8 */
+#define MMCR1_UNIT_SHIFT(pmc)		(60 - (4 * ((pmc) - 1)))
+#define MMCR1_COMBINE_SHIFT(pmc)	(35 - ((pmc) - 1))
+#define MMCR1_PMCSEL_SHIFT(pmc)		(24 - (((pmc) - 1)) * 8)
+#define MMCR1_DC_QUAL_SHIFT		47
+#define MMCR1_IC_QUAL_SHIFT		46
+
+/* Bits in MMCRA for POWER8 */
+#define MMCRA_SAMP_MODE_SHIFT		1
+#define MMCRA_SAMP_ELIG_SHIFT		4
+#define MMCRA_THR_CTL_SHIFT		8
+#define MMCRA_THR_SEL_SHIFT		16
+#define MMCRA_THR_CMP_SHIFT		32
+#define MMCRA_SDAR_MODE_TLB		(1ull << 42)
+
+
+static inline bool event_is_fab_match(u64 event)
+{
+	/* Only check pmc, unit and pmcxsel, ignore the edge bit (0) */
+	event &= 0xff0fe;
+
+	/* PM_MRK_FAB_RSP_MATCH & PM_MRK_FAB_RSP_MATCH_CYC */
+	return (event == 0x30056 || event == 0x4f052);
+}
+
+static int power8_get_constraint(u64 event, unsigned long *maskp, unsigned long *valp)
+{
+	unsigned int unit, pmc, cache;
+	unsigned long mask, value;
+
+	mask = value = 0;
+
+	pmc   = (event >> EVENT_PMC_SHIFT)       & EVENT_PMC_MASK;
+	unit  = (event >> EVENT_UNIT_SHIFT)      & EVENT_UNIT_MASK;
+	cache = (event >> EVENT_CACHE_SEL_SHIFT) & EVENT_CACHE_SEL_MASK;
+
+	if (pmc) {
+		if (pmc > 6)
+			return -1;
+
+		mask  |= CNST_PMC_MASK(pmc);
+		value |= CNST_PMC_VAL(pmc);
+
+		if (pmc >= 5 && event != 0x500fa && event != 0x600f4)
+			return -1;
+	}
+
+	if (pmc <= 4) {
+		/*
+		 * Add to number of counters in use. Note this includes events with
+		 * a PMC of 0 - they still need a PMC, it's just assigned later.
+		 * Don't count events on PMC 5 & 6, there is only one valid event
+		 * on each of those counters, and they are handled above.
+		 */
+		mask  |= CNST_NC_MASK;
+		value |= CNST_NC_VAL;
+	}
+
+	if (unit >= 6 && unit <= 9) {
+		/*
+		 * L2/L3 events contain a cache selector field, which is
+		 * supposed to be programmed into MMCRC. However MMCRC is only
+		 * HV writable, and there is no API for guest kernels to modify
+		 * it. The solution is for the hypervisor to initialise the
+		 * field to zeroes, and for us to only ever allow events that
+		 * have a cache selector of zero.
+		 */
+		if (cache)
+			return -1;
+
+	} else if (event & EVENT_IS_L1) {
+		mask  |= CNST_L1_QUAL_MASK;
+		value |= CNST_L1_QUAL_VAL(cache);
+	}
+
+	if (event & EVENT_IS_MARKED) {
+		mask  |= CNST_SAMPLE_MASK;
+		value |= CNST_SAMPLE_VAL(event >> EVENT_SAMPLE_SHIFT);
+	}
+
+	/*
+	 * Special case for PM_MRK_FAB_RSP_MATCH and PM_MRK_FAB_RSP_MATCH_CYC,
+	 * the threshold control bits are used for the match value.
+	 */
+	if (event_is_fab_match(event)) {
+		mask  |= CNST_FAB_MATCH_MASK;
+		value |= CNST_FAB_MATCH_VAL(event >> EVENT_THR_CTL_SHIFT);
+	} else {
+		/*
+		 * Check the mantissa upper two bits are not zero, unless the
+		 * exponent is also zero. See the THRESH_CMP_MANTISSA doc.
+		 */
+		unsigned int cmp, exp;
+
+		cmp = (event >> EVENT_THR_CMP_SHIFT) & EVENT_THR_CMP_MASK;
+		exp = cmp >> 7;
+
+		if (exp && (cmp & 0x60) == 0)
+			return -1;
+
+		mask  |= CNST_THRESH_MASK;
+		value |= CNST_THRESH_VAL(event >> EVENT_THRESH_SHIFT);
+	}
+
+	*maskp = mask;
+	*valp = value;
+
+	return 0;
+}
+
+static int power8_compute_mmcr(u64 event[], int n_ev,
+			       unsigned int hwc[], unsigned long mmcr[])
+{
+	unsigned long mmcra, mmcr1, unit, combine, psel, cache, val;
+	unsigned int pmc, pmc_inuse;
+	int i;
+
+	pmc_inuse = 0;
+
+	/* First pass to count resource use */
+	for (i = 0; i < n_ev; ++i) {
+		pmc = (event[i] >> EVENT_PMC_SHIFT) & EVENT_PMC_MASK;
+		if (pmc)
+			pmc_inuse |= 1 << pmc;
+	}
+
+	/* In continous sampling mode, update SDAR on TLB miss */
+	mmcra = MMCRA_SDAR_MODE_TLB;
+	mmcr1 = 0;
+
+	/* Second pass: assign PMCs, set all MMCR1 fields */
+	for (i = 0; i < n_ev; ++i) {
+		pmc     = (event[i] >> EVENT_PMC_SHIFT) & EVENT_PMC_MASK;
+		unit    = (event[i] >> EVENT_UNIT_SHIFT) & EVENT_UNIT_MASK;
+		combine = (event[i] >> EVENT_COMBINE_SHIFT) & EVENT_COMBINE_MASK;
+		psel    =  event[i] & EVENT_PSEL_MASK;
+
+		if (!pmc) {
+			for (pmc = 1; pmc <= 4; ++pmc) {
+				if (!(pmc_inuse & (1 << pmc)))
+					break;
+			}
+
+			pmc_inuse |= 1 << pmc;
+		}
+
+		if (pmc <= 4) {
+			mmcr1 |= unit << MMCR1_UNIT_SHIFT(pmc);
+			mmcr1 |= combine << MMCR1_COMBINE_SHIFT(pmc);
+			mmcr1 |= psel << MMCR1_PMCSEL_SHIFT(pmc);
+		}
+
+		if (event[i] & EVENT_IS_L1) {
+			cache = event[i] >> EVENT_CACHE_SEL_SHIFT;
+			mmcr1 |= (cache & 1) << MMCR1_IC_QUAL_SHIFT;
+			cache >>= 1;
+			mmcr1 |= (cache & 1) << MMCR1_DC_QUAL_SHIFT;
+		}
+
+		if (event[i] & EVENT_IS_MARKED) {
+			mmcra |= MMCRA_SAMPLE_ENABLE;
+
+			val = (event[i] >> EVENT_SAMPLE_SHIFT) & EVENT_SAMPLE_MASK;
+			if (val) {
+				mmcra |= (val &  3) << MMCRA_SAMP_MODE_SHIFT;
+				mmcra |= (val >> 2) << MMCRA_SAMP_ELIG_SHIFT;
+			}
+		}
+
+		/*
+		 * PM_MRK_FAB_RSP_MATCH and PM_MRK_FAB_RSP_MATCH_CYC,
+		 * the threshold bits are used for the match value.
+		 */
+		if (event_is_fab_match(event[i])) {
+			mmcr1 |= (event[i] >> EVENT_THR_CTL_SHIFT) &
+				  EVENT_THR_CTL_MASK;
+		} else {
+			val = (event[i] >> EVENT_THR_CTL_SHIFT) & EVENT_THR_CTL_MASK;
+			mmcra |= val << MMCRA_THR_CTL_SHIFT;
+			val = (event[i] >> EVENT_THR_SEL_SHIFT) & EVENT_THR_SEL_MASK;
+			mmcra |= val << MMCRA_THR_SEL_SHIFT;
+			val = (event[i] >> EVENT_THR_CMP_SHIFT) & EVENT_THR_CMP_MASK;
+			mmcra |= val << MMCRA_THR_CMP_SHIFT;
+		}
+
+		hwc[i] = pmc - 1;
+	}
+
+	/* Return MMCRx values */
+	mmcr[0] = 0;
+
+	/* pmc_inuse is 1-based */
+	if (pmc_inuse & 2)
+		mmcr[0] = MMCR0_PMC1CE;
+
+	if (pmc_inuse & 0x7c)
+		mmcr[0] |= MMCR0_PMCjCE;
+
+	mmcr[1] = mmcr1;
+	mmcr[2] = mmcra;
+
+	return 0;
+}
+
+#define MAX_ALT	2
+
+/* Table of alternatives, sorted by column 0 */
+static const unsigned int event_alternatives[][MAX_ALT] = {
+	{ 0x10134, 0x301e2 },		/* PM_MRK_ST_CMPL */
+	{ 0x10138, 0x40138 },		/* PM_BR_MRK_2PATH */
+	{ 0x18082, 0x3e05e },		/* PM_L3_CO_MEPF */
+	{ 0x1d14e, 0x401e8 },		/* PM_MRK_DATA_FROM_L2MISS */
+	{ 0x1e054, 0x4000a },		/* PM_CMPLU_STALL */
+	{ 0x20036, 0x40036 },		/* PM_BR_2PATH */
+	{ 0x200f2, 0x300f2 },		/* PM_INST_DISP */
+	{ 0x200f4, 0x600f4 },		/* PM_RUN_CYC */
+	{ 0x2013c, 0x3012e },		/* PM_MRK_FILT_MATCH */
+	{ 0x3e054, 0x400f0 },		/* PM_LD_MISS_L1 */
+	{ 0x400fa, 0x500fa },		/* PM_RUN_INST_CMPL */
+};
+
+/*
+ * Scan the alternatives table for a match and return the
+ * index into the alternatives table if found, else -1.
+ */
+static int find_alternative(u64 event)
+{
+	int i, j;
+
+	for (i = 0; i < ARRAY_SIZE(event_alternatives); ++i) {
+		if (event < event_alternatives[i][0])
+			break;
+
+		for (j = 0; j < MAX_ALT && event_alternatives[i][j]; ++j)
+			if (event == event_alternatives[i][j])
+				return i;
+	}
+
+	return -1;
+}
+
+static int power8_get_alternatives(u64 event, unsigned int flags, u64 alt[])
+{
+	int i, j, num_alt = 0;
+	u64 alt_event;
+
+	alt[num_alt++] = event;
+
+	i = find_alternative(event);
+	if (i >= 0) {
+		/* Filter out the original event, it's already in alt[0] */
+		for (j = 0; j < MAX_ALT; ++j) {
+			alt_event = event_alternatives[i][j];
+			if (alt_event && alt_event != event)
+				alt[num_alt++] = alt_event;
+		}
+	}
+
+	if (flags & PPMU_ONLY_COUNT_RUN) {
+		/*
+		 * We're only counting in RUN state, so PM_CYC is equivalent to
+		 * PM_RUN_CYC and PM_INST_CMPL === PM_RUN_INST_CMPL.
+		 */
+		j = num_alt;
+		for (i = 0; i < num_alt; ++i) {
+			switch (alt[i]) {
+			case 0x1e:	/* PM_CYC */
+				alt[j++] = 0x600f4;	/* PM_RUN_CYC */
+				break;
+			case 0x600f4:	/* PM_RUN_CYC */
+				alt[j++] = 0x1e;
+				break;
+			case 0x2:	/* PM_PPC_CMPL */
+				alt[j++] = 0x500fa;	/* PM_RUN_INST_CMPL */
+				break;
+			case 0x500fa:	/* PM_RUN_INST_CMPL */
+				alt[j++] = 0x2;	/* PM_PPC_CMPL */
+				break;
+			}
+		}
+		num_alt = j;
+	}
+
+	return num_alt;
+}
+
+static void power8_disable_pmc(unsigned int pmc, unsigned long mmcr[])
+{
+	if (pmc <= 3)
+		mmcr[1] &= ~(0xffUL << MMCR1_PMCSEL_SHIFT(pmc + 1));
+}
+
+PMU_FORMAT_ATTR(event,		"config:0-49");
+PMU_FORMAT_ATTR(pmcxsel,	"config:0-7");
+PMU_FORMAT_ATTR(mark,		"config:8");
+PMU_FORMAT_ATTR(combine,	"config:11");
+PMU_FORMAT_ATTR(unit,		"config:12-15");
+PMU_FORMAT_ATTR(pmc,		"config:16-19");
+PMU_FORMAT_ATTR(cache_sel,	"config:20-23");
+PMU_FORMAT_ATTR(sample_mode,	"config:24-28");
+PMU_FORMAT_ATTR(thresh_sel,	"config:29-31");
+PMU_FORMAT_ATTR(thresh_stop,	"config:32-35");
+PMU_FORMAT_ATTR(thresh_start,	"config:36-39");
+PMU_FORMAT_ATTR(thresh_cmp,	"config:40-49");
+
+static struct attribute *power8_pmu_format_attr[] = {
+	&format_attr_event.attr,
+	&format_attr_pmcxsel.attr,
+	&format_attr_mark.attr,
+	&format_attr_combine.attr,
+	&format_attr_unit.attr,
+	&format_attr_pmc.attr,
+	&format_attr_cache_sel.attr,
+	&format_attr_sample_mode.attr,
+	&format_attr_thresh_sel.attr,
+	&format_attr_thresh_stop.attr,
+	&format_attr_thresh_start.attr,
+	&format_attr_thresh_cmp.attr,
+	NULL,
+};
+
+struct attribute_group power8_pmu_format_group = {
+	.name = "format",
+	.attrs = power8_pmu_format_attr,
+};
+
+static const struct attribute_group *power8_pmu_attr_groups[] = {
+	&power8_pmu_format_group,
+	NULL,
+};
+
+static int power8_generic_events[] = {
+	[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_BRANCH_INSTRUCTIONS] =		PM_BRU_FIN,
+	[PERF_COUNT_HW_BRANCH_MISSES] =			PM_BR_MPRED_CMPL,
+};
+
+static struct power_pmu power8_pmu = {
+	.name			= "POWER8",
+	.n_counter		= 6,
+	.max_alternatives	= MAX_ALT + 1,
+	.add_fields		= POWER8_ADD_FIELDS,
+	.test_adder		= POWER8_TEST_ADDER,
+	.compute_mmcr		= power8_compute_mmcr,
+	.get_constraint		= power8_get_constraint,
+	.get_alternatives	= power8_get_alternatives,
+	.disable_pmc		= power8_disable_pmc,
+	.flags			= PPMU_HAS_SSLOT | PPMU_HAS_SIER,
+	.n_generic		= ARRAY_SIZE(power8_generic_events),
+	.generic_events		= power8_generic_events,
+	.attr_groups		= power8_pmu_attr_groups,
+};
+
+static int __init init_power8_pmu(void)
+{
+	if (!cur_cpu_spec->oprofile_cpu_type ||
+	    strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power8"))
+		return -ENODEV;
+
+	return register_power_pmu(&power8_pmu);
+}
+early_initcall(init_power8_pmu);
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 6/7] powerpc/perf: Add support for SIER
From: Michael Ellerman @ 2013-04-26  5:28 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1366954108-27081-1-git-send-email-michael@ellerman.id.au>

On power8 we have a new SIER (Sampled Instruction Event Register), which
captures information about instructions when we have random sampling
enabled.

Add support for loading the SIER into pt_regs, overloading regs->dar.
Also set the new NO_SIPR flag in regs->result if we don't have SIPR.

Update regs_sihv/sipr() to look for SIPR/SIHV in SIER.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/include/asm/perf_event_server.h |    1 +
 arch/powerpc/include/asm/reg.h               |    5 +++++
 arch/powerpc/perf/core-book3s.c              |   19 +++++++++++++++++++
 3 files changed, 25 insertions(+)

diff --git a/arch/powerpc/include/asm/perf_event_server.h b/arch/powerpc/include/asm/perf_event_server.h
index 7074aec..57b42da 100644
--- a/arch/powerpc/include/asm/perf_event_server.h
+++ b/arch/powerpc/include/asm/perf_event_server.h
@@ -53,6 +53,7 @@ struct power_pmu {
 #define PPMU_NO_CONT_SAMPLING	0x00000008 /* no continuous sampling */
 #define PPMU_SIAR_VALID		0x00000010 /* Processor has SIAR Valid bit */
 #define PPMU_HAS_SSLOT		0x00000020 /* Has sampled slot in MMCRA */
+#define PPMU_HAS_SIER		0x00000040 /* Has SIER */
 
 /*
  * Values for flags to get_alternatives()
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 5735ebb..5c6fbe2 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -671,6 +671,11 @@
 #define SPRN_PMC8	794
 #define SPRN_SIAR	780
 #define SPRN_SDAR	781
+#define SPRN_SIER	784
+#define   SIER_SIPR		0x2000000	/* Sampled MSR_PR */
+#define   SIER_SIHV		0x1000000	/* Sampled MSR_HV */
+#define   SIER_SIAR_VALID	0x0400000	/* SIAR contents valid */
+#define   SIER_SDAR_VALID	0x0200000	/* SDAR contents valid */
 
 #define SPRN_PA6T_MMCR0 795
 #define   PA6T_MMCR0_EN0	0x0000000000000001UL
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 1c13c3d..4ac6e64 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -140,6 +140,9 @@ static bool regs_sihv(struct pt_regs *regs)
 {
 	unsigned long sihv = MMCRA_SIHV;
 
+	if (ppmu->flags & PPMU_HAS_SIER)
+		return !!(regs->dar & SIER_SIHV);
+
 	if (ppmu->flags & PPMU_ALT_SIPR)
 		sihv = POWER6_MMCRA_SIHV;
 
@@ -150,6 +153,9 @@ static bool regs_sipr(struct pt_regs *regs)
 {
 	unsigned long sipr = MMCRA_SIPR;
 
+	if (ppmu->flags & PPMU_HAS_SIER)
+		return !!(regs->dar & SIER_SIPR);
+
 	if (ppmu->flags & PPMU_ALT_SIPR)
 		sipr = POWER6_MMCRA_SIPR;
 
@@ -203,6 +209,7 @@ static inline u32 perf_get_misc_flags(struct pt_regs *regs)
 /*
  * Overload regs->dsisr to store MMCRA so we only need to read it once
  * on each interrupt.
+ * Overload regs->dar to store SIER if we have it.
  * Overload regs->result to specify whether we should use the MSR (result
  * is zero) or the SIAR (result is non zero).
  */
@@ -219,6 +226,18 @@ static inline void perf_read_regs(struct pt_regs *regs)
 		regs->result |= 2;
 
 	/*
+	 * On power8 if we're in random sampling mode, the SIER is updated.
+	 * If we're in continuous sampling mode, we don't have SIPR.
+	 */
+	if (ppmu->flags & PPMU_HAS_SIER) {
+		if (marked)
+			regs->dar = mfspr(SPRN_SIER);
+		else
+			regs->result |= 2;
+	}
+
+
+	/*
 	 * If this isn't a PMU exception (eg a software event) the SIAR is
 	 * not valid. Use pt_regs.
 	 *
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 5/7] powerpc/perf: Add regs_no_sipr()
From: Michael Ellerman @ 2013-04-26  5:28 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1366954108-27081-1-git-send-email-michael@ellerman.id.au>

On power8 the presence or absence of SIPR depends on settings at runtime,
so convert to using a dynamic flag for NO_SIPR. Existing backends that
set NO_SIPR unconditionally set the dynamic flag obviously.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/perf/core-book3s.c |   15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 5d30001..1c13c3d 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -156,6 +156,11 @@ static bool regs_sipr(struct pt_regs *regs)
 	return !!(regs->dsisr & sipr);
 }
 
+static bool regs_no_sipr(struct pt_regs *regs)
+{
+	return !!(regs->result & 2);
+}
+
 static inline u32 perf_flags_from_msr(struct pt_regs *regs)
 {
 	if (regs->msr & MSR_PR)
@@ -178,7 +183,7 @@ static inline u32 perf_get_misc_flags(struct pt_regs *regs)
 	 * SIAR which should give slightly more reliable
 	 * results
 	 */
-	if (ppmu->flags & PPMU_NO_SIPR) {
+	if (regs_no_sipr(regs)) {
 		unsigned long siar = mfspr(SPRN_SIAR);
 		if (siar >= PAGE_OFFSET)
 			return PERF_RECORD_MISC_KERNEL;
@@ -208,6 +213,10 @@ static inline void perf_read_regs(struct pt_regs *regs)
 	int use_siar;
 
 	regs->dsisr = mmcra;
+	regs->result = 0;
+
+	if (ppmu->flags & PPMU_NO_SIPR)
+		regs->result |= 2;
 
 	/*
 	 * If this isn't a PMU exception (eg a software event) the SIAR is
@@ -232,12 +241,12 @@ static inline void perf_read_regs(struct pt_regs *regs)
 		use_siar = 1;
 	else if ((ppmu->flags & PPMU_NO_CONT_SAMPLING))
 		use_siar = 0;
-	else if (!(ppmu->flags & PPMU_NO_SIPR) && regs_sipr(regs))
+	else if (!regs_no_sipr(regs) && regs_sipr(regs))
 		use_siar = 0;
 	else
 		use_siar = 1;
 
-	regs->result = use_siar;
+	regs->result |= use_siar;
 }
 
 /*
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 4/7] powerpc/perf: Add an accessor for regs->result
From: Michael Ellerman @ 2013-04-26  5:28 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1366954108-27081-1-git-send-email-michael@ellerman.id.au>

Add an accessor for regs->result so we can use it to store more flags in
future.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/perf/core-book3s.c |    9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 2417fe2..5d30001 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -89,6 +89,11 @@ static inline int siar_valid(struct pt_regs *regs)
 
 #endif /* CONFIG_PPC32 */
 
+static bool regs_use_siar(struct pt_regs *regs)
+{
+	return !!(regs->result & 1);
+}
+
 /*
  * Things that are specific to 64-bit implementations.
  */
@@ -162,7 +167,7 @@ static inline u32 perf_flags_from_msr(struct pt_regs *regs)
 
 static inline u32 perf_get_misc_flags(struct pt_regs *regs)
 {
-	unsigned long use_siar = regs->result;
+	bool use_siar = regs_use_siar(regs);
 
 	if (!use_siar)
 		return perf_flags_from_msr(regs);
@@ -1425,7 +1430,7 @@ unsigned long perf_misc_flags(struct pt_regs *regs)
  */
 unsigned long perf_instruction_pointer(struct pt_regs *regs)
 {
-	unsigned long use_siar = regs->result;
+	bool use_siar = regs_use_siar(regs);
 
 	if (use_siar && siar_valid(regs))
 		return mfspr(SPRN_SIAR) + perf_ip_adjust(regs);
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 3/7] powerpc/perf: Convert mmcra_sipr/sihv() to regs_sipr/sihv()
From: Michael Ellerman @ 2013-04-26  5:28 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1366954108-27081-1-git-send-email-michael@ellerman.id.au>

On power8 the SIPR and SIHV are not in MMCRA, so convert the routines
to take regs and change the names accordingly.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/perf/core-book3s.c |   20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index eb64480..2417fe2 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -131,24 +131,24 @@ static inline void perf_get_data_addr(struct pt_regs *regs, u64 *addrp)
 		*addrp = mfspr(SPRN_SDAR);
 }
 
-static bool mmcra_sihv(unsigned long mmcra)
+static bool regs_sihv(struct pt_regs *regs)
 {
 	unsigned long sihv = MMCRA_SIHV;
 
 	if (ppmu->flags & PPMU_ALT_SIPR)
 		sihv = POWER6_MMCRA_SIHV;
 
-	return !!(mmcra & sihv);
+	return !!(regs->dsisr & sihv);
 }
 
-static bool mmcra_sipr(unsigned long mmcra)
+static bool regs_sipr(struct pt_regs *regs)
 {
 	unsigned long sipr = MMCRA_SIPR;
 
 	if (ppmu->flags & PPMU_ALT_SIPR)
 		sipr = POWER6_MMCRA_SIPR;
 
-	return !!(mmcra & sipr);
+	return !!(regs->dsisr & sipr);
 }
 
 static inline u32 perf_flags_from_msr(struct pt_regs *regs)
@@ -162,7 +162,6 @@ static inline u32 perf_flags_from_msr(struct pt_regs *regs)
 
 static inline u32 perf_get_misc_flags(struct pt_regs *regs)
 {
-	unsigned long mmcra = regs->dsisr;
 	unsigned long use_siar = regs->result;
 
 	if (!use_siar)
@@ -182,10 +181,12 @@ static inline u32 perf_get_misc_flags(struct pt_regs *regs)
 	}
 
 	/* PR has priority over HV, so order below is important */
-	if (mmcra_sipr(mmcra))
+	if (regs_sipr(regs))
 		return PERF_RECORD_MISC_USER;
-	if (mmcra_sihv(mmcra) && (freeze_events_kernel != MMCR0_FCHV))
+
+	if (regs_sihv(regs) && (freeze_events_kernel != MMCR0_FCHV))
 		return PERF_RECORD_MISC_HYPERVISOR;
+
 	return PERF_RECORD_MISC_KERNEL;
 }
 
@@ -201,6 +202,8 @@ static inline void perf_read_regs(struct pt_regs *regs)
 	int marked = mmcra & MMCRA_SAMPLE_ENABLE;
 	int use_siar;
 
+	regs->dsisr = mmcra;
+
 	/*
 	 * If this isn't a PMU exception (eg a software event) the SIAR is
 	 * not valid. Use pt_regs.
@@ -224,12 +227,11 @@ static inline void perf_read_regs(struct pt_regs *regs)
 		use_siar = 1;
 	else if ((ppmu->flags & PPMU_NO_CONT_SAMPLING))
 		use_siar = 0;
-	else if (!(ppmu->flags & PPMU_NO_SIPR) && mmcra_sipr(mmcra))
+	else if (!(ppmu->flags & PPMU_NO_SIPR) && regs_sipr(regs))
 		use_siar = 0;
 	else
 		use_siar = 1;
 
-	regs->dsisr = mmcra;
 	regs->result = use_siar;
 }
 
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 2/7] powerpc/perf: Add an explict flag indicating presence of SLOT field
From: Michael Ellerman @ 2013-04-26  5:28 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1366954108-27081-1-git-send-email-michael@ellerman.id.au>

In perf_ip_adjust() we potentially use the MMCRA[SLOT] field to adjust
the reported IP of a sampled instruction.

Currently the logic is written so that if the backend does NOT have
the PPMU_ALT_SIPR flag set then we assume MMCRA[SLOT] exists.

However on power8 we do not want to set ALT_SIPR (it's in a third
location), and we also do not have MMCRA[SLOT].

So add a new flag which only indicates whether MMCRA[SLOT] exists.

Naively we'd set it on everything except power6/7, because they set
ALT_SIPR, and we've reversed the polarity of the flag. But it's more
complicated than that.

mpc7450 is 32-bit, and uses its own version of perf_ip_adjust()
which doesn't use MMCRA[SLOT], so it doesn't need the new flag set and
the behaviour is unchanged.

PPC970 (and I assume power4) don't have MMCRA[SLOT], so shouldn't have
the new flag set. This is a behaviour change on those cpus, though we
were probably getting lucky and the bits in question were 0.

power5 and power5+ set the new flag, behaviour unchanged.

power6 & power7 do not set the new flag, behaviour unchanged.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/include/asm/perf_event_server.h |    1 +
 arch/powerpc/perf/core-book3s.c              |    3 ++-
 arch/powerpc/perf/power5+-pmu.c              |    2 +-
 arch/powerpc/perf/power5-pmu.c               |    1 +
 4 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/include/asm/perf_event_server.h b/arch/powerpc/include/asm/perf_event_server.h
index d0aec72..7074aec 100644
--- a/arch/powerpc/include/asm/perf_event_server.h
+++ b/arch/powerpc/include/asm/perf_event_server.h
@@ -52,6 +52,7 @@ struct power_pmu {
 #define PPMU_NO_SIPR		0x00000004 /* no SIPR/HV in MMCRA at all */
 #define PPMU_NO_CONT_SAMPLING	0x00000008 /* no continuous sampling */
 #define PPMU_SIAR_VALID		0x00000010 /* Processor has SIAR Valid bit */
+#define PPMU_HAS_SSLOT		0x00000020 /* Has sampled slot in MMCRA */
 
 /*
  * Values for flags to get_alternatives()
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 65362e9..eb64480 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -98,11 +98,12 @@ static inline unsigned long perf_ip_adjust(struct pt_regs *regs)
 {
 	unsigned long mmcra = regs->dsisr;
 
-	if ((mmcra & MMCRA_SAMPLE_ENABLE) && !(ppmu->flags & PPMU_ALT_SIPR)) {
+	if ((ppmu->flags & PPMU_HAS_SSLOT) && (mmcra & MMCRA_SAMPLE_ENABLE)) {
 		unsigned long slot = (mmcra & MMCRA_SLOT) >> MMCRA_SLOT_SHIFT;
 		if (slot > 1)
 			return 4 * (slot - 1);
 	}
+
 	return 0;
 }
 
diff --git a/arch/powerpc/perf/power5+-pmu.c b/arch/powerpc/perf/power5+-pmu.c
index a8757ba..b03b6dc 100644
--- a/arch/powerpc/perf/power5+-pmu.c
+++ b/arch/powerpc/perf/power5+-pmu.c
@@ -671,7 +671,7 @@ static struct power_pmu power5p_pmu = {
 	.get_alternatives	= power5p_get_alternatives,
 	.disable_pmc		= power5p_disable_pmc,
 	.limited_pmc_event	= power5p_limited_pmc_event,
-	.flags			= PPMU_LIMITED_PMC5_6,
+	.flags			= PPMU_LIMITED_PMC5_6 | PPMU_HAS_SSLOT,
 	.n_generic		= ARRAY_SIZE(power5p_generic_events),
 	.generic_events		= power5p_generic_events,
 	.cache_events		= &power5p_cache_events,
diff --git a/arch/powerpc/perf/power5-pmu.c b/arch/powerpc/perf/power5-pmu.c
index e7f06eb..1e8ce42 100644
--- a/arch/powerpc/perf/power5-pmu.c
+++ b/arch/powerpc/perf/power5-pmu.c
@@ -615,6 +615,7 @@ static struct power_pmu power5_pmu = {
 	.n_generic		= ARRAY_SIZE(power5_generic_events),
 	.generic_events		= power5_generic_events,
 	.cache_events		= &power5_cache_events,
+	.flags			= PPMU_HAS_SSLOT,
 };
 
 static int __init init_power5_pmu(void)
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 1/7] powerpc: Initialise PMU related regs on Power8
From: Michael Ellerman @ 2013-04-26  5:28 UTC (permalink / raw)
  To: linuxppc-dev

For both HV and guest kernels, intialise PMU regs to something sane.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/include/asm/reg.h        |    6 ++++++
 arch/powerpc/kernel/cpu_setup_power.S |   21 ++++++++++++++++++++-
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 4ae2d44..5735ebb 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -271,6 +271,7 @@
 #define SPRN_HFSCR	0xbe	/* HV=1 Facility Status & Control Register */
 #define   HFSCR_TAR	(1 << (63-55)) /* Enable Target Address Register */
 #define   HFSCR_TM	(1 << (63-58)) /* Enable Transactional Memory */
+#define   HFSCR_PM	(1 << (63-60)) /* Enable prob/priv access to PMU SPRs */
 #define   HFSCR_DSCR	(1 << (63-61)) /* Enable Data Stream Control Register */
 #define   HFSCR_VECVSX	(1 << (63-62)) /* Enable VMX/VSX  */
 #define   HFSCR_FP	(1 << (63-63)) /* Enable Floating Point */
@@ -637,6 +638,7 @@
 #define   MMCR0_FCWAIT	0x00000002UL /* freeze counter in WAIT state */
 #define   MMCR0_FCHV	0x00000001UL /* freeze conditions in hypervisor mode */
 #define SPRN_MMCR1	798
+#define SPRN_MMCR2	769
 #define SPRN_MMCRA	0x312
 #define   MMCRA_SDSYNC	0x80000000UL /* SDAR synced with SIAR */
 #define   MMCRA_SDAR_DCACHE_MISS 0x40000000UL
@@ -655,6 +657,10 @@
 #define   POWER7P_MMCRA_SIAR_VALID 0x10000000	/* P7+ SIAR contents valid */
 #define   POWER7P_MMCRA_SDAR_VALID 0x08000000	/* P7+ SDAR contents valid */
 
+#define SPRN_MMCRH	316	/* Hypervisor monitor mode control register */
+#define SPRN_MMCRS	894	/* Supervisor monitor mode control register */
+#define SPRN_MMCRC	851	/* Core monitor mode control register */
+
 #define SPRN_PMC1	787
 #define SPRN_PMC2	788
 #define SPRN_PMC3	789
diff --git a/arch/powerpc/kernel/cpu_setup_power.S b/arch/powerpc/kernel/cpu_setup_power.S
index 2e6ad11..02a6945 100644
--- a/arch/powerpc/kernel/cpu_setup_power.S
+++ b/arch/powerpc/kernel/cpu_setup_power.S
@@ -49,6 +49,7 @@ _GLOBAL(__restore_cpu_power7)
 _GLOBAL(__setup_cpu_power8)
 	mflr	r11
 	bl	__init_FSCR
+	bl	__init_PMU
 	bl	__init_hvmode_206
 	mtlr	r11
 	beqlr
@@ -59,12 +60,14 @@ _GLOBAL(__setup_cpu_power8)
 	bl	__init_LPCR
 	bl	__init_HFSCR
 	bl	__init_TLB
+	bl	__init_PMU_HV
 	mtlr	r11
 	blr
 
 _GLOBAL(__restore_cpu_power8)
 	mflr	r11
 	bl	__init_FSCR
+	bl	__init_PMU
 	mfmsr	r3
 	rldicl.	r0,r3,4,63
 	beqlr
@@ -75,6 +78,7 @@ _GLOBAL(__restore_cpu_power8)
 	bl	__init_LPCR
 	bl	__init_HFSCR
 	bl	__init_TLB
+	bl	__init_PMU_HV
 	mtlr	r11
 	blr
 
@@ -124,7 +128,7 @@ __init_FSCR:
 
 __init_HFSCR:
 	mfspr	r3,SPRN_HFSCR
-	ori	r3,r3,HFSCR_TAR|HFSCR_TM|HFSCR_DSCR|HFSCR_VECVSX|HFSCR_FP
+	ori	r3,r3,HFSCR_TAR|HFSCR_TM|HFSCR_DSCR|HFSCR_VECVSX|HFSCR_FP|HFSCR_PM
 	mtspr	SPRN_HFSCR,r3
 	blr
 
@@ -139,3 +143,18 @@ __init_TLB:
 	bdnz	2b
 	ptesync
 1:	blr
+
+__init_PMU_HV:
+	li	r5,0
+	mtspr	SPRN_MMCRC,r5
+	mtspr	SPRN_MMCRH,r5
+	blr
+
+__init_PMU:
+	li	r5,0
+	mtspr	SPRN_MMCRS,r5
+	mtspr	SPRN_MMCRA,r5
+	mtspr	SPRN_MMCR0,r5
+	mtspr	SPRN_MMCR1,r5
+	mtspr	SPRN_MMCR2,r5
+	blr
-- 
1.7.10.4

^ 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