LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: ppc/sata-fsl: orphan config value: CONFIG_MPC8315_DS
From: Scott Wood @ 2012-05-30 20:20 UTC (permalink / raw)
  To: Anthony Foiani
  Cc: Robert P.J.Day, linuxppc-dev@lists.ozlabs.org, Li Yang-R58472,
	Jeff Garzik, Adrian Bunk
In-Reply-To: <gd35lbf55.fsf@dworkin.scrye.com>

On 05/30/2012 03:14 PM, Anthony Foiani wrote:
> Scott Wood <scottwood@freescale.com> writes:
> 
>> Board information is available from the device tree, and from
>> platform code that was selected based on the device tree.
> 
> You're right, of course; I was focusing on discovery/probing, and
> completely forgot about "provided information".
> 
> However, as I just mentioned in my reply to Yang, I'm pretty happy
> with the kconfig solution (Adrian's patch, basically).
> 
> If we find that this is a more widespread problem, we can revisit this
> discussion; but if only a handful of us have encountered this in a
> 5-year-old design, then I don't think it's worth the extra effort of
> making it dynamic.

We currently support building one kernel that supports a bunch of
different boards.  The hardcoding of this workaround was harmless so far
because it was conditional on a symbol that was never defined, but now
you'll be enabling this workaround on any kernel that simply has support
for mpc8315erdb.  That is not acceptable unless you show it's harmless
on all those other boards.

-Scott

^ permalink raw reply

* Re: ppc/sata-fsl: orphan config value: CONFIG_MPC8315_DS
From: Anthony Foiani @ 2012-05-30 20:52 UTC (permalink / raw)
  To: Scott Wood
  Cc: Robert P.J.Day, linuxppc-dev@lists.ozlabs.org, Li Yang-R58472,
	Jeff Garzik, Adrian Bunk
In-Reply-To: <4FC68109.3030607@freescale.com>

Scott Wood <scottwood@freescale.com> writes:

> We currently support building one kernel that supports a bunch of
> different boards.  The hardcoding of this workaround was harmless so
> far because it was conditional on a symbol that was never defined,
> but now you'll be enabling this workaround on any kernel that simply
> has support for mpc8315erdb.  That is not acceptable unless you show
> it's harmless on all those other boards.

Ok, I see your point now.  Sorry for being dense.

At the moment, I'm building a kernel that is only going to run on this
particular board, so the kconfig solution works *for me*.

Unfortunately, I'm not sure I can help develop a more generic
solution.  I can't reliably reproduce the problem, so I can't even
offer to help test for it.

Even more unfortunately, I don't currently have the bandwidth to do
any more investigation or experimenting with the devtree option (as
much as I would like to!).  At this point in my project, I probably
can't even justify trying to switch to a more current kernel, so I
couldn't try out a new release regardless.

Sorry I can't be more help.

Thanks again,
Tony

^ permalink raw reply

* Re: kernel panic during kernel module load (powerpc specific part)
From: Michael Ellerman @ 2012-05-30 23:24 UTC (permalink / raw)
  To: Steffen Rumler; +Cc: linuxppc-dev
In-Reply-To: <4FC62FB9.8010701@nsn.com>

On Wed, 2012-05-30 at 16:33 +0200, Steffen Rumler wrote:
> Hi,
> 
> The system crashes inside the return of the init entry point of the kernel module.
> 
> I've found the following root cause:
> 
>      (6) Unfortunately, the trampoline code (do_plt_call()) is using register r11 to setup the jump.
>            It looks like the prologue and epilogue are using also the register r11, in order to point to the previous stack frame.
>            This is a conflict !!! The trampoline code is damaging the content of r11.

Hi Steffen,

Great bug report!

I can't quite work out what the standards say, the versions I'm looking
at are probably old anyway.

Have you tried the obvious fix?

cheers


diff --git a/arch/powerpc/kernel/module_32.c b/arch/powerpc/kernel/module_32.c
index 0b6d796..989d79a 100644
--- a/arch/powerpc/kernel/module_32.c
+++ b/arch/powerpc/kernel/module_32.c
@@ -205,9 +205,9 @@ static uint32_t do_plt_call(void *location,
        }
 
        /* Stolen from Paul Mackerras as well... */
-       entry->jump[0] = 0x3d600000+((val+0x8000)>>16); /* lis r11,sym@ha */
-       entry->jump[1] = 0x396b0000 + (val&0xffff);     /* addi r11,r11,sym@l*/
-       entry->jump[2] = 0x7d6903a6;                    /* mtctr r11 */
+       entry->jump[0] = 0x3d800000+((val+0x8000)>>16); /* lis r12,sym@ha */
+       entry->jump[1] = 0x398c0000 + (val&0xffff);     /* addi r12,r12,sym@l*/
+       entry->jump[2] = 0x7d8903a6;                    /* mtctr r12 */
        entry->jump[3] = 0x4e800420;                    /* bctr */
 
        DEBUGP("Initialized plt for 0x%x at %p\n", val, entry);

^ permalink raw reply related

* [PATCH] powerpc/mm: dereference OF node "/chosen"
From: Gavin Shan @ 2012-05-31  3:07 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: michael, Gavin Shan

The form affinity for NUMA is set to 1 if the firmware supports
OPAL. Otherwise, we have to retrieve that from OF node "/chosen".
For the latter case, OF node "/chosen" was referred without
dereferencing.

The patch dereference OF node "/chosen" if necessary.

Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
---
 arch/powerpc/mm/numa.c |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index b6edbb3..5ca3a15 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -340,6 +340,8 @@ static int __init find_min_common_depth(void)
 				dbg("Using form 1 affinity\n");
 				form1_affinity = 1;
 			}
+
+			of_node_put(chosen);
 		}
 	}
 
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH] powerpc/pci: cleanup on duplicate assignment
From: Gavin Shan @ 2012-05-31  6:17 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: michael, Gavin Shan

While creating the PCI root bus through function pci_create_root_bus()
of PCI core, it should have assigned the secondary bus number for the
newly created PCI root bus. Thus we needn't do the explicit assignment
for the secondary bus number again in pcibios_scan_phb().

Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
---
 arch/powerpc/kernel/pci-common.c |    1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 8e78e93..0f75bd5 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -1646,7 +1646,6 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose)
 		pci_free_resource_list(&resources);
 		return;
 	}
-	bus->secondary = hose->first_busno;
 	hose->bus = bus;
 
 	/* Get probe mode and perform scan */
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH] powerpc: Use enhanced touch instructions in POWER7 copy_to_user/copy_from_user
From: Anton Blanchard @ 2012-05-31  6:19 UTC (permalink / raw)
  To: benh, paulus, michael, amodra; +Cc: linuxppc-dev
In-Reply-To: <20120529181432.2038c1a3@kryten>


Version 2.06 of the POWER ISA introduced enhanced touch instructions,
allowing us to specify a number of attributes including the length of
a stream.

This patch adds a software stream for both loads and stores in the
POWER7 copy_tofrom_user loop. Since the setup is quite complicated
and we have to use an eieio to ensure correct ordering of the "GO"
command we only do this for copies above 4kB.

To quantify any performance improvements we need a working set
bigger than the caches so we operate on a 1GB file:

# dd if=/dev/zero of=/tmp/foo bs=1M count=1024

And we compare how fast we can read the file:

# dd if=/tmp/foo of=/dev/null bs=1M

before: 7.7 GB/s
after:  9.6 GB/s

A 25% improvement.

The worst case for this patch will be a completely L1 cache contained
copy of just over 4kB. We can test this with the copy_to_user
testcase we used to tune copy_tofrom_user originally:

http://ozlabs.org/~anton/junkcode/copy_to_user.c

# time ./copy_to_user2 -l 4224 -i 10000000

before: 6.807 s
after:  6.946 s

A 2% slowdown, which seems reasonable considering our data is unlikely
to be completely L1 contained.

Signed-off-by: Anton Blanchard <anton@samba.org>  
---

v2: Use cr1 in the comparison so we don't corrupt the compare/branch
to select vmx vs non vmx loops.

Index: linux-build/arch/powerpc/lib/copyuser_power7.S
===================================================================
--- linux-build.orig/arch/powerpc/lib/copyuser_power7.S	2012-05-29 21:22:40.445551834 +1000
+++ linux-build/arch/powerpc/lib/copyuser_power7.S	2012-05-31 15:28:35.336354208 +1000
@@ -298,6 +298,37 @@ err1;	stb	r0,0(r3)
 	ld	r5,STACKFRAMESIZE+64(r1)
 	mtlr	r0
 
+	/*
+	 * We prefetch both the source and destination using enhanced touch
+	 * instructions. We use a stream ID of 0 for the load side and
+	 * 1 for the store side.
+	 */
+	clrrdi	r6,r4,7
+	clrrdi	r9,r3,7
+	ori	r9,r9,1		/* stream=1 */
+
+	srdi	r7,r5,7		/* length in cachelines, capped at 0x3FF */
+	cmpldi	cr1,r7,0x3FF
+	ble	cr1,1f
+	li	r7,0x3FF
+1:	lis	r0,0x0E00	/* depth=7 */
+	sldi	r7,r7,7
+	or	r7,r7,r0
+	ori	r10,r7,1	/* stream=1 */
+
+	lis	r8,0x8000	/* GO=1 */
+	clrldi	r8,r8,32
+
+.machine push
+.machine "power4"
+	dcbt	r0,r6,0b01000
+	dcbt	r0,r7,0b01010
+	dcbtst	r0,r9,0b01000
+	dcbtst	r0,r10,0b01010
+	eieio
+	dcbt	r0,r8,0b01010	/* GO */
+.machine pop
+
 	beq	.Lunwind_stack_nonvmx_copy
 
 	/*

^ permalink raw reply

* [PATCH] powerpc: POWER7 optimised memcpy using VMX and enhanced prefetch
From: Anton Blanchard @ 2012-05-31  6:22 UTC (permalink / raw)
  To: benh, paulus, michael; +Cc: linuxppc-dev


Implement a POWER7 optimised memcpy using VMX and enhanced prefetch
instructions.

This is a copy of the POWER7 optimised copy_to_user/copy_from_user
loop. Detailed implementation and performance details can be found in
commit a66086b8197d (powerpc: POWER7 optimised
copy_to_user/copy_from_user using VMX).

I noticed memcpy issues when profiling a RAID6 workload:

	.memcpy
	.async_memcpy
	.async_copy_data
	.__raid_run_ops
	.handle_stripe
	.raid5d
	.md_thread

I created a simplified testcase by building a RAID6 array with 4 1GB
ramdisks (booting with brd.rd_size=1048576):

# mdadm -CR -e 1.2 /dev/md0 --level=6 -n4 /dev/ram[0-3]

I then timed how long it took to write to the entire array:

# dd if=/dev/zero of=/dev/md0 bs=1M

Before: 892 MB/s
After:  999 MB/s

A 12% improvement.

Signed-off-by: Anton Blanchard <anton@samba.org>
---

Index: linux-build/arch/powerpc/lib/Makefile
===================================================================
--- linux-build.orig/arch/powerpc/lib/Makefile	2012-05-30 15:27:30.000000000 +1000
+++ linux-build/arch/powerpc/lib/Makefile	2012-05-31 09:12:27.574372864 +1000
@@ -17,7 +17,8 @@ obj-$(CONFIG_HAS_IOMEM)	+= devres.o
 obj-$(CONFIG_PPC64)	+= copypage_64.o copyuser_64.o \
 			   memcpy_64.o usercopy_64.o mem_64.o string.o \
 			   checksum_wrappers_64.o hweight_64.o \
-			   copyuser_power7.o string_64.o copypage_power7.o
+			   copyuser_power7.o string_64.o copypage_power7.o \
+			   memcpy_power7.o
 obj-$(CONFIG_XMON)	+= sstep.o ldstfp.o
 obj-$(CONFIG_KPROBES)	+= sstep.o ldstfp.o
 obj-$(CONFIG_HAVE_HW_BREAKPOINT)	+= sstep.o ldstfp.o
Index: linux-build/arch/powerpc/lib/memcpy_64.S
===================================================================
--- linux-build.orig/arch/powerpc/lib/memcpy_64.S	2012-05-30 09:39:59.000000000 +1000
+++ linux-build/arch/powerpc/lib/memcpy_64.S	2012-05-31 09:12:00.093876936 +1000
@@ -11,7 +11,11 @@
 
 	.align	7
 _GLOBAL(memcpy)
+BEGIN_FTR_SECTION
 	std	r3,48(r1)	/* save destination pointer for return value */
+FTR_SECTION_ELSE
+	b	memcpy_power7
+ALT_FTR_SECTION_END_IFCLR(CPU_FTR_VMX_COPY)
 	PPC_MTOCRF(0x01,r5)
 	cmpldi	cr1,r5,16
 	neg	r6,r3		# LS 3 bits = # bytes to 8-byte dest bdry
Index: linux-build/arch/powerpc/lib/memcpy_power7.S
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-build/arch/powerpc/lib/memcpy_power7.S	2012-05-31 15:28:03.495781127 +1000
@@ -0,0 +1,650 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2012
+ *
+ * Author: Anton Blanchard <anton@au.ibm.com>
+ */
+#include <asm/ppc_asm.h>
+
+#define STACKFRAMESIZE	256
+#define STK_REG(i)	(112 + ((i)-14)*8)
+
+_GLOBAL(memcpy_power7)
+#ifdef CONFIG_ALTIVEC
+	cmpldi	r5,16
+	cmpldi	cr1,r5,4096
+
+	std	r3,48(r1)
+
+	blt	.Lshort_copy
+	bgt	cr1,.Lvmx_copy
+#else
+	cmpldi	r5,16
+
+	std	r3,48(r1)
+
+	blt	.Lshort_copy
+#endif
+
+.Lnonvmx_copy:
+	/* Get the source 8B aligned */
+	neg	r6,r4
+	mtocrf	0x01,r6
+	clrldi	r6,r6,(64-3)
+
+	bf	cr7*4+3,1f
+	lbz	r0,0(r4)
+	addi	r4,r4,1
+	stb	r0,0(r3)
+	addi	r3,r3,1
+
+1:	bf	cr7*4+2,2f
+	lhz	r0,0(r4)
+	addi	r4,r4,2
+	sth	r0,0(r3)
+	addi	r3,r3,2
+
+2:	bf	cr7*4+1,3f
+	lwz	r0,0(r4)
+	addi	r4,r4,4
+	stw	r0,0(r3)
+	addi	r3,r3,4
+
+3:	sub	r5,r5,r6
+	cmpldi	r5,128
+	blt	5f
+
+	mflr	r0
+	stdu	r1,-STACKFRAMESIZE(r1)
+	std	r14,STK_REG(r14)(r1)
+	std	r15,STK_REG(r15)(r1)
+	std	r16,STK_REG(r16)(r1)
+	std	r17,STK_REG(r17)(r1)
+	std	r18,STK_REG(r18)(r1)
+	std	r19,STK_REG(r19)(r1)
+	std	r20,STK_REG(r20)(r1)
+	std	r21,STK_REG(r21)(r1)
+	std	r22,STK_REG(r22)(r1)
+	std	r0,STACKFRAMESIZE+16(r1)
+
+	srdi	r6,r5,7
+	mtctr	r6
+
+	/* Now do cacheline (128B) sized loads and stores. */
+	.align	5
+4:
+	ld	r0,0(r4)
+	ld	r6,8(r4)
+	ld	r7,16(r4)
+	ld	r8,24(r4)
+	ld	r9,32(r4)
+	ld	r10,40(r4)
+	ld	r11,48(r4)
+	ld	r12,56(r4)
+	ld	r14,64(r4)
+	ld	r15,72(r4)
+	ld	r16,80(r4)
+	ld	r17,88(r4)
+	ld	r18,96(r4)
+	ld	r19,104(r4)
+	ld	r20,112(r4)
+	ld	r21,120(r4)
+	addi	r4,r4,128
+	std	r0,0(r3)
+	std	r6,8(r3)
+	std	r7,16(r3)
+	std	r8,24(r3)
+	std	r9,32(r3)
+	std	r10,40(r3)
+	std	r11,48(r3)
+	std	r12,56(r3)
+	std	r14,64(r3)
+	std	r15,72(r3)
+	std	r16,80(r3)
+	std	r17,88(r3)
+	std	r18,96(r3)
+	std	r19,104(r3)
+	std	r20,112(r3)
+	std	r21,120(r3)
+	addi	r3,r3,128
+	bdnz	4b
+
+	clrldi	r5,r5,(64-7)
+
+	ld	r14,STK_REG(r14)(r1)
+	ld	r15,STK_REG(r15)(r1)
+	ld	r16,STK_REG(r16)(r1)
+	ld	r17,STK_REG(r17)(r1)
+	ld	r18,STK_REG(r18)(r1)
+	ld	r19,STK_REG(r19)(r1)
+	ld	r20,STK_REG(r20)(r1)
+	ld	r21,STK_REG(r21)(r1)
+	ld	r22,STK_REG(r22)(r1)
+	addi	r1,r1,STACKFRAMESIZE
+
+	/* Up to 127B to go */
+5:	srdi	r6,r5,4
+	mtocrf	0x01,r6
+
+6:	bf	cr7*4+1,7f
+	ld	r0,0(r4)
+	ld	r6,8(r4)
+	ld	r7,16(r4)
+	ld	r8,24(r4)
+	ld	r9,32(r4)
+	ld	r10,40(r4)
+	ld	r11,48(r4)
+	ld	r12,56(r4)
+	addi	r4,r4,64
+	std	r0,0(r3)
+	std	r6,8(r3)
+	std	r7,16(r3)
+	std	r8,24(r3)
+	std	r9,32(r3)
+	std	r10,40(r3)
+	std	r11,48(r3)
+	std	r12,56(r3)
+	addi	r3,r3,64
+
+	/* Up to 63B to go */
+7:	bf	cr7*4+2,8f
+	ld	r0,0(r4)
+	ld	r6,8(r4)
+	ld	r7,16(r4)
+	ld	r8,24(r4)
+	addi	r4,r4,32
+	std	r0,0(r3)
+	std	r6,8(r3)
+	std	r7,16(r3)
+	std	r8,24(r3)
+	addi	r3,r3,32
+
+	/* Up to 31B to go */
+8:	bf	cr7*4+3,9f
+	ld	r0,0(r4)
+	ld	r6,8(r4)
+	addi	r4,r4,16
+	std	r0,0(r3)
+	std	r6,8(r3)
+	addi	r3,r3,16
+
+9:	clrldi	r5,r5,(64-4)
+
+	/* Up to 15B to go */
+.Lshort_copy:
+	mtocrf	0x01,r5
+	bf	cr7*4+0,12f
+	lwz	r0,0(r4)	/* Less chance of a reject with word ops */
+	lwz	r6,4(r4)
+	addi	r4,r4,8
+	stw	r0,0(r3)
+	stw	r6,4(r3)
+	addi	r3,r3,8
+
+12:	bf	cr7*4+1,13f
+	lwz	r0,0(r4)
+	addi	r4,r4,4
+	stw	r0,0(r3)
+	addi	r3,r3,4
+
+13:	bf	cr7*4+2,14f
+	lhz	r0,0(r4)
+	addi	r4,r4,2
+	sth	r0,0(r3)
+	addi	r3,r3,2
+
+14:	bf	cr7*4+3,15f
+	lbz	r0,0(r4)
+	stb	r0,0(r3)
+
+15:	ld	r3,48(r1)
+	blr
+
+.Lunwind_stack_nonvmx_copy:
+	addi	r1,r1,STACKFRAMESIZE
+	b	.Lnonvmx_copy
+
+#ifdef CONFIG_ALTIVEC
+.Lvmx_copy:
+	mflr	r0
+	std	r4,56(r1)
+	std	r5,64(r1)
+	std	r0,16(r1)
+	stdu	r1,-STACKFRAMESIZE(r1)
+	bl	.enter_vmx_copy
+	cmpwi	r3,0
+	ld	r0,STACKFRAMESIZE+16(r1)
+	ld	r3,STACKFRAMESIZE+48(r1)
+	ld	r4,STACKFRAMESIZE+56(r1)
+	ld	r5,STACKFRAMESIZE+64(r1)
+	mtlr	r0
+
+	/*
+	 * We prefetch both the source and destination using enhanced touch
+	 * instructions. We use a stream ID of 0 for the load side and
+	 * 1 for the store side.
+	 */
+	clrrdi	r6,r4,7
+	clrrdi	r9,r3,7
+	ori	r9,r9,1		/* stream=1 */
+
+	srdi	r7,r5,7		/* length in cachelines, capped at 0x3FF */
+	cmpldi	cr1,r7,0x3FF
+	ble	cr1,1f
+	li	r7,0x3FF
+1:	lis	r0,0x0E00	/* depth=7 */
+	sldi	r7,r7,7
+	or	r7,r7,r0
+	ori	r10,r7,1	/* stream=1 */
+
+	lis	r8,0x8000	/* GO=1 */
+	clrldi	r8,r8,32
+
+.machine push
+.machine "power4"
+	dcbt	r0,r6,0b01000
+	dcbt	r0,r7,0b01010
+	dcbtst	r0,r9,0b01000
+	dcbtst	r0,r10,0b01010
+	eieio
+	dcbt	r0,r8,0b01010	/* GO */
+.machine pop
+
+	beq	.Lunwind_stack_nonvmx_copy
+
+	/*
+	 * If source and destination are not relatively aligned we use a
+	 * slower permute loop.
+	 */
+	xor	r6,r4,r3
+	rldicl.	r6,r6,0,(64-4)
+	bne	.Lvmx_unaligned_copy
+
+	/* Get the destination 16B aligned */
+	neg	r6,r3
+	mtocrf	0x01,r6
+	clrldi	r6,r6,(64-4)
+
+	bf	cr7*4+3,1f
+	lbz	r0,0(r4)
+	addi	r4,r4,1
+	stb	r0,0(r3)
+	addi	r3,r3,1
+
+1:	bf	cr7*4+2,2f
+	lhz	r0,0(r4)
+	addi	r4,r4,2
+	sth	r0,0(r3)
+	addi	r3,r3,2
+
+2:	bf	cr7*4+1,3f
+	lwz	r0,0(r4)
+	addi	r4,r4,4
+	stw	r0,0(r3)
+	addi	r3,r3,4
+
+3:	bf	cr7*4+0,4f
+	ld	r0,0(r4)
+	addi	r4,r4,8
+	std	r0,0(r3)
+	addi	r3,r3,8
+
+4:	sub	r5,r5,r6
+
+	/* Get the desination 128B aligned */
+	neg	r6,r3
+	srdi	r7,r6,4
+	mtocrf	0x01,r7
+	clrldi	r6,r6,(64-7)
+
+	li	r9,16
+	li	r10,32
+	li	r11,48
+
+	bf	cr7*4+3,5f
+	lvx	vr1,r0,r4
+	addi	r4,r4,16
+	stvx	vr1,r0,r3
+	addi	r3,r3,16
+
+5:	bf	cr7*4+2,6f
+	lvx	vr1,r0,r4
+	lvx	vr0,r4,r9
+	addi	r4,r4,32
+	stvx	vr1,r0,r3
+	stvx	vr0,r3,r9
+	addi	r3,r3,32
+
+6:	bf	cr7*4+1,7f
+	lvx	vr3,r0,r4
+	lvx	vr2,r4,r9
+	lvx	vr1,r4,r10
+	lvx	vr0,r4,r11
+	addi	r4,r4,64
+	stvx	vr3,r0,r3
+	stvx	vr2,r3,r9
+	stvx	vr1,r3,r10
+	stvx	vr0,r3,r11
+	addi	r3,r3,64
+
+7:	sub	r5,r5,r6
+	srdi	r6,r5,7
+
+	std	r14,STK_REG(r14)(r1)
+	std	r15,STK_REG(r15)(r1)
+	std	r16,STK_REG(r16)(r1)
+
+	li	r12,64
+	li	r14,80
+	li	r15,96
+	li	r16,112
+
+	mtctr	r6
+
+	/*
+	 * Now do cacheline sized loads and stores. By this stage the
+	 * cacheline stores are also cacheline aligned.
+	 */
+	.align	5
+8:
+	lvx	vr7,r0,r4
+	lvx	vr6,r4,r9
+	lvx	vr5,r4,r10
+	lvx	vr4,r4,r11
+	lvx	vr3,r4,r12
+	lvx	vr2,r4,r14
+	lvx	vr1,r4,r15
+	lvx	vr0,r4,r16
+	addi	r4,r4,128
+	stvx	vr7,r0,r3
+	stvx	vr6,r3,r9
+	stvx	vr5,r3,r10
+	stvx	vr4,r3,r11
+	stvx	vr3,r3,r12
+	stvx	vr2,r3,r14
+	stvx	vr1,r3,r15
+	stvx	vr0,r3,r16
+	addi	r3,r3,128
+	bdnz	8b
+
+	ld	r14,STK_REG(r14)(r1)
+	ld	r15,STK_REG(r15)(r1)
+	ld	r16,STK_REG(r16)(r1)
+
+	/* Up to 127B to go */
+	clrldi	r5,r5,(64-7)
+	srdi	r6,r5,4
+	mtocrf	0x01,r6
+
+	bf	cr7*4+1,9f
+	lvx	vr3,r0,r4
+	lvx	vr2,r4,r9
+	lvx	vr1,r4,r10
+	lvx	vr0,r4,r11
+	addi	r4,r4,64
+	stvx	vr3,r0,r3
+	stvx	vr2,r3,r9
+	stvx	vr1,r3,r10
+	stvx	vr0,r3,r11
+	addi	r3,r3,64
+
+9:	bf	cr7*4+2,10f
+	lvx	vr1,r0,r4
+	lvx	vr0,r4,r9
+	addi	r4,r4,32
+	stvx	vr1,r0,r3
+	stvx	vr0,r3,r9
+	addi	r3,r3,32
+
+10:	bf	cr7*4+3,11f
+	lvx	vr1,r0,r4
+	addi	r4,r4,16
+	stvx	vr1,r0,r3
+	addi	r3,r3,16
+
+	/* Up to 15B to go */
+11:	clrldi	r5,r5,(64-4)
+	mtocrf	0x01,r5
+	bf	cr7*4+0,12f
+	ld	r0,0(r4)
+	addi	r4,r4,8
+	std	r0,0(r3)
+	addi	r3,r3,8
+
+12:	bf	cr7*4+1,13f
+	lwz	r0,0(r4)
+	addi	r4,r4,4
+	stw	r0,0(r3)
+	addi	r3,r3,4
+
+13:	bf	cr7*4+2,14f
+	lhz	r0,0(r4)
+	addi	r4,r4,2
+	sth	r0,0(r3)
+	addi	r3,r3,2
+
+14:	bf	cr7*4+3,15f
+	lbz	r0,0(r4)
+	stb	r0,0(r3)
+
+15:	addi	r1,r1,STACKFRAMESIZE
+	ld	r3,48(r1)
+	b	.exit_vmx_copy		/* tail call optimise */
+
+.Lvmx_unaligned_copy:
+	/* Get the destination 16B aligned */
+	neg	r6,r3
+	mtocrf	0x01,r6
+	clrldi	r6,r6,(64-4)
+
+	bf	cr7*4+3,1f
+	lbz	r0,0(r4)
+	addi	r4,r4,1
+	stb	r0,0(r3)
+	addi	r3,r3,1
+
+1:	bf	cr7*4+2,2f
+	lhz	r0,0(r4)
+	addi	r4,r4,2
+	sth	r0,0(r3)
+	addi	r3,r3,2
+
+2:	bf	cr7*4+1,3f
+	lwz	r0,0(r4)
+	addi	r4,r4,4
+	stw	r0,0(r3)
+	addi	r3,r3,4
+
+3:	bf	cr7*4+0,4f
+	lwz	r0,0(r4)	/* Less chance of a reject with word ops */
+	lwz	r7,4(r4)
+	addi	r4,r4,8
+	stw	r0,0(r3)
+	stw	r7,4(r3)
+	addi	r3,r3,8
+
+4:	sub	r5,r5,r6
+
+	/* Get the desination 128B aligned */
+	neg	r6,r3
+	srdi	r7,r6,4
+	mtocrf	0x01,r7
+	clrldi	r6,r6,(64-7)
+
+	li	r9,16
+	li	r10,32
+	li	r11,48
+
+	lvsl	vr16,0,r4	/* Setup permute control vector */
+	lvx	vr0,0,r4
+	addi	r4,r4,16
+
+	bf	cr7*4+3,5f
+	lvx	vr1,r0,r4
+	vperm	vr8,vr0,vr1,vr16
+	addi	r4,r4,16
+	stvx	vr8,r0,r3
+	addi	r3,r3,16
+	vor	vr0,vr1,vr1
+
+5:	bf	cr7*4+2,6f
+	lvx	vr1,r0,r4
+	vperm	vr8,vr0,vr1,vr16
+	lvx	vr0,r4,r9
+	vperm	vr9,vr1,vr0,vr16
+	addi	r4,r4,32
+	stvx	vr8,r0,r3
+	stvx	vr9,r3,r9
+	addi	r3,r3,32
+
+6:	bf	cr7*4+1,7f
+	lvx	vr3,r0,r4
+	vperm	vr8,vr0,vr3,vr16
+	lvx	vr2,r4,r9
+	vperm	vr9,vr3,vr2,vr16
+	lvx	vr1,r4,r10
+	vperm	vr10,vr2,vr1,vr16
+	lvx	vr0,r4,r11
+	vperm	vr11,vr1,vr0,vr16
+	addi	r4,r4,64
+	stvx	vr8,r0,r3
+	stvx	vr9,r3,r9
+	stvx	vr10,r3,r10
+	stvx	vr11,r3,r11
+	addi	r3,r3,64
+
+7:	sub	r5,r5,r6
+	srdi	r6,r5,7
+
+	std	r14,STK_REG(r14)(r1)
+	std	r15,STK_REG(r15)(r1)
+	std	r16,STK_REG(r16)(r1)
+
+	li	r12,64
+	li	r14,80
+	li	r15,96
+	li	r16,112
+
+	mtctr	r6
+
+	/*
+	 * Now do cacheline sized loads and stores. By this stage the
+	 * cacheline stores are also cacheline aligned.
+	 */
+	.align	5
+8:
+	lvx	vr7,r0,r4
+	vperm	vr8,vr0,vr7,vr16
+	lvx	vr6,r4,r9
+	vperm	vr9,vr7,vr6,vr16
+	lvx	vr5,r4,r10
+	vperm	vr10,vr6,vr5,vr16
+	lvx	vr4,r4,r11
+	vperm	vr11,vr5,vr4,vr16
+	lvx	vr3,r4,r12
+	vperm	vr12,vr4,vr3,vr16
+	lvx	vr2,r4,r14
+	vperm	vr13,vr3,vr2,vr16
+	lvx	vr1,r4,r15
+	vperm	vr14,vr2,vr1,vr16
+	lvx	vr0,r4,r16
+	vperm	vr15,vr1,vr0,vr16
+	addi	r4,r4,128
+	stvx	vr8,r0,r3
+	stvx	vr9,r3,r9
+	stvx	vr10,r3,r10
+	stvx	vr11,r3,r11
+	stvx	vr12,r3,r12
+	stvx	vr13,r3,r14
+	stvx	vr14,r3,r15
+	stvx	vr15,r3,r16
+	addi	r3,r3,128
+	bdnz	8b
+
+	ld	r14,STK_REG(r14)(r1)
+	ld	r15,STK_REG(r15)(r1)
+	ld	r16,STK_REG(r16)(r1)
+
+	/* Up to 127B to go */
+	clrldi	r5,r5,(64-7)
+	srdi	r6,r5,4
+	mtocrf	0x01,r6
+
+	bf	cr7*4+1,9f
+	lvx	vr3,r0,r4
+	vperm	vr8,vr0,vr3,vr16
+	lvx	vr2,r4,r9
+	vperm	vr9,vr3,vr2,vr16
+	lvx	vr1,r4,r10
+	vperm	vr10,vr2,vr1,vr16
+	lvx	vr0,r4,r11
+	vperm	vr11,vr1,vr0,vr16
+	addi	r4,r4,64
+	stvx	vr8,r0,r3
+	stvx	vr9,r3,r9
+	stvx	vr10,r3,r10
+	stvx	vr11,r3,r11
+	addi	r3,r3,64
+
+9:	bf	cr7*4+2,10f
+	lvx	vr1,r0,r4
+	vperm	vr8,vr0,vr1,vr16
+	lvx	vr0,r4,r9
+	vperm	vr9,vr1,vr0,vr16
+	addi	r4,r4,32
+	stvx	vr8,r0,r3
+	stvx	vr9,r3,r9
+	addi	r3,r3,32
+
+10:	bf	cr7*4+3,11f
+	lvx	vr1,r0,r4
+	vperm	vr8,vr0,vr1,vr16
+	addi	r4,r4,16
+	stvx	vr8,r0,r3
+	addi	r3,r3,16
+
+	/* Up to 15B to go */
+11:	clrldi	r5,r5,(64-4)
+	addi	r4,r4,-16	/* Unwind the +16 load offset */
+	mtocrf	0x01,r5
+	bf	cr7*4+0,12f
+	lwz	r0,0(r4)	/* Less chance of a reject with word ops */
+	lwz	r6,4(r4)
+	addi	r4,r4,8
+	stw	r0,0(r3)
+	stw	r6,4(r3)
+	addi	r3,r3,8
+
+12:	bf	cr7*4+1,13f
+	lwz	r0,0(r4)
+	addi	r4,r4,4
+	stw	r0,0(r3)
+	addi	r3,r3,4
+
+13:	bf	cr7*4+2,14f
+	lhz	r0,0(r4)
+	addi	r4,r4,2
+	sth	r0,0(r3)
+	addi	r3,r3,2
+
+14:	bf	cr7*4+3,15f
+	lbz	r0,0(r4)
+	stb	r0,0(r3)
+
+15:	addi	r1,r1,STACKFRAMESIZE
+	ld	r3,48(r1)
+	b	.exit_vmx_copy		/* tail call optimise */
+#endif /* CONFiG_ALTIVEC */

^ permalink raw reply

* RE: kernel panic during kernel module load (powerpc specific part)
From: Wrobel Heinz-R39252 @ 2012-05-31  7:04 UTC (permalink / raw)
  To: Michael Ellerman, Steffen Rumler; +Cc: linuxppc-dev@lists.ozlabs.org
In-Reply-To: <1338420242.27402.2.camel@concordia>

Michael,

> On Wed, 2012-05-30 at 16:33 +0200, Steffen Rumler wrote:
> > I've found the following root cause:
> >
> >      (6) Unfortunately, the trampoline code (do_plt_call()) is using
> register r11 to setup the jump.
> >            It looks like the prologue and epilogue are using also the
> register r11, in order to point to the previous stack frame.
> >            This is a conflict !!! The trampoline code is damaging the
> content of r11.
>=20
> Hi Steffen,
>=20
> Great bug report!
>=20
> I can't quite work out what the standards say, the versions I'm looking
> at are probably old anyway.

The ABI supplement from https://www.power.org/resources/downloads/ is expli=
cit about r11 being a requirement for the statically lined save/restore fun=
ctions in section 3.3.4 on page 59.

This means that any trampoline code must not ever use r11 or it can't be us=
ed to get to such save/restore functions safely from far away.

Unfortunately the same doc and predecessors show r11 in all basic examples =
for PLT/trampoline code AFAICS, which is likely why all trampoline code use=
s r11 in any known case.

I would guess that it was never envisioned that compiler generated code wou=
ld be in a different section than save/restore functions, i.e., the Linux m=
odule "__init" assumptions for Power break the ABI. Or does the ABI break t=
he __init concept?!

Using r12 in the trampoline seems to be the obvious solution for module loa=
ding.

But what about other code loading done? If, e.g., a user runs any app from =
bash it gets loaded and relocated and trampolines might get set up somehow.

Wouldn't we have to find fix ANY trampoline code generator remotely related=
 to a basic Power Architecture Linux?
Or is it a basic assumption for anything but modules that compiler generate=
d code may never ever be outside the .text section? I am not sure that woul=
d be a safe assumption.

Isn't this problem going beyond just module loading for Power Architecture =
Linux?

Regards,

Heinz

^ permalink raw reply

* [PATCH 1/2] edac: Use ccsr_pci structure instead of hardcoded define
From: Chunhe Lan @ 2012-06-01  8:16 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Doug Thompson, Chunhe Lan

There are some differences of register offset and definition between
pci and pcie error management registers. While, some other pci/pcie
error management registers are nearly the same.

To merge pci and pcie edac code into one, it is easier to use ccsr_pci
structure than the hardcoded define. So remove the hardcoded define and
add pci/pcie error management register in ccsr_pci structure.

Signed-off-by: Chunhe Lan <Chunhe.Lan@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Doug Thompson <dougthompson@xmission.com>
---
 arch/powerpc/sysdev/fsl_pci.h |   46 +++++++++++++++++++++++++++++++++-------
 drivers/edac/mpc85xx_edac.h   |   13 +---------
 2 files changed, 40 insertions(+), 19 deletions(-)

diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
index a39ed5c..5378a47 100644
--- a/arch/powerpc/sysdev/fsl_pci.h
+++ b/arch/powerpc/sysdev/fsl_pci.h
@@ -1,7 +1,7 @@
 /*
  * MPC85xx/86xx PCI Express structure define
  *
- * Copyright 2007,2011 Freescale Semiconductor, Inc
+ * Copyright 2007,2011,2012 Freescale Semiconductor, Inc
  *
  * 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
@@ -14,6 +14,8 @@
 #ifndef __POWERPC_FSL_PCI_H
 #define __POWERPC_FSL_PCI_H
 
+#include <asm/pci-bridge.h>
+
 #define PCIE_LTSSM	0x0404		/* PCIE Link Training and Status */
 #define PCIE_LTSSM_L0	0x16		/* L0 state */
 #define PIWAR_EN		0x80000000	/* Enable */
@@ -74,13 +76,41 @@ struct ccsr_pci {
  */
 	struct pci_inbound_window_regs piw[4];
 
-	__be32	pex_err_dr;		/* 0x.e00 - PCI/PCIE error detect register */
-	u8	res21[4];
-	__be32	pex_err_en;		/* 0x.e08 - PCI/PCIE error interrupt enable register */
-	u8	res22[4];
-	__be32	pex_err_disr;		/* 0x.e10 - PCI/PCIE error disable register */
-	u8	res23[12];
-	__be32	pex_err_cap_stat;	/* 0x.e20 - PCI/PCIE error capture status register */
+/* Merge PCI Express/PCI error management registers */
+	__be32	pex_err_dr;	  /* 0x.e00
+				   * - PCI/PCIE error detect register
+				   */
+	__be32	pex_err_cap_dr;	  /* 0x.e04
+				   * - PCI error capture disabled register
+				   * - PCIE has no this register
+				   */
+	__be32	pex_err_en;	  /* 0x.e08
+				   * - PCI/PCIE error interrupt enable register
+				   */
+	__be32	pex_err_attrib;	  /* 0x.e0c
+				   * - PCI error attributes capture register
+				   * - PCIE has no this register
+				   */
+	__be32	pex_err_disr;	  /* 0x.e10
+				   * - PCI error address capture register
+				   * - PCIE error disable register
+				   */
+	__be32	pex_err_ext_addr; /* 0x.e14
+				   * - PCI error extended addr capture register
+				   * - PCIE has no this register
+				   */
+	__be32	pex_err_dl;	  /* 0x.e18
+				   * - PCI error data low capture register
+				   * - PCIE has no this register
+				   */
+	__be32	pex_err_dh;	  /* 0x.e1c
+				   * - PCI error data high capture register
+				   * - PCIE has no this register
+				   */
+	__be32	pex_err_cap_stat; /* 0x.e20
+				   * - PCI gasket timer register
+				   * - PCIE error capture status register
+				   */
 	u8	res24[4];
 	__be32	pex_err_cap_r0;		/* 0x.e28 - PCIE error capture register 0 */
 	__be32	pex_err_cap_r1;		/* 0x.e2c - PCIE error capture register 0 */
diff --git a/drivers/edac/mpc85xx_edac.h b/drivers/edac/mpc85xx_edac.h
index 932016f..8ba4152 100644
--- a/drivers/edac/mpc85xx_edac.h
+++ b/drivers/edac/mpc85xx_edac.h
@@ -1,5 +1,7 @@
 /*
  * Freescale MPC85xx Memory Controller kenel module
+ * Copyright (c) 2012 Freescale Semiconductor, Inc.
+ *
  * Author: Dave Jiang <djiang@mvista.com>
  *
  * 2006-2007 (c) MontaVista Software, Inc. This file is licensed under
@@ -131,17 +133,6 @@
 #define PCI_EDE_PERR_MASK	(PCI_EDE_TGT_PERR | PCI_EDE_MST_PERR | \
 				PCI_EDE_ADDR_PERR)
 
-#define MPC85XX_PCI_ERR_DR		0x0000
-#define MPC85XX_PCI_ERR_CAP_DR		0x0004
-#define MPC85XX_PCI_ERR_EN		0x0008
-#define MPC85XX_PCI_ERR_ATTRIB		0x000c
-#define MPC85XX_PCI_ERR_ADDR		0x0010
-#define MPC85XX_PCI_ERR_EXT_ADDR	0x0014
-#define MPC85XX_PCI_ERR_DL		0x0018
-#define MPC85XX_PCI_ERR_DH		0x001c
-#define MPC85XX_PCI_GAS_TIMR		0x0020
-#define MPC85XX_PCI_PCIX_TIMR		0x0024
-
 struct mpc85xx_mc_pdata {
 	char *name;
 	int edac_idx;
-- 
1.5.6.5

^ permalink raw reply related

* [PATCH 2/2] edac/85xx: PCI/PCIe error interrupt edac support
From: Chunhe Lan @ 2012-06-01  8:16 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Doug Thompson, Chunhe Lan
In-Reply-To: <1338538618-26939-1-git-send-email-Chunhe.Lan@freescale.com>

Adding pcie error interrupt edac support for mpc85xx and p4080.
mpc85xx uses the legacy interrupt report mechanism - the error
interrupts are reported directly to mpic. While, p4080 attaches
the most of error interrupts to interrupt 0. And report error
interrupts to mpic via interrupt 0. This patch can handle both
of them.

Signed-off-by: Chunhe Lan <Chunhe.Lan@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Doug Thompson <dougthompson@xmission.com>
---
 drivers/edac/mpc85xx_edac.c |  236 +++++++++++++++++++++++++++++++++----------
 drivers/edac/mpc85xx_edac.h |    9 ++-
 2 files changed, 191 insertions(+), 54 deletions(-)

diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index 73464a6..35eef79 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -1,5 +1,6 @@
 /*
  * Freescale MPC85xx Memory Controller kenel module
+ * Copyright (c) 2012 Freescale Semiconductor, Inc.
  *
  * Author: Dave Jiang <djiang@mvista.com>
  *
@@ -21,6 +22,7 @@
 
 #include <linux/of_platform.h>
 #include <linux/of_device.h>
+#include <sysdev/fsl_pci.h>
 #include "edac_module.h"
 #include "edac_core.h"
 #include "mpc85xx_edac.h"
@@ -37,11 +39,6 @@ static u32 orig_ddr_err_sbe;
 /*
  * PCI Err defines
  */
-#ifdef CONFIG_PCI
-static u32 orig_pci_err_cap_dr;
-static u32 orig_pci_err_en;
-#endif
-
 static u32 orig_l2_err_disable;
 #ifdef CONFIG_FSL_SOC_BOOKE
 static u32 orig_hid1[2];
@@ -151,37 +148,52 @@ static void mpc85xx_pci_check(struct edac_pci_ctl_info *pci)
 {
 	struct mpc85xx_pci_pdata *pdata = pci->pvt_info;
 	u32 err_detect;
+	struct ccsr_pci *reg = pdata->pci_reg;
+
+	err_detect = in_be32(&pdata->pci_reg->pex_err_dr);
+
+	if (pdata->pcie_flag) {
+		printk(KERN_ERR "PCIE error(s) detected\n");
+		printk(KERN_ERR "PCIE ERR_DR register: 0x%08x\n", err_detect);
+		printk(KERN_ERR "PCIE ERR_CAP_STAT register: 0x%08x\n",
+				in_be32(&reg->pex_err_cap_stat));
+		printk(KERN_ERR "PCIE ERR_CAP_R0 register: 0x%08x\n",
+				in_be32(&reg->pex_err_cap_r0));
+		printk(KERN_ERR "PCIE ERR_CAP_R1 register: 0x%08x\n",
+				in_be32(&reg->pex_err_cap_r1));
+		printk(KERN_ERR "PCIE ERR_CAP_R2 register: 0x%08x\n",
+				in_be32(&reg->pex_err_cap_r2));
+		printk(KERN_ERR "PCIE ERR_CAP_R3 register: 0x%08x\n",
+				in_be32(&reg->pex_err_cap_r3));
+	} else {
+		/* master aborts can happen during PCI config cycles */
+		if (!(err_detect & ~(PCI_EDE_MULTI_ERR | PCI_EDE_MST_ABRT))) {
+			out_be32(&reg->pex_err_dr, err_detect);
+			return;
+		}
 
-	err_detect = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR);
-
-	/* master aborts can happen during PCI config cycles */
-	if (!(err_detect & ~(PCI_EDE_MULTI_ERR | PCI_EDE_MST_ABRT))) {
-		out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, err_detect);
-		return;
+		printk(KERN_ERR "PCI error(s) detected\n");
+		printk(KERN_ERR "PCI/X ERR_DR register: 0x%08x\n", err_detect);
+		printk(KERN_ERR "PCI/X ERR_ATTRIB register: 0x%08x\n",
+				in_be32(&reg->pex_err_attrib));
+		printk(KERN_ERR "PCI/X ERR_ADDR register: 0x%08x\n",
+				in_be32(&reg->pex_err_disr));
+		printk(KERN_ERR "PCI/X ERR_EXT_ADDR register: 0x%08x\n",
+				in_be32(&reg->pex_err_ext_addr));
+		printk(KERN_ERR "PCI/X ERR_DL register: 0x%08x\n",
+				in_be32(&reg->pex_err_dl));
+		printk(KERN_ERR "PCI/X ERR_DH register: 0x%08x\n",
+				in_be32(&reg->pex_err_dh));
+
+		if (err_detect & PCI_EDE_PERR_MASK)
+			edac_pci_handle_pe(pci, pci->ctl_name);
+
+		if (err_detect & ~(PCI_EDE_MULTI_ERR | PCI_EDE_PERR_MASK))
+			edac_pci_handle_npe(pci, pci->ctl_name);
 	}
 
-	printk(KERN_ERR "PCI error(s) detected\n");
-	printk(KERN_ERR "PCI/X ERR_DR register: %#08x\n", err_detect);
-
-	printk(KERN_ERR "PCI/X ERR_ATTRIB register: %#08x\n",
-	       in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ATTRIB));
-	printk(KERN_ERR "PCI/X ERR_ADDR register: %#08x\n",
-	       in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR));
-	printk(KERN_ERR "PCI/X ERR_EXT_ADDR register: %#08x\n",
-	       in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EXT_ADDR));
-	printk(KERN_ERR "PCI/X ERR_DL register: %#08x\n",
-	       in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DL));
-	printk(KERN_ERR "PCI/X ERR_DH register: %#08x\n",
-	       in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DH));
-
 	/* clear error bits */
-	out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, err_detect);
-
-	if (err_detect & PCI_EDE_PERR_MASK)
-		edac_pci_handle_pe(pci, pci->ctl_name);
-
-	if ((err_detect & ~PCI_EDE_MULTI_ERR) & ~PCI_EDE_PERR_MASK)
-		edac_pci_handle_npe(pci, pci->ctl_name);
+	out_be32(&reg->pex_err_dr, err_detect);
 }
 
 static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id)
@@ -190,7 +202,7 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id)
 	struct mpc85xx_pci_pdata *pdata = pci->pvt_info;
 	u32 err_detect;
 
-	err_detect = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR);
+	err_detect = in_be32(&pdata->pci_reg->pex_err_dr);
 
 	if (!err_detect)
 		return IRQ_NONE;
@@ -200,11 +212,104 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+/*
+ * This function is for error interrupt ORed mechanism.
+ * This mechanism attaches most functions' error interrupts to interrupt 0.
+ * And report error interrupt to mpic via interrupt 0.
+ * EIMR0 - Error Interrupt Mask Register 0.
+ *
+ * This function check whether the device support error interrupt ORed
+ * mechanism via device tree. If supported, umask pcie error interrupt
+ * bit in EIMR0.
+ */
+static int mpc85xx_err_int_en(struct platform_device *op)
+{
+	u32 *int_cell;
+	struct device_node *np;
+	void __iomem *mpic_base;
+	u32 reg_tmp;
+	u32 int_len;
+	struct resource r;
+	int res;
+
+	if (!op->dev.of_node)
+		return -EINVAL;
+
+	/*
+	 * Unmask pcie error interrupt bit in EIMR0.
+	 * Extend interrupt specifier has 4 cells.
+	 * For the 3rd cell:
+	 *	0 -- normal interrupt;
+	 *	1 -- error interrupt.
+	 */
+	int_cell = (u32 *)of_get_property(op->dev.of_node, "interrupts",
+								&int_len);
+	if ((int_len/sizeof(u32)) == 4) {
+		/* soc has error interrupt integration handling mechanism */
+		if (*(int_cell + 2) == 1) {
+			np = of_find_node_by_type(NULL, "open-pic");
+
+			if (of_address_to_resource(np, 0, &r)) {
+				printk(KERN_ERR "%s: Failed to map mpic regs\n",
+						__func__);
+				of_node_put(np);
+				res = -ENOMEM;
+				goto err;
+			}
+
+			if (!request_mem_region(r.start, r.end - r.start + 1,
+						"mpic")) {
+				printk(KERN_ERR
+				       "%s: Error when requesting mem region\n",
+				       __func__);
+				res = -EBUSY;
+				goto err;
+			}
+
+			mpic_base = ioremap(r.start, r.end - r.start + 1);
+			if (!mpic_base) {
+				printk(KERN_ERR "%s: Unable to map mpic regs\n",
+						__func__);
+				res = -ENOMEM;
+				goto err_ioremap;
+			}
+
+			reg_tmp = in_be32(mpic_base + MPC85XX_MPIC_EIMR0);
+			out_be32(mpic_base + MPC85XX_MPIC_EIMR0,
+				reg_tmp & ~(1 << (31 - *(int_cell + 3))));
+			iounmap(mpic_base);
+			release_mem_region(r.start, r.end - r.start + 1);
+			of_node_put(np);
+		}
+	}
+
+	return 0;
+
+err_ioremap:
+	release_mem_region(r.start, r.end - r.start + 1);
+err:
+	return res;
+}
+
+static int mpc85xx_pcie_find_capability(struct device_node *np)
+{
+	struct pci_controller *hose;
+
+	if (!np)
+		return -EINVAL;
+
+	hose = pci_find_hose_for_OF_device(np);
+
+	return early_find_capability(hose, hose->bus->number, 0,
+				     PCI_CAP_ID_EXP);
+}
+
 static int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
 {
 	struct edac_pci_ctl_info *pci;
 	struct mpc85xx_pci_pdata *pdata;
 	struct resource r;
+	struct ccsr_pci *reg;
 	int res = 0;
 
 	if (!devres_open_group(&op->dev, mpc85xx_pci_err_probe, GFP_KERNEL))
@@ -223,6 +328,9 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
 	pci->ctl_name = pdata->name;
 	pci->dev_name = dev_name(&op->dev);
 
+	if (mpc85xx_pcie_find_capability(op->dev.of_node) > 0)
+		pdata->pcie_flag = 1;
+
 	if (edac_op_state == EDAC_OPSTATE_POLL)
 		pci->edac_check = mpc85xx_pci_check;
 
@@ -234,10 +342,6 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
 		       "PCI err regs\n", __func__);
 		goto err;
 	}
-
-	/* we only need the error registers */
-	r.start += 0xe00;
-
 	if (!devm_request_mem_region(&op->dev, r.start, resource_size(&r),
 					pdata->name)) {
 		printk(KERN_ERR "%s: Error while requesting mem region\n",
@@ -246,26 +350,32 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
 		goto err;
 	}
 
-	pdata->pci_vbase = devm_ioremap(&op->dev, r.start, resource_size(&r));
-	if (!pdata->pci_vbase) {
+	pdata->pci_reg = devm_ioremap(&op->dev, r.start, resource_size(&r));
+	if (!pdata->pci_reg) {
 		printk(KERN_ERR "%s: Unable to setup PCI err regs\n", __func__);
 		res = -ENOMEM;
 		goto err;
 	}
 
-	orig_pci_err_cap_dr =
-	    in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR);
-
-	/* PCI master abort is expected during config cycles */
-	out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR, 0x40);
+	if (mpc85xx_err_int_en(op) < 0)
+		goto err;
 
-	orig_pci_err_en = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN);
+	reg = pdata->pci_reg;
+	/* disable pci/pcie error detect */
+	if (pdata->pcie_flag) {
+		pdata->orig_pci_err_dr =  in_be32(&reg->pex_err_disr);
+		out_be32(&reg->pex_err_disr, ~0);
+	} else {
+		pdata->orig_pci_err_dr =  in_be32(&reg->pex_err_cap_dr);
+		out_be32(&reg->pex_err_cap_dr, ~0);
+	}
 
-	/* disable master abort reporting */
-	out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, ~0x40);
+	/* disable all pcie error interrupt */
+	pdata->orig_pci_err_en = in_be32(&reg->pex_err_en);
+	out_be32(&reg->pex_err_en, 0);
 
-	/* clear error bits */
-	out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, ~0);
+	/* clear all error bits */
+	out_be32(&reg->pex_err_dr, ~0);
 
 	if (edac_pci_add_device(pci, pdata->edac_idx) > 0) {
 		debugf3("%s(): failed edac_pci_add_device()\n", __func__);
@@ -275,7 +385,7 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
 	if (edac_op_state == EDAC_OPSTATE_INT) {
 		pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
 		res = devm_request_irq(&op->dev, pdata->irq,
-				       mpc85xx_pci_isr, IRQF_DISABLED,
+				       mpc85xx_pci_isr, IRQF_SHARED,
 				       "[EDAC] PCI err", pci);
 		if (res < 0) {
 			printk(KERN_ERR
@@ -290,6 +400,17 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
 		       pdata->irq);
 	}
 
+	if (pdata->pcie_flag) {
+		/* enable all pcie error interrupt & error detect */
+		out_be32(&reg->pex_err_en, ~0);
+		out_be32(&reg->pex_err_disr, 0);
+	} else {
+		/* PCI master abort is expected during config cycles */
+		out_be32(&reg->pex_err_cap_dr, PCI_ERR_CAP_DR_DIS_MST);
+		/* disable master abort reporting */
+		out_be32(&reg->pex_err_en, PCI_ERR_EN_DIS_MST);
+	}
+
 	devres_remove_group(&op->dev, mpc85xx_pci_err_probe);
 	debugf3("%s(): success\n", __func__);
 	printk(KERN_INFO EDAC_MOD_STR " PCI err registered\n");
@@ -311,10 +432,13 @@ static int mpc85xx_pci_err_remove(struct platform_device *op)
 
 	debugf0("%s()\n", __func__);
 
-	out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR,
-		 orig_pci_err_cap_dr);
+	if (pdata->pcie_flag)
+		out_be32(&pdata->pci_reg->pex_err_disr, pdata->orig_pci_err_dr);
+	else
+		out_be32(&pdata->pci_reg->pex_err_cap_dr,
+						pdata->orig_pci_err_dr);
 
-	out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, orig_pci_err_en);
+	out_be32(&pdata->pci_reg->pex_err_en, pdata->orig_pci_err_en);
 
 	edac_pci_del_device(pci->dev);
 
@@ -333,6 +457,12 @@ static struct of_device_id mpc85xx_pci_err_of_match[] = {
 	{
 	 .compatible = "fsl,mpc8540-pci",
 	},
+	{
+	.compatible = "fsl,mpc8548-pcie",
+	},
+	{
+	 .compatible = "fsl,p4080-pcie",
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, mpc85xx_pci_err_of_match);
diff --git a/drivers/edac/mpc85xx_edac.h b/drivers/edac/mpc85xx_edac.h
index 8ba4152..262004d 100644
--- a/drivers/edac/mpc85xx_edac.h
+++ b/drivers/edac/mpc85xx_edac.h
@@ -133,6 +133,10 @@
 #define PCI_EDE_PERR_MASK	(PCI_EDE_TGT_PERR | PCI_EDE_MST_PERR | \
 				PCI_EDE_ADDR_PERR)
 
+#define PCI_ERR_CAP_DR_DIS_MST		0x40
+#define PCI_ERR_EN_DIS_MST		(~PCI_ERR_CAP_DR_DIS_MST)
+#define MPC85XX_MPIC_EIMR0		0x3910
+
 struct mpc85xx_mc_pdata {
 	char *name;
 	int edac_idx;
@@ -149,8 +153,11 @@ struct mpc85xx_l2_pdata {
 
 struct mpc85xx_pci_pdata {
 	char *name;
+	u8 pcie_flag;
 	int edac_idx;
-	void __iomem *pci_vbase;
+	struct ccsr_pci *pci_reg;
+	u32 orig_pci_err_dr;
+	u32 orig_pci_err_en;
 	int irq;
 };
 
-- 
1.5.6.5

^ permalink raw reply related

* Re: Re[2]: [RFC] [PATCH] powerpc: Add MSR_DE to MSR_KERNEL
From: Joakim Tjernlund @ 2012-05-31  9:05 UTC (permalink / raw)
  To: Support; +Cc: linuxppc-dev, Dan Malek, Bob Cochran
In-Reply-To: <10126984030.20120530140826@abatron.ch>

Abatron Support <support@abatron.ch> wrote on 2012/05/30 14:08:26:
>
> >> I have tested this briefly with BDI2000 on P2010(e500) and
> >> it works for me. I don't know if there are any bad side effects,
> >> therfore
> >> this RFC.
>
> > We used to have MSR_DE surrounded by CONFIG_something
> > to ensure it wasn't set under normal operation.  IIRC, if MSR_DE
> > is set, you will have problems with software debuggers that
> > utilize the the debugging registers in the chip itself.  You only want
> > to force this to be set when using the BDI, not at other times.
>
> This MSR_DE is also of interest and used for software debuggers that
> make use of the debug registers. Only if MSR_DE is set then debug
> interrupts are generated. If a debug event leads to a debug interrupt
> handled by a software debugger or if it leads to a debug halt handled
> by a JTAG tool is selected with DBCR0_EDM / DBCR0_IDM.
>
> The "e500 Core Family Reference Manual" chapter "Chapter 8
> Debug Support" explains in detail the effect of MSR_DE.

So what is the verdict on this? I don't buy into Dan argument without some
hard data.

 Jocke

^ permalink raw reply

* Re[4]: [RFC] [PATCH] powerpc: Add MSR_DE to MSR_KERNEL
From: Abatron Support @ 2012-05-31  9:30 UTC (permalink / raw)
  To: Joakim Tjernlund; +Cc: linuxppc-dev, Dan Malek, Bob Cochran
In-Reply-To: <OF53CDE18C.59DD377E-ONC1257A0F.0031C7A0-C1257A0F.0031EA81@transmode.se>


> Abatron Support <support@abatron.ch> wrote on 2012/05/30 14:08:26:
>>
>> >> I have tested this briefly with BDI2000 on P2010(e500) and
>> >> it works for me. I don't know if there are any bad side effects,
>> >> therfore
>> >> this RFC.
>>
>> > We used to have MSR_DE surrounded by CONFIG_something
>> > to ensure it wasn't set under normal operation.  IIRC, if MSR_DE
>> > is set, you will have problems with software debuggers that
>> > utilize the the debugging registers in the chip itself.  You only want
>> > to force this to be set when using the BDI, not at other times.
>>
>> This MSR_DE is also of interest and used for software debuggers that
>> make use of the debug registers. Only if MSR_DE is set then debug
>> interrupts are generated. If a debug event leads to a debug interrupt
>> handled by a software debugger or if it leads to a debug halt handled
>> by a JTAG tool is selected with DBCR0_EDM / DBCR0_IDM.
>>
>> The "e500 Core Family Reference Manual" chapter "Chapter 8
>> Debug Support" explains in detail the effect of MSR_DE.

> So what is the verdict on this? I don't buy into Dan argument without some
> hard data.

What I tried to mention is that handling the MSR_DE correct is not only
an emulator (JTAG debugger) requirement. Also a software debugger may
depend on a correct handled MSR_DE bit.

Ruedi

^ permalink raw reply

* Re: Re[4]: [RFC] [PATCH] powerpc: Add MSR_DE to MSR_KERNEL
From: Joakim Tjernlund @ 2012-05-31  9:56 UTC (permalink / raw)
  To: Support; +Cc: linuxppc-dev, Dan Malek, Bob Cochran
In-Reply-To: <13517672561.20120531113057@abatron.ch>

Abatron Support <support@abatron.ch> wrote on 2012/05/31 11:30:57:
>
>
> > Abatron Support <support@abatron.ch> wrote on 2012/05/30 14:08:26:
> >>
> >> >> I have tested this briefly with BDI2000 on P2010(e500) and
> >> >> it works for me. I don't know if there are any bad side effects,
> >> >> therfore
> >> >> this RFC.
> >>
> >> > We used to have MSR_DE surrounded by CONFIG_something
> >> > to ensure it wasn't set under normal operation.  IIRC, if MSR_DE
> >> > is set, you will have problems with software debuggers that
> >> > utilize the the debugging registers in the chip itself.  You only want
> >> > to force this to be set when using the BDI, not at other times.
> >>
> >> This MSR_DE is also of interest and used for software debuggers that
> >> make use of the debug registers. Only if MSR_DE is set then debug
> >> interrupts are generated. If a debug event leads to a debug interrupt
> >> handled by a software debugger or if it leads to a debug halt handled
> >> by a JTAG tool is selected with DBCR0_EDM / DBCR0_IDM.
> >>
> >> The "e500 Core Family Reference Manual" chapter "Chapter 8
> >> Debug Support" explains in detail the effect of MSR_DE.
>
> > So what is the verdict on this? I don't buy into Dan argument without some
> > hard data.
>
> What I tried to mention is that handling the MSR_DE correct is not only
> an emulator (JTAG debugger) requirement. Also a software debugger may
> depend on a correct handled MSR_DE bit.

Yes, that made sense to me too. How would SW debuggers work if the kernel keeps
turning off MSR_DE first chance it gets?

 Jocke

^ permalink raw reply

* Re: kernel panic during kernel module load (powerpc specific part)
From: Gabriel Paubert @ 2012-05-31 11:04 UTC (permalink / raw)
  To: Wrobel Heinz-R39252
  Cc: Michael Ellerman, Steffen Rumler, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <192298D25D96A042975E372855100DB70FEA87@039-SN2MPN1-011.039d.mgd.msft.net>

On Thu, May 31, 2012 at 07:04:42AM +0000, Wrobel Heinz-R39252 wrote:
> Michael,
> 
> > On Wed, 2012-05-30 at 16:33 +0200, Steffen Rumler wrote:
> > > I've found the following root cause:
> > >
> > >      (6) Unfortunately, the trampoline code (do_plt_call()) is using
> > register r11 to setup the jump.
> > >            It looks like the prologue and epilogue are using also the
> > register r11, in order to point to the previous stack frame.
> > >            This is a conflict !!! The trampoline code is damaging the
> > content of r11.
> > 
> > Hi Steffen,
> > 
> > Great bug report!
> > 
> > I can't quite work out what the standards say, the versions I'm looking
> > at are probably old anyway.
> 
> The ABI supplement from https://www.power.org/resources/downloads/ is explicit about r11 being a requirement for the statically lined save/restore functions in section 3.3.4 on page 59.
> 
> This means that any trampoline code must not ever use r11 or it can't be used to get to such save/restore functions safely from far away.

I believe that the basic premise is that you should provide a directly reachable copy 
of the save/rstore functions, even if this means that you need several copies of the functions.

> 
> Unfortunately the same doc and predecessors show r11 in all basic examples for PLT/trampoline code AFAICS, which is likely why all trampoline code uses r11 in any known case.
> 
> I would guess that it was never envisioned that compiler generated code would be in a different section than save/restore functions, i.e., the Linux module "__init" assumptions for Power break the ABI. Or does the ABI break the __init concept?!
> 
> Using r12 in the trampoline seems to be the obvious solution for module loading.
> 
> But what about other code loading done? If, e.g., a user runs any app from bash it gets loaded and relocated and trampolines might get set up somehow.

I don't think so. The linker/whatever should generate a copy of the save/restore functions for every
executable code area (shared library), and probably more than one copy if the text becomes too large.

For 64 bit code, these functions are actually inserted by the linker.

[Ok, I just recompiled my 64 bit kernel with -Os and I see that vmlinux gets one copy
of the save/restore functions and every module also gets its copy.]

This makes sense, really these functions are there for a compromise between locality 
and performance, there should be one per code section, otherwise the cache line 
used by the trampoline negates a large part of their advantage.

> 
> Wouldn't we have to find fix ANY trampoline code generator remotely related to a basic Power Architecture Linux?
> Or is it a basic assumption for anything but modules that compiler generated code may never ever be outside the .text section? I am not sure that would be a safe assumption.
> 
> Isn't this problem going beyond just module loading for Power Architecture Linux?

I don't think so. It really seems to be a 32 bit kernel problem.

	Regards,
	Gabriel

^ permalink raw reply

* Re: [RFC] [PATCH] powerpc: Add MSR_DE to MSR_KERNEL
From: Scott Wood @ 2012-05-31 17:47 UTC (permalink / raw)
  To: Joakim Tjernlund; +Cc: linuxppc-dev, Dan Malek, Bob Cochran, Support
In-Reply-To: <OF1016B1AA.DF19B646-ONC1257A0F.003647EF-C1257A0F.003699E5@transmode.se>

On 05/31/2012 04:56 AM, Joakim Tjernlund wrote:
> Abatron Support <support@abatron.ch> wrote on 2012/05/31 11:30:57:
>>
>>
>>> Abatron Support <support@abatron.ch> wrote on 2012/05/30 14:08:26:
>>>>
>>>>>> I have tested this briefly with BDI2000 on P2010(e500) and
>>>>>> it works for me. I don't know if there are any bad side effects,
>>>>>> therfore
>>>>>> this RFC.
>>>>
>>>>> We used to have MSR_DE surrounded by CONFIG_something
>>>>> to ensure it wasn't set under normal operation.  IIRC, if MSR_DE
>>>>> is set, you will have problems with software debuggers that
>>>>> utilize the the debugging registers in the chip itself.  You only want
>>>>> to force this to be set when using the BDI, not at other times.
>>>>
>>>> This MSR_DE is also of interest and used for software debuggers that
>>>> make use of the debug registers. Only if MSR_DE is set then debug
>>>> interrupts are generated. If a debug event leads to a debug interrupt
>>>> handled by a software debugger or if it leads to a debug halt handled
>>>> by a JTAG tool is selected with DBCR0_EDM / DBCR0_IDM.
>>>>
>>>> The "e500 Core Family Reference Manual" chapter "Chapter 8
>>>> Debug Support" explains in detail the effect of MSR_DE.
>>
>>> So what is the verdict on this? I don't buy into Dan argument without some
>>> hard data.
>>
>> What I tried to mention is that handling the MSR_DE correct is not only
>> an emulator (JTAG debugger) requirement. Also a software debugger may
>> depend on a correct handled MSR_DE bit.
> 
> Yes, that made sense to me too. How would SW debuggers work if the kernel keeps
> turning off MSR_DE first chance it gets?

The kernel selectively enables MSR_DE when it wants to debug.  I'm not
sure if anything will be bothered by leaving it on all the time.  This
is something we need for virtualization as well, so a hypervisor can
debug the guest.

-Scott

^ permalink raw reply

* [Early RFC 0/6] arch/powerpc: Add 64TB support to ppc64
From: Aneesh Kumar K.V @ 2012-05-31 19:50 UTC (permalink / raw)
  To: benh, paulus, michael, anton; +Cc: linuxppc-dev

Hi,

This patchset include preparatory patches for supporting 64TB with ppc64. I haven't
completed the actual patch that bump the USER_ESID bits. I wanted the share the
changes early so that I can get feedback on the approach. The changes itself
contains few FIXME!! which I will be addressing in the later updates.

Thanks,
-aneesh

^ permalink raw reply

* [Early RFC 1/6] arch/powerpc: Use hpt_va to compute virtual address
From: Aneesh Kumar K.V @ 2012-05-31 19:50 UTC (permalink / raw)
  To: benh, paulus, michael, anton; +Cc: linuxppc-dev, Aneesh Kumar K.V
In-Reply-To: <1338493841-9926-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com>

From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>

Don't open code the same

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 arch/powerpc/platforms/cell/beat_htab.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/powerpc/platforms/cell/beat_htab.c b/arch/powerpc/platforms/cell/beat_htab.c
index 943c9d3..b83077e 100644
--- a/arch/powerpc/platforms/cell/beat_htab.c
+++ b/arch/powerpc/platforms/cell/beat_htab.c
@@ -259,7 +259,7 @@ static void beat_lpar_hpte_updateboltedpp(unsigned long newpp,
 	u64 dummy0, dummy1;
 
 	vsid = get_kernel_vsid(ea, MMU_SEGSIZE_256M);
-	va = (vsid << 28) | (ea & 0x0fffffff);
+	va = hpt_va(ea, vsid, MMU_SEGSIZE_256M);
 
 	raw_spin_lock(&beat_htab_lock);
 	slot = beat_lpar_hpte_find(va, psize);
-- 
1.7.10

^ permalink raw reply related

* [Early RFC 2/6] arch/powerpc: Convert virtual address to a struct
From: Aneesh Kumar K.V @ 2012-05-31 19:50 UTC (permalink / raw)
  To: benh, paulus, michael, anton; +Cc: linuxppc-dev, Aneesh Kumar K.V
In-Reply-To: <1338493841-9926-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com>

From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>

This is in preparation to the conversion of 64 bit powerpc virtual address
to the max 78 bits. Later patch will switch struct virt_addr to a struct
of virtual segment id and segment offset.

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/kvm_book3s.h   |    2 +-
 arch/powerpc/include/asm/machdep.h      |    6 +--
 arch/powerpc/include/asm/mmu-hash64.h   |   24 ++++++----
 arch/powerpc/include/asm/tlbflush.h     |    4 +-
 arch/powerpc/kvm/book3s_64_mmu_host.c   |    3 +-
 arch/powerpc/mm/hash_native_64.c        |   76 +++++++++++++++++--------------
 arch/powerpc/mm/hash_utils_64.c         |   12 ++---
 arch/powerpc/mm/hugetlbpage-hash64.c    |    3 +-
 arch/powerpc/mm/tlb_hash64.c            |    3 +-
 arch/powerpc/platforms/cell/beat_htab.c |   17 +++----
 arch/powerpc/platforms/ps3/htab.c       |    6 +--
 arch/powerpc/platforms/pseries/lpar.c   |   30 ++++++------
 12 files changed, 103 insertions(+), 83 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
index fd07f43..374b75d 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -59,7 +59,7 @@ struct hpte_cache {
 	struct hlist_node list_vpte;
 	struct hlist_node list_vpte_long;
 	struct rcu_head rcu_head;
-	u64 host_va;
+	struct virt_addr host_va;
 	u64 pfn;
 	ulong slot;
 	struct kvmppc_pte pte;
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index 42ce570..b34d0a9 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -34,19 +34,19 @@ struct machdep_calls {
 	char		*name;
 #ifdef CONFIG_PPC64
 	void            (*hpte_invalidate)(unsigned long slot,
-					   unsigned long va,
+					   struct virt_addr va,
 					   int psize, int ssize,
 					   int local);
 	long		(*hpte_updatepp)(unsigned long slot, 
 					 unsigned long newpp, 
-					 unsigned long va,
+					 struct virt_addr va,
 					 int psize, int ssize,
 					 int local);
 	void            (*hpte_updateboltedpp)(unsigned long newpp, 
 					       unsigned long ea,
 					       int psize, int ssize);
 	long		(*hpte_insert)(unsigned long hpte_group,
-				       unsigned long va,
+				       struct virt_addr va,
 				       unsigned long prpn,
 				       unsigned long rflags,
 				       unsigned long vflags,
diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h
index 1c65a59..5ff936b 100644
--- a/arch/powerpc/include/asm/mmu-hash64.h
+++ b/arch/powerpc/include/asm/mmu-hash64.h
@@ -143,6 +143,10 @@ struct mmu_psize_def
 	unsigned long	sllp;	/* SLB L||LP (exact mask to use in slbmte) */
 };
 
+struct virt_addr {
+	unsigned long addr;
+};
+
 #endif /* __ASSEMBLY__ */
 
 /*
@@ -183,11 +187,11 @@ extern int mmu_ci_restrictions;
  * This function sets the AVPN and L fields of the HPTE  appropriately
  * for the page size
  */
-static inline unsigned long hpte_encode_v(unsigned long va, int psize,
+static inline unsigned long hpte_encode_v(struct virt_addr va, int psize,
 					  int ssize)
 {
 	unsigned long v;
-	v = (va >> 23) & ~(mmu_psize_defs[psize].avpnm);
+	v = (va.addr >> 23) & ~(mmu_psize_defs[psize].avpnm);
 	v <<= HPTE_V_AVPN_SHIFT;
 	if (psize != MMU_PAGE_4K)
 		v |= HPTE_V_LARGE;
@@ -218,28 +222,30 @@ static inline unsigned long hpte_encode_r(unsigned long pa, int psize)
 /*
  * Build a VA given VSID, EA and segment size
  */
-static inline unsigned long hpt_va(unsigned long ea, unsigned long vsid,
+static inline struct virt_addr hpt_va(unsigned long ea, unsigned long vsid,
 				   int ssize)
 {
+	struct virt_addr va;
 	if (ssize == MMU_SEGSIZE_256M)
-		return (vsid << 28) | (ea & 0xfffffffUL);
-	return (vsid << 40) | (ea & 0xffffffffffUL);
+		va.addr = (vsid << 28) | (ea & 0xfffffffUL);
+	va.addr = (vsid << 40) | (ea & 0xffffffffffUL);
+	return va;
 }
 
 /*
  * This hashes a virtual address
  */
 
-static inline unsigned long hpt_hash(unsigned long va, unsigned int shift,
+static inline unsigned long hpt_hash(struct virt_addr va, unsigned int shift,
 				     int ssize)
 {
 	unsigned long hash, vsid;
 
 	if (ssize == MMU_SEGSIZE_256M) {
-		hash = (va >> 28) ^ ((va & 0x0fffffffUL) >> shift);
+		hash = (va.addr >> 28) ^ ((va.addr & 0x0fffffffUL) >> shift);
 	} else {
-		vsid = va >> 40;
-		hash = vsid ^ (vsid << 25) ^ ((va & 0xffffffffffUL) >> shift);
+		vsid = va.addr >> 40;
+		hash = vsid ^ (vsid << 25) ^ ((va.addr & 0xffffffffffUL) >> shift);
 	}
 	return hash & 0x7fffffffffUL;
 }
diff --git a/arch/powerpc/include/asm/tlbflush.h b/arch/powerpc/include/asm/tlbflush.h
index 81143fc..2c8ad50 100644
--- a/arch/powerpc/include/asm/tlbflush.h
+++ b/arch/powerpc/include/asm/tlbflush.h
@@ -95,7 +95,7 @@ struct ppc64_tlb_batch {
 	unsigned long		index;
 	struct mm_struct	*mm;
 	real_pte_t		pte[PPC64_TLB_BATCH_NR];
-	unsigned long		vaddr[PPC64_TLB_BATCH_NR];
+	struct virt_addr	vaddr[PPC64_TLB_BATCH_NR];
 	unsigned int		psize;
 	int			ssize;
 };
@@ -127,7 +127,7 @@ static inline void arch_leave_lazy_mmu_mode(void)
 #define arch_flush_lazy_mmu_mode()      do {} while (0)
 
 
-extern void flush_hash_page(unsigned long va, real_pte_t pte, int psize,
+extern void flush_hash_page(struct virt_addr va, real_pte_t pte, int psize,
 			    int ssize, int local);
 extern void flush_hash_range(unsigned long number, int local);
 
diff --git a/arch/powerpc/kvm/book3s_64_mmu_host.c b/arch/powerpc/kvm/book3s_64_mmu_host.c
index 10fc8ec..933b117 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_host.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_host.c
@@ -80,8 +80,9 @@ static struct kvmppc_sid_map *find_sid_vsid(struct kvm_vcpu *vcpu, u64 gvsid)
 
 int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
 {
+	struct virt_addr va;
 	pfn_t hpaddr;
-	ulong hash, hpteg, va;
+	ulong hash, hpteg;
 	u64 vsid;
 	int ret;
 	int rflags = 0x192;
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index 90039bc..cab3892 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -39,62 +39,67 @@
 
 DEFINE_RAW_SPINLOCK(native_tlbie_lock);
 
-static inline void __tlbie(unsigned long va, int psize, int ssize)
+/* Verify docs says 14 .. 14+i bits */
+static inline void __tlbie(struct virt_addr va, int psize, int ssize)
 {
+	unsigned long vaddr = va.addr;
 	unsigned int penc;
 
+	vaddr &= ~(0xffffULL << 48);
+
 	/* clear top 16 bits, non SLS segment */
-	va &= ~(0xffffULL << 48);
+	vaddr &= ~(0xffffULL << 48);
 
 	switch (psize) {
 	case MMU_PAGE_4K:
-		va &= ~0xffful;
-		va |= ssize << 8;
+		vaddr &= ~0xffful;
+		vaddr |= ssize << 8;
 		asm volatile(ASM_FTR_IFCLR("tlbie %0,0", PPC_TLBIE(%1,%0), %2)
-			     : : "r" (va), "r"(0), "i" (CPU_FTR_ARCH_206)
+			     : : "r" (vaddr), "r"(0), "i" (CPU_FTR_ARCH_206)
 			     : "memory");
 		break;
 	default:
 		penc = mmu_psize_defs[psize].penc;
-		va &= ~((1ul << mmu_psize_defs[psize].shift) - 1);
-		va |= penc << 12;
-		va |= ssize << 8;
-		va |= 1; /* L */
+		vaddr &= ~((1ul << mmu_psize_defs[psize].shift) - 1);
+		vaddr |= penc << 12;
+		vaddr |= ssize << 8;
+		vaddr |= 1; /* L */
 		asm volatile(ASM_FTR_IFCLR("tlbie %0,1", PPC_TLBIE(%1,%0), %2)
-			     : : "r" (va), "r"(0), "i" (CPU_FTR_ARCH_206)
+			     : : "r" (vaddr), "r"(0), "i" (CPU_FTR_ARCH_206)
 			     : "memory");
 		break;
 	}
 }
 
-static inline void __tlbiel(unsigned long va, int psize, int ssize)
+/* Verify docs says 14 .. 14+i bits */
+static inline void __tlbiel(struct virt_addr va, int psize, int ssize)
 {
+	unsigned long vaddr = va.addr;
 	unsigned int penc;
 
-	/* clear top 16 bits, non SLS segment */
-	va &= ~(0xffffULL << 48);
+	vaddr &= ~(0xffffULL << 48);
 
 	switch (psize) {
 	case MMU_PAGE_4K:
-		va &= ~0xffful;
-		va |= ssize << 8;
+		vaddr &= ~0xffful;
+		vaddr |= ssize << 8;
 		asm volatile(".long 0x7c000224 | (%0 << 11) | (0 << 21)"
-			     : : "r"(va) : "memory");
+			     : : "r"(vaddr) : "memory");
 		break;
 	default:
 		penc = mmu_psize_defs[psize].penc;
-		va &= ~((1ul << mmu_psize_defs[psize].shift) - 1);
-		va |= penc << 12;
-		va |= ssize << 8;
-		va |= 1; /* L */
+		vaddr &= ~((1ul << mmu_psize_defs[psize].shift) - 1);
+		vaddr |= penc << 12;
+		vaddr |= ssize << 8;
+		vaddr |= 1; /* L */
 		asm volatile(".long 0x7c000224 | (%0 << 11) | (1 << 21)"
-			     : : "r"(va) : "memory");
+			     : : "r"(vaddr) : "memory");
 		break;
 	}
 
 }
 
-static inline void tlbie(unsigned long va, int psize, int ssize, int local)
+static inline void tlbie(struct virt_addr va, int psize, int ssize, int local)
 {
 	unsigned int use_local = local && mmu_has_feature(MMU_FTR_TLBIEL);
 	int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
@@ -134,7 +139,7 @@ static inline void native_unlock_hpte(struct hash_pte *hptep)
 	clear_bit_unlock(HPTE_LOCK_BIT, word);
 }
 
-static long native_hpte_insert(unsigned long hpte_group, unsigned long va,
+static long native_hpte_insert(unsigned long hpte_group, struct virt_addr va,
 			unsigned long pa, unsigned long rflags,
 			unsigned long vflags, int psize, int ssize)
 {
@@ -225,7 +230,7 @@ static long native_hpte_remove(unsigned long hpte_group)
 }
 
 static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
-				 unsigned long va, int psize, int ssize,
+				 struct virt_addr va, int psize, int ssize,
 				 int local)
 {
 	struct hash_pte *hptep = htab_address + slot;
@@ -259,7 +264,7 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
 	return ret;
 }
 
-static long native_hpte_find(unsigned long va, int psize, int ssize)
+static long native_hpte_find(struct virt_addr va, int psize, int ssize)
 {
 	struct hash_pte *hptep;
 	unsigned long hash;
@@ -295,7 +300,8 @@ static long native_hpte_find(unsigned long va, int psize, int ssize)
 static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
 				       int psize, int ssize)
 {
-	unsigned long vsid, va;
+	struct virt_addr va;
+	unsigned long vsid;
 	long slot;
 	struct hash_pte *hptep;
 
@@ -315,7 +321,7 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
 	tlbie(va, psize, ssize, 0);
 }
 
-static void native_hpte_invalidate(unsigned long slot, unsigned long va,
+static void native_hpte_invalidate(unsigned long slot, struct virt_addr va,
 				   int psize, int ssize, int local)
 {
 	struct hash_pte *hptep = htab_address + slot;
@@ -349,7 +355,7 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va,
 #define LP_MASK(i)	((0xFF >> (i)) << LP_SHIFT)
 
 static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
-			int *psize, int *ssize, unsigned long *va)
+			int *psize, int *ssize, struct virt_addr *va)
 {
 	unsigned long hpte_r = hpte->r;
 	unsigned long hpte_v = hpte->v;
@@ -403,7 +409,7 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
 		avpn |= (vpi << mmu_psize_defs[size].shift);
 	}
 
-	*va = avpn;
+	va->addr = avpn;
 	*psize = size;
 	*ssize = hpte_v >> HPTE_V_SSIZE_SHIFT;
 }
@@ -418,9 +424,10 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
  */
 static void native_hpte_clear(void)
 {
+	struct virt_addr va;
 	unsigned long slot, slots, flags;
 	struct hash_pte *hptep = htab_address;
-	unsigned long hpte_v, va;
+	unsigned long hpte_v;
 	unsigned long pteg_count;
 	int psize, ssize;
 
@@ -465,7 +472,8 @@ static void native_hpte_clear(void)
  */
 static void native_flush_hash_range(unsigned long number, int local)
 {
-	unsigned long va, hash, index, hidx, shift, slot;
+	struct virt_addr va;
+	unsigned long hash, index, hidx, shift, slot;
 	struct hash_pte *hptep;
 	unsigned long hpte_v;
 	unsigned long want_v;
@@ -482,7 +490,7 @@ static void native_flush_hash_range(unsigned long number, int local)
 		va = batch->vaddr[i];
 		pte = batch->pte[i];
 
-		pte_iterate_hashed_subpages(pte, psize, va, index, shift) {
+		pte_iterate_hashed_subpages(pte, psize, va.addr, index, shift) {
 			hash = hpt_hash(va, shift, ssize);
 			hidx = __rpte_to_hidx(pte, index);
 			if (hidx & _PTEIDX_SECONDARY)
@@ -508,7 +516,7 @@ static void native_flush_hash_range(unsigned long number, int local)
 			va = batch->vaddr[i];
 			pte = batch->pte[i];
 
-			pte_iterate_hashed_subpages(pte, psize, va, index,
+			pte_iterate_hashed_subpages(pte, psize, va.addr, index,
 						    shift) {
 				__tlbiel(va, psize, ssize);
 			} pte_iterate_hashed_end();
@@ -525,7 +533,7 @@ static void native_flush_hash_range(unsigned long number, int local)
 			va = batch->vaddr[i];
 			pte = batch->pte[i];
 
-			pte_iterate_hashed_subpages(pte, psize, va, index,
+			pte_iterate_hashed_subpages(pte, psize, va.addr, index,
 						    shift) {
 				__tlbie(va, psize, ssize);
 			} pte_iterate_hashed_end();
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 377e5cb..2429d53 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -192,7 +192,7 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
 	     vaddr += step, paddr += step) {
 		unsigned long hash, hpteg;
 		unsigned long vsid = get_kernel_vsid(vaddr, ssize);
-		unsigned long va = hpt_va(vaddr, vsid, ssize);
+		struct virt_addr va = hpt_va(vaddr, vsid, ssize);
 		unsigned long tprot = prot;
 
 		/* Make kernel text executable */
@@ -1153,13 +1153,13 @@ void hash_preload(struct mm_struct *mm, unsigned long ea,
 /* WARNING: This is called from hash_low_64.S, if you change this prototype,
  *          do not forget to update the assembly call site !
  */
-void flush_hash_page(unsigned long va, real_pte_t pte, int psize, int ssize,
+void flush_hash_page(struct virt_addr va, real_pte_t pte, int psize, int ssize,
 		     int local)
 {
 	unsigned long hash, index, shift, hidx, slot;
 
-	DBG_LOW("flush_hash_page(va=%016lx)\n", va);
-	pte_iterate_hashed_subpages(pte, psize, va, index, shift) {
+	DBG_LOW("flush_hash_page(va=%016lx)\n", va.addr);
+	pte_iterate_hashed_subpages(pte, psize, va.addr, index, shift) {
 		hash = hpt_hash(va, shift, ssize);
 		hidx = __rpte_to_hidx(pte, index);
 		if (hidx & _PTEIDX_SECONDARY)
@@ -1208,7 +1208,7 @@ static void kernel_map_linear_page(unsigned long vaddr, unsigned long lmi)
 {
 	unsigned long hash, hpteg;
 	unsigned long vsid = get_kernel_vsid(vaddr, mmu_kernel_ssize);
-	unsigned long va = hpt_va(vaddr, vsid, mmu_kernel_ssize);
+	struct virt_addr va = hpt_va(vaddr, vsid, mmu_kernel_ssize);
 	unsigned long mode = htab_convert_pte_flags(PAGE_KERNEL);
 	int ret;
 
@@ -1229,7 +1229,7 @@ static void kernel_unmap_linear_page(unsigned long vaddr, unsigned long lmi)
 {
 	unsigned long hash, hidx, slot;
 	unsigned long vsid = get_kernel_vsid(vaddr, mmu_kernel_ssize);
-	unsigned long va = hpt_va(vaddr, vsid, mmu_kernel_ssize);
+	struct virt_addr va = hpt_va(vaddr, vsid, mmu_kernel_ssize);
 
 	hash = hpt_hash(va, PAGE_SHIFT, mmu_kernel_ssize);
 	spin_lock(&linear_map_hash_lock);
diff --git a/arch/powerpc/mm/hugetlbpage-hash64.c b/arch/powerpc/mm/hugetlbpage-hash64.c
index cc5c273..47b4ed0 100644
--- a/arch/powerpc/mm/hugetlbpage-hash64.c
+++ b/arch/powerpc/mm/hugetlbpage-hash64.c
@@ -18,8 +18,9 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
 		     pte_t *ptep, unsigned long trap, int local, int ssize,
 		     unsigned int shift, unsigned int mmu_psize)
 {
+	struct virt_addr va;
 	unsigned long old_pte, new_pte;
-	unsigned long va, rflags, pa, sz;
+	unsigned long rflags, pa, sz;
 	long slot;
 
 	BUG_ON(shift != mmu_psize_defs[mmu_psize].shift);
diff --git a/arch/powerpc/mm/tlb_hash64.c b/arch/powerpc/mm/tlb_hash64.c
index 31f1820..b830466 100644
--- a/arch/powerpc/mm/tlb_hash64.c
+++ b/arch/powerpc/mm/tlb_hash64.c
@@ -42,8 +42,9 @@ DEFINE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch);
 void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
 		     pte_t *ptep, unsigned long pte, int huge)
 {
+	struct virt_addr vaddr;
 	struct ppc64_tlb_batch *batch = &get_cpu_var(ppc64_tlb_batch);
-	unsigned long vsid, vaddr;
+	unsigned long vsid;
 	unsigned int psize;
 	int ssize;
 	real_pte_t rpte;
diff --git a/arch/powerpc/platforms/cell/beat_htab.c b/arch/powerpc/platforms/cell/beat_htab.c
index b83077e..a2dfc22 100644
--- a/arch/powerpc/platforms/cell/beat_htab.c
+++ b/arch/powerpc/platforms/cell/beat_htab.c
@@ -88,7 +88,7 @@ static inline unsigned int beat_read_mask(unsigned hpte_group)
 }
 
 static long beat_lpar_hpte_insert(unsigned long hpte_group,
-				  unsigned long va, unsigned long pa,
+				  struct virt_addr va, unsigned long pa,
 				  unsigned long rflags, unsigned long vflags,
 				  int psize, int ssize)
 {
@@ -184,7 +184,7 @@ static void beat_lpar_hptab_clear(void)
  */
 static long beat_lpar_hpte_updatepp(unsigned long slot,
 				    unsigned long newpp,
-				    unsigned long va,
+				    struct virt_addr va,
 				    int psize, int ssize, int local)
 {
 	unsigned long lpar_rc;
@@ -220,7 +220,7 @@ static long beat_lpar_hpte_updatepp(unsigned long slot,
 	return 0;
 }
 
-static long beat_lpar_hpte_find(unsigned long va, int psize)
+static long beat_lpar_hpte_find(struct virt_addr va, int psize)
 {
 	unsigned long hash;
 	unsigned long i, j;
@@ -255,7 +255,8 @@ static void beat_lpar_hpte_updateboltedpp(unsigned long newpp,
 					  unsigned long ea,
 					  int psize, int ssize)
 {
-	unsigned long lpar_rc, slot, vsid, va;
+	struct virt_addr va;
+	unsigned long lpar_rc, slot, vsid;
 	u64 dummy0, dummy1;
 
 	vsid = get_kernel_vsid(ea, MMU_SEGSIZE_256M);
@@ -272,7 +273,7 @@ static void beat_lpar_hpte_updateboltedpp(unsigned long newpp,
 	BUG_ON(lpar_rc != 0);
 }
 
-static void beat_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
+static void beat_lpar_hpte_invalidate(unsigned long slot, struct virt_addr va,
 					 int psize, int ssize, int local)
 {
 	unsigned long want_v;
@@ -311,7 +312,7 @@ void __init hpte_init_beat(void)
 }
 
 static long beat_lpar_hpte_insert_v3(unsigned long hpte_group,
-				  unsigned long va, unsigned long pa,
+				  struct virt_addr va, unsigned long pa,
 				  unsigned long rflags, unsigned long vflags,
 				  int psize, int ssize)
 {
@@ -364,7 +365,7 @@ static long beat_lpar_hpte_insert_v3(unsigned long hpte_group,
  */
 static long beat_lpar_hpte_updatepp_v3(unsigned long slot,
 				    unsigned long newpp,
-				    unsigned long va,
+				    struct virt_addr va,
 				    int psize, int ssize, int local)
 {
 	unsigned long lpar_rc;
@@ -392,7 +393,7 @@ static long beat_lpar_hpte_updatepp_v3(unsigned long slot,
 	return 0;
 }
 
-static void beat_lpar_hpte_invalidate_v3(unsigned long slot, unsigned long va,
+static void beat_lpar_hpte_invalidate_v3(unsigned long slot, struct virt_addr va,
 					 int psize, int ssize, int local)
 {
 	unsigned long want_v;
diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c
index 3124cf7..6e27576 100644
--- a/arch/powerpc/platforms/ps3/htab.c
+++ b/arch/powerpc/platforms/ps3/htab.c
@@ -43,7 +43,7 @@ enum ps3_lpar_vas_id {
 
 static DEFINE_SPINLOCK(ps3_htab_lock);
 
-static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va,
+static long ps3_hpte_insert(unsigned long hpte_group, struct virt_addr va,
 	unsigned long pa, unsigned long rflags, unsigned long vflags,
 	int psize, int ssize)
 {
@@ -107,7 +107,7 @@ static long ps3_hpte_remove(unsigned long hpte_group)
 }
 
 static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp,
-	unsigned long va, int psize, int ssize, int local)
+	struct virt_addr va, int psize, int ssize, int local)
 {
 	int result;
 	u64 hpte_v, want_v, hpte_rs;
@@ -159,7 +159,7 @@ static void ps3_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
 	panic("ps3_hpte_updateboltedpp() not implemented");
 }
 
-static void ps3_hpte_invalidate(unsigned long slot, unsigned long va,
+static void ps3_hpte_invalidate(unsigned long slot, struct virt_addr va,
 	int psize, int ssize, int local)
 {
 	unsigned long flags;
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 5f3ef87..b4e9641 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -108,9 +108,9 @@ void vpa_init(int cpu)
 }
 
 static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
- 			      unsigned long va, unsigned long pa,
- 			      unsigned long rflags, unsigned long vflags,
-			      int psize, int ssize)
+				     struct virt_addr va, unsigned long pa,
+				     unsigned long rflags, unsigned long vflags,
+				     int psize, int ssize)
 {
 	unsigned long lpar_rc;
 	unsigned long flags;
@@ -120,7 +120,7 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
 	if (!(vflags & HPTE_V_BOLTED))
 		pr_devel("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
 			 "rflags=%lx, vflags=%lx, psize=%d)\n",
-			 hpte_group, va, pa, rflags, vflags, psize);
+			 hpte_group, va.addr, pa, rflags, vflags, psize);
 
 	hpte_v = hpte_encode_v(va, psize, ssize) | vflags | HPTE_V_VALID;
 	hpte_r = hpte_encode_r(pa, psize) | rflags;
@@ -231,12 +231,12 @@ static void pSeries_lpar_hptab_clear(void)
  * for use when we want to match an existing PTE.  The bottom 7 bits
  * of the returned value are zero.
  */
-static inline unsigned long hpte_encode_avpn(unsigned long va, int psize,
+static inline unsigned long hpte_encode_avpn(struct virt_addr va, int psize,
 					     int ssize)
 {
 	unsigned long v;
 
-	v = (va >> 23) & ~(mmu_psize_defs[psize].avpnm);
+	v = (va.addr >> 23) & ~(mmu_psize_defs[psize].avpnm);
 	v <<= HPTE_V_AVPN_SHIFT;
 	v |= ((unsigned long) ssize) << HPTE_V_SSIZE_SHIFT;
 	return v;
@@ -250,7 +250,7 @@ static inline unsigned long hpte_encode_avpn(unsigned long va, int psize,
  */
 static long pSeries_lpar_hpte_updatepp(unsigned long slot,
 				       unsigned long newpp,
-				       unsigned long va,
+				       struct virt_addr va,
 				       int psize, int ssize, int local)
 {
 	unsigned long lpar_rc;
@@ -295,7 +295,7 @@ static unsigned long pSeries_lpar_hpte_getword0(unsigned long slot)
 	return dword0;
 }
 
-static long pSeries_lpar_hpte_find(unsigned long va, int psize, int ssize)
+static long pSeries_lpar_hpte_find(struct virt_addr va, int psize, int ssize)
 {
 	unsigned long hash;
 	unsigned long i;
@@ -323,7 +323,8 @@ static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp,
 					     unsigned long ea,
 					     int psize, int ssize)
 {
-	unsigned long lpar_rc, slot, vsid, va, flags;
+	struct virt_addr va;
+	unsigned long lpar_rc, slot, vsid, flags;
 
 	vsid = get_kernel_vsid(ea, ssize);
 	va = hpt_va(ea, vsid, ssize);
@@ -337,7 +338,7 @@ static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp,
 	BUG_ON(lpar_rc != H_SUCCESS);
 }
 
-static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
+static void pSeries_lpar_hpte_invalidate(unsigned long slot, struct virt_addr va,
 					 int psize, int ssize, int local)
 {
 	unsigned long want_v;
@@ -345,7 +346,7 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
 	unsigned long dummy1, dummy2;
 
 	pr_devel("    inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
-		 slot, va, psize, local);
+		 slot, va.addr, psize, local);
 
 	want_v = hpte_encode_avpn(va, psize, ssize);
 	lpar_rc = plpar_pte_remove(H_AVPN, slot, want_v, &dummy1, &dummy2);
@@ -358,7 +359,8 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
 static void pSeries_lpar_hpte_removebolted(unsigned long ea,
 					   int psize, int ssize)
 {
-	unsigned long slot, vsid, va;
+	struct virt_addr va;
+	unsigned long slot, vsid;
 
 	vsid = get_kernel_vsid(ea, ssize);
 	va = hpt_va(ea, vsid, ssize);
@@ -382,12 +384,12 @@ static void pSeries_lpar_hpte_removebolted(unsigned long ea,
  */
 static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
 {
+	struct virt_addr va;
 	unsigned long i, pix, rc;
 	unsigned long flags = 0;
 	struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
 	int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
 	unsigned long param[9];
-	unsigned long va;
 	unsigned long hash, index, shift, hidx, slot;
 	real_pte_t pte;
 	int psize, ssize;
@@ -401,7 +403,7 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
 	for (i = 0; i < number; i++) {
 		va = batch->vaddr[i];
 		pte = batch->pte[i];
-		pte_iterate_hashed_subpages(pte, psize, va, index, shift) {
+		pte_iterate_hashed_subpages(pte, psize, va.addr, index, shift) {
 			hash = hpt_hash(va, shift, ssize);
 			hidx = __rpte_to_hidx(pte, index);
 			if (hidx & _PTEIDX_SECONDARY)
-- 
1.7.10

^ permalink raw reply related

* [Early RFC 3/6] arch/powerpc: Simplify hpte_decode
From: Aneesh Kumar K.V @ 2012-05-31 19:50 UTC (permalink / raw)
  To: benh, paulus, michael, anton; +Cc: linuxppc-dev, Aneesh Kumar K.V
In-Reply-To: <1338493841-9926-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com>

From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>

This patch simplify hpte_decode for easy switching of virtual address to
vsid and segment offset combination in the later patch

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 arch/powerpc/mm/hash_native_64.c |   51 ++++++++++++++++++++++----------------
 1 file changed, 30 insertions(+), 21 deletions(-)

diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index cab3892..76c2574 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -357,9 +357,10 @@ static void native_hpte_invalidate(unsigned long slot, struct virt_addr va,
 static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
 			int *psize, int *ssize, struct virt_addr *va)
 {
+	unsigned long avpn, pteg, vpi;
 	unsigned long hpte_r = hpte->r;
 	unsigned long hpte_v = hpte->v;
-	unsigned long avpn;
+	unsigned long vsid, seg_off;
 	int i, size, shift, penc;
 
 	if (!(hpte_v & HPTE_V_LARGE))
@@ -386,32 +387,40 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
 	}
 
 	/* This works for all page sizes, and for 256M and 1T segments */
+	*ssize = hpte_v >> HPTE_V_SSIZE_SHIFT;
 	shift = mmu_psize_defs[size].shift;
-	avpn = (HPTE_V_AVPN_VAL(hpte_v) & ~mmu_psize_defs[size].avpnm) << 23;
-
-	if (shift < 23) {
-		unsigned long vpi, vsid, pteg;
 
-		pteg = slot / HPTES_PER_GROUP;
-		if (hpte_v & HPTE_V_SECONDARY)
-			pteg = ~pteg;
-		switch (hpte_v >> HPTE_V_SSIZE_SHIFT) {
-		case MMU_SEGSIZE_256M:
-			vpi = ((avpn >> 28) ^ pteg) & htab_hash_mask;
-			break;
-		case MMU_SEGSIZE_1T:
-			vsid = avpn >> 40;
+	avpn = (HPTE_V_AVPN_VAL(hpte_v) & ~mmu_psize_defs[size].avpnm);
+	pteg = slot / HPTES_PER_GROUP;
+	if (hpte_v & HPTE_V_SECONDARY)
+		pteg = ~pteg;
+
+	switch (*ssize) {
+	case MMU_SEGSIZE_256M:
+		/* We only have 28 - 23 bits of seg_off in avpn */
+		seg_off = (avpn & 0x1f) << 23;
+		vsid    =  avpn >> 5;
+		/* We can find more bits from the pteg value */
+		if (shift < 23) {
+			vpi = (vsid ^ pteg) & htab_hash_mask;
+			seg_off |= vpi << shift;
+		}
+		va->addr = vsid << 28 | seg_off;
+	case MMU_SEGSIZE_1T:
+		/* We only have 40 - 23 bits of seg_off in avpn */
+		seg_off = (avpn & 0x1ffff) << 23;
+		vsid    = avpn >> 17;
+		if (shift < 23) {
 			vpi = (vsid ^ (vsid << 25) ^ pteg) & htab_hash_mask;
-			break;
-		default:
-			avpn = vpi = size = 0;
+			seg_off |= vpi << shift;
 		}
-		avpn |= (vpi << mmu_psize_defs[size].shift);
+		va->addr = vsid << 40 | seg_off;
+	default:
+		seg_off = 0;
+		vsid    = 0;
+		va->addr = 0;
 	}
-
-	va->addr = avpn;
 	*psize = size;
-	*ssize = hpte_v >> HPTE_V_SSIZE_SHIFT;
 }
 
 /*
-- 
1.7.10

^ permalink raw reply related

* [Early RFC 4/6] arch/powerpc: Use vsid and segment offset to represent virtual address
From: Aneesh Kumar K.V @ 2012-05-31 19:50 UTC (permalink / raw)
  To: benh, paulus, michael, anton; +Cc: linuxppc-dev, Aneesh Kumar K.V
In-Reply-To: <1338493841-9926-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com>

From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>

This patch enables us to have 78 bit virtual address.

With 1TB segments we use 40 bits of virtual adress as segment offset and
the remaining 24 bits (of the current 64 bit virtual address) are used
to index the virtual segment. Out of the 24 bits we currently use 19 bits
for user context and that leave us with only 4 bits for effective segment
ID. In-order to support more than 16TB of memory we would require more than
4 ESID bits. This patch splits the virtual address to two unsigned long
components, vsid and segment offset thereby allowing us to support 78 bit
virtual address.

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/mmu-hash64.h |   62 ++++++++---
 arch/powerpc/mm/hash_low_64.S         |  191 ++++++++++++++++++---------------
 arch/powerpc/mm/hash_native_64.c      |   34 +++---
 arch/powerpc/mm/hash_utils_64.c       |    6 +-
 arch/powerpc/platforms/ps3/htab.c     |   13 +--
 arch/powerpc/platforms/pseries/lpar.c |   29 ++---
 6 files changed, 191 insertions(+), 144 deletions(-)

diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h
index 5ff936b..e563bd2 100644
--- a/arch/powerpc/include/asm/mmu-hash64.h
+++ b/arch/powerpc/include/asm/mmu-hash64.h
@@ -143,8 +143,10 @@ struct mmu_psize_def
 	unsigned long	sllp;	/* SLB L||LP (exact mask to use in slbmte) */
 };
 
+/* 78 bit power virtual address */
 struct virt_addr {
-	unsigned long addr;
+	unsigned long vsid;
+	unsigned long seg_off;
 };
 
 #endif /* __ASSEMBLY__ */
@@ -161,6 +163,13 @@ struct virt_addr {
 
 #ifndef __ASSEMBLY__
 
+static inline int segment_shift(int ssize)
+{
+	if (ssize == MMU_SEGSIZE_256M)
+		return SID_SHIFT;
+	return SID_SHIFT_1T;
+}
+
 /*
  * The current system page and segment sizes
  */
@@ -184,6 +193,32 @@ extern unsigned long tce_alloc_start, tce_alloc_end;
 extern int mmu_ci_restrictions;
 
 /*
+ * This computes the AVPN and B fields of the first dword of a HPTE,
+ * for use when we want to match an existing PTE.  The bottom 7 bits
+ * of the returned value are zero.
+ */
+static inline unsigned long hpte_encode_avpn(struct virt_addr va, int psize,
+					     int ssize)
+{
+	unsigned long v;
+
+	/*
+	 * The AVA field omits the low-order 23 bits of the 78 bits VA.
+	 * These bits are not needed in the PTE, because the
+	 * low-order b of these bits are part of the byte offset
+	 * into the virtual page and, if b < 23, the high-order
+	 * 23-b of these bits are always used in selecting the
+	 * PTEGs to be searched
+	 */
+	v = va.seg_off >> 23;
+	v |= va.vsid << (segment_shift(ssize) - 23);
+	v &= ~(mmu_psize_defs[psize].avpnm);
+	v <<= HPTE_V_AVPN_SHIFT;
+	v |= ((unsigned long) ssize) << HPTE_V_SSIZE_SHIFT;
+	return v;
+}
+
+/*
  * This function sets the AVPN and L fields of the HPTE  appropriately
  * for the page size
  */
@@ -191,11 +226,9 @@ static inline unsigned long hpte_encode_v(struct virt_addr va, int psize,
 					  int ssize)
 {
 	unsigned long v;
-	v = (va.addr >> 23) & ~(mmu_psize_defs[psize].avpnm);
-	v <<= HPTE_V_AVPN_SHIFT;
+	v = hpte_encode_avpn(va, psize, ssize);
 	if (psize != MMU_PAGE_4K)
 		v |= HPTE_V_LARGE;
-	v |= ((unsigned long) ssize) << HPTE_V_SSIZE_SHIFT;
 	return v;
 }
 
@@ -222,30 +255,31 @@ static inline unsigned long hpte_encode_r(unsigned long pa, int psize)
 /*
  * Build a VA given VSID, EA and segment size
  */
-static inline struct virt_addr hpt_va(unsigned long ea, unsigned long vsid,
-				   int ssize)
+static inline struct virt_addr hpt_va(unsigned long ea, unsigned long vsid, int ssize)
 {
 	struct virt_addr va;
+
+	va.vsid    = vsid;
 	if (ssize == MMU_SEGSIZE_256M)
-		va.addr = (vsid << 28) | (ea & 0xfffffffUL);
-	va.addr = (vsid << 40) | (ea & 0xffffffffffUL);
+		va.seg_off = ea & 0xfffffffUL;
+	else
+		va.seg_off = ea & 0xffffffffffUL;
 	return va;
 }
 
 /*
  * This hashes a virtual address
  */
-
-static inline unsigned long hpt_hash(struct virt_addr va, unsigned int shift,
-				     int ssize)
+/* Verify */
+static inline unsigned long hpt_hash(struct virt_addr va, unsigned int shift, int ssize)
 {
 	unsigned long hash, vsid;
 
 	if (ssize == MMU_SEGSIZE_256M) {
-		hash = (va.addr >> 28) ^ ((va.addr & 0x0fffffffUL) >> shift);
+		hash = va.vsid ^ (va.seg_off >> shift);
 	} else {
-		vsid = va.addr >> 40;
-		hash = vsid ^ (vsid << 25) ^ ((va.addr & 0xffffffffffUL) >> shift);
+		vsid = va.vsid;
+		hash = vsid ^ (vsid << 25) ^ (va.seg_off >> shift);
 	}
 	return hash & 0x7fffffffffUL;
 }
diff --git a/arch/powerpc/mm/hash_low_64.S b/arch/powerpc/mm/hash_low_64.S
index a242b5d..cf66a0a 100644
--- a/arch/powerpc/mm/hash_low_64.S
+++ b/arch/powerpc/mm/hash_low_64.S
@@ -71,10 +71,12 @@ _GLOBAL(__hash_page_4K)
 	/* Save non-volatile registers.
 	 * r31 will hold "old PTE"
 	 * r30 is "new PTE"
-	 * r29 is "va"
+	 * r29 is vsid
 	 * r28 is a hash value
 	 * r27 is hashtab mask (maybe dynamic patched instead ?)
+	 * r26 is seg_off
 	 */
+	std	r26,STK_REG(r26)(r1)
 	std	r27,STK_REG(r27)(r1)
 	std	r28,STK_REG(r28)(r1)
 	std	r29,STK_REG(r29)(r1)
@@ -119,10 +121,9 @@ BEGIN_FTR_SECTION
 	cmpdi	r9,0			/* check segment size */
 	bne	3f
 END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
-	/* Calc va and put it in r29 */
-	rldicr	r29,r5,28,63-28
-	rldicl	r3,r3,0,36
-	or	r29,r3,r29
+	/* r29 is virtual address and r26 is seg_off */
+	mr	r29,r5			/* vsid */
+	rldicl	r26,r3,0,36		/* ea & 0x000000000fffffffUL */
 
 	/* Calculate hash value for primary slot and store it in r28 */
 	rldicl	r5,r5,0,25		/* vsid & 0x0000007fffffffff */
@@ -130,14 +131,17 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
 	xor	r28,r5,r0
 	b	4f
 
-3:	/* Calc VA and hash in r29 and r28 for 1T segment */
-	sldi	r29,r5,40		/* vsid << 40 */
-	clrldi	r3,r3,24		/* ea & 0xffffffffff */
+3:	/* r29 is virtual address and r26 is seg_off */
+	mr	r29,r5			/* vsid */
+	rldicl	r26,r3,0,24		/* ea & 0xffffffffff */
+	/*
+	 * calculate hash value for primary slot and
+	 * store it in r28 for 1T segment
+	 */
 	rldic	r28,r5,25,25		/* (vsid << 25) & 0x7fffffffff */
 	clrldi	r5,r5,40		/* vsid & 0xffffff */
 	rldicl	r0,r3,64-12,36		/* (ea >> 12) & 0xfffffff */
 	xor	r28,r28,r5
-	or	r29,r3,r29		/* VA */
 	xor	r28,r28,r0		/* hash */
 
 	/* Convert linux PTE bits into HW equivalents */
@@ -183,20 +187,21 @@ htab_insert_pte:
 	andc	r30,r30,r0
 	ori	r30,r30,_PAGE_HASHPTE
 
-	/* physical address r5 */
-	rldicl	r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT
-	sldi	r5,r5,PAGE_SHIFT
+	/* physical address r6 */
+	rldicl	r6,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT
+	sldi	r6,r6,PAGE_SHIFT
 
 	/* Calculate primary group hash */
 	and	r0,r28,r27
 	rldicr	r3,r0,3,63-3		/* r3 = (hash & mask) << 3 */
 
 	/* Call ppc_md.hpte_insert */
-	ld	r6,STK_PARM(r4)(r1)	/* Retrieve new pp bits */
-	mr	r4,r29			/* Retrieve va */
-	li	r7,0			/* !bolted, !secondary */
-	li	r8,MMU_PAGE_4K		/* page size */
-	ld	r9,STK_PARM(r9)(r1)	/* segment size */
+	ld	r7,STK_PARM(r4)(r1)	/* Retrieve new pp bits */
+	mr	r4,r29			/* Retrieve vsid */
+	mr	r5,r26			/* seg_off */
+	li	r8,0			/* !bolted, !secondary */
+	li	r9,MMU_PAGE_4K		/* page size */
+	ld	r10,STK_PARM(r9)(r1)	/* segment size */
 _GLOBAL(htab_call_hpte_insert1)
 	bl	.			/* Patched by htab_finish_init() */
 	cmpdi	0,r3,0
@@ -206,20 +211,21 @@ _GLOBAL(htab_call_hpte_insert1)
 
 	/* Now try secondary slot */
 	
-	/* physical address r5 */
-	rldicl	r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT
-	sldi	r5,r5,PAGE_SHIFT
+	/* physical address r6 */
+	rldicl	r6,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT
+	sldi	r6,r6,PAGE_SHIFT
 
 	/* Calculate secondary group hash */
 	andc	r0,r27,r28
 	rldicr	r3,r0,3,63-3	/* r0 = (~hash & mask) << 3 */
 	
 	/* Call ppc_md.hpte_insert */
-	ld	r6,STK_PARM(r4)(r1)	/* Retrieve new pp bits */
-	mr	r4,r29			/* Retrieve va */
-	li	r7,HPTE_V_SECONDARY	/* !bolted, secondary */
-	li	r8,MMU_PAGE_4K		/* page size */
-	ld	r9,STK_PARM(r9)(r1)	/* segment size */
+	ld	r7,STK_PARM(r4)(r1)	/* Retrieve new pp bits */
+	mr	r4,r29			/* Retrieve vsid */
+	mr	r5,r26			/* seg_off */
+	li	r8,HPTE_V_SECONDARY	/* !bolted, secondary */
+	li	r9,MMU_PAGE_4K		/* page size */
+	ld	r10,STK_PARM(r9)(r1)	/* segment size */
 _GLOBAL(htab_call_hpte_insert2)
 	bl	.			/* Patched by htab_finish_init() */
 	cmpdi	0,r3,0
@@ -286,13 +292,13 @@ htab_modify_pte:
 	add	r3,r0,r3	/* add slot idx */
 
 	/* Call ppc_md.hpte_updatepp */
-	mr	r5,r29			/* va */
-	li	r6,MMU_PAGE_4K		/* page size */
-	ld	r7,STK_PARM(r9)(r1)	/* segment size */
-	ld	r8,STK_PARM(r8)(r1)	/* get "local" param */
+	mr	r5,r29			/* vsid */
+	mr	r6,r26			/* seg off */
+	li	r7,MMU_PAGE_4K		/* page size */
+	ld	r8,STK_PARM(r9)(r1)	/* segment size */
+	ld	r9,STK_PARM(r8)(r1)	/* get "local" param */
 _GLOBAL(htab_call_hpte_updatepp)
 	bl	.			/* Patched by htab_finish_init() */
-
 	/* if we failed because typically the HPTE wasn't really here
 	 * we try an insertion. 
 	 */
@@ -347,12 +353,14 @@ _GLOBAL(__hash_page_4K)
 	/* Save non-volatile registers.
 	 * r31 will hold "old PTE"
 	 * r30 is "new PTE"
-	 * r29 is "va"
+	 * r29 is vsid
 	 * r28 is a hash value
 	 * r27 is hashtab mask (maybe dynamic patched instead ?)
 	 * r26 is the hidx mask
 	 * r25 is the index in combo page
+	 * r24 is seg_off
 	 */
+	std	r24,STK_REG(r24)(r1)
 	std	r25,STK_REG(r25)(r1)
 	std	r26,STK_REG(r26)(r1)
 	std	r27,STK_REG(r27)(r1)
@@ -402,10 +410,9 @@ BEGIN_FTR_SECTION
 	cmpdi	r9,0			/* check segment size */
 	bne	3f
 END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
-	/* Calc va and put it in r29 */
-	rldicr	r29,r5,28,63-28		/* r29 = (vsid << 28) */
-	rldicl	r3,r3,0,36		/* r3 = (ea & 0x0fffffff) */
-	or	r29,r3,r29		/* r29 = va */
+	/* r29 is virtual address and r24 is seg_off */
+	mr	r29,r5			/* vsid */
+	rldicl	r24,r3,0,36		/* ea & 0x000000000fffffffUL */
 
 	/* Calculate hash value for primary slot and store it in r28 */
 	rldicl	r5,r5,0,25		/* vsid & 0x0000007fffffffff */
@@ -413,14 +420,17 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
 	xor	r28,r5,r0
 	b	4f
 
-3:	/* Calc VA and hash in r29 and r28 for 1T segment */
-	sldi	r29,r5,40		/* vsid << 40 */
-	clrldi	r3,r3,24		/* ea & 0xffffffffff */
+3:	/* r29 is virtual address and r24 is seg_off */
+	mr	r29,r5			/* vsid */
+	rldicl	r24,r3,0,24		/* ea & 0xffffffffff */
+	/*
+	 * Calculate hash value for primary slot and
+	 * store it in r28  for 1T segment
+	 */
 	rldic	r28,r5,25,25		/* (vsid << 25) & 0x7fffffffff */
 	clrldi	r5,r5,40		/* vsid & 0xffffff */
 	rldicl	r0,r3,64-12,36		/* (ea >> 12) & 0xfffffff */
 	xor	r28,r28,r5
-	or	r29,r3,r29		/* VA */
 	xor	r28,r28,r0		/* hash */
 
 	/* Convert linux PTE bits into HW equivalents */
@@ -481,25 +491,26 @@ END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE)
 	bne	htab_modify_pte
 
 htab_insert_pte:
-	/* real page number in r5, PTE RPN value + index */
+	/* real page number in r6, PTE RPN value + index */
 	andis.	r0,r31,_PAGE_4K_PFN@h
 	srdi	r5,r31,PTE_RPN_SHIFT
 	bne-	htab_special_pfn
 	sldi	r5,r5,PAGE_SHIFT-HW_PAGE_SHIFT
 	add	r5,r5,r25
 htab_special_pfn:
-	sldi	r5,r5,HW_PAGE_SHIFT
+	sldi	r6,r5,HW_PAGE_SHIFT
 
 	/* Calculate primary group hash */
 	and	r0,r28,r27
 	rldicr	r3,r0,3,63-3		/* r0 = (hash & mask) << 3 */
 
 	/* Call ppc_md.hpte_insert */
-	ld	r6,STK_PARM(r4)(r1)	/* Retrieve new pp bits */
-	mr	r4,r29			/* Retrieve va */
-	li	r7,0			/* !bolted, !secondary */
-	li	r8,MMU_PAGE_4K		/* page size */
-	ld	r9,STK_PARM(r9)(r1)	/* segment size */
+	ld	r7,STK_PARM(r4)(r1)	/* Retrieve new pp bits */
+	mr	r4,r29			/* Retrieve vsid */
+	mr      r5,r24			/* seg off */
+	li	r8,0			/* !bolted, !secondary */
+	li	r9,MMU_PAGE_4K		/* page size */
+	ld	r10,STK_PARM(r9)(r1)	/* segment size */
 _GLOBAL(htab_call_hpte_insert1)
 	bl	.			/* patched by htab_finish_init() */
 	cmpdi	0,r3,0
@@ -515,18 +526,19 @@ _GLOBAL(htab_call_hpte_insert1)
 	bne-	3f
 	sldi	r5,r5,PAGE_SHIFT-HW_PAGE_SHIFT
 	add	r5,r5,r25
-3:	sldi	r5,r5,HW_PAGE_SHIFT
+3:	sldi	r6,r5,HW_PAGE_SHIFT
 
 	/* Calculate secondary group hash */
 	andc	r0,r27,r28
 	rldicr	r3,r0,3,63-3		/* r0 = (~hash & mask) << 3 */
 
 	/* Call ppc_md.hpte_insert */
-	ld	r6,STK_PARM(r4)(r1)	/* Retrieve new pp bits */
-	mr	r4,r29			/* Retrieve va */
-	li	r7,HPTE_V_SECONDARY	/* !bolted, secondary */
-	li	r8,MMU_PAGE_4K		/* page size */
-	ld	r9,STK_PARM(r9)(r1)	/* segment size */
+	ld	r7,STK_PARM(r4)(r1)	/* Retrieve new pp bits */
+	mr	r4,r29			/* Retrieve vsid */
+	mr      r5,r24			/* seg off */
+	li	r8,HPTE_V_SECONDARY	/* !bolted, secondary */
+	li	r9,MMU_PAGE_4K		/* page size */
+	ld	r10,STK_PARM(r9)(r1)	/* segment size */
 _GLOBAL(htab_call_hpte_insert2)
 	bl	.			/* patched by htab_finish_init() */
 	cmpdi	0,r3,0
@@ -628,13 +640,13 @@ htab_modify_pte:
 	add	r3,r0,r3	/* add slot idx */
 
 	/* Call ppc_md.hpte_updatepp */
-	mr	r5,r29			/* va */
-	li	r6,MMU_PAGE_4K		/* page size */
-	ld	r7,STK_PARM(r9)(r1)	/* segment size */
-	ld	r8,STK_PARM(r8)(r1)	/* get "local" param */
+	mr	r5,r29			/* vsid */
+	mr      r6,r24			/* seg off */
+	li	r7,MMU_PAGE_4K		/* page size */
+	ld	r8,STK_PARM(r9)(r1)	/* segment size */
+	ld	r9,STK_PARM(r8)(r1)	/* get "local" param */
 _GLOBAL(htab_call_hpte_updatepp)
 	bl	.			/* patched by htab_finish_init() */
-
 	/* if we failed because typically the HPTE wasn't really here
 	 * we try an insertion.
 	 */
@@ -684,10 +696,12 @@ _GLOBAL(__hash_page_64K)
 	/* Save non-volatile registers.
 	 * r31 will hold "old PTE"
 	 * r30 is "new PTE"
-	 * r29 is "va"
+	 * r29 is vsid
 	 * r28 is a hash value
 	 * r27 is hashtab mask (maybe dynamic patched instead ?)
+	 * r26 is seg off
 	 */
+	std	r26,STK_REG(r26)(r1)
 	std	r27,STK_REG(r27)(r1)
 	std	r28,STK_REG(r28)(r1)
 	std	r29,STK_REG(r29)(r1)
@@ -737,10 +751,9 @@ BEGIN_FTR_SECTION
 	cmpdi	r9,0			/* check segment size */
 	bne	3f
 END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
-	/* Calc va and put it in r29 */
-	rldicr	r29,r5,28,63-28
-	rldicl	r3,r3,0,36
-	or	r29,r3,r29
+	/* r29 is virtual address and r26 is seg_off */
+	mr	r29,r5			/* vsid */
+	rldicl	r26,r3,0,36		/* ea & 0x000000000fffffffUL */
 
 	/* Calculate hash value for primary slot and store it in r28 */
 	rldicl	r5,r5,0,25		/* vsid & 0x0000007fffffffff */
@@ -748,14 +761,17 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
 	xor	r28,r5,r0
 	b	4f
 
-3:	/* Calc VA and hash in r29 and r28 for 1T segment */
-	sldi	r29,r5,40		/* vsid << 40 */
-	clrldi	r3,r3,24		/* ea & 0xffffffffff */
+3:	/* r29 is virtual address and r26 is seg_off */
+	mr	r29,r5			/* vsid */
+	rldicl	r26,r3,0,24		/* ea & 0xffffffffff */
+	/*
+	 * calculate hash value for primary slot and
+	 * store it in r28 for 1T segment
+	 */
 	rldic	r28,r5,25,25		/* (vsid << 25) & 0x7fffffffff */
 	clrldi	r5,r5,40		/* vsid & 0xffffff */
 	rldicl	r0,r3,64-16,40		/* (ea >> 16) & 0xffffff */
 	xor	r28,r28,r5
-	or	r29,r3,r29		/* VA */
 	xor	r28,r28,r0		/* hash */
 
 	/* Convert linux PTE bits into HW equivalents */
@@ -804,20 +820,21 @@ ht64_insert_pte:
 #else
 	ori	r30,r30,_PAGE_HASHPTE
 #endif
-	/* Phyical address in r5 */
-	rldicl	r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT
-	sldi	r5,r5,PAGE_SHIFT
+	/* Phyical address in r6 */
+	rldicl	r6,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT
+	sldi	r6,r6,PAGE_SHIFT
 
 	/* Calculate primary group hash */
 	and	r0,r28,r27
 	rldicr	r3,r0,3,63-3	/* r0 = (hash & mask) << 3 */
 
 	/* Call ppc_md.hpte_insert */
-	ld	r6,STK_PARM(r4)(r1)	/* Retrieve new pp bits */
-	mr	r4,r29			/* Retrieve va */
-	li	r7,0			/* !bolted, !secondary */
-	li	r8,MMU_PAGE_64K
-	ld	r9,STK_PARM(r9)(r1)	/* segment size */
+	ld	r7,STK_PARM(r4)(r1)	/* Retrieve new pp bits */
+	mr	r4,r29			/* Retrieve vsid */
+	mr	r5,r26			/* seg_off */
+	li	r8,0			/* !bolted, !secondary */
+	li	r9,MMU_PAGE_64K
+	ld	r10,STK_PARM(r9)(r1)	/* segment size */
 _GLOBAL(ht64_call_hpte_insert1)
 	bl	.			/* patched by htab_finish_init() */
 	cmpdi	0,r3,0
@@ -827,20 +844,21 @@ _GLOBAL(ht64_call_hpte_insert1)
 
 	/* Now try secondary slot */
 
-	/* Phyical address in r5 */
-	rldicl	r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT
-	sldi	r5,r5,PAGE_SHIFT
+	/* Phyical address in r6 */
+	rldicl	r6,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT
+	sldi	r6,r6,PAGE_SHIFT
 
 	/* Calculate secondary group hash */
 	andc	r0,r27,r28
 	rldicr	r3,r0,3,63-3	/* r0 = (~hash & mask) << 3 */
 
 	/* Call ppc_md.hpte_insert */
-	ld	r6,STK_PARM(r4)(r1)	/* Retrieve new pp bits */
-	mr	r4,r29			/* Retrieve va */
-	li	r7,HPTE_V_SECONDARY	/* !bolted, secondary */
-	li	r8,MMU_PAGE_64K
-	ld	r9,STK_PARM(r9)(r1)	/* segment size */
+	ld	r7,STK_PARM(r4)(r1)	/* Retrieve new pp bits */
+	mr	r4,r29			/* Retrieve vsid */
+	mr	r5,r26			/* seg_off */
+	li	r8,HPTE_V_SECONDARY	/* !bolted, secondary */
+	li	r9,MMU_PAGE_64K
+	ld	r10,STK_PARM(r9)(r1)	/* segment size */
 _GLOBAL(ht64_call_hpte_insert2)
 	bl	.			/* patched by htab_finish_init() */
 	cmpdi	0,r3,0
@@ -907,10 +925,11 @@ ht64_modify_pte:
 	add	r3,r0,r3	/* add slot idx */
 
 	/* Call ppc_md.hpte_updatepp */
-	mr	r5,r29			/* va */
-	li	r6,MMU_PAGE_64K
-	ld	r7,STK_PARM(r9)(r1)	/* segment size */
-	ld	r8,STK_PARM(r8)(r1)	/* get "local" param */
+	mr	r5,r29			/* vsid */
+	mr	r6,r26			/* seg off */
+	li	r7,MMU_PAGE_64K
+	ld	r8,STK_PARM(r9)(r1)	/* segment size */
+	ld	r9,STK_PARM(r8)(r1)	/* get "local" param */
 _GLOBAL(ht64_call_hpte_updatepp)
 	bl	.			/* patched by htab_finish_init() */
 
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index 76c2574..f3628f8 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -42,10 +42,12 @@ DEFINE_RAW_SPINLOCK(native_tlbie_lock);
 /* Verify docs says 14 .. 14+i bits */
 static inline void __tlbie(struct virt_addr va, int psize, int ssize)
 {
-	unsigned long vaddr = va.addr;
+	unsigned long vaddr;
 	unsigned int penc;
 
-	vaddr &= ~(0xffffULL << 48);
+	/* We need only lower 48 bit of va, non SLS segment */
+	vaddr = va.vsid << segment_shift(ssize);
+	vaddr |= va.seg_off;
 
 	/* clear top 16 bits, non SLS segment */
 	vaddr &= ~(0xffffULL << 48);
@@ -74,9 +76,13 @@ static inline void __tlbie(struct virt_addr va, int psize, int ssize)
 /* Verify docs says 14 .. 14+i bits */
 static inline void __tlbiel(struct virt_addr va, int psize, int ssize)
 {
-	unsigned long vaddr = va.addr;
+	unsigned long vaddr;
 	unsigned int penc;
 
+	/* We need only lower 48 bit of va, non SLS segment */
+	vaddr = va.vsid << segment_shift(ssize);
+	vaddr |= va.seg_off;
+
 	vaddr &= ~(0xffffULL << 48);
 
 	switch (psize) {
@@ -148,9 +154,9 @@ static long native_hpte_insert(unsigned long hpte_group, struct virt_addr va,
 	int i;
 
 	if (!(vflags & HPTE_V_BOLTED)) {
-		DBG_LOW("    insert(group=%lx, va=%016lx, pa=%016lx,"
-			" rflags=%lx, vflags=%lx, psize=%d)\n",
-			hpte_group, va, pa, rflags, vflags, psize);
+		DBG_LOW("    insert(group=%lx, vsid=%016lx, seg_off=%016lx, pa=%016lx,"
+			" rflags=%lx, vflags=%lx, psize=%d)\n", hpte_group,
+			va.vsid, va.seg_off, pa, rflags, vflags, psize);
 	}
 
 	for (i = 0; i < HPTES_PER_GROUP; i++) {
@@ -239,8 +245,9 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
 
 	want_v = hpte_encode_v(va, psize, ssize);
 
-	DBG_LOW("    update(va=%016lx, avpnv=%016lx, hash=%016lx, newpp=%x)",
-		va, want_v & HPTE_V_AVPN, slot, newpp);
+	DBG_LOW("    update(vsid=%016lx, seg_off=%016lx, avpnv=%016lx, "
+		"hash=%016lx, newpp=%x)", va.vsid, va.seg_off,
+		want_v & HPTE_V_AVPN, slot, newpp);
 
 	native_lock_hpte(hptep);
 
@@ -405,7 +412,6 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
 			vpi = (vsid ^ pteg) & htab_hash_mask;
 			seg_off |= vpi << shift;
 		}
-		va->addr = vsid << 28 | seg_off;
 	case MMU_SEGSIZE_1T:
 		/* We only have 40 - 23 bits of seg_off in avpn */
 		seg_off = (avpn & 0x1ffff) << 23;
@@ -414,12 +420,12 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
 			vpi = (vsid ^ (vsid << 25) ^ pteg) & htab_hash_mask;
 			seg_off |= vpi << shift;
 		}
-		va->addr = vsid << 40 | seg_off;
 	default:
 		seg_off = 0;
 		vsid    = 0;
-		va->addr = 0;
 	}
+	va->vsid = vsid;
+	va->seg_off = seg_off;
 	*psize = size;
 }
 
@@ -499,7 +505,7 @@ static void native_flush_hash_range(unsigned long number, int local)
 		va = batch->vaddr[i];
 		pte = batch->pte[i];
 
-		pte_iterate_hashed_subpages(pte, psize, va.addr, index, shift) {
+		pte_iterate_hashed_subpages(pte, psize, va.seg_off, index, shift) {
 			hash = hpt_hash(va, shift, ssize);
 			hidx = __rpte_to_hidx(pte, index);
 			if (hidx & _PTEIDX_SECONDARY)
@@ -525,7 +531,7 @@ static void native_flush_hash_range(unsigned long number, int local)
 			va = batch->vaddr[i];
 			pte = batch->pte[i];
 
-			pte_iterate_hashed_subpages(pte, psize, va.addr, index,
+			pte_iterate_hashed_subpages(pte, psize, va.seg_off, index,
 						    shift) {
 				__tlbiel(va, psize, ssize);
 			} pte_iterate_hashed_end();
@@ -542,7 +548,7 @@ static void native_flush_hash_range(unsigned long number, int local)
 			va = batch->vaddr[i];
 			pte = batch->pte[i];
 
-			pte_iterate_hashed_subpages(pte, psize, va.addr, index,
+			pte_iterate_hashed_subpages(pte, psize, va.seg_off, index,
 						    shift) {
 				__tlbie(va, psize, ssize);
 			} pte_iterate_hashed_end();
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 2429d53..8b5d3c2 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -1158,8 +1158,10 @@ void flush_hash_page(struct virt_addr va, real_pte_t pte, int psize, int ssize,
 {
 	unsigned long hash, index, shift, hidx, slot;
 
-	DBG_LOW("flush_hash_page(va=%016lx)\n", va.addr);
-	pte_iterate_hashed_subpages(pte, psize, va.addr, index, shift) {
+	DBG_LOW("flush_hash_page(vsid=%016lx seg_off=%016lx)\n",
+		va.vsid, va.seg_off);
+	/* since we won't cross segments, use seg_off for iteration */
+	pte_iterate_hashed_subpages(pte, psize, va.seg_off, index, shift) {
 		hash = hpt_hash(va, shift, ssize);
 		hidx = __rpte_to_hidx(pte, index);
 		if (hidx & _PTEIDX_SECONDARY)
diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c
index 6e27576..4aa969d 100644
--- a/arch/powerpc/platforms/ps3/htab.c
+++ b/arch/powerpc/platforms/ps3/htab.c
@@ -75,8 +75,9 @@ static long ps3_hpte_insert(unsigned long hpte_group, struct virt_addr va,
 
 	if (result) {
 		/* all entries bolted !*/
-		pr_info("%s:result=%d va=%lx pa=%lx ix=%lx v=%llx r=%llx\n",
-			__func__, result, va, pa, hpte_group, hpte_v, hpte_r);
+		pr_info("%s:result=%d vsid=%lx seg_off=%lx pa=%lx ix=%lx "
+			"v=%llx r=%llx\n", __func__, result, va.vsid,
+			va.seg_off, pa, hpte_group, hpte_v, hpte_r);
 		BUG();
 	}
 
@@ -125,8 +126,8 @@ static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp,
 				       &hpte_rs);
 
 	if (result) {
-		pr_info("%s: res=%d read va=%lx slot=%lx psize=%d\n",
-			__func__, result, va, slot, psize);
+		pr_info("%s: res=%d read vsid=%lx seg_off=%lx slot=%lx psize=%d\n",
+			__func__, result, va.vsid, va.seg_off, slot, psize);
 		BUG();
 	}
 
@@ -170,8 +171,8 @@ static void ps3_hpte_invalidate(unsigned long slot, struct virt_addr va,
 	result = lv1_write_htab_entry(PS3_LPAR_VAS_ID_CURRENT, slot, 0, 0);
 
 	if (result) {
-		pr_info("%s: res=%d va=%lx slot=%lx psize=%d\n",
-			__func__, result, va, slot, psize);
+		pr_info("%s: res=%d vsid=%lx seg_off=%lx slot=%lx psize=%d\n",
+			__func__, result, va.vsid, va.seg_off, slot, psize);
 		BUG();
 	}
 
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index b4e9641..4c0848f 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -118,9 +118,10 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
 	unsigned long hpte_v, hpte_r;
 
 	if (!(vflags & HPTE_V_BOLTED))
-		pr_devel("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
-			 "rflags=%lx, vflags=%lx, psize=%d)\n",
-			 hpte_group, va.addr, pa, rflags, vflags, psize);
+		pr_devel("hpte_insert(group=%lx, vsid=%016lx, segoff=%016lx, "
+			 "pa=%016lx, rflags=%lx, vflags=%lx, psize=%d)\n",
+			 hpte_group, va.vsid, va.seg_off,
+			 pa, rflags, vflags, psize);
 
 	hpte_v = hpte_encode_v(va, psize, ssize) | vflags | HPTE_V_VALID;
 	hpte_r = hpte_encode_r(pa, psize) | rflags;
@@ -227,22 +228,6 @@ static void pSeries_lpar_hptab_clear(void)
 }
 
 /*
- * This computes the AVPN and B fields of the first dword of a HPTE,
- * for use when we want to match an existing PTE.  The bottom 7 bits
- * of the returned value are zero.
- */
-static inline unsigned long hpte_encode_avpn(struct virt_addr va, int psize,
-					     int ssize)
-{
-	unsigned long v;
-
-	v = (va.addr >> 23) & ~(mmu_psize_defs[psize].avpnm);
-	v <<= HPTE_V_AVPN_SHIFT;
-	v |= ((unsigned long) ssize) << HPTE_V_SSIZE_SHIFT;
-	return v;
-}
-
-/*
  * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and
  * the low 3 bits of flags happen to line up.  So no transform is needed.
  * We can probably optimize here and assume the high bits of newpp are
@@ -345,8 +330,8 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, struct virt_addr va
 	unsigned long lpar_rc;
 	unsigned long dummy1, dummy2;
 
-	pr_devel("    inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
-		 slot, va.addr, psize, local);
+	pr_devel("    inval : slot=%lx, vsid=%016lx, seg_off=%016lx, psize: %d, local: %d\n",
+		 slot, va.vsid, va.seg_off, psize, local);
 
 	want_v = hpte_encode_avpn(va, psize, ssize);
 	lpar_rc = plpar_pte_remove(H_AVPN, slot, want_v, &dummy1, &dummy2);
@@ -403,7 +388,7 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
 	for (i = 0; i < number; i++) {
 		va = batch->vaddr[i];
 		pte = batch->pte[i];
-		pte_iterate_hashed_subpages(pte, psize, va.addr, index, shift) {
+		pte_iterate_hashed_subpages(pte, psize, va.seg_off, index, shift) {
 			hash = hpt_hash(va, shift, ssize);
 			hidx = __rpte_to_hidx(pte, index);
 			if (hidx & _PTEIDX_SECONDARY)
-- 
1.7.10

^ permalink raw reply related

* [Early RFC 5/6] arch/powerpc: Make KERN_VIRT_SIZE not dependend on PGTABLE_RANGE
From: Aneesh Kumar K.V @ 2012-05-31 19:50 UTC (permalink / raw)
  To: benh, paulus, michael, anton; +Cc: linuxppc-dev, Aneesh Kumar K.V
In-Reply-To: <1338493841-9926-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com>

From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>

As we keep increasing PGTABLE_RANGE we need not increase the virual
map area for kernel.

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/pgtable-ppc64.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/powerpc/include/asm/pgtable-ppc64.h b/arch/powerpc/include/asm/pgtable-ppc64.h
index c420561..8af1cf2 100644
--- a/arch/powerpc/include/asm/pgtable-ppc64.h
+++ b/arch/powerpc/include/asm/pgtable-ppc64.h
@@ -41,7 +41,7 @@
 #else
 #define KERN_VIRT_START ASM_CONST(0xD000000000000000)
 #endif
-#define KERN_VIRT_SIZE	PGTABLE_RANGE
+#define KERN_VIRT_SIZE	ASM_CONST(0x0000100000000000)
 
 /*
  * The vmalloc space starts at the beginning of that region, and
-- 
1.7.10

^ permalink raw reply related

* [Early RFC 6/6] arch/powerpc: Increase the slice range to 64TB
From: Aneesh Kumar K.V @ 2012-05-31 19:50 UTC (permalink / raw)
  To: benh, paulus, michael, anton; +Cc: linuxppc-dev, Aneesh Kumar K.V
In-Reply-To: <1338493841-9926-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com>

From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>

This patch makes the high psizes mask as an unsigned char array
so that we can have more than 16TB. Currently we support upto
64TB

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/mmu-hash64.h |    7 ++-
 arch/powerpc/include/asm/page_64.h    |    7 ++-
 arch/powerpc/mm/hash_utils_64.c       |   15 +++---
 arch/powerpc/mm/slb_low.S             |   35 ++++++++----
 arch/powerpc/mm/slice.c               |   95 +++++++++++++++++++++------------
 5 files changed, 109 insertions(+), 50 deletions(-)

diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h
index e563bd2..0f8b10d 100644
--- a/arch/powerpc/include/asm/mmu-hash64.h
+++ b/arch/powerpc/include/asm/mmu-hash64.h
@@ -456,7 +456,12 @@ typedef struct {
 
 #ifdef CONFIG_PPC_MM_SLICES
 	u64 low_slices_psize;	/* SLB page size encodings */
-	u64 high_slices_psize;  /* 4 bits per slice for now */
+	/*
+	 * FIXME!! it should be derived from PGTABLE_RANGE
+	 * Right now we support 64TB and 4 bits for each
+	 * 1TB slice we need 32 bytes for 64TB.
+	 */
+	unsigned char high_slices_psize[32];  /* 4 bits per slice for now */
 #else
 	u16 sllp;		/* SLB page size encoding */
 #endif
diff --git a/arch/powerpc/include/asm/page_64.h b/arch/powerpc/include/asm/page_64.h
index fed85e6..8806e87 100644
--- a/arch/powerpc/include/asm/page_64.h
+++ b/arch/powerpc/include/asm/page_64.h
@@ -82,7 +82,12 @@ extern u64 ppc64_pft_size;
 
 struct slice_mask {
 	u16 low_slices;
-	u16 high_slices;
+	/*
+	 * FIXME!!
+	 * This should be derived out of PGTABLE_RANGE. For the current
+	 * max 64TB, u64 should be ok.
+	 */
+	u64 high_slices;
 };
 
 struct mm_struct;
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 8b5d3c2..beace0b 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -804,16 +804,19 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap)
 #ifdef CONFIG_PPC_MM_SLICES
 unsigned int get_paca_psize(unsigned long addr)
 {
-	unsigned long index, slices;
+	u64 lpsizes;
+	unsigned char *hpsizes;
+	unsigned long index, mask_index;
 
 	if (addr < SLICE_LOW_TOP) {
-		slices = get_paca()->context.low_slices_psize;
+		lpsizes = get_paca()->context.low_slices_psize;
 		index = GET_LOW_SLICE_INDEX(addr);
-	} else {
-		slices = get_paca()->context.high_slices_psize;
-		index = GET_HIGH_SLICE_INDEX(addr);
+		return (lpsizes >> (index * 4)) & 0xF;
 	}
-	return (slices >> (index * 4)) & 0xF;
+	hpsizes = get_paca()->context.high_slices_psize;
+	index = GET_HIGH_SLICE_INDEX(addr) >> 1;
+	mask_index = GET_HIGH_SLICE_INDEX(addr) - (index << 1);
+	return (hpsizes[index] >> (mask_index * 4)) & 0xF;
 }
 
 #else
diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S
index b9ee79ce..c355af6 100644
--- a/arch/powerpc/mm/slb_low.S
+++ b/arch/powerpc/mm/slb_low.S
@@ -108,17 +108,34 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT)
 	 * between 4k and 64k standard page size
 	 */
 #ifdef CONFIG_PPC_MM_SLICES
+	/* r10 have esid */
 	cmpldi	r10,16
-
-	/* Get the slice index * 4 in r11 and matching slice size mask in r9 */
-	ld	r9,PACALOWSLICESPSIZE(r13)
-	sldi	r11,r10,2
+	/* below SLICE_LOW_TOP */
 	blt	5f
-	ld	r9,PACAHIGHSLICEPSIZE(r13)
-	srdi	r11,r10,(SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT - 2)
-	andi.	r11,r11,0x3c
-
-5:	/* Extract the psize and multiply to get an array offset */
+	/*
+	 * Handle hpsizes,
+	 * r9 is get_paca()->context.high_slices_psize[index], r11 is mask_index
+	 * We use r10 here, later we restore it to esid.
+	 * Can we use other register instead of r10 ?
+	 */
+	srdi    r10,r10,(SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT) /* index */
+	srdi	r11,r10,1			/* r11 is array index */
+	addi	r9,r11,PACAHIGHSLICEPSIZE
+	lbzx	r9,r9,r13			/* r9 is hpsizes[r11] */
+	sldi    r11,r11,1
+	subf	r11,r11,r10	/* mask_index = index - (array_index << 1) */
+	srdi	r10,r3,28	/* restore r10 with esid */
+	b	6f
+5:
+	/*
+	 * Handle lpsizes
+	 * r9 is get_paca()->context.low_slices_psize, r11 is index
+	 */
+	ld	r9,PACALOWSLICESPSIZE(r13)
+	mr	r11,r10
+6:
+	sldi	r11,r11,2  /* index * 4 */
+	/* Extract the psize and multiply to get an array offset */
 	srd	r9,r9,r11
 	andi.	r9,r9,0xf
 	mulli	r9,r9,MMUPSIZEDEFSIZE
diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c
index 73709f7..302a481 100644
--- a/arch/powerpc/mm/slice.c
+++ b/arch/powerpc/mm/slice.c
@@ -42,7 +42,7 @@ int _slice_debug = 1;
 
 static void slice_print_mask(const char *label, struct slice_mask mask)
 {
-	char	*p, buf[16 + 3 + 16 + 1];
+	char	*p, buf[16 + 3 + 64 + 1];
 	int	i;
 
 	if (!_slice_debug)
@@ -142,19 +142,24 @@ static struct slice_mask slice_mask_for_free(struct mm_struct *mm)
 
 static struct slice_mask slice_mask_for_size(struct mm_struct *mm, int psize)
 {
+	unsigned char *hpsizes;
+	int index, mask_index;
 	struct slice_mask ret = { 0, 0 };
 	unsigned long i;
-	u64 psizes;
+	u64 lpsizes;
 
-	psizes = mm->context.low_slices_psize;
+	lpsizes = mm->context.low_slices_psize;
 	for (i = 0; i < SLICE_NUM_LOW; i++)
-		if (((psizes >> (i * 4)) & 0xf) == psize)
+		if (((lpsizes >> (i * 4)) & 0xf) == psize)
 			ret.low_slices |= 1u << i;
 
-	psizes = mm->context.high_slices_psize;
-	for (i = 0; i < SLICE_NUM_HIGH; i++)
-		if (((psizes >> (i * 4)) & 0xf) == psize)
+	hpsizes = mm->context.high_slices_psize;
+	for (i = 0; i < SLICE_NUM_HIGH; i++) {
+		index = i >> 1;
+		mask_index = i - (index << 1);
+		if (((hpsizes[index] >> (mask_index * 4)) & 0xf) == psize)
 			ret.high_slices |= 1u << i;
+	}
 
 	return ret;
 }
@@ -183,8 +188,10 @@ static void slice_flush_segments(void *parm)
 
 static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psize)
 {
+	int index, mask_index;
 	/* Write the new slice psize bits */
-	u64 lpsizes, hpsizes;
+	unsigned char *hpsizes;
+	u64 lpsizes;
 	unsigned long i, flags;
 
 	slice_dbg("slice_convert(mm=%p, psize=%d)\n", mm, psize);
@@ -201,14 +208,18 @@ static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psiz
 			lpsizes = (lpsizes & ~(0xful << (i * 4))) |
 				(((unsigned long)psize) << (i * 4));
 
+	/* Assign the value back */
+	mm->context.low_slices_psize = lpsizes;
+
 	hpsizes = mm->context.high_slices_psize;
-	for (i = 0; i < SLICE_NUM_HIGH; i++)
+	for (i = 0; i < SLICE_NUM_HIGH; i++) {
+		index = i >> 1;
+		mask_index = i - (index << 1);
 		if (mask.high_slices & (1u << i))
-			hpsizes = (hpsizes & ~(0xful << (i * 4))) |
-				(((unsigned long)psize) << (i * 4));
-
-	mm->context.low_slices_psize = lpsizes;
-	mm->context.high_slices_psize = hpsizes;
+			hpsizes[index] = (hpsizes[index] &
+					  ~(0xf << (mask_index * 4))) |
+				(((unsigned long)psize) << (mask_index * 4));
+	}
 
 	slice_dbg(" lsps=%lx, hsps=%lx\n",
 		  mm->context.low_slices_psize,
@@ -587,18 +598,19 @@ unsigned long arch_get_unmapped_area_topdown(struct file *filp,
 
 unsigned int get_slice_psize(struct mm_struct *mm, unsigned long addr)
 {
-	u64 psizes;
-	int index;
+	unsigned char *hpsizes;
+	int index, mask_index;
 
 	if (addr < SLICE_LOW_TOP) {
-		psizes = mm->context.low_slices_psize;
+		u64 lpsizes;
+		lpsizes = mm->context.low_slices_psize;
 		index = GET_LOW_SLICE_INDEX(addr);
-	} else {
-		psizes = mm->context.high_slices_psize;
-		index = GET_HIGH_SLICE_INDEX(addr);
+		return (lpsizes >> (index * 4)) & 0xf;
 	}
-
-	return (psizes >> (index * 4)) & 0xf;
+	hpsizes = mm->context.high_slices_psize;
+	index = GET_HIGH_SLICE_INDEX(addr) >> 1;
+	mask_index = GET_HIGH_SLICE_INDEX(addr) - (index << 1);
+	return (hpsizes[index] >> (mask_index * 4)) & 0xf;
 }
 EXPORT_SYMBOL_GPL(get_slice_psize);
 
@@ -618,7 +630,9 @@ EXPORT_SYMBOL_GPL(get_slice_psize);
  */
 void slice_set_user_psize(struct mm_struct *mm, unsigned int psize)
 {
-	unsigned long flags, lpsizes, hpsizes;
+	int index, mask_index;
+	unsigned char *hpsizes;
+	unsigned long flags, lpsizes;
 	unsigned int old_psize;
 	int i;
 
@@ -639,15 +653,21 @@ void slice_set_user_psize(struct mm_struct *mm, unsigned int psize)
 		if (((lpsizes >> (i * 4)) & 0xf) == old_psize)
 			lpsizes = (lpsizes & ~(0xful << (i * 4))) |
 				(((unsigned long)psize) << (i * 4));
+	/* Assign the value back */
+	mm->context.low_slices_psize = lpsizes;
 
 	hpsizes = mm->context.high_slices_psize;
-	for (i = 0; i < SLICE_NUM_HIGH; i++)
-		if (((hpsizes >> (i * 4)) & 0xf) == old_psize)
-			hpsizes = (hpsizes & ~(0xful << (i * 4))) |
-				(((unsigned long)psize) << (i * 4));
+	for (i = 0; i < SLICE_NUM_HIGH; i++) {
+		index = i >> 1;
+		mask_index = i - (index << 1);
+		if (((hpsizes[index] >> (mask_index * 4)) & 0xf) == old_psize)
+			hpsizes[index] = (hpsizes[index] &
+					  ~(0xf << (mask_index * 4))) |
+				(((unsigned long)psize) << (mask_index * 4));
+	}
+
+
 
-	mm->context.low_slices_psize = lpsizes;
-	mm->context.high_slices_psize = hpsizes;
 
 	slice_dbg(" lsps=%lx, hsps=%lx\n",
 		  mm->context.low_slices_psize,
@@ -660,18 +680,27 @@ void slice_set_user_psize(struct mm_struct *mm, unsigned int psize)
 void slice_set_psize(struct mm_struct *mm, unsigned long address,
 		     unsigned int psize)
 {
+	unsigned char *hpsizes;
 	unsigned long i, flags;
-	u64 *p;
+	u64 *lpsizes;
 
 	spin_lock_irqsave(&slice_convert_lock, flags);
 	if (address < SLICE_LOW_TOP) {
 		i = GET_LOW_SLICE_INDEX(address);
-		p = &mm->context.low_slices_psize;
+		lpsizes = &mm->context.low_slices_psize;
+		*lpsizes = (*lpsizes & ~(0xful << (i * 4))) |
+			((unsigned long) psize << (i * 4));
 	} else {
+		int index, mask_index;
 		i = GET_HIGH_SLICE_INDEX(address);
-		p = &mm->context.high_slices_psize;
+		hpsizes = mm->context.high_slices_psize;
+		index = i >> 1;
+		mask_index = i - (index << 1);
+		hpsizes[index] = (hpsizes[index] &
+				  ~(0xf << (mask_index * 4))) |
+			(((unsigned long)psize) << (mask_index * 4));
 	}
-	*p = (*p & ~(0xful << (i * 4))) | ((unsigned long) psize << (i * 4));
+
 	spin_unlock_irqrestore(&slice_convert_lock, flags);
 
 #ifdef CONFIG_SPU_BASE
-- 
1.7.10

^ permalink raw reply related

* Re: [Early RFC 0/6] arch/powerpc: Add 64TB support to ppc64
From: Aneesh Kumar K.V @ 2012-05-31 19:58 UTC (permalink / raw)
  To: benh, paulus, michael, anton; +Cc: linuxppc-dev
In-Reply-To: <1338493841-9926-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com>

"Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> writes:

> Hi,
>
> This patchset include preparatory patches for supporting 64TB with ppc64. I haven't
> completed the actual patch that bump the USER_ESID bits. I wanted the share the
> changes early so that I can get feedback on the approach. The changes itself
> contains few FIXME!! which I will be addressing in the later updates.
>

Here is the patch that update USER_ESID_BITS. I get a machine check
exception with this changes. That is why I didn't include this in the patch
series. 

commit 5fff8ff606bc136c510350a40528431196f60001
Author: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Date:   Wed May 23 16:59:36 2012 +0530

    arch/powerpc: Add 64TB support
    
    Increase max addressable range to 64TB. This is not tested on
    real hardware yet.
    
    Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>

diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h
index 0f8b10d..9f9a2a1 100644
--- a/arch/powerpc/include/asm/mmu-hash64.h
+++ b/arch/powerpc/include/asm/mmu-hash64.h
@@ -375,8 +375,8 @@ extern void slb_set_size(u16 size);
 #define VSID_MODULUS_1T		((1UL<<VSID_BITS_1T)-1)
 
 #define CONTEXT_BITS		19
-#define USER_ESID_BITS		16
-#define USER_ESID_BITS_1T	4
+#define USER_ESID_BITS		18
+#define USER_ESID_BITS_1T	6
 
 #define USER_VSID_RANGE	(1UL << (USER_ESID_BITS + SID_SHIFT))
 
diff --git a/arch/powerpc/include/asm/pgtable-ppc64-4k.h b/arch/powerpc/include/asm/pgtable-ppc64-4k.h
index 6eefdcf..b3eccf2 100644
--- a/arch/powerpc/include/asm/pgtable-ppc64-4k.h
+++ b/arch/powerpc/include/asm/pgtable-ppc64-4k.h
@@ -7,7 +7,7 @@
  */
 #define PTE_INDEX_SIZE  9
 #define PMD_INDEX_SIZE  7
-#define PUD_INDEX_SIZE  7
+#define PUD_INDEX_SIZE  9
 #define PGD_INDEX_SIZE  9
 
 #ifndef __ASSEMBLY__
diff --git a/arch/powerpc/include/asm/pgtable-ppc64-64k.h b/arch/powerpc/include/asm/pgtable-ppc64-64k.h
index 90533dd..be4e287 100644
--- a/arch/powerpc/include/asm/pgtable-ppc64-64k.h
+++ b/arch/powerpc/include/asm/pgtable-ppc64-64k.h
@@ -7,7 +7,7 @@
 #define PTE_INDEX_SIZE  12
 #define PMD_INDEX_SIZE  12
 #define PUD_INDEX_SIZE	0
-#define PGD_INDEX_SIZE  4
+#define PGD_INDEX_SIZE  6
 
 #ifndef __ASSEMBLY__
 #define PTE_TABLE_SIZE	(sizeof(real_pte_t) << PTE_INDEX_SIZE)
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index 8e2d037..426ed13 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -100,8 +100,8 @@ extern struct task_struct *last_task_used_spe;
 #endif
 
 #ifdef CONFIG_PPC64
-/* 64-bit user address space is 44-bits (16TB user VM) */
-#define TASK_SIZE_USER64 (0x0000100000000000UL)
+/* 64-bit user address space is 46-bits (64TB user VM) */
+#define TASK_SIZE_USER64 (0x0000400000000000UL)
 
 /* 
  * 32-bit user address space is 4GB - 1 page 
diff --git a/arch/powerpc/include/asm/sparsemem.h b/arch/powerpc/include/asm/sparsemem.h
index 0c5fa31..f6fc0ee 100644
--- a/arch/powerpc/include/asm/sparsemem.h
+++ b/arch/powerpc/include/asm/sparsemem.h
@@ -10,8 +10,8 @@
  */
 #define SECTION_SIZE_BITS       24
 
-#define MAX_PHYSADDR_BITS       44
-#define MAX_PHYSMEM_BITS        44
+#define MAX_PHYSADDR_BITS       46
+#define MAX_PHYSMEM_BITS        46
 
 #endif /* CONFIG_SPARSEMEM */
 

^ permalink raw reply related

* Re: [RFC] [PATCH] powerpc: Add MSR_DE to MSR_KERNEL
From: Joakim Tjernlund @ 2012-05-31 21:38 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev, Dan Malek, Bob Cochran, Support
In-Reply-To: <4FC7AEC9.5050203@freescale.com>

Scott Wood <scottwood@freescale.com> wrote on 2012/05/31 19:47:53:
>
> On 05/31/2012 04:56 AM, Joakim Tjernlund wrote:
> > Abatron Support <support@abatron.ch> wrote on 2012/05/31 11:30:57:
> >>
> >>
> >>> Abatron Support <support@abatron.ch> wrote on 2012/05/30 14:08:26:
> >>>>
> >>>>>> I have tested this briefly with BDI2000 on P2010(e500) and
> >>>>>> it works for me. I don't know if there are any bad side effects,
> >>>>>> therfore
> >>>>>> this RFC.
> >>>>
> >>>>> We used to have MSR_DE surrounded by CONFIG_something
> >>>>> to ensure it wasn't set under normal operation.  IIRC, if MSR_DE
> >>>>> is set, you will have problems with software debuggers that
> >>>>> utilize the the debugging registers in the chip itself.  You only want
> >>>>> to force this to be set when using the BDI, not at other times.
> >>>>
> >>>> This MSR_DE is also of interest and used for software debuggers that
> >>>> make use of the debug registers. Only if MSR_DE is set then debug
> >>>> interrupts are generated. If a debug event leads to a debug interrupt
> >>>> handled by a software debugger or if it leads to a debug halt handled
> >>>> by a JTAG tool is selected with DBCR0_EDM / DBCR0_IDM.
> >>>>
> >>>> The "e500 Core Family Reference Manual" chapter "Chapter 8
> >>>> Debug Support" explains in detail the effect of MSR_DE.
> >>
> >>> So what is the verdict on this? I don't buy into Dan argument without some
> >>> hard data.
> >>
> >> What I tried to mention is that handling the MSR_DE correct is not only
> >> an emulator (JTAG debugger) requirement. Also a software debugger may
> >> depend on a correct handled MSR_DE bit.
> >
> > Yes, that made sense to me too. How would SW debuggers work if the kernel keeps
> > turning off MSR_DE first chance it gets?
>
> The kernel selectively enables MSR_DE when it wants to debug.  I'm not
> sure if anything will be bothered by leaving it on all the time.  This
> is something we need for virtualization as well, so a hypervisor can
> debug the guest.

hmm, I read that as you as in favour of the patch?

^ permalink raw reply

* Re: [RFC] [PATCH] powerpc: Add MSR_DE to MSR_KERNEL
From: Scott Wood @ 2012-05-31 21:43 UTC (permalink / raw)
  To: Joakim Tjernlund; +Cc: linuxppc-dev, Dan Malek, Bob Cochran, Support
In-Reply-To: <OF3AA5925F.E17EF6A4-ONC1257A0F.0076C23F-C1257A0F.0076D836@transmode.se>

On 05/31/2012 04:38 PM, Joakim Tjernlund wrote:
> Scott Wood <scottwood@freescale.com> wrote on 2012/05/31 19:47:53:
>>
>> On 05/31/2012 04:56 AM, Joakim Tjernlund wrote:
>>> Abatron Support <support@abatron.ch> wrote on 2012/05/31 11:30:57:
>>>>
>>>>
>>>>> Abatron Support <support@abatron.ch> wrote on 2012/05/30 14:08:26:
>>>>>>
>>>>>>>> I have tested this briefly with BDI2000 on P2010(e500) and
>>>>>>>> it works for me. I don't know if there are any bad side effects,
>>>>>>>> therfore
>>>>>>>> this RFC.
>>>>>>
>>>>>>> We used to have MSR_DE surrounded by CONFIG_something
>>>>>>> to ensure it wasn't set under normal operation.  IIRC, if MSR_DE
>>>>>>> is set, you will have problems with software debuggers that
>>>>>>> utilize the the debugging registers in the chip itself.  You only want
>>>>>>> to force this to be set when using the BDI, not at other times.
>>>>>>
>>>>>> This MSR_DE is also of interest and used for software debuggers that
>>>>>> make use of the debug registers. Only if MSR_DE is set then debug
>>>>>> interrupts are generated. If a debug event leads to a debug interrupt
>>>>>> handled by a software debugger or if it leads to a debug halt handled
>>>>>> by a JTAG tool is selected with DBCR0_EDM / DBCR0_IDM.
>>>>>>
>>>>>> The "e500 Core Family Reference Manual" chapter "Chapter 8
>>>>>> Debug Support" explains in detail the effect of MSR_DE.
>>>>
>>>>> So what is the verdict on this? I don't buy into Dan argument without some
>>>>> hard data.
>>>>
>>>> What I tried to mention is that handling the MSR_DE correct is not only
>>>> an emulator (JTAG debugger) requirement. Also a software debugger may
>>>> depend on a correct handled MSR_DE bit.
>>>
>>> Yes, that made sense to me too. How would SW debuggers work if the kernel keeps
>>> turning off MSR_DE first chance it gets?
>>
>> The kernel selectively enables MSR_DE when it wants to debug.  I'm not
>> sure if anything will be bothered by leaving it on all the time.  This
>> is something we need for virtualization as well, so a hypervisor can
>> debug the guest.
> 
> hmm, I read that as you as in favour of the patch?

I'd want some confirmation that it doesn't break anything, and that
there aren't any other places that need MSR_DE that this doesn't cover,
but in general yes.

-Scott

^ permalink raw reply


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