LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] DT: add MDIO node for FMan node
From: Scott Wood @ 2014-11-11 17:37 UTC (permalink / raw)
  To: Xie Shaohui-B21989
  Cc: Liberman Igal-B31950, linuxppc-dev@lists.ozlabs.org,
	Medve Emilian-EMMEDVE1, devicetree@vger.kernel.org
In-Reply-To: <fb6dc6131da04e89bfc31bd8278030a0@DM2PR0301MB0864.namprd03.prod.outlook.com>

On Tue, 2014-11-11 at 04:32 -0600, Xie Shaohui-B21989 wrote:
> > -----Original Message-----
> > From: Wood Scott-B07421
> > Sent: Tuesday, November 11, 2014 8:23 AM
> > To: shh.xie@gmail.com
> > Cc: linuxppc-dev@lists.ozlabs.org; devicetree@vger.kernel.org; Medve
> > Emilian-EMMEDVE1; Xie Shaohui-B21989
> > Subject: Re: [PATCH] DT: add MDIO node for FMan node
> > 
> > On Tue, 2014-11-04 at 19:56 +0800, shh.xie@gmail.com wrote:
> > > From: Shaohui Xie <Shaohui.Xie@freescale.com>
> > >
> > > This binding is for FMan MDIO, it covers FMan v2 & FMan v3.
> > >
> > > Signed-off-by: Shaohui Xie <Shaohui.Xie@freescale.com>
> > > ---
> > > based on http://patchwork.ozlabs.org/patch/390351/
> > > for 'next' of
> > > git://git.kernel.org/pub/scm/linux/kernel/git/scottwood/linux.git
> > 
> > Are there any other FMan pieces that are missing from the above patch?
> [S.H] I'm adding Igal for this comment.
> 
> > 
> > >  .../devicetree/bindings/powerpc/fsl/fman.txt       | 69
> > ++++++++++++++++++++++
> > >  1 file changed, 69 insertions(+)
> > >
> > > diff --git a/Documentation/devicetree/bindings/powerpc/fsl/fman.txt
> > > b/Documentation/devicetree/bindings/powerpc/fsl/fman.txt
> > > index da8e5f2..83c2f14 100644
> > > --- a/Documentation/devicetree/bindings/powerpc/fsl/fman.txt
> > > +++ b/Documentation/devicetree/bindings/powerpc/fsl/fman.txt
> > > @@ -7,6 +7,7 @@ CONTENTS
> > >    - FMan MURAM Node
> > >    - FMan dTSEC/XGEC/mEMAC Node
> > >    - FMan IEEE 1588 Node
> > > +  - FMan MDIO Node
> > >    - Example
> > >
> > >
> > > ======================================================================
> > > ======= @@ -352,6 +353,67 @@ ptp-timer@fe000 {  };
> > >
> > >
> > > ======================================================================
> > > =======
> > > +FMan MDIO Node
> > > +
> > > +DESCRIPTION
> > > +
> > > +The MDIO is a bus to which the PHY devices are connected.
> > > +
> > > +PROPERTIES
> > > +
> > > +- compatible
> > > +		Usage: required
> > > +		Value type: <stringlist>
> > > +		Definition: A standard property.
> > > +		Must include "fsl,fman-mdio" for 1 Gb/s MDIO from FMan v2.
> > > +		Must include "fsl,fman-xmdio" for 10 Gb/s MDIO from FMan v2.
> > > +		Must include "fsl,fman-memac-mdio" for 1/10 Gb/s MDIO from
> > > +		FMan v3.
> > > +
> > > +- reg
> > > +		Usage: required
> > > +		Value type: <prop-encoded-array>
> > > +		Definition: A standard property.
> > > +
> > > +- bus-frequency
> > > +		Usage: optional
> > > +		Value type: <u32>
> > > +		Definition: Default MDIO bus clock speed.
> > 
> > Use clocks/clock-names
> [S.H] The MDIO uses Fman clock and divides it to a proper value which is specified by this property.

Use clocks/clock-names to describe that relationship.

> > 
> > > +- interrupts
> > > +		Usage: optional
> > > +		Value type: <prop-encoded-array>
> > > +		Definition: MDIO controller event interrupts.
> > 
> > One interrupt or multiple?
> [S.H] One for 1 Gb/s, one for 10 Gb/s.

Then the binding needs to say that there are two (except for
"fsl,fman-mdio", right?) and which is which.

> > 
> > > +
> > > +- type
> > > +		Usage: required for FMan v3
> > > +		Value type: <stringlist>
> > > +		Definition: A standard property.
> > 
> > What standard is "type" defined in?
>
> [S.H] It's to differentiate between the internal and external MDIO, I'm
> not quite sure about naming it, or what could be better way to
> differentiate the MDIOs?

I'm not questioning the need to convey this information.  I'm saying
it's not "A standard property".  I'd also like to see a better name.

> > 
> > > +		FMan v3 has internal MDIO for internal PCS(Physical Coding
> > > +		Sublayer) PHYs and external MDIO for external PHYs.
> > > +		The settings and programming routines for internal/external
> > > +		MDIO are different. Must include "internal" for internal MDIO,
> > > +		must include "external" for external MDIO.
> > 
> > I assume fman v2 is always internal?  How about a boolean "fsl,fman-
> > internal-phy" property instead?
> [S.H] Both Fman v2 & v3 have internal/external MDIO, Fman v2 uses internal MDIO for TBI operations to set the SGMII PHY, 
>
> The TBI implements transmit/receive portions of PCS, it's not used in
> Linux. The PCS on Fman V3 are not just for SGMII, it has more
> implementations, it's used in Linux.

The device tree is about the hardware, not what's used in Linux.

-Scott

^ permalink raw reply

* RE: [PATCH] DT: add MDIO node for FMan node
From: Shaohui Xie @ 2014-11-11 10:32 UTC (permalink / raw)
  To: Scott Wood, Igal.Liberman@freescale.com
  Cc: devicetree@vger.kernel.org, linuxppc-dev@lists.ozlabs.org,
	Emilian Medve
In-Reply-To: <1415665384.15957.16.camel@freescale.com>

PiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiBGcm9tOiBXb29kIFNjb3R0LUIwNzQyMQ0K
PiBTZW50OiBUdWVzZGF5LCBOb3ZlbWJlciAxMSwgMjAxNCA4OjIzIEFNDQo+IFRvOiBzaGgueGll
QGdtYWlsLmNvbQ0KPiBDYzogbGludXhwcGMtZGV2QGxpc3RzLm96bGFicy5vcmc7IGRldmljZXRy
ZWVAdmdlci5rZXJuZWwub3JnOyBNZWR2ZQ0KPiBFbWlsaWFuLUVNTUVEVkUxOyBYaWUgU2hhb2h1
aS1CMjE5ODkNCj4gU3ViamVjdDogUmU6IFtQQVRDSF0gRFQ6IGFkZCBNRElPIG5vZGUgZm9yIEZN
YW4gbm9kZQ0KPiANCj4gT24gVHVlLCAyMDE0LTExLTA0IGF0IDE5OjU2ICswODAwLCBzaGgueGll
QGdtYWlsLmNvbSB3cm90ZToNCj4gPiBGcm9tOiBTaGFvaHVpIFhpZSA8U2hhb2h1aS5YaWVAZnJl
ZXNjYWxlLmNvbT4NCj4gPg0KPiA+IFRoaXMgYmluZGluZyBpcyBmb3IgRk1hbiBNRElPLCBpdCBj
b3ZlcnMgRk1hbiB2MiAmIEZNYW4gdjMuDQo+ID4NCj4gPiBTaWduZWQtb2ZmLWJ5OiBTaGFvaHVp
IFhpZSA8U2hhb2h1aS5YaWVAZnJlZXNjYWxlLmNvbT4NCj4gPiAtLS0NCj4gPiBiYXNlZCBvbiBo
dHRwOi8vcGF0Y2h3b3JrLm96bGFicy5vcmcvcGF0Y2gvMzkwMzUxLw0KPiA+IGZvciAnbmV4dCcg
b2YNCj4gPiBnaXQ6Ly9naXQua2VybmVsLm9yZy9wdWIvc2NtL2xpbnV4L2tlcm5lbC9naXQvc2Nv
dHR3b29kL2xpbnV4LmdpdA0KPiANCj4gQXJlIHRoZXJlIGFueSBvdGhlciBGTWFuIHBpZWNlcyB0
aGF0IGFyZSBtaXNzaW5nIGZyb20gdGhlIGFib3ZlIHBhdGNoPw0KW1MuSF0gSSdtIGFkZGluZyBJ
Z2FsIGZvciB0aGlzIGNvbW1lbnQuDQoNCj4gDQo+ID4gIC4uLi9kZXZpY2V0cmVlL2JpbmRpbmdz
L3Bvd2VycGMvZnNsL2ZtYW4udHh0ICAgICAgIHwgNjkNCj4gKysrKysrKysrKysrKysrKysrKysr
Kw0KPiA+ICAxIGZpbGUgY2hhbmdlZCwgNjkgaW5zZXJ0aW9ucygrKQ0KPiA+DQo+ID4gZGlmZiAt
LWdpdCBhL0RvY3VtZW50YXRpb24vZGV2aWNldHJlZS9iaW5kaW5ncy9wb3dlcnBjL2ZzbC9mbWFu
LnR4dA0KPiA+IGIvRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdzL3Bvd2VycGMvZnNs
L2ZtYW4udHh0DQo+ID4gaW5kZXggZGE4ZTVmMi4uODNjMmYxNCAxMDA2NDQNCj4gPiAtLS0gYS9E
b2N1bWVudGF0aW9uL2RldmljZXRyZWUvYmluZGluZ3MvcG93ZXJwYy9mc2wvZm1hbi50eHQNCj4g
PiArKysgYi9Eb2N1bWVudGF0aW9uL2RldmljZXRyZWUvYmluZGluZ3MvcG93ZXJwYy9mc2wvZm1h
bi50eHQNCj4gPiBAQCAtNyw2ICs3LDcgQEAgQ09OVEVOVFMNCj4gPiAgICAtIEZNYW4gTVVSQU0g
Tm9kZQ0KPiA+ICAgIC0gRk1hbiBkVFNFQy9YR0VDL21FTUFDIE5vZGUNCj4gPiAgICAtIEZNYW4g
SUVFRSAxNTg4IE5vZGUNCj4gPiArICAtIEZNYW4gTURJTyBOb2RlDQo+ID4gICAgLSBFeGFtcGxl
DQo+ID4NCj4gPg0KPiA+ID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09
PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCj4gPiA9PT09PT09IEBAIC0zNTIsNiArMzUz
LDY3IEBAIHB0cC10aW1lckBmZTAwMCB7ICB9Ow0KPiA+DQo+ID4NCj4gPiA9PT09PT09PT09PT09
PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09
DQo+ID4gPT09PT09PQ0KPiA+ICtGTWFuIE1ESU8gTm9kZQ0KPiA+ICsNCj4gPiArREVTQ1JJUFRJ
T04NCj4gPiArDQo+ID4gK1RoZSBNRElPIGlzIGEgYnVzIHRvIHdoaWNoIHRoZSBQSFkgZGV2aWNl
cyBhcmUgY29ubmVjdGVkLg0KPiA+ICsNCj4gPiArUFJPUEVSVElFUw0KPiA+ICsNCj4gPiArLSBj
b21wYXRpYmxlDQo+ID4gKwkJVXNhZ2U6IHJlcXVpcmVkDQo+ID4gKwkJVmFsdWUgdHlwZTogPHN0
cmluZ2xpc3Q+DQo+ID4gKwkJRGVmaW5pdGlvbjogQSBzdGFuZGFyZCBwcm9wZXJ0eS4NCj4gPiAr
CQlNdXN0IGluY2x1ZGUgImZzbCxmbWFuLW1kaW8iIGZvciAxIEdiL3MgTURJTyBmcm9tIEZNYW4g
djIuDQo+ID4gKwkJTXVzdCBpbmNsdWRlICJmc2wsZm1hbi14bWRpbyIgZm9yIDEwIEdiL3MgTURJ
TyBmcm9tIEZNYW4gdjIuDQo+ID4gKwkJTXVzdCBpbmNsdWRlICJmc2wsZm1hbi1tZW1hYy1tZGlv
IiBmb3IgMS8xMCBHYi9zIE1ESU8gZnJvbQ0KPiA+ICsJCUZNYW4gdjMuDQo+ID4gKw0KPiA+ICst
IHJlZw0KPiA+ICsJCVVzYWdlOiByZXF1aXJlZA0KPiA+ICsJCVZhbHVlIHR5cGU6IDxwcm9wLWVu
Y29kZWQtYXJyYXk+DQo+ID4gKwkJRGVmaW5pdGlvbjogQSBzdGFuZGFyZCBwcm9wZXJ0eS4NCj4g
PiArDQo+ID4gKy0gYnVzLWZyZXF1ZW5jeQ0KPiA+ICsJCVVzYWdlOiBvcHRpb25hbA0KPiA+ICsJ
CVZhbHVlIHR5cGU6IDx1MzI+DQo+ID4gKwkJRGVmaW5pdGlvbjogRGVmYXVsdCBNRElPIGJ1cyBj
bG9jayBzcGVlZC4NCj4gDQo+IFVzZSBjbG9ja3MvY2xvY2stbmFtZXMNCltTLkhdIFRoZSBNRElP
IHVzZXMgRm1hbiBjbG9jayBhbmQgZGl2aWRlcyBpdCB0byBhIHByb3BlciB2YWx1ZSB3aGljaCBp
cyBzcGVjaWZpZWQgYnkgdGhpcyBwcm9wZXJ0eS4NCg0KPiANCj4gPiArLSBpbnRlcnJ1cHRzDQo+
ID4gKwkJVXNhZ2U6IG9wdGlvbmFsDQo+ID4gKwkJVmFsdWUgdHlwZTogPHByb3AtZW5jb2RlZC1h
cnJheT4NCj4gPiArCQlEZWZpbml0aW9uOiBNRElPIGNvbnRyb2xsZXIgZXZlbnQgaW50ZXJydXB0
cy4NCj4gDQo+IE9uZSBpbnRlcnJ1cHQgb3IgbXVsdGlwbGU/DQpbUy5IXSBPbmUgZm9yIDEgR2Iv
cywgb25lIGZvciAxMCBHYi9zLg0KDQo+IA0KPiA+ICsNCj4gPiArLSB0eXBlDQo+ID4gKwkJVXNh
Z2U6IHJlcXVpcmVkIGZvciBGTWFuIHYzDQo+ID4gKwkJVmFsdWUgdHlwZTogPHN0cmluZ2xpc3Q+
DQo+ID4gKwkJRGVmaW5pdGlvbjogQSBzdGFuZGFyZCBwcm9wZXJ0eS4NCj4gDQo+IFdoYXQgc3Rh
bmRhcmQgaXMgInR5cGUiIGRlZmluZWQgaW4/DQpbUy5IXSBJdCdzIHRvIGRpZmZlcmVudGlhdGUg
YmV0d2VlbiB0aGUgaW50ZXJuYWwgYW5kIGV4dGVybmFsIE1ESU8sIEknbSBub3QgcXVpdGUgc3Vy
ZSBhYm91dCBuYW1pbmcgaXQsIG9yIHdoYXQgY291bGQgYmUgYmV0dGVyIHdheSB0byBkaWZmZXJl
bnRpYXRlIHRoZSBNRElPcz8NCg0KPiANCj4gPiArCQlGTWFuIHYzIGhhcyBpbnRlcm5hbCBNRElP
IGZvciBpbnRlcm5hbCBQQ1MoUGh5c2ljYWwgQ29kaW5nDQo+ID4gKwkJU3VibGF5ZXIpIFBIWXMg
YW5kIGV4dGVybmFsIE1ESU8gZm9yIGV4dGVybmFsIFBIWXMuDQo+ID4gKwkJVGhlIHNldHRpbmdz
IGFuZCBwcm9ncmFtbWluZyByb3V0aW5lcyBmb3IgaW50ZXJuYWwvZXh0ZXJuYWwNCj4gPiArCQlN
RElPIGFyZSBkaWZmZXJlbnQuIE11c3QgaW5jbHVkZSAiaW50ZXJuYWwiIGZvciBpbnRlcm5hbCBN
RElPLA0KPiA+ICsJCW11c3QgaW5jbHVkZSAiZXh0ZXJuYWwiIGZvciBleHRlcm5hbCBNRElPLg0K
PiANCj4gSSBhc3N1bWUgZm1hbiB2MiBpcyBhbHdheXMgaW50ZXJuYWw/ICBIb3cgYWJvdXQgYSBi
b29sZWFuICJmc2wsZm1hbi0NCj4gaW50ZXJuYWwtcGh5IiBwcm9wZXJ0eSBpbnN0ZWFkPw0KW1Mu
SF0gQm90aCBGbWFuIHYyICYgdjMgaGF2ZSBpbnRlcm5hbC9leHRlcm5hbCBNRElPLCBGbWFuIHYy
IHVzZXMgaW50ZXJuYWwgTURJTyBmb3IgVEJJIG9wZXJhdGlvbnMgdG8gc2V0IHRoZSBTR01JSSBQ
SFksIA0KVGhlIFRCSSBpbXBsZW1lbnRzIHRyYW5zbWl0L3JlY2VpdmUgcG9ydGlvbnMgb2YgUENT
LCBpdCdzIG5vdCB1c2VkIGluIExpbnV4LiBUaGUgUENTIG9uIEZtYW4gVjMgYXJlIG5vdCBqdXN0
IGZvciBTR01JSSwgaXQgaGFzIG1vcmUgaW1wbGVtZW50YXRpb25zLCBpdCdzIHVzZWQgaW4gTGlu
dXguDQoNCj4gDQo+ID4gKw0KPiA+ICtFWEFNUExFDQo+ID4gKw0KPiA+ICtFeGFtcGxlIGZvciBG
TWFuIHYyOg0KPiA+ICsNCj4gPiArbWRpb0BmMTAwMCB7DQo+ID4gKwljb21wYXRpYmxlID0gImZz
bCxmbWFuLXhtZGlvIjsNCj4gPiArCXJlZyA9IDwweGYxMDAwIDB4MTAwMD47DQo+ID4gK307DQo+
ID4gKw0KPiA+ICtFeGFtcGxlIGZvciBGTWFuIHYzOg0KPiA+ICsNCj4gPiArbWRpb0BmZDAwMCB7
DQo+ID4gKwljb21wYXRpYmxlID0gImZzbCxmbWFuLW1lbWFjLW1kaW8iOw0KPiA+ICsJcmVnID0g
PDB4ZmQwMDAgMHgxMDAwPjsNCj4gPiArCWJ1cy1mcmVxdWVuY3kgPSA8MjUwMDAwMD47DQo+ID4g
Kwl0eXBlID0gImV4dGVybmFsIjsNCj4gPiArfTsNCj4gPiArDQo+ID4gKz09PT09PT09PT09PT09
PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0K
PiA+ICs9PT09PT09PQ0KPiA+ICBFeGFtcGxlDQo+ID4NCj4gPiAgZm1hbkA0MDAwMDAgew0KPiA+
IEBAIC01MjYsNCArNTg4LDExIEBAIGZtYW5ANDAwMDAwIHsNCj4gPiAgCQljb21wYXRpYmxlID0g
ImZzbCxmbWFuLXB0cC10aW1lciI7DQo+ID4gIAkJcmVnID0gPDB4ZmUwMDAgMHgxMDAwPjsNCj4g
PiAgCX07DQo+ID4gKw0KPiA+ICsJbWRpb0BmZDAwMCB7DQo+ID4gKwkJY29tcGF0aWJsZSA9ICJm
c2wsZm1hbi1tZW1hYy1tZGlvIjsNCj4gPiArCQlyZWcgPSA8MHhmZDAwMCAweDEwMDA+Ow0KPiA+
ICsJCWJ1cy1mcmVxdWVuY3kgPSA8MjUwMDAwMD47DQo+ID4gKwkJdHlwZSA9ICJleHRlcm5hbCI7
DQo+ID4gKwl9Ow0KPiA+ICB9Ow0KPiANCj4gVGhlIHJlc3Qgb2YgdGhlIGV4YW1wbGUgaXMgZm1h
biB2MjsgZG9uJ3QgbWl4IGFuIGZtYW4gdjMgbm9kZSBpbiB3aXRoDQo+IHRoYXQuDQpbUy5IXSBP
Sy4gV2lsbCBmaXggaXQuDQoNClRoYW5rcyENClNoYW9odWkNCiANCg0K

^ permalink raw reply

* Re: [PATCH v6 41/48] powerpc: Register with kernel power-off handler
From: Guenter Roeck @ 2014-11-11 10:42 UTC (permalink / raw)
  To: Michael Ellerman
  Cc: linuxppc-dev list, Alexander Graf, linux-kernel, linux-pm
In-Reply-To: <1415691766.9757.1.camel@concordia>

On 11/10/2014 11:42 PM, Michael Ellerman wrote:
> On Sun, 2014-11-09 at 17:42 -0800, Guenter Roeck wrote:
>> Register with kernel power-off handler instead of setting pm_power_off
>> directly.
>>
>> If there is an indication that there can be more than one power-off handler,
>> use register_power_off_handler, otherwise use register_power_off_handler_simple
>> to register the power-off handler.
>>
>> If the power-off handler only resets or stops the system, select the fallback
>> priority to indicate that the power-off handler is one of last resort.
>> If the power-off handler powers off the system, select the default priority,
>> unless the power-off handler installation code suggests that there can be
>> more than one power-off handler and the new handler is only installed
>> conditionally. In this case, install the handler with low priority.
>>
>> Cc: Alexander Graf <agraf@suse.de>
>> Cc: Michael Ellerman <mpe@ellerman.id.au>
>> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
>
> Can you fold in the patch below. I know pm.h is included by device.h, so most
> things will already have it, but I'd rather be explicit.
>
> With that you can add my:
>
> Acked-by: Michael Ellerman <mpe@ellerman.id.au>
>

Done.

Thanks,
Guenter

^ permalink raw reply

* Re: [PATCH v6 41/48] powerpc: Register with kernel power-off handler
From: Michael Ellerman @ 2014-11-11  7:42 UTC (permalink / raw)
  To: Guenter Roeck; +Cc: linuxppc-dev list, Alexander Graf, linux-kernel, linux-pm
In-Reply-To: <1415583785-6980-42-git-send-email-linux@roeck-us.net>

On Sun, 2014-11-09 at 17:42 -0800, Guenter Roeck wrote:
> Register with kernel power-off handler instead of setting pm_power_off
> directly.
> 
> If there is an indication that there can be more than one power-off handler,
> use register_power_off_handler, otherwise use register_power_off_handler_simple
> to register the power-off handler.
> 
> If the power-off handler only resets or stops the system, select the fallback
> priority to indicate that the power-off handler is one of last resort.
> If the power-off handler powers off the system, select the default priority,
> unless the power-off handler installation code suggests that there can be
> more than one power-off handler and the new handler is only installed
> conditionally. In this case, install the handler with low priority.
> 
> Cc: Alexander Graf <agraf@suse.de>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Signed-off-by: Guenter Roeck <linux@roeck-us.net>

Can you fold in the patch below. I know pm.h is included by device.h, so most
things will already have it, but I'd rather be explicit.

With that you can add my:

Acked-by: Michael Ellerman <mpe@ellerman.id.au>

cheers



diff --git a/arch/powerpc/platforms/44x/ppc476.c b/arch/powerpc/platforms/44x/ppc476.c
index 590d31fbbfc0..adbf36d8c5d9 100644
--- a/arch/powerpc/platforms/44x/ppc476.c
+++ b/arch/powerpc/platforms/44x/ppc476.c
@@ -24,6 +24,7 @@
 #include <linux/init.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
+#include <linux/pm.h>
 #include <linux/rtc.h>
 
 #include <asm/machdep.h>
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c
index 321a7a76eb80..7bdf4e8f7b99 100644
--- a/arch/powerpc/platforms/52xx/efika.c
+++ b/arch/powerpc/platforms/52xx/efika.c
@@ -13,6 +13,7 @@
 #include <generated/utsrelease.h>
 #include <linux/pci.h>
 #include <linux/of.h>
+#include <linux/pm.h>
 #include <asm/dma.h>
 #include <asm/prom.h>
 #include <asm/time.h>
diff --git a/arch/powerpc/platforms/85xx/corenet_generic.c b/arch/powerpc/platforms/85xx/corenet_generic.c
index f0c4b5106103..4892491969ab 100644
--- a/arch/powerpc/platforms/85xx/corenet_generic.c
+++ b/arch/powerpc/platforms/85xx/corenet_generic.c
@@ -16,6 +16,7 @@
 #include <linux/kdev_t.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/pm.h>
 
 #include <asm/time.h>
 #include <asm/machdep.h>
diff --git a/arch/powerpc/platforms/cell/celleb_setup.c b/arch/powerpc/platforms/cell/celleb_setup.c
index e301b1ae9c2d..1e14047f98d6 100644
--- a/arch/powerpc/platforms/cell/celleb_setup.c
+++ b/arch/powerpc/platforms/cell/celleb_setup.c
@@ -42,6 +42,7 @@
 #include <linux/root_dev.h>
 #include <linux/console.h>
 #include <linux/of_platform.h>
+#include <linux/pm.h>
 
 #include <asm/mmu.h>
 #include <asm/processor.h>
diff --git a/arch/powerpc/platforms/cell/qpace_setup.c b/arch/powerpc/platforms/cell/qpace_setup.c
index 223d40a73130..429fefd30e4e 100644
--- a/arch/powerpc/platforms/cell/qpace_setup.c
+++ b/arch/powerpc/platforms/cell/qpace_setup.c
@@ -22,6 +22,7 @@
 #include <linux/irq.h>
 #include <linux/console.h>
 #include <linux/of_platform.h>
+#include <linux/pm.h>
 
 #include <asm/mmu.h>
 #include <asm/processor.h>
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index ea5460c0b8e7..1203a9d6cd53 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -31,6 +31,7 @@
 #include <linux/mutex.h>
 #include <linux/memory_hotplug.h>
 #include <linux/of_platform.h>
+#include <linux/pm.h>
 
 #include <asm/mmu.h>
 #include <asm/processor.h>
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 0c0288ed0c3b..910bd8b45fae 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -31,6 +31,7 @@
 #include <linux/root_dev.h>
 #include <linux/initrd.h>
 #include <linux/timer.h>
+#include <linux/pm.h>
 
 #include <asm/io.h>
 #include <asm/pgtable.h>
diff --git a/arch/powerpc/platforms/embedded6xx/gamecube.c b/arch/powerpc/platforms/embedded6xx/gamecube.c
index af40f0fc2579..c90caff045bb 100644
--- a/arch/powerpc/platforms/embedded6xx/gamecube.c
+++ b/arch/powerpc/platforms/embedded6xx/gamecube.c
@@ -18,6 +18,7 @@
 #include <linux/kexec.h>
 #include <linux/seq_file.h>
 #include <linux/of_platform.h>
+#include <linux/pm.h>
 
 #include <asm/io.h>
 #include <asm/machdep.h>
diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c
index 0c4dcf86fc7b..e1aec530f0ad 100644
--- a/arch/powerpc/platforms/embedded6xx/linkstation.c
+++ b/arch/powerpc/platforms/embedded6xx/linkstation.c
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/initrd.h>
 #include <linux/of_platform.h>
+#include <linux/pm.h>
 
 #include <asm/time.h>
 #include <asm/prom.h>
diff --git a/arch/powerpc/platforms/embedded6xx/wii.c b/arch/powerpc/platforms/embedded6xx/wii.c
index eea88245a9de..8c93b95bcc29 100644
--- a/arch/powerpc/platforms/embedded6xx/wii.c
+++ b/arch/powerpc/platforms/embedded6xx/wii.c
@@ -20,6 +20,7 @@
 #include <linux/seq_file.h>
 #include <linux/of_platform.h>
 #include <linux/memblock.h>
+#include <linux/pm.h>
 #include <mm/mmu_decl.h>
 
 #include <asm/io.h>
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index 73c3988202d8..962e4968d967 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -43,6 +43,7 @@
 #include <linux/bitops.h>
 #include <linux/of_device.h>
 #include <linux/memblock.h>
+#include <linux/pm.h>
 
 #include <asm/processor.h>
 #include <asm/sections.h>
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 6496ae41a51d..52f2e965200a 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -53,6 +53,7 @@
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
 #include <linux/memblock.h>
+#include <linux/pm.h>
 
 #include <asm/reg.h>
 #include <asm/sections.h>
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
index a03c41bcfed1..9b124ddcddf5 100644
--- a/arch/powerpc/platforms/powernv/setup.c
+++ b/arch/powerpc/platforms/powernv/setup.c
@@ -28,6 +28,7 @@
 #include <linux/bug.h>
 #include <linux/pci.h>
 #include <linux/cpufreq.h>
+#include <linux/pm.h>
 
 #include <asm/machdep.h>
 #include <asm/firmware.h>
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c
index 77e0dea2590b..63ed88e25f3e 100644
--- a/arch/powerpc/platforms/ps3/setup.c
+++ b/arch/powerpc/platforms/ps3/setup.c
@@ -25,6 +25,7 @@
 #include <linux/console.h>
 #include <linux/export.h>
 #include <linux/bootmem.h>
+#include <linux/pm.h>
 
 #include <asm/machdep.h>
 #include <asm/firmware.h>
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index b3c85bb90e34..d5c944e42612 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -41,6 +41,7 @@
 #include <linux/root_dev.h>
 #include <linux/of.h>
 #include <linux/kexec.h>
+#include <linux/pm.h>
 
 #include <asm/mmu.h>
 #include <asm/processor.h>

^ permalink raw reply related

* [PATCH V4 3/8] powerpc, process: Merge functions __switch_to_tm and tm_reclaim_task
From: Anshuman Khandual @ 2014-11-11  5:26 UTC (permalink / raw)
  To: linux-kernel, linuxppc-dev
  Cc: mikey, james.hogan, avagin, Paul.Clothier, peterz, palves, oleg,
	davem, dhowells, davej, akpm, sukadev, tglx, sam.bobroff
In-Reply-To: <1415683597-22819-1-git-send-email-khandual@linux.vnet.ibm.com>

The function tm_reclaim_task is only called from the function
 __switch_to_tm. This patch merges these two functions to make
it more readable without changing the functionality in any way.

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 arch/powerpc/kernel/process.c | 20 ++++++++------------
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index c36477b..99b41ed 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -585,6 +585,10 @@ static inline void tm_reclaim_task(struct task_struct *tsk)
 	 */
 	struct thread_struct *thr = &tsk->thread;
 
+	if (!cpu_has_feature(CPU_FTR_TM))
+		return;
+	tm_enable();
+
 	if (!thr->regs)
 		return;
 
@@ -696,14 +700,6 @@ static inline void tm_recheckpoint_new_task(struct task_struct *new)
 		 new->pid, mfmsr());
 }
 
-static inline void __switch_to_tm(struct task_struct *prev)
-{
-	if (cpu_has_feature(CPU_FTR_TM)) {
-		tm_enable();
-		tm_reclaim_task(prev);
-	}
-}
-
 /*
  * This is called if we are on the way out to userspace and the
  * TIF_RESTORE_TM flag is set.  It checks if we need to reload
@@ -742,13 +738,13 @@ void restore_tm_state(struct pt_regs *regs)
 
 #else
 #define tm_recheckpoint_new_task(new)
-#define __switch_to_tm(prev)
+#define tm_reclaim_task(prev)
 #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
 
 /*
  * flush_tm_state
  *
- * Flush TM state out so we can copy it.  __switch_to_tm() does this
+ * Flush TM state out so we can copy it.  tm_reclaim_task() does this
  * flush but it removes the checkpointed state from the current CPU and
  * transitions the CPU out of TM mode.  Hence we need to call
  * tm_recheckpoint_new_task() (on the same task) to restore the
@@ -756,7 +752,7 @@ void restore_tm_state(struct pt_regs *regs)
  */
 static void flush_tm_state(struct task_struct *src)
 {
-	__switch_to_tm(src);
+	tm_reclaim_task(src);
 	tm_recheckpoint_new_task(src);
 }
 
@@ -805,7 +801,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
 	 */
 	save_early_sprs(&prev->thread);
 
-	__switch_to_tm(prev);
+	tm_reclaim_task(prev);
 
 #ifdef CONFIG_SMP
 	/* avoid complexity of lazy save/restore of fpu
-- 
1.9.3

^ permalink raw reply related

* [PATCH V4 8/8] selftests, powerpc: Add new test case for TM related ptrace interfaces
From: Anshuman Khandual @ 2014-11-11  5:26 UTC (permalink / raw)
  To: linux-kernel, linuxppc-dev
  Cc: mikey, james.hogan, avagin, Paul.Clothier, peterz, palves, oleg,
	davem, dhowells, davej, akpm, sukadev, tglx, sam.bobroff
In-Reply-To: <1415683597-22819-1-git-send-email-khandual@linux.vnet.ibm.com>

This patch adds one more test case called tm-ptrace targeting TM
related ptrace interfaces. This test creates one child process to
run some basic transactions and the parent process attaches the
child to do some ptrace probing using the recently added regset
interfaces. The parent process then compares the received values
against the expected values to verify whether it passed the test
or not.

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 tools/testing/selftests/powerpc/tm/Makefile    |   2 +-
 tools/testing/selftests/powerpc/tm/tm-ptrace.c | 529 +++++++++++++++++++++++++
 2 files changed, 530 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/powerpc/tm/tm-ptrace.c

diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile
index 2cede23..71d400a 100644
--- a/tools/testing/selftests/powerpc/tm/Makefile
+++ b/tools/testing/selftests/powerpc/tm/Makefile
@@ -1,4 +1,4 @@
-PROGS := tm-resched-dscr
+PROGS := tm-resched-dscr tm-ptrace
 
 all: $(PROGS)
 
diff --git a/tools/testing/selftests/powerpc/tm/tm-ptrace.c b/tools/testing/selftests/powerpc/tm/tm-ptrace.c
new file mode 100644
index 0000000..858e77e
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-ptrace.c
@@ -0,0 +1,529 @@
+/*
+ * Test program for TM ptrace interface
+ *
+ * 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.
+ *
+ * Copyright 2014 IBM Corporation
+ *
+ * Author: Anshuman Khandual <khandual@linux.vnet.ibm.com>
+ */
+#include <inttypes.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <malloc.h>
+#include <errno.h>
+#include <sys/ptrace.h>
+#include <sys/uio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/signal.h>
+#include <sys/user.h>
+#include <linux/elf.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+
+#include "utils.h"
+
+#define MAX_OUTPUT 100
+
+/* ELF core notes */
+#define NT_PPC_TM_SPR  0x103	/* PowerPC TM special registers */
+#define NT_PPC_TM_CGPR 0x104	/* PowerpC TM checkpointed GPR */
+#define NT_PPC_TM_CFPR 0x105	/* PowerPC TM checkpointed FPR */
+#define NT_PPC_TM_CVMX 0x106	/* PowerPC TM checkpointed VMX */
+#define NT_PPC_MISC    0x107	/* PowerPC miscellaneous registers */
+
+/* TM instructions */
+#define TBEGIN		".long 0x7C00051D ;"
+#define TEND		".long 0x7C00055D ;"
+
+/* SPR number */
+#define SPRN_DSCR	3
+#define SPRN_TAR	815
+#define SPRN_PPR	896
+
+#define C_DSCR	10		/* TM checkpointed DSCR */
+#define C_TAR	20		/* TM checkpointed TAR */
+#define C_PPR	0x8000000000000	/* TM checkpointed PPR */
+
+#define DSCR	50		/* TM running DSCR */
+#define TAR	60		/* TM running TAR */
+#define PPR	0x4000000000000	/* TM running PPR */
+
+/* Values for GPR-FPR[0..31] */
+#define VAL0	0
+#define VAL1	1
+#define VAL2	2
+#define VAL3	3
+#define VAL4	4
+#define VAL5	5
+#define VAL6	6
+#define VAL7	7
+#define VAL8	8
+#define VAL9	9
+#define VAL10	10
+#define VAL11	11
+#define VAL12	12
+#define VAL13	13
+#define VAL14	14
+#define VAL15	15
+#define VAL_MAX	16
+
+/* Standard data types */
+typedef unsigned int u32;
+typedef __vector128 vector128;
+
+/* NT_PPC_TM_SPR buffer layout */
+struct tm_spr_regs {
+	u64	tm_tfhar;
+	u64	tm_texasr;
+	u64	tm_tfiar;
+	u64	tm_orig_msr;
+	u64	tm_tar;
+	u64	tm_ppr;
+	u64	tm_dscr;
+};
+
+/*
+ * NT_PPC_TM_CGPR buffer layout
+ *
+ * Same as that of struct pt_regs
+ */
+
+/* NT_PPC_TM_CFPR buffer layout */
+struct tm_cfpr {
+	u64	fpr[32];
+	u64	fpscr;
+};
+
+/* NT_PPC_TM_CVMX buffer layout */
+struct tm_cvmx {
+	vector128	vr[32] __attribute__((aligned(16)));
+	vector128	vscr __attribute__((aligned(16)));
+	u32		vrsave;
+};
+
+/* NT_PPC_MISC buffer layout */
+struct misc_regs {
+	u64	dscr;
+	u64	ppr;
+	u64	tar;
+};
+
+/*
+ * do_transaction
+ *
+ * This functions sets the values for TAR, DSCR, PPR, GPR[0..31],
+ * FPR[0..31] registers before starting the trasanction which will
+ * enable the kernel to save them as checkpointed values. Then it
+ * starts the transaction where it loads a different set of values
+ * into the same registers again thus enabling the kernel to save
+ * them off as running values for this transaction. Then the function
+ * gets stuck forcing the process to loop at one single instruction.
+ * The transaction never finishes, thus giving the parent process
+ * the opportunity to trace the running and checkpointed values of
+ * various registers.
+ */
+void do_transaction(void)
+{
+	asm __volatile__(
+		/* TM checkpointed values */
+
+		/* SPR */
+		"li 0, %[c_tar];"	/* TAR */
+		"mtspr %[sprn_tar], 0;"
+		"li 0, %[c_dscr];"	/* DSCR */
+		"mtspr %[sprn_dscr], 0;"
+		"or	1,1,1;"		/* PPR (0x8000000000000) */
+
+		/* GPR[0..31] */
+		"li 0, %[val0];"	/* GPR[0] */
+		"li 1, %[val1];"	/* GPR[1] */
+		"li 2, %[val2];"	/* GPR[2] */
+		"li 3, %[val3];"	/* GPR[3] */
+		"li 4, %[val4];"	/* GPR[4] */
+		"li 5, %[val5];"	/* GPR[5] */
+		"li 6, %[val6];"	/* GPR[6] */
+		"li 7, %[val7];"	/* GPR[7] */
+		"li 8, %[val8];"	/* GPR[8] */
+		"li 9, %[val9];"	/* GPR[9] */
+		"li 10, %[val10];"	/* GPR[10] */
+		"li 11, %[val11];"	/* GPR[11] */
+		"li 12, %[val12];"	/* GPR[12] */
+		"li 13, %[val13];"	/* GPR[13] */
+		"li 14, %[val14];"	/* GPR[14] */
+		"li 15, %[val15];"	/* GPR[15] */
+		"li 16, %[val0];"	/* GPR[16] */
+		"li 17, %[val1];"	/* GPR[17] */
+		"li 18, %[val2];"	/* GPR[18] */
+		"li 19, %[val3];"	/* GPR[19] */
+		"li 20, %[val4];"	/* GPR[20] */
+		"li 21, %[val5];"	/* GPR[21] */
+		"li 22, %[val6];"	/* GPR[22] */
+		"li 23, %[val7];"	/* GPR[23] */
+		"li 24, %[val8];"	/* GPR[24] */
+		"li 25, %[val9];"	/* GPR[25] */
+		"li 26, %[val10];"	/* GPR[26] */
+		"li 27, %[val11];"	/* GPR[27] */
+		"li 28, %[val12];"	/* GPR[28] */
+		"li 29, %[val13];"	/* GPR[29] */
+		"li 30, %[val14];"	/* GPR[30] */
+		"li 31, %[val15];"	/* GPR[31] */
+
+		/* FPR[0..31] */
+		".long 0x7C000166;"	/* GPR[0] --> FPR[0] */
+		".long 0x7C210166;"	/* GPR[1] --> FPR[1] */
+		".long 0x7C420166;"	/* GPR[0] --> FPR[2] */
+		".long 0x7C630166;"	/* GPR[3] --> FPR[3] */
+		".long 0x7C840166;"	/* GPR[4] --> FPR[4] */
+		".long 0x7CA50166;"	/* GPR[5] --> FPR[5] */
+		".long 0x7CC60166;"	/* GPR[6] --> FPR[6] */
+		".long 0x7CE70166;"	/* GPR[7] --> FPR[7] */
+		".long 0x7D080166;"	/* GPR[8] --> FPR[8] */
+		".long 0x7D290166;"	/* GPR[9] --> FPR[9] */
+		".long 0x7d4a0166;"	/* GPR[10] --> FPR[10] */
+		".long 0x7d6b0166;"	/* GPR[11] --> FPR[11] */
+		".long 0x7d8c0166;"	/* GPR[12] --> FPR[12] */
+		".long 0x7dad0166;"	/* GPR[13] --> FPR[13] */
+		".long 0x7dce0166;"	/* GPR[14] --> FPR[14] */
+		".long 0x7def0166;"	/* GPR[15] --> FPR[15] */
+		".long 0x7e100166;"	/* GPR[16] --> FPR[16] */
+		".long 0x7e310166;"	/* GPR[17] --> FPR[17] */
+		".long 0x7e520166;"	/* GPR[18] --> FPR[18] */
+		".long 0x7e730166;"	/* GPR[19] --> FPR[19] */
+		".long 0x7e940166;"	/* GPR[20] --> FPR[20] */
+		".long 0x7eb50166;"	/* GPR[21] --> FPR[21] */
+		".long 0x7ed60166;"	/* GPR[22] --> FPR[22] */
+		".long 0x7ef70166;"	/* GPR[23] --> FPR[23] */
+		".long 0x7f180166;"	/* GPR[24] --> FPR[24] */
+		".long 0x7f390166;"	/* GPR[25] --> FPR[25] */
+		".long 0x7f5a0166;"	/* GPR[26] --> FPR[26] */
+		".long 0x7f7b0166;"	/* GPR[27] --> FPR[27] */
+		".long 0x7f9c0166;"	/* GPR[28] --> FPR[28] */
+		".long 0x7fbd0166;"	/* GPR[29] --> FPR[29] */
+		".long 0x7fde0166;"	/* GPR[30] --> FPR[30] */
+		".long 0x7fff0166;"	/* GPR[31] --> FPR[31] */
+
+		/* TM running values */
+
+		"1: ;"
+		TBEGIN
+		"beq 2f;"
+
+		/* SPR */
+		"li 0, %[tar];"		/* TAR */
+		"mtspr %[sprn_tar], 0;"
+		"li 0, %[dscr];"	/* DSCR */
+		"mtspr %[sprn_dscr], 0;"
+		"or	31,31,31;"	/* PPR (0x4000000000000) */
+
+		/* GPR[0..31] */
+		"li 0, %[val15];"	/* GPR[0] */
+		"li 1, %[val14];"	/* GPR[1] */
+		"li 2, %[val13];"	/* GPR[2] */
+		"li 3, %[val12];"	/* GPR[3] */
+		"li 4, %[val11];"	/* GPR[4] */
+		"li 5, %[val10];"	/* GPR[5] */
+		"li 6, %[val9];"	/* GPR[6] */
+		"li 7, %[val8];"	/* GPR[7] */
+		"li 8, %[val7];"	/* GPR[8] */
+		"li 9, %[val6];"	/* GPR[9] */
+		"li 10, %[val5];"	/* GPR[10] */
+		"li 11, %[val4];"	/* GPR[11] */
+		"li 12, %[val3];"	/* GPR[12] */
+		"li 13, %[val2];"	/* GPR[13] */
+		"li 14, %[val1];"	/* GPR[14] */
+		"li 15, %[val0];"	/* GPR[15] */
+		"li 16, %[val15];"	/* GPR[16] */
+		"li 17, %[val14];"	/* GPR[17] */
+		"li 18, %[val13];"	/* GPR[18] */
+		"li 19, %[val12];"	/* GPR[19] */
+		"li 20, %[val11];"	/* GPR[20] */
+		"li 21, %[val10];"	/* GPR[21] */
+		"li 22, %[val9];"	/* GPR[22] */
+		"li 23, %[val8];"	/* GPR[23] */
+		"li 24, %[val7];"	/* GPR[24] */
+		"li 25, %[val6];"	/* GPR[25] */
+		"li 26, %[val5];"	/* GPR[26] */
+		"li 27, %[val4];"	/* GPR[27] */
+		"li 28, %[val3];"	/* GPR[28] */
+		"li 29, %[val2];"	/* GPR[29] */
+		"li 30, %[val1];"	/* GPR[30] */
+		"li 31, %[val0];"	/* GPR[31] */
+
+		/* FPR[0..31] */
+		".long 0x7C000166;"	/* GPR[0] --> FPR[0] */
+		".long 0x7C210166;"	/* GPR[1] --> FPR[1] */
+		".long 0x7C420166;"	/* GPR[2] --> FPR[2] */
+		".long 0x7C630166;"	/* GPR[3] --> FPR[3] */
+		".long 0x7C840166;"	/* GPR[4] --> FPR[4] */
+		".long 0x7CA50166;"	/* GPR[5] --> FPR[5] */
+		".long 0x7CC60166;"	/* GPR[6] --> FPR[6] */
+		".long 0x7CE70166;"	/* GPR[7] --> FPR[7] */
+		".long 0x7D080166;"	/* GPR[8] --> FPR[8] */
+		".long 0x7D290166;"	/* GPR[9] --> FPR[9] */
+		".long 0x7d4a0166;"	/* GPR[10] --> FPR[10] */
+		".long 0x7d6b0166;"	/* GPR[11] --> FPR[11] */
+		".long 0x7d8c0166;"	/* GPR[12] --> FPR[12] */
+		".long 0x7dad0166;"	/* GPR[13] --> FPR[13] */
+		".long 0x7dce0166;"	/* GPR[14] --> FPR[14] */
+		".long 0x7def0166;"	/* GPR[15] --> FPR[15] */
+		".long 0x7e100166;"	/* GPR[16] --> FPR[16] */
+		".long 0x7e310166;"	/* GPR[17] --> FPR[17] */
+		".long 0x7e520166;"	/* GPR[18] --> FPR[18] */
+		".long 0x7e730166;"	/* GPR[19] --> FPR[19] */
+		".long 0x7e940166;"	/* GPR[20] --> FPR[20] */
+		".long 0x7eb50166;"	/* GPR[21] --> FPR[21] */
+		".long 0x7ed60166;"	/* GPR[22] --> FPR[22] */
+		".long 0x7ef70166;"	/* GPR[23] --> FPR[23] */
+		".long 0x7f180166;"	/* GPR[24] --> FPR[24] */
+		".long 0x7f390166;"	/* GPR[25] --> FPR[25] */
+		".long 0x7f5a0166;"	/* GPR[26] --> FPR[26] */
+		".long 0x7f7b0166;"	/* GPR[27] --> FPR[27] */
+		".long 0x7f9c0166;"	/* GPR[28] --> FPR[28] */
+		".long 0x7fbd0166;"	/* GPR[29] --> FPR[29] */
+		".long 0x7fde0166;"	/* GPR[30] --> FPR[30] */
+		".long 0x7fff0166;"	/* GPR[31] --> FPR[31] */
+
+		"b .;"			/* Get stuck here */
+		TEND
+
+		/* Transaction abort handler */
+		"2: ;"
+		"b 1b;"			/* Start from TBEGIN */
+
+		:: [sprn_dscr]"i"(SPRN_DSCR), [sprn_tar]"i"(SPRN_TAR),
+		[sprn_ppr]"i"(SPRN_PPR), [val0]"i"(VAL0),
+		[val1]"i"(VAL1), [val2]"i"(VAL2), [val3]"i"(VAL3),
+		[val4]"i"(VAL4), [val5]"i"(VAL5), [val6]"i"(VAL6),
+		[val7]"i"(VAL7), [val8]"i"(VAL8), [val9]"i"(VAL9),
+		[val10]"i"(VAL10), [val11]"i"(VAL11), [val12]"i"(VAL12),
+		[val13]"i"(VAL13), [val14]"i"(VAL14), [val15]"i"(VAL15),
+		[c_tar]"i"(C_TAR), [c_dscr]"i"(C_DSCR), [tar]"i"(TAR),
+		[dscr]"i"(DSCR), [ppr]"i"(PPR), [c_ppr]"i"(C_PPR)
+		: "memory", "r7");
+}
+
+void test_result(const u64 variable, const u64 value, const char *str)
+{
+	if (variable == value)
+		printf("%s: %llx (PASSED)\n", str, variable);
+	else
+		printf("%s: %llx (FAILED)\n", str, variable);
+}
+
+int trace_transaction(pid_t child)
+{
+	struct tm_spr_regs *tmspr;
+	struct pt_regs *cregs, *regs;
+	struct tm_cfpr *cfpr, *fpr;
+	struct misc_regs *mregs;
+	struct iovec iov;
+	char str[MAX_OUTPUT];
+	int ret, i, j;
+
+	regs = (struct pt_regs *) malloc(sizeof(struct pt_regs));
+	fpr = (struct tm_cfpr *) malloc(sizeof(struct tm_cfpr));
+
+	/* Wait till the tracee hits "b ." instruction */
+	sleep(3);
+
+	ret = ptrace(PTRACE_ATTACH, child, NULL, NULL);
+	if (ret) {
+		printf("ptrace(PTRACE_ATTACH) Failed: %s\n", strerror(errno));
+		return 1;
+	}
+
+	ret = waitpid(child, NULL, 0);
+	if (ret != child) {
+		printf("PID mismatch: %s\n", strerror(errno));
+		return 1;
+	}
+
+	/* TM specific SPR */
+	iov.iov_base = (struct tm_spr_regs *)
+				malloc(sizeof(struct tm_spr_regs));
+	iov.iov_len = sizeof(struct tm_spr_regs);
+	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_SPR, &iov);
+	if (ret) {
+		printf("ptrace(NT_PPC_TM_SPR) Failed: %s\n", strerror(errno));
+		return 1;
+	}
+
+	if (iov.iov_len != sizeof(struct tm_spr_regs)) {
+		printf("ptrace(NT_PPC_TM_SPR): Returned wrong length\n");
+		return 1;
+	}
+
+	printf("-------TM Specific SPR------\n");
+	tmspr = iov.iov_base;
+
+	printf("TFHAR: %llx\n", tmspr->tm_tfhar);
+	printf("TEXASR: %llx\n", tmspr->tm_texasr);
+	printf("TFIAR: %llx\n", tmspr->tm_tfiar);
+	printf("TM ORIG_MSR: %llx\n", tmspr->tm_orig_msr);
+
+	test_result(tmspr->tm_dscr, C_DSCR, "TM CH DSCR");
+	test_result(tmspr->tm_tar, C_TAR, "TM CH TAR");
+	test_result(tmspr->tm_ppr, C_PPR, "TM CH PPR");
+
+	/* TM checkpointed GPR */
+	iov.iov_base = (struct pt_regs *) malloc(sizeof(struct pt_regs));
+	iov.iov_len = sizeof(struct pt_regs);
+	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CGPR, &iov);
+	if (ret) {
+		printf("ptrace(NT_PPC_TM_CGPR) Failed: %s\n", strerror(errno));
+		return 1;
+	}
+
+	if (iov.iov_len != sizeof(struct pt_regs)) {
+		printf("ptrace(NT_PPC_TM_CGPR): Returned wrong length\n");
+		return 1;
+	}
+
+	printf("-------TM Checkpointed GPR-----\n");
+	cregs = iov.iov_base;
+
+	printf("TM CH NIP: %lx\n", cregs->nip);
+	printf("TM CH LINK: %lx\n", cregs->link);
+	printf("TM CH CCR: %lx\n", cregs->ccr);
+
+	for (i = 0; i < VAL_MAX; i++) {
+		sprintf(str, "TM CH GPR[%d]", i);
+		test_result(cregs->gpr[i], i, str);
+	}
+
+	for (j = 0; i < VAL_MAX * 2; j++, i++) {
+		sprintf(str, "TM CH GPR[%d]", i);
+		test_result(cregs->gpr[i], j, str);
+	}
+
+	/* TM checkpointed FPR */
+	iov.iov_base = (struct tm_cfpr *) malloc(sizeof(struct tm_cfpr));
+	iov.iov_len = sizeof(struct tm_cfpr);
+	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_TM_CFPR, &iov);
+	if (ret) {
+		printf("ptrace(NT_PPC_TM_CFPR) Failed: %s\n", strerror(errno));
+		return 1;
+	}
+
+	if (iov.iov_len != sizeof(struct tm_cfpr)) {
+		printf("ptrace(NT_PPC_TM_CFPR): Returned wrong length\n");
+		return 1;
+	}
+
+	printf("-------TM Checkpointed FPR-----\n");
+	cfpr = iov.iov_base;
+	printf("TM CH FPSCR: %llx\n", cfpr->fpscr);
+
+	for (i = 0; i < VAL_MAX; i++) {
+		sprintf(str, "TM CH FPR[%d]", i);
+		test_result(cfpr->fpr[i], i, str);
+	}
+
+	for (j = 0; i < VAL_MAX * 2; j++, i++) {
+		sprintf(str, "TM CH FPR[%d]", i);
+		test_result(cfpr->fpr[i], j, str);
+	}
+
+	/* TM running GPR */
+	ret = ptrace(PTRACE_GETREGS, child, NULL, regs);
+	if (ret) {
+		printf("ptrace(PTRACE_GETREGS) Failed: %s\n", strerror(errno));
+		return 1;
+	}
+
+	printf("-------TM Running GPR-----\n");
+	printf("TM RN NIP: %lx\n", regs->nip);
+	printf("TM RN LINK: %lx\n", regs->link);
+	printf("TM RN CCR: %lx\n", regs->ccr);
+
+	for (i = 0, j = VAL_MAX - 1; i < VAL_MAX; i++, j--) {
+		sprintf(str, "TM RN GPR[%d]", i);
+		test_result(regs->gpr[i], j, str);
+	}
+
+	for (j = VAL_MAX - 1 ; i < VAL_MAX * 2; i++, j--) {
+		sprintf(str, "TM RN GPR[%d]", i);
+		test_result(regs->gpr[i], j, str);
+	}
+
+	/* TM running FPR */
+	ret = ptrace(PTRACE_GETFPREGS, child, NULL, fpr);
+	if (ret) {
+		printf("ptrace(PTRACE_GETFPREGS) Failed: %s\n",
+							strerror(errno));
+		return 1;
+	}
+
+	printf("-------TM Running FPR-----\n");
+	printf("TM RN FPSCR: %llx\n", fpr->fpscr);
+
+	for (i = 0, j = VAL_MAX - 1; i < VAL_MAX; i++, j--) {
+		sprintf(str, "TM RN FPR[%d]", i);
+		test_result(fpr->fpr[i], j, str);
+	}
+
+	for (j = VAL_MAX - 1; i < VAL_MAX * 2; i++, j--) {
+		sprintf(str, "TM RN FPR[%d]", i);
+		test_result(fpr->fpr[i], j, str);
+	}
+
+	/* Running misc debug registers */
+	iov.iov_base = (struct misc_regs *) malloc(sizeof(struct misc_regs));
+	iov.iov_len = sizeof(struct misc_regs);
+	ret = ptrace(PTRACE_GETREGSET, child, NT_PPC_MISC, &iov);
+	if (ret) {
+		printf("ptrace(NT_PPC_MISC): Failed: %s\n", strerror(errno));
+		return 1;
+	}
+
+	if (iov.iov_len != sizeof(struct misc_regs)) {
+		printf("ptrace(NT_PPC_TM_MISC): Returned wrong length\n");
+		return 1;
+	}
+
+	printf("-------TM Running MISC Registers-------\n");
+	mregs  = iov.iov_base;
+	test_result(mregs->dscr, DSCR, "TM RN DSCR");
+	test_result(mregs->tar, TAR, "TM RN TAR");
+	test_result(mregs->ppr, PPR, "TM RN PPR");
+
+	ret = ptrace(PTRACE_DETACH, child, NULL, NULL);
+	if (ret) {
+		printf("ptrace(PTRACE_DETACH) Failed: %s\n", strerror(errno));
+		return 1;
+	}
+	return 0;
+}
+
+int tm_ptrace_test(void)
+{
+	pid_t child;
+
+	printf("=============Testing TM based PTRACE calls==============\n");
+	fflush(stdout);
+	child = fork();
+	if (child < 0) {
+		printf("fork() Failed: %s\n", strerror(errno));
+		return 1;
+	}
+
+	/* Child to run the transaction */
+	if (child == 0)
+		do_transaction();
+
+	/* Parent to trace the child */
+	if (child)
+		trace_transaction(child);
+	return 0;
+}
+
+int main(void)
+{
+	return test_harness(tm_ptrace_test, "tm_ptrace");
+}
-- 
1.9.3

^ permalink raw reply related

* [PATCH V4 7/8] powerpc, ptrace: Enable support for miscellaneous debug registers
From: Anshuman Khandual @ 2014-11-11  5:26 UTC (permalink / raw)
  To: linux-kernel, linuxppc-dev
  Cc: mikey, james.hogan, avagin, Paul.Clothier, peterz, palves, oleg,
	davem, dhowells, davej, akpm, sukadev, tglx, sam.bobroff
In-Reply-To: <1415683597-22819-1-git-send-email-khandual@linux.vnet.ibm.com>

This patch enables get and set of miscellaneous debug registers through
ptrace PTRACE_GETREGSET-PTRACE_SETREGSET interface by implementing new
powerpc specific register set REGSET_MISC support corresponding to the
new ELF core note NT_PPC_MISC added previously in this regard.

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 arch/powerpc/include/uapi/asm/elf.h |   1 +
 arch/powerpc/kernel/ptrace.c        | 102 ++++++++++++++++++++++++++++++++++++
 2 files changed, 103 insertions(+)

diff --git a/arch/powerpc/include/uapi/asm/elf.h b/arch/powerpc/include/uapi/asm/elf.h
index fdc8e2f..a41bd98 100644
--- a/arch/powerpc/include/uapi/asm/elf.h
+++ b/arch/powerpc/include/uapi/asm/elf.h
@@ -93,6 +93,7 @@
 #define ELF_NFPREG	33	/* includes fpscr */
 #define ELF_NVMX	34	/* includes all vector registers */
 #define ELF_NTMSPRREG	7	/* includes TM sprs, org_msr, dscr, tar, ppr */
+#define ELF_NMISCREG	3	/* includes dscr, tar, ppr */
 
 typedef unsigned long elf_greg_t64;
 typedef elf_greg_t64 elf_gregset_t64[ELF_NGREG];
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index b279947..61a2581 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -1327,6 +1327,97 @@ static int tm_cvmx_set(struct task_struct *target,
 #endif	/* CONFIG_PPC_TRANSACTIONAL_MEM */
 
 /*
+ * get_misc_dbg
+ *
+ * This function gets miscellaneous debug registers
+ * which includes DSCR, PPR and TAR.
+ *
+ * Userspace intarface buffer layout:
+ *
+ * struct {
+ *	unsigned long dscr;
+ *	unsigned long ppr;
+ *	unsigned long tar;
+ * };
+ */
+static int get_misc_dbg(struct task_struct *target,
+			const struct user_regset *regset, unsigned int pos,
+			unsigned int count, void *kbuf, void __user *ubuf)
+{
+	int ret;
+
+	/* Build test */
+	BUILD_BUG_ON(TSO(dscr) + 2 * sizeof(unsigned long) != TSO(ppr));
+	BUILD_BUG_ON(TSO(ppr) + sizeof(unsigned long) != TSO(tar));
+
+	/* DSCR register */
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+					&target->thread.dscr, 0,
+					sizeof(unsigned long));
+
+	/* PPR register */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+						&target->thread.ppr,
+						sizeof(unsigned long),
+						2 * sizeof(unsigned long));
+
+	/* TAR register */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+						&target->thread.tar,
+						2 * sizeof(unsigned long),
+						3 * sizeof(unsigned long));
+	return ret;
+}
+
+/*
+ * set_misc_dbg
+ *
+ * This function sets miscellaneous debug registers
+ * which includes DSCR, PPR and TAR.
+ *
+ * Userspace intarface buffer layout:
+ *
+ * struct {
+ *	unsigned long dscr;
+ *	unsigned long ppr;
+ *	unsigned long tar;
+ * };
+ */
+static int set_misc_dbg(struct task_struct *target,
+			const struct user_regset *regset, unsigned int pos,
+			unsigned int count, const void *kbuf,
+			const void __user *ubuf)
+{
+	int ret;
+
+	/* Build test */
+	BUILD_BUG_ON(TSO(dscr) + 2 * sizeof(unsigned long) != TSO(ppr));
+	BUILD_BUG_ON(TSO(ppr) + sizeof(unsigned long) != TSO(tar));
+
+	/* DSCR register */
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+					&target->thread.dscr, 0,
+					sizeof(unsigned long));
+
+	/* PPR register */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+						&target->thread.ppr,
+						sizeof(unsigned long),
+						2 * sizeof(unsigned long));
+
+	/* TAR register */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+						&target->thread.tar,
+						2 * sizeof(unsigned long),
+						3 * sizeof(unsigned long));
+	return ret;
+}
+
+/*
  * These are our native regset flavors.
  */
 enum powerpc_regset {
@@ -1347,6 +1438,7 @@ enum powerpc_regset {
 	REGSET_TM_CFPR,		/* TM checkpointed FPR registers */
 	REGSET_TM_CVMX,		/* TM checkpointed VMX registers */
 #endif
+	REGSET_MISC		/* Miscellaneous debug registers */
 };
 
 static const struct user_regset native_regsets[] = {
@@ -1403,6 +1495,11 @@ static const struct user_regset native_regsets[] = {
 		.active = tm_cvmx_active, .get = tm_cvmx_get, .set = tm_cvmx_set
 	},
 #endif
+	[REGSET_MISC] = {
+		.core_note_type = NT_PPC_MISC, .n = ELF_NMISCREG,
+		.size = sizeof(u64), .align = sizeof(u64),
+		.get = get_misc_dbg, .set = set_misc_dbg
+	},
 };
 
 static const struct user_regset_view user_ppc_native_view = {
@@ -1646,6 +1743,11 @@ static const struct user_regset compat_regsets[] = {
 		.active = tm_cvmx_active, .get = tm_cvmx_get, .set = tm_cvmx_set
 	},
 #endif
+	[REGSET_MISC] = {
+		.core_note_type = NT_PPC_MISC, .n = ELF_NMISCREG,
+		.size = sizeof(u64), .align = sizeof(u64),
+		.get = get_misc_dbg, .set = set_misc_dbg
+	},
 };
 
 static const struct user_regset_view user_ppc_compat_view = {
-- 
1.9.3

^ permalink raw reply related

* [PATCH V4 6/8] powerpc, ptrace: Enable support for transactional memory register sets
From: Anshuman Khandual @ 2014-11-11  5:26 UTC (permalink / raw)
  To: linux-kernel, linuxppc-dev
  Cc: mikey, james.hogan, avagin, Paul.Clothier, peterz, palves, oleg,
	davem, dhowells, davej, akpm, sukadev, tglx, sam.bobroff
In-Reply-To: <1415683597-22819-1-git-send-email-khandual@linux.vnet.ibm.com>

This patch enables get and set of transactional memory related register
sets through PTRACE_GETREGSET-PTRACE_SETREGSET interface by implementing
four new powerpc specific register sets i.e REGSET_TM_SPR, REGSET_TM_CGPR,
REGSET_TM_CFPR, REGSET_CVMX support corresponding to these following new
ELF core note types added previously in this regard.

	(1) NT_PPC_TM_SPR
	(2) NT_PPC_TM_CGPR
	(3) NT_PPC_TM_CFPR
	(4) NT_PPC_TM_CVMX

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 arch/powerpc/include/uapi/asm/elf.h |   2 +
 arch/powerpc/kernel/ptrace.c        | 666 +++++++++++++++++++++++++++++++++++-
 2 files changed, 653 insertions(+), 15 deletions(-)

diff --git a/arch/powerpc/include/uapi/asm/elf.h b/arch/powerpc/include/uapi/asm/elf.h
index 59dad11..fdc8e2f 100644
--- a/arch/powerpc/include/uapi/asm/elf.h
+++ b/arch/powerpc/include/uapi/asm/elf.h
@@ -91,6 +91,8 @@
 
 #define ELF_NGREG	48	/* includes nip, msr, lr, etc. */
 #define ELF_NFPREG	33	/* includes fpscr */
+#define ELF_NVMX	34	/* includes all vector registers */
+#define ELF_NTMSPRREG	7	/* includes TM sprs, org_msr, dscr, tar, ppr */
 
 typedef unsigned long elf_greg_t64;
 typedef elf_greg_t64 elf_gregset_t64[ELF_NGREG];
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 2bbbd10..b279947 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -63,6 +63,11 @@ struct pt_regs_offset {
 	{.name = STR(gpr##num), .offset = offsetof(struct pt_regs, gpr[num])}
 #define REG_OFFSET_END {.name = NULL, .offset = 0}
 
+/* Some common structure offsets */
+#define TSO(f)	(offsetof(struct thread_struct, f))
+#define TVSO(f)	(offsetof(struct thread_vr_state, f))
+#define TFSO(f)	(offsetof(struct thread_fp_state, f))
+
 static const struct pt_regs_offset regoffset_table[] = {
 	GPR_OFFSET_NAME(0),
 	GPR_OFFSET_NAME(1),
@@ -792,6 +797,534 @@ static int evr_set(struct task_struct *target, const struct user_regset *regset,
 }
 #endif /* CONFIG_SPE */
 
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+/*
+ * tm_spr_active
+ *
+ * This function checks number of available regisers in
+ * the transactional memory SPR category.
+ */
+static int tm_spr_active(struct task_struct *target,
+			 const struct user_regset *regset)
+{
+	if (!cpu_has_feature(CPU_FTR_TM))
+		return -ENODEV;
+
+	if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+		return 0;
+
+	return regset->n;
+}
+
+/*
+ * tm_spr_get
+ *
+ * This function gets transactional memory related SPR registers
+ *
+ * Userspace interface buffer layout:
+ *
+ * struct {
+ *	u64		tm_tfhar;
+ *	u64		tm_texasr;
+ *	u64		tm_tfiar;
+ *	unsigned long	tm_orig_msr;
+ *	unsigned long	tm_tar;
+ *	unsigned long	tm_ppr;
+ *	unsigned long	tm_dscr;
+ * };
+ */
+static int tm_spr_get(struct task_struct *target,
+		      const struct user_regset *regset,
+		      unsigned int pos, unsigned int count,
+		      void *kbuf, void __user *ubuf)
+{
+	int ret;
+
+	/* Build tests */
+	BUILD_BUG_ON(TSO(tm_tfhar) + sizeof(u64) != TSO(tm_texasr));
+	BUILD_BUG_ON(TSO(tm_texasr) + sizeof(u64) != TSO(tm_tfiar));
+	BUILD_BUG_ON(TSO(tm_tfiar) + sizeof(u64) != TSO(tm_orig_msr));
+	BUILD_BUG_ON(TSO(tm_orig_msr) +	sizeof(unsigned long) +
+				sizeof(struct pt_regs) != TSO(tm_tar));
+	BUILD_BUG_ON(TSO(tm_tar) + sizeof(unsigned long) != TSO(tm_ppr));
+	BUILD_BUG_ON(TSO(tm_ppr) + sizeof(unsigned long) != TSO(tm_dscr));
+
+	if (!cpu_has_feature(CPU_FTR_TM))
+		return -ENODEV;
+
+	if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+		return -ENODATA;
+
+	/* Flush the states */
+	flush_fp_to_thread(target);
+	flush_altivec_to_thread(target);
+	flush_tmregs_to_thread(target);
+
+	/* TFHAR register */
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_tfhar, 0, sizeof(u64));
+
+	/* TEXASR register */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_texasr, sizeof(u64),
+				2 * sizeof(u64));
+
+	/* TFIAR register */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_tfiar,
+				2 * sizeof(u64), 3 * sizeof(u64));
+
+	/* TM checkpointed original MSR */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_orig_msr, 3 * sizeof(u64),
+				3 * sizeof(u64) + sizeof(unsigned long));
+
+	/* TM checkpointed TAR register */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_tar, 3 * sizeof(u64) +
+				sizeof(unsigned long) ,
+				3 * sizeof(u64) + 2 * sizeof(unsigned long));
+
+	/* TM checkpointed PPR register */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_ppr, 3 * sizeof(u64) +
+				2 * sizeof(unsigned long),
+				3 * sizeof(u64) + 3 * sizeof(unsigned long));
+
+	/* TM checkpointed DSCR register */
+	if (!ret)
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_dscr, 3 * sizeof(u64) +
+				3 * sizeof(unsigned long),
+				3 * sizeof(u64) + 4 * sizeof(unsigned long));
+	return ret;
+}
+
+/*
+ * tm_spr_set
+ *
+ * This function sets transactional memory related SPR registers
+ *
+ * Userspace interface buffer layout:
+ *
+ * struct {
+ *	u64		tm_tfhar;
+ *	u64		tm_texasr;
+ *	u64		tm_tfiar;
+ *	unsigned long	tm_orig_msr;
+ *	unsigned long	tm_tar;
+ *	unsigned long	tm_ppr;
+ *	unsigned long	tm_dscr;
+ * };
+ */
+static int tm_spr_set(struct task_struct *target,
+		      const struct user_regset *regset,
+		      unsigned int pos, unsigned int count,
+		      const void *kbuf, const void __user *ubuf)
+{
+	int ret;
+
+	/* Build tests */
+	BUILD_BUG_ON(TSO(tm_tfhar) + sizeof(u64) != TSO(tm_texasr));
+	BUILD_BUG_ON(TSO(tm_texasr) + sizeof(u64) != TSO(tm_tfiar));
+	BUILD_BUG_ON(TSO(tm_orig_msr) + sizeof(unsigned long)
+				+ sizeof(struct pt_regs) != TSO(tm_tar));
+	BUILD_BUG_ON(TSO(tm_tar) + sizeof(unsigned long) != TSO(tm_ppr));
+	BUILD_BUG_ON(TSO(tm_ppr) + sizeof(unsigned long) != TSO(tm_dscr));
+	BUILD_BUG_ON(TSO(tm_tfiar) + sizeof(u64) != TSO(tm_orig_msr));
+
+	if (!cpu_has_feature(CPU_FTR_TM))
+		return -ENODEV;
+
+	if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+		return -ENODATA;
+
+	/* Flush the states */
+	flush_fp_to_thread(target);
+	flush_altivec_to_thread(target);
+	flush_tmregs_to_thread(target);
+
+	/* TFHAR register */
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_tfhar, 0, sizeof(u64));
+
+	/* TEXASR register */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_texasr, sizeof(u64),
+				2 * sizeof(u64));
+
+	/* TFIAR register */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_tfiar,
+				 2 * sizeof(u64), 3 * sizeof(u64));
+
+
+	/* TM checkpointed orig MSR */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_orig_msr, 3 * sizeof(u64),
+				3 * sizeof(u64) + sizeof(unsigned long));
+
+
+	/* TM checkpointed TAR register */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_tar, 3 * sizeof(u64) +
+				sizeof(unsigned long), 3 * sizeof(u64) +
+				2 * sizeof(unsigned long));
+
+	/* TM checkpointed PPR register */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_ppr, 3 * sizeof(u64) +
+				2 * sizeof(unsigned long), 3 * sizeof(u64) +
+				3 * sizeof(unsigned long));
+
+	/* TM checkpointed DSCR register */
+	if (!ret)
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				&target->thread.tm_dscr, 3 * sizeof(u64) +
+				3 * sizeof(unsigned long), 3 * sizeof(u64) +
+				4 * sizeof(unsigned long));
+	return ret;
+}
+
+/*
+ * tm_cgpr_active
+ *
+ * This function checks the number of available regisers in
+ * transaction checkpointed GPR category.
+ */
+static int tm_cgpr_active(struct task_struct *target,
+			  const struct user_regset *regset)
+{
+	if (!cpu_has_feature(CPU_FTR_TM))
+		return -ENODEV;
+
+	if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+		return 0;
+
+	return regset->n;
+}
+
+/*
+ * tm_cgpr_get
+ *
+ * This function gets transaction checkpointed GPR registers
+ *
+ * When the transaction is active, 'ckpt_regs' holds all the checkpointed
+ * GPR register values for the current transaction to fall back on if it
+ * aborts in between. This function gets those checkpointed GPR registers.
+ *
+ * Userspace interface buffer layout:
+ *
+ * struct data {
+ *	struct pt_regs ckpt_regs;
+ * };
+ */
+static int tm_cgpr_get(struct task_struct *target,
+			const struct user_regset *regset,
+			unsigned int pos, unsigned int count,
+			void *kbuf, void __user *ubuf)
+{
+	int ret;
+
+	if (!cpu_has_feature(CPU_FTR_TM))
+		return -ENODEV;
+
+	if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+		return -ENODATA;
+
+	flush_fp_to_thread(target);
+	flush_altivec_to_thread(target);
+	flush_tmregs_to_thread(target);
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+					&target->thread.ckpt_regs, 0,
+					sizeof(struct pt_regs));
+	return ret;
+}
+
+/*
+ * tm_cgpr_set
+ *
+ * This function sets in transaction checkpointed GPR registers
+ *
+ * When the transaction is active, 'ckpt_regs' holds the checkpointed
+ * GPR register values for the current transaction to fall back on if it
+ * aborts in between. This function sets those checkpointed GPR registers.
+ *
+ * Userspace intaerface buffer:
+ *
+ * struct data {
+ *	struct pt_regs ckpt_regs;
+ * };
+ */
+static int tm_cgpr_set(struct task_struct *target,
+			const struct user_regset *regset,
+			unsigned int pos, unsigned int count,
+			const void *kbuf, const void __user *ubuf)
+{
+	int ret;
+
+	if (!cpu_has_feature(CPU_FTR_TM))
+		return -ENODEV;
+
+	if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+		return -ENODATA;
+
+	flush_fp_to_thread(target);
+	flush_altivec_to_thread(target);
+	flush_tmregs_to_thread(target);
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+					&target->thread.ckpt_regs, 0,
+					sizeof(struct pt_regs));
+	return ret;
+}
+
+/*
+ * tm_cfpr_active
+ *
+ * This function checks number of available regisers in
+ * transaction checkpointed FPR category.
+ */
+static int tm_cfpr_active(struct task_struct *target,
+				const struct user_regset *regset)
+{
+	if (!cpu_has_feature(CPU_FTR_TM))
+		return -ENODEV;
+
+	if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+		return 0;
+
+	return regset->n;
+}
+
+/*
+ * tm_cfpr_get
+ *
+ * This function gets in transaction checkpointed FPR registers
+ *
+ * When the transaction is active 'fp_state' holds the checkpointed
+ * values for the current transaction to fall back on if it aborts
+ * in between. This function gets those checkpointed FPR registers.
+ *
+ * Userspace interface buffer layout:
+ *
+ * struct data {
+ *	u64	fpr[32];
+ *	u64	fpscr;
+ *};
+ */
+static int tm_cfpr_get(struct task_struct *target,
+			const struct user_regset *regset,
+			unsigned int pos, unsigned int count,
+			void *kbuf, void __user *ubuf)
+{
+	u64 buf[33];
+	int i;
+
+	if (!cpu_has_feature(CPU_FTR_TM))
+		return -ENODEV;
+
+	if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+		return -ENODATA;
+
+	flush_fp_to_thread(target);
+	flush_altivec_to_thread(target);
+	flush_tmregs_to_thread(target);
+
+	/* copy to local buffer then write that out */
+	for (i = 0; i < 32 ; i++)
+		buf[i] = target->thread.TS_FPR(i);
+	buf[32] = target->thread.fp_state.fpscr;
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
+}
+
+/*
+ * tm_cfpr_set
+ *
+ * This function sets in transaction checkpointed FPR registers
+ *
+ * When the transaction is active 'fp_state' holds the checkpointed
+ * FPR register values for the current transaction to fall back on
+ * if it aborts in between. This function sets these checkpointed
+ * FPR registers.
+ *
+ * Userspace interface buffer layout:
+ *
+ * struct data {
+ *	u64	fpr[32];
+ *	u64	fpscr;
+ *};
+ */
+static int tm_cfpr_set(struct task_struct *target,
+			const struct user_regset *regset,
+			unsigned int pos, unsigned int count,
+			const void *kbuf, const void __user *ubuf)
+{
+	u64 buf[33];
+	int i;
+
+	if (!cpu_has_feature(CPU_FTR_TM))
+		return -ENODEV;
+
+	if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+		return -ENODATA;
+
+	flush_fp_to_thread(target);
+	flush_altivec_to_thread(target);
+	flush_tmregs_to_thread(target);
+
+	/* copy to local buffer then write that out */
+	i = user_regset_copyin(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
+	if (i)
+		return i;
+	for (i = 0; i < 32 ; i++)
+		target->thread.TS_FPR(i) = buf[i];
+	target->thread.fp_state.fpscr = buf[32];
+	return 0;
+}
+
+/*
+ * tm_cvmx_active
+ *
+ * This function checks the number of available regisers in
+ * checkpointed VMX category.
+ */
+static int tm_cvmx_active(struct task_struct *target,
+				const struct user_regset *regset)
+{
+	if (!cpu_has_feature(CPU_FTR_TM))
+		return -ENODEV;
+
+	if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+		return 0;
+
+	return regset->n;
+}
+
+/*
+ * tm_cvmx_get
+ *
+ * This function gets in transaction checkpointed VMX registers
+ *
+ * When the transaction is active 'vr_state' and 'vr_save' hold
+ * the checkpointed values for the current transaction to fall
+ * back on if it aborts in between.
+ *
+ * User interface buffer:
+ *
+ * struct data {
+ *	vector128	vr[32];
+ *	vector128	vscr;
+ *	vector128	vrsave;
+ *};
+ */
+static int tm_cvmx_get(struct task_struct *target,
+			const struct user_regset *regset,
+			unsigned int pos, unsigned int count,
+			void *kbuf, void __user *ubuf)
+{
+	int ret;
+
+	BUILD_BUG_ON(TVSO(vscr) != TVSO(vr[32]));
+
+	if (!cpu_has_feature(CPU_FTR_TM))
+		return -ENODEV;
+
+	if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+		return -ENODATA;
+
+	/* Flush the state */
+	flush_fp_to_thread(target);
+	flush_altivec_to_thread(target);
+	flush_tmregs_to_thread(target);
+
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+					&target->thread.vr_state, 0,
+					33 * sizeof(vector128));
+	if (!ret) {
+		/*
+		 * Copy out only the low-order word of vrsave.
+		 */
+		union {
+			elf_vrreg_t reg;
+			u32 word;
+		} vrsave;
+		memset(&vrsave, 0, sizeof(vrsave));
+		vrsave.word = target->thread.vrsave;
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &vrsave,
+						33 * sizeof(vector128), -1);
+	}
+
+	return ret;
+}
+
+/*
+ * tm_cvmx_set
+ *
+ * This function sets in transaction checkpointed VMX registers
+ *
+ * When the transaction is active 'vr_state' and 'vr_save' hold
+ * the checkpointed values for the current transaction to fall
+ * back on if it aborts in between.
+ *
+ * Userspace interface buffer:
+ *
+ * struct data {
+ *	vector128	vr[32];
+ *	vector128	vscr;
+ *	vector128	vrsave;
+ *};
+ */
+static int tm_cvmx_set(struct task_struct *target,
+			const struct user_regset *regset,
+			unsigned int pos, unsigned int count,
+			const void *kbuf, const void __user *ubuf)
+{
+	int ret;
+
+	BUILD_BUG_ON(TVSO(vscr) != TVSO(vr[32]));
+
+	if (!cpu_has_feature(CPU_FTR_TM))
+		return -ENODEV;
+
+	if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+		return -ENODATA;
+
+	flush_fp_to_thread(target);
+	flush_altivec_to_thread(target);
+	flush_tmregs_to_thread(target);
+
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+					&target->thread.vr_state, 0,
+					33 * sizeof(vector128));
+	if (!ret && count > 0) {
+		/*
+		 * We use only the first word of vrsave.
+		 */
+		union {
+			elf_vrreg_t reg;
+			u32 word;
+		} vrsave;
+		memset(&vrsave, 0, sizeof(vrsave));
+		vrsave.word = target->thread.vrsave;
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &vrsave,
+						33 * sizeof(vector128), -1);
+		if (!ret)
+			target->thread.vrsave = vrsave.word;
+	}
+
+	return ret;
+}
+#endif	/* CONFIG_PPC_TRANSACTIONAL_MEM */
 
 /*
  * These are our native regset flavors.
@@ -808,6 +1341,12 @@ enum powerpc_regset {
 #ifdef CONFIG_SPE
 	REGSET_SPE,
 #endif
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+	REGSET_TM_SPR,		/* TM specific SPR registers */
+	REGSET_TM_CGPR,		/* TM checkpointed GPR registers */
+	REGSET_TM_CFPR,		/* TM checkpointed FPR registers */
+	REGSET_TM_CVMX,		/* TM checkpointed VMX registers */
+#endif
 };
 
 static const struct user_regset native_regsets[] = {
@@ -842,6 +1381,28 @@ static const struct user_regset native_regsets[] = {
 		.active = evr_active, .get = evr_get, .set = evr_set
 	},
 #endif
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+	[REGSET_TM_SPR] = {
+		.core_note_type = NT_PPC_TM_SPR, .n = ELF_NTMSPRREG,
+		.size = sizeof(u64), .align = sizeof(u64),
+		.active = tm_spr_active, .get = tm_spr_get, .set = tm_spr_set
+	},
+	[REGSET_TM_CGPR] = {
+		.core_note_type = NT_PPC_TM_CGPR, .n = ELF_NGREG,
+		.size = sizeof(long), .align = sizeof(long),
+		.active = tm_cgpr_active, .get = tm_cgpr_get, .set = tm_cgpr_set
+	},
+	[REGSET_TM_CFPR] = {
+		.core_note_type = NT_PPC_TM_CFPR, .n = ELF_NFPREG,
+		.size = sizeof(double), .align = sizeof(double),
+		.active = tm_cfpr_active, .get = tm_cfpr_get, .set = tm_cfpr_set
+	},
+	[REGSET_TM_CVMX] = {
+		.core_note_type = NT_PPC_TM_CVMX, .n = ELF_NVMX,
+		.size = sizeof(vector128), .align = sizeof(vector128),
+		.active = tm_cvmx_active, .get = tm_cvmx_get, .set = tm_cvmx_set
+	},
+#endif
 };
 
 static const struct user_regset_view user_ppc_native_view = {
@@ -852,24 +1413,35 @@ static const struct user_regset_view user_ppc_native_view = {
 #ifdef CONFIG_PPC64
 #include <linux/compat.h>
 
-static int gpr32_get(struct task_struct *target,
+static int common_gpr32_get(struct task_struct *target,
 		     const struct user_regset *regset,
 		     unsigned int pos, unsigned int count,
-		     void *kbuf, void __user *ubuf)
+			    void *kbuf, void __user *ubuf, bool in_tm)
 {
-	const unsigned long *regs = &target->thread.regs->gpr[0];
+	const unsigned long *regs;
 	compat_ulong_t *k = kbuf;
 	compat_ulong_t __user *u = ubuf;
 	compat_ulong_t reg;
 	int i;
 
-	if (target->thread.regs == NULL)
-		return -EIO;
+	if (in_tm) {
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+		regs = &target->thread.ckpt_regs.gpr[0];
+#endif
+	} else {
+		regs = &target->thread.regs->gpr[0];
 
-	if (!FULL_REGS(target->thread.regs)) {
-		/* We have a partial register set.  Fill 14-31 with bogus values */
-		for (i = 14; i < 32; i++)
-			target->thread.regs->gpr[i] = NV_REG_POISON; 
+		if (target->thread.regs == NULL)
+			return -EIO;
+
+		if (!FULL_REGS(target->thread.regs)) {
+			/*
+			 * We have a partial register set.
+			 * Fill 14-31 with bogus values.
+			 */
+			for (i = 14; i < 32; i++)
+				target->thread.regs->gpr[i] = NV_REG_POISON;
+		}
 	}
 
 	pos /= sizeof(reg);
@@ -909,20 +1481,28 @@ static int gpr32_get(struct task_struct *target,
 					PT_REGS_COUNT * sizeof(reg), -1);
 }
 
-static int gpr32_set(struct task_struct *target,
+static int common_gpr32_set(struct task_struct *target,
 		     const struct user_regset *regset,
 		     unsigned int pos, unsigned int count,
-		     const void *kbuf, const void __user *ubuf)
+		     const void *kbuf, const void __user *ubuf, bool in_tm)
 {
-	unsigned long *regs = &target->thread.regs->gpr[0];
+	unsigned long *regs;
 	const compat_ulong_t *k = kbuf;
 	const compat_ulong_t __user *u = ubuf;
 	compat_ulong_t reg;
 
-	if (target->thread.regs == NULL)
-		return -EIO;
+	if (in_tm) {
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+		regs = &target->thread.ckpt_regs.gpr[0];
+#endif
+	} else {
+		regs = &target->thread.regs->gpr[0];
 
-	CHECK_FULL_REGS(target->thread.regs);
+		if (target->thread.regs == NULL)
+			return -EIO;
+
+		CHECK_FULL_REGS(target->thread.regs);
+	}
 
 	pos /= sizeof(reg);
 	count /= sizeof(reg);
@@ -982,6 +1562,39 @@ static int gpr32_set(struct task_struct *target,
 					 (PT_TRAP + 1) * sizeof(reg), -1);
 }
 
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+static int tm_cgpr32_get(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     void *kbuf, void __user *ubuf)
+{
+	return common_gpr32_get(target, regset, pos, count, kbuf, ubuf, 1);
+}
+
+static int tm_cgpr32_set(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     const void *kbuf, const void __user *ubuf)
+{
+	return common_gpr32_set(target, regset, pos, count, kbuf, ubuf, 0);
+}
+#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
+
+static int gpr32_get(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     void *kbuf, void __user *ubuf)
+{
+	return common_gpr32_get(target, regset, pos, count, kbuf, ubuf, 0);
+}
+
+static int gpr32_set(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     const void *kbuf, const void __user *ubuf)
+{
+	return common_gpr32_set(target, regset, pos, count, kbuf, ubuf, 0);
+}
 /*
  * These are the regset flavors matching the CONFIG_PPC32 native set.
  */
@@ -1010,6 +1623,29 @@ static const struct user_regset compat_regsets[] = {
 		.active = evr_active, .get = evr_get, .set = evr_set
 	},
 #endif
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+	[REGSET_TM_SPR] = {
+		.core_note_type = NT_PPC_TM_SPR, .n = ELF_NTMSPRREG,
+		.size = sizeof(u64), .align = sizeof(u64),
+		.active = tm_spr_active, .get = tm_spr_get, .set = tm_spr_set
+	},
+	[REGSET_TM_CGPR] = {
+		.core_note_type = NT_PPC_TM_CGPR, .n = ELF_NGREG,
+		.size = sizeof(long), .align = sizeof(long),
+		.active = tm_cgpr_active,
+		.get = tm_cgpr32_get, .set = tm_cgpr32_set
+	},
+	[REGSET_TM_CFPR] = {
+		.core_note_type = NT_PPC_TM_CFPR, .n = ELF_NFPREG,
+		.size = sizeof(double), .align = sizeof(double),
+		.active = tm_cfpr_active, .get = tm_cfpr_get, .set = tm_cfpr_set
+	},
+	[REGSET_TM_CVMX] = {
+		.core_note_type = NT_PPC_TM_CVMX, .n = ELF_NVMX,
+		.size = sizeof(vector128), .align = sizeof(vector128),
+		.active = tm_cvmx_active, .get = tm_cvmx_get, .set = tm_cvmx_set
+	},
+#endif
 };
 
 static const struct user_regset_view user_ppc_compat_view = {
-- 
1.9.3

^ permalink raw reply related

* [PATCH V4 5/8] powerpc, ptrace: Enable vr_(get/set) for transactional memory
From: Anshuman Khandual @ 2014-11-11  5:26 UTC (permalink / raw)
  To: linux-kernel, linuxppc-dev
  Cc: mikey, james.hogan, avagin, Paul.Clothier, peterz, palves, oleg,
	davem, dhowells, davej, akpm, sukadev, tglx, sam.bobroff
In-Reply-To: <1415683597-22819-1-git-send-email-khandual@linux.vnet.ibm.com>

This patch enables the vr_get which gets the running value of all
the VMX registers and the vr_set which sets the running value of
of all the VMX registers to accommodate in transaction ptrace
interface based requests.

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 arch/powerpc/kernel/ptrace.c | 94 ++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 91 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index fd36b32..2bbbd10 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -523,10 +523,30 @@ static int vr_active(struct task_struct *target,
 	return target->thread.used_vr ? regset->n : 0;
 }
 
+/*
+ * vr_get
+ *
+ * When the transaction is active, 'transact_vr' holds the current running
+ * value of all the VMX registers and 'vr_state' holds the last checkpointed
+ * value of all the VMX registers for the current transaction to fall back
+ * on in case it aborts. When transaction is not active 'vr_state' holds
+ * the current running state of all the VMX registers. So this function which
+ * gets the current running values of all the VMX registers, needs to know
+ * whether any transaction is active or not.
+ *
+ * Userspace interface buffer layout:
+ *
+ * struct data {
+ *	vector128	vr[32];
+ *	vector128	vscr;
+ *	vector128	vrsave;
+ * };
+ */
 static int vr_get(struct task_struct *target, const struct user_regset *regset,
 		  unsigned int pos, unsigned int count,
 		  void *kbuf, void __user *ubuf)
 {
+	struct thread_vr_state *addr;
 	int ret;
 
 	flush_altivec_to_thread(target);
@@ -534,8 +554,19 @@ static int vr_get(struct task_struct *target, const struct user_regset *regset,
 	BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
 		     offsetof(struct thread_vr_state, vr[32]));
 
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+	if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
+		flush_fp_to_thread(target);
+		flush_tmregs_to_thread(target);
+		addr = &target->thread.transact_vr;
+	} else {
+		addr = &target->thread.vr_state;
+	}
+#else
+	addr = &target->thread.vr_state;
+#endif
 	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-				  &target->thread.vr_state, 0,
+				  addr, 0,
 				  33 * sizeof(vector128));
 	if (!ret) {
 		/*
@@ -546,7 +577,16 @@ static int vr_get(struct task_struct *target, const struct user_regset *regset,
 			u32 word;
 		} vrsave;
 		memset(&vrsave, 0, sizeof(vrsave));
+
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+		if (MSR_TM_ACTIVE(target->thread.regs->msr))
+			vrsave.word = target->thread.transact_vrsave;
+		else
+			vrsave.word = target->thread.vrsave;
+#else
 		vrsave.word = target->thread.vrsave;
+#endif
+
 		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &vrsave,
 					  33 * sizeof(vector128), -1);
 	}
@@ -554,10 +594,30 @@ static int vr_get(struct task_struct *target, const struct user_regset *regset,
 	return ret;
 }
 
+/*
+ * vr_set
+ *
+ * When the transaction is active, 'transact_vr' holds the current running
+ * value of all the VMX registers and 'vr_state' holds the last checkpointed
+ * value of all the VMX registers for the current transaction to fall back
+ * on in case it aborts. When transaction is not active 'vr_state' holds
+ * the current running state of all the VMX registers. So this function which
+ * sets the current running values of all the VMX registers, needs to know
+ * whether any transaction is active or not.
+ *
+ * Userspace interface buffer layout:
+ *
+ * struct data {
+ *	vector128	vr[32];
+ *	vector128	vscr;
+ *	vector128	vrsave;
+ * };
+ */
 static int vr_set(struct task_struct *target, const struct user_regset *regset,
 		  unsigned int pos, unsigned int count,
 		  const void *kbuf, const void __user *ubuf)
 {
+	struct thread_vr_state *addr;
 	int ret;
 
 	flush_altivec_to_thread(target);
@@ -565,8 +625,19 @@ static int vr_set(struct task_struct *target, const struct user_regset *regset,
 	BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
 		     offsetof(struct thread_vr_state, vr[32]));
 
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+	if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
+		flush_fp_to_thread(target);
+		flush_tmregs_to_thread(target);
+		addr = &target->thread.transact_vr;
+	} else {
+		addr = &target->thread.vr_state;
+	}
+#else
+	addr = &target->thread.vr_state;
+#endif
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-				 &target->thread.vr_state, 0,
+				 addr, 0,
 				 33 * sizeof(vector128));
 	if (!ret && count > 0) {
 		/*
@@ -577,11 +648,28 @@ static int vr_set(struct task_struct *target, const struct user_regset *regset,
 			u32 word;
 		} vrsave;
 		memset(&vrsave, 0, sizeof(vrsave));
+
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+		if (MSR_TM_ACTIVE(target->thread.regs->msr))
+			vrsave.word = target->thread.transact_vrsave;
+		else
+			vrsave.word = target->thread.vrsave;
+#else
 		vrsave.word = target->thread.vrsave;
+#endif
 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &vrsave,
 					 33 * sizeof(vector128), -1);
-		if (!ret)
+		if (!ret) {
+
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+			if (MSR_TM_ACTIVE(target->thread.regs->msr))
+				target->thread.transact_vrsave = vrsave.word;
+			else
+				target->thread.vrsave = vrsave.word;
+#else
 			target->thread.vrsave = vrsave.word;
+#endif
+		}
 	}
 
 	return ret;
-- 
1.9.3

^ permalink raw reply related

* [PATCH V4 4/8] powerpc, ptrace: Enable fpr_(get/set) for transactional memory
From: Anshuman Khandual @ 2014-11-11  5:26 UTC (permalink / raw)
  To: linux-kernel, linuxppc-dev
  Cc: mikey, james.hogan, avagin, Paul.Clothier, peterz, palves, oleg,
	davem, dhowells, davej, akpm, sukadev, tglx, sam.bobroff
In-Reply-To: <1415683597-22819-1-git-send-email-khandual@linux.vnet.ibm.com>

This patch enables the fpr_get which gets the running value of all
the FPR registers and the fpr_set which sets the running value of
of all the FPR registers to accommodate in transaction ptrace
interface based requests.

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 arch/powerpc/kernel/ptrace.c | 103 ++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 97 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index f21897b..fd36b32 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -357,6 +357,33 @@ static int gpr_set(struct task_struct *target, const struct user_regset *regset,
 	return ret;
 }
 
+
+/*
+ * fpr_get
+ *
+ * When the transaction is active, 'transact_fp' holds the current running
+ * value of all FPR registers and 'fp_state' holds the last checkpointed
+ * value of all FPR registers for the current transaction. When transaction
+ * is not active 'fp_state' holds the current running state of all the FPR
+ * registers. So this function which returns the current running values of
+ * all the FPR registers, needs to know whether any transaction is active
+ * or not.
+ *
+ * Userspace interface buffer layout:
+ *
+ * struct data {
+ *	u64	fpr[32];
+ *	u64	fpscr;
+ * };
+ *
+ * There are two config options CONFIG_VSX and CONFIG_PPC_TRANSACTIONAL_MEM
+ * which determines the final code in this function. All the combinations of
+ * these two config options are possible except the one below as transactional
+ * memory config pulls in CONFIG_VSX automatically.
+ *
+ *	!defined(CONFIG_VSX) && defined(CONFIG_PPC_TRANSACTIONAL_MEM)
+ *
+ */
 static int fpr_get(struct task_struct *target, const struct user_regset *regset,
 		   unsigned int pos, unsigned int count,
 		   void *kbuf, void __user *ubuf)
@@ -367,22 +394,64 @@ static int fpr_get(struct task_struct *target, const struct user_regset *regset,
 #endif
 	flush_fp_to_thread(target);
 
-#ifdef CONFIG_VSX
+#if defined(CONFIG_VSX) && defined(CONFIG_PPC_TRANSACTIONAL_MEM)
+	/* copy to local buffer then write that out */
+	if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
+		flush_altivec_to_thread(target);
+		flush_tmregs_to_thread(target);
+		for (i = 0; i < 32 ; i++)
+			buf[i] = target->thread.TS_TRANS_FPR(i);
+		buf[32] = target->thread.transact_fp.fpscr;
+	} else {
+		for (i = 0; i < 32 ; i++)
+			buf[i] = target->thread.TS_FPR(i);
+		buf[32] = target->thread.fp_state.fpscr;
+	}
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
+#endif
+
+#if defined(CONFIG_VSX) && !defined(CONFIG_PPC_TRANSACTIONAL_MEM)
 	/* copy to local buffer then write that out */
 	for (i = 0; i < 32 ; i++)
 		buf[i] = target->thread.TS_FPR(i);
 	buf[32] = target->thread.fp_state.fpscr;
 	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
+#endif
 
-#else
+
+#if !defined(CONFIG_VSX) && !defined(CONFIG_PPC_TRANSACTIONAL_MEM)
 	BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
 		     offsetof(struct thread_fp_state, fpr[32][0]));
-
 	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 				   &target->thread.fp_state, 0, -1);
 #endif
 }
 
+/*
+ * fpr_set
+ *
+ * When the transaction is active, 'transact_fp' holds the current running
+ * value of all FPR registers and 'fp_state' holds the last checkpointed
+ * value of all FPR registers for the current transaction. When transaction
+ * is not active 'fp_state' holds the current running state of all the FPR
+ * registers. So this function which setss the current running values of
+ * all the FPR registers, needs to know whether any transaction is active
+ * or not.
+ *
+ * Userspace interface buffer layout:
+ *
+ * struct data {
+ *	u64	fpr[32];
+ *	u64	fpscr;
+ * };
+ *
+ * There are two config options CONFIG_VSX and CONFIG_PPC_TRANSACTIONAL_MEM
+ * which determines the final code in this function. All the combinations of
+ * these two config options are possible except the one below as transactional
+ * memory config pulls in CONFIG_VSX automatically.
+ *
+ *	!defined(CONFIG_VSX) && defined(CONFIG_PPC_TRANSACTIONAL_MEM)
+ */
 static int fpr_set(struct task_struct *target, const struct user_regset *regset,
 		   unsigned int pos, unsigned int count,
 		   const void *kbuf, const void __user *ubuf)
@@ -393,7 +462,27 @@ static int fpr_set(struct task_struct *target, const struct user_regset *regset,
 #endif
 	flush_fp_to_thread(target);
 
-#ifdef CONFIG_VSX
+#if defined(CONFIG_VSX) && defined(CONFIG_PPC_TRANSACTIONAL_MEM)
+	/* copy to local buffer then write that out */
+	i = user_regset_copyin(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
+	if (i)
+		return i;
+
+	if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
+		flush_altivec_to_thread(target);
+		flush_tmregs_to_thread(target);
+		for (i = 0; i < 32 ; i++)
+			target->thread.TS_TRANS_FPR(i) = buf[i];
+		target->thread.transact_fp.fpscr = buf[32];
+	} else {
+		for (i = 0; i < 32 ; i++)
+			target->thread.TS_FPR(i) = buf[i];
+		target->thread.fp_state.fpscr = buf[32];
+	}
+	return 0;
+#endif
+
+#if defined(CONFIG_VSX) && !defined(CONFIG_PPC_TRANSACTIONAL_MEM)
 	/* copy to local buffer then write that out */
 	i = user_regset_copyin(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
 	if (i)
@@ -402,12 +491,14 @@ static int fpr_set(struct task_struct *target, const struct user_regset *regset,
 		target->thread.TS_FPR(i) = buf[i];
 	target->thread.fp_state.fpscr = buf[32];
 	return 0;
-#else
+#endif
+
+#if !defined(CONFIG_VSX) && !defined(CONFIG_PPC_TRANSACTIONAL_MEM)
 	BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
 		     offsetof(struct thread_fp_state, fpr[32][0]));
-
 	return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 				  &target->thread.fp_state, 0, -1);
+
 #endif
 }
 
-- 
1.9.3

^ permalink raw reply related

* [PATCH V4 1/8] elf: Add new PowerPC specifc core note sections
From: Anshuman Khandual @ 2014-11-11  5:26 UTC (permalink / raw)
  To: linux-kernel, linuxppc-dev
  Cc: mikey, james.hogan, avagin, Paul.Clothier, peterz, palves, oleg,
	davem, dhowells, davej, akpm, sukadev, tglx, sam.bobroff
In-Reply-To: <1415683597-22819-1-git-send-email-khandual@linux.vnet.ibm.com>

This patch adds four new core note sections for PowerPC transactional
memory and one core note section for general miscellaneous debug registers.
These addition of new elf core note sections extends the existing elf ABI
without affecting it in any manner.

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 include/uapi/linux/elf.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h
index ea9bf25..2260fc0 100644
--- a/include/uapi/linux/elf.h
+++ b/include/uapi/linux/elf.h
@@ -379,6 +379,11 @@ typedef struct elf64_shdr {
 #define NT_PPC_VMX	0x100		/* PowerPC Altivec/VMX registers */
 #define NT_PPC_SPE	0x101		/* PowerPC SPE/EVR registers */
 #define NT_PPC_VSX	0x102		/* PowerPC VSX registers */
+#define NT_PPC_TM_SPR	0x103		/* PowerPC TM special registers */
+#define NT_PPC_TM_CGPR	0x104		/* PowerpC TM checkpointed GPR */
+#define NT_PPC_TM_CFPR	0x105		/* PowerPC TM checkpointed FPR */
+#define NT_PPC_TM_CVMX	0x106		/* PowerPC TM checkpointed VMX */
+#define NT_PPC_MISC	0x107		/* PowerPC miscellaneous registers */
 #define NT_386_TLS	0x200		/* i386 TLS slots (struct user_desc) */
 #define NT_386_IOPERM	0x201		/* x86 io permission bitmap (1=deny) */
 #define NT_X86_XSTATE	0x202		/* x86 extended state using xsave */
-- 
1.9.3

^ permalink raw reply related

* [PATCH V4 2/8] powerpc, process: Add functions flush_tm_state, flush_tmregs_to_thread
From: Anshuman Khandual @ 2014-11-11  5:26 UTC (permalink / raw)
  To: linux-kernel, linuxppc-dev
  Cc: mikey, james.hogan, avagin, Paul.Clothier, peterz, palves, oleg,
	davem, dhowells, davej, akpm, sukadev, tglx, sam.bobroff
In-Reply-To: <1415683597-22819-1-git-send-email-khandual@linux.vnet.ibm.com>

This patch creates a new function called flush_tm_state to flush
the existing transactional memory state from the thread. It also
creates a function called flush_tmregs_to_thread which will then
be used on subsequent patches in this series.

Signed-off-by: Anshuman Khandual <khandual@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/switch_to.h |  8 ++++++
 arch/powerpc/kernel/process.c        | 49 +++++++++++++++++++++++++++++-------
 2 files changed, 48 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/include/asm/switch_to.h b/arch/powerpc/include/asm/switch_to.h
index 58abeda..23752a9 100644
--- a/arch/powerpc/include/asm/switch_to.h
+++ b/arch/powerpc/include/asm/switch_to.h
@@ -82,6 +82,14 @@ static inline void flush_spe_to_thread(struct task_struct *t)
 }
 #endif
 
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+extern void flush_tmregs_to_thread(struct task_struct *);
+#else
+static inline void flush_tmregs_to_thread(struct task_struct *t)
+{
+}
+#endif
+
 static inline void clear_task_ebb(struct task_struct *t)
 {
 #ifdef CONFIG_PPC_BOOK3S_64
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index aa1df89..c36477b 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -745,6 +745,45 @@ void restore_tm_state(struct pt_regs *regs)
 #define __switch_to_tm(prev)
 #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
 
+/*
+ * flush_tm_state
+ *
+ * Flush TM state out so we can copy it.  __switch_to_tm() does this
+ * flush but it removes the checkpointed state from the current CPU and
+ * transitions the CPU out of TM mode.  Hence we need to call
+ * tm_recheckpoint_new_task() (on the same task) to restore the
+ * checkpointed state back and the TM mode.
+ */
+static void flush_tm_state(struct task_struct *src)
+{
+	__switch_to_tm(src);
+	tm_recheckpoint_new_task(src);
+}
+
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+void flush_tmregs_to_thread(struct task_struct *tsk)
+{
+	/*
+	 * If task is not current, it should have been flushed
+	 * already to it's thread_struct during __switch_to().
+	 */
+	if (tsk != current)
+		return;
+
+	preempt_disable();
+	if (tsk->thread.regs) {
+		/*
+		 * If we are still current, the TM state need to
+		 * be flushed to thread_struct as it will be still
+		 * present in the current cpu.
+		 */
+		if (MSR_TM_ACTIVE(tsk->thread.regs->msr))
+			flush_tm_state(tsk);
+	}
+	preempt_enable();
+}
+#endif
+
 struct task_struct *__switch_to(struct task_struct *prev,
 	struct task_struct *new)
 {
@@ -1079,15 +1118,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
 	flush_altivec_to_thread(src);
 	flush_vsx_to_thread(src);
 	flush_spe_to_thread(src);
-	/*
-	 * Flush TM state out so we can copy it.  __switch_to_tm() does this
-	 * flush but it removes the checkpointed state from the current CPU and
-	 * transitions the CPU out of TM mode.  Hence we need to call
-	 * tm_recheckpoint_new_task() (on the same task) to restore the
-	 * checkpointed state back and the TM mode.
-	 */
-	__switch_to_tm(src);
-	tm_recheckpoint_new_task(src);
+	flush_tm_state(src);
 
 	*dst = *src;
 
-- 
1.9.3

^ permalink raw reply related

* [PATCH V4 0/8] Add new PowerPC specific ELF core notes
From: Anshuman Khandual @ 2014-11-11  5:26 UTC (permalink / raw)
  To: linux-kernel, linuxppc-dev
  Cc: mikey, james.hogan, avagin, Paul.Clothier, peterz, palves, oleg,
	davem, dhowells, davej, akpm, sukadev, tglx, sam.bobroff

	This patch series adds five new ELF core note sections which can be
used with existing ptrace request PTRACE_GETREGSET-SETREGSET for accessing
various transactional memory and miscellaneous debug register sets on PowerPC
platform.

Previous versions:
==================
RFC: https://lkml.org/lkml/2014/4/1/292
V1:  https://lkml.org/lkml/2014/4/2/43
V2:  https://lkml.org/lkml/2014/5/5/88
V3:  https://lkml.org/lkml/2014/5/23/486

Changes in V4:
--------------
- Added one test program into the powerpc selftest bucket in this regard
- Split the 2nd patch in the previous series into four different patches
- Accommodated most of the review comments on the previous patch series
- Added a patch to merge functions __switch_to_tm and tm_reclaim_task

Changes in V3:
--------------
- Added two new error paths in every TM related get/set functions when regset
  support is not present on the system (ENODEV) or when the process does not
  have any transaction active (ENODATA) in the context
- Installed the active hooks for all the newly added regset core note types

Changes in V2:
--------------
- Removed all the power specific ptrace requests corresponding to new NT_PPC_*
  elf core note types. Now all the register sets can be accessed from ptrace
  through PTRACE_GETREGSET/PTRACE_SETREGSET using the individual NT_PPC* core
  note type instead
- Fixed couple of attribute values for REGSET_TM_CGPR register set
- Renamed flush_tmreg_to_thread as flush_tmregs_to_thread
- Fixed 32 bit checkpointed GPR support
- Changed commit messages accordingly

Test Result
-----------
The patch series has been verified both in 32 bit and 64 bit compiled mode.
Test result for the selftest test (64 bit compiled mode) can be found here.

test: tm_ptrace
tags: git_version:v3.18-rc4-9-g000adb7
=============Testing TM based PTRACE calls==============
-------TM Specific SPR------
TFHAR: 10000cc8
TEXASR: de0000018c000001
TFIAR: c0000000000414f0
TM ORIG_MSR: 50000f032
TM CH DSCR: a (PASSED)
TM CH TAR: 14 (PASSED)
TM CH PPR: 8000000000000 (PASSED)
-------TM Checkpointed GPR-----
TM CH NIP: 10000cc8
TM CH LINK: 10000af8
TM CH CCR: 22000422
TM CH GPR[0]: 0 (PASSED)
TM CH GPR[1]: 1 (PASSED)
TM CH GPR[2]: 2 (PASSED)
TM CH GPR[3]: 3 (PASSED)
TM CH GPR[4]: 4 (PASSED)
TM CH GPR[5]: 5 (PASSED)
TM CH GPR[6]: 6 (PASSED)
TM CH GPR[7]: 7 (PASSED)
TM CH GPR[8]: 8 (PASSED)
TM CH GPR[9]: 9 (PASSED)
TM CH GPR[10]: a (PASSED)
TM CH GPR[11]: b (PASSED)
TM CH GPR[12]: c (PASSED)
TM CH GPR[13]: d (PASSED)
TM CH GPR[14]: e (PASSED)
TM CH GPR[15]: f (PASSED)
TM CH GPR[16]: 0 (PASSED)
TM CH GPR[17]: 1 (PASSED)
TM CH GPR[18]: 2 (PASSED)
TM CH GPR[19]: 3 (PASSED)
TM CH GPR[20]: 4 (PASSED)
TM CH GPR[21]: 5 (PASSED)
TM CH GPR[22]: 6 (PASSED)
TM CH GPR[23]: 7 (PASSED)
TM CH GPR[24]: 8 (PASSED)
TM CH GPR[25]: 9 (PASSED)
TM CH GPR[26]: a (PASSED)
TM CH GPR[27]: b (PASSED)
TM CH GPR[28]: c (PASSED)
TM CH GPR[29]: d (PASSED)
TM CH GPR[30]: e (PASSED)
TM CH GPR[31]: f (PASSED)
-------TM Checkpointed FPR-----
TM CH FPSCR: 0
TM CH FPR[0]: 0 (PASSED)
TM CH FPR[1]: 1 (PASSED)
TM CH FPR[2]: 2 (PASSED)
TM CH FPR[3]: 3 (PASSED)
TM CH FPR[4]: 4 (PASSED)
TM CH FPR[5]: 5 (PASSED)
TM CH FPR[6]: 6 (PASSED)
TM CH FPR[7]: 7 (PASSED)
TM CH FPR[8]: 8 (PASSED)
TM CH FPR[9]: 9 (PASSED)
TM CH FPR[10]: a (PASSED)
TM CH FPR[11]: b (PASSED)
TM CH FPR[12]: c (PASSED)
TM CH FPR[13]: d (PASSED)
TM CH FPR[14]: e (PASSED)
TM CH FPR[15]: f (PASSED)
TM CH FPR[16]: 0 (PASSED)
TM CH FPR[17]: 1 (PASSED)
TM CH FPR[18]: 2 (PASSED)
TM CH FPR[19]: 3 (PASSED)
TM CH FPR[20]: 4 (PASSED)
TM CH FPR[21]: 5 (PASSED)
TM CH FPR[22]: 6 (PASSED)
TM CH FPR[23]: 7 (PASSED)
TM CH FPR[24]: 8 (PASSED)
TM CH FPR[25]: 9 (PASSED)
TM CH FPR[26]: a (PASSED)
TM CH FPR[27]: b (PASSED)
TM CH FPR[28]: c (PASSED)
TM CH FPR[29]: d (PASSED)
TM CH FPR[30]: e (PASSED)
TM CH FPR[31]: f (PASSED)
-------TM Running GPR-----
TM RN NIP: 10000de0
TM RN LINK: 10000af8
TM RN CCR: 2000422
TM RN GPR[0]: f (PASSED)
TM RN GPR[1]: e (PASSED)
TM RN GPR[2]: d (PASSED)
TM RN GPR[3]: c (PASSED)
TM RN GPR[4]: b (PASSED)
TM RN GPR[5]: a (PASSED)
TM RN GPR[6]: 9 (PASSED)
TM RN GPR[7]: 8 (PASSED)
TM RN GPR[8]: 7 (PASSED)
TM RN GPR[9]: 6 (PASSED)
TM RN GPR[10]: 5 (PASSED)
TM RN GPR[11]: 4 (PASSED)
TM RN GPR[12]: 3 (PASSED)
TM RN GPR[13]: 2 (PASSED)
TM RN GPR[14]: 1 (PASSED)
TM RN GPR[15]: 0 (PASSED)
TM RN GPR[16]: f (PASSED)
TM RN GPR[17]: e (PASSED)
TM RN GPR[18]: d (PASSED)
TM RN GPR[19]: c (PASSED)
TM RN GPR[20]: b (PASSED)
TM RN GPR[21]: a (PASSED)
TM RN GPR[22]: 9 (PASSED)
TM RN GPR[23]: 8 (PASSED)
TM RN GPR[24]: 7 (PASSED)
TM RN GPR[25]: 6 (PASSED)
TM RN GPR[26]: 5 (PASSED)
TM RN GPR[27]: 4 (PASSED)
TM RN GPR[28]: 3 (PASSED)
TM RN GPR[29]: 2 (PASSED)
TM RN GPR[30]: 1 (PASSED)
TM RN GPR[31]: 0 (PASSED)
-------TM Running FPR-----
TM RN FPSCR: 0
TM RN FPR[0]: f (PASSED)
TM RN FPR[1]: e (PASSED)
TM RN FPR[2]: d (PASSED)
TM RN FPR[3]: c (PASSED)
TM RN FPR[4]: b (PASSED)
TM RN FPR[5]: a (PASSED)
TM RN FPR[6]: 9 (PASSED)
TM RN FPR[7]: 8 (PASSED)
TM RN FPR[8]: 7 (PASSED)
TM RN FPR[9]: 6 (PASSED)
TM RN FPR[10]: 5 (PASSED)
TM RN FPR[11]: 4 (PASSED)
TM RN FPR[12]: 3 (PASSED)
TM RN FPR[13]: 2 (PASSED)
TM RN FPR[14]: 1 (PASSED)
TM RN FPR[15]: 0 (PASSED)
TM RN FPR[16]: f (PASSED)
TM RN FPR[17]: e (PASSED)
TM RN FPR[18]: d (PASSED)
TM RN FPR[19]: c (PASSED)
TM RN FPR[20]: b (PASSED)
TM RN FPR[21]: a (PASSED)
TM RN FPR[22]: 9 (PASSED)
TM RN FPR[23]: 8 (PASSED)
TM RN FPR[24]: 7 (PASSED)
TM RN FPR[25]: 6 (PASSED)
TM RN FPR[26]: 5 (PASSED)
TM RN FPR[27]: 4 (PASSED)
TM RN FPR[28]: 3 (PASSED)
TM RN FPR[29]: 2 (PASSED)
TM RN FPR[30]: 1 (PASSED)
TM RN FPR[31]: 0 (PASSED)
-------TM Running MISC Registers-------
TM RN DSCR: 32 (PASSED)
TM RN TAR: 3c (PASSED)
TM RN PPR: 4000000000000 (PASSED)
success: tm_ptrace

Anshuman Khandual (8):
  elf: Add new PowerPC specifc core note sections
  powerpc, process: Add functions flush_tm_state, flush_tmregs_to_thread
  powerpc, process: Merge functions __switch_to_tm and tm_reclaim_task
  powerpc, ptrace: Enable fpr_(get/set) for transactional memory
  powerpc, ptrace: Enable vr_(get/set) for transactional memory
  powerpc, ptrace: Enable support for transactional memory register sets
  powerpc, ptrace: Enable support for miscellaneous debug registers
  selftests, powerpc: Add new test case for TM related ptrace interfaces

 arch/powerpc/include/asm/switch_to.h           |   8 +
 arch/powerpc/include/uapi/asm/elf.h            |   3 +
 arch/powerpc/kernel/process.c                  |  65 +-
 arch/powerpc/kernel/ptrace.c                   | 965 ++++++++++++++++++++++++-
 include/uapi/linux/elf.h                       |   5 +
 tools/testing/selftests/powerpc/tm/Makefile    |   2 +-
 tools/testing/selftests/powerpc/tm/tm-ptrace.c | 529 ++++++++++++++
 7 files changed, 1533 insertions(+), 44 deletions(-)
 create mode 100644 tools/testing/selftests/powerpc/tm/tm-ptrace.c

-- 
1.9.3

^ permalink raw reply

* [PATCH] powerpc: Fix comment typos in arch/powerpc/include/asm/bitops.h
From: Boqun Feng @ 2014-11-11  4:50 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Boqun Feng, Michael Ellerman

In arch/powerpc/include/asm/bitops.h, the comments about bit numbers in
large (> 1 word) bitmaps have two typos:
- On ppc64 system, the LSB of the 4th word should be bit 192 rather than
  196, because if it's bit 196, bit 192-195 will be missing in the
  bitmap.
- On ppc32 system, the LSB of the second word should be bit 32 rather
  than 31, because bit 31 is already in the first word.

This patch fixes these typos.

Signed-off-by: Boqun Feng <boqun.feng@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/bitops.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h
index bd3bd57..a39ab08 100644
--- a/arch/powerpc/include/asm/bitops.h
+++ b/arch/powerpc/include/asm/bitops.h
@@ -14,9 +14,9 @@
  *
  * The bitop functions are defined to work on unsigned longs, so for a
  * ppc64 system the bits end up numbered:
- *   |63..............0|127............64|191...........128|255...........196|
+ *   |63..............0|127............64|191...........128|255...........192|
  * and on ppc32:
- *   |31.....0|63....31|95....64|127...96|159..128|191..160|223..192|255..224|
+ *   |31.....0|63....32|95....64|127...96|159..128|191..160|223..192|255..224|
  *
  * There are a few little-endian macros used mostly for filesystem
  * bitmaps, these work on similar bit arrays layouts, but
-- 
2.1.3

^ permalink raw reply related

* Re: [PATCH] DT: add MDIO node for FMan node
From: Scott Wood @ 2014-11-11  0:23 UTC (permalink / raw)
  To: shh.xie; +Cc: devicetree, linuxppc-dev, Shaohui Xie, Emilian.Medve
In-Reply-To: <1415102196-9238-1-git-send-email-shh.xie@gmail.com>

On Tue, 2014-11-04 at 19:56 +0800, shh.xie@gmail.com wrote:
> From: Shaohui Xie <Shaohui.Xie@freescale.com>
> 
> This binding is for FMan MDIO, it covers FMan v2 & FMan v3.
> 
> Signed-off-by: Shaohui Xie <Shaohui.Xie@freescale.com>
> ---
> based on http://patchwork.ozlabs.org/patch/390351/
> for 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/scottwood/linux.git

Are there any other FMan pieces that are missing from the above patch?

>  .../devicetree/bindings/powerpc/fsl/fman.txt       | 69 ++++++++++++++++++++++
>  1 file changed, 69 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/powerpc/fsl/fman.txt b/Documentation/devicetree/bindings/powerpc/fsl/fman.txt
> index da8e5f2..83c2f14 100644
> --- a/Documentation/devicetree/bindings/powerpc/fsl/fman.txt
> +++ b/Documentation/devicetree/bindings/powerpc/fsl/fman.txt
> @@ -7,6 +7,7 @@ CONTENTS
>    - FMan MURAM Node
>    - FMan dTSEC/XGEC/mEMAC Node
>    - FMan IEEE 1588 Node
> +  - FMan MDIO Node
>    - Example
>  
>  =============================================================================
> @@ -352,6 +353,67 @@ ptp-timer@fe000 {
>  };
>  
>  =============================================================================
> +FMan MDIO Node
> +
> +DESCRIPTION
> +
> +The MDIO is a bus to which the PHY devices are connected.
> +
> +PROPERTIES
> +
> +- compatible
> +		Usage: required
> +		Value type: <stringlist>
> +		Definition: A standard property.
> +		Must include "fsl,fman-mdio" for 1 Gb/s MDIO from FMan v2.
> +		Must include "fsl,fman-xmdio" for 10 Gb/s MDIO from FMan v2.
> +		Must include "fsl,fman-memac-mdio" for 1/10 Gb/s MDIO from
> +		FMan v3.
> +
> +- reg
> +		Usage: required
> +		Value type: <prop-encoded-array>
> +		Definition: A standard property.
> +
> +- bus-frequency
> +		Usage: optional
> +		Value type: <u32>
> +		Definition: Default MDIO bus clock speed.

Use clocks/clock-names

> +- interrupts
> +		Usage: optional
> +		Value type: <prop-encoded-array>
> +		Definition: MDIO controller event interrupts.

One interrupt or multiple?

> +
> +- type
> +		Usage: required for FMan v3
> +		Value type: <stringlist>
> +		Definition: A standard property.

What standard is "type" defined in?

> +		FMan v3 has internal MDIO for internal PCS(Physical Coding
> +		Sublayer) PHYs and external MDIO for external PHYs.
> +		The settings and programming routines for internal/external
> +		MDIO are different. Must include "internal" for internal MDIO,
> +		must include "external" for external MDIO.

I assume fman v2 is always internal?  How about a boolean
"fsl,fman-internal-phy" property instead?

> +
> +EXAMPLE
> +
> +Example for FMan v2:
> +
> +mdio@f1000 {
> +	compatible = "fsl,fman-xmdio";
> +	reg = <0xf1000 0x1000>;
> +};
> +
> +Example for FMan v3:
> +
> +mdio@fd000 {
> +	compatible = "fsl,fman-memac-mdio";
> +	reg = <0xfd000 0x1000>;
> +	bus-frequency = <2500000>;
> +	type = "external";
> +};
> +
> +=============================================================================
>  Example
>  
>  fman@400000 {
> @@ -526,4 +588,11 @@ fman@400000 {
>  		compatible = "fsl,fman-ptp-timer";
>  		reg = <0xfe000 0x1000>;
>  	};
> +
> +	mdio@fd000 {
> +		compatible = "fsl,fman-memac-mdio";
> +		reg = <0xfd000 0x1000>;
> +		bus-frequency = <2500000>;
> +		type = "external";
> +	};
>  };

The rest of the example is fman v2; don't mix an fman v3 node in with
that.

-Scott

^ permalink raw reply

* [PATCH] powerpc: Bad NULL pointer check in udbg_uart_getc_poll
From: Anton Blanchard @ 2014-11-10 22:12 UTC (permalink / raw)
  To: benh, paulus, mpe; +Cc: linuxppc-dev

We have some code in udbg_uart_getc_poll that tries to protect
against a NULL udbg_uart_in, but gets it all wrong.

Found with the LLVM static analyzer (scan-build).

Fixes: 309257484cc1 ("powerpc: Cleanup udbg_16550 and add support for LPC PIO-only UARTs")
Cc: stable@vger.kernel.org
Signed-off-by: Anton Blanchard <anton@samba.org>
---
 arch/powerpc/kernel/udbg_16550.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c
index 6e7c492..3faf393 100644
--- a/arch/powerpc/kernel/udbg_16550.c
+++ b/arch/powerpc/kernel/udbg_16550.c
@@ -69,7 +69,9 @@ static void udbg_uart_putc(char c)
 
 static int udbg_uart_getc_poll(void)
 {
-	if (!udbg_uart_in || !(udbg_uart_in(UART_LSR) & LSR_DR))
+	if (!udbg_uart_in)
+		return -1;
+	if (!(udbg_uart_in(UART_LSR) & LSR_DR))
 		return udbg_uart_in(UART_RBR);
 	return -1;
 }
-- 
1.9.1

^ permalink raw reply related

* Re: [PATCH] powerpc: mitigate impact of decrementer reset
From: Paul Clarke @ 2014-11-10 20:58 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: paulmck, linuxppc-dev
In-Reply-To: <1415614083.5769.18.camel@kernel.crashing.org>

On 11/10/2014 04:08 AM, Benjamin Herrenschmidt wrote:
> On Tue, 2014-10-07 at 14:13 -0500, Paul Clarke wrote:
>> The POWER ISA defines an always-running decrementer which can be used
>> to schedule interrupts after a certain time interval has elapsed.
>> The decrementer counts down at the same frequency as the Time Base,
>> which is 512 MHz.  The maximum value of the decrementer is 0x7fffffff.
>> This works out to a maximum interval of about 4.19 seconds.
>>
>> If a larger interval is desired, the kernel will set the decrementer
>> to its maximum value and reset it after it expires (underflows)
>> a sufficient number of times until the desired interval has elapsed.
>>
>> The negative effect of this is that an unwanted latency spike will
>> impact normal processing at most every 4.19 seconds.  On an IBM
>> POWER8-based system, this spike was measured at about 25-30
>> microseconds, much of which was basic, opportunistic housekeeping
>> tasks that could otherwise have waited.
>>
>> This patch short-circuits the reset of the decrementer, exiting after
>> the decrementer reset, but before the housekeeping tasks if the only
>> need for the interrupt is simply to reset it.  After this patch,
>> the latency spike was measured at about 150 nanoseconds.
>
> Doesn't this break the irq_work stuff ? We trigger it with a set_dec(1);
> and your patch will probably cause it to be skipped...

You're right.

I'm confused by the division between timer_interrupt() and 
__timer_interrupt().  The former is called with interrupts disabled (and 
enables them), but also calls irq_enter()/irq_exit().  Why are those 
calls not in __timer_interrupt()?  (If they were, the short-circuit 
logic might be a bit easier to put directly in __timer_interrupt(), 
which would eliminate any duplicate code.)

It looks like __timer_interrupt is only called directly by the broadcast 
timer IPI handler.  (Why is __timer_interrupt not static?)  Does this 
path not need irq_enter/irq_exit?
	
>> Signed-off-by: Paul A. Clarke <pc@us.ibm.com>
>> ---
>>    arch/powerpc/kernel/time.c | 13 +++++++++++++
>>    1 file changed, 13 insertions(+)
>>
>> diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
>> index 368ab37..962a06b 100644
>> --- a/arch/powerpc/kernel/time.c
>> +++ b/arch/powerpc/kernel/time.c
>> @@ -528,6 +528,7 @@ void timer_interrupt(struct pt_regs * regs)
>>    {
>>    	struct pt_regs *old_regs;
>>    	u64 *next_tb = &__get_cpu_var(decrementers_next_tb);
>> +	u64 now;
>>
>>    	/* Ensure a positive value is written to the decrementer, or else
>>    	 * some CPUs will continue to take decrementer exceptions.
>> @@ -550,6 +551,18 @@ void timer_interrupt(struct pt_regs * regs)
>>    	 */
>>    	may_hard_irq_enable();
>>
>> +	/* If this is simply the decrementer expiring (underflow) due to
>> +	 * the limited size of the decrementer, and not a set timer,
>> +	 * reset (if needed) and return
>> +	 */
>> +	now = get_tb_or_rtc();
>> +	if (now < *next_tb) {
>> +		now = *next_tb - now;
>> +		if (now <= DECREMENTER_MAX)
>> +			set_dec((int)now);
>> +		__get_cpu_var(irq_stat).timer_irqs_others++;
>> +		return;
>> +	}
>>
>>    #if defined(CONFIG_PPC32) && defined(CONFIG_PPC_PMAC)
>>    	if (atomic_read(&ppc_n_lost_interrupts) != 0)

Regards,
PC

^ permalink raw reply

* Re: [PATCH v2 net-next] PPC: bpf_jit_comp: add SKF_AD_HATYPE instruction
From: Alexei Starovoitov @ 2014-11-10 18:26 UTC (permalink / raw)
  To: Denis Kirjanov
  Cc: Philippe Bergheaud, netdev@vger.kernel.org, Daniel Borkmann,
	linuxppc-dev
In-Reply-To: <1415599183-3883-1-git-send-email-kda@linux-powerpc.org>

On Sun, Nov 9, 2014 at 9:59 PM, Denis Kirjanov <kda@linux-powerpc.org> wrote:
> Add BPF extension SKF_AD_HATYPE to ppc JIT to check
> the hw type of the interface
>
> Before:
> [   57.723666] test_bpf: #20 LD_HATYPE
> [   57.723675] BPF filter opcode 0020 (@0) unsupported
> [   57.724168] 48 48 PASS
>
> After:
> [  103.053184] test_bpf: #20 LD_HATYPE 7 6 PASS
>
> CC: Alexei Starovoitov<alexei.starovoitov@gmail.com>
> CC: Daniel Borkmann<dborkman@redhat.com>
> CC: Philippe Bergheaud<felix@linux.vnet.ibm.com>
> Signed-off-by: Denis Kirjanov <kda@linux-powerpc.org>
>
> v2: address Alexei's comments
> ---
>  arch/powerpc/net/bpf_jit_comp.c | 17 +++++++++++++----
>  1 file changed, 13 insertions(+), 4 deletions(-)
>
> diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
> index d110e28..d3fa80d 100644
> --- a/arch/powerpc/net/bpf_jit_comp.c
> +++ b/arch/powerpc/net/bpf_jit_comp.c
> @@ -361,6 +361,11 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
>                                                             protocol));
>                         break;
>                 case BPF_ANC | SKF_AD_IFINDEX:
> +               case BPF_ANC | SKF_AD_HATYPE:
> +                       BUILD_BUG_ON(FIELD_SIZEOF(struct net_device,
> +                                               ifindex) != 4);
> +                       BUILD_BUG_ON(FIELD_SIZEOF(struct net_device,
> +                                               type) != 2);
>                         PPC_LD_OFFS(r_scratch1, r_skb, offsetof(struct sk_buff,
>                                                                 dev));
>                         PPC_CMPDI(r_scratch1, 0);
> @@ -368,14 +373,18 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
>                                 PPC_BCC(COND_EQ, addrs[ctx->pc_ret0]);
>                         } else {
>                                 /* Exit, returning 0; first pass hits here. */
> -                               PPC_BCC_SHORT(COND_NE, (ctx->idx*4)+12);
> +                               PPC_BCC_SHORT(COND_NE, ctx->idx * 4 + 12);
>                                 PPC_LI(r_ret, 0);
>                                 PPC_JMP(exit_addr);
>                         }
> -                       BUILD_BUG_ON(FIELD_SIZEOF(struct net_device,
> -                                                 ifindex) != 4);
> -                       PPC_LWZ_OFFS(r_A, r_scratch1,
> +                       if (code == (BPF_ANC | SKF_AD_IFINDEX)) {
> +                               PPC_LWZ_OFFS(r_A, r_scratch1,
>                                      offsetof(struct net_device, ifindex));
> +                       } else {
> +                               PPC_LHZ_OFFS(r_A, r_scratch1,
> +                                    offsetof(struct net_device, type));

formatting is a bit off here, but that's minor.
Acked-by: Alexei Starovoitov <ast@plumgrid.com>

^ permalink raw reply

* RE: [PATCH] DT: add MDIO node for FMan node
From: Shaohui Xie @ 2014-11-10 10:19 UTC (permalink / raw)
  To: shh.xie@gmail.com, linuxppc-dev@lists.ozlabs.org,
	devicetree@vger.kernel.org, Scott Wood
  Cc: Emilian Medve
In-Reply-To: <1415102196-9238-1-git-send-email-shh.xie@gmail.com>

Ping.

Best Regards,=20
Shaohui Xie

> -----Original Message-----
> From: shh.xie@gmail.com [mailto:shh.xie@gmail.com]
> Sent: Tuesday, November 04, 2014 7:57 PM
> To: linuxppc-dev@lists.ozlabs.org; devicetree@vger.kernel.org; Wood
> Scott-B07421
> Cc: Medve Emilian-EMMEDVE1; Xie Shaohui-B21989
> Subject: [PATCH] DT: add MDIO node for FMan node
>=20
> From: Shaohui Xie <Shaohui.Xie@freescale.com>
>=20
> This binding is for FMan MDIO, it covers FMan v2 & FMan v3.
>=20
> Signed-off-by: Shaohui Xie <Shaohui.Xie@freescale.com>
> ---
> based on http://patchwork.ozlabs.org/patch/390351/
> for 'next' of
> git://git.kernel.org/pub/scm/linux/kernel/git/scottwood/linux.git
>=20
>  .../devicetree/bindings/powerpc/fsl/fman.txt       | 69
> ++++++++++++++++++++++
>  1 file changed, 69 insertions(+)
>=20
> diff --git a/Documentation/devicetree/bindings/powerpc/fsl/fman.txt
> b/Documentation/devicetree/bindings/powerpc/fsl/fman.txt
> index da8e5f2..83c2f14 100644
> --- a/Documentation/devicetree/bindings/powerpc/fsl/fman.txt
> +++ b/Documentation/devicetree/bindings/powerpc/fsl/fman.txt
> @@ -7,6 +7,7 @@ CONTENTS
>    - FMan MURAM Node
>    - FMan dTSEC/XGEC/mEMAC Node
>    - FMan IEEE 1588 Node
> +  - FMan MDIO Node
>    - Example
>=20
>=20
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> =3D=3D=3D=3D
> @@ -352,6 +353,67 @@ ptp-timer@fe000 {
>  };
>=20
>=20
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> =3D=3D=3D=3D
> +FMan MDIO Node
> +
> +DESCRIPTION
> +
> +The MDIO is a bus to which the PHY devices are connected.
> +
> +PROPERTIES
> +
> +- compatible
> +		Usage: required
> +		Value type: <stringlist>
> +		Definition: A standard property.
> +		Must include "fsl,fman-mdio" for 1 Gb/s MDIO from FMan v2.
> +		Must include "fsl,fman-xmdio" for 10 Gb/s MDIO from FMan v2.
> +		Must include "fsl,fman-memac-mdio" for 1/10 Gb/s MDIO from
> +		FMan v3.
> +
> +- reg
> +		Usage: required
> +		Value type: <prop-encoded-array>
> +		Definition: A standard property.
> +
> +- bus-frequency
> +		Usage: optional
> +		Value type: <u32>
> +		Definition: Default MDIO bus clock speed.
> +
> +- interrupts
> +		Usage: optional
> +		Value type: <prop-encoded-array>
> +		Definition: MDIO controller event interrupts.
> +
> +- type
> +		Usage: required for FMan v3
> +		Value type: <stringlist>
> +		Definition: A standard property.
> +		FMan v3 has internal MDIO for internal PCS(Physical Coding
> +		Sublayer) PHYs and external MDIO for external PHYs.
> +		The settings and programming routines for internal/external
> +		MDIO are different. Must include "internal" for internal MDIO,
> +		must include "external" for external MDIO.
> +
> +EXAMPLE
> +
> +Example for FMan v2:
> +
> +mdio@f1000 {
> +	compatible =3D "fsl,fman-xmdio";
> +	reg =3D <0xf1000 0x1000>;
> +};
> +
> +Example for FMan v3:
> +
> +mdio@fd000 {
> +	compatible =3D "fsl,fman-memac-mdio";
> +	reg =3D <0xfd000 0x1000>;
> +	bus-frequency =3D <2500000>;
> +	type =3D "external";
> +};
> +
> +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> =3D=3D=3D=3D=3D
>  Example
>=20
>  fman@400000 {
> @@ -526,4 +588,11 @@ fman@400000 {
>  		compatible =3D "fsl,fman-ptp-timer";
>  		reg =3D <0xfe000 0x1000>;
>  	};
> +
> +	mdio@fd000 {
> +		compatible =3D "fsl,fman-memac-mdio";
> +		reg =3D <0xfd000 0x1000>;
> +		bus-frequency =3D <2500000>;
> +		type =3D "external";
> +	};
>  };
> --
> 1.8.4.1

^ permalink raw reply

* Re: [PATCH] cpuidle/powernv: Fix return value of idle index in fastsleep
From: Preeti U Murthy @ 2014-11-10 10:48 UTC (permalink / raw)
  To: mpe, mikey, joel.stanley, benh@kernel.crashing.org
  Cc: rjw, linuxppc-dev, linux-kernel
In-Reply-To: <20141027132618.9085.97044.stgit@preeti.in.ibm.com>

Hi Ben, Mikey,

Can you please take a look at this patch?  I feel the commit dcb1869 was
just a plug-in solution. Shouldn't we take a look at this again?

Ideally we should not need this check. With the cpuidle redesign on
PowerNV going in, we can enable fastsleep at bootup itself and without
checks on any debug parameters such as powersave_nap .We will then only
need to check for powersave_nap == 0 and return only if that is the
case. This check is still required since the user can disable all deep
idle states by setting powersave_nap to 0.

Regards
Preeti U Murthy

On 10/27/2014 06:56 PM, Preeti U Murthy wrote:
> Commit dcb18694 : Fix ipi on Palmeto added a workaround to disable
> going into fastsleep on Palmeto boards which was reported to fail
> to boot when fastsleep was enabled. However it missed returning
> an idle index. Fix this.
> 
> There is probably no harm in returning the index of fastsleep
> although the cpu did not enter this state. The governor will notice
> the difference in the residency time in the idle state and the
> target residency of the idle state and prevent cpus from entering
> fastsleep from that point on. Hence the usage and time statistics
> logged for fastsleep will not be out of sync with reality except
> for the first entry.
> 
> Signed-off-by: Preeti U Murthy <preeti@linux.vnet.ibm.com>
> ---
> Do we still need this workaround? Or can we get rid of the check
> on powersave_nap altogether?
> ---
> 
>  drivers/cpuidle/cpuidle-powernv.c |    2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/cpuidle/cpuidle-powernv.c b/drivers/cpuidle/cpuidle-powernv.c
> index fa79392..c18da24 100644
> --- a/drivers/cpuidle/cpuidle-powernv.c
> +++ b/drivers/cpuidle/cpuidle-powernv.c
> @@ -70,7 +70,7 @@ static int fastsleep_loop(struct cpuidle_device *dev,
>  	unsigned long new_lpcr;
>  
>  	if (powersave_nap < 2)
> -		return;
> +		return index;
>  	if (unlikely(system_state < SYSTEM_RUNNING))
>  		return index;
>  
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
> 

^ permalink raw reply

* Re: [PATCH] powerpc: mitigate impact of decrementer reset
From: Benjamin Herrenschmidt @ 2014-11-10 10:08 UTC (permalink / raw)
  To: Paul Clarke; +Cc: linuxppc-dev
In-Reply-To: <54343B54.4060500@us.ibm.com>

On Tue, 2014-10-07 at 14:13 -0500, Paul Clarke wrote:
> The POWER ISA defines an always-running decrementer which can be used
> to schedule interrupts after a certain time interval has elapsed.
> The decrementer counts down at the same frequency as the Time Base,
> which is 512 MHz.  The maximum value of the decrementer is 0x7fffffff.
> This works out to a maximum interval of about 4.19 seconds.
> 
> If a larger interval is desired, the kernel will set the decrementer
> to its maximum value and reset it after it expires (underflows)
> a sufficient number of times until the desired interval has elapsed.
> 
> The negative effect of this is that an unwanted latency spike will
> impact normal processing at most every 4.19 seconds.  On an IBM
> POWER8-based system, this spike was measured at about 25-30
> microseconds, much of which was basic, opportunistic housekeeping
> tasks that could otherwise have waited.
> 
> This patch short-circuits the reset of the decrementer, exiting after
> the decrementer reset, but before the housekeeping tasks if the only
> need for the interrupt is simply to reset it.  After this patch,
> the latency spike was measured at about 150 nanoseconds.

Doesn't this break the irq_work stuff ? We trigger it with a set_dec(1);
and your patch will probably cause it to be skipped...

Cheers,
Ben.

> Signed-off-by: Paul A. Clarke <pc@us.ibm.com>
> ---
>   arch/powerpc/kernel/time.c | 13 +++++++++++++
>   1 file changed, 13 insertions(+)
> 
> diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
> index 368ab37..962a06b 100644
> --- a/arch/powerpc/kernel/time.c
> +++ b/arch/powerpc/kernel/time.c
> @@ -528,6 +528,7 @@ void timer_interrupt(struct pt_regs * regs)
>   {
>   	struct pt_regs *old_regs;
>   	u64 *next_tb = &__get_cpu_var(decrementers_next_tb);
> +	u64 now;
> 
>   	/* Ensure a positive value is written to the decrementer, or else
>   	 * some CPUs will continue to take decrementer exceptions.
> @@ -550,6 +551,18 @@ void timer_interrupt(struct pt_regs * regs)
>   	 */
>   	may_hard_irq_enable();
> 
> +	/* If this is simply the decrementer expiring (underflow) due to
> +	 * the limited size of the decrementer, and not a set timer,
> +	 * reset (if needed) and return
> +	 */
> +	now = get_tb_or_rtc();
> +	if (now < *next_tb) {
> +		now = *next_tb - now;
> +		if (now <= DECREMENTER_MAX)
> +			set_dec((int)now);
> +		__get_cpu_var(irq_stat).timer_irqs_others++;
> +		return;
> +	}
> 
>   #if defined(CONFIG_PPC32) && defined(CONFIG_PPC_PMAC)
>   	if (atomic_read(&ppc_n_lost_interrupts) != 0)

^ permalink raw reply

* Re: [PATCH 0/2] Add IPMI support for powernv powerpc machines
From: Benjamin Herrenschmidt @ 2014-11-10  6:57 UTC (permalink / raw)
  To: Alistair Popple; +Cc: openipmi-developer, linuxppc-dev, Jeremy Kerr, minyard
In-Reply-To: <11418996.omepm2UeRF@mexican>

On Mon, 2014-11-10 at 17:01 +1100, Alistair Popple wrote:
> Ben,
> 
> > 
> > Our OPAL interface can only do one at a time ? Because our underlying FW
> > driver already has a queue ..
> 
> The OPAL interface supports sending more than one message at a time using the 
> underlying FW queue as you suggest. However in theory the interface doesn't 
> make any response order guarantees, but in practice they should be ordered as 
> our BMC doesn't send out-of-order responses.

Can't we put some ID in the response message ? OPAL messages have
room...

Cheers,
Ben.

> Regards,
> 
> Alistair
> 
> > > > I'll look at doing that.  If that is the case, then your NULL check
> > > > for current message should probably be a BUG_ON().
> > > 
> > > OK, I'll update this when the msghandler bit is implemented.
> > > 
> > > > Do you need to handle any BMC flags?  Particularly incoming events?
> > > 
> > > Not at this stage - we may in future though.
> > > 
> > > Cheers,
> > > 
> > > 
> > > Jeremy
> > > _______________________________________________
> > > Linuxppc-dev mailing list
> > > Linuxppc-dev@lists.ozlabs.org
> > > https://lists.ozlabs.org/listinfo/linuxppc-dev
> > 
> > _______________________________________________
> > Linuxppc-dev mailing list
> > Linuxppc-dev@lists.ozlabs.org
> > https://lists.ozlabs.org/listinfo/linuxppc-dev

^ permalink raw reply

* [PATCH] tty: pr_warning->pr_warn and logging neatening
From: Joe Perches @ 2014-11-10  6:46 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Jiri Slaby; +Cc: linuxppc-dev, linux-kernel, linux-serial

Convert the pr_warning to the more common pr_warn.

Other miscellanea:

o Convert unusual PR_FMT define and uses to pr_fmt
o Remove unnecessary OOM message
o Fix grammar in an error message
o Convert a pr_warning with a KERN_ERR to pr_err

Signed-off-by: Joe Perches <joe@perches.com>
---
 drivers/tty/ehv_bytechan.c           |  4 ++--
 drivers/tty/hvc/hvcs.c               |  2 +-
 drivers/tty/isicom.c                 | 14 +++++++-------
 drivers/tty/serial/bfin_sport_uart.c |  5 +++--
 drivers/tty/serial/mfd.c             |  2 +-
 drivers/tty/serial/mrst_max3110.c    | 27 ++++++++++++---------------
 drivers/tty/vt/keyboard.c            |  6 +++---
 drivers/tty/vt/vt.c                  |  4 ++--
 8 files changed, 31 insertions(+), 33 deletions(-)

diff --git a/drivers/tty/ehv_bytechan.c b/drivers/tty/ehv_bytechan.c
index 4f485e8..9d29d7e 100644
--- a/drivers/tty/ehv_bytechan.c
+++ b/drivers/tty/ehv_bytechan.c
@@ -309,8 +309,8 @@ static int __init ehv_bc_console_init(void)
 	 * handle for udbg.
 	 */
 	if (stdout_bc != CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE)
-		pr_warning("ehv-bc: udbg handle %u is not the stdout handle\n",
-			   CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE);
+		pr_warn("ehv-bc: udbg handle %u is not the stdout handle\n",
+			CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE);
 #endif
 
 	/* add_preferred_console() must be called before register_console(),
diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c
index 81e939e..00bec633 100644
--- a/drivers/tty/hvc/hvcs.c
+++ b/drivers/tty/hvc/hvcs.c
@@ -1575,7 +1575,7 @@ static int __init hvcs_module_init(void)
 	 */
 	rc = driver_create_file(&(hvcs_vio_driver.driver), &driver_attr_rescan);
 	if (rc)
-		pr_warning(KERN_ERR "HVCS: Failed to create rescan file (err %d)\n", rc);
+		pr_err("HVCS: Failed to create rescan file (err %d)\n", rc);
 
 	return 0;
 }
diff --git a/drivers/tty/isicom.c b/drivers/tty/isicom.c
index 858291c..59ed783 100644
--- a/drivers/tty/isicom.c
+++ b/drivers/tty/isicom.c
@@ -249,7 +249,7 @@ static int lock_card(struct isi_board *card)
 		spin_unlock_irqrestore(&card->card_lock, card->flags);
 		msleep(10);
 	}
-	pr_warning("Failed to lock Card (0x%lx)\n", card->base);
+	pr_warn("Failed to lock Card (0x%lx)\n", card->base);
 
 	return 0;	/* Failed to acquire the card! */
 }
@@ -378,13 +378,13 @@ static inline int __isicom_paranoia_check(struct isi_port const *port,
 	char *name, const char *routine)
 {
 	if (!port) {
-		pr_warning("Warning: bad isicom magic for dev %s in %s.\n",
-			   name, routine);
+		pr_warn("Warning: bad isicom magic for dev %s in %s\n",
+			name, routine);
 		return 1;
 	}
 	if (port->magic != ISICOM_MAGIC) {
-		pr_warning("Warning: NULL isicom port for dev %s in %s.\n",
-			   name, routine);
+		pr_warn("Warning: NULL isicom port for dev %s in %s\n",
+			name, routine);
 		return 1;
 	}
 
@@ -546,8 +546,8 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
 	byte_count = header & 0xff;
 
 	if (channel + 1 > card->port_count) {
-		pr_warning("%s(0x%lx): %d(channel) > port_count.\n",
-			   __func__, base, channel+1);
+		pr_warn("%s(0x%lx): %d(channel) > port_count\n",
+			__func__, base, channel + 1);
 		outw(0x0000, base+0x04); /* enable interrupts */
 		spin_unlock(&card->card_lock);
 		return IRQ_HANDLED;
diff --git a/drivers/tty/serial/bfin_sport_uart.c b/drivers/tty/serial/bfin_sport_uart.c
index d62d8da..67d4083 100644
--- a/drivers/tty/serial/bfin_sport_uart.c
+++ b/drivers/tty/serial/bfin_sport_uart.c
@@ -517,14 +517,15 @@ static void sport_set_termios(struct uart_port *port,
 		up->csize = 5;
 		break;
 	default:
-		pr_warning("requested word length not supported\n");
+		pr_warn("requested word length not supported\n");
+		break;
 	}
 
 	if (termios->c_cflag & CSTOPB) {
 		up->stopb = 1;
 	}
 	if (termios->c_cflag & PARENB) {
-		pr_warning("PAREN bits is not supported yet\n");
+		pr_warn("PAREN bit is not supported yet\n");
 		/* up->parib = 1; */
 	}
 
diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c
index 445799d..e1f4fda 100644
--- a/drivers/tty/serial/mfd.c
+++ b/drivers/tty/serial/mfd.c
@@ -1371,7 +1371,7 @@ static void hsu_global_init(void)
 	hsu->iolen = 0x1000;
 
 	if (!(request_mem_region(hsu->paddr, hsu->iolen, "HSU global")))
-		pr_warning("HSU: error in request mem region\n");
+		pr_warn("HSU: error in request mem region\n");
 
 	hsu->reg = ioremap_nocache((unsigned long)hsu->paddr, hsu->iolen);
 	if (!hsu->reg) {
diff --git a/drivers/tty/serial/mrst_max3110.c b/drivers/tty/serial/mrst_max3110.c
index 1504a14..77239d5 100644
--- a/drivers/tty/serial/mrst_max3110.c
+++ b/drivers/tty/serial/mrst_max3110.c
@@ -27,6 +27,8 @@
  *    interrupt for a low speed UART device
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #ifdef CONFIG_MAGIC_SYSRQ
 #define SUPPORT_SYSRQ
 #endif
@@ -47,8 +49,6 @@
 
 #include "mrst_max3110.h"
 
-#define PR_FMT	"mrst_max3110: "
-
 #define UART_TX_NEEDED 1
 #define CON_TX_NEEDED  2
 #define BIT_IRQ_PENDING    3
@@ -127,8 +127,8 @@ static int max3110_out(struct uart_max3110 *max, const u16 out)
 	*obuf = out;
 	ret = max3110_write_then_read(max, obuf, ibuf, 2, 1);
 	if (ret) {
-		pr_warning(PR_FMT "%s(): get err msg %d when sending 0x%x\n",
-				__func__, ret, out);
+		pr_warn("%s: get err msg %d when sending 0x%x\n",
+			__func__, ret, out);
 		goto exit;
 	}
 
@@ -153,10 +153,8 @@ static int max3110_read_multi(struct uart_max3110 *max)
 
 	blen = M3110_RX_FIFO_DEPTH * sizeof(u16);
 	buf = kzalloc(blen * 2, GFP_KERNEL | GFP_DMA);
-	if (!buf) {
-		pr_warning(PR_FMT "%s(): fail to alloc dma buffer\n", __func__);
+	if (!buf)
 		return 0;
-	}
 
 	/* tx/rx always have the same length */
 	obuf = buf;
@@ -212,13 +210,13 @@ serial_m3110_con_setup(struct console *co, char *options)
 	int parity = 'n';
 	int flow = 'n';
 
-	pr_info(PR_FMT "setting up console\n");
+	pr_info("setting up console\n");
 
 	if (co->index == -1)
 		co->index = 0;
 
 	if (!max) {
-		pr_err(PR_FMT "pmax is NULL, return");
+		pr_err("pmax is NULL, return\n");
 		return -ENODEV;
 	}
 
@@ -296,8 +294,7 @@ static void send_circ_buf(struct uart_max3110 *max,
 
 			ret = max3110_write_then_read(max, obuf, ibuf, blen, 0);
 			if (ret)
-				pr_warning(PR_FMT "%s(): get err msg %d\n",
-						__func__, ret);
+				pr_warn("%s: get err msg %d\n", __func__, ret);
 
 			receive_chars(max, ibuf, len);
 
@@ -411,7 +408,7 @@ static int max3110_main_thread(void *_max)
 	int ret = 0;
 	struct circ_buf *xmit = &max->con_xmit;
 
-	pr_info(PR_FMT "start main thread\n");
+	pr_info("start main thread\n");
 
 	do {
 		wait_event_interruptible(*wq,
@@ -455,7 +452,7 @@ static int max3110_read_thread(void *_max)
 {
 	struct uart_max3110 *max = _max;
 
-	pr_info(PR_FMT "start read thread\n");
+	pr_info("start read thread\n");
 	do {
 		/*
 		 * If can't acquire the mutex, it means the main thread
@@ -481,7 +478,7 @@ static int serial_m3110_startup(struct uart_port *port)
 	int ret = 0;
 
 	if (port->line != 0) {
-		pr_err(PR_FMT "uart port startup failed\n");
+		pr_err("uart port startup failed\n");
 		return -1;
 	}
 
@@ -504,7 +501,7 @@ static int serial_m3110_startup(struct uart_port *port)
 		if (IS_ERR(max->read_thread)) {
 			ret = PTR_ERR(max->read_thread);
 			max->read_thread = NULL;
-			pr_err(PR_FMT "Can't create read thread!\n");
+			pr_err("Can't create read thread!\n");
 			return ret;
 		}
 	}
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index 9d00088..acfb4c0 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -926,7 +926,7 @@ static void k_brl(struct vc_data *vc, unsigned char value, char up_flag)
 
 	if (kbd->kbdmode != VC_UNICODE) {
 		if (!up_flag)
-			pr_warning("keyboard mode must be unicode for braille patterns\n");
+			pr_warn("keyboard mode must be unicode for braille patterns\n");
 		return;
 	}
 
@@ -1310,8 +1310,8 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
 	if (raw_mode && !hw_raw)
 		if (emulate_raw(vc, keycode, !down << 7))
 			if (keycode < BTN_MISC && printk_ratelimit())
-				pr_warning("can't emulate rawmode for keycode %d\n",
-					   keycode);
+				pr_warn("can't emulate rawmode for keycode %d\n",
+					keycode);
 
 #ifdef CONFIG_SPARC
 	if (keycode == KEY_A && sparc_l1_a_state) {
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index b33b00b..7b1665d 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -3849,8 +3849,8 @@ void do_unblank_screen(int leaving_gfx)
 		return;
 	if (!vc_cons_allocated(fg_console)) {
 		/* impossible */
-		pr_warning("unblank_screen: tty %d not allocated ??\n",
-			   fg_console+1);
+		pr_warn("unblank_screen: tty %d not allocated ??\n",
+			fg_console + 1);
 		return;
 	}
 	vc = vc_cons[fg_console].d;

^ permalink raw reply related

* Re: [PATCH 0/2] Add IPMI support for powernv powerpc machines
From: Jeremy Kerr @ 2014-11-10  6:41 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: openipmi-developer, linuxppc-dev, minyard
In-Reply-To: <1415598090.5769.15.camel@kernel.crashing.org>

Hi Ben,

> Our OPAL interface can only do one at a time ? Because our underlying
> FW driver already has a queue ..

The Linux driver needs to match responses to their requests, so the
driver needs to keep a reference to the requests that we've sent. The
current implementation is very simple: we just keep one pointer, and
require that there's only one outstanding request.

To have multiple outstanding requests, our options here are that we either:

1) duplicate the si_intf's queuing code in the powernv driver; or

2) move the queuing code from the si_intf component to the generic
   IPMI msghander, and use that (so all drivers can assume a single
   outstanding request)

Corey has suggested the latter, which will only require a minimal change
to the powerpv IPMI driver.

Cheers,


Jeremy

^ permalink raw reply

* [PATCH v2 net-next] PPC: bpf_jit_comp: add SKF_AD_HATYPE instruction
From: Denis Kirjanov @ 2014-11-10  5:59 UTC (permalink / raw)
  To: netdev
  Cc: Philippe Bergheaud, linuxppc-dev, Denis Kirjanov, Daniel Borkmann,
	Alexei Starovoitov

Add BPF extension SKF_AD_HATYPE to ppc JIT to check
the hw type of the interface

Before:
[   57.723666] test_bpf: #20 LD_HATYPE
[   57.723675] BPF filter opcode 0020 (@0) unsupported
[   57.724168] 48 48 PASS

After:
[  103.053184] test_bpf: #20 LD_HATYPE 7 6 PASS

CC: Alexei Starovoitov<alexei.starovoitov@gmail.com>
CC: Daniel Borkmann<dborkman@redhat.com>
CC: Philippe Bergheaud<felix@linux.vnet.ibm.com>
Signed-off-by: Denis Kirjanov <kda@linux-powerpc.org>

v2: address Alexei's comments
---
 arch/powerpc/net/bpf_jit_comp.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index d110e28..d3fa80d 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -361,6 +361,11 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
 							    protocol));
 			break;
 		case BPF_ANC | SKF_AD_IFINDEX:
+		case BPF_ANC | SKF_AD_HATYPE:
+			BUILD_BUG_ON(FIELD_SIZEOF(struct net_device,
+						ifindex) != 4);
+			BUILD_BUG_ON(FIELD_SIZEOF(struct net_device,
+						type) != 2);
 			PPC_LD_OFFS(r_scratch1, r_skb, offsetof(struct sk_buff,
 								dev));
 			PPC_CMPDI(r_scratch1, 0);
@@ -368,14 +373,18 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
 				PPC_BCC(COND_EQ, addrs[ctx->pc_ret0]);
 			} else {
 				/* Exit, returning 0; first pass hits here. */
-				PPC_BCC_SHORT(COND_NE, (ctx->idx*4)+12);
+				PPC_BCC_SHORT(COND_NE, ctx->idx * 4 + 12);
 				PPC_LI(r_ret, 0);
 				PPC_JMP(exit_addr);
 			}
-			BUILD_BUG_ON(FIELD_SIZEOF(struct net_device,
-						  ifindex) != 4);
-			PPC_LWZ_OFFS(r_A, r_scratch1,
+			if (code == (BPF_ANC | SKF_AD_IFINDEX)) {
+				PPC_LWZ_OFFS(r_A, r_scratch1,
 				     offsetof(struct net_device, ifindex));
+			} else {
+				PPC_LHZ_OFFS(r_A, r_scratch1,
+				     offsetof(struct net_device, type));
+			}
+
 			break;
 		case BPF_ANC | SKF_AD_MARK:
 			BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, mark) != 4);
-- 
2.1.0

^ 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