LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] STAGING: Comedi: Build only on arches providing PAGE_KERNEL_NOCACHE
From: Martyn Welch @ 2011-06-23 12:13 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: devel, linux-m32r-ja, linux-m32r, Paul Mundt, linux-sh,
	Greg Kroah-Hartman, linux-kernel, Chris Metcalf, David Howells,
	linux-am33-list, Paul Mackerras, H. Peter Anvin, Thomas Gleixner,
	linux-arch, linuxppc-dev, Ingo Molnar, x86
In-Reply-To: <20110623120234.GA22524@linux-mips.org>

On 23/06/11 13:02, Ralf Baechle wrote:
> On Thu, Jun 23, 2011 at 12:53:36PM +0100, Martyn Welch wrote:
> 
>> On 23/06/11 12:45, Ralf Baechle wrote:
>>> On architectures that don't define PAGE_KERNEL_NOCACHE, the Comedi driver turns
>>> into tragedy:
>>>
>>>   CC [M]  drivers/staging/comedi/drivers.o
>>> drivers/staging/comedi/drivers.c: In function ‘comedi_buf_alloc’:
>>> drivers/staging/comedi/drivers.c:505:41: error: ‘PAGE_KERNEL_NOCACHE’ undeclared (first use in this function)
>>> drivers/staging/comedi/drivers.c:505:41: note: each undeclared identifier is rep orted only once for each function it appears in
>>> make[3]: *** [drivers/staging/comedi/drivers.o] Error 1
>>>
>>> Restrict the driver to only those architectures that define PAGE_KERNEL_NOCACHE.
>>>
>>> PAGE_KERNEL_NOCACHE is a kludge - some system architectures such as SGI IP27
>>> are even uable to offer uncached operation - at least in the way an unwitting
>>> driver might assume.  I haven't looked in details how the driver is using
>>> the area vmaped with PAGE_KERNEL_NOCACHE but maybe doing it XFS-style using
>>> cached memory and the flush_kernel_vmap_range / invalidate_kernel_vmap_range
>>> APIs in conjunction with the DMA API is a practical alternative.
>>>
>>> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
>>>
>>>  drivers/staging/comedi/Kconfig |    1 +
>>>  1 files changed, 1 insertions(+), 0 deletions(-)
>>>
>>> diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig
>>> index 1502d80..bccdc12 100644
>>> --- a/drivers/staging/comedi/Kconfig
>>> +++ b/drivers/staging/comedi/Kconfig
>>> @@ -2,6 +2,7 @@ config COMEDI
>>>  	tristate "Data acquisition support (comedi)"
>>>  	default N
>>>  	depends on m
>>> +	depends on BROKEN || FRV || M32R || MN10300 || SUPERH || TILE || X86
>>
>> I'm sure I got comedi to compile on a 32-bit PPC board not that long ago. Has
>> something changed, or is this just not an exhaustive list?
> 
> (Adding the PPC folks to cc.)
> 
> A "git grep -w PAGE_KERNEL_NOCACHE arch/powerpc/" doesn't find anything so
> I don't think the driver will build there.  I don't have a PPC toolchain
> to verify that.

Ah, just found the tree looks like I had a little patch to make it seemingly
work, though it will make it "not work" for most other archs at a guess (it
may not even be right on PPC):

diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
index 44d6b62..263ad3d 100644
--- a/drivers/staging/comedi/drivers.c
+++ b/drivers/staging/comedi/drivers.c
@@ -505,7 +505,7 @@ int comedi_buf_alloc(struct comedi_device *dev, struct
comedi_subdevice *s,
                }
                if (i == n_pages) {
                        async->prealloc_buf =
-                           vmap(pages, n_pages, VM_MAP, PAGE_KERNEL_NOCACHE);
+                           vmap(pages, n_pages, VM_MAP, PAGE_KERNEL_NC);
                }
                vfree(pages);

(Sorry for the wrapping)

-- 
Martyn Welch (Principal Software Engineer) | Registered in England and
GE Intelligent Platforms                   | Wales (3828642) at 100
T +44(0)127322748                          | Barbirolli Square, Manchester,
E martyn.welch@ge.com                      | M2 3AB  VAT:GB 927559189

^ permalink raw reply related

* Re: [PATCH] STAGING: Comedi: Build only on arches providing PAGE_KERNEL_NOCACHE
From: Ralf Baechle @ 2011-06-23 12:02 UTC (permalink / raw)
  To: Martyn Welch
  Cc: devel, linux-m32r-ja, linux-m32r, Paul Mundt, linux-sh,
	Greg Kroah-Hartman, linux-kernel, Chris Metcalf, David Howells,
	linux-am33-list, Paul Mackerras, H. Peter Anvin, Thomas Gleixner,
	linux-arch, linuxppc-dev, Ingo Molnar, x86
In-Reply-To: <4E032940.5010205@ge.com>

On Thu, Jun 23, 2011 at 12:53:36PM +0100, Martyn Welch wrote:

> On 23/06/11 12:45, Ralf Baechle wrote:
> > On architectures that don't define PAGE_KERNEL_NOCACHE, the Comedi driver turns
> > into tragedy:
> > 
> >   CC [M]  drivers/staging/comedi/drivers.o
> > drivers/staging/comedi/drivers.c: In function ‘comedi_buf_alloc’:
> > drivers/staging/comedi/drivers.c:505:41: error: ‘PAGE_KERNEL_NOCACHE’ undeclared (first use in this function)
> > drivers/staging/comedi/drivers.c:505:41: note: each undeclared identifier is rep orted only once for each function it appears in
> > make[3]: *** [drivers/staging/comedi/drivers.o] Error 1
> > 
> > Restrict the driver to only those architectures that define PAGE_KERNEL_NOCACHE.
> > 
> > PAGE_KERNEL_NOCACHE is a kludge - some system architectures such as SGI IP27
> > are even uable to offer uncached operation - at least in the way an unwitting
> > driver might assume.  I haven't looked in details how the driver is using
> > the area vmaped with PAGE_KERNEL_NOCACHE but maybe doing it XFS-style using
> > cached memory and the flush_kernel_vmap_range / invalidate_kernel_vmap_range
> > APIs in conjunction with the DMA API is a practical alternative.
> > 
> > Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
> > 
> >  drivers/staging/comedi/Kconfig |    1 +
> >  1 files changed, 1 insertions(+), 0 deletions(-)
> > 
> > diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig
> > index 1502d80..bccdc12 100644
> > --- a/drivers/staging/comedi/Kconfig
> > +++ b/drivers/staging/comedi/Kconfig
> > @@ -2,6 +2,7 @@ config COMEDI
> >  	tristate "Data acquisition support (comedi)"
> >  	default N
> >  	depends on m
> > +	depends on BROKEN || FRV || M32R || MN10300 || SUPERH || TILE || X86
> 
> I'm sure I got comedi to compile on a 32-bit PPC board not that long ago. Has
> something changed, or is this just not an exhaustive list?

(Adding the PPC folks to cc.)

A "git grep -w PAGE_KERNEL_NOCACHE arch/powerpc/" doesn't find anything so
I don't think the driver will build there.  I don't have a PPC toolchain
to verify that.

  Ralf

^ permalink raw reply

* Re: [PATCH] STAGING: Comedi: Build only on arches providing PAGE_KERNEL_NOCACHE
From: Kumar Gala @ 2011-06-23 12:10 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: devel, David Howells, linux-m32r, Paul Mundt, linux-sh,
	Greg Kroah-Hartman, linux-kernel, Chris Metcalf, Martyn Welch,
	linux-am33-list, Paul Mackerras, linux-m32r-ja, H. Peter Anvin,
	Thomas Gleixner, linux-arch, linuxppc-dev, Ingo Molnar, x86
In-Reply-To: <20110623120234.GA22524@linux-mips.org>


On Jun 23, 2011, at 7:02 AM, Ralf Baechle wrote:

> On Thu, Jun 23, 2011 at 12:53:36PM +0100, Martyn Welch wrote:
>=20
>> On 23/06/11 12:45, Ralf Baechle wrote:
>>> On architectures that don't define PAGE_KERNEL_NOCACHE, the Comedi =
driver turns
>>> into tragedy:
>>>=20
>>>  CC [M]  drivers/staging/comedi/drivers.o
>>> drivers/staging/comedi/drivers.c: In function =91comedi_buf_alloc=92:
>>> drivers/staging/comedi/drivers.c:505:41: error: =
=91PAGE_KERNEL_NOCACHE=92 undeclared (first use in this function)
>>> drivers/staging/comedi/drivers.c:505:41: note: each undeclared =
identifier is rep orted only once for each function it appears in
>>> make[3]: *** [drivers/staging/comedi/drivers.o] Error 1
>>>=20
>>> Restrict the driver to only those architectures that define =
PAGE_KERNEL_NOCACHE.
>>>=20
>>> PAGE_KERNEL_NOCACHE is a kludge - some system architectures such as =
SGI IP27
>>> are even uable to offer uncached operation - at least in the way an =
unwitting
>>> driver might assume.  I haven't looked in details how the driver is =
using
>>> the area vmaped with PAGE_KERNEL_NOCACHE but maybe doing it =
XFS-style using
>>> cached memory and the flush_kernel_vmap_range / =
invalidate_kernel_vmap_range
>>> APIs in conjunction with the DMA API is a practical alternative.
>>>=20
>>> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
>>>=20
>>> drivers/staging/comedi/Kconfig |    1 +
>>> 1 files changed, 1 insertions(+), 0 deletions(-)
>>>=20
>>> diff --git a/drivers/staging/comedi/Kconfig =
b/drivers/staging/comedi/Kconfig
>>> index 1502d80..bccdc12 100644
>>> --- a/drivers/staging/comedi/Kconfig
>>> +++ b/drivers/staging/comedi/Kconfig
>>> @@ -2,6 +2,7 @@ config COMEDI
>>> 	tristate "Data acquisition support (comedi)"
>>> 	default N
>>> 	depends on m
>>> +	depends on BROKEN || FRV || M32R || MN10300 || SUPERH || TILE || =
X86
>>=20
>> I'm sure I got comedi to compile on a 32-bit PPC board not that long =
ago. Has
>> something changed, or is this just not an exhaustive list?
>=20
> (Adding the PPC folks to cc.)
>=20
> A "git grep -w PAGE_KERNEL_NOCACHE arch/powerpc/" doesn't find =
anything so
> I don't think the driver will build there.  I don't have a PPC =
toolchain
> to verify that.

I can verify it fails on PPC as well:

drivers/staging/comedi/drivers.c: In function 'comedi_buf_alloc':
drivers/staging/comedi/drivers.c:505:37: error: 'PAGE_KERNEL_NOCACHE' =
undeclared (first use in this function)
drivers/staging/comedi/drivers.c:505:37: note: each undeclared =
identifier is reported only once for each function it appears in

However, we do have a #define for PAGE_KERNEL_NC.

- k=

^ permalink raw reply

* Fwd: [PATCH] powerpc, 460gt: Add 460gt as compatible in the check for 460ex-compatible crypto
From: Mike Williams @ 2011-06-23 14:21 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <BANLkTikKNqEoQxGA642h14eOUjZ3hGZaQw@mail.gmail.com>

On Wed, Jun 22, 2011 at 7:24 PM, Segher Boessenkool
<segher@kernel.crashing.org> wrote:
>> - =A0 =A0 =A0 if (of_find_compatible_node(NULL, NULL, "amcc,ppc460ex-cry=
pto")) {
>> + =A0 =A0 =A0 if (of_find_compatible_node(NULL, NULL, "amcc,ppc460ex-cry=
pto") ||
>> + =A0 =A0 =A0 =A0 =A0 of_find_compatible_node(NULL, NULL, "amcc,ppc460gt=
-crypto")) {
>
> If the device is actually compatible, the device tree node should claim
> it is, and you do not need this code change.

That was actually my first instinct, however I tried to follow the
current convention in the glacier and canyonlands DTS files, which is
to set every device compatible to 460gt or 460ex, depending on the
processor. Many of the devices are identical between the two, since
they are variations of the same SoC, so which is the preferred method?
Follow the device tree convention and add the compatibility check in
the driver, or alter the device trees? I'll send another patch if it's
the latter.

Thanks,
Mike

>
>
> Segher
>
>

^ permalink raw reply

* [PATCH 2/2] powerpc/86xx: improve calculation of DIU pixel clock on the MPC8610 HPCD
From: Timur Tabi @ 2011-06-23 16:16 UTC (permalink / raw)
  To: kumar.gala, linuxppc-dev
In-Reply-To: <1308845808-11392-1-git-send-email-timur@freescale.com>

mpc8610hpcd_set_pixel_clock() calculates the correct value of the PXCLK
bits in the CLKDVDR register for a given pixel clock rate.  The code which
performs this calculation is overly complicated and includes an error
estimation routine that doesn't work most of the time anyway.  Replace the
code with the simpler routine that's currently used on the P1022DS.

Signed-off-by: Timur Tabi <timur@freescale.com>
---
 arch/powerpc/platforms/86xx/mpc8610_hpcd.c |  107 ++++++++++++---------------
 1 files changed, 48 insertions(+), 59 deletions(-)

diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
index a896511..74e018e 100644
--- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
@@ -39,12 +39,19 @@
 #include <sysdev/fsl_pci.h>
 #include <sysdev/fsl_soc.h>
 #include <sysdev/simple_gpio.h>
+#include <asm/fsl_guts.h>
 
 #include "mpc86xx.h"
 
 static struct device_node *pixis_node;
 static unsigned char *pixis_bdcfg0, *pixis_arch;
 
+/* DIU Pixel Clock bits of the CLKDVDR Global Utilities register */
+#define CLKDVDR_PXCKEN		0x80000000
+#define CLKDVDR_PXCKINV		0x10000000
+#define CLKDVDR_PXCKDLY		0x06000000
+#define CLKDVDR_PXCLK_MASK	0x001F0000
+
 #ifdef CONFIG_SUSPEND
 static irqreturn_t mpc8610_sw9_irq(int irq, void *data)
 {
@@ -205,72 +212,54 @@ void mpc8610hpcd_set_monitor_port(int monitor_port)
 			     bdcfg[monitor_port]);
 }
 
+/**
+ * mpc8610hpcd_set_pixel_clock: program the DIU's clock
+ *
+ * @pixclock: the wavelength, in picoseconds, of the clock
+ */
 void mpc8610hpcd_set_pixel_clock(unsigned int pixclock)
 {
-	u32 __iomem *clkdvdr;
-	u32 temp;
-	/* variables for pixel clock calcs */
-	ulong  bestval, bestfreq, speed_ccb, minpixclock, maxpixclock;
-	ulong pixval;
-	long err;
-	int i;
-
-	clkdvdr = ioremap(get_immrbase() + 0xe0800, sizeof(u32));
-	if (!clkdvdr) {
-		printk(KERN_ERR "Err: can't map clock divider register!\n");
+	struct device_node *guts_np = NULL;
+	struct ccsr_guts_86xx __iomem *guts;
+	unsigned long freq;
+	u64 temp;
+	u32 pxclk;
+
+	/* Map the global utilities registers. */
+	guts_np = of_find_compatible_node(NULL, NULL, "fsl,mpc8610-guts");
+	if (!guts_np) {
+		pr_err("mpc8610hpcd: missing global utilties device node\n");
 		return;
 	}
 
-	/* Pixel Clock configuration */
-	speed_ccb = fsl_get_sys_freq();
-
-	/* Calculate the pixel clock with the smallest error */
-	/* calculate the following in steps to avoid overflow */
-	pr_debug("DIU pixclock in ps - %d\n", pixclock);
-	temp = 1000000000/pixclock;
-	temp *= 1000;
-	pixclock = temp;
-	pr_debug("DIU pixclock freq - %u\n", pixclock);
-
-	temp = pixclock * 5 / 100;
-	pr_debug("deviation = %d\n", temp);
-	minpixclock = pixclock - temp;
-	maxpixclock = pixclock + temp;
-	pr_debug("DIU minpixclock - %lu\n", minpixclock);
-	pr_debug("DIU maxpixclock - %lu\n", maxpixclock);
-	pixval = speed_ccb/pixclock;
-	pr_debug("DIU pixval = %lu\n", pixval);
-
-	err = 100000000;
-	bestval = pixval;
-	pr_debug("DIU bestval = %lu\n", bestval);
-
-	bestfreq = 0;
-	for (i = -1; i <= 1; i++) {
-		temp = speed_ccb / ((pixval+i) + 1);
-		pr_debug("DIU test pixval i= %d, pixval=%lu, temp freq. = %u\n",
-							i, pixval, temp);
-		if ((temp < minpixclock) || (temp > maxpixclock))
-			pr_debug("DIU exceeds monitor range (%lu to %lu)\n",
-				minpixclock, maxpixclock);
-		else if (abs(temp - pixclock) < err) {
-		  pr_debug("Entered the else if block %d\n", i);
-			err = abs(temp - pixclock);
-			bestval = pixval+i;
-			bestfreq = temp;
-		}
+	guts = of_iomap(guts_np, 0);
+	of_node_put(guts_np);
+	if (!guts) {
+		pr_err("mpc8610hpcd: could not map global utilties device\n");
+		return;
 	}
 
-	pr_debug("DIU chose = %lx\n", bestval);
-	pr_debug("DIU error = %ld\n NomPixClk ", err);
-	pr_debug("DIU: Best Freq = %lx\n", bestfreq);
-	/* Modify PXCLK in GUTS CLKDVDR */
-	pr_debug("DIU: Current value of CLKDVDR = 0x%08x\n", (*clkdvdr));
-	temp = (*clkdvdr) & 0x2000FFFF;
-	*clkdvdr = temp;		/* turn off clock */
-	*clkdvdr = temp | 0x80000000 | (((bestval) & 0x1F) << 16);
-	pr_debug("DIU: Modified value of CLKDVDR = 0x%08x\n", (*clkdvdr));
-	iounmap(clkdvdr);
+	/* Convert pixclock from a wavelength to a frequency */
+	temp = 1000000000000ULL;
+	do_div(temp, pixclock);
+	freq = temp;
+
+	/*
+	 * 'pxclk' is the ratio of the platform clock to the pixel clock.
+	 * On the MPC8610, the value programmed into CLKDVDR is the ratio
+	 * minus one.  The valid range of values is 2-31.
+	 */
+	pxclk = DIV_ROUND_CLOSEST(fsl_get_sys_freq(), freq) - 1;
+	pxclk = clamp_t(u32, pxclk, 2, 31);
+
+	/* Disable the pixel clock, and set it to non-inverted and no delay */
+	clrbits32(&guts->clkdvdr,
+		  CLKDVDR_PXCKEN | CLKDVDR_PXCKDLY | CLKDVDR_PXCLK_MASK);
+
+	/* Enable the clock and set the pxclk */
+	setbits32(&guts->clkdvdr, CLKDVDR_PXCKEN | (pxclk << 16));
+
+	iounmap(guts);
 }
 
 ssize_t mpc8610hpcd_show_monitor_port(int monitor_port, char *buf)
-- 
1.7.3.4

^ permalink raw reply related

* [PATCH 1/2] powerpc/86xx: enable the framebuffer console on the MPC8610 HPCD
From: Timur Tabi @ 2011-06-23 16:16 UTC (permalink / raw)
  To: kumar.gala, linuxppc-dev

Enable framebuffer console support by default in the defconfig on the
Freescale MPC8610 HPCD reference board.  This allows the boot messages to
be shown on the video display.

Signed-off-by: Timur Tabi <timur@freescale.com>
---
 arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig b/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
index 036bfb2..0db9ba0 100644
--- a/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
+++ b/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
@@ -89,6 +89,11 @@ CONFIG_I2C_MPC=y
 CONFIG_VIDEO_OUTPUT_CONTROL=y
 CONFIG_FB=y
 CONFIG_FB_FSL_DIU=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
 CONFIG_SOUND=y
 CONFIG_SND=y
 CONFIG_SND_MIXER_OSS=y
-- 
1.7.3.4

^ permalink raw reply related

* Re: [PATCH] libata/sas: only set FROZEN flag if new EH is supported
From: Nishanth Aravamudan @ 2011-06-23 17:15 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: linux-ide, jgarzik, wayneb, linux-kernel, Tejun Heo, Brian King,
	mbizon, linuxppc-dev
In-Reply-To: <1308804120.32158.202.camel@pasglop>

On 23.06.2011 [14:42:00 +1000], Benjamin Herrenschmidt wrote:
> On Thu, 2011-06-23 at 14:31 +1000, Benjamin Herrenschmidt wrote:
> > On Tue, 2011-06-21 at 15:30 -0500, Brian King wrote:
> > > Looks good to me. Jeff/Tejun - any issues with merging this?
> > 
> > BTW. Current upstream with that patch applied on a machine here leads to
> > several oddities, I don't know at this point whether any of that is
> > actually a regression :
> 
> Ooops... pressed "send" too quickly. Here's a log excerpt with some
> comments:

Hrm, I didn't see any of this on my box, which I thought was the same as
yours :)

> ipr: IBM Power RAID SCSI Device Driver version: 2.5.2 (April 27, 2011)
> ipr 0000:04:00.0: Found IOA with IRQ: 129
> ipr 0000:04:00.0: Initializing IOA.
> ipr 0000:04:00.0: Starting IOA initialization sequence.
> ipr 0000:04:00.0: Adapter firmware version: 04220029
> ipr 0000:04:00.0: IOA initialized.
> scsi0 : IBM 2B4C Storage Adapter
> scsi 0:0:4:0: Direct-Access     IBM      ST9300603SS      BB09 PQ: 0 ANSI: 6
> scsi scan: INQUIRY result too short (5), using 36
> 
> -> Are these odd INQUIRY results expected ?
> 
> scsi 0:0:5:0: Direct-Access                                    PQ: 0 ANSI: 0
> scsi 0:0:6:0: Direct-Access     IBM      ST9300603SS      BB09 PQ: 0 ANSI: 6
> scsi 0:0:7:0: Direct-Access     IBM      ST9300603SS      BB09 PQ: 0 ANSI: 6
> scsi scan: INQUIRY result too short (5), using 36
> scsi 0:0:18:0: Direct-Access                                    PQ: 0 ANSI: 0
> scsi 0:2:18:0: Enclosure         IBM      PSBPD6E4A  3GSAS 0109 PQ: 0 ANSI: 4
> scsi: unknown device type 31
> scsi 0:255:255:255: No Device         IBM      2B4C001SISIOA    0150 PQ: 0 ANSI: 0
> 
> -> The above looks odd, not sure what it means

The "unknown device type"? I see it all the time on lots of different
machines.

> ipr 0000:05:00.0: Found IOA with IRQ: 130
> ipr 0000:05:00.0: Initializing IOA.
> scsi 0:254:0:0: Processor         IBM      57CB001SISIOA    0150 PQ: 0 ANSI: 0
> ipr 0000:05:00.0: Starting IOA initialization sequence.
> ipr 0000:05:00.0: Adapter firmware version: 04220029
> ipr 0000:05:00.0: IOA initialized.
> scsi1 : IBM 57CB Storage Adapter
> scsi scan: INQUIRY result too short (5), using 36
> scsi 1:0:4:0: Direct-Access                                    PQ: 0 ANSI: 0
> scsi 1:0:5:0: Direct-Access     IBM      ST9300603SS      BB09 PQ: 0 ANSI: 6
> scsi scan: INQUIRY result too short (5), using 36
> scsi 1:0:6:0: Direct-Access                                    PQ: 0 ANSI: 0
> scsi 1:0:7:0: Direct-Access     IBM      ST9300603SS      BB09 PQ: 0 ANSI: 6
> scsi 1:0:18:0: Enclosure         IBM      PSBPD6E4A  3GSAS 0109 PQ: 0 ANSI: 4
> scsi: On host 1 channel 0 id 18 only 511 (max_scsi_report_luns) of 402653184 luns reported, try increasing max_scsi_report_luns.
> scsi: host 1 channel 0 id 18 lun 0xc0000007f01e810f has a LUN larger than currently supported.
> 
> -> Now that looks horribly wrong... that LUN number looks like a kernel pointer

Yeah, that's weird.

> scsi scan: INQUIRY result too short (5), using 36
> scsi 1:2:18:0: Direct-Access                                    PQ: 0 ANSI: 0
> ata1.00: ATAPI: IBM     RMBO0040532, SA61, max UDMA/100
> ata1.00: failed to IDENTIFY (device reports invalid type, err_mask=0x0)
> ata1.00: revalidation failed (errno=-22)
> ata1.00: disabled
> 
> -> So SATA works "better" with the patch but doesn't actually work properly :-)
> 
> scsi_alloc_sdev: Allocation failure during SCSI scanning, some SCSI devices might not be configured
> 
> -> That error could give us more info... not sure what it means, we do have plenty of 
> memory...

That message is sort of strange. It's not necessarily referring to
memory allocation failing, but the port allocation failing in the SCSI
code. And that just means an error, like the failed to IDENTIFY above,
is occurring in the allocation path. It *can* also mean memory
allocation failure, I think, just not in this case.

I don't know much about the following errors, though, sorry.

-Nish

> scsi 1:8:0:0: Enclosure         IBM      VSBPD6E4B  3GSAS   01 PQ: 0 ANSI: 2
> scsi: unknown device type 31
> scsi 1:255:255:255: No Device         IBM      57CB001SISIOA    0150 PQ: 0 ANSI: 0
> work_for_cpu used greatest stack depth: 9520 bytes left
> st: Version 20101219, fixed bufsize 32768, s/g segs 256
> sd 0:0:4:0: [sda] 585937500 512-byte logical blocks: (300 GB/279 GiB)
> sd 0:0:5:0: [sdb] 585937500 512-byte logical blocks: (300 GB/279 GiB)
> sd 0:0:6:0: [sdc] 585937500 512-byte logical blocks: (300 GB/279 GiB)
> sd 0:0:7:0: [sdd] 585937500 512-byte logical blocks: (300 GB/279 GiB)
> sd 0:0:18:0: [sde] READ CAPACITY failed
> sd 0:0:18:0: [sde]  Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
> sd 0:0:18:0: [sde]  Sense Key : Illegal Request [current] 
> sd 0:0:18:0: [sde]  Add. Sense: Invalid command operation code
> 
> -> Any idea what's up with that guy ?
> 
> sd 0:0:4:0: Attached scsi generic sg0 type 0
> sd 0:0:5:0: [sdb] Write Protect is off
> sd 0:0:5:0: Attached scsi generic sg1 type 0
> sd 0:0:18:0: [sde] Test WP failed, assume Write Enabled
> sd 0:0:6:0: Attached scsi generic sg2 type 0
> sd 0:0:18:0: [sde] Asking for cache data failed
> sd 0:0:7:0: Attached scsi generic sg3 type 0
> sd 0:0:18:0: [sde] Assuming drive cache: write through
> sd 1:2:18:0: [sdj] READ CAPACITY failed
> sd 1:2:18:0: [sdj]  Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
> sd 1:2:18:0: [sdj]  Sense Key : Illegal Request [current] 
> sd 1:2:18:0: [sdj]  Add. Sense: Invalid command operation code
> 
> -> And this one ?
> 
> There's more below ...
> 
> sd 0:0:18:0: Attached scsi generic sg4 type 0
> sd 1:0:4:0: [sdf] 585937500 512-byte logical blocks: (300 GB/279 GiB)
> scsi 0:2:18:0: Attached scsi generic sg5 type 13
> sd 1:0:6:0: [sdh] 585937500 512-byte logical blocks: (300 GB/279 GiB)
> scsi 0:255:255:255: Attached scsi generic sg6 type 31
> scsi 0:254:0:0: Attached scsi generic sg7 type 3
> sd 1:0:4:0: Attached scsi generic sg8 type 0
> sd 1:2:18:0: [sdj] Test WP failed, assume Write Enabled
> sd 1:0:5:0: Attached scsi generic sg9 type 0
> sd 1:0:6:0: Attached scsi generic sg10 type 0
> sd 1:0:7:0: [sdi] 585937500 512-byte logical blocks: (300 GB/279 GiB)
> sd 1:2:18:0: [sdj] Asking for cache data failed
> sd 1:2:18:0: [sdj] Assuming drive cache: write through
> sd 1:0:7:0: Attached scsi generic sg11 type 0
> scsi 1:0:18:0: Attached scsi generic sg12 type 13
> sd 0:0:4:0: [sda] Write Protect is off
> sd 1:2:18:0: Attached scsi generic sg13 type 0
> sd 0:0:18:0: [sde] READ CAPACITY failed
> sd 0:0:18:0: [sde]  Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
> sd 0:0:18:0: [sde]  Sense Key : Illegal Request [current] 
> sd 0:0:18:0: [sde]  Add. Sense: Invalid command operation code
> scsi 1:8:0:0: Attached scsi generic sg14 type 13
> scsi 1:255:255:255: Attached scsi generic sg15 type 31
> e1000: Intel(R) PRO/1000 Network Driver - version 7.3.21-k8-NAPI
> e1000: Copyright (c) 1999-2006 Intel Corporation.
> e1000e: Intel(R) PRO/1000 Network Driver - 1.3.10-k2
> e1000e: Copyright(c) 1999 - 2011 Intel Corporation.
> sd 1:0:6:0: [sdh] Write Protect is off
> sd 0:0:5:0: [sdb] Write cache: disabled, read cache: enabled, supports DPO and FUA
> sd 0:0:18:0: [sde] Test WP failed, assume Write Enabled
> sd 0:0:7:0: [sdd] Write Protect is off
> sd 1:2:18:0: [sdj] READ CAPACITY failed
> sd 1:2:18:0: [sdj]  Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
> sd 1:2:18:0: [sdj]  Sense Key : Illegal Request [current] 
> sd 1:2:18:0: [sdj]  Add. Sense: Invalid command operation code
> sd 0:0:18:0: [sde] Asking for cache data failed
> sd 0:0:18:0: [sde] Assuming drive cache: write through
> sd 0:0:18:0: [sde] Attached SCSI disk
> sd 1:0:5:0: [sdg] 585937500 512-byte logical blocks: (300 GB/279 GiB)
> sd 1:0:4:0: [sdf] Write Protect is off
> sd 1:2:18:0: [sdj] Test WP failed, assume Write Enabled
> sd 0:0:6:0: [sdc] Write Protect is off
> sd 1:2:18:0: [sdj] Asking for cache data failed
> sd 1:2:18:0: [sdj] Assuming drive cache: write through
> sd 1:2:18:0: [sdj] Attached SCSI disk
> sd 0:0:7:0: [sdd] Write cache: disabled, read cache: enabled, supports DPO and FUA
> sd 0:0:4:0: [sda] Write cache: disabled, read cache: enabled, supports DPO and FUA
> sd 1:0:6:0: [sdh] Write cache: disabled, read cache: enabled, supports DPO and FUA
> sd 1:0:4:0: [sdf] Write cache: disabled, read cache: enabled, supports DPO and FUA
> sd 1:0:5:0: [sdg] Write Protect is off
> sd 1:0:7:0: [sdi] Write Protect is off
> sd 0:0:6:0: [sdc] Write cache: disabled, read cache: enabled, supports DPO and FUA
> sd 1:0:7:0: [sdi] Write cache: disabled, read cache: enabled, supports DPO and FUA
> sd 1:0:5:0: [sdg] Write cache: disabled, read cache: enabled, supports DPO and FUA
>  sdb: unknown partition table
>  sdd: unknown partition table
>  sdh: unknown partition table
>  sdi: unknown partition table
>  sdf: [AIX] unknown partition table
>  sdg: unknown partition table
> e1000e 0002:03:00.0: Disabling ASPM  L1
>  sdc: unknown partition table
> e1000e 0002:03:00.0: (unregistered net_device): Failed to initialize MSI interrupts.  Falling back to legacy interrupts.
> scsi 1:254:0:0: Processor         IBM      2B4C001SISIOA    0150 PQ: 0 ANSI: 0
>  sda: [AIX] unknown partition table
> sd 0:0:5:0: [sdb] Attached SCSI disk
> sd 1:0:6:0: [sdh] Attached SCSI disk
> sd 1:0:7:0: [sdi] Attached SCSI disk
> sd 0:0:6:0: [sdc] Attached SCSI disk
> sd 1:0:5:0: [sdg] Attached SCSI disk
> sd 0:0:7:0: [sdd] Attached SCSI disk
> scsi 1:254:0:0: Attached scsi generic sg16 type 3
> sd 1:0:4:0: [sdf] Attached SCSI disk
> sd 0:0:4:0: [sda] Attached SCSI disk
> 
> Cheers,
> Ben.
> > 
> > 
> > > Thanks,
> > > 
> > > Brian
> > > 
> > > On 06/21/2011 11:07 AM, Nishanth Aravamudan wrote:
> > > > Ping on this -- Tejun, Brian, Jeff, this is a pretty annoying 2.6.39
> > > > regression which it would be good to have fixed in 3.0.
> > > > 
> > > > Thanks,
> > > > Nish
> > > > 
> > > > On 16.06.2011 [08:28:36 -0700], Nishanth Aravamudan wrote:
> > > >> On 16.06.2011 [08:28:39 -0500], Brian King wrote:
> > > >>> On 06/16/2011 02:51 AM, Tejun Heo wrote:
> > > >>>> On Wed, Jun 15, 2011 at 04:34:17PM -0700, Nishanth Aravamudan wrote:
> > > >>>>>> That looks like the right thing to do. For ipr's usage of
> > > >>>>>> libata, we don't have the concept of a port frozen state, so this flag
> > > >>>>>> should really never get set. The alternate way to fix this would be to
> > > >>>>>> only set ATA_PFLAG_FROZEN in ata_port_alloc if ap->ops->error_handler
> > > >>>>>> is not NULL.
> > > >>>>>
> > > >>>>> It seemed like ipr is as you say, but I wasn't sure if it was
> > > >>>>> appropriate to make the change above in the common libata-scis code or
> > > >>>>> not. I don't want to break some other device on accident.
> > > >>>>>
> > > >>>>> Also, I tried your suggestion, but I don't think that can happen in
> > > >>>>> ata_port_alloc? ata_port_alloc is allocated ap itself, and it seems like
> > > >>>>> ap->ops typically gets set only after ata_port_alloc returns?
> > > >>>>
> > > >>>> Maybe we can test error_handler in ata_sas_port_start()?
> > > >>>
> > > >>> Good point. Since libsas is converted to the new eh now, we would need to have
> > > >>> this test.
> > > >>
> > > >> Commit 7b3a24c57d2eeda8dba9c205342b12689c4679f9 ("ahci: don't enable
> > > >> port irq before handler is registered") caused a regression for CD-ROMs
> > > >> attached to the IPR SATA bus on Power machines:
> > > >>
> > > >>   ata_port_alloc: ENTER
> > > >>   ata_port_probe: ata1: bus probe begin
> > > >>   ata1.00: ata_dev_read_id: ENTER
> > > >>   ata1.00: failed to IDENTIFY (I/O error, err_mask=0x40)
> > > >>   ata1.00: ata_dev_read_id: ENTER
> > > >>   ata1.00: failed to IDENTIFY (I/O error, err_mask=0x40)
> > > >>   ata1.00: limiting speed to UDMA7:PIO5
> > > >>   ata1.00: ata_dev_read_id: ENTER
> > > >>   ata1.00: failed to IDENTIFY (I/O error, err_mask=0x40)
> > > >>   ata1.00: disabled
> > > >>   ata_port_probe: ata1: bus probe end
> > > >>   scsi_alloc_sdev: Allocation failure during SCSI scanning, some SCSI devices might not be configured
> > > >>
> > > >> The FROZEN flag added in that commit is only cleared by the new EH code,
> > > >> which is not used by ipr. Clear this flag in the SAS code if we don't
> > > >> support new EH.
> > > >>
> > > >> Reported-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> > > >> Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
> > > >>
> > > >> diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
> > > >> index d51f979..ebe1685 100644
> > > >> --- a/drivers/ata/libata-scsi.c
> > > >> +++ b/drivers/ata/libata-scsi.c
> > > >> @@ -3797,6 +3797,12 @@ EXPORT_SYMBOL_GPL(ata_sas_port_alloc);
> > > >>   */
> > > >>  int ata_sas_port_start(struct ata_port *ap)
> > > >>  {
> > > >> +	/*
> > > >> +	 * the port is marked as frozen at allocation time, but if we don't
> > > >> +	 * have new eh, we won't thaw it
> > > >> +	 */
> > > >> +	if (!ap->ops->error_handler)
> > > >> +		ap->pflags &= ~ATA_PFLAG_FROZEN;
> > > >>  	return 0;
> > > >>  }
> > > >>  EXPORT_SYMBOL_GPL(ata_sas_port_start);
> > > >>
> > > >>
> > > >> -- 
> > > >> Nishanth Aravamudan <nacc@us.ibm.com>
> > > >> IBM Linux Technology Center
> > > > 
> > > 
> > > 
> > 
> 
> 

-- 
Nishanth Aravamudan <nacc@us.ibm.com>
IBM Linux Technology Center

^ permalink raw reply

* Re: [PATCH] powerpc/85xx: disable timebase synchronization under the hypervisor
From: Scott Wood @ 2011-06-23 17:22 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Wood Scott-B07421, linuxppc-dev@ozlabs.org, paulus@samba.org,
	McClintock Matthew-B29882, Gala Kumar-B11780
In-Reply-To: <4E020268.2020809@freescale.com>

On Wed, 22 Jun 2011 09:55:36 -0500
Timur Tabi <timur@freescale.com> wrote:

> Kumar Gala wrote:
> >> >=20
> >> > Well, not exactly. Paul wants to break that up since we're adding so=
me
> >> > primitive support for 201 HV mode too (for 970's). Last we discussed,
> >> > the plan was to go for a generic HV mode bit and a separate bit for =
the
> >> > version.
> >> >=20
> >> > Cheers,
> >> > Ben.
>=20
> > Any ETA on Paul's intro of the FTR bit?  If not I'll pull this into my =
'next' tree and we can clean up later.
>=20
> Just FYI, this particular patch is because of a limitation in the Freesca=
le
> hypervisor.  It's not because we're running in guest mode.  If the hyperv=
isor
> provided full emulation of the timebase register, then we wouldn't need t=
his
> patch.  The same can be said of KVM or any other hypervisor.

=46rom Power ISA 2.06B, book III-E, section 9.2.1:

Virtualized Implementation Note:

In virtualized implementations, TBU and TBL are
read-only.

> So a generic HV mode bit is not going to help me, unless there's also a b=
it
> that's specific to our hypervisor.  And even then, we would need some way=
 to
> differentiate among different versions of our hypervisor, in case some fu=
ture
> version adds timebase support.=20

That's very unlikely to happen.

Ideally we would avoid doing this sync even when not running under a
hypervisor, as long as firmware has done the sync, and kexec hasn't messed
it up.  Besides being a waste of boot time, the firmware's sync is
probably tighter since it can use a platform-specific mechanism to start all
the timebases at once.

-Scott

^ permalink raw reply

* Re: [PATCH] powerpc/85xx: disable timebase synchronization under the hypervisor
From: Timur Tabi @ 2011-06-23 17:33 UTC (permalink / raw)
  To: Scott Wood
  Cc: Wood Scott-B07421, linuxppc-dev@ozlabs.org, paulus@samba.org,
	McClintock Matthew-B29882, Gala Kumar-B11780
In-Reply-To: <20110623122210.06ee9f55@schlenkerla.am.freescale.net>

Scott Wood wrote:
> From Power ISA 2.06B, book III-E, section 9.2.1:
> 
> Virtualized Implementation Note:
> 
> In virtualized implementations, TBU and TBL are
> read-only.

But does that mean that a guest should never be allowed to modify a virtualized
timebase register, even if the hypervisor can support it?

>> > So a generic HV mode bit is not going to help me, unless there's also a bit
>> > that's specific to our hypervisor.  And even then, we would need some way to
>> > differentiate among different versions of our hypervisor, in case some future
>> > version adds timebase support. 

> That's very unlikely to happen.

I know. I was just being architecturally pedantic.

> Ideally we would avoid doing this sync even when not running under a
> hypervisor, as long as firmware has done the sync, and kexec hasn't messed
> it up.  Besides being a waste of boot time, the firmware's sync is
> probably tighter since it can use a platform-specific mechanism to start all
> the timebases at once.

I agree with that, but for now, I need to work around that kexec "limitation".

-- 
Timur Tabi
Linux kernel developer at Freescale

^ permalink raw reply

* Re: [PATCH] powerpc/85xx: disable timebase synchronization under the hypervisor
From: Scott Wood @ 2011-06-23 17:48 UTC (permalink / raw)
  To: Timur Tabi
  Cc: Wood Scott-B07421, linuxppc-dev@ozlabs.org, paulus@samba.org,
	McClintock Matthew-B29882, Gala Kumar-B11780
In-Reply-To: <4E0378F4.5010501@freescale.com>

On Thu, 23 Jun 2011 12:33:40 -0500
Timur Tabi <timur@freescale.com> wrote:

> Scott Wood wrote:
> > From Power ISA 2.06B, book III-E, section 9.2.1:
> > 
> > Virtualized Implementation Note:
> > 
> > In virtualized implementations, TBU and TBL are
> > read-only.
> 
> But does that mean that a guest should never be allowed to modify a virtualized
> timebase register, even if the hypervisor can support it?

The book3e mtspr writeup doesn't appear to specify the behavior when
writing to a read-only SPR, so perhaps you could argue that something other
than a no-op is implementation-specific behavior.

For a guest, the safe thing is to not write to those registers unless you
specifically know it's going to do what you want under a particular
implementation.  It's not specifically a Topaz limitation.

> >> > So a generic HV mode bit is not going to help me, unless there's also a bit
> >> > that's specific to our hypervisor.  And even then, we would need some way to
> >> > differentiate among different versions of our hypervisor, in case some future
> >> > version adds timebase support. 
> 
> > That's very unlikely to happen.
> 
> I know. I was just being architecturally pedantic.

It's not as if it would hurt anything to ignore such a capability.

> > Ideally we would avoid doing this sync even when not running under a
> > hypervisor, as long as firmware has done the sync, and kexec hasn't messed
> > it up.  Besides being a waste of boot time, the firmware's sync is
> > probably tighter since it can use a platform-specific mechanism to start all
> > the timebases at once.
> 
> I agree with that, but for now, I need to work around that kexec "limitation".

Is there any way we can detect whether we booted via kexec (as opposed to
just having kexec support enabled), and only do the sync in that case?

-Scott

^ permalink raw reply

* [PATCH] powerpc/85xx: enable the framebuffer console for the defconfigs
From: Timur Tabi @ 2011-06-23 19:48 UTC (permalink / raw)
  To: kumar.gala, linuxppc-dev
In-Reply-To: <1308858535-17396-1-git-send-email-timur@freescale.com>

Enable framebuffer console support by default in the defconfigs for the
Freescale 85xx-based reference board.  This allows the boot messages to
be shown on the video display on the P1022DS.

Signed-off-by: Timur Tabi <timur@freescale.com>
---
 arch/powerpc/configs/mpc85xx_defconfig     |    4 ++++
 arch/powerpc/configs/mpc85xx_smp_defconfig |    4 ++++
 2 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/configs/mpc85xx_defconfig b/arch/powerpc/configs/mpc85xx_defconfig
index 96b89df..b212e3d 100644
--- a/arch/powerpc/configs/mpc85xx_defconfig
+++ b/arch/powerpc/configs/mpc85xx_defconfig
@@ -128,6 +128,10 @@ CONFIG_VIDEO_OUTPUT_CONTROL=y
 CONFIG_FB=y
 CONFIG_FB_FSL_DIU=y
 # CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
 CONFIG_SOUND=y
 CONFIG_SND=y
 # CONFIG_SND_SUPPORT_OLD_API is not set
diff --git a/arch/powerpc/configs/mpc85xx_smp_defconfig b/arch/powerpc/configs/mpc85xx_smp_defconfig
index de65841..87fbb2e 100644
--- a/arch/powerpc/configs/mpc85xx_smp_defconfig
+++ b/arch/powerpc/configs/mpc85xx_smp_defconfig
@@ -130,6 +130,10 @@ CONFIG_VIDEO_OUTPUT_CONTROL=y
 CONFIG_FB=y
 CONFIG_FB_FSL_DIU=y
 # CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
 CONFIG_SOUND=y
 CONFIG_SND=y
 # CONFIG_SND_SUPPORT_OLD_API is not set
-- 
1.7.3.4

^ permalink raw reply related

* [PATCH] powerpc/85xx: clamp the P1022DS DIU pixel clock to allowed values
From: Timur Tabi @ 2011-06-23 19:48 UTC (permalink / raw)
  To: kumar.gala, linuxppc-dev

To ensure that the DIU pixel clock will not be set to an invalid value,
clamp the PXCLK divider to the allowed range (2-255).  This also acts as
a limiter for the pixel clock.

Signed-off-by: Timur Tabi <timur@freescale.com>
---
 arch/powerpc/platforms/85xx/p1022_ds.c |    7 ++++++-
 1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index e083e1f..266b3aa 100644
--- a/arch/powerpc/platforms/85xx/p1022_ds.c
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c
@@ -195,8 +195,13 @@ void p1022ds_set_pixel_clock(unsigned int pixclock)
 	do_div(temp, pixclock);
 	freq = temp;
 
-	/* pixclk is the ratio of the platform clock to the pixel clock */
+	/*
+	 * 'pxclk' is the ratio of the platform clock to the pixel clock.
+	 * This number is programmed into the CLKDVDR register, and the valid
+	 * range of values is 2-255.
+	 */
 	pxclk = DIV_ROUND_CLOSEST(fsl_get_sys_freq(), freq);
+	pxclk = clamp_t(u32, pxclk, 2, 255);
 
 	/* Disable the pixel clock, and set it to non-inverted and no delay */
 	clrbits32(&guts->clkdvdr,
-- 
1.7.3.4

^ permalink raw reply related

* Re: [PATCH] libata/sas: only set FROZEN flag if new EH is supported
From: Brian King @ 2011-06-23 20:05 UTC (permalink / raw)
  To: Nishanth Aravamudan
  Cc: Wayne Boyer, linux-kernel, linux-ide, jgarzik, Tejun Heo, mbizon,
	linuxppc-dev
In-Reply-To: <20110623171502.GA11855@us.ibm.com>

On 06/23/2011 12:15 PM, Nishanth Aravamudan wrote:
> On 23.06.2011 [14:42:00 +1000], Benjamin Herrenschmidt wrote:
>> On Thu, 2011-06-23 at 14:31 +1000, Benjamin Herrenschmidt wrote:
>>> On Tue, 2011-06-21 at 15:30 -0500, Brian King wrote:
>>>> Looks good to me. Jeff/Tejun - any issues with merging this?
>>>
>>> BTW. Current upstream with that patch applied on a machine here leads to
>>> several oddities, I don't know at this point whether any of that is
>>> actually a regression :
>>
>> Ooops... pressed "send" too quickly. Here's a log excerpt with some
>> comments:
> 
> Hrm, I didn't see any of this on my box, which I thought was the same as
> yours :)
> 
>> ipr: IBM Power RAID SCSI Device Driver version: 2.5.2 (April 27, 2011)
>> ipr 0000:04:00.0: Found IOA with IRQ: 129
>> ipr 0000:04:00.0: Initializing IOA.
>> ipr 0000:04:00.0: Starting IOA initialization sequence.
>> ipr 0000:04:00.0: Adapter firmware version: 04220029
>> ipr 0000:04:00.0: IOA initialized.
>> scsi0 : IBM 2B4C Storage Adapter
>> scsi 0:0:4:0: Direct-Access     IBM      ST9300603SS      BB09 PQ: 0 ANSI: 6
>> scsi scan: INQUIRY result too short (5), using 36
>>
>> -> Are these odd INQUIRY results expected ?

Looking at the log, my guess is that we are dealing with a zero buffer. If we were
to get an all zero buffer on the Inquiry, we would think it was a Direct-Access
device with an inquiry response buffer of 5 bytes in length.

>> scsi 0:0:5:0: Direct-Access                                    PQ: 0 ANSI: 0
>> scsi 0:0:6:0: Direct-Access     IBM      ST9300603SS      BB09 PQ: 0 ANSI: 6
>> scsi 0:0:7:0: Direct-Access     IBM      ST9300603SS      BB09 PQ: 0 ANSI: 6
>> scsi scan: INQUIRY result too short (5), using 36
>> scsi 0:0:18:0: Direct-Access                                    PQ: 0 ANSI: 0

I'm guessing this should really be an Enclosure device here rather than a disk,
which would be symptomatic of the all zero inquiry buffer.

>> scsi 0:2:18:0: Enclosure         IBM      PSBPD6E4A  3GSAS 0109 PQ: 0 ANSI: 4
>> scsi: unknown device type 31
>> scsi 0:255:255:255: No Device         IBM      2B4C001SISIOA    0150 PQ: 0 ANSI: 0
>>
>> -> The above looks odd, not sure what it means
> 
> The "unknown device type"? I see it all the time on lots of different
> machines.

That is normal and expected on an ipr adapter. The unknown device seen on every ipr
adapter at SCSI bus/target/lun 255:255:255 is the adapter itself. It is used by
the RAID management tools in Linux to do things like RAID configuration via SG_IO.

> 
>> ipr 0000:05:00.0: Found IOA with IRQ: 130
>> ipr 0000:05:00.0: Initializing IOA.
>> scsi 0:254:0:0: Processor         IBM      57CB001SISIOA    0150 PQ: 0 ANSI: 0
>> ipr 0000:05:00.0: Starting IOA initialization sequence.
>> ipr 0000:05:00.0: Adapter firmware version: 04220029
>> ipr 0000:05:00.0: IOA initialized.
>> scsi1 : IBM 57CB Storage Adapter
>> scsi scan: INQUIRY result too short (5), using 36
>> scsi 1:0:4:0: Direct-Access                                    PQ: 0 ANSI: 0
>> scsi 1:0:5:0: Direct-Access     IBM      ST9300603SS      BB09 PQ: 0 ANSI: 6
>> scsi scan: INQUIRY result too short (5), using 36
>> scsi 1:0:6:0: Direct-Access                                    PQ: 0 ANSI: 0
>> scsi 1:0:7:0: Direct-Access     IBM      ST9300603SS      BB09 PQ: 0 ANSI: 6
>> scsi 1:0:18:0: Enclosure         IBM      PSBPD6E4A  3GSAS 0109 PQ: 0 ANSI: 4
>> scsi: On host 1 channel 0 id 18 only 511 (max_scsi_report_luns) of 402653184 luns reported, try increasing max_scsi_report_luns.
>> scsi: host 1 channel 0 id 18 lun 0xc0000007f01e810f has a LUN larger than currently supported.
>>
>> -> Now that looks horribly wrong... that LUN number looks like a kernel pointer
> 
> Yeah, that's weird.
> 
>> scsi scan: INQUIRY result too short (5), using 36
>> scsi 1:2:18:0: Direct-Access                                    PQ: 0 ANSI: 0
>> ata1.00: ATAPI: IBM     RMBO0040532, SA61, max UDMA/100
>> ata1.00: failed to IDENTIFY (device reports invalid type, err_mask=0x0)
>> ata1.00: revalidation failed (errno=-22)
>> ata1.00: disabled
>>
>> -> So SATA works "better" with the patch but doesn't actually work properly :-)
>>
>> scsi_alloc_sdev: Allocation failure during SCSI scanning, some SCSI devices might not be configured
>>
>> -> That error could give us more info... not sure what it means, we do have plenty of 
>> memory...
> 
> That message is sort of strange. It's not necessarily referring to
> memory allocation failing, but the port allocation failing in the SCSI
> code. And that just means an error, like the failed to IDENTIFY above,
> is occurring in the allocation path. It *can* also mean memory
> allocation failure, I think, just not in this case.
> 
> I don't know much about the following errors, though, sorry.
> 
> -Nish
> 
>> scsi 1:8:0:0: Enclosure         IBM      VSBPD6E4B  3GSAS   01 PQ: 0 ANSI: 2
>> scsi: unknown device type 31
>> scsi 1:255:255:255: No Device         IBM      57CB001SISIOA    0150 PQ: 0 ANSI: 0
>> work_for_cpu used greatest stack depth: 9520 bytes left
>> st: Version 20101219, fixed bufsize 32768, s/g segs 256
>> sd 0:0:4:0: [sda] 585937500 512-byte logical blocks: (300 GB/279 GiB)
>> sd 0:0:5:0: [sdb] 585937500 512-byte logical blocks: (300 GB/279 GiB)
>> sd 0:0:6:0: [sdc] 585937500 512-byte logical blocks: (300 GB/279 GiB)
>> sd 0:0:7:0: [sdd] 585937500 512-byte logical blocks: (300 GB/279 GiB)
>> sd 0:0:18:0: [sde] READ CAPACITY failed
>> sd 0:0:18:0: [sde]  Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
>> sd 0:0:18:0: [sde]  Sense Key : Illegal Request [current] 
>> sd 0:0:18:0: [sde]  Add. Sense: Invalid command operation code
>>
>> -> Any idea what's up with that guy ?

If this guy is really an enclosure, this is the response you would get
on a Read Capacity.

>>
>> sd 0:0:4:0: Attached scsi generic sg0 type 0
>> sd 0:0:5:0: [sdb] Write Protect is off
>> sd 0:0:5:0: Attached scsi generic sg1 type 0
>> sd 0:0:18:0: [sde] Test WP failed, assume Write Enabled
>> sd 0:0:6:0: Attached scsi generic sg2 type 0
>> sd 0:0:18:0: [sde] Asking for cache data failed
>> sd 0:0:7:0: Attached scsi generic sg3 type 0
>> sd 0:0:18:0: [sde] Assuming drive cache: write through
>> sd 1:2:18:0: [sdj] READ CAPACITY failed
>> sd 1:2:18:0: [sdj]  Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
>> sd 1:2:18:0: [sdj]  Sense Key : Illegal Request [current] 
>> sd 1:2:18:0: [sdj]  Add. Sense: Invalid command operation code
>>
>> -> And this one ?

Same here.

When did this last work on this system? It seems like this is completely
separate from the libata issue.

-Brian

-- 
Brian King
Linux on Power Virtualization
IBM Linux Technology Center

^ permalink raw reply

* [PATCH] fsl-diu-fb: remove check for pixel clock ranges
From: Timur Tabi @ 2011-06-23 20:20 UTC (permalink / raw)
  To: lethal, linux-fbdev, agust, yorksun, linuxppc-dev

The Freescale DIU framebuffer driver defines two constants, MIN_PIX_CLK and
MAX_PIX_CLK, that are supposed to represent the lower and upper limits of
the pixel clock.  These values, however, are true only for one platform
clock rate (533MHz) and only for the MPC8610.  So the actual range for
the pixel clock is chip-specific, which means the current values are almost
always wrong.  The chance of an out-of-range pixel clock being used are also
remote.

Rather than try to detect an out-of-range clock in the DIU driver, we depend
on the board-specific pixel clock function (e.g. p1022ds_set_pixel_clock)
to clamp the pixel clock to a supported value.

Signed-off-by: Timur Tabi <timur@freescale.com>
---
 drivers/video/fsl-diu-fb.c |   16 ----------------
 include/linux/fsl-diu-fb.h |    6 ------
 2 files changed, 0 insertions(+), 22 deletions(-)

diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index bedf5be..0acc7d6 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -555,8 +555,6 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
 static int fsl_diu_check_var(struct fb_var_screeninfo *var,
 				struct fb_info *info)
 {
-	unsigned long htotal, vtotal;
-
 	pr_debug("check_var xres: %d\n", var->xres);
 	pr_debug("check_var yres: %d\n", var->yres);
 
@@ -635,20 +633,6 @@ static int fsl_diu_check_var(struct fb_var_screeninfo *var,
 
 		break;
 	}
-	/* If the pixclock is below the minimum spec'd value then set to
-	 * refresh rate for 60Hz since this is supported by most monitors.
-	 * Refer to Documentation/fb/ for calculations.
-	 */
-	if ((var->pixclock < MIN_PIX_CLK) || (var->pixclock > MAX_PIX_CLK)) {
-		htotal = var->xres + var->right_margin + var->hsync_len +
-		    var->left_margin;
-		vtotal = var->yres + var->lower_margin + var->vsync_len +
-		    var->upper_margin;
-		var->pixclock = (vtotal * htotal * 6UL) / 100UL;
-		var->pixclock = KHZ2PICOS(var->pixclock);
-		pr_debug("pixclock set for 60Hz refresh = %u ps\n",
-			var->pixclock);
-	}
 
 	var->height = -1;
 	var->width = -1;
diff --git a/include/linux/fsl-diu-fb.h b/include/linux/fsl-diu-fb.h
index 781d467..daa9952 100644
--- a/include/linux/fsl-diu-fb.h
+++ b/include/linux/fsl-diu-fb.h
@@ -24,12 +24,6 @@
  * See mpc8610fb_set_par(), map_video_memory(), and unmap_video_memory()
  */
 #define MEM_ALLOC_THRESHOLD (1024*768*4+32)
-/* Minimum value that the pixel clock can be set to in pico seconds
- * This is determined by platform clock/3 where the minimum platform
- * clock is 533MHz. This gives 5629 pico seconds.
- */
-#define MIN_PIX_CLK 5629
-#define MAX_PIX_CLK 96096
 
 #include <linux/types.h>
 
-- 
1.7.3.4

^ permalink raw reply related

* Re: Connecting SGMII PHY to eTSEC1 on P1022
From: Felix Radensky @ 2011-06-23 20:43 UTC (permalink / raw)
  To: Timur Tabi; +Cc: linuxppc-dev@ozlabs.org
In-Reply-To: <4E02229B.50707@embedded-sol.com>

Hi,

On 06/22/2011 08:12 PM, Felix Radensky wrote:
> Hi Timur,
>
> On 06/22/2011 07:18 PM, Timur Tabi wrote:
>> Felix Radensky wrote:
>>> What am I doing wrong ?
>> Can you debug the PHY driver to see if it's getting called and 
>> trying to talk to
>> the PHY itself?
>>
> I'll do that tomorrow and report back.

I've found the problem by looking at the code. My SGMII PHY is Marvell 
88E1112.
Marvell PHY driver claims it supports that PHY, but in reality it 
doesn't. It uses
routines initially written for 88E1111 to configure 88E1112, 
essentially writing
to registers that do not exist on that PHY. After disabling Marvell 
PHY driver my
PHY started working.

Felix.

^ permalink raw reply

* Re: [PATCH 3/5] drivers/amba: create devices from device tree
From: Grant Likely @ 2011-06-23 20:55 UTC (permalink / raw)
  To: Rob Herring
  Cc: Nicolas Pitre, Russell King, Arnd Bergmann, devicetree-discuss,
	linux-kernel, linuxppc-dev, linux-arm-kernel
In-Reply-To: <4E00F9ED.1020500@gmail.com>

On Tue, Jun 21, 2011 at 2:07 PM, Rob Herring <robherring2@gmail.com> wrote:
> Grant,
>
> On 06/21/2011 01:45 PM, Grant Likely wrote:
>> Add a function to create amba_devices (i.e. primecell peripherals)
>> from device tree nodes. The device tree scanning is done by the
>> of_platform_populate() function which can call of_amba_device_create
>> based on a match table entry.
>>
>> Nodes with a "arm,primecell-periphid" property can override the h/w
>> peripheral id value.
>>
>> Based on the original work by Jeremy Kerr.
>>
>> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
>> Acked-by: Linus Walleij <linus.walleij@linaro.org>
>> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
>> Reviewed-by: Arnd Bergmann <arnd@arndb.de>
>> [grant.likely: add Jeremy's original s-o-b line, changes from review
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0comments, and moved all code to drivers/o=
f/platform.c]
>> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
>> ---
>> =A0.../devicetree/bindings/arm/primecell.txt =A0 =A0 =A0 =A0 =A0| =A0 21=
 ++++++
>> =A0drivers/of/platform.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0| =A0 71 ++++++++++++++++++++
>> =A02 files changed, 92 insertions(+), 0 deletions(-)
>> =A0create mode 100644 Documentation/devicetree/bindings/arm/primecell.tx=
t
>>
>> diff --git a/Documentation/devicetree/bindings/arm/primecell.txt b/Docum=
entation/devicetree/bindings/arm/primecell.txt
>> new file mode 100644
>> index 0000000..1d5d7a8
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/arm/primecell.txt
>> @@ -0,0 +1,21 @@
>> +* ARM Primecell Peripherals
>> +
>> +ARM, Ltd. Primecell peripherals have a standard id register that can be=
 used to
>> +identify the peripheral type, vendor, and revision. This value can be u=
sed for
>> +driver matching.
>> +
>> +Required properties:
>> +
>> +- compatible : should be a specific value for peripheral and "arm,prime=
cell"
>
> Can I review what I wrote... Perhaps we should put strings in for all
> existing drivers in the kernel. This should be a complete list:
>
> arm,pl010
> arm,pl011
> st,pl011
> arm,pl022
> st,pl022
> st,pl023
> arm,pl030
> arm,pl031
> st,pl031
> arm,pl061
> arm,pl050
> arm,pl080
> arm,pl081
> st,pl080
> arm,pl110
> arm,pl180
> arm,pl330
> arm,sp804
> arm,sp805


Yes, this whole list should be added.

g.

^ permalink raw reply

* Re: [PATCH] libata/sas: only set FROZEN flag if new EH is supported
From: Benjamin Herrenschmidt @ 2011-06-23 21:43 UTC (permalink / raw)
  To: Brian King
  Cc: jgarzik, wayneb, linux-kernel, linux-ide, mbizon, Tejun Heo,
	Nishanth Aravamudan, linuxppc-dev
In-Reply-To: <4E039C95.3070907@linux.vnet.ibm.com>

On Thu, 2011-06-23 at 15:05 -0500, Brian King wrote:
> 
> Same here.
> 
> When did this last work on this system? It seems like this is
> completely
> separate from the libata issue. 

It's separate. See my other internal message. This is a BML system and
it's broken as far as 2.6.36 but the BML "patched" kernel works,
anyways, moving that off list for now.

Cheers,
Ben.

^ permalink raw reply

* Re: [PATCH] STAGING: Comedi: Build only on arches providing PAGE_KERNEL_NOCACHE
From: Benjamin Herrenschmidt @ 2011-06-23 22:01 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: devel, David Howells, linux-m32r, Paul Mundt, linux-sh,
	Greg Kroah-Hartman, linux-kernel, Chris Metcalf, Martyn Welch,
	linux-am33-list, Paul Mackerras, linux-m32r-ja, H. Peter Anvin,
	Thomas Gleixner, linux-arch, linuxppc-dev, Ingo Molnar, x86
In-Reply-To: <20110623120234.GA22524@linux-mips.org>

On Thu, 2011-06-23 at 13:02 +0100, Ralf Baechle wrote:
> On Thu, Jun 23, 2011 at 12:53:36PM +0100, Martyn Welch wrote:
> 
> > On 23/06/11 12:45, Ralf Baechle wrote:
> > > On architectures that don't define PAGE_KERNEL_NOCACHE, the Comedi driver turns
> > > into tragedy:
> > > 
> > >   CC [M]  drivers/staging/comedi/drivers.o
> > > drivers/staging/comedi/drivers.c: In function ‘comedi_buf_alloc’:
> > > drivers/staging/comedi/drivers.c:505:41: error: ‘PAGE_KERNEL_NOCACHE’ undeclared (first use in this function)
> > > drivers/staging/comedi/drivers.c:505:41: note: each undeclared identifier is rep orted only once for each function it appears in
> > > make[3]: *** [drivers/staging/comedi/drivers.o] Error 1
> > > 
> > > Restrict the driver to only those architectures that define PAGE_KERNEL_NOCACHE.
> > > 
> > > PAGE_KERNEL_NOCACHE is a kludge - some system architectures such as SGI IP27
> > > are even uable to offer uncached operation - at least in the way an unwitting
> > > driver might assume.  I haven't looked in details how the driver is using
> > > the area vmaped with PAGE_KERNEL_NOCACHE but maybe doing it XFS-style using
> > > cached memory and the flush_kernel_vmap_range / invalidate_kernel_vmap_range
> > > APIs in conjunction with the DMA API is a practical alternative.
> > > 
> > > Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
> > > 
> > >  drivers/staging/comedi/Kconfig |    1 +
> > >  1 files changed, 1 insertions(+), 0 deletions(-)
> > > 
> > > diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig
> > > index 1502d80..bccdc12 100644
> > > --- a/drivers/staging/comedi/Kconfig
> > > +++ b/drivers/staging/comedi/Kconfig
> > > @@ -2,6 +2,7 @@ config COMEDI
> > >  	tristate "Data acquisition support (comedi)"
> > >  	default N
> > >  	depends on m
> > > +	depends on BROKEN || FRV || M32R || MN10300 || SUPERH || TILE || X86
> > 
> > I'm sure I got comedi to compile on a 32-bit PPC board not that long ago. Has
> > something changed, or is this just not an exhaustive list?

It went away. There's a proper API (pgprot_noncached), but it depends
what this is used for and it's likely to be broken anyways... what is
that driver trying to map non-cached ?

Cheers,
Ben.

> (Adding the PPC folks to cc.)
> 
> A "git grep -w PAGE_KERNEL_NOCACHE arch/powerpc/" doesn't find anything so
> I don't think the driver will build there.  I don't have a PPC toolchain
> to verify that.
> 
>   Ralf
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arch" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH v9 11/13] powerpc: select HAVE_SECCOMP_FILTER and provide seccomp_execve
From: Will Drewry @ 2011-06-24  0:36 UTC (permalink / raw)
  To: linux-kernel
  Cc: linuxppc-dev, Will Drewry, fweisbec, scarybeasts, djm, jmorris,
	rostedt, tglx, mingo, Paul Mackerras, kees.cook, torvalds, segoon
In-Reply-To: <1308875813-20122-1-git-send-email-wad@chromium.org>

Facilitate the use of CONFIG_SECCOMP_FILTER by wrapping compatibility
system call numbering for execve and selecting HAVE_SECCOMP_FILTER.

v9: rebase on to bccaeafd7c117acee36e90d37c7e05c19be9e7bf

Signed-off-by: Will Drewry <wad@chromium.org>
---
 arch/powerpc/Kconfig               |    1 +
 arch/powerpc/include/asm/seccomp.h |    2 ++
 2 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 2729c66..030d392 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -129,6 +129,7 @@ config PPC
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS && PPC_BOOK3S_64
 	select HAVE_GENERIC_HARDIRQS
 	select HAVE_SPARSE_IRQ
+	select HAVE_SECCOMP_FILTER
 	select IRQ_PER_CPU
 	select GENERIC_IRQ_SHOW
 	select GENERIC_IRQ_SHOW_LEVEL
diff --git a/arch/powerpc/include/asm/seccomp.h b/arch/powerpc/include/asm/seccomp.h
index 00c1d91..3cb9cc1 100644
--- a/arch/powerpc/include/asm/seccomp.h
+++ b/arch/powerpc/include/asm/seccomp.h
@@ -7,10 +7,12 @@
 #define __NR_seccomp_write __NR_write
 #define __NR_seccomp_exit __NR_exit
 #define __NR_seccomp_sigreturn __NR_rt_sigreturn
+#define __NR_seccomp_execve __NR_execve
 
 #define __NR_seccomp_read_32 __NR_read
 #define __NR_seccomp_write_32 __NR_write
 #define __NR_seccomp_exit_32 __NR_exit
 #define __NR_seccomp_sigreturn_32 __NR_sigreturn
+#define __NR_seccomp_execve_32 __NR_execve
 
 #endif	/* _ASM_POWERPC_SECCOMP_H */
-- 
1.7.0.4

^ permalink raw reply related

* Re: [PATCH] powerpc, 460gt: Add 460gt as compatible in the check for 460ex-compatible crypto
From: Segher Boessenkool @ 2011-06-24  2:14 UTC (permalink / raw)
  To: Mike Williams; +Cc: linuxppc-dev
In-Reply-To: <BANLkTinisHPrEN8Xc_KoqFwxknMooE=H4w@mail.gmail.com>

>>> - =A0 =A0 =A0 if (of_find_compatible_node(NULL, NULL,=20
>>> "amcc,ppc460ex-crypto")) {
>>> + =A0 =A0 =A0 if (of_find_compatible_node(NULL, NULL,=20
>>> "amcc,ppc460ex-crypto") ||
>>> + =A0 =A0 =A0 =A0 =A0 of_find_compatible_node(NULL, NULL,=20
>>> "amcc,ppc460gt-crypto")) {
>>
>> If the device is actually compatible, the device tree node should=20
>> claim
>> it is, and you do not need this code change.
>
> That was actually my first instinct, however I tried to follow the
> current convention in the glacier and canyonlands DTS files, which is
> to set every device compatible to 460gt or 460ex, depending on the
> processor. Many of the devices are identical between the two, since
> they are variations of the same SoC, so which is the preferred method?
> Follow the device tree convention and add the compatibility check in
> the driver,

That is not the convention.

> or alter the device trees? I'll send another patch if it's
> the latter.

You say

   compatible =3D "amcc,ppc460gt-crypto", "amcc,ppc460ex-crypto";

So, a unique name for the actual device first, followed by the name of
what it is compatible to.  The driver for 460ex-crypto will then work
without any changes, but it can also do some 460gt-specific workarounds
or enhancements; or you could even have a totally separate driver for
the 460gt-crypto (you'll have to arrange for it to be used preferably
then).

You should document this 460gt-crypto binding, btw (a single line in
the 460ex-crypto binding doc will do).


Segher

^ permalink raw reply

* Re: [PATCH] powerpc/85xx: disable timebase synchronization under the hypervisor
From: Segher Boessenkool @ 2011-06-24  2:36 UTC (permalink / raw)
  To: Scott Wood
  Cc: Wood Scott-B07421, linuxppc-dev@ozlabs.org, paulus@samba.org,
	McClintock Matthew-B29882, Gala Kumar-B11780, Timur Tabi
In-Reply-To: <20110623124802.7aeb6b66@schlenkerla.am.freescale.net>

>> But does that mean that a guest should never be allowed to modify a 
>> virtualized
>> timebase register, even if the hypervisor can support it?
>
> The book3e mtspr writeup doesn't appear to specify the behavior when
> writing to a read-only SPR, so perhaps you could argue that something 
> other
> than a no-op is implementation-specific behavior.

v2.06 III-E 9.2.1:
"Writing the Time Base is hypervisor privileged."

v2.06 III-E 2.1:
"If a hypervisor-privileged register is accessed in the guest supervisor
state (MSR[GS PR] = 0b10), an Embedded Hypervisor Privilege exception 
occurs."

(v2.06 III-E 5.4.1, the big SPR table, also shows the TB regs (for 
writing,
i.e. 284 and 285) to be hypervisor privileged.  Consistency, hurray :-) 
)


Segher

^ permalink raw reply

* Re: [PATCH] powerpc/85xx: disable timebase synchronization under the hypervisor
From: Tabi Timur-B04825 @ 2011-06-24  2:38 UTC (permalink / raw)
  To: Segher Boessenkool
  Cc: McClintock Matthew-B29882, Wood Scott-B07421, Gala Kumar-B11780,
	paulus@samba.org, linuxppc-dev@ozlabs.org
In-Reply-To: <59f786bfaced051a14e2bb75d3d1ce77@kernel.crashing.org>

Segher Boessenkool wrote:
>
> v2.06 III-E 9.2.1:
> "Writing the Time Base is hypervisor privileged."
>
> v2.06 III-E 2.1:
> "If a hypervisor-privileged register is accessed in the guest supervisor
> state (MSR[GS PR] =3D 0b10), an Embedded Hypervisor Privilege exception
> occurs."
>
> (v2.06 III-E 5.4.1, the big SPR table, also shows the TB regs (for writin=
g,
> i.e. 284 and 285) to be hypervisor privileged.  Consistency, hurray :-) )

To me, all this means that a guest cannot write to the actual timebase=20
register.  I'm not interpreting this to mean that a hypervisor can't=20
virtualize the timebase and allow a guest to read/write a virtual timebase=
=20
register, so that it thinks it's writing to the real hardware timebase regi=
ster.

--=20
Timur Tabi
Linux kernel developer at Freescale=

^ permalink raw reply

* Re: [PATCH] powerpc/85xx: disable timebase synchronization under the hypervisor
From: Segher Boessenkool @ 2011-06-24  3:50 UTC (permalink / raw)
  To: Tabi Timur-B04825
  Cc: McClintock Matthew-B29882, Wood Scott-B07421, Gala Kumar-B11780,
	paulus@samba.org, linuxppc-dev@ozlabs.org
In-Reply-To: <4E03F8C1.60706@freescale.com>

(context put back:)

>> But does that mean that a guest should never be allowed to modify a 
>> virtualized
>> timebase register, even if the hypervisor can support it?
>
> The book3e mtspr writeup doesn't appear to specify the behavior when
> writing to a read-only SPR, so perhaps you could argue that something 
> other
> than a no-op is implementation-specific behavior.

>> v2.06 III-E 9.2.1:
>> "Writing the Time Base is hypervisor privileged."
>>
>> v2.06 III-E 2.1:
>> "If a hypervisor-privileged register is accessed in the guest 
>> supervisor
>> state (MSR[GS PR] = 0b10), an Embedded Hypervisor Privilege exception
>> occurs."
>>
>> (v2.06 III-E 5.4.1, the big SPR table, also shows the TB regs (for 
>> writing,
>> i.e. 284 and 285) to be hypervisor privileged.  Consistency, hurray 
>> :-) )
>
> To me, all this means that a guest cannot write to the actual timebase
> register.

It also means that the hypervisor gets a trap when a guest tries to do 
this.

>   I'm not interpreting this to mean that a hypervisor can't
> virtualize the timebase and allow a guest to read/write a virtual 
> timebase
> register, so that it thinks it's writing to the real hardware timebase 
> register.

Yes, a hypervisor can do this.  The behaviour of the hardware is not
implementation-specific (modulo bugs ;-) ); when a guest tries to write
to the timebase, the hypervisor gets a trap.  The hypervisor can then
do whatever it wants with it.


Segher

^ permalink raw reply

* [RFC PATCH 0/1] BPF JIT for PPC64
From: Matt Evans @ 2011-06-24  6:02 UTC (permalink / raw)
  To: netdev, linuxppc-dev

Hi,


Inspired by Eric Dumazet's x86-64 compiler for Berkeley Packet Filter programs,
I've written a BPF compiler for 64-bit PowerPC.  Although it hasn't finished its
strenuous testing regime, I'll have intermittent net access for a couple of
weeks so thought I'd post it for feedback now and submit a 'proper' version when
I'm back.

It's a fairly simple code generator, following a similar structure to the x86
version.  The filter programs are an array of opcode/constant/branch destination
structs, and can perform arithmetic/logical/comparison operations on two virtual
registers A and X, loads from packet headers/data and accesses to local
variables, M[].  Branching is also supported, but only forwards and only within
the extent of the program.

I would probably describe this as more of a "static template binary translator"
than a "JIT" but have kept naming consistent :)


Features include:

- Filter code is generated as an ABI-compliant function, stackframe &
  prologue/epilogue if necessary.

- Simple filters (e.g. RET nn) need no stackframe or save/restore code so
  generate into only an li/blr.

- Local variables, M[], live in registers

- I believe this supports all BPF opcodes, although "complicated" loads from
  negative packet offsets (e.g. SKF_LL_OFF) are not yet supported.

Caveats include:  :)

- Packet data loads call out to simple helper functions (bpf_jit.S) which
  themselves may fall back to a trampoline to skb_copy_bits.  I haven't decided
  whether (as per comments there) it would be better to generate the simple
  loads inline and only call out in the slow case.

- Branches currently generate to "bcc 1f; b <far dest>; 1:" or
  "bcc <near dest> ; nop" so either case is the same size.  Multiple passes of
  assembly are used (the first gets an idea of how big everything is and what
  features are required), the next generates everything at accurate size, the
  third generates everything with accurate branch destination addresses); I
  intend not to nop-pad the short branch case but changing code size may
  result in more passes and a 'settling-down period'.  Kept simple for now.

- Anyone running PPC64 little-endian is doing something both interesting and
  unsupported for this work :-)  (There are some trivial endian assumptions.)

Tested in-situ (tcpdump with varying complexity filters) and with a random BPF
generator; I haven't verified loads from the fall back skb_copy_bits path.  Bug
reports/testing would be very welcome.



Cheers,



Matt

^ permalink raw reply

* [RFC PATCH 1/1] BPF JIT for PPC64
From: Matt Evans @ 2011-06-24  6:02 UTC (permalink / raw)
  To: netdev, linuxppc-dev


 arch/powerpc/Kconfig                  |    1 +
 arch/powerpc/Makefile                 |    3 +-
 arch/powerpc/include/asm/ppc-opcode.h |   40 ++
 arch/powerpc/net/Makefile             |    4 +
 arch/powerpc/net/bpf_jit.S            |  138 +++++++
 arch/powerpc/net/bpf_jit.h            |  226 +++++++++++
 arch/powerpc/net/bpf_jit_comp.c       |  697 +++++++++++++++++++++++++++++++++
 7 files changed, 1108 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 2729c66..39860fc 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -134,6 +134,7 @@ config PPC
 	select GENERIC_IRQ_SHOW_LEVEL
 	select HAVE_RCU_TABLE_FREE if SMP
 	select HAVE_SYSCALL_TRACEPOINTS
+	select HAVE_BPF_JIT if PPC64
 
 config EARLY_PRINTK
 	bool
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index b7212b6..b94740f 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -154,7 +154,8 @@ core-y				+= arch/powerpc/kernel/ \
 				   arch/powerpc/lib/ \
 				   arch/powerpc/sysdev/ \
 				   arch/powerpc/platforms/ \
-				   arch/powerpc/math-emu/
+				   arch/powerpc/math-emu/ \
+				   arch/powerpc/net/
 core-$(CONFIG_XMON)		+= arch/powerpc/xmon/
 core-$(CONFIG_KVM) 		+= arch/powerpc/kvm/
 
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
index e472659..e980faa 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -71,6 +71,42 @@
 #define PPC_INST_ERATSX			0x7c000126
 #define PPC_INST_ERATSX_DOT		0x7c000127
 
+/* Misc instructions for BPF compiler */
+#define PPC_INST_LD			0xe8000000
+#define PPC_INST_LHZ			0xa0000000
+#define PPC_INST_LWZ			0x80000000
+#define PPC_INST_STD			0xf8000000
+#define PPC_INST_STDU			0xf8000001
+#define PPC_INST_MFLR			0x7c0802a6
+#define PPC_INST_MTLR			0x7c0803a6
+#define PPC_INST_CMPWI			0x2c000000
+#define PPC_INST_CMPDI			0x2c200000
+#define PPC_INST_CMPLW			0x7c000040
+#define PPC_INST_CMPLWI			0x28000000
+#define PPC_INST_ADDI			0x38000000
+#define PPC_INST_ADDIS			0x3c000000
+#define PPC_INST_ADD			0x7c000214
+#define PPC_INST_SUB			0x7c000050
+#define PPC_INST_BLR			0x4e800020
+#define PPC_INST_BLRL			0x4e800021
+#define PPC_INST_MULLW			0x7c0001d6
+#define PPC_INST_MULHWU			0x7c000016
+#define PPC_INST_MULLI			0x1c000000
+#define PPC_INST_DIVWU			0x7c0003d6
+#define PPC_INST_RLWINM			0x54000000
+#define PPC_INST_RLDICR			0x78000004
+#define PPC_INST_SLW			0x7c000030
+#define PPC_INST_SRW			0x7c000430
+#define PPC_INST_AND			0x7c000038
+#define PPC_INST_ANDDOT			0x7c000039
+#define PPC_INST_OR			0x7c000378
+#define PPC_INST_ANDI			0x70000000
+#define PPC_INST_ORI			0x60000000
+#define PPC_INST_ORIS			0x64000000
+#define PPC_INST_NEG			0x7c0000d0
+#define PPC_INST_BRANCH			0x48000000
+#define PPC_INST_BRANCH_COND		0x40800000
+
 /* macros to insert fields into opcodes */
 #define __PPC_RA(a)	(((a) & 0x1f) << 16)
 #define __PPC_RB(b)	(((b) & 0x1f) << 11)
@@ -83,6 +119,10 @@
 #define __PPC_T_TLB(t)	(((t) & 0x3) << 21)
 #define __PPC_WC(w)	(((w) & 0x3) << 21)
 #define __PPC_WS(w)	(((w) & 0x1f) << 11)
+#define __PPC_SH(s)	__PPC_WS(s)
+#define __PPC_MB(s)	(((s) & 0x1f) << 6)
+#define __PPC_ME(s)	(((s) & 0x1f) << 1)
+#define __PPC_BI(s)	(((s) & 0x1f) << 16)
 
 /*
  * Only use the larx hint bit on 64bit CPUs. e500v1/v2 based CPUs will treat a
diff --git a/arch/powerpc/net/Makefile b/arch/powerpc/net/Makefile
new file mode 100644
index 0000000..90568c3
--- /dev/null
+++ b/arch/powerpc/net/Makefile
@@ -0,0 +1,4 @@
+#
+# Arch-specific network modules
+#
+obj-$(CONFIG_BPF_JIT) += bpf_jit.o bpf_jit_comp.o
diff --git a/arch/powerpc/net/bpf_jit.S b/arch/powerpc/net/bpf_jit.S
new file mode 100644
index 0000000..ce2225e
--- /dev/null
+++ b/arch/powerpc/net/bpf_jit.S
@@ -0,0 +1,138 @@
+/* bpf_jit.S: Packet/header access helper functions
+ * for PPC64 BPF compiler.
+ *
+ * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <asm/ppc_asm.h>
+#include "bpf_jit.h"
+
+/*
+ * All of these routines are called directly from generated code,
+ * whose register usage is:
+ *
+ * r3		skb
+ * r4,r5	A,X
+ * r6		*** address parameter to helper ***
+ * r7-r10	scratch
+ * r14		skb->data
+ * r15		skb headlen
+ * r16-31	M[]
+ */
+
+/*
+ * To consider:	 These helpers are so small it may be better to just
+ * generate them inline.  They're out here for debug at the moment,
+ * but inline code can do the simple headlen check then branch
+ * directly to slow_path_XXX if required.  (In fact, could load a spare
+ * GPR with slow_path_generic and pass size as an argument.)
+ *
+ * Technically, the "is addr < 0" check is unnecessary & slowing down
+ * the ABS path, as it's statically checked on generation.
+ */
+	.globl	sk_load_word
+sk_load_word:
+	cmpdi	r_addr, 0
+	blt	bpf_error
+	/* Are we accessing past headlen? */
+	subi	r_scratch1, r_HL, 4
+	cmpd	r_scratch1, r_addr
+	blt	bpf_slow_path_word
+	/* Nope, just hitting the header.  cr0 here is eq or gt! */
+	lwzx	r_A, r_D, r_addr
+	/* When big endian we don't need to byteswap. */
+	blr	/* Return success, cr0 != LT */
+
+	.globl	sk_load_half
+sk_load_half:
+	cmpdi	r_addr, 0
+	blt	bpf_error
+	subi	r_scratch1, r_HL, 2
+	cmpd	r_scratch1, r_addr
+	blt	bpf_slow_path_half
+	lhzx	r_A, r_D, r_addr
+	blr
+
+	.globl	sk_load_byte
+sk_load_byte:
+	cmpdi	r_addr, 0
+	blt	bpf_error
+	cmpd	r_HL, r_addr
+	ble	bpf_slow_path_byte
+	lbzx	r_A, r_D, r_addr
+	blr
+
+/*
+ * BPF_S_LDX_B_MSH: ldxb  4*([offset]&0xf)
+ * r_addr is the offset value, already known positive
+ */
+	.globl sk_load_byte_msh
+sk_load_byte_msh:
+	cmpd	r_HL, r_addr
+	ble	bpf_slow_path_byte_msh
+	lbzx	r_X, r_D, r_addr
+	rlwinm	r_X, r_X, 2, 32-4-2, 31-2
+	blr
+
+bpf_error:
+	/* Entered with cr0 = lt */
+	li	r3, 0
+	/* Generated code will 'blt epilogue', returning 0. */
+	blr
+
+/* Call out to skb_copy_bits:
+ * We'll need to back up our volatile regs first; we have
+ * local variable space at r1+(BPF_PPC_STACK_BASIC).
+ * Allocate a new stack frame here to remain ABI-compliant in
+ * stashing LR.
+ */
+#define bpf_slow_path_common(SIZE)				\
+	mflr	r0;						\
+	std	r0, 16(r1);					\
+	/* R3 goes in parameter space of caller's frame */	\
+	std	r_skb, (BPF_PPC_STACKFRAME+48)(r1);		\
+	std	r_A, (BPF_PPC_STACK_BASIC+(0*8))(r1);		\
+	std	r_X, (BPF_PPC_STACK_BASIC+(1*8))(r1);		\
+	stdu	r1, -128(r1);					\
+	/* R3 = r_skb, as passed */				\
+	mr	r4, r_addr;					\
+	addi	r5, r1, 128+BPF_PPC_STACK_BASIC+(2*8);		\
+	li	r6, SIZE;					\
+	bl	skb_copy_bits;					\
+	/* R3 = 0 on success */					\
+	addi	r1, r1, 128;					\
+	ld	r0, 16(r1);					\
+	ld	r_A, (BPF_PPC_STACK_BASIC+(0*8))(r1);		\
+	ld	r_X, (BPF_PPC_STACK_BASIC+(1*8))(r1);		\
+	mtlr	r0;						\
+	cmpdi	r3, 0;						\
+	blt	bpf_error;	/* cr0 = LT */			\
+	ld	r_skb, (BPF_PPC_STACKFRAME+48)(r1);		\
+	/* Great success! */
+
+bpf_slow_path_word:
+	bpf_slow_path_common(4)
+	/* Data value is on stack, and cr0 != LT */
+	lwz	r_A, BPF_PPC_STACK_BASIC+(2*8)(r1)
+	blr
+
+bpf_slow_path_half:
+	bpf_slow_path_common(2)
+	lhz	r_A, BPF_PPC_STACK_BASIC+(2*8)(r1)
+	blr
+
+bpf_slow_path_byte:
+	bpf_slow_path_common(1)
+	lbz	r_A, BPF_PPC_STACK_BASIC+(2*8)(r1)
+	blr
+
+bpf_slow_path_byte_msh:
+	bpf_slow_path_common(1)
+	lbz	r_X, BPF_PPC_STACK_BASIC+(2*8)(r1)
+	rlwinm	r_X, r_X, 2, 32-4-2, 31-2
+	blr
diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
new file mode 100644
index 0000000..1fe54b9
--- /dev/null
+++ b/arch/powerpc/net/bpf_jit.h
@@ -0,0 +1,226 @@
+/* bpf_jit.h: BPF JIT compiler for PPC64
+ *
+ * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+#ifndef _BPF_JIT_H
+#define _BPF_JIT_H
+
+#define BPF_PPC_STACK_LOCALS	32
+#define BPF_PPC_STACK_BASIC	112
+#define BPF_PPC_STACK_SAVE	128
+#define BPF_PPC_STACKFRAME	(BPF_PPC_STACK_BASIC+BPF_PPC_STACK_LOCALS+ \
+				 BPF_PPC_STACK_SAVE)
+
+/*
+ * Generated code register usage:
+ *
+ * As normal PPC C ABI (e.g. r1=sp, r2=TOC), with:
+ *
+ * skb		r3	(Entry parameter)
+ * A register	r4
+ * X register	r5
+ * addr param	r6
+ * r7-r10	scratch
+ * skb->data	r14
+ * skb headlen	r15	(skb->len - skb->data_len)
+ * m[0]		r16
+ * m[...]	...
+ * m[15]	r31
+ */
+#define r_skb		3
+#define r_ret		3
+#define r_A		4
+#define r_X		5
+#define r_addr		6
+#define r_scratch1	7
+#define r_D		14
+#define r_HL		15
+#define r_M		16
+
+#ifndef __ASSEMBLY__
+
+/*
+ * Assembly helpers from arch/powerpc/net/bpf_jit.S:
+ */
+extern u8 sk_load_word[], sk_load_half[], sk_load_byte[], sk_load_byte_msh[];
+
+#define FUNCTION_DESCR_SIZE	24
+
+/*
+ * 16-bit immediate helper macros: HA() is for use with sign-extending instrs
+ * (e.g. LD, ADDI).  If the bottom 16 bits is "-ve", add another bit into the
+ * top half to negate the effect (i.e. 0xffff + 1 = 0x(1)0000).
+ */
+#define IMM_H(i)		((uintptr_t)(i)>>16)
+#define IMM_HA(i)		(((uintptr_t)(i)>>16) +			      \
+				 (((uintptr_t)(i) & 0x8000) >> 15))
+#define IMM_L(i)		((uintptr_t)(i) & 0xffff)
+
+#define PLANT_INSTR(d, idx, instr)					      \
+	do { if (d) { (d)[idx] = instr; } idx++; } while (0)
+#define EMIT(instr)		PLANT_INSTR(image, ctx->idx, instr)
+
+#define PPC_NOP()		EMIT(PPC_INST_NOP)
+#define PPC_BLR()		EMIT(PPC_INST_BLR)
+#define PPC_BLRL()		EMIT(PPC_INST_BLRL)
+#define PPC_MTLR(r)		EMIT(PPC_INST_MTLR | __PPC_RT(r))
+#define PPC_ADDI(d, a, i)	EMIT(PPC_INST_ADDI | __PPC_RT(d) |	      \
+				     __PPC_RA(a) | IMM_L(i))
+#define PPC_MR(d, a)		PPC_OR(d, a, a)
+#define PPC_LI(r, i)		PPC_ADDI(r, 0, i)
+#define PPC_ADDIS(d, a, i)	EMIT(PPC_INST_ADDIS |			      \
+				     __PPC_RS(d) | __PPC_RA(a) | IMM_L(i))
+#define PPC_LIS(r, i)		PPC_ADDIS(r, 0, i)
+#define PPC_STD(r, base, i)	EMIT(PPC_INST_STD | __PPC_RS(r) |	      \
+				     __PPC_RA(base) | ((i) & 0xfffc))
+
+#define PPC_LD(r, base, i)	EMIT(PPC_INST_LD | __PPC_RT(r) |	      \
+				     __PPC_RA(base) | IMM_L(i))
+#define PPC_LWZ(r, base, i)	EMIT(PPC_INST_LWZ | __PPC_RT(r) |	      \
+				     __PPC_RA(base) | IMM_L(i))
+#define PPC_LHZ(r, base, i)	EMIT(PPC_INST_LHZ | __PPC_RT(r) |	      \
+				     __PPC_RA(base) | IMM_L(i))
+/* Convenience helpers for the above with 'far' offsets: */
+#define PPC_LD_OFFS(r, base, i) do { if ((i) < 32768) PPC_LD(r, base, i);     \
+		else {	PPC_ADDIS(r, base, IMM_HA(i));			      \
+			PPC_LD(r, r, IMM_L(i)); } } while(0)
+
+#define PPC_LWZ_OFFS(r, base, i) do { if ((i) < 32768) PPC_LWZ(r, base, i);   \
+		else {	PPC_ADDIS(r, base, IMM_HA(i));			      \
+			PPC_LWZ(r, r, IMM_L(i)); } } while(0)
+
+#define PPC_LHZ_OFFS(r, base, i) do { if ((i) < 32768) PPC_LHZ(r, base, i);   \
+		else {	PPC_ADDIS(r, base, IMM_HA(i));			      \
+			PPC_LHZ(r, r, IMM_L(i)); } } while(0)
+
+#define PPC_CMPWI(a, i)		EMIT(PPC_INST_CMPWI | __PPC_RA(a) | IMM_L(i))
+#define PPC_CMPDI(a, i)		EMIT(PPC_INST_CMPDI | __PPC_RA(a) | IMM_L(i))
+#define PPC_CMPLWI(a, i)	EMIT(PPC_INST_CMPLWI | __PPC_RA(a) | IMM_L(i))
+#define PPC_CMPLW(a, b)		EMIT(PPC_INST_CMPLW | __PPC_RA(a) | __PPC_RB(b))
+
+#define PPC_SUB(d, a, b)	EMIT(PPC_INST_SUB | __PPC_RT(d) |	      \
+				     __PPC_RB(a) | __PPC_RA(b))
+#define PPC_ADD(d, a, b)	EMIT(PPC_INST_ADD | __PPC_RT(d) |	      \
+				     __PPC_RA(a) | __PPC_RB(b))
+#define PPC_MUL(d, a, b)	EMIT(PPC_INST_MULLW | __PPC_RT(d) |	      \
+				     __PPC_RA(a) | __PPC_RB(b))
+#define PPC_MULHWU(d, a, b)	EMIT(PPC_INST_MULHWU | __PPC_RT(d) |	      \
+				     __PPC_RA(a) | __PPC_RB(b))
+#define PPC_MULI(d, a, i)	EMIT(PPC_INST_MULLI | __PPC_RT(d) |	      \
+				     __PPC_RA(a) | IMM_L(i))
+#define PPC_DIVWU(d, a, b)	EMIT(PPC_INST_DIVWU | __PPC_RT(d) |	      \
+				     __PPC_RA(a) | __PPC_RB(b))
+#define PPC_AND(d, a, b)	EMIT(PPC_INST_AND | __PPC_RA(d) |	      \
+				     __PPC_RS(a) | __PPC_RB(b))
+#define PPC_ANDI(d, a, i)	EMIT(PPC_INST_ANDI | __PPC_RA(d) |	      \
+				     __PPC_RS(a) | IMM_L(i))
+#define PPC_AND_DOT(d, a, b)	EMIT(PPC_INST_ANDDOT | __PPC_RA(d) |	      \
+				     __PPC_RS(a) | __PPC_RB(b))
+#define PPC_OR(d, a, b)		EMIT(PPC_INST_OR | __PPC_RA(d) |	      \
+				     __PPC_RS(a) | __PPC_RB(b))
+#define PPC_ORI(d, a, i)	EMIT(PPC_INST_ORI | __PPC_RA(d) |	      \
+				     __PPC_RS(a) | IMM_L(i))
+#define PPC_ORIS(d, a, i)	EMIT(PPC_INST_ORIS | __PPC_RA(d) |	      \
+				     __PPC_RS(a) | IMM_L(i))
+#define PPC_SLW(d, a, s)	EMIT(PPC_INST_SLW | __PPC_RA(d) |	      \
+				     __PPC_RS(a) | __PPC_RB(s))
+#define PPC_SRW(d, a, s)	EMIT(PPC_INST_SRW | __PPC_RA(d) |	      \
+				     __PPC_RS(a) | __PPC_RB(s))
+/* slwi = rlwinm Rx, Ry, n, 0, 31-n */
+#define PPC_SLWI(d, a, i)	EMIT(PPC_INST_RLWINM | __PPC_RA(d) |	      \
+				     __PPC_RS(a) | __PPC_SH(i) |	      \
+				     __PPC_MB(0) | __PPC_ME(31-(i)))
+/* srwi = rlwinm Rx, Ry, 32-n, n, 31 */
+#define PPC_SRWI(d, a, i)	EMIT(PPC_INST_RLWINM | __PPC_RA(d) |	      \
+				     __PPC_RS(a) | __PPC_SH(32-(i)) |	      \
+				     __PPC_MB(i) | __PPC_ME(31))
+/* sldi = rldicr Rx, Ry, n, 63-n */
+#define PPC_SLDI(d, a, i)	EMIT(PPC_INST_RLDICR | __PPC_RA(d) |	      \
+				     __PPC_RS(a) | __PPC_SH(i) |	      \
+				     __PPC_MB(63-(i)) | (((i) & 0x20) >> 4))
+#define PPC_NEG(d, a)		EMIT(PPC_INST_NEG | __PPC_RT(d) | __PPC_RA(a))
+
+/* Long jump; (unconditional 'branch') */
+#define PPC_JMP(dest)		EMIT(PPC_INST_BRANCH |			      \
+				     (((dest) - (ctx->idx * 4)) & 0x03fffffc))
+/* "cond" here covers BO:BI fields. */
+#define PPC_BCC_SHORT(cond, dest)	EMIT(PPC_INST_BRANCH_COND |	      \
+					     (((cond) & 0x3ff) << 16) |	      \
+					     (((dest) - (ctx->idx * 4)) &     \
+					      0xfffc))
+#define PPC_LI32(d, i)		do { PPC_LI(d, IMM_L(i));		      \
+		if ((u32)(uintptr_t)(i) >= 32768) {			      \
+			PPC_ADDIS(d, d, IMM_HA(i));			      \
+		} } while(0)
+#define PPC_LI64(d, i)		do {					      \
+		if (!((uintptr_t)(i) & 0xffffffff00000000ULL))		      \
+			PPC_LI32(d, i);					      \
+		else {							      \
+			PPC_LIS(d, ((uintptr_t)(i) >> 48));		      \
+			if ((uintptr_t)(i) & 0x0000ffff00000000ULL)	      \
+				PPC_ORI(d, d,				      \
+					((uintptr_t)(i) >> 32) & 0xffff);     \
+			PPC_SLDI(d, d, 32);				      \
+			if ((uintptr_t)(i) & 0x00000000ffff0000ULL)	      \
+				PPC_ORIS(d, d,				      \
+					 ((uintptr_t)(i) >> 16) & 0xffff);    \
+			if ((uintptr_t)(i) & 0x000000000000ffffULL)	      \
+				PPC_ORI(d, d, (uintptr_t)(i) & 0xffff);	      \
+		} } while (0);
+
+static inline bool is_nearbranch(int offset)
+{
+	return (offset < 32768) && (offset >= -32768);
+}
+
+/*
+ * The fly in the ointment of code size changing from pass to pass is
+ * avoided by padding the short branch case with a NOP.	 If code size differs
+ * with different branch reaches we will have the issue of code moving from
+ * one pass to the next and will need a few passes to converge on a stable
+ * state.
+ */
+#define PPC_BCC(cond, dest)	do {					      \
+		if (is_nearbranch((dest) - (ctx->idx * 4))) {		      \
+			PPC_BCC_SHORT(cond, dest);			      \
+			PPC_NOP();					      \
+		} else {						      \
+			/* Flip the 'T or F' bit to invert comparison */      \
+			PPC_BCC_SHORT(cond ^ COND_CMP_TRUE, (ctx->idx+2)*4);  \
+			PPC_JMP(dest);					      \
+		} } while(0)
+
+/* To create a branch condition, select a bit of cr0... */
+#define CR0_LT		0
+#define CR0_GT		1
+#define CR0_EQ		2
+/* ...and modify BO[3] */
+#define COND_CMP_TRUE	0x100
+#define COND_CMP_FALSE	0x000
+/* Together, they make all required comparisons: */
+#define COND_GT		(CR0_GT | COND_CMP_TRUE)
+#define COND_GE		(CR0_LT | COND_CMP_FALSE)
+#define COND_EQ		(CR0_EQ | COND_CMP_TRUE)
+#define COND_NE		(CR0_EQ | COND_CMP_FALSE)
+#define COND_LT		(CR0_LT | COND_CMP_TRUE)
+
+#define SEEN_DATAREF 0x10000 /* might call external helpers */
+#define SEEN_XREG    0x20000 /* X reg is used */
+#define SEEN_MEM     0x40000 /* SEEN_MEM+(1<<n) = use mem[n] for temporary
+			      * storage */
+#define SEEN_MEM_MSK 0x0ffff
+
+struct codegen_context {
+	unsigned int seen;
+	unsigned int idx;
+	int pc_ret0; /* bpf index of first RET #0 instruction (if any) */
+};
+
+#endif
+
+#endif
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
new file mode 100644
index 0000000..8a76350
--- /dev/null
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -0,0 +1,697 @@
+/* bpf_jit_comp.c: BPF JIT compiler for PPC64
+ *
+ * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation
+ *
+ * Based on the x86 BPF compiler, by Eric Dumazet (eric.dumazet@gmail.com)
+ *
+ * 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; version 2
+ * of the License.
+ */
+#include <linux/moduleloader.h>
+#include <asm/cacheflush.h>
+#include <linux/netdevice.h>
+#include <linux/filter.h>
+#include "bpf_jit.h"
+
+#ifndef __BIG_ENDIAN
+/* There are endianness assumptions herein. */
+#error "Little-endian PPC not supported in BPF compiler"
+#endif
+
+int bpf_jit_enable __read_mostly;
+
+
+static inline void bpf_flush_icache(void *start, void *end)
+{
+	smp_wmb();
+	flush_icache_range((unsigned long)start, (unsigned long)end);
+}
+
+static void bpf_jit_build_prologue(struct sk_filter *fp, u32 *image,
+				   struct codegen_context *ctx)
+{
+	int i;
+	const struct sock_filter *filter = fp->insns;
+
+	if (ctx->seen & (SEEN_MEM | SEEN_DATAREF)) {
+		/* Make stackframe */
+		if (ctx->seen & SEEN_DATAREF) {
+			/* If we call any helpers (for loads), save LR */
+			EMIT(PPC_INST_MFLR | __PPC_RT(0));
+			PPC_STD(0, 1, 16);
+
+			/* Back up non-volatile regs. */
+			PPC_STD(r_D, 1, -(8*(32-r_D)));
+			PPC_STD(r_HL, 1, -(8*(32-r_HL)));
+		}
+		if (ctx->seen & SEEN_MEM) {
+			/*
+			 * Conditionally save regs r15-r31 as some will be used
+			 * for M[] data.
+			 */
+			for (i = 0; i < 16; i++) {
+				if (ctx->seen & (1 << i))
+					PPC_STD(r_M + i, 1, -128 + (8*i));
+			}
+		}
+		EMIT(PPC_INST_STDU | __PPC_RS(1) | __PPC_RA(1) |
+		     (-BPF_PPC_STACKFRAME & 0xfffc));
+	}
+
+	if (ctx->seen & SEEN_DATAREF) {
+		/*
+		 * If this filter needs to access skb data,
+		 * prepare r_D and r_HL:
+		 *  r_HL = skb->len - skb->data_len
+		 *  r_D	 = skb->data
+		 */
+		PPC_LWZ_OFFS(r_scratch1, r_skb, offsetof(struct sk_buff,
+							 data_len));
+		PPC_LWZ_OFFS(r_HL, r_skb, offsetof(struct sk_buff, len));
+		PPC_SUB(r_HL, r_HL, r_scratch1);
+		PPC_LD_OFFS(r_D, r_skb, offsetof(struct sk_buff, data));
+	}
+
+	if (ctx->seen & SEEN_XREG) {
+		/*
+		 * TODO: Could also detect whether first instr. sets X and
+		 * avoid this (as below, with A).
+		 */
+		PPC_LI(r_X, 0);
+	}
+
+	switch (filter[0].code) {
+	case BPF_S_RET_K:
+	case BPF_S_LD_W_LEN:
+	case BPF_S_ANC_PROTOCOL:
+	case BPF_S_ANC_IFINDEX:
+	case BPF_S_ANC_MARK:
+	case BPF_S_ANC_RXHASH:
+	case BPF_S_ANC_CPU:
+	case BPF_S_ANC_QUEUE:
+	case BPF_S_LD_W_ABS:
+	case BPF_S_LD_H_ABS:
+	case BPF_S_LD_B_ABS:
+		/* first instruction sets A register (or is RET 'constant') */
+		break;
+	default:
+		/* make sure we dont leak kernel information to user */
+		PPC_LI(r_A, 0);
+	}
+}
+
+static void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx)
+{
+	int i;
+
+	if (ctx->seen & (SEEN_MEM | SEEN_DATAREF)) {
+		PPC_ADDI(1, 1, BPF_PPC_STACKFRAME);
+		if (ctx->seen & SEEN_DATAREF) {
+			PPC_LD(0, 1, 16);
+			PPC_MTLR(0);
+			PPC_LD(r_D, 1, -(8*(32-r_D)));
+			PPC_LD(r_HL, 1, -(8*(32-r_HL)));
+		}
+		if (ctx->seen & SEEN_MEM) {
+			/* Restore any saved non-vol registers */
+			for (i = 0; i < 16; i++) {
+				if (ctx->seen & (1 << i))
+					PPC_LD(r_M + i, 1, -128 + (8*i));
+			}
+		}
+	}
+	/* The RETs have left a return value in R3. */
+
+	PPC_BLR();
+}
+
+/* Assemble the body code between the prologue & epilogue. */
+static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
+			      struct codegen_context *ctx,
+			      unsigned int *addrs)
+{
+	const struct sock_filter *filter = fp->insns;
+	int flen = fp->len;
+	u8 *func;
+	unsigned int true_cond;
+	int i;
+
+	/* Start of epilogue code */
+	unsigned int exit_addr = addrs[flen];
+
+	for (i = 0; i < flen; i++) {
+		unsigned int K = filter[i].k;
+
+		/*
+		 * addrs[] maps a BPF bytecode address into a real offset from
+		 * the start of the body code.
+		 */
+		addrs[i] = ctx->idx * 4;
+
+		switch (filter[i].code) {
+			/*** ALU ops ***/
+		case BPF_S_ALU_ADD_X: /* A += X; */
+			ctx->seen |= SEEN_XREG;
+			PPC_ADD(r_A, r_A, r_X);
+			break;
+		case BPF_S_ALU_ADD_K: /* A += K; */
+			if (!K)
+				break;
+			if (K < 32768)
+				PPC_ADDI(r_A, r_A, K);
+			else
+				PPC_ADDI(r_A, r_A, IMM_L(K));
+				PPC_ADDIS(r_A, r_A, IMM_HA(K));
+			break;
+		case BPF_S_ALU_SUB_X: /* A -= X; */
+			ctx->seen |= SEEN_XREG;
+			PPC_SUB(r_A, r_A, r_X);
+			break;
+		case BPF_S_ALU_SUB_K: /* A -= K */
+			if (!K)
+				break;
+			if (K < 32768)
+				PPC_ADDI(r_A, r_A, -K);
+			else
+				PPC_ADDI(r_A, r_A, IMM_L(-K));
+				PPC_ADDIS(r_A, r_A, IMM_HA(-K));
+			break;
+		case BPF_S_ALU_MUL_X: /* A *= X; */
+			ctx->seen |= SEEN_XREG;
+			PPC_MUL(r_A, r_A, r_X);
+			break;
+		case BPF_S_ALU_MUL_K: /* A *= K */
+			if (K < 32768)
+				PPC_MULI(r_A, r_A, K);
+			else {
+				PPC_LI32(r_scratch1, K);
+				PPC_MUL(r_A, r_A, r_scratch1);
+			}
+			break;
+		case BPF_S_ALU_DIV_X: /* A /= X; */
+			ctx->seen |= SEEN_XREG;
+			PPC_CMPWI(r_X, 0);
+			if (ctx->pc_ret0 != -1) {
+				PPC_BCC(COND_EQ, addrs[ctx->pc_ret0]);
+			} else {
+				/*
+				 * Exit, returning 0; first pass hits here
+				 * (longer worst-case code size).
+				 */
+				PPC_BCC_SHORT(COND_NE, (ctx->idx*4)+12);
+				PPC_LI(r_ret, 0);
+				PPC_JMP(exit_addr);
+			}
+			PPC_DIVWU(r_A, r_A, r_X);
+			break;
+		case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K); */
+			PPC_LI32(r_scratch1, K);
+			/* Top 32 bits of 64bit result -> A */
+			PPC_MULHWU(r_A, r_A, r_scratch1);
+			break;
+		case BPF_S_ALU_AND_X:
+			ctx->seen |= SEEN_XREG;
+			PPC_AND(r_A, r_A, r_X);
+			break;
+		case BPF_S_ALU_AND_K:
+			if (!IMM_H(K))
+				PPC_ANDI(r_A, r_A, K);
+			else {
+				PPC_LI32(r_scratch1, K);
+				PPC_AND(r_A, r_A, r_scratch1);
+			}
+			break;
+		case BPF_S_ALU_OR_X:
+			ctx->seen |= SEEN_XREG;
+			PPC_OR(r_A, r_A, r_X);
+			break;
+		case BPF_S_ALU_OR_K:
+			if (IMM_L(K))
+				PPC_ORI(r_A, r_A, IMM_L(K));
+			if (K >= 65536)
+				PPC_ORIS(r_A, r_A, IMM_H(K));
+			break;
+		case BPF_S_ALU_LSH_X: /* A <<= X; */
+			ctx->seen |= SEEN_XREG;
+			PPC_SLW(r_A, r_A, r_X);
+			break;
+		case BPF_S_ALU_LSH_K:
+			if (K == 0)
+				break;
+			else
+				PPC_SLWI(r_A, r_A, K);
+			break;
+		case BPF_S_ALU_RSH_X: /* A >>= X; */
+			ctx->seen |= SEEN_XREG;
+			PPC_SRW(r_A, r_A, r_X);
+			break;
+		case BPF_S_ALU_RSH_K: /* A >>= K; */
+			if (K == 0)
+				break;
+			else
+				PPC_SRWI(r_A, r_A, K);
+			break;
+		case BPF_S_ALU_NEG:
+			PPC_NEG(r_A, r_A);
+			break;
+		case BPF_S_RET_K:
+			PPC_LI32(r_ret, K);
+			if (!K) {
+				if (ctx->pc_ret0 == -1)
+					ctx->pc_ret0 = i;
+			}
+			/*
+			 * If this isn't the very last instruction, branch to
+			 * the epilogue if we've stuff to clean up.  Otherwise,
+			 * if there's nothing to tidy, just return.  If we /are/
+			 * the last instruction, we're about to fall through to
+			 * the epilogue to return.
+			 */
+			if (i != flen - 1) {
+				/*
+				 * Note: 'seen' is properly valid only on pass
+				 * #2.	Both parts of this conditional are the
+				 * same instruction size though, meaning the
+				 * first pass will still correctly determine the
+				 * code size/addresses.
+				 */
+				if (ctx->seen)
+					PPC_JMP(exit_addr);
+				else
+					PPC_BLR();
+			}
+			break;
+		case BPF_S_RET_A:
+			PPC_MR(r_ret, r_A);
+			if (i != flen - 1) {
+				if (ctx->seen)
+					PPC_JMP(exit_addr);
+				else
+					PPC_BLR();
+			}
+			break;
+		case BPF_S_MISC_TAX: /* X = A */
+			ctx->seen |= SEEN_XREG;
+			PPC_MR(r_X, r_A);
+			break;
+		case BPF_S_MISC_TXA: /* A = X */
+			ctx->seen |= SEEN_XREG;
+			PPC_MR(r_A, r_X);
+			break;
+
+			/*** Constant loads/M[] access ***/
+		case BPF_S_LD_IMM: /* A = K */
+			PPC_LI32(r_A, K);
+			break;
+		case BPF_S_LDX_IMM: /* X = K */
+			ctx->seen |= SEEN_XREG;
+			PPC_LI32(r_X, K);
+			break;
+		case BPF_S_LD_MEM: /* A = mem[K] */
+			PPC_MR(r_A, r_M + (K & 0xf));
+			ctx->seen |= SEEN_MEM | (1<<(K & 0xf));
+			break;
+		case BPF_S_LDX_MEM: /* X = mem[K] */
+			PPC_MR(r_X, r_M + (K & 0xf));
+			ctx->seen |= SEEN_XREG | SEEN_MEM | (1<<(K & 0xf));
+			break;
+		case BPF_S_ST: /* mem[K] = A */
+			PPC_MR(r_M + (K & 0xf), r_A);
+			ctx->seen |= SEEN_MEM | (1<<(K & 0xf));
+			break;
+		case BPF_S_STX: /* mem[K] = X */
+			PPC_MR(r_M + (K & 0xf), r_X);
+			ctx->seen |= SEEN_XREG | SEEN_MEM | (1<<(K & 0xf));
+			break;
+		case BPF_S_LD_W_LEN: /*	A = skb->len; */
+			BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, len) != 4);
+			PPC_LWZ_OFFS(r_A, r_skb, offsetof(struct sk_buff, len));
+			break;
+		case BPF_S_LDX_W_LEN: /* X = skb->len; */
+			ctx->seen |= SEEN_XREG;
+			PPC_LWZ_OFFS(r_X, r_skb, offsetof(struct sk_buff, len));
+			break;
+
+			/*** Ancillary info loads ***/
+
+			/* None of the BPF_S_ANC* codes appear to be passed by
+			 * sk_chk_filter().  The interpreter and the x86 BPF
+			 * compiler implement them so we do too -- they may be
+			 * planted in future.
+			 */
+		case BPF_S_ANC_PROTOCOL: /* A = ntohs(skb->protocol); */
+			BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
+						  protocol) != 2);
+			PPC_LHZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
+							  protocol));
+			/* ntohs is a NOP with BE loads. */
+			break;
+		case BPF_S_ANC_IFINDEX:
+			PPC_LD_OFFS(r_scratch1, r_skb, offsetof(struct sk_buff,
+								dev));
+			PPC_CMPDI(r_scratch1, 0);
+			if (ctx->pc_ret0 != -1) {
+				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_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,
+				     offsetof(struct net_device, ifindex));
+			break;
+		case BPF_S_ANC_MARK:
+			BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, mark) != 4);
+			PPC_LWZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
+							  mark));
+			break;
+		case BPF_S_ANC_RXHASH:
+			BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, rxhash) != 4);
+			PPC_LWZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
+							  rxhash));
+			break;
+		case BPF_S_ANC_QUEUE:
+			BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
+						  queue_mapping) != 2);
+			PPC_LWZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
+							  queue_mapping));
+			break;
+		case BPF_S_ANC_CPU:
+#ifdef CONFIG_SMP
+			/*
+			 * PACA ptr is r13:
+			 * raw_smp_processor_id() = local_paca->paca_index
+			 */
+			PPC_LHZ_OFFS(r_A, 13,
+				     offsetof(struct paca_struct, paca_index));
+#else
+			PPC_LI(r_A, 0);
+#endif
+			break;
+
+			/*** Absolute loads from packet header/data ***/
+		case BPF_S_LD_W_ABS:
+			func = sk_load_word;
+			goto common_load;
+		case BPF_S_LD_H_ABS:
+			func = sk_load_half;
+			goto common_load;
+		case BPF_S_LD_B_ABS:
+			func = sk_load_byte;
+		common_load:
+			/*
+			 * Load from [K].  Reference with the (negative)
+			 * SKF_NET_OFF/SKF_LL_OFF offsets is unsupported.
+			 */
+			ctx->seen |= SEEN_DATAREF;
+			if ((int)K < 0)
+				return -ENOTSUPP;
+			PPC_LI64(r_scratch1, func);
+			PPC_MTLR(r_scratch1);
+			PPC_LI32(r_addr, K);
+			PPC_BLRL();
+			/*
+			 * Helper returns 'lt' condition on error, and an
+			 * appropriate return value in r3
+			 */
+			PPC_BCC(COND_LT, exit_addr);
+			break;
+
+			/*** Indirect loads from packet header/data ***/
+		case BPF_S_LD_W_IND:
+			func = sk_load_word;
+			goto common_load_ind;
+		case BPF_S_LD_H_IND:
+			func = sk_load_half;
+			goto common_load_ind;
+		case BPF_S_LD_B_IND:
+			func = sk_load_byte;
+		common_load_ind:
+			/*
+			 * Load from [X + K].  Negative offsets are tested for
+			 * in the helper functions, and result in a 'ret 0'.
+			 */
+			ctx->seen |= SEEN_DATAREF | SEEN_XREG;
+			PPC_LI64(r_scratch1, func);
+			PPC_MTLR(r_scratch1);
+			PPC_ADDI(r_addr, r_X, IMM_L(K));
+			if (K >= 32768)
+				PPC_ADDIS(r_addr, r_addr, IMM_HA(K));
+			PPC_BLRL();
+			/* If error, cr0.LT set */
+			PPC_BCC(COND_LT, exit_addr);
+			break;
+
+		case BPF_S_LDX_B_MSH:
+			/*
+			 * x86 version drops packet (RET 0) when K<0, whereas
+			 * interpreter does allow K<0 (__load_pointer, special
+			 * ancillary data).
+			 */
+			ctx->seen |= SEEN_XREG;
+			func = sk_load_byte_msh;
+			goto common_load;
+			break;
+
+			/*** Jump and branches ***/
+		case BPF_S_JMP_JA:
+			PPC_JMP(addrs[i + K]);
+			break;
+
+		case BPF_S_JMP_JGT_K:
+		case BPF_S_JMP_JGT_X:
+			true_cond = COND_GT;
+			goto cond_branch;
+		case BPF_S_JMP_JGE_K:
+		case BPF_S_JMP_JGE_X:
+			true_cond = COND_GE;
+			goto cond_branch;
+		case BPF_S_JMP_JEQ_K:
+		case BPF_S_JMP_JEQ_X:
+			true_cond = COND_EQ;
+			goto cond_branch;
+		case BPF_S_JMP_JSET_K:
+		case BPF_S_JMP_JSET_X:
+			true_cond = COND_NE;
+			/* Fall through */
+		cond_branch:
+			/* same targets, can avoid doing the test :) */
+			if (filter[i].jt == filter[i].jf) {
+				if (filter[i].jt > 0)
+					PPC_JMP(addrs[i + 1 + filter[i].jt]);
+				break;
+			}
+
+			switch (filter[i].code) {
+			case BPF_S_JMP_JGT_X:
+			case BPF_S_JMP_JGE_X:
+			case BPF_S_JMP_JEQ_X:
+				ctx->seen |= SEEN_XREG;
+				PPC_CMPLW(r_A, r_X);
+				break;
+			case BPF_S_JMP_JSET_X:
+				ctx->seen |= SEEN_XREG;
+				PPC_AND_DOT(r_scratch1, r_A, r_X);
+				break;
+			case BPF_S_JMP_JEQ_K:
+			case BPF_S_JMP_JGT_K:
+			case BPF_S_JMP_JGE_K:
+				if (K < 32768)
+					PPC_CMPLWI(r_A, K);
+				else {
+					PPC_LI32(r_scratch1, K);
+					PPC_CMPLW(r_A, r_scratch1);
+				}
+				break;
+			case BPF_S_JMP_JSET_K:
+				if (K < 32768)
+					/* PPC_ANDI is /only/ dot-form */
+					PPC_ANDI(r_scratch1, r_A, K);
+				else {
+					PPC_LI32(r_scratch1, K);
+					PPC_AND_DOT(r_scratch1, r_A,
+						    r_scratch1);
+				}
+				break;
+			}
+			/* Sometimes branches are constructed "backward", with
+			 * the false path being the branch and true path being
+			 * a fallthrough to the next instruction.
+			 */
+			if (filter[i].jt == 0)
+				/* Swap the sense of the branch */
+				PPC_BCC(true_cond ^ COND_CMP_TRUE,
+					addrs[i + 1 + filter[i].jf]);
+			else {
+				PPC_BCC(true_cond, addrs[i + 1 + filter[i].jt]);
+				if (filter[i].jf != 0)
+					PPC_JMP(addrs[i + 1 + filter[i].jf]);
+			}
+			break;
+		default:
+			/* The filter contains something cruel & unusual.
+			 * We don't handle it, but also there shouldn't be
+			 * anything missing from our list.
+			 */
+			pr_err("BPF filter opcode %04x (@%d) unsupported\n",
+			       filter[i].code, i);
+			return -ENOTSUPP;
+		}
+
+	}
+	/* Set end-of-body-code address for exit. */
+	addrs[i] = ctx->idx * 4;
+
+	return 0;
+}
+
+void bpf_jit_compile(struct sk_filter *fp)
+{
+	unsigned int proglen;
+	unsigned int alloclen;
+	u32 *image = NULL;
+	u32 *code_base;
+	unsigned int *addrs;
+	struct codegen_context cgctx;
+	int pass;
+	int flen = fp->len;
+
+	if (!bpf_jit_enable)
+		return;
+
+	addrs = kzalloc((flen+1) * sizeof(*addrs), GFP_KERNEL);
+	if (addrs == NULL)
+		return;
+
+	/*
+	 * There are multiple assembly passes as the generated code will change
+	 * size as it settles down, figuring out the max branch offsets/exit
+	 * paths required.
+	 *
+	 * The range of standard conditional branches is +/- 32Kbytes.	Since
+	 * BPF_MAXINSNS = 4096, we can only jump from (worst case) start to
+	 * finish with 8 bytes/instruction.  Not feasible, so long jumps are
+	 * used, distinct from short branches.
+	 *
+	 * Current:
+	 *
+	 * For now, both branch types assemble to 2 words (short branches padded
+	 * with a NOP); this is inefficient, but assembly will always complete
+	 * after exactly 3 passes:
+	 *
+	 * First pass: No code buffer; Program is "faux-generated" -- no code
+	 * emitted but maximum size of output determined (and addrs[] filled
+	 * in).	 Also, we note whether we use M[], whether we use skb data, etc.
+	 * All generation choices assumed to be 'worst-case', e.g. branches all
+	 * far (2 instructions), return path code reduction not available, etc.
+	 *
+	 * Second pass: Code buffer allocated with size determined previously.
+	 * Prologue generated to support features we have seen used.  Exit paths
+	 * determined and addrs[] is filled in again, as code may be slightly
+	 * smaller as a result.
+	 *
+	 * Third pass: Code generated 'for real', and branch destinations
+	 * determined from now-accurate addrs[] map.
+	 *
+	 * Ideal:
+	 *
+	 * If we optimise this, near branches will be shorter.	On the
+	 * first assembly pass, we should err on the side of caution and
+	 * generate the biggest code.  On subsequent passes, branches will be
+	 * generated short or long and code size will reduce.  With smaller
+	 * code, more branches may fall into the short category, and code will
+	 * reduce more.
+	 *
+	 * Finally, if we see one pass generate code the same size as the
+	 * previous pass we have converged and should now generate code for
+	 * real.  Allocating at the end will also save the memory that would
+	 * otherwise be wasted by the (small) current code shrinkage.
+	 * Preferably, we should do a small number of passes (e.g. 5) and if we
+	 * haven't converged by then, get impatient and force code to generate
+	 * as-is, even if the odd branch would be left long.  The chances of a
+	 * long jump are tiny with all but the most enormous of BPF filter
+	 * inputs, so we should usually converge on the third pass.
+	 */
+
+	cgctx.idx = 0;
+	cgctx.seen = 0;
+	cgctx.pc_ret0 = -1;
+	/* Scouting faux-generate pass 0 */
+	if (bpf_jit_build_body(fp, 0, &cgctx, addrs))
+		/* We hit something illegal or unsupported. */
+		goto out;
+
+	/*
+	 * Pretend to build prologue, given the features we've seen.  This will
+	 * update ctgtx.idx as it pretends to output instructions, then we can
+	 * calculate total size from idx.
+	 */
+	bpf_jit_build_prologue(fp, 0, &cgctx);
+	bpf_jit_build_epilogue(0, &cgctx);
+
+	proglen = cgctx.idx * 4;
+	alloclen = proglen + FUNCTION_DESCR_SIZE;
+	image = module_alloc(max_t(unsigned int, alloclen,
+				   sizeof(struct work_struct)));
+	if (!image)
+		goto out;
+
+	code_base = image + (FUNCTION_DESCR_SIZE/4);
+
+	/* Code generation passes 1-2 */
+	for (pass = 1; pass < 3; pass++) {
+		/* Now build the prologue, body code & epilogue for real. */
+		cgctx.idx = 0;
+		bpf_jit_build_prologue(fp, code_base, &cgctx);
+		bpf_jit_build_body(fp, code_base, &cgctx, addrs);
+		bpf_jit_build_epilogue(code_base, &cgctx);
+
+		if (bpf_jit_enable > 1)
+			pr_info("Pass %d: shrink = %d, seen = 0x%x\n", pass,
+				proglen - (cgctx.idx * 4), cgctx.seen);
+	}
+
+	if (bpf_jit_enable > 1)
+		pr_info("flen=%d proglen=%u pass=%d image=%p\n",
+		       flen, proglen, pass, image);
+
+	if (image) {
+		if (bpf_jit_enable > 1)
+			print_hex_dump(KERN_ERR, "JIT code: ",
+				       DUMP_PREFIX_ADDRESS,
+				       16, 1, code_base,
+				       proglen, false);
+
+		bpf_flush_icache(code_base, code_base + (proglen/4));
+		/* Function descriptor nastiness: Address + TOC */
+		((u64 *)image)[0] = (u64)code_base;
+		((u64 *)image)[1] = local_paca->kernel_toc;
+		fp->bpf_func = (void *)image;
+	}
+out:
+	kfree(addrs);
+	return;
+}
+
+static void jit_free_defer(struct work_struct *arg)
+{
+	module_free(NULL, arg);
+}
+
+/* run from softirq, we must use a work_struct to call
+ * module_free() from process context
+ */
+void bpf_jit_free(struct sk_filter *fp)
+{
+	if (fp->bpf_func != sk_run_filter) {
+		struct work_struct *work = (struct work_struct *)fp->bpf_func;
+
+		INIT_WORK(work, jit_free_defer);
+		schedule_work(work);
+	}
+}

^ 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