All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction
@ 2014-09-16 16:50 Bob Picco
  2014-09-17  1:48 ` David Miller
                   ` (19 more replies)
  0 siblings, 20 replies; 21+ messages in thread
From: Bob Picco @ 2014-09-16 16:50 UTC (permalink / raw)
  To: sparclinux

From: bob picco <bpicco@meloft.net>

For physical address larger than 47 bits the computed physical address
was insufficient within KERN_TSB_LOOKUP_TL1. This resulted in a vmlinux
loaded above 47 bits of physical address unable to boot in spectacular
ways.

For now we've expanded the physical address range to 52 bits at the cost of
two instructions. Older sparc64 incur two nop-s.

The two new instructions from this patch and the former KTSB_PHYS_SHIFT can
potentially be eliminated using memblock aligning large and constraining
the physical limit. Essentially use the "sethi" for a physical manipulated
address and replacing the "or" at patch time with a "sllx". This would leave
the tsb within head_64.S unused and possibly not a good solution for Cheetah+.
We'll comtemplate this more in another round.

Cc: sparclinux@vger.kernel.org
Signed-off-by: Bob Picco <bob.picco@oracle.com>
---
 arch/sparc/include/asm/tsb.h    |   33 ++++++++++++++++++++++++++++++++-
 arch/sparc/kernel/vmlinux.lds.S |   10 ++++++++++
 arch/sparc/mm/init_64.c         |   35 +++++++++++++++++++++++++++++++++++
 3 files changed, 77 insertions(+), 1 deletions(-)

diff --git a/arch/sparc/include/asm/tsb.h b/arch/sparc/include/asm/tsb.h
index 90916f9..d4e09c5 100644
--- a/arch/sparc/include/asm/tsb.h
+++ b/arch/sparc/include/asm/tsb.h
@@ -246,7 +246,24 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
 	(KERNEL_TSB_SIZE_BYTES / 16)
 #define KERNEL_TSB4M_NENTRIES	4096
 
-#define KTSB_PHYS_SHIFT		15
+	/* This is required for more than 47 bits of physical address.
+	 * It is a memory versus instruction count choice. I chose two
+	 * more instructions which is two nops for not participating sparc64.
+	 * Should we increase the swapper_tsb size and/or swapper_4m_tsb size
+	 * then this choice should be reconsidered.
+	 */
+#define KTSB_PHYS_SHIFT		20
+#define	KTSB_PHYS_MASK_LOW_1MB	(~((1UL << KTSB_PHYS_SHIFT) - 1))
+#ifndef	__ASSEMBLY__
+struct tsb_phys_patch_low_1mb_entry {
+	unsigned int	addr;
+	unsigned int	inst[2];
+};
+extern struct tsb_phys_patch_low_1mb_entry
+	__swapper_phys_low_1mb_patch, __swapper_phys_low_1mb_patch_end,
+	__swapper_4m_phys_low_1mb_patch, __swapper_4m_phys_low_1mb_patch_end;
+#endif
+
 
 	/* Do a kernel TSB lookup at tl>0 on VADDR+TAG, branch to OK_LABEL
 	 * on TSB hit.  REG1, REG2, REG3, and REG4 are used as temporaries
@@ -267,6 +284,13 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
 	sllx		REG1, KTSB_PHYS_SHIFT, REG1; \
 	sllx		REG1, KTSB_PHYS_SHIFT, REG1; \
 	.previous; \
+661:	nop; \
+	nop; \
+	.section	.swapper_phys_low_1mb_patch, "ax"; \
+	.word		661b; \
+	sethi		0, REG2; \
+	or		REG2, REG1, REG1; \
+	.previous; \
 	srlx		VADDR, PAGE_SHIFT, REG2; \
 	and		REG2, (KERNEL_TSB_NENTRIES - 1), REG2; \
 	sllx		REG2, 4, REG2; \
@@ -292,6 +316,13 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
 	sllx		REG1, KTSB_PHYS_SHIFT, REG1; \
 	sllx		REG1, KTSB_PHYS_SHIFT, REG1; \
 	.previous; \
+661:	nop; \
+	nop; \
+	.section	.swapper_4m_phys_low_1mb_patch, "ax"; \
+	.word		661b; \
+	sethi		0, REG2; \
+	or		REG2, REG1, REG1; \
+	.previous; \
 	and		TAG, (KERNEL_TSB4M_NENTRIES - 1), REG2; \
 	sllx		REG2, 4, REG2; \
 	add		REG1, REG2, REG2; \
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index 932ff90..2da4f39 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -127,6 +127,16 @@ SECTIONS
 		*(.page_offset_shift_patch)
 		__page_offset_shift_patch_end = .;
 	}
+	.swapper_phys_low_1mb_patch : {
+		__swapper_phys_low_1mb_patch = .;
+		*(.swapper_phys_low_1mb_patch)
+		__swapper_phys_low_1mb_patch_end = .;
+	}
+	.swapper_4m_phys_low_1mb_patch : {
+		__swapper_4m_phys_low_1mb_patch = .;
+		*(.swapper_4m_phys_low_1mb_patch)
+		__swapper_4m_phys_low_1mb_patch_end = .;
+	}
 	.popc_3insn_patch : {
 		__popc_3insn_patch = .;
 		*(.popc_3insn_patch)
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 87047fb..1bf4643 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -1722,6 +1722,36 @@ static void patch_one_ktsb_phys(unsigned int *start, unsigned int *end, unsigned
 	}
 }
 
+/* We know this patch correctly functions for swapper_tsb and swapper_4m_tsb
+ * because of their respective data alignment. That is bits [31:10] are within
+ * the alignment. The physical address is shifted right 20 which clips the
+ * low bits within thirty two bits.
+ */
+static void
+patch_one_ktsb_phys_low_1mb(struct tsb_phys_patch_low_1mb_entry *entry,
+			    struct tsb_phys_patch_low_1mb_entry *end,
+			    unsigned long phys)
+{
+	unsigned long phys_low_1mb = phys & ~KTSB_PHYS_MASK_LOW_1MB;
+
+	while (entry < end) {
+		unsigned long addr = entry->addr;
+		unsigned int *inst = (unsigned int *)(unsigned long) addr;
+
+		inst[0] = entry->inst[0] | (phys_low_1mb >> 10);
+		__asm__ __volatile__("flush %0\n\t"
+			: /* no outputs */
+			: "r" (inst));
+
+		inst[1] = entry->inst[1];
+		__asm__ __volatile__("flush %0\n\t"
+			: /* no outputs */
+			: "r" (inst + 1));
+
+		entry++;
+	}
+}
+
 static void ktsb_phys_patch(void)
 {
 	extern unsigned int __swapper_tsb_phys_patch;
@@ -1731,6 +1761,8 @@ static void ktsb_phys_patch(void)
 	ktsb_pa = kern_base + ((unsigned long)&swapper_tsb[0] - KERNBASE);
 	patch_one_ktsb_phys(&__swapper_tsb_phys_patch,
 			    &__swapper_tsb_phys_patch_end, ktsb_pa);
+	patch_one_ktsb_phys_low_1mb(&__swapper_phys_low_1mb_patch,
+				    &__swapper_phys_low_1mb_patch_end, ktsb_pa);
 #ifndef CONFIG_DEBUG_PAGEALLOC
 	{
 	extern unsigned int __swapper_4m_tsb_phys_patch;
@@ -1739,6 +1771,9 @@ static void ktsb_phys_patch(void)
 		   ((unsigned long)&swapper_4m_tsb[0] - KERNBASE));
 	patch_one_ktsb_phys(&__swapper_4m_tsb_phys_patch,
 			    &__swapper_4m_tsb_phys_patch_end, ktsb_pa);
+	patch_one_ktsb_phys_low_1mb(&__swapper_4m_phys_low_1mb_patch,
+				    &__swapper_4m_phys_low_1mb_patch_end,
+				    ktsb_pa);
 	}
 #endif
 }
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction
  2014-09-16 16:50 [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction Bob Picco
@ 2014-09-17  1:48 ` David Miller
  2014-09-17 12:42 ` Bob Picco
                   ` (18 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: David Miller @ 2014-09-17  1:48 UTC (permalink / raw)
  To: sparclinux

From: Bob Picco <bpicco@meloft.net>
Date: Tue, 16 Sep 2014 12:50:39 -0400

> From: bob picco <bpicco@meloft.net>
> 
> For physical address larger than 47 bits the computed physical address
> was insufficient within KERN_TSB_LOOKUP_TL1. This resulted in a vmlinux
> loaded above 47 bits of physical address unable to boot in spectacular
> ways.
> 
> For now we've expanded the physical address range to 52 bits at the cost of
> two instructions. Older sparc64 incur two nop-s.
> 
> The two new instructions from this patch and the former KTSB_PHYS_SHIFT can
> potentially be eliminated using memblock aligning large and constraining
> the physical limit. Essentially use the "sethi" for a physical manipulated
> address and replacing the "or" at patch time with a "sllx". This would leave
> the tsb within head_64.S unused and possibly not a good solution for Cheetah+.
> We'll comtemplate this more in another round.
> 
> Cc: sparclinux@vger.kernel.org
> Signed-off-by: Bob Picco <bob.picco@oracle.com>

Bob, thanks for doing this work to support up to 49-bits of physical
addressing.

There are a lot of tradeoffs and thorny issues involved here, so I'm
going to take some time reviewing this set of patches.

I'll try to get back to you on these changes in a reasonable amount of
time, thanks for your patience.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction
  2014-09-16 16:50 [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction Bob Picco
  2014-09-17  1:48 ` David Miller
@ 2014-09-17 12:42 ` Bob Picco
  2014-09-17 17:16 ` David Miller
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Bob Picco @ 2014-09-17 12:42 UTC (permalink / raw)
  To: sparclinux

David Miller wrote:	[Tue Sep 16 2014, 09:48:03PM EDT]
> From: Bob Picco <bpicco@meloft.net>
> Date: Tue, 16 Sep 2014 12:50:39 -0400
> 
> > From: bob picco <bpicco@meloft.net>
> > 
> > For physical address larger than 47 bits the computed physical address
> > was insufficient within KERN_TSB_LOOKUP_TL1. This resulted in a vmlinux
> > loaded above 47 bits of physical address unable to boot in spectacular
> > ways.
> > 
> > For now we've expanded the physical address range to 52 bits at the cost of
> > two instructions. Older sparc64 incur two nop-s.
> > 
> > The two new instructions from this patch and the former KTSB_PHYS_SHIFT can
> > potentially be eliminated using memblock aligning large and constraining
> > the physical limit. Essentially use the "sethi" for a physical manipulated
> > address and replacing the "or" at patch time with a "sllx". This would leave
> > the tsb within head_64.S unused and possibly not a good solution for Cheetah+.
> > We'll comtemplate this more in another round.
> > 
> > Cc: sparclinux@vger.kernel.org
> > Signed-off-by: Bob Picco <bob.picco@oracle.com>
> 
> Bob, thanks for doing this work to support up to 49-bits of physical
> addressing.
You are very welcome.
> 
> There are a lot of tradeoffs and thorny issues involved here, so I'm
> going to take some time reviewing this set of patches.
Indeed many tricky issues. I took a first stab at it.
> 
> I'll try to get back to you on these changes in a reasonable amount of
> time, thanks for your patience.
No hurry and thanx.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction
  2014-09-16 16:50 [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction Bob Picco
  2014-09-17  1:48 ` David Miller
  2014-09-17 12:42 ` Bob Picco
@ 2014-09-17 17:16 ` David Miller
  2014-09-17 19:22 ` Bob Picco
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: David Miller @ 2014-09-17 17:16 UTC (permalink / raw)
  To: sparclinux

From: Bob Picco <bpicco@meloft.net>
Date: Tue, 16 Sep 2014 12:50:39 -0400

> From: bob picco <bpicco@meloft.net>
> 
> For physical address larger than 47 bits the computed physical address
> was insufficient within KERN_TSB_LOOKUP_TL1. This resulted in a vmlinux
> loaded above 47 bits of physical address unable to boot in spectacular
> ways.
> 
> For now we've expanded the physical address range to 52 bits at the cost of
> two instructions. Older sparc64 incur two nop-s.
> 
> The two new instructions from this patch and the former KTSB_PHYS_SHIFT can
> potentially be eliminated using memblock aligning large and constraining
> the physical limit. Essentially use the "sethi" for a physical manipulated
> address and replacing the "or" at patch time with a "sllx". This would leave
> the tsb within head_64.S unused and possibly not a good solution for Cheetah+.
> We'll comtemplate this more in another round.
> 
> Cc: sparclinux@vger.kernel.org
> Signed-off-by: Bob Picco <bob.picco@oracle.com>

Bob, I think we can do this with a 4 instruction sequence, basically
"sethi, sethi, sllx, or".  The two sethi's give us 22 bits each, and
we again take advantage of the 32K+ alignment of both kernel TSBs.

Can you give this patch below a quick test on your machine that hits
this issue?

Thanks.

==========
[PATCH] sparc64: Adjust KTSB assembler to support larger physical addresses.

As currently coded the KTSB accesses in the kernel only support up to
47 bits of physical addressing.

Adjust the instruction and patching sequence in order to increase it
to 54 bits.

Validate that the KTSB physical address will work with this scheme,
at run time, so that we fail gracefully instead of crapping all
over memory randomly.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 arch/sparc/include/asm/tsb.h | 26 ++++++++------------------
 arch/sparc/mm/init_64.c      | 44 +++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 49 insertions(+), 21 deletions(-)

diff --git a/arch/sparc/include/asm/tsb.h b/arch/sparc/include/asm/tsb.h
index 90916f9..def62ed4 100644
--- a/arch/sparc/include/asm/tsb.h
+++ b/arch/sparc/include/asm/tsb.h
@@ -246,8 +246,6 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
 	(KERNEL_TSB_SIZE_BYTES / 16)
 #define KERNEL_TSB4M_NENTRIES	4096
 
-#define KTSB_PHYS_SHIFT		15
-
 	/* Do a kernel TSB lookup at tl>0 on VADDR+TAG, branch to OK_LABEL
 	 * on TSB hit.  REG1, REG2, REG3, and REG4 are used as temporaries
 	 * and the found TTE will be left in REG1.  REG3 and REG4 must
@@ -256,17 +254,13 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
 	 * VADDR and TAG will be preserved and not clobbered by this macro.
 	 */
 #define KERN_TSB_LOOKUP_TL1(VADDR, TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
-661:	sethi		%hi(swapper_tsb), REG1;			\
-	or		REG1, %lo(swapper_tsb), REG1; \
+661:	sethi		%hi(0), REG1; \
+	sethi		%hi(swapper_tsb), REG2; \
 	.section	.swapper_tsb_phys_patch, "ax"; \
 	.word		661b; \
 	.previous; \
-661:	nop; \
-	.section	.tsb_ldquad_phys_patch, "ax"; \
-	.word		661b; \
-	sllx		REG1, KTSB_PHYS_SHIFT, REG1; \
-	sllx		REG1, KTSB_PHYS_SHIFT, REG1; \
-	.previous; \
+	sllx		REG1, 32, REG1; \
+	or		REG1, REG2, REG1; \
 	srlx		VADDR, PAGE_SHIFT, REG2; \
 	and		REG2, (KERNEL_TSB_NENTRIES - 1), REG2; \
 	sllx		REG2, 4, REG2; \
@@ -281,17 +275,13 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
 	 * we can make use of that for the index computation.
 	 */
 #define KERN_TSB4M_LOOKUP_TL1(TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
-661:	sethi		%hi(swapper_4m_tsb), REG1;	     \
-	or		REG1, %lo(swapper_4m_tsb), REG1; \
+661:	sethi		%hi(0), REG1; \
+	sethi		%hi(swapper_4m_tsb), REG2; \
 	.section	.swapper_4m_tsb_phys_patch, "ax"; \
 	.word		661b; \
 	.previous; \
-661:	nop; \
-	.section	.tsb_ldquad_phys_patch, "ax"; \
-	.word		661b; \
-	sllx		REG1, KTSB_PHYS_SHIFT, REG1; \
-	sllx		REG1, KTSB_PHYS_SHIFT, REG1; \
-	.previous; \
+	sllx		REG1, 32, REG1; \
+	or		REG1, REG2, REG1; \
 	and		TAG, (KERNEL_TSB4M_NENTRIES - 1), REG2; \
 	sllx		REG2, 4, REG2; \
 	add		REG1, REG2, REG2; \
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index c8bccaf..c30a796 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -1705,17 +1705,55 @@ static void __init tsb_phys_patch(void)
 static struct hv_tsb_descr ktsb_descr[NUM_KTSB_DESCR];
 extern struct tsb swapper_tsb[KERNEL_TSB_NENTRIES];
 
+/* The swapper TSBs are loaded with a base sequence of:
+ *
+ *	sethi	%hi(0), REG1
+ *	sethi	%hi(SYMBOL), REG2
+ *	sllx	REG1, 32, REG1
+ *	or	REG1, REG2, REG1
+ *
+ * The two KTSBs are both at least 32K aligned, so a single
+ * sethi can load the virtual address.
+ *
+ * When we use physical addressing for the TSB accesses, we patch the
+ * first two instructions in the above sequence.  This scheme supports
+ * up to 54 bits of physical addressing.
+ */
+
 static void patch_one_ktsb_phys(unsigned int *start, unsigned int *end, unsigned long pa)
 {
-	pa >>= KTSB_PHYS_SHIFT;
+	const unsigned long check_mask = 0x003ffffffffffc00UL;
+	unsigned long high_bits, low_bits;
+
+	if (unlikely(pa & ~check_mask)) {
+		prom_printf("Kernel TSB pa[0x%016lx] is out of range.\n", pa);
+		prom_halt();
+	}
+
+	/* We are extracting:
+	 *
+	 * ------------------------------------
+	 * | --- | high bits | low bits | --- |
+	 * ------------------------------------
+	 *  63 54 53       32 31      10 9   0
+	 *
+	 * from the KTSB physical address.
+	 *
+	 * The sethi instruction's 22-bit immediate field starts at bit
+	 * zero, so we are shifting the fields down into that location
+	 * and masking things off.
+	 */
+
+	high_bits = (pa >> 32) & 0x3fffff;
+	low_bits = (pa >> 10) & 0x3fffff;
 
 	while (start < end) {
 		unsigned int *ia = (unsigned int *)(unsigned long)*start;
 
-		ia[0] = (ia[0] & ~0x3fffff) | (pa >> 10);
+		ia[0] = (ia[0] & ~0x3fffff) | high_bits;
 		__asm__ __volatile__("flush	%0" : : "r" (ia));
 
-		ia[1] = (ia[1] & ~0x3ff) | (pa & 0x3ff);
+		ia[1] = (ia[1] & ~0x3fffff) | low_bits;
 		__asm__ __volatile__("flush	%0" : : "r" (ia + 1));
 
 		start++;
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction
  2014-09-16 16:50 [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction Bob Picco
                   ` (2 preceding siblings ...)
  2014-09-17 17:16 ` David Miller
@ 2014-09-17 19:22 ` Bob Picco
  2014-09-17 20:04 ` David Miller
                   ` (15 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Bob Picco @ 2014-09-17 19:22 UTC (permalink / raw)
  To: sparclinux

David Miller wrote:	[Wed Sep 17 2014, 01:16:22PM EDT]
> From: Bob Picco <bpicco@meloft.net>
> Date: Tue, 16 Sep 2014 12:50:39 -0400
> 
> > From: bob picco <bpicco@meloft.net>
> > 
> > For physical address larger than 47 bits the computed physical address
> > was insufficient within KERN_TSB_LOOKUP_TL1. This resulted in a vmlinux
> > loaded above 47 bits of physical address unable to boot in spectacular
> > ways.
> > 
> > For now we've expanded the physical address range to 52 bits at the cost of
> > two instructions. Older sparc64 incur two nop-s.
> > 
> > The two new instructions from this patch and the former KTSB_PHYS_SHIFT can
> > potentially be eliminated using memblock aligning large and constraining
> > the physical limit. Essentially use the "sethi" for a physical manipulated
> > address and replacing the "or" at patch time with a "sllx". This would leave
> > the tsb within head_64.S unused and possibly not a good solution for Cheetah+.
> > We'll comtemplate this more in another round.
> > 
> > Cc: sparclinux@vger.kernel.org
> > Signed-off-by: Bob Picco <bob.picco@oracle.com>
> 
> Bob, I think we can do this with a 4 instruction sequence, basically
> "sethi, sethi, sllx, or".  The two sethi's give us 22 bits each, and
> we again take advantage of the 32K+ alignment of both kernel TSBs.
> 
> Can you give this patch below a quick test on your machine that hits
> this issue?
Yes, please give me until later tomorrow. One, I haven't wrapped my
head around this code in a bit. The other, the machine is possibly
closer to you than me and can be temperamental.
> 
> Thanks.
you're welcome,

bob

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction
  2014-09-16 16:50 [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction Bob Picco
                   ` (3 preceding siblings ...)
  2014-09-17 19:22 ` Bob Picco
@ 2014-09-17 20:04 ` David Miller
  2014-09-17 21:00 ` Bob Picco
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: David Miller @ 2014-09-17 20:04 UTC (permalink / raw)
  To: sparclinux

From: Bob Picco <bpicco@meloft.net>
Date: Wed, 17 Sep 2014 15:22:37 -0400

> Yes, please give me until later tomorrow. One, I haven't wrapped my
> head around this code in a bit.

No problem.

> The other, the machine is possibly closer to you than me and can be
> temperamental.

Probably it isn't, I'm in NYC at the moment.



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction
  2014-09-16 16:50 [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction Bob Picco
                   ` (4 preceding siblings ...)
  2014-09-17 20:04 ` David Miller
@ 2014-09-17 21:00 ` Bob Picco
  2014-09-18 10:09 ` Bob Picco
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Bob Picco @ 2014-09-17 21:00 UTC (permalink / raw)
  To: sparclinux

David Miller wrote:	[Wed Sep 17 2014, 04:04:25PM EDT]
> From: Bob Picco <bpicco@meloft.net>
> Date: Wed, 17 Sep 2014 15:22:37 -0400
> 
> > Yes, please give me until later tomorrow. One, I haven't wrapped my
> > head around this code in a bit.
> 
> No problem.
Okay.
> 
> > The other, the machine is possibly closer to you than me and can be
> > temperamental.
> 
> Probably it isn't, I'm in NYC at the moment.
Ah but you are. I'm in Manchester, NH.

The bloody machine decided to hemorrhage. I'm in repair mode and it usually
recovers without issue.
> 
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction
  2014-09-16 16:50 [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction Bob Picco
                   ` (5 preceding siblings ...)
  2014-09-17 21:00 ` Bob Picco
@ 2014-09-18 10:09 ` Bob Picco
  2014-09-18 17:08 ` David Miller
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Bob Picco @ 2014-09-18 10:09 UTC (permalink / raw)
  To: sparclinux

Hi,
Bob Picco wrote:	[Wed Sep 17 2014, 05:00:35PM EDT]
> David Miller wrote:	[Wed Sep 17 2014, 04:04:25PM EDT]
> > From: Bob Picco <bpicco@meloft.net>
> > Date: Wed, 17 Sep 2014 15:22:37 -0400
> > 
> > > Yes, please give me until later tomorrow. One, I haven't wrapped my
> > > head around this code in a bit.
> > 
> > No problem.
> Okay.
> > 
> > > The other, the machine is possibly closer to you than me and can be
> > > temperamental.
> > 
> > Probably it isn't, I'm in NYC at the moment.
> Ah but you are. I'm in Manchester, NH.
> 
> The bloody machine decided to hemorrhage. I'm in repair mode and it usually
> recovers without issue.
The machine hung after remapping. It could have been my mistake. Please
let me investigate.

I have two appointments today. One I forgot about and was reminded with
a call late yesterday.
> > 
> > 
> --
> To unsubscribe from this list: send the line "unsubscribe sparclinux" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction
  2014-09-16 16:50 [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction Bob Picco
                   ` (6 preceding siblings ...)
  2014-09-18 10:09 ` Bob Picco
@ 2014-09-18 17:08 ` David Miller
  2014-09-18 19:43 ` David Miller
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: David Miller @ 2014-09-18 17:08 UTC (permalink / raw)
  To: sparclinux

From: Bob Picco <bpicco@meloft.net>
Date: Thu, 18 Sep 2014 06:09:12 -0400

> The machine hung after remapping. It could have been my mistake. Please
> let me investigate.

I was hoping this would have been the simplest of the patches :-)

If you get stuck just print some debugging information with
prom_printf() (the physical address of the KTSB, and the final
instruction values after patching) then prom_halt() so it doesn't hang
and you can reset more quickly.


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction
  2014-09-16 16:50 [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction Bob Picco
                   ` (7 preceding siblings ...)
  2014-09-18 17:08 ` David Miller
@ 2014-09-18 19:43 ` David Miller
  2014-09-18 21:34 ` Bob Picco
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: David Miller @ 2014-09-18 19:43 UTC (permalink / raw)
  To: sparclinux

From: David Miller <davem@davemloft.net>
Date: Wed, 17 Sep 2014 13:16:22 -0400 (EDT)

> [PATCH] sparc64: Adjust KTSB assembler to support larger physical addresses.

Bob, just a quick update.

I've adjusted this patch of mine to support arbitrary physical addresses,
not just up to 54-bits.

With the other related changes being discussed, we will have no
limitations to deal with wrt. physical addressing ever again and
honestly I don't want to have to play with this area any more :)

--------------------
[PATCH] sparc64: Adjust KTSB assembler to support larger physical addresses.

As currently coded the KTSB accesses in the kernel only support up to
47 bits of physical addressing.

Adjust the instruction and patching sequence in order to support
arbitrary 64 bits addresses.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 arch/sparc/include/asm/tsb.h | 30 ++++++++++++------------------
 arch/sparc/mm/init_64.c      | 28 +++++++++++++++++++++++++---
 2 files changed, 37 insertions(+), 21 deletions(-)

diff --git a/arch/sparc/include/asm/tsb.h b/arch/sparc/include/asm/tsb.h
index 90916f9..11c5047 100644
--- a/arch/sparc/include/asm/tsb.h
+++ b/arch/sparc/include/asm/tsb.h
@@ -246,8 +246,6 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
 	(KERNEL_TSB_SIZE_BYTES / 16)
 #define KERNEL_TSB4M_NENTRIES	4096
 
-#define KTSB_PHYS_SHIFT		15
-
 	/* Do a kernel TSB lookup at tl>0 on VADDR+TAG, branch to OK_LABEL
 	 * on TSB hit.  REG1, REG2, REG3, and REG4 are used as temporaries
 	 * and the found TTE will be left in REG1.  REG3 and REG4 must
@@ -256,17 +254,15 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
 	 * VADDR and TAG will be preserved and not clobbered by this macro.
 	 */
 #define KERN_TSB_LOOKUP_TL1(VADDR, TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
-661:	sethi		%hi(swapper_tsb), REG1;			\
-	or		REG1, %lo(swapper_tsb), REG1; \
+661:	sethi		%uhi(swapper_tsb), REG1; \
+	sethi		%hi(swapper_tsb), REG2; \
+	or		REG1, %ulo(swapper_tsb), REG1; \
+	or		REG2, %lo(swapper_tsb), REG2; \
 	.section	.swapper_tsb_phys_patch, "ax"; \
 	.word		661b; \
 	.previous; \
-661:	nop; \
-	.section	.tsb_ldquad_phys_patch, "ax"; \
-	.word		661b; \
-	sllx		REG1, KTSB_PHYS_SHIFT, REG1; \
-	sllx		REG1, KTSB_PHYS_SHIFT, REG1; \
-	.previous; \
+	sllx		REG1, 32, REG1; \
+	or		REG1, REG2, REG1; \
 	srlx		VADDR, PAGE_SHIFT, REG2; \
 	and		REG2, (KERNEL_TSB_NENTRIES - 1), REG2; \
 	sllx		REG2, 4, REG2; \
@@ -281,17 +277,15 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
 	 * we can make use of that for the index computation.
 	 */
 #define KERN_TSB4M_LOOKUP_TL1(TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
-661:	sethi		%hi(swapper_4m_tsb), REG1;	     \
-	or		REG1, %lo(swapper_4m_tsb), REG1; \
+661:	sethi		%uhi(swapper_4m_tsb), REG1; \
+	sethi		%hi(swapper_4m_tsb), REG2; \
+	or		REG1, %ulo(swapper_4m_tsb), REG1; \
+	or		REG2, %lo(swapper_4m_tsb), REG2; \
 	.section	.swapper_4m_tsb_phys_patch, "ax"; \
 	.word		661b; \
 	.previous; \
-661:	nop; \
-	.section	.tsb_ldquad_phys_patch, "ax"; \
-	.word		661b; \
-	sllx		REG1, KTSB_PHYS_SHIFT, REG1; \
-	sllx		REG1, KTSB_PHYS_SHIFT, REG1; \
-	.previous; \
+	sllx		REG1, 32, REG1; \
+	or		REG1, REG2, REG1; \
 	and		TAG, (KERNEL_TSB4M_NENTRIES - 1), REG2; \
 	sllx		REG2, 4, REG2; \
 	add		REG1, REG2, REG2; \
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index c8bccaf..971ac36 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -1705,19 +1705,41 @@ static void __init tsb_phys_patch(void)
 static struct hv_tsb_descr ktsb_descr[NUM_KTSB_DESCR];
 extern struct tsb swapper_tsb[KERNEL_TSB_NENTRIES];
 
+/* The swapper TSBs are loaded with a base sequence of:
+ *
+ *	sethi	%uhi(SYMBOL), REG1
+ *	sethi	%hi(SYMBOL), REG2
+ *	or	REG1, %ulo(SYMBOL), REG1
+ *	or	REG2, %lo(SYMBOL), REG2
+ *	sllx	REG1, 32, REG1
+ *	or	REG1, REG2, REG1
+ *
+ * When we use physical addressing for the TSB accesses, we patch the
+ * first four instructions in the above sequence.
+ */
+
 static void patch_one_ktsb_phys(unsigned int *start, unsigned int *end, unsigned long pa)
 {
-	pa >>= KTSB_PHYS_SHIFT;
+	unsigned long high_bits, low_bits;
+
+	high_bits = (pa >> 32) & 0xffffffff;
+	low_bits = (pa >> 0) & 0xffffffff;
 
 	while (start < end) {
 		unsigned int *ia = (unsigned int *)(unsigned long)*start;
 
-		ia[0] = (ia[0] & ~0x3fffff) | (pa >> 10);
+		ia[0] = (ia[0] & ~0x3fffff) | (high_bits >> 10);
 		__asm__ __volatile__("flush	%0" : : "r" (ia));
 
-		ia[1] = (ia[1] & ~0x3ff) | (pa & 0x3ff);
+		ia[1] = (ia[1] & ~0x3fffff) | (low_bits >> 10);
 		__asm__ __volatile__("flush	%0" : : "r" (ia + 1));
 
+		ia[2] = (ia[2] & ~0x1fff) | (high_bits & 0x3ff);
+		__asm__ __volatile__("flush	%0" : : "r" (ia + 2));
+
+		ia[3] = (ia[3] & ~0x1fff) | (low_bits & 0x3ff);
+		__asm__ __volatile__("flush	%0" : : "r" (ia + 3));
+
 		start++;
 	}
 }
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction
  2014-09-16 16:50 [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction Bob Picco
                   ` (8 preceding siblings ...)
  2014-09-18 19:43 ` David Miller
@ 2014-09-18 21:34 ` Bob Picco
  2014-09-18 22:15 ` Bob Picco
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Bob Picco @ 2014-09-18 21:34 UTC (permalink / raw)
  To: sparclinux

Hi,
David Miller wrote:	[Thu Sep 18 2014, 01:08:08PM EDT]
> From: Bob Picco <bpicco@meloft.net>
> Date: Thu, 18 Sep 2014 06:09:12 -0400
> 
> > The machine hung after remapping. It could have been my mistake. Please
> > let me investigate.
> 
> I was hoping this would have been the simplest of the patches :-)
> 
> If you get stuck just print some debugging information with
> prom_printf() (the physical address of the KTSB, and the final
> instruction values after patching) then prom_halt() so it doesn't hang
> and you can reset more quickly.
> 
Sorry I was being yanked all over the place today. This boots on T5-2.
Now I'll look at your second version.


diff -u b/arch/sparc/include/asm/tsb.h b/arch/sparc/include/asm/tsb.h
--- b/arch/sparc/include/asm/tsb.h
+++ b/arch/sparc/include/asm/tsb.h
@@ -259,7 +259,7 @@
 	.section	.swapper_tsb_phys_patch, "ax"; \
 	.word		661b; \
 	.previous; \
-	sllx		REG1, 32, REG1; \
+	sllx		REG1, 22, REG1; \
 	or		REG1, REG2, REG1; \
 	srlx		VADDR, PAGE_SHIFT, REG2; \
 	and		REG2, (KERNEL_TSB_NENTRIES - 1), REG2; \
@@ -280,7 +280,7 @@
 	.section	.swapper_4m_tsb_phys_patch, "ax"; \
 	.word		661b; \
 	.previous; \
-	sllx		REG1, 32, REG1; \
+	sllx		REG1, 22, REG1; \
 	or		REG1, REG2, REG1; \
 	and		TAG, (KERNEL_TSB4M_NENTRIES - 1), REG2; \
 	sllx		REG2, 4, REG2; \

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction
  2014-09-16 16:50 [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction Bob Picco
                   ` (9 preceding siblings ...)
  2014-09-18 21:34 ` Bob Picco
@ 2014-09-18 22:15 ` Bob Picco
  2014-09-18 23:16 ` David Miller
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Bob Picco @ 2014-09-18 22:15 UTC (permalink / raw)
  To: sparclinux

David Miller wrote:	[Thu Sep 18 2014, 03:43:12PM EDT]
> From: David Miller <davem@davemloft.net>
> Date: Wed, 17 Sep 2014 13:16:22 -0400 (EDT)
> 
> > [PATCH] sparc64: Adjust KTSB assembler to support larger physical addresses.
> 
> Bob, just a quick update.
> 
> I've adjusted this patch of mine to support arbitrary physical addresses,
> not just up to 54-bits.
> 
> With the other related changes being discussed, we will have no
> limitations to deal with wrt. physical addressing ever again and
> honestly I don't want to have to play with this area any more :)
Honestly, me too :) It boots fine on T5-2. I'll hopefully take it for
a test drive on M7-4 tomorrow.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction
  2014-09-16 16:50 [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction Bob Picco
                   ` (10 preceding siblings ...)
  2014-09-18 22:15 ` Bob Picco
@ 2014-09-18 23:16 ` David Miller
  2014-09-19 19:28 ` David Miller
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: David Miller @ 2014-09-18 23:16 UTC (permalink / raw)
  To: sparclinux

From: Bob Picco <bpicco@meloft.net>
Date: Thu, 18 Sep 2014 18:15:30 -0400

> David Miller wrote:	[Thu Sep 18 2014, 03:43:12PM EDT]
>> From: David Miller <davem@davemloft.net>
>> Date: Wed, 17 Sep 2014 13:16:22 -0400 (EDT)
>> 
>> > [PATCH] sparc64: Adjust KTSB assembler to support larger physical addresses.
>> 
>> Bob, just a quick update.
>> 
>> I've adjusted this patch of mine to support arbitrary physical addresses,
>> not just up to 54-bits.
>> 
>> With the other related changes being discussed, we will have no
>> limitations to deal with wrt. physical addressing ever again and
>> honestly I don't want to have to play with this area any more :)
> Honestly, me too :) It boots fine on T5-2. I'll hopefully take it for
> a test drive on M7-4 tomorrow.

Thanks for all of your help and testing so far.

So I'll consider this patch good to go.

I'm half-way done with the "use kernel page tables for everything"
patch, and will post once I have something that at least work for
me.

BTW, with all of the static table removals, my images currently fit in
just 2 locked TLB entries :-)

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction
  2014-09-16 16:50 [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction Bob Picco
                   ` (11 preceding siblings ...)
  2014-09-18 23:16 ` David Miller
@ 2014-09-19 19:28 ` David Miller
  2014-09-19 19:57 ` Bob Picco
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: David Miller @ 2014-09-19 19:28 UTC (permalink / raw)
  To: sparclinux

From: David Miller <davem@davemloft.net>
Date: Thu, 18 Sep 2014 19:16:37 -0400 (EDT)

> I'm half-way done with the "use kernel page tables for everything"
> patch, and will post once I have something that at least work for
> me.

Bob, I ran into a major roadblock which is going to delay this work
a little bit.

In fact it pointed out a bug we introduced when increasing max phys
bits to 47.  We broke DEBUG_PAGEALLOC completely.  The issue is that
the page table layout only supports up to 43-bits.

I'll brain storm about this over the weekend.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction
  2014-09-16 16:50 [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction Bob Picco
                   ` (12 preceding siblings ...)
  2014-09-19 19:28 ` David Miller
@ 2014-09-19 19:57 ` Bob Picco
  2014-09-22  4:22 ` David Miller
                   ` (5 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Bob Picco @ 2014-09-19 19:57 UTC (permalink / raw)
  To: sparclinux

Hi,
David Miller wrote:	[Fri Sep 19 2014, 03:28:46PM EDT]
> From: David Miller <davem@davemloft.net>
> Date: Thu, 18 Sep 2014 19:16:37 -0400 (EDT)
> 
> > I'm half-way done with the "use kernel page tables for everything"
> > patch, and will post once I have something that at least work for
> > me.
> 
> Bob, I ran into a major roadblock which is going to delay this work
> a little bit.
Okay.
> 
> In fact it pointed out a bug we introduced when increasing max phys
> bits to 47.  We broke DEBUG_PAGEALLOC completely.  The issue is that
> the page table layout only supports up to 43-bits.
Oh bugger yes. I recall testing this when first introducting four level
page table layout in late 2012 and early 2013. It just isn't an everyday
thought but VERY nice to have.
> 
> I'll brain storm about this over the weekend.
Me too.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction
  2014-09-16 16:50 [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction Bob Picco
                   ` (13 preceding siblings ...)
  2014-09-19 19:57 ` Bob Picco
@ 2014-09-22  4:22 ` David Miller
  2014-09-22 18:56 ` Bob Picco
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: David Miller @ 2014-09-22  4:22 UTC (permalink / raw)
  To: sparclinux

From: Bob Picco <bpicco@meloft.net>
Date: Fri, 19 Sep 2014 15:57:31 -0400

> Hi,
> David Miller wrote:	[Fri Sep 19 2014, 03:28:46PM EDT]
>> From: David Miller <davem@davemloft.net>
>> Date: Thu, 18 Sep 2014 19:16:37 -0400 (EDT)
>> 
>> > I'm half-way done with the "use kernel page tables for everything"
>> > patch, and will post once I have something that at least work for
>> > me.
>> 
>> Bob, I ran into a major roadblock which is going to delay this work
>> a little bit.
> Okay.
>> 
>> In fact it pointed out a bug we introduced when increasing max phys
>> bits to 47.  We broke DEBUG_PAGEALLOC completely.  The issue is that
>> the page table layout only supports up to 43-bits.
> Oh bugger yes. I recall testing this when first introducting four level
> page table layout in late 2012 and early 2013. It just isn't an everyday
> thought but VERY nice to have.
>> 
>> I'll brain storm about this over the weekend.
> Me too.

Ok, here is what I have so far and I just got it working.

The long and short of it is that we have a 4-level page table
but only for the PAGE_OFFSET linear kernel mappings.

To the rest of the kernel this is transparent, because all
vmalloc et al. mappings have virtual addresses which index
to swapper_pg_dir.

The only thing I have to do is bring back 256MB et al. mapping usage
for suitable aligned PAGE_OFFSET linear areas.  It's only using 4MB
mappings at the moment.

diff --git a/arch/sparc/include/asm/page_64.h b/arch/sparc/include/asm/page_64.h
index bf10998..4af4e69 100644
--- a/arch/sparc/include/asm/page_64.h
+++ b/arch/sparc/include/asm/page_64.h
@@ -129,9 +129,6 @@ extern unsigned long PAGE_OFFSET;
  */
 #define MAX_PHYS_ADDRESS_BITS	47
 
-/* These two shift counts are used when indexing sparc64_valid_addr_bitmap
- * and kpte_linear_bitmap.
- */
 #define ILOG2_4MB		22
 #define ILOG2_256MB		28
 
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
index 3770bf5..d000904 100644
--- a/arch/sparc/include/asm/pgtable_64.h
+++ b/arch/sparc/include/asm/pgtable_64.h
@@ -61,6 +61,11 @@
 #define PGDIR_MASK	(~(PGDIR_SIZE-1))
 #define PGDIR_BITS	(PAGE_SHIFT - 3)
 
+#define KPGD_SHIFT	(PAGE_SHIFT + (PAGE_SHIFT-3) + (PAGE_SHIFT-3) + PGDIR_BITS)
+#define KPGD_SIZE	(_AC(1,UL) << KPGD_SHIFT)
+#define KPGD_MASK	(~(KPGD_SIZE-1))
+#define KPGD_BITS	(PAGE_SHIFT - 3)
+
 #if (PGDIR_SHIFT + PGDIR_BITS) != 43
 #error Page table parameters do not cover virtual address space properly.
 #endif
@@ -73,27 +78,13 @@
 
 #include <linux/sched.h>
 
-extern unsigned long sparc64_valid_addr_bitmap[];
-
-/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
-static inline bool __kern_addr_valid(unsigned long paddr)
-{
-	if ((paddr >> MAX_PHYS_ADDRESS_BITS) != 0UL)
-		return false;
-	return test_bit(paddr >> ILOG2_4MB, sparc64_valid_addr_bitmap);
-}
-
-static inline bool kern_addr_valid(unsigned long addr)
-{
-	unsigned long paddr = __pa(addr);
-
-	return __kern_addr_valid(paddr);
-}
+bool kern_addr_valid(unsigned long addr);
 
 /* Entries per page directory level. */
 #define PTRS_PER_PTE	(1UL << (PAGE_SHIFT-3))
 #define PTRS_PER_PMD	(1UL << PMD_BITS)
 #define PTRS_PER_PGD	(1UL << PGDIR_BITS)
+#define PTRS_PER_KPGD	(1UL << KPGD_BITS)
 
 /* Kernel has a separate 44bit address space. */
 #define FIRST_USER_ADDRESS	0
@@ -658,26 +649,26 @@ static inline unsigned long pmd_large(pmd_t pmd)
 	return pte_val(pte) & _PAGE_PMD_HUGE;
 }
 
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-static inline unsigned long pmd_young(pmd_t pmd)
+static inline unsigned long pmd_pfn(pmd_t pmd)
 {
 	pte_t pte = __pte(pmd_val(pmd));
 
-	return pte_young(pte);
+	return pte_pfn(pte);
 }
 
-static inline unsigned long pmd_write(pmd_t pmd)
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+static inline unsigned long pmd_young(pmd_t pmd)
 {
 	pte_t pte = __pte(pmd_val(pmd));
 
-	return pte_write(pte);
+	return pte_young(pte);
 }
 
-static inline unsigned long pmd_pfn(pmd_t pmd)
+static inline unsigned long pmd_write(pmd_t pmd)
 {
 	pte_t pte = __pte(pmd_val(pmd));
 
-	return pte_pfn(pte);
+	return pte_write(pte);
 }
 
 static inline unsigned long pmd_trans_huge(pmd_t pmd)
@@ -771,13 +762,11 @@ static inline int pmd_present(pmd_t pmd)
  * the top bits outside of the range of any physical address size we
  * support are clear as well.  We also validate the physical itself.
  */
-#define pmd_bad(pmd)			((pmd_val(pmd) & ~PAGE_MASK) || \
-					 !__kern_addr_valid(pmd_val(pmd)))
+#define pmd_bad(pmd)			(pmd_val(pmd) & ~PAGE_MASK)
 
 #define pud_none(pud)			(!pud_val(pud))
 
-#define pud_bad(pud)			((pud_val(pud) & ~PAGE_MASK) || \
-					 !__kern_addr_valid(pud_val(pud)))
+#define pud_bad(pud)			(pud_val(pud) & ~PAGE_MASK)
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 void set_pmd_at(struct mm_struct *mm, unsigned long addr,
@@ -819,6 +808,8 @@ static inline unsigned long __pmd_page(pmd_t pmd)
 /* Same in both SUN4V and SUN4U.  */
 #define pte_none(pte) 			(!pte_val(pte))
 
+#define kpgd_index(address)	(((address) >> KPGD_SHIFT) & (PTRS_PER_KPGD - 1))
+
 /* to find an entry in a page-table-directory. */
 #define pgd_index(address)	(((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
 #define pgd_offset(mm, address)	((mm)->pgd + pgd_index(address))
@@ -897,6 +888,7 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
 })
 #endif
 
+extern unsigned long kpgd_demux[PTRS_PER_PGD];
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 extern pmd_t swapper_low_pmd_dir[PTRS_PER_PMD];
 
diff --git a/arch/sparc/include/asm/tsb.h b/arch/sparc/include/asm/tsb.h
index 11c5047..e570894 100644
--- a/arch/sparc/include/asm/tsb.h
+++ b/arch/sparc/include/asm/tsb.h
@@ -133,27 +133,45 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
 	sub	TSB, 0x8, TSB;   \
 	TSB_STORE(TSB, TAG);
 
-	/* Do a kernel page table walk.  Leaves physical PTE pointer in
+	/* Do a kernel page table walk.  Leaves valid PTE value in
 	 * REG1.  Jumps to FAIL_LABEL on early page table walk termination.
 	 * VADDR will not be clobbered, but REG2 will.
 	 */
 #define KERN_PGTABLE_WALK(VADDR, REG1, REG2, FAIL_LABEL)	\
-	sethi		%hi(swapper_pg_dir), REG1; \
-	or		REG1, %lo(swapper_pg_dir), REG1; \
-	sllx		VADDR, 64 - (PGDIR_SHIFT + PGDIR_BITS), REG2; \
+	sethi		%hi(kpgd_demux), REG1; \
+	or		REG1, %lo(kpgd_demux), REG1; \
+	sllx		VADDR, 64 - (KPGD_SHIFT + KPGD_BITS), REG2; \
 	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
 	andn		REG2, 0x7, REG2; \
 	ldx		[REG1 + REG2], REG1; \
 	brz,pn		REG1, FAIL_LABEL; \
+	 sllx		VADDR, 64 - (PGDIR_SHIFT + PGDIR_BITS), REG2; \
+	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
+	andn		REG2, 0x7, REG2; \
+	ldxa		[REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
+	brz,pn		REG1, FAIL_LABEL; \
 	 sllx		VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \
 	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
 	andn		REG2, 0x7, REG2; \
 	ldxa		[REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
+	sethi		%uhi(_PAGE_PMD_HUGE), REG2; \
 	brz,pn		REG1, FAIL_LABEL; \
-	 sllx		VADDR, 64 - PMD_SHIFT, REG2; \
+	 sllx		REG2, 32, REG2; \
+	andcc		REG1, REG2, %g0; \
+	be,pn		%xcc, 698f; \
+	 sethi		%hi(4 * 1024 * 1024), REG2; \
+	brgez,pn	REG1, FAIL_LABEL; \
+	 andn		REG1, REG2, REG1; \
+	and		VADDR, REG2, REG2; \
+	ba,pt		%xcc, 699f; \
+	 or		REG1, REG2, REG1; \
+698:	sllx		VADDR, 64 - PMD_SHIFT, REG2; \
 	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
 	andn		REG2, 0x7, REG2; \
-	add		REG1, REG2, REG1;
+	ldxa		[REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
+	brgez,pn	REG1, FAIL_LABEL; \
+	 nop; \
+699:
 
 	/* PMD has been loaded into REG1, interpret the value, seeing
 	 * if it is a HUGE PMD or a normal one.  If it is not valid
diff --git a/arch/sparc/kernel/ktlb.S b/arch/sparc/kernel/ktlb.S
index 605d492..94a1e66 100644
--- a/arch/sparc/kernel/ktlb.S
+++ b/arch/sparc/kernel/ktlb.S
@@ -47,14 +47,6 @@ kvmap_itlb_vmalloc_addr:
 	KERN_PGTABLE_WALK(%g4, %g5, %g2, kvmap_itlb_longpath)
 
 	TSB_LOCK_TAG(%g1, %g2, %g7)
-
-	/* Load and check PTE.  */
-	ldxa		[%g5] ASI_PHYS_USE_EC, %g5
-	mov		1, %g7
-	sllx		%g7, TSB_TAG_INVALID_BIT, %g7
-	brgez,a,pn	%g5, kvmap_itlb_longpath
-	 TSB_STORE(%g1, %g7)
-
 	TSB_WRITE(%g1, %g5, %g6)
 
 	/* fallthrough to TLB load */
@@ -118,6 +110,12 @@ kvmap_dtlb_obp:
 	ba,pt		%xcc, kvmap_dtlb_load
 	 nop
 
+kvmap_linear_early:
+	sethi		%hi(kern_linear_pte_xor), %g7
+	ldx		[%g7 + %lo(kern_linear_pte_xor)], %g2
+	ba,pt		%xcc, kvmap_dtlb_tsb4m_load
+	 xor		%g2, %g4, %g5
+
 	.align		32
 kvmap_dtlb_tsb4m_load:
 	TSB_LOCK_TAG(%g1, %g2, %g7)
@@ -146,105 +144,17 @@ kvmap_dtlb_4v:
 	/* Correct TAG_TARGET is already in %g6, check 4mb TSB.  */
 	KERN_TSB4M_LOOKUP_TL1(%g6, %g5, %g1, %g2, %g3, kvmap_dtlb_load)
 #endif
-	/* TSB entry address left in %g1, lookup linear PTE.
-	 * Must preserve %g1 and %g6 (TAG).
-	 */
-kvmap_dtlb_tsb4m_miss:
-	/* Clear the PAGE_OFFSET top virtual bits, shift
-	 * down to get PFN, and make sure PFN is in range.
-	 */
-661:	sllx		%g4, 0, %g5
-	.section	.page_offset_shift_patch, "ax"
-	.word		661b
-	.previous
-
-	/* Check to see if we know about valid memory at the 4MB
-	 * chunk this physical address will reside within.
+	/* Linear mapping TSB lookup failed.  Fallthrough to kernel
+	 * page table based lookup.
 	 */
-661:	srlx		%g5, MAX_PHYS_ADDRESS_BITS, %g2
-	.section	.page_offset_shift_patch, "ax"
-	.word		661b
-	.previous
-
-	brnz,pn		%g2, kvmap_dtlb_longpath
-	 nop
-
-	/* This unconditional branch and delay-slot nop gets patched
-	 * by the sethi sequence once the bitmap is properly setup.
-	 */
-	.globl		valid_addr_bitmap_insn
-valid_addr_bitmap_insn:
-	ba,pt		%xcc, 2f
-	 nop
-	.subsection	2
-	.globl		valid_addr_bitmap_patch
-valid_addr_bitmap_patch:
-	sethi		%hi(sparc64_valid_addr_bitmap), %g7
-	or		%g7, %lo(sparc64_valid_addr_bitmap), %g7
-	.previous
-
-661:	srlx		%g5, ILOG2_4MB, %g2
-	.section	.page_offset_shift_patch, "ax"
-	.word		661b
-	.previous
-
-	srlx		%g2, 6, %g5
-	and		%g2, 63, %g2
-	sllx		%g5, 3, %g5
-	ldx		[%g7 + %g5], %g5
-	mov		1, %g7
-	sllx		%g7, %g2, %g7
-	andcc		%g5, %g7, %g0
-	be,pn		%xcc, kvmap_dtlb_longpath
-
-2:	 sethi		%hi(kpte_linear_bitmap), %g2
-
-	/* Get the 256MB physical address index. */
-661:	sllx		%g4, 0, %g5
-	.section	.page_offset_shift_patch, "ax"
-	.word		661b
-	.previous
-
-	or		%g2, %lo(kpte_linear_bitmap), %g2
-
-661:	srlx		%g5, ILOG2_256MB, %g5
-	.section	.page_offset_shift_patch, "ax"
-	.word		661b
-	.previous
-
-	and		%g5, (32 - 1), %g7
-
-	/* Divide by 32 to get the offset into the bitmask.  */
-	srlx		%g5, 5, %g5
-	add		%g7, %g7, %g7
-	sllx		%g5, 3, %g5
-
-	/* kern_linear_pte_xor[(mask >> shift) & 3)] */
-	ldx		[%g2 + %g5], %g2
-	srlx		%g2, %g7, %g7
-	sethi		%hi(kern_linear_pte_xor), %g5
-	and		%g7, 3, %g7
-	or		%g5, %lo(kern_linear_pte_xor), %g5
-	sllx		%g7, 3, %g7
-	ldx		[%g5 + %g7], %g2
-
 	.globl		kvmap_linear_patch
 kvmap_linear_patch:
-	ba,pt		%xcc, kvmap_dtlb_tsb4m_load
-	 xor		%g2, %g4, %g5
+	ba,a,pt		%xcc, kvmap_linear_early
 
 kvmap_dtlb_vmalloc_addr:
 	KERN_PGTABLE_WALK(%g4, %g5, %g2, kvmap_dtlb_longpath)
 
 	TSB_LOCK_TAG(%g1, %g2, %g7)
-
-	/* Load and check PTE.  */
-	ldxa		[%g5] ASI_PHYS_USE_EC, %g5
-	mov		1, %g7
-	sllx		%g7, TSB_TAG_INVALID_BIT, %g7
-	brgez,a,pn	%g5, kvmap_dtlb_longpath
-	 TSB_STORE(%g1, %g7)
-
 	TSB_WRITE(%g1, %g5, %g6)
 
 	/* fallthrough to TLB load */
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 971ac36..b149872 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -75,7 +75,6 @@ unsigned long kern_linear_pte_xor[4] __read_mostly;
  * 'cpu' properties, but we need to have this table setup before the
  * MDESC is initialized.
  */
-unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)];
 
 #ifndef CONFIG_DEBUG_PAGEALLOC
 /* A special kernel TSB for 4MB, 256MB, 2GB and 16GB linear mappings.
@@ -165,10 +164,6 @@ static void __init read_obp_memory(const char *property,
 	     cmp_p64, NULL);
 }
 
-unsigned long sparc64_valid_addr_bitmap[VALID_ADDR_BITMAP_BYTES /
-					sizeof(unsigned long)];
-EXPORT_SYMBOL(sparc64_valid_addr_bitmap);
-
 /* Kernel physical address base and size in bytes.  */
 unsigned long kern_base __read_mostly;
 unsigned long kern_size __read_mostly;
@@ -1369,9 +1364,45 @@ static unsigned long __init bootmem_init(unsigned long phys_base)
 static struct linux_prom64_registers pall[MAX_BANKS] __initdata;
 static int pall_ents __initdata;
 
-#ifdef CONFIG_DEBUG_PAGEALLOC
+bool kern_addr_valid(unsigned long addr)
+{
+	unsigned long pgd_pa;
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *pte;
+
+	pgd_pa = kpgd_demux[kpgd_index(addr)];
+	if (!pgd_pa)
+		return 0;
+
+	pgd = __va(pgd_pa);
+	pgd += pgd_index(addr);
+	if (pgd_none(*pgd))
+		return 0;
+
+	pud = pud_offset(pgd, addr);
+	if (pud_none(*pud))
+		return 0;
+
+	pmd = pmd_offset(pud, addr);
+	if (pmd_none(*pmd))
+		return 0;
+
+	if (pmd_large(*pmd))
+		return pfn_valid(pmd_pfn(*pmd));
+
+	pte = pte_offset_kernel(pmd, addr);
+	if (pte_none(*pte))
+		return 0;
+
+	return pfn_valid(pte_pfn(*pte));
+}
+EXPORT_SYMBOL(kern_addr_valid);
+
 static unsigned long __ref kernel_map_range(unsigned long pstart,
-					    unsigned long pend, pgprot_t prot)
+					    unsigned long pend, pgprot_t prot,
+					    bool use_huge)
 {
 	unsigned long vstart = PAGE_OFFSET + pstart;
 	unsigned long vend = PAGE_OFFSET + pend;
@@ -1385,11 +1416,23 @@ static unsigned long __ref kernel_map_range(unsigned long pstart,
 
 	while (vstart < vend) {
 		unsigned long this_end, paddr = __pa(vstart);
-		pgd_t *pgd = pgd_offset_k(vstart);
+		unsigned long kpgd_demux_index, pgd_pa;
+		pgd_t *pgd;
 		pud_t *pud;
 		pmd_t *pmd;
 		pte_t *pte;
 
+		kpgd_demux_index = kpgd_index(vstart);
+
+		pgd_pa = kpgd_demux[kpgd_demux_index];
+		if (!pgd_pa) {
+			pgd = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
+			alloc_bytes += PAGE_SIZE;
+			kpgd_demux[kpgd_demux_index] = __pa(pgd);
+		} else
+			pgd = __va(pgd_pa);
+		pgd += pgd_index(vstart);
+
 		pud = pud_offset(pgd, vstart);
 		if (pud_none(*pud)) {
 			pmd_t *new;
@@ -1403,6 +1446,14 @@ static unsigned long __ref kernel_map_range(unsigned long pstart,
 		if (!pmd_present(*pmd)) {
 			pte_t *new;
 
+			if (use_huge) {
+				u64 pte_val = vstart ^ kern_linear_pte_xor[0];
+
+				pte_val |= _PAGE_PMD_HUGE;
+				pmd_val(*pmd) = pte_val;
+				vstart += PMD_SIZE;
+				continue;
+			}
 			new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
 			alloc_bytes += PAGE_SIZE;
 			pmd_populate_kernel(&init_mm, pmd, new);
@@ -1426,99 +1477,15 @@ static unsigned long __ref kernel_map_range(unsigned long pstart,
 }
 
 extern unsigned int kvmap_linear_patch[1];
-#endif /* CONFIG_DEBUG_PAGEALLOC */
-
-static void __init kpte_set_val(unsigned long index, unsigned long val)
-{
-	unsigned long *ptr = kpte_linear_bitmap;
-
-	val <<= ((index % (BITS_PER_LONG / 2)) * 2);
-	ptr += (index / (BITS_PER_LONG / 2));
-
-	*ptr |= val;
-}
-
-static const unsigned long kpte_shift_min = 28; /* 256MB */
-static const unsigned long kpte_shift_max = 34; /* 16GB */
-static const unsigned long kpte_shift_incr = 3;
-
-static unsigned long kpte_mark_using_shift(unsigned long start, unsigned long end,
-					   unsigned long shift)
-{
-	unsigned long size = (1UL << shift);
-	unsigned long mask = (size - 1UL);
-	unsigned long remains = end - start;
-	unsigned long val;
-
-	if (remains < size || (start & mask))
-		return start;
-
-	/* VAL maps:
-	 *
-	 *	shift 28 --> kern_linear_pte_xor index 1
-	 *	shift 31 --> kern_linear_pte_xor index 2
-	 *	shift 34 --> kern_linear_pte_xor index 3
-	 */
-	val = ((shift - kpte_shift_min) / kpte_shift_incr) + 1;
-
-	remains &= ~mask;
-	if (shift != kpte_shift_max)
-		remains = size;
-
-	while (remains) {
-		unsigned long index = start >> kpte_shift_min;
-
-		kpte_set_val(index, val);
-
-		start += 1UL << kpte_shift_min;
-		remains -= 1UL << kpte_shift_min;
-	}
-
-	return start;
-}
-
-static void __init mark_kpte_bitmap(unsigned long start, unsigned long end)
-{
-	unsigned long smallest_size, smallest_mask;
-	unsigned long s;
-
-	smallest_size = (1UL << kpte_shift_min);
-	smallest_mask = (smallest_size - 1UL);
-
-	while (start < end) {
-		unsigned long orig_start = start;
-
-		for (s = kpte_shift_max; s >= kpte_shift_min; s -= kpte_shift_incr) {
-			start = kpte_mark_using_shift(start, end, s);
-
-			if (start != orig_start)
-				break;
-		}
-
-		if (start = orig_start)
-			start = (start + smallest_size) & ~smallest_mask;
-	}
-}
-
-static void __init init_kpte_bitmap(void)
-{
-	unsigned long i;
-
-	for (i = 0; i < pall_ents; i++) {
-		unsigned long phys_start, phys_end;
-
-		phys_start = pall[i].phys_addr;
-		phys_end = phys_start + pall[i].reg_size;
-
-		mark_kpte_bitmap(phys_start, phys_end);
-	}
-}
 
 static void __init kernel_physical_mapping_init(void)
 {
-#ifdef CONFIG_DEBUG_PAGEALLOC
 	unsigned long i, mem_alloced = 0UL;
+	bool use_huge = true;
 
+#ifdef CONFIG_DEBUG_PAGEALLOC
+	use_huge = false;
+#endif
 	for (i = 0; i < pall_ents; i++) {
 		unsigned long phys_start, phys_end;
 
@@ -1526,7 +1493,7 @@ static void __init kernel_physical_mapping_init(void)
 		phys_end = phys_start + pall[i].reg_size;
 
 		mem_alloced += kernel_map_range(phys_start, phys_end,
-						PAGE_KERNEL);
+						PAGE_KERNEL, use_huge);
 	}
 
 	printk("Allocated %ld bytes for kernel page tables.\n",
@@ -1536,7 +1503,6 @@ static void __init kernel_physical_mapping_init(void)
 	flushi(&kvmap_linear_patch[0]);
 
 	__flush_tlb_all();
-#endif
 }
 
 #ifdef CONFIG_DEBUG_PAGEALLOC
@@ -1546,7 +1512,7 @@ void kernel_map_pages(struct page *page, int numpages, int enable)
 	unsigned long phys_end = phys_start + (numpages * PAGE_SIZE);
 
 	kernel_map_range(phys_start, phys_end,
-			 (enable ? PAGE_KERNEL : __pgprot(0)));
+			 (enable ? PAGE_KERNEL : __pgprot(0)), false);
 
 	flush_tsb_kernel_range(PAGE_OFFSET + phys_start,
 			       PAGE_OFFSET + phys_end);
@@ -1878,6 +1844,7 @@ static void __init sun4v_linear_pte_xor_finalize(void)
 /* paging_init() sets up the page tables */
 
 static unsigned long last_valid_pfn;
+unsigned long kpgd_demux[PTRS_PER_PGD];
 pgd_t swapper_pg_dir[PTRS_PER_PGD];
 
 static void sun4u_pgprot_init(void);
@@ -2027,17 +1994,16 @@ void __init paging_init(void)
 	 * work.
 	 */
 	init_mm.pgd += ((shift) / (sizeof(pgd_t)));
+	kpgd_demux[0] = __pa(init_mm.pgd);
 	
 	memset(swapper_low_pmd_dir, 0, sizeof(swapper_low_pmd_dir));
 
 	/* Now can init the kernel/bad page tables. */
 	pud_set(pud_offset(&swapper_pg_dir[0], 0),
 		swapper_low_pmd_dir + (shift / sizeof(pgd_t)));
-	
+
 	inherit_prom_mappings();
 	
-	init_kpte_bitmap();
-
 	/* Ok, we can use our TLB miss and window trap handlers safely.  */
 	setup_tba();
 
@@ -2144,70 +2110,6 @@ int page_in_phys_avail(unsigned long paddr)
 	return 0;
 }
 
-static struct linux_prom64_registers pavail_rescan[MAX_BANKS] __initdata;
-static int pavail_rescan_ents __initdata;
-
-/* Certain OBP calls, such as fetching "available" properties, can
- * claim physical memory.  So, along with initializing the valid
- * address bitmap, what we do here is refetch the physical available
- * memory list again, and make sure it provides at least as much
- * memory as 'pavail' does.
- */
-static void __init setup_valid_addr_bitmap_from_pavail(unsigned long *bitmap)
-{
-	int i;
-
-	read_obp_memory("available", &pavail_rescan[0], &pavail_rescan_ents);
-
-	for (i = 0; i < pavail_ents; i++) {
-		unsigned long old_start, old_end;
-
-		old_start = pavail[i].phys_addr;
-		old_end = old_start + pavail[i].reg_size;
-		while (old_start < old_end) {
-			int n;
-
-			for (n = 0; n < pavail_rescan_ents; n++) {
-				unsigned long new_start, new_end;
-
-				new_start = pavail_rescan[n].phys_addr;
-				new_end = new_start +
-					pavail_rescan[n].reg_size;
-
-				if (new_start <= old_start &&
-				    new_end >= (old_start + PAGE_SIZE)) {
-					set_bit(old_start >> ILOG2_4MB, bitmap);
-					goto do_next_page;
-				}
-			}
-
-			prom_printf("mem_init: Lost memory in pavail\n");
-			prom_printf("mem_init: OLD start[%lx] size[%lx]\n",
-				    pavail[i].phys_addr,
-				    pavail[i].reg_size);
-			prom_printf("mem_init: NEW start[%lx] size[%lx]\n",
-				    pavail_rescan[i].phys_addr,
-				    pavail_rescan[i].reg_size);
-			prom_printf("mem_init: Cannot continue, aborting.\n");
-			prom_halt();
-
-		do_next_page:
-			old_start += PAGE_SIZE;
-		}
-	}
-}
-
-static void __init patch_tlb_miss_handler_bitmap(void)
-{
-	extern unsigned int valid_addr_bitmap_insn[];
-	extern unsigned int valid_addr_bitmap_patch[];
-
-	valid_addr_bitmap_insn[1] = valid_addr_bitmap_patch[1];
-	mb();
-	valid_addr_bitmap_insn[0] = valid_addr_bitmap_patch[0];
-	flushi(&valid_addr_bitmap_insn[0]);
-}
-
 static void __init register_page_bootmem_info(void)
 {
 #ifdef CONFIG_NEED_MULTIPLE_NODES
@@ -2220,18 +2122,6 @@ static void __init register_page_bootmem_info(void)
 }
 void __init mem_init(void)
 {
-	unsigned long addr, last;
-
-	addr = PAGE_OFFSET + kern_base;
-	last = PAGE_ALIGN(kern_size) + addr;
-	while (addr < last) {
-		set_bit(__pa(addr) >> ILOG2_4MB, sparc64_valid_addr_bitmap);
-		addr += PAGE_SIZE;
-	}
-
-	setup_valid_addr_bitmap_from_pavail(sparc64_valid_addr_bitmap);
-	patch_tlb_miss_handler_bitmap();
-
 	high_memory = __va(last_valid_pfn << PAGE_SHIFT);
 
 	register_page_bootmem_info();
diff --git a/arch/sparc/mm/init_64.h b/arch/sparc/mm/init_64.h
index 0668b36..29ff73f 100644
--- a/arch/sparc/mm/init_64.h
+++ b/arch/sparc/mm/init_64.h
@@ -8,15 +8,8 @@
  */
 
 #define MAX_PHYS_ADDRESS	(1UL << MAX_PHYS_ADDRESS_BITS)
-#define KPTE_BITMAP_CHUNK_SZ		(256UL * 1024UL * 1024UL)
-#define KPTE_BITMAP_BYTES	\
-	((MAX_PHYS_ADDRESS / KPTE_BITMAP_CHUNK_SZ) / 4)
-#define VALID_ADDR_BITMAP_CHUNK_SZ	(4UL * 1024UL * 1024UL)
-#define VALID_ADDR_BITMAP_BYTES	\
-	((MAX_PHYS_ADDRESS / VALID_ADDR_BITMAP_CHUNK_SZ) / 8)
 
 extern unsigned long kern_linear_pte_xor[4];
-extern unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)];
 extern unsigned int sparc64_highest_unlocked_tlb_ent;
 extern unsigned long sparc64_kern_pri_context;
 extern unsigned long sparc64_kern_pri_nuc_bits;

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction
  2014-09-16 16:50 [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction Bob Picco
                   ` (14 preceding siblings ...)
  2014-09-22  4:22 ` David Miller
@ 2014-09-22 18:56 ` Bob Picco
  2014-09-22 19:13 ` David Miller
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Bob Picco @ 2014-09-22 18:56 UTC (permalink / raw)
  To: sparclinux

Hi,
David Miller wrote:	[Mon Sep 22 2014, 12:22:46AM EDT]
> From: Bob Picco <bpicco@meloft.net>
> Date: Fri, 19 Sep 2014 15:57:31 -0400
> 
> > Hi,
> > David Miller wrote:	[Fri Sep 19 2014, 03:28:46PM EDT]
> >> From: David Miller <davem@davemloft.net>
> >> Date: Thu, 18 Sep 2014 19:16:37 -0400 (EDT)
> >> 
> >> > I'm half-way done with the "use kernel page tables for everything"
> >> > patch, and will post once I have something that at least work for
> >> > me.
> >> 
> >> Bob, I ran into a major roadblock which is going to delay this work
> >> a little bit.
> > Okay.
> >> 
> >> In fact it pointed out a bug we introduced when increasing max phys
> >> bits to 47.  We broke DEBUG_PAGEALLOC completely.  The issue is that
> >> the page table layout only supports up to 43-bits.
> > Oh bugger yes. I recall testing this when first introducting four level
> > page table layout in late 2012 and early 2013. It just isn't an everyday
> > thought but VERY nice to have.
> >> 
> >> I'll brain storm about this over the weekend.
> > Me too.
> 
> Ok, here is what I have so far and I just got it working.
I thought about this issue some over the weekend and PRIQ. Most variants 
considered for this issue were not appealing.
> 
> The long and short of it is that we have a 4-level page table
> but only for the PAGE_OFFSET linear kernel mappings.
This is the variant that seems good to me. It should prevent future issues
for at least another core revision - me hopes.
> 
> To the rest of the kernel this is transparent, because all
> vmalloc et al. mappings have virtual addresses which index
> to swapper_pg_dir.
Yes, I reviewed most of the code before attempting to use it :)

Jalap?no and T5-2 seem happy. From T5-2:
[    0.000000] Kernel: Using 3 locked TLB entries for main kernel image.
> 
> The only thing I have to do is bring back 256MB et al. mapping usage
> for suitable aligned PAGE_OFFSET linear areas.  It's only using 4MB
> mappings at the moment.
Okay.

I'll review more.

Oh and boot with DEBUG_PAGEALLOC at some point.
Alright, need to chase a DEBUG_PAGEALLOC issue with prom_halt() blink:
[bpicco@zareason ~]$ cat /tmp/t5-blink.txt
[23233.728105] IPv6: ADDRCONF(NETDEV_CHANGE): eth1: link becomes ready
[23233.753380] SUN4V-DTLB: Error at TPC[446930], tl 1
[23233.762729] SUN4V-DTLB: TPC<dma_4v_map_page+0x10/0x220>
[23233.773124] SUN4V-DTLB: O7[55206c]
[23233.779910] SUN4V-DTLB: O7<cache_grow+0x12c/0x200>
[23233.789455] SUN4V-DTLB: vaddr[1103f23e000] ctx[0] pte[0] error[2]
. We were nearly at the console login prompt. Hm, maybe turn off LDOMS
config :)

thanx and nice!

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction
  2014-09-16 16:50 [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction Bob Picco
                   ` (15 preceding siblings ...)
  2014-09-22 18:56 ` Bob Picco
@ 2014-09-22 19:13 ` David Miller
  2014-09-24 22:26 ` David Miller
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: David Miller @ 2014-09-22 19:13 UTC (permalink / raw)
  To: sparclinux

From: Bob Picco <bpicco@meloft.net>
Date: Mon, 22 Sep 2014 14:56:31 -0400

> David Miller wrote:	[Mon Sep 22 2014, 12:22:46AM EDT]
>> From: Bob Picco <bpicco@meloft.net>
>> Date: Fri, 19 Sep 2014 15:57:31 -0400
>> 
>> To the rest of the kernel this is transparent, because all
>> vmalloc et al. mappings have virtual addresses which index
>> to swapper_pg_dir.
> Yes, I reviewed most of the code before attempting to use it :)
> 
> Jalap?no and T5-2 seem happy. From T5-2:
> [    0.000000] Kernel: Using 3 locked TLB entries for main kernel image.

Yeah we only get down to 2 locked TLB entries when we deal with
ditching the vmemmap table too, which I'll work on combining into this
work.

> Alright, need to chase a DEBUG_PAGEALLOC issue with prom_halt() blink:
> [bpicco@zareason ~]$ cat /tmp/t5-blink.txt
> [23233.728105] IPv6: ADDRCONF(NETDEV_CHANGE): eth1: link becomes ready
> [23233.753380] SUN4V-DTLB: Error at TPC[446930], tl 1
> [23233.762729] SUN4V-DTLB: TPC<dma_4v_map_page+0x10/0x220>
> [23233.773124] SUN4V-DTLB: O7[55206c]
> [23233.779910] SUN4V-DTLB: O7<cache_grow+0x12c/0x200>
> [23233.789455] SUN4V-DTLB: vaddr[1103f23e000] ctx[0] pte[0] error[2]
> . We were nearly at the console login prompt. Hm, maybe turn off LDOMS
> config :)

Hmmm...

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction
  2014-09-16 16:50 [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction Bob Picco
                   ` (16 preceding siblings ...)
  2014-09-22 19:13 ` David Miller
@ 2014-09-24 22:26 ` David Miller
  2014-09-24 23:12 ` Bob Picco
  2014-09-25 17:43 ` Bob Picco
  19 siblings, 0 replies; 21+ messages in thread
From: David Miller @ 2014-09-24 22:26 UTC (permalink / raw)
  To: sparclinux

From: Bob Picco <bpicco@meloft.net>
Date: Mon, 22 Sep 2014 14:56:31 -0400

> I'll review more.
> 
> Oh and boot with DEBUG_PAGEALLOC at some point.
> Alright, need to chase a DEBUG_PAGEALLOC issue with prom_halt() blink:
> [bpicco@zareason ~]$ cat /tmp/t5-blink.txt
> [23233.728105] IPv6: ADDRCONF(NETDEV_CHANGE): eth1: link becomes ready
> [23233.753380] SUN4V-DTLB: Error at TPC[446930], tl 1
> [23233.762729] SUN4V-DTLB: TPC<dma_4v_map_page+0x10/0x220>
> [23233.773124] SUN4V-DTLB: O7[55206c]
> [23233.779910] SUN4V-DTLB: O7<cache_grow+0x12c/0x200>
> [23233.789455] SUN4V-DTLB: vaddr[1103f23e000] ctx[0] pte[0] error[2]
> . We were nearly at the console login prompt. Hm, maybe turn off LDOMS
> config :)
> 
> thanx and nice!

Bob, here is what I have now, can you please help me test it?

It should restore 256MB/2GB/16GB page size usage.

The biggest bug was that I wasn't flushing the kernel TSB(s)
after building the kernel page tables and NOP'ing out that
instruction in kernel_physical_mapping_init().

Once I fixed that everything runs smoothly so far :-)

I haven't gotten to testing DEBUG_PAGEALLOC yet, but I suspect it
probably works now.

Thanks!

diff --git a/arch/sparc/include/asm/page_64.h b/arch/sparc/include/asm/page_64.h
index bf10998..4af4e69 100644
--- a/arch/sparc/include/asm/page_64.h
+++ b/arch/sparc/include/asm/page_64.h
@@ -129,9 +129,6 @@ extern unsigned long PAGE_OFFSET;
  */
 #define MAX_PHYS_ADDRESS_BITS	47
 
-/* These two shift counts are used when indexing sparc64_valid_addr_bitmap
- * and kpte_linear_bitmap.
- */
 #define ILOG2_4MB		22
 #define ILOG2_256MB		28
 
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
index 3770bf5..a8042fb 100644
--- a/arch/sparc/include/asm/pgtable_64.h
+++ b/arch/sparc/include/asm/pgtable_64.h
@@ -61,6 +61,11 @@
 #define PGDIR_MASK	(~(PGDIR_SIZE-1))
 #define PGDIR_BITS	(PAGE_SHIFT - 3)
 
+#define KPGD_SHIFT	(PAGE_SHIFT + (PAGE_SHIFT-3) + (PAGE_SHIFT-3) + PGDIR_BITS)
+#define KPGD_SIZE	(_AC(1,UL) << KPGD_SHIFT)
+#define KPGD_MASK	(~(KPGD_SIZE-1))
+#define KPGD_BITS	(PAGE_SHIFT - 3)
+
 #if (PGDIR_SHIFT + PGDIR_BITS) != 43
 #error Page table parameters do not cover virtual address space properly.
 #endif
@@ -73,27 +78,13 @@
 
 #include <linux/sched.h>
 
-extern unsigned long sparc64_valid_addr_bitmap[];
-
-/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
-static inline bool __kern_addr_valid(unsigned long paddr)
-{
-	if ((paddr >> MAX_PHYS_ADDRESS_BITS) != 0UL)
-		return false;
-	return test_bit(paddr >> ILOG2_4MB, sparc64_valid_addr_bitmap);
-}
-
-static inline bool kern_addr_valid(unsigned long addr)
-{
-	unsigned long paddr = __pa(addr);
-
-	return __kern_addr_valid(paddr);
-}
+bool kern_addr_valid(unsigned long addr);
 
 /* Entries per page directory level. */
 #define PTRS_PER_PTE	(1UL << (PAGE_SHIFT-3))
 #define PTRS_PER_PMD	(1UL << PMD_BITS)
 #define PTRS_PER_PGD	(1UL << PGDIR_BITS)
+#define PTRS_PER_KPGD	(1UL << KPGD_BITS)
 
 /* Kernel has a separate 44bit address space. */
 #define FIRST_USER_ADDRESS	0
@@ -112,6 +103,7 @@ static inline bool kern_addr_valid(unsigned long addr)
 #define _PAGE_R	  	  _AC(0x8000000000000000,UL) /* Keep ref bit uptodate*/
 #define _PAGE_SPECIAL     _AC(0x0200000000000000,UL) /* Special page         */
 #define _PAGE_PMD_HUGE    _AC(0x0100000000000000,UL) /* Huge page            */
+#define _PAGE_PUD_HUGE    _PAGE_PMD_HUGE
 
 /* Advertise support for _PAGE_SPECIAL */
 #define __HAVE_ARCH_PTE_SPECIAL
@@ -658,26 +650,26 @@ static inline unsigned long pmd_large(pmd_t pmd)
 	return pte_val(pte) & _PAGE_PMD_HUGE;
 }
 
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-static inline unsigned long pmd_young(pmd_t pmd)
+static inline unsigned long pmd_pfn(pmd_t pmd)
 {
 	pte_t pte = __pte(pmd_val(pmd));
 
-	return pte_young(pte);
+	return pte_pfn(pte);
 }
 
-static inline unsigned long pmd_write(pmd_t pmd)
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+static inline unsigned long pmd_young(pmd_t pmd)
 {
 	pte_t pte = __pte(pmd_val(pmd));
 
-	return pte_write(pte);
+	return pte_young(pte);
 }
 
-static inline unsigned long pmd_pfn(pmd_t pmd)
+static inline unsigned long pmd_write(pmd_t pmd)
 {
 	pte_t pte = __pte(pmd_val(pmd));
 
-	return pte_pfn(pte);
+	return pte_write(pte);
 }
 
 static inline unsigned long pmd_trans_huge(pmd_t pmd)
@@ -771,13 +763,11 @@ static inline int pmd_present(pmd_t pmd)
  * the top bits outside of the range of any physical address size we
  * support are clear as well.  We also validate the physical itself.
  */
-#define pmd_bad(pmd)			((pmd_val(pmd) & ~PAGE_MASK) || \
-					 !__kern_addr_valid(pmd_val(pmd)))
+#define pmd_bad(pmd)			(pmd_val(pmd) & ~PAGE_MASK)
 
 #define pud_none(pud)			(!pud_val(pud))
 
-#define pud_bad(pud)			((pud_val(pud) & ~PAGE_MASK) || \
-					 !__kern_addr_valid(pud_val(pud)))
+#define pud_bad(pud)			(pud_val(pud) & ~PAGE_MASK)
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 void set_pmd_at(struct mm_struct *mm, unsigned long addr,
@@ -816,9 +806,25 @@ static inline unsigned long __pmd_page(pmd_t pmd)
 #define pud_present(pud)		(pud_val(pud) != 0U)
 #define pud_clear(pudp)			(pud_val(*(pudp)) = 0UL)
 
+static inline unsigned long pud_large(pud_t pud)
+{
+	pte_t pte = __pte(pud_val(pud));
+
+	return pte_val(pte) & _PAGE_PMD_HUGE;
+}
+
+static inline unsigned long pud_pfn(pud_t pud)
+{
+	pte_t pte = __pte(pud_val(pud));
+
+	return pte_pfn(pte);
+}
+
 /* Same in both SUN4V and SUN4U.  */
 #define pte_none(pte) 			(!pte_val(pte))
 
+#define kpgd_index(address)	(((address) >> KPGD_SHIFT) & (PTRS_PER_KPGD - 1))
+
 /* to find an entry in a page-table-directory. */
 #define pgd_index(address)	(((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
 #define pgd_offset(mm, address)	((mm)->pgd + pgd_index(address))
@@ -897,6 +903,7 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
 })
 #endif
 
+extern unsigned long kpgd_demux[PTRS_PER_PGD];
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 extern pmd_t swapper_low_pmd_dir[PTRS_PER_PMD];
 
diff --git a/arch/sparc/include/asm/tsb.h b/arch/sparc/include/asm/tsb.h
index 11c5047..1a18148 100644
--- a/arch/sparc/include/asm/tsb.h
+++ b/arch/sparc/include/asm/tsb.h
@@ -133,27 +133,50 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
 	sub	TSB, 0x8, TSB;   \
 	TSB_STORE(TSB, TAG);
 
-	/* Do a kernel page table walk.  Leaves physical PTE pointer in
+	/* Do a kernel page table walk.  Leaves valid PTE value in
 	 * REG1.  Jumps to FAIL_LABEL on early page table walk termination.
 	 * VADDR will not be clobbered, but REG2 will.
 	 */
 #define KERN_PGTABLE_WALK(VADDR, REG1, REG2, FAIL_LABEL)	\
-	sethi		%hi(swapper_pg_dir), REG1; \
-	or		REG1, %lo(swapper_pg_dir), REG1; \
-	sllx		VADDR, 64 - (PGDIR_SHIFT + PGDIR_BITS), REG2; \
+	sethi		%hi(kpgd_demux), REG1; \
+	or		REG1, %lo(kpgd_demux), REG1; \
+	sllx		VADDR, 64 - (KPGD_SHIFT + KPGD_BITS), REG2; \
 	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
 	andn		REG2, 0x7, REG2; \
 	ldx		[REG1 + REG2], REG1; \
 	brz,pn		REG1, FAIL_LABEL; \
+	 sllx		VADDR, 64 - (PGDIR_SHIFT + PGDIR_BITS), REG2; \
+	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
+	andn		REG2, 0x7, REG2; \
+	ldxa		[REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
+	sethi		%uhi(_PAGE_PUD_HUGE), REG2; \
+	brz,pn		REG1, FAIL_LABEL; \
+	 sllx		REG2, 32, REG2; \
+	andcc		REG1, REG2, %g0; \
+	bne,pt		%xcc, 697f; \
 	 sllx		VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \
 	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
 	andn		REG2, 0x7, REG2; \
 	ldxa		[REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
+	sethi		%uhi(_PAGE_PMD_HUGE), REG2; \
 	brz,pn		REG1, FAIL_LABEL; \
-	 sllx		VADDR, 64 - PMD_SHIFT, REG2; \
+	 sllx		REG2, 32, REG2; \
+	andcc		REG1, REG2, %g0; \
+	be,pn		%xcc, 698f; \
+697:	 sethi		%hi(0xffe00000), REG2; \
+	sllx		REG2, 1, REG2; \
+	brgez,pn	REG1, FAIL_LABEL; \
+	 andn		REG1, REG2, REG1; \
+	and		VADDR, REG2, REG2; \
+	ba,pt		%xcc, 699f; \
+	 or		REG1, REG2, REG1; \
+698:	sllx		VADDR, 64 - PMD_SHIFT, REG2; \
 	srlx		REG2, 64 - PAGE_SHIFT, REG2; \
 	andn		REG2, 0x7, REG2; \
-	add		REG1, REG2, REG1;
+	ldxa		[REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
+	brgez,pn	REG1, FAIL_LABEL; \
+	 nop; \
+699:
 
 	/* PMD has been loaded into REG1, interpret the value, seeing
 	 * if it is a HUGE PMD or a normal one.  If it is not valid
diff --git a/arch/sparc/kernel/ktlb.S b/arch/sparc/kernel/ktlb.S
index 605d492..94a1e66 100644
--- a/arch/sparc/kernel/ktlb.S
+++ b/arch/sparc/kernel/ktlb.S
@@ -47,14 +47,6 @@ kvmap_itlb_vmalloc_addr:
 	KERN_PGTABLE_WALK(%g4, %g5, %g2, kvmap_itlb_longpath)
 
 	TSB_LOCK_TAG(%g1, %g2, %g7)
-
-	/* Load and check PTE.  */
-	ldxa		[%g5] ASI_PHYS_USE_EC, %g5
-	mov		1, %g7
-	sllx		%g7, TSB_TAG_INVALID_BIT, %g7
-	brgez,a,pn	%g5, kvmap_itlb_longpath
-	 TSB_STORE(%g1, %g7)
-
 	TSB_WRITE(%g1, %g5, %g6)
 
 	/* fallthrough to TLB load */
@@ -118,6 +110,12 @@ kvmap_dtlb_obp:
 	ba,pt		%xcc, kvmap_dtlb_load
 	 nop
 
+kvmap_linear_early:
+	sethi		%hi(kern_linear_pte_xor), %g7
+	ldx		[%g7 + %lo(kern_linear_pte_xor)], %g2
+	ba,pt		%xcc, kvmap_dtlb_tsb4m_load
+	 xor		%g2, %g4, %g5
+
 	.align		32
 kvmap_dtlb_tsb4m_load:
 	TSB_LOCK_TAG(%g1, %g2, %g7)
@@ -146,105 +144,17 @@ kvmap_dtlb_4v:
 	/* Correct TAG_TARGET is already in %g6, check 4mb TSB.  */
 	KERN_TSB4M_LOOKUP_TL1(%g6, %g5, %g1, %g2, %g3, kvmap_dtlb_load)
 #endif
-	/* TSB entry address left in %g1, lookup linear PTE.
-	 * Must preserve %g1 and %g6 (TAG).
-	 */
-kvmap_dtlb_tsb4m_miss:
-	/* Clear the PAGE_OFFSET top virtual bits, shift
-	 * down to get PFN, and make sure PFN is in range.
-	 */
-661:	sllx		%g4, 0, %g5
-	.section	.page_offset_shift_patch, "ax"
-	.word		661b
-	.previous
-
-	/* Check to see if we know about valid memory at the 4MB
-	 * chunk this physical address will reside within.
+	/* Linear mapping TSB lookup failed.  Fallthrough to kernel
+	 * page table based lookup.
 	 */
-661:	srlx		%g5, MAX_PHYS_ADDRESS_BITS, %g2
-	.section	.page_offset_shift_patch, "ax"
-	.word		661b
-	.previous
-
-	brnz,pn		%g2, kvmap_dtlb_longpath
-	 nop
-
-	/* This unconditional branch and delay-slot nop gets patched
-	 * by the sethi sequence once the bitmap is properly setup.
-	 */
-	.globl		valid_addr_bitmap_insn
-valid_addr_bitmap_insn:
-	ba,pt		%xcc, 2f
-	 nop
-	.subsection	2
-	.globl		valid_addr_bitmap_patch
-valid_addr_bitmap_patch:
-	sethi		%hi(sparc64_valid_addr_bitmap), %g7
-	or		%g7, %lo(sparc64_valid_addr_bitmap), %g7
-	.previous
-
-661:	srlx		%g5, ILOG2_4MB, %g2
-	.section	.page_offset_shift_patch, "ax"
-	.word		661b
-	.previous
-
-	srlx		%g2, 6, %g5
-	and		%g2, 63, %g2
-	sllx		%g5, 3, %g5
-	ldx		[%g7 + %g5], %g5
-	mov		1, %g7
-	sllx		%g7, %g2, %g7
-	andcc		%g5, %g7, %g0
-	be,pn		%xcc, kvmap_dtlb_longpath
-
-2:	 sethi		%hi(kpte_linear_bitmap), %g2
-
-	/* Get the 256MB physical address index. */
-661:	sllx		%g4, 0, %g5
-	.section	.page_offset_shift_patch, "ax"
-	.word		661b
-	.previous
-
-	or		%g2, %lo(kpte_linear_bitmap), %g2
-
-661:	srlx		%g5, ILOG2_256MB, %g5
-	.section	.page_offset_shift_patch, "ax"
-	.word		661b
-	.previous
-
-	and		%g5, (32 - 1), %g7
-
-	/* Divide by 32 to get the offset into the bitmask.  */
-	srlx		%g5, 5, %g5
-	add		%g7, %g7, %g7
-	sllx		%g5, 3, %g5
-
-	/* kern_linear_pte_xor[(mask >> shift) & 3)] */
-	ldx		[%g2 + %g5], %g2
-	srlx		%g2, %g7, %g7
-	sethi		%hi(kern_linear_pte_xor), %g5
-	and		%g7, 3, %g7
-	or		%g5, %lo(kern_linear_pte_xor), %g5
-	sllx		%g7, 3, %g7
-	ldx		[%g5 + %g7], %g2
-
 	.globl		kvmap_linear_patch
 kvmap_linear_patch:
-	ba,pt		%xcc, kvmap_dtlb_tsb4m_load
-	 xor		%g2, %g4, %g5
+	ba,a,pt		%xcc, kvmap_linear_early
 
 kvmap_dtlb_vmalloc_addr:
 	KERN_PGTABLE_WALK(%g4, %g5, %g2, kvmap_dtlb_longpath)
 
 	TSB_LOCK_TAG(%g1, %g2, %g7)
-
-	/* Load and check PTE.  */
-	ldxa		[%g5] ASI_PHYS_USE_EC, %g5
-	mov		1, %g7
-	sllx		%g7, TSB_TAG_INVALID_BIT, %g7
-	brgez,a,pn	%g5, kvmap_dtlb_longpath
-	 TSB_STORE(%g1, %g7)
-
 	TSB_WRITE(%g1, %g5, %g6)
 
 	/* fallthrough to TLB load */
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 971ac36..c33b239 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -75,7 +75,6 @@ unsigned long kern_linear_pte_xor[4] __read_mostly;
  * 'cpu' properties, but we need to have this table setup before the
  * MDESC is initialized.
  */
-unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)];
 
 #ifndef CONFIG_DEBUG_PAGEALLOC
 /* A special kernel TSB for 4MB, 256MB, 2GB and 16GB linear mappings.
@@ -84,6 +83,7 @@ unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)];
  */
 extern struct tsb swapper_4m_tsb[KERNEL_TSB4M_NENTRIES];
 #endif
+extern struct tsb swapper_tsb[KERNEL_TSB_NENTRIES];
 
 static unsigned long cpu_pgsz_mask;
 
@@ -165,10 +165,6 @@ static void __init read_obp_memory(const char *property,
 	     cmp_p64, NULL);
 }
 
-unsigned long sparc64_valid_addr_bitmap[VALID_ADDR_BITMAP_BYTES /
-					sizeof(unsigned long)];
-EXPORT_SYMBOL(sparc64_valid_addr_bitmap);
-
 /* Kernel physical address base and size in bytes.  */
 unsigned long kern_base __read_mostly;
 unsigned long kern_size __read_mostly;
@@ -1369,9 +1365,137 @@ static unsigned long __init bootmem_init(unsigned long phys_base)
 static struct linux_prom64_registers pall[MAX_BANKS] __initdata;
 static int pall_ents __initdata;
 
-#ifdef CONFIG_DEBUG_PAGEALLOC
+bool kern_addr_valid(unsigned long addr)
+{
+	unsigned long pgd_pa;
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *pte;
+
+	if (addr >= (unsigned long) KERNBASE &&
+	    addr < (unsigned long)&_end)
+		return true;
+
+	if (addr >= PAGE_OFFSET) {
+		unsigned long pa = __pa(addr);
+
+		return pfn_valid(pa >> PAGE_SHIFT);
+	}
+
+	pgd_pa = kpgd_demux[kpgd_index(addr)];
+	if (!pgd_pa)
+		return 0;
+
+	pgd = __va(pgd_pa);
+	pgd += pgd_index(addr);
+	if (pgd_none(*pgd))
+		return 0;
+
+	pud = pud_offset(pgd, addr);
+	if (pud_none(*pud))
+		return 0;
+
+	if (pud_large(*pud))
+		return pfn_valid(pud_pfn(*pud));
+
+	pmd = pmd_offset(pud, addr);
+	if (pmd_none(*pmd))
+		return 0;
+
+	if (pmd_large(*pmd))
+		return pfn_valid(pmd_pfn(*pmd));
+
+	pte = pte_offset_kernel(pmd, addr);
+	if (pte_none(*pte))
+		return 0;
+
+	return pfn_valid(pte_pfn(*pte));
+}
+EXPORT_SYMBOL(kern_addr_valid);
+
+static unsigned long __ref kernel_map_hugepud(unsigned long vstart,
+					      unsigned long vend,
+					      pud_t *pud)
+{
+	const unsigned long mask16gb = (1UL << 34) - 1UL;
+	u64 pte_val = vstart;
+
+	/* Each PUD is 8GB */
+	if ((vstart & mask16gb) ||
+	    (vend - vstart <= mask16gb)) {
+		pte_val ^= kern_linear_pte_xor[2];
+		pud_val(*pud) = pte_val | _PAGE_PUD_HUGE;
+
+		return vstart + PUD_SIZE;
+	}
+
+	pte_val ^= kern_linear_pte_xor[3];
+	pte_val |= _PAGE_PUD_HUGE;
+
+	vend = vstart + mask16gb + 1UL;
+	while (vstart < vend) {
+		pud_val(*pud) = pte_val;
+
+		pte_val += PUD_SIZE;
+		vstart += PUD_SIZE;
+		pud++;
+	}
+	return vstart;
+}
+
+static bool kernel_can_map_hugepud(unsigned long vstart, unsigned long vend,
+				   bool guard)
+{
+	if (guard && !(vstart & ~PUD_MASK) && (vend - vstart) >= PUD_SIZE)
+		return true;
+
+	return false;
+}
+
+static unsigned long __ref kernel_map_hugepmd(unsigned long vstart,
+					      unsigned long vend,
+					      pmd_t *pmd)
+{
+	const unsigned long mask256mb = (1UL << 28) - 1UL;
+	u64 pte_val = vstart;
+
+	/* Each PMD is 8MB */
+	if ((vstart & mask256mb) ||
+	    (vend - vstart <= mask256mb)) {
+		pte_val ^= kern_linear_pte_xor[0];
+		pmd_val(*pmd) = pte_val | _PAGE_PMD_HUGE;
+
+		return vstart + PMD_SIZE;
+	}
+
+	pte_val ^= kern_linear_pte_xor[1];
+	pte_val |= _PAGE_PMD_HUGE;
+
+	vend = vstart + mask256mb + 1UL;
+	while (vstart < vend) {
+		pmd_val(*pmd) = pte_val;
+
+		pte_val += PMD_SIZE;
+		vstart += PMD_SIZE;
+		pmd++;
+	}
+
+	return vstart;
+}
+
+static bool kernel_can_map_hugepmd(unsigned long vstart, unsigned long vend,
+				   bool guard)
+{
+	if (guard && !(vstart & ~PMD_MASK) && (vend - vstart) >= PMD_SIZE)
+		return true;
+
+	return false;
+}
+
 static unsigned long __ref kernel_map_range(unsigned long pstart,
-					    unsigned long pend, pgprot_t prot)
+					    unsigned long pend, pgprot_t prot,
+					    bool use_huge)
 {
 	unsigned long vstart = PAGE_OFFSET + pstart;
 	unsigned long vend = PAGE_OFFSET + pend;
@@ -1385,24 +1509,44 @@ static unsigned long __ref kernel_map_range(unsigned long pstart,
 
 	while (vstart < vend) {
 		unsigned long this_end, paddr = __pa(vstart);
-		pgd_t *pgd = pgd_offset_k(vstart);
+		unsigned long kpgd_demux_index, pgd_pa;
+		pgd_t *pgd;
 		pud_t *pud;
 		pmd_t *pmd;
 		pte_t *pte;
 
+		kpgd_demux_index = kpgd_index(vstart);
+
+		pgd_pa = kpgd_demux[kpgd_demux_index];
+		if (!pgd_pa) {
+			pgd = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
+			alloc_bytes += PAGE_SIZE;
+			kpgd_demux[kpgd_demux_index] = __pa(pgd);
+		} else
+			pgd = __va(pgd_pa);
+		pgd += pgd_index(vstart);
+
 		pud = pud_offset(pgd, vstart);
 		if (pud_none(*pud)) {
 			pmd_t *new;
 
+			if (kernel_can_map_hugepud(vstart, vend, use_huge)) {
+				vstart = kernel_map_hugepud(vstart, vend, pud);
+				continue;
+			}
 			new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
 			alloc_bytes += PAGE_SIZE;
 			pud_populate(&init_mm, pud, new);
 		}
 
 		pmd = pmd_offset(pud, vstart);
-		if (!pmd_present(*pmd)) {
+		if (pmd_none(*pmd)) {
 			pte_t *new;
 
+			if (kernel_can_map_hugepmd(vstart, vend, use_huge)) {
+				vstart = kernel_map_hugepmd(vstart, vend, pmd);
+				continue;
+			}
 			new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
 			alloc_bytes += PAGE_SIZE;
 			pmd_populate_kernel(&init_mm, pmd, new);
@@ -1425,100 +1569,34 @@ static unsigned long __ref kernel_map_range(unsigned long pstart,
 	return alloc_bytes;
 }
 
-extern unsigned int kvmap_linear_patch[1];
-#endif /* CONFIG_DEBUG_PAGEALLOC */
-
-static void __init kpte_set_val(unsigned long index, unsigned long val)
+static void __init flush_all_kernel_tsbs(void)
 {
-	unsigned long *ptr = kpte_linear_bitmap;
-
-	val <<= ((index % (BITS_PER_LONG / 2)) * 2);
-	ptr += (index / (BITS_PER_LONG / 2));
-
-	*ptr |= val;
-}
-
-static const unsigned long kpte_shift_min = 28; /* 256MB */
-static const unsigned long kpte_shift_max = 34; /* 16GB */
-static const unsigned long kpte_shift_incr = 3;
-
-static unsigned long kpte_mark_using_shift(unsigned long start, unsigned long end,
-					   unsigned long shift)
-{
-	unsigned long size = (1UL << shift);
-	unsigned long mask = (size - 1UL);
-	unsigned long remains = end - start;
-	unsigned long val;
-
-	if (remains < size || (start & mask))
-		return start;
-
-	/* VAL maps:
-	 *
-	 *	shift 28 --> kern_linear_pte_xor index 1
-	 *	shift 31 --> kern_linear_pte_xor index 2
-	 *	shift 34 --> kern_linear_pte_xor index 3
-	 */
-	val = ((shift - kpte_shift_min) / kpte_shift_incr) + 1;
-
-	remains &= ~mask;
-	if (shift != kpte_shift_max)
-		remains = size;
-
-	while (remains) {
-		unsigned long index = start >> kpte_shift_min;
+	int i;
 
-		kpte_set_val(index, val);
+	for (i = 0; i < KERNEL_TSB_NENTRIES; i++) {
+		struct tsb *ent = &swapper_tsb[i];
 
-		start += 1UL << kpte_shift_min;
-		remains -= 1UL << kpte_shift_min;
+		ent->tag = (1UL << TSB_TAG_INVALID_BIT);
 	}
+#ifndef CONFIG_DEBUG_PAGEALLOC
+	for (i = 0; i < KERNEL_TSB4M_NENTRIES; i++) {
+		struct tsb *ent = &swapper_4m_tsb[i];
 
-	return start;
-}
-
-static void __init mark_kpte_bitmap(unsigned long start, unsigned long end)
-{
-	unsigned long smallest_size, smallest_mask;
-	unsigned long s;
-
-	smallest_size = (1UL << kpte_shift_min);
-	smallest_mask = (smallest_size - 1UL);
-
-	while (start < end) {
-		unsigned long orig_start = start;
-
-		for (s = kpte_shift_max; s >= kpte_shift_min; s -= kpte_shift_incr) {
-			start = kpte_mark_using_shift(start, end, s);
-
-			if (start != orig_start)
-				break;
-		}
-
-		if (start = orig_start)
-			start = (start + smallest_size) & ~smallest_mask;
+		ent->tag = (1UL << TSB_TAG_INVALID_BIT);
 	}
+#endif
 }
 
-static void __init init_kpte_bitmap(void)
-{
-	unsigned long i;
-
-	for (i = 0; i < pall_ents; i++) {
-		unsigned long phys_start, phys_end;
-
-		phys_start = pall[i].phys_addr;
-		phys_end = phys_start + pall[i].reg_size;
-
-		mark_kpte_bitmap(phys_start, phys_end);
-	}
-}
+extern unsigned int kvmap_linear_patch[1];
 
 static void __init kernel_physical_mapping_init(void)
 {
-#ifdef CONFIG_DEBUG_PAGEALLOC
 	unsigned long i, mem_alloced = 0UL;
+	bool use_huge = true;
 
+#ifdef CONFIG_DEBUG_PAGEALLOC
+	use_huge = false;
+#endif
 	for (i = 0; i < pall_ents; i++) {
 		unsigned long phys_start, phys_end;
 
@@ -1526,7 +1604,7 @@ static void __init kernel_physical_mapping_init(void)
 		phys_end = phys_start + pall[i].reg_size;
 
 		mem_alloced += kernel_map_range(phys_start, phys_end,
-						PAGE_KERNEL);
+						PAGE_KERNEL, use_huge);
 	}
 
 	printk("Allocated %ld bytes for kernel page tables.\n",
@@ -1535,8 +1613,9 @@ static void __init kernel_physical_mapping_init(void)
 	kvmap_linear_patch[0] = 0x01000000; /* nop */
 	flushi(&kvmap_linear_patch[0]);
 
+	flush_all_kernel_tsbs();
+
 	__flush_tlb_all();
-#endif
 }
 
 #ifdef CONFIG_DEBUG_PAGEALLOC
@@ -1546,7 +1625,7 @@ void kernel_map_pages(struct page *page, int numpages, int enable)
 	unsigned long phys_end = phys_start + (numpages * PAGE_SIZE);
 
 	kernel_map_range(phys_start, phys_end,
-			 (enable ? PAGE_KERNEL : __pgprot(0)));
+			 (enable ? PAGE_KERNEL : __pgprot(0)), false);
 
 	flush_tsb_kernel_range(PAGE_OFFSET + phys_start,
 			       PAGE_OFFSET + phys_end);
@@ -1703,7 +1782,6 @@ static void __init tsb_phys_patch(void)
 #define NUM_KTSB_DESCR	1
 #endif
 static struct hv_tsb_descr ktsb_descr[NUM_KTSB_DESCR];
-extern struct tsb swapper_tsb[KERNEL_TSB_NENTRIES];
 
 /* The swapper TSBs are loaded with a base sequence of:
  *
@@ -1878,6 +1956,7 @@ static void __init sun4v_linear_pte_xor_finalize(void)
 /* paging_init() sets up the page tables */
 
 static unsigned long last_valid_pfn;
+unsigned long kpgd_demux[PTRS_PER_PGD];
 pgd_t swapper_pg_dir[PTRS_PER_PGD];
 
 static void sun4u_pgprot_init(void);
@@ -2027,17 +2106,16 @@ void __init paging_init(void)
 	 * work.
 	 */
 	init_mm.pgd += ((shift) / (sizeof(pgd_t)));
+	kpgd_demux[0] = __pa(init_mm.pgd);
 	
 	memset(swapper_low_pmd_dir, 0, sizeof(swapper_low_pmd_dir));
 
 	/* Now can init the kernel/bad page tables. */
 	pud_set(pud_offset(&swapper_pg_dir[0], 0),
 		swapper_low_pmd_dir + (shift / sizeof(pgd_t)));
-	
+
 	inherit_prom_mappings();
 	
-	init_kpte_bitmap();
-
 	/* Ok, we can use our TLB miss and window trap handlers safely.  */
 	setup_tba();
 
@@ -2144,70 +2222,6 @@ int page_in_phys_avail(unsigned long paddr)
 	return 0;
 }
 
-static struct linux_prom64_registers pavail_rescan[MAX_BANKS] __initdata;
-static int pavail_rescan_ents __initdata;
-
-/* Certain OBP calls, such as fetching "available" properties, can
- * claim physical memory.  So, along with initializing the valid
- * address bitmap, what we do here is refetch the physical available
- * memory list again, and make sure it provides at least as much
- * memory as 'pavail' does.
- */
-static void __init setup_valid_addr_bitmap_from_pavail(unsigned long *bitmap)
-{
-	int i;
-
-	read_obp_memory("available", &pavail_rescan[0], &pavail_rescan_ents);
-
-	for (i = 0; i < pavail_ents; i++) {
-		unsigned long old_start, old_end;
-
-		old_start = pavail[i].phys_addr;
-		old_end = old_start + pavail[i].reg_size;
-		while (old_start < old_end) {
-			int n;
-
-			for (n = 0; n < pavail_rescan_ents; n++) {
-				unsigned long new_start, new_end;
-
-				new_start = pavail_rescan[n].phys_addr;
-				new_end = new_start +
-					pavail_rescan[n].reg_size;
-
-				if (new_start <= old_start &&
-				    new_end >= (old_start + PAGE_SIZE)) {
-					set_bit(old_start >> ILOG2_4MB, bitmap);
-					goto do_next_page;
-				}
-			}
-
-			prom_printf("mem_init: Lost memory in pavail\n");
-			prom_printf("mem_init: OLD start[%lx] size[%lx]\n",
-				    pavail[i].phys_addr,
-				    pavail[i].reg_size);
-			prom_printf("mem_init: NEW start[%lx] size[%lx]\n",
-				    pavail_rescan[i].phys_addr,
-				    pavail_rescan[i].reg_size);
-			prom_printf("mem_init: Cannot continue, aborting.\n");
-			prom_halt();
-
-		do_next_page:
-			old_start += PAGE_SIZE;
-		}
-	}
-}
-
-static void __init patch_tlb_miss_handler_bitmap(void)
-{
-	extern unsigned int valid_addr_bitmap_insn[];
-	extern unsigned int valid_addr_bitmap_patch[];
-
-	valid_addr_bitmap_insn[1] = valid_addr_bitmap_patch[1];
-	mb();
-	valid_addr_bitmap_insn[0] = valid_addr_bitmap_patch[0];
-	flushi(&valid_addr_bitmap_insn[0]);
-}
-
 static void __init register_page_bootmem_info(void)
 {
 #ifdef CONFIG_NEED_MULTIPLE_NODES
@@ -2220,18 +2234,6 @@ static void __init register_page_bootmem_info(void)
 }
 void __init mem_init(void)
 {
-	unsigned long addr, last;
-
-	addr = PAGE_OFFSET + kern_base;
-	last = PAGE_ALIGN(kern_size) + addr;
-	while (addr < last) {
-		set_bit(__pa(addr) >> ILOG2_4MB, sparc64_valid_addr_bitmap);
-		addr += PAGE_SIZE;
-	}
-
-	setup_valid_addr_bitmap_from_pavail(sparc64_valid_addr_bitmap);
-	patch_tlb_miss_handler_bitmap();
-
 	high_memory = __va(last_valid_pfn << PAGE_SHIFT);
 
 	register_page_bootmem_info();
diff --git a/arch/sparc/mm/init_64.h b/arch/sparc/mm/init_64.h
index 0668b36..29ff73f 100644
--- a/arch/sparc/mm/init_64.h
+++ b/arch/sparc/mm/init_64.h
@@ -8,15 +8,8 @@
  */
 
 #define MAX_PHYS_ADDRESS	(1UL << MAX_PHYS_ADDRESS_BITS)
-#define KPTE_BITMAP_CHUNK_SZ		(256UL * 1024UL * 1024UL)
-#define KPTE_BITMAP_BYTES	\
-	((MAX_PHYS_ADDRESS / KPTE_BITMAP_CHUNK_SZ) / 4)
-#define VALID_ADDR_BITMAP_CHUNK_SZ	(4UL * 1024UL * 1024UL)
-#define VALID_ADDR_BITMAP_BYTES	\
-	((MAX_PHYS_ADDRESS / VALID_ADDR_BITMAP_CHUNK_SZ) / 8)
 
 extern unsigned long kern_linear_pte_xor[4];
-extern unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)];
 extern unsigned int sparc64_highest_unlocked_tlb_ent;
 extern unsigned long sparc64_kern_pri_context;
 extern unsigned long sparc64_kern_pri_nuc_bits;

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction
  2014-09-16 16:50 [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction Bob Picco
                   ` (17 preceding siblings ...)
  2014-09-24 22:26 ` David Miller
@ 2014-09-24 23:12 ` Bob Picco
  2014-09-25 17:43 ` Bob Picco
  19 siblings, 0 replies; 21+ messages in thread
From: Bob Picco @ 2014-09-24 23:12 UTC (permalink / raw)
  To: sparclinux

Hi,
David Miller wrote:	[Wed Sep 24 2014, 06:26:51PM EDT]
> From: Bob Picco <bpicco@meloft.net>
> Date: Mon, 22 Sep 2014 14:56:31 -0400
> 
> > I'll review more.
> > 
> > Oh and boot with DEBUG_PAGEALLOC at some point.
> > Alright, need to chase a DEBUG_PAGEALLOC issue with prom_halt() blink:
> > [bpicco@zareason ~]$ cat /tmp/t5-blink.txt
> > [23233.728105] IPv6: ADDRCONF(NETDEV_CHANGE): eth1: link becomes ready
> > [23233.753380] SUN4V-DTLB: Error at TPC[446930], tl 1
> > [23233.762729] SUN4V-DTLB: TPC<dma_4v_map_page+0x10/0x220>
> > [23233.773124] SUN4V-DTLB: O7[55206c]
> > [23233.779910] SUN4V-DTLB: O7<cache_grow+0x12c/0x200>
> > [23233.789455] SUN4V-DTLB: vaddr[1103f23e000] ctx[0] pte[0] error[2]
> > . We were nearly at the console login prompt. Hm, maybe turn off LDOMS
> > config :)
> > 
> > thanx and nice!
> 
> Bob, here is what I have now, can you please help me test it?
Absolutely. I'm slightly exhausted at the moment and productivity would
be uncertain.
> 
> It should restore 256MB/2GB/16GB page size usage.
> 
> The biggest bug was that I wasn't flushing the kernel TSB(s)
> after building the kernel page tables and NOP'ing out that
> instruction in kernel_physical_mapping_init().
Okay.
> 
> Once I fixed that everything runs smoothly so far :-)
Good.
> 
> I haven't gotten to testing DEBUG_PAGEALLOC yet, but I suspect it
> probably works now.
Ah, I didn't return to this. In fact I've been busy with other things.
I will help.
> 
> Thanks!
you're welcome!

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction
  2014-09-16 16:50 [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction Bob Picco
                   ` (18 preceding siblings ...)
  2014-09-24 23:12 ` Bob Picco
@ 2014-09-25 17:43 ` Bob Picco
  19 siblings, 0 replies; 21+ messages in thread
From: Bob Picco @ 2014-09-25 17:43 UTC (permalink / raw)
  To: sparclinux

David Miller wrote:	[Wed Sep 24 2014, 06:26:51PM EDT]
> From: Bob Picco <bpicco@meloft.net>
> Date: Mon, 22 Sep 2014 14:56:31 -0400
> 
> > I'll review more.
> > 
> > Oh and boot with DEBUG_PAGEALLOC at some point.
> > Alright, need to chase a DEBUG_PAGEALLOC issue with prom_halt() blink:
> > [bpicco@zareason ~]$ cat /tmp/t5-blink.txt
> > [23233.728105] IPv6: ADDRCONF(NETDEV_CHANGE): eth1: link becomes ready
> > [23233.753380] SUN4V-DTLB: Error at TPC[446930], tl 1
> > [23233.762729] SUN4V-DTLB: TPC<dma_4v_map_page+0x10/0x220>
> > [23233.773124] SUN4V-DTLB: O7[55206c]
> > [23233.779910] SUN4V-DTLB: O7<cache_grow+0x12c/0x200>
> > [23233.789455] SUN4V-DTLB: vaddr[1103f23e000] ctx[0] pte[0] error[2]
> > . We were nearly at the console login prompt. Hm, maybe turn off LDOMS
> > config :)
> > 
> > thanx and nice!
> 
> Bob, here is what I have now, can you please help me test it?
> 
> It should restore 256MB/2GB/16GB page size usage.
> 
> The biggest bug was that I wasn't flushing the kernel TSB(s)
> after building the kernel page tables and NOP'ing out that
> instruction in kernel_physical_mapping_init().
> 
> Once I fixed that everything runs smoothly so far :-)
> 
> I haven't gotten to testing DEBUG_PAGEALLOC yet, but I suspect it
> probably works now.
> 
> Thanks!
Boots up !DEBUG_PAGEALLOC on T5-2. Review is in progress and looks good so
far. This is important to have correct as we both know. I will attempt
DEBUG_PAGEALLOC, hopefully later today, locally.

We should give it a spin on M7. Though it is scheduled for a core upgrade
today and one never knows :)

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2014-09-25 17:43 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-16 16:50 [PATCH] sparc64: swapper_tsb and swapper_4m_tsb phys correction Bob Picco
2014-09-17  1:48 ` David Miller
2014-09-17 12:42 ` Bob Picco
2014-09-17 17:16 ` David Miller
2014-09-17 19:22 ` Bob Picco
2014-09-17 20:04 ` David Miller
2014-09-17 21:00 ` Bob Picco
2014-09-18 10:09 ` Bob Picco
2014-09-18 17:08 ` David Miller
2014-09-18 19:43 ` David Miller
2014-09-18 21:34 ` Bob Picco
2014-09-18 22:15 ` Bob Picco
2014-09-18 23:16 ` David Miller
2014-09-19 19:28 ` David Miller
2014-09-19 19:57 ` Bob Picco
2014-09-22  4:22 ` David Miller
2014-09-22 18:56 ` Bob Picco
2014-09-22 19:13 ` David Miller
2014-09-24 22:26 ` David Miller
2014-09-24 23:12 ` Bob Picco
2014-09-25 17:43 ` Bob Picco

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.