Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index aba0539..6537445 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -25,62 +25,6 @@
 
 menu "General machine setup"
 
-config VT
-	bool
-	select INPUT
-	default y
-	---help---
-	  If you say Y here, you will get support for terminal devices with
-	  display and keyboard devices. These are called "virtual" because you
-	  can run several virtual terminals (also called virtual consoles) on
-	  one physical terminal. This is rather useful, for example one
-	  virtual terminal can collect system messages and warnings, another
-	  one can be used for a text-mode user session, and a third could run
-	  an X session, all in parallel. Switching between virtual terminals
-	  is done with certain key combinations, usually Alt-<function key>.
-
-	  The setterm command ("man setterm") can be used to change the
-	  properties (such as colors or beeping) of a virtual terminal. The
-	  man page console_codes(4) ("man console_codes") contains the special
-	  character sequences that can be used to change those properties
-	  directly. The fonts used on virtual terminals can be changed with
-	  the setfont ("man setfont") command and the key bindings are defined
-	  with the loadkeys ("man loadkeys") command.
-
-	  You need at least one virtual terminal device in order to make use
-	  of your keyboard and monitor. Therefore, only people configuring an
-	  embedded system would want to say N here in order to save some
-	  memory; the only way to log into such a system is then via a serial
-	  or network connection.
-
-	  If unsure, say Y, or else you won't be able to do much with your new
-	  shiny Linux system :-)
-
-config VT_CONSOLE
-	bool
-	default y
-	---help---
-	  The system console is the device which receives all kernel messages
-	  and warnings and which allows logins in single user mode. If you
-	  answer Y here, a virtual terminal (the device used to interact with
-	  a physical terminal) can be used as system console. This is the most
-	  common mode of operations, so you should say Y here unless you want
-	  the kernel messages be output only to a serial port (in which case
-	  you should say Y to "Console on serial port", below).
-
-	  If you do say Y here, by default the currently visible virtual
-	  terminal (/dev/tty0) will be used as system console. You can change
-	  that with a kernel command line option such as "console=tty3" which
-	  would use the third virtual terminal as system console. (Try "man
-	  bootparam" or see the documentation of your boot loader (lilo or
-	  loadlin) about how to pass options to the kernel at boot time.)
-
-	  If unsure, say Y.
-
-config HW_CONSOLE
-	bool
-	default y
-
 config SMP
 	bool "Symmetric multi-processing support (does not work on sun4/sun4c)"
 	depends on BROKEN
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
index 2879b10..f685035dbd 100644
--- a/arch/sparc64/kernel/entry.S
+++ b/arch/sparc64/kernel/entry.S
@@ -97,8 +97,8 @@
 	faddd		%f0, %f2, %f4
 	fmuld		%f0, %f2, %f6
 	ldxa		[%g3] ASI_DMMU, %g5
-cplus_fptrap_insn_1:
-	sethi		%hi(0), %g2
+	sethi		%hi(sparc64_kern_sec_context), %g2
+	ldx		[%g2 + %lo(sparc64_kern_sec_context)], %g2
 	stxa		%g2, [%g3] ASI_DMMU
 	membar		#Sync
 	add		%g6, TI_FPREGS + 0xc0, %g2
@@ -126,8 +126,8 @@
 	fzero		%f34
 	ldxa		[%g3] ASI_DMMU, %g5
 	add		%g6, TI_FPREGS, %g1
-cplus_fptrap_insn_2:
-	sethi		%hi(0), %g2
+	sethi		%hi(sparc64_kern_sec_context), %g2
+	ldx		[%g2 + %lo(sparc64_kern_sec_context)], %g2
 	stxa		%g2, [%g3] ASI_DMMU
 	membar		#Sync
 	add		%g6, TI_FPREGS + 0x40, %g2
@@ -153,8 +153,8 @@
 3:	mov		SECONDARY_CONTEXT, %g3
 	add		%g6, TI_FPREGS, %g1
 	ldxa		[%g3] ASI_DMMU, %g5
-cplus_fptrap_insn_3:
-	sethi		%hi(0), %g2
+	sethi		%hi(sparc64_kern_sec_context), %g2
+	ldx		[%g2 + %lo(sparc64_kern_sec_context)], %g2
 	stxa		%g2, [%g3] ASI_DMMU
 	membar		#Sync
 	mov		0x40, %g2
@@ -319,8 +319,8 @@
 	stx		%g3, [%g6 + TI_GSR]
 	mov		SECONDARY_CONTEXT, %g3
 	ldxa		[%g3] ASI_DMMU, %g5
-cplus_fptrap_insn_4:
-	sethi		%hi(0), %g2
+	sethi		%hi(sparc64_kern_sec_context), %g2
+	ldx		[%g2 + %lo(sparc64_kern_sec_context)], %g2
 	stxa		%g2, [%g3] ASI_DMMU
 	membar		#Sync
 	add		%g6, TI_FPREGS, %g2
@@ -341,33 +341,6 @@
 	ba,pt		%xcc, etrap
 	 wr		%g0, 0, %fprs
 
-cplus_fptrap_1:
-	sethi		%hi(CTX_CHEETAH_PLUS_CTX0), %g2
-
-	.globl		cheetah_plus_patch_fpdis
-cheetah_plus_patch_fpdis:
-	/* We configure the dTLB512_0 for 4MB pages and the
-	 * dTLB512_1 for 8K pages when in context zero.
-	 */
-	sethi			%hi(cplus_fptrap_1), %o0
-	lduw			[%o0 + %lo(cplus_fptrap_1)], %o1
-
-	set			cplus_fptrap_insn_1, %o2
-	stw			%o1, [%o2]
-	flush			%o2
-	set			cplus_fptrap_insn_2, %o2
-	stw			%o1, [%o2]
-	flush			%o2
-	set			cplus_fptrap_insn_3, %o2
-	stw			%o1, [%o2]
-	flush			%o2
-	set			cplus_fptrap_insn_4, %o2
-	stw			%o1, [%o2]
-	flush			%o2
-
-	retl
-	 nop
-
 	/* The registers for cross calls will be:
 	 *
 	 * DATA 0: [low 32-bits]  Address of function to call, jmp to this
diff --git a/arch/sparc64/kernel/etrap.S b/arch/sparc64/kernel/etrap.S
index 50d2af1..0d8eba2 100644
--- a/arch/sparc64/kernel/etrap.S
+++ b/arch/sparc64/kernel/etrap.S
@@ -68,12 +68,8 @@
 
 		wrpr	%g3, 0, %otherwin
 		wrpr	%g2, 0, %wstate
-cplus_etrap_insn_1:
-		sethi	%hi(0), %g3
-		sllx	%g3, 32, %g3
-cplus_etrap_insn_2:
-		sethi	%hi(0), %g2
-		or	%g3, %g2, %g3
+		sethi	%hi(sparc64_kern_pri_context), %g2
+		ldx	[%g2 + %lo(sparc64_kern_pri_context)], %g3
 		stxa	%g3, [%l4] ASI_DMMU
 		flush	%l6
 		wr	%g0, ASI_AIUS, %asi
@@ -215,12 +211,8 @@
 		mov	PRIMARY_CONTEXT, %l4
 		wrpr	%g3, 0, %otherwin
 		wrpr	%g2, 0, %wstate
-cplus_etrap_insn_3:
-		sethi	%hi(0), %g3
-		sllx	%g3, 32, %g3
-cplus_etrap_insn_4:
-		sethi	%hi(0), %g2
-		or	%g3, %g2, %g3
+		sethi	%hi(sparc64_kern_pri_context), %g2
+		ldx	[%g2 + %lo(sparc64_kern_pri_context)], %g3
 		stxa	%g3, [%l4] ASI_DMMU
 		flush	%l6
 
@@ -264,38 +256,3 @@
 
 #undef TASK_REGOFF
 #undef ETRAP_PSTATE1
-
-cplus_einsn_1:
-		sethi			%uhi(CTX_CHEETAH_PLUS_NUC), %g3
-cplus_einsn_2:
-		sethi			%hi(CTX_CHEETAH_PLUS_CTX0), %g2
-
-		.globl			cheetah_plus_patch_etrap
-cheetah_plus_patch_etrap:
-		/* We configure the dTLB512_0 for 4MB pages and the
-		 * dTLB512_1 for 8K pages when in context zero.
-		 */
-		sethi			%hi(cplus_einsn_1), %o0
-		sethi			%hi(cplus_etrap_insn_1), %o2
-		lduw			[%o0 + %lo(cplus_einsn_1)], %o1
-		or			%o2, %lo(cplus_etrap_insn_1), %o2
-		stw			%o1, [%o2]
-		flush			%o2
-		sethi			%hi(cplus_etrap_insn_3), %o2
-		or			%o2, %lo(cplus_etrap_insn_3), %o2
-		stw			%o1, [%o2]
-		flush			%o2
-
-		sethi			%hi(cplus_einsn_2), %o0
-		sethi			%hi(cplus_etrap_insn_2), %o2
-		lduw			[%o0 + %lo(cplus_einsn_2)], %o1
-		or			%o2, %lo(cplus_etrap_insn_2), %o2
-		stw			%o1, [%o2]
-		flush			%o2
-		sethi			%hi(cplus_etrap_insn_4), %o2
-		or			%o2, %lo(cplus_etrap_insn_4), %o2
-		stw			%o1, [%o2]
-		flush			%o2
-
-		retl
-		 nop
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
index 89406f9..2434049 100644
--- a/arch/sparc64/kernel/head.S
+++ b/arch/sparc64/kernel/head.S
@@ -325,23 +325,7 @@
 1:	sethi	%hi(tlb_type), %g1
 	stw	%g2, [%g1 + %lo(tlb_type)]
 
-	BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,1f)
-	ba,pt	%xcc, 2f
-	 nop
-
-1:	/* Patch context register writes to support nucleus page
-	 * size correctly.
-	 */
-	call	cheetah_plus_patch_etrap
-	 nop
-	call	cheetah_plus_patch_rtrap
-	 nop
-	call	cheetah_plus_patch_fpdis
-	 nop
-	call	cheetah_plus_patch_winfixup
-	 nop
-
-2:	/* Patch copy/page operations to cheetah optimized versions. */
+	/* Patch copy/page operations to cheetah optimized versions. */
 	call	cheetah_patch_copyops
 	 nop
 	call	cheetah_patch_copy_page
@@ -484,20 +468,13 @@
 	call	prom_set_trap_table
 	 sethi	%hi(sparc64_ttable_tl0), %o0
 
-	BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g2,g3,1f)
-	ba,pt	%xcc, 2f
-	 nop
-
-1:	/* Start using proper page size encodings in ctx register.  */
-	sethi	%uhi(CTX_CHEETAH_PLUS_NUC), %g3
+	/* Start using proper page size encodings in ctx register.  */
+	sethi	%hi(sparc64_kern_pri_context), %g3
+	ldx	[%g3 + %lo(sparc64_kern_pri_context)], %g2
 	mov	PRIMARY_CONTEXT, %g1
-	sllx	%g3, 32, %g3
-	sethi	%hi(CTX_CHEETAH_PLUS_CTX0), %g2
-	or	%g3, %g2, %g3
-	stxa	%g3, [%g1] ASI_DMMU
+	stxa	%g2, [%g1] ASI_DMMU
 	membar	#Sync
 
-2:
 	rdpr	%pstate, %o1
 	or	%o1, PSTATE_IE, %o1
 	wrpr	%o1, 0, %pstate
diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S
index fafd227..ecfb42a 100644
--- a/arch/sparc64/kernel/rtrap.S
+++ b/arch/sparc64/kernel/rtrap.S
@@ -256,9 +256,8 @@
 		brnz,pn			%l3, kern_rtt
 		 mov			PRIMARY_CONTEXT, %l7
 		ldxa			[%l7 + %l7] ASI_DMMU, %l0
-cplus_rtrap_insn_1:
-		sethi			%hi(0), %l1
-		sllx			%l1, 32, %l1
+		sethi			%hi(sparc64_kern_pri_nuc_bits), %l1
+		ldx			[%l1 + %lo(sparc64_kern_pri_nuc_bits)], %l1
 		or			%l0, %l1, %l0
 		stxa			%l0, [%l7] ASI_DMMU
 		flush			%g6
@@ -345,21 +344,3 @@
 		wr			%g0, FPRS_DU, %fprs
 		ba,pt			%xcc, rt_continue
 		 stb			%l5, [%g6 + TI_FPDEPTH]
-
-cplus_rinsn_1:
-		sethi			%uhi(CTX_CHEETAH_PLUS_NUC), %l1
-
-		.globl			cheetah_plus_patch_rtrap
-cheetah_plus_patch_rtrap:
-		/* We configure the dTLB512_0 for 4MB pages and the
-		 * dTLB512_1 for 8K pages when in context zero.
-		 */
-		sethi			%hi(cplus_rinsn_1), %o0
-		sethi			%hi(cplus_rtrap_insn_1), %o2
-		lduw			[%o0 + %lo(cplus_rinsn_1)], %o1
-		or			%o2, %lo(cplus_rtrap_insn_1), %o2
-		stw			%o1, [%o2]
-		flush			%o2
-
-		retl
-		 nop
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index 4c9c8f2..c1f3423 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -187,17 +187,13 @@
 		}
 
 		if ((va >= KERNBASE) && (va < (KERNBASE + (4 * 1024 * 1024)))) {
-			unsigned long kernel_pctx = 0;
-
-			if (tlb_type == cheetah_plus)
-				kernel_pctx |= (CTX_CHEETAH_PLUS_NUC |
-						CTX_CHEETAH_PLUS_CTX0);
+			extern unsigned long sparc64_kern_pri_context;
 
 			/* Spitfire Errata #32 workaround */
 			__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
 					     "flush	%%g6"
 					     : /* No outputs */
-					     : "r" (kernel_pctx),
+					     : "r" (sparc64_kern_pri_context),
 					       "r" (PRIMARY_CONTEXT),
 					       "i" (ASI_DMMU));
 
diff --git a/arch/sparc64/kernel/trampoline.S b/arch/sparc64/kernel/trampoline.S
index 89f2fcf..9478551 100644
--- a/arch/sparc64/kernel/trampoline.S
+++ b/arch/sparc64/kernel/trampoline.S
@@ -336,20 +336,13 @@
 	call		init_irqwork_curcpu
 	 nop
 
-	BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g2,g3,1f)
-	ba,pt	%xcc, 2f
-	 nop
-
-1:	/* Start using proper page size encodings in ctx register.  */
-	sethi	%uhi(CTX_CHEETAH_PLUS_NUC), %g3
+	/* Start using proper page size encodings in ctx register.  */
+	sethi	%hi(sparc64_kern_pri_context), %g3
+	ldx	[%g3 + %lo(sparc64_kern_pri_context)], %g2
 	mov	PRIMARY_CONTEXT, %g1
-	sllx	%g3, 32, %g3
-	sethi	%hi(CTX_CHEETAH_PLUS_CTX0), %g2
-	or	%g3, %g2, %g3
-	stxa	%g3, [%g1] ASI_DMMU
+	stxa	%g2, [%g1] ASI_DMMU
 	membar	#Sync
 
-2:
 	rdpr		%pstate, %o1
 	or		%o1, PSTATE_IE, %o1
 	wrpr		%o1, 0, %pstate
diff --git a/arch/sparc64/kernel/winfixup.S b/arch/sparc64/kernel/winfixup.S
index 99c809a..3916092 100644
--- a/arch/sparc64/kernel/winfixup.S
+++ b/arch/sparc64/kernel/winfixup.S
@@ -16,23 +16,14 @@
 	.text
 
 set_pcontext:
-cplus_winfixup_insn_1:
-	sethi	%hi(0), %l1
+	sethi	%hi(sparc64_kern_pri_context), %l1
+	ldx	[%l1 + %lo(sparc64_kern_pri_context)], %l1
 	mov	PRIMARY_CONTEXT, %g1
-	sllx	%l1, 32, %l1
-cplus_winfixup_insn_2:
-	sethi	%hi(0), %g2
-	or	%l1, %g2, %l1
 	stxa	%l1, [%g1] ASI_DMMU
 	flush	%g6
 	retl
 	 nop
 
-cplus_wfinsn_1:
-	sethi	%uhi(CTX_CHEETAH_PLUS_NUC), %l1
-cplus_wfinsn_2:
-	sethi	%hi(CTX_CHEETAH_PLUS_CTX0), %g2
-
 	.align	32
 
 	/* Here are the rules, pay attention.
@@ -395,23 +386,3 @@
 	 add		%sp, PTREGS_OFF, %o0
 	ba,pt		%xcc, rtrap
 	 clr		%l6
-	
-
-	.globl		cheetah_plus_patch_winfixup
-cheetah_plus_patch_winfixup:
-	sethi			%hi(cplus_wfinsn_1), %o0
-	sethi			%hi(cplus_winfixup_insn_1), %o2
-	lduw			[%o0 + %lo(cplus_wfinsn_1)], %o1
-	or			%o2, %lo(cplus_winfixup_insn_1), %o2
-	stw			%o1, [%o2]
-	flush			%o2
-
-	sethi			%hi(cplus_wfinsn_2), %o0
-	sethi			%hi(cplus_winfixup_insn_2), %o2
-	lduw			[%o0 + %lo(cplus_wfinsn_2)], %o1
-	or			%o2, %lo(cplus_winfixup_insn_2), %o2
-	stw			%o1, [%o2]
-	flush			%o2
-
-	retl
-	 nop
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index 5db5052..0d2e967 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -133,6 +133,12 @@
 
 struct page *mem_map_zero __read_mostly;
 
+unsigned int sparc64_highest_unlocked_tlb_ent __read_mostly;
+
+unsigned long sparc64_kern_pri_context __read_mostly;
+unsigned long sparc64_kern_pri_nuc_bits __read_mostly;
+unsigned long sparc64_kern_sec_context __read_mostly;
+
 int bigkernel = 0;
 
 /* XXX Tune this... */
@@ -362,6 +368,7 @@
 	unsigned long data;
 };
 static struct linux_prom_translation prom_trans[512] __initdata;
+static unsigned int prom_trans_ents __initdata;
 
 extern unsigned long prom_boot_page;
 extern void prom_remap(unsigned long physpage, unsigned long virtpage, int mmu_ihandle);
@@ -375,57 +382,7 @@
 unsigned long prom_pmd_phys __read_mostly;
 unsigned int swapper_pgd_zero __read_mostly;
 
-/* Allocate power-of-2 aligned chunks from the end of the
- * kernel image.  Return physical address.
- */
-static inline unsigned long early_alloc_phys(unsigned long size)
-{
-	unsigned long base;
-
-	BUILD_BUG_ON(size & (size - 1));
-
-	kern_size = (kern_size + (size - 1)) & ~(size - 1);
-	base = kern_base + kern_size;
-	kern_size += size;
-
-	return base;
-}
-
-static inline unsigned long load_phys32(unsigned long pa)
-{
-	unsigned long val;
-
-	__asm__ __volatile__("lduwa	[%1] %2, %0"
-			     : "=&r" (val)
-			     : "r" (pa), "i" (ASI_PHYS_USE_EC));
-
-	return val;
-}
-
-static inline unsigned long load_phys64(unsigned long pa)
-{
-	unsigned long val;
-
-	__asm__ __volatile__("ldxa	[%1] %2, %0"
-			     : "=&r" (val)
-			     : "r" (pa), "i" (ASI_PHYS_USE_EC));
-
-	return val;
-}
-
-static inline void store_phys32(unsigned long pa, unsigned long val)
-{
-	__asm__ __volatile__("stwa	%0, [%1] %2"
-			     : /* no outputs */
-			     : "r" (val), "r" (pa), "i" (ASI_PHYS_USE_EC));
-}
-
-static inline void store_phys64(unsigned long pa, unsigned long val)
-{
-	__asm__ __volatile__("stxa	%0, [%1] %2"
-			     : /* no outputs */
-			     : "r" (val), "r" (pa), "i" (ASI_PHYS_USE_EC));
-}
+static pmd_t *prompmd __read_mostly;
 
 #define BASE_PAGE_SIZE 8192
 
@@ -435,34 +392,28 @@
  */
 unsigned long prom_virt_to_phys(unsigned long promva, int *error)
 {
-	unsigned long pmd_phys = (prom_pmd_phys +
-				  ((promva >> 23) & 0x7ff) * sizeof(pmd_t));
-	unsigned long pte_phys;
-	pmd_t pmd_ent;
-	pte_t pte_ent;
+	pmd_t *pmdp = prompmd + ((promva >> 23) & 0x7ff);
+	pte_t *ptep;
 	unsigned long base;
 
-	pmd_val(pmd_ent) = load_phys32(pmd_phys);
-	if (pmd_none(pmd_ent)) {
+	if (pmd_none(*pmdp)) {
 		if (error)
 			*error = 1;
 		return 0;
 	}
-
-	pte_phys = (unsigned long)pmd_val(pmd_ent) << 11UL;
-	pte_phys += ((promva >> 13) & 0x3ff) * sizeof(pte_t);
-	pte_val(pte_ent) = load_phys64(pte_phys);
-	if (!pte_present(pte_ent)) {
+	ptep = (pte_t *)__pmd_page(*pmdp) + ((promva >> 13) & 0x3ff);
+	if (!pte_present(*ptep)) {
 		if (error)
 			*error = 1;
 		return 0;
 	}
 	if (error) {
 		*error = 0;
-		return pte_val(pte_ent);
+		return pte_val(*ptep);
 	}
-	base = pte_val(pte_ent) & _PAGE_PADDR;
-	return (base + (promva & (BASE_PAGE_SIZE - 1)));
+	base = pte_val(*ptep) & _PAGE_PADDR;
+
+	return base + (promva & (BASE_PAGE_SIZE - 1));
 }
 
 /* The obp translations are saved based on 8k pagesize, since obp can
@@ -475,25 +426,20 @@
 	unsigned long vaddr;
 
 	for (vaddr = start; vaddr < end; vaddr += BASE_PAGE_SIZE) {
-		unsigned long val, pte_phys, pmd_phys;
-		pmd_t pmd_ent;
-		int i;
+		unsigned long val;
+		pmd_t *pmd;
+		pte_t *pte;
 
-		pmd_phys = (prom_pmd_phys +
-			    (((vaddr >> 23) & 0x7ff) * sizeof(pmd_t)));
-		pmd_val(pmd_ent) = load_phys32(pmd_phys);
-		if (pmd_none(pmd_ent)) {
-			pte_phys = early_alloc_phys(BASE_PAGE_SIZE);
-
-			for (i = 0; i < BASE_PAGE_SIZE / sizeof(pte_t); i++)
-				store_phys64(pte_phys+i*sizeof(pte_t),0);
-
-			pmd_val(pmd_ent) = pte_phys >> 11UL;
-			store_phys32(pmd_phys, pmd_val(pmd_ent));
+		pmd = prompmd + ((vaddr >> 23) & 0x7ff);
+		if (pmd_none(*pmd)) {
+			pte = __alloc_bootmem(BASE_PAGE_SIZE, BASE_PAGE_SIZE,
+					      PAGE_SIZE);
+			if (!pte)
+				prom_halt();
+			memset(pte, 0, BASE_PAGE_SIZE);
+			pmd_set(pmd, pte);
 		}
-
-		pte_phys = (unsigned long)pmd_val(pmd_ent) << 11UL;
-		pte_phys += (((vaddr >> 13) & 0x3ff) * sizeof(pte_t));
+		pte = (pte_t *) __pmd_page(*pmd) + ((vaddr >> 13) & 0x3ff);
 
 		val = data;
 
@@ -501,7 +447,8 @@
 		if (tlb_type == spitfire)
 			val &= ~0x0003fe0000000000UL;
 
-		store_phys64(pte_phys, val | _PAGE_MODIFIED);
+		set_pte_at(&init_mm, vaddr, pte,
+			   __pte(val | _PAGE_MODIFIED));
 
 		data += BASE_PAGE_SIZE;
 	}
@@ -514,13 +461,17 @@
 }
 
 #define OBP_PMD_SIZE 2048
-static void __init build_obp_pgtable(int prom_trans_ents)
+static void __init build_obp_pgtable(void)
 {
 	unsigned long i;
 
-	prom_pmd_phys = early_alloc_phys(OBP_PMD_SIZE);
-	for (i = 0; i < OBP_PMD_SIZE; i += 4)
-		store_phys32(prom_pmd_phys + i, 0);
+	prompmd = __alloc_bootmem(OBP_PMD_SIZE, OBP_PMD_SIZE, PAGE_SIZE);
+	if (!prompmd)
+		prom_halt();
+
+	memset(prompmd, 0, OBP_PMD_SIZE);
+
+	prom_pmd_phys = __pa(prompmd);
 
 	for (i = 0; i < prom_trans_ents; i++) {
 		unsigned long start, end;
@@ -540,7 +491,7 @@
 /* Read OBP translations property into 'prom_trans[]'.
  * Return the number of entries.
  */
-static int __init read_obp_translations(void)
+static void __init read_obp_translations(void)
 {
 	int n, node;
 
@@ -561,8 +512,10 @@
 		prom_printf("prom_mappings: Couldn't get property.\n");
 		prom_halt();
 	}
+
 	n = n / sizeof(struct linux_prom_translation);
-	return n;
+
+	prom_trans_ents = n;
 }
 
 static void __init remap_kernel(void)
@@ -582,28 +535,38 @@
 	prom_dtlb_load(tlb_ent, tte_data, tte_vaddr);
 	prom_itlb_load(tlb_ent, tte_data, tte_vaddr);
 	if (bigkernel) {
-		prom_dtlb_load(tlb_ent - 1,
+		tlb_ent -= 1;
+		prom_dtlb_load(tlb_ent,
 			       tte_data + 0x400000, 
 			       tte_vaddr + 0x400000);
-		prom_itlb_load(tlb_ent - 1,
+		prom_itlb_load(tlb_ent,
 			       tte_data + 0x400000, 
 			       tte_vaddr + 0x400000);
 	}
+	sparc64_highest_unlocked_tlb_ent = tlb_ent - 1;
+	if (tlb_type == cheetah_plus) {
+		sparc64_kern_pri_context = (CTX_CHEETAH_PLUS_CTX0 |
+					    CTX_CHEETAH_PLUS_NUC);
+		sparc64_kern_pri_nuc_bits = CTX_CHEETAH_PLUS_NUC;
+		sparc64_kern_sec_context = CTX_CHEETAH_PLUS_CTX0;
+	}
 }
 
-static void __init inherit_prom_mappings(void)
-{
-	int n;
 
-	n = read_obp_translations();
-	build_obp_pgtable(n);
+static void __init inherit_prom_mappings_pre(void)
+{
+	read_obp_translations();
 
 	/* Now fixup OBP's idea about where we really are mapped. */
 	prom_printf("Remapping the kernel... ");
 	remap_kernel();
 
 	prom_printf("done.\n");
+}
 
+static void __init inherit_prom_mappings_post(void)
+{
+	build_obp_pgtable();
 	register_prom_callbacks();
 }
 
@@ -788,8 +751,8 @@
 		}
 	}
 	if (tlb_type == spitfire) {
-		int high = SPITFIRE_HIGHEST_LOCKED_TLBENT - bigkernel;
-		for (i = 0; i < high; i++) {
+		int high = sparc64_highest_unlocked_tlb_ent;
+		for (i = 0; i <= high; i++) {
 			unsigned long data;
 
 			/* Spitfire Errata #32 workaround */
@@ -877,9 +840,9 @@
 			}
 		}
 	} else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
-		int high = CHEETAH_HIGHEST_LOCKED_TLBENT - bigkernel;
+		int high = sparc64_highest_unlocked_tlb_ent;
 
-		for (i = 0; i < high; i++) {
+		for (i = 0; i <= high; i++) {
 			unsigned long data;
 
 			data = cheetah_get_ldtlb_data(i);
@@ -1556,8 +1519,7 @@
 	
 	swapper_pgd_zero = pgd_val(swapper_pg_dir[0]);
 	
-	/* Inherit non-locked OBP mappings. */
-	inherit_prom_mappings();
+	inherit_prom_mappings_pre();
 	
 	/* Ok, we can use our TLB miss and window trap handlers safely.
 	 * We need to do a quick peek here to see if we are on StarFire
@@ -1568,15 +1530,23 @@
 		extern void setup_tba(int);
 		setup_tba(this_is_starfire);
 	}
-
-	inherit_locked_prom_mappings(1);
-
 	__flush_tlb_all();
 
+	/* Everything from this point forward, until we are done with
+	 * inherit_prom_mappings_post(), must complete successfully
+	 * without calling into the firmware.  The firwmare page tables
+	 * have not been built, but we are running on the Linux kernel's
+	 * trap table.
+	 */
+
 	/* Setup bootmem... */
 	pages_avail = 0;
 	last_valid_pfn = end_pfn = bootmem_init(&pages_avail);
 
+	inherit_prom_mappings_post();
+
+	inherit_locked_prom_mappings(1);
+
 #ifdef CONFIG_DEBUG_PAGEALLOC
 	kernel_physical_mapping_init();
 #endif