diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile
index 2d019aa73b8f..7011f9ba9678 100644
--- a/arch/parisc/Makefile
+++ b/arch/parisc/Makefile
@@ -83,7 +83,7 @@ endif
 # Currently we save and restore fpregs on all kernel entry/interruption paths.
 # If that gets optimized, we might need to disable the use of fpregs in the
 # kernel.
-cflags-y	+= -mdisable-fpregs
+# cflags-y	+= -mdisable-fpregs
 
 # Use long jumps instead of long branches (needed if your linker fails to
 # link a too big vmlinux executable). Not enabled for building modules.
diff --git a/arch/parisc/boot/compressed/Makefile b/arch/parisc/boot/compressed/Makefile
index dff453687530..81f64a90857d 100644
--- a/arch/parisc/boot/compressed/Makefile
+++ b/arch/parisc/boot/compressed/Makefile
@@ -18,7 +18,8 @@ KBUILD_CFLAGS := -D__KERNEL__ -O2 -DBOOTLOADER
 KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
 KBUILD_CFLAGS += -fno-strict-aliasing
 KBUILD_CFLAGS += $(cflags-y) -fno-delete-null-pointer-checks -fno-builtin-printf
-KBUILD_CFLAGS += -fno-PIE -mno-space-regs -mdisable-fpregs -Os
+# KBUILD_CFLAGS += -fno-PIE -mno-space-regs -mdisable-fpregs -Os
+KBUILD_CFLAGS += -fno-PIE -mno-space-regs -Os
 ifndef CONFIG_64BIT
 KBUILD_CFLAGS += -mfast-indirect-calls
 endif
diff --git a/arch/parisc/include/asm/assembly.h b/arch/parisc/include/asm/assembly.h
index a39250cb7dfc..13ed4b809b05 100644
--- a/arch/parisc/include/asm/assembly.h
+++ b/arch/parisc/include/asm/assembly.h
@@ -135,6 +135,16 @@
 	extrd,u \r, 63-(\sa), 64-(\sa), \t
 	.endm
 
+	/* The extru instruction leaves the most significant 32 bits of the
+	 * target register in an undefined state on PA 2.0 systems. */
+	.macro extru_safe r, p, len, t
+#ifdef CONFIG_64BIT
+	extrd,u	\r, 32+(\p), \len, \t
+#else
+	extru	\r, \p, \len, \t
+#endif
+	.endm
+
 	/* load 32-bit 'value' into 'reg' compensating for the ldil
 	 * sign-extension when running in wide mode.
 	 * WARNING!! neither 'value' nor 'reg' can be expressions
diff --git a/arch/parisc/include/asm/futex.h b/arch/parisc/include/asm/futex.h
index fceb9cf02fb3..e0c7f8d61365 100644
--- a/arch/parisc/include/asm/futex.h
+++ b/arch/parisc/include/asm/futex.h
@@ -10,23 +10,28 @@
 #include <asm/errno.h>
 
 /* The following has to match the LWS code in syscall.S.  We have
-   sixteen four-word locks. */
+   256 four-word locks. We xor three 8-bit hunks of the futex physical
+   address to create the hash index. */
+
+static unsigned long
+_futex_hash_index(unsigned long pa)
+{
+	return ((pa >> 6) ^ (pa >> 14) ^ (pa >> 22)) & 0x3fc;
+}
 
 static inline void
-_futex_spin_lock_irqsave(u32 __user *uaddr, unsigned long int *flags)
+_futex_spin_lock_irqsave(unsigned long index, unsigned long int *flags)
 {
 	extern u32 lws_lock_start[];
-	long index = ((long)uaddr & 0x3f8) >> 1;
 	arch_spinlock_t *s = (arch_spinlock_t *)&lws_lock_start[index];
 	local_irq_save(*flags);
 	arch_spin_lock(s);
 }
 
 static inline void
-_futex_spin_unlock_irqrestore(u32 __user *uaddr, unsigned long int *flags)
+_futex_spin_unlock_irqrestore(unsigned long index, unsigned long int *flags)
 {
 	extern u32 lws_lock_start[];
-	long index = ((long)uaddr & 0x3f8) >> 1;
 	arch_spinlock_t *s = (arch_spinlock_t *)&lws_lock_start[index];
 	arch_spin_unlock(s);
 	local_irq_restore(*flags);
@@ -35,11 +40,14 @@ _futex_spin_unlock_irqrestore(u32 __user *uaddr, unsigned long int *flags)
 static inline int
 arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
 {
+	unsigned long ua = (unsigned long)uaddr;
+	unsigned long index;
 	unsigned long int flags;
 	int oldval, ret;
 	u32 tmp;
 
-	_futex_spin_lock_irqsave(uaddr, &flags);
+	index = _futex_hash_index(ua);
+	_futex_spin_lock_irqsave(index, &flags);
 
 	ret = -EFAULT;
 	if (unlikely(get_user(oldval, uaddr) != 0))
@@ -72,7 +80,7 @@ arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
 		ret = -EFAULT;
 
 out_pagefault_enable:
-	_futex_spin_unlock_irqrestore(uaddr, &flags);
+	_futex_spin_unlock_irqrestore(index, &flags);
 
 	if (!ret)
 		*oval = oldval;
@@ -84,10 +92,12 @@ static inline int
 futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 			      u32 oldval, u32 newval)
 {
+	unsigned long ua = (unsigned long)uaddr;
+	unsigned long index;
 	u32 val;
 	unsigned long flags;
 
-	/* futex.c wants to do a cmpxchg_inatomic on kernel NULL, which is
+ 	/* futex.c wants to do a cmpxchg_inatomic on kernel NULL, which is
 	 * our gateway page, and causes no end of trouble...
 	 */
 	if (uaccess_kernel() && !uaddr)
@@ -98,23 +108,25 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 
 	/* HPPA has no cmpxchg in hardware and therefore the
 	 * best we can do here is use an array of locks. The
-	 * lock selected is based on a hash of the userspace
-	 * address. This should scale to a couple of CPUs.
+	 * lock selected is based on a hash of the virtual
+	 * address of the futex. This should scale to a couple
+	 * of CPUs.
 	 */
 
-	_futex_spin_lock_irqsave(uaddr, &flags);
+	index = _futex_hash_index(ua);
+	_futex_spin_lock_irqsave(index, &flags);
 	if (unlikely(get_user(val, uaddr) != 0)) {
-		_futex_spin_unlock_irqrestore(uaddr, &flags);
+		_futex_spin_unlock_irqrestore(index, &flags);
 		return -EFAULT;
 	}
 
 	if (val == oldval && unlikely(put_user(newval, uaddr) != 0)) {
-		_futex_spin_unlock_irqrestore(uaddr, &flags);
+		_futex_spin_unlock_irqrestore(index, &flags);
 		return -EFAULT;
 	}
 
 	*uval = val;
-	_futex_spin_unlock_irqrestore(uaddr, &flags);
+	_futex_spin_unlock_irqrestore(index, &flags);
 
 	return 0;
 }
diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h
index 1f2fea3bfacd..7c6a3fcd51bd 100644
--- a/arch/parisc/include/asm/pgtable.h
+++ b/arch/parisc/include/asm/pgtable.h
@@ -65,6 +65,8 @@ extern int pa_serialize_tlb_flushes;
  * are slow on SMP machines since the purge must be broadcast to all CPUs.
  */
 
+extern void __update_cache(pte_t pte);
+
 static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
 {
 	unsigned long flags;
diff --git a/arch/parisc/include/asm/special_insns.h b/arch/parisc/include/asm/special_insns.h
index a303ae9a77f4..0493cbf70012 100644
--- a/arch/parisc/include/asm/special_insns.h
+++ b/arch/parisc/include/asm/special_insns.h
@@ -2,26 +2,30 @@
 #ifndef __PARISC_SPECIAL_INSNS_H
 #define __PARISC_SPECIAL_INSNS_H
 
-#define lpa(va)	({			\
-	unsigned long pa;		\
-	__asm__ __volatile__(		\
-		"copy %%r0,%0\n\t"	\
-		"lpa %%r0(%1),%0"	\
-		: "=r" (pa)		\
-		: "r" (va)		\
-		: "memory"		\
-	);				\
-	pa;				\
+#define lpa(va)	({					\
+	unsigned long pa;				\
+	__asm__ __volatile__(				\
+		"copy %%r0,%0\n"			\
+		"9998:\tlpa %%r0(%1),%0\n"		\
+		"9999:\n"				\
+		ASM_EXCEPTIONTABLE_ENTRY(9998b, 9999b)	\
+		: "=&r" (pa)				\
+		: "r" (va)				\
+		: "memory"				\
+	);						\
+	pa;						\
 })
 
-#define lpa_user(va)	({		\
-	unsigned long pa;		\
-	__asm__ __volatile__(		\
-		"copy %%r0,%0\n\t"	\
-		"lpa %%r0(%%sr3,%1),%0"	\
-		: "=r" (pa)		\
-		: "r" (va)		\
-		: "memory"		\
+#define lpa_user(va)	({				\
+	unsigned long pa;				\
+	__asm__ __volatile__(				\
+		"copy %%r0,%0\n"			\
+		"9998:\tlpa %%r0(%%sr3,%1),%0\n"	\
+		"9999:\n"				\
+		ASM_EXCEPTIONTABLE_ENTRY(9998b, 9999b)	\
+		: "=&r" (pa)				\
+		: "r" (va)				\
+		: "memory"				\
 	);				\
 	pa;				\
 })
diff --git a/arch/parisc/install.sh b/arch/parisc/install.sh
index 056d588befdd..70d3cffb0251 100644
--- a/arch/parisc/install.sh
+++ b/arch/parisc/install.sh
@@ -39,6 +39,7 @@ verify "$3"
 if [ -n "${INSTALLKERNEL}" ]; then
   if [ -x ~/bin/${INSTALLKERNEL} ]; then exec ~/bin/${INSTALLKERNEL} "$@"; fi
   if [ -x /sbin/${INSTALLKERNEL} ]; then exec /sbin/${INSTALLKERNEL} "$@"; fi
+  if [ -x /usr/sbin/${INSTALLKERNEL} ]; then exec /usr/sbin/${INSTALLKERNEL} "$@"; fi
 fi
 
 # Default install
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index c81ab0cb8925..c9f09d2a4461 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -559,6 +559,7 @@ void flush_cache_mm(struct mm_struct *mm)
 		return;
 	}
 
+	preempt_disable();
 	if (mm->context == mfsp(3)) {
 		for (vma = mm->mmap; vma; vma = vma->vm_next) {
 			flush_user_dcache_range_asm(vma->vm_start, vma->vm_end);
@@ -566,8 +567,10 @@ void flush_cache_mm(struct mm_struct *mm)
 				flush_user_icache_range_asm(vma->vm_start, vma->vm_end);
 			flush_tlb_range(vma, vma->vm_start, vma->vm_end);
 		}
+		preempt_enable();
 		return;
 	}
+	preempt_enable();
 
 	pgd = mm->pgd;
 	for (vma = mm->mmap; vma; vma = vma->vm_next) {
@@ -606,13 +609,16 @@ void flush_cache_range(struct vm_area_struct *vma,
 		return;
 	}
 
+	preempt_disable();
 	if (vma->vm_mm->context == mfsp(3)) {
 		flush_user_dcache_range_asm(start, end);
 		if (vma->vm_flags & VM_EXEC)
 			flush_user_icache_range_asm(start, end);
 		flush_tlb_range(vma, start, end);
+		preempt_enable();
 		return;
 	}
+	preempt_enable();
 
 	pgd = vma->vm_mm->pgd;
 	for (addr = vma->vm_start; addr < vma->vm_end; addr += PAGE_SIZE) {
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index 437c8d31f390..7f33e3236a1e 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -393,17 +393,9 @@
 	 */
 	.macro		L2_ptep	pmd,pte,index,va,fault
 #if CONFIG_PGTABLE_LEVELS == 3
-	extru		\va,31-ASM_PMD_SHIFT,ASM_BITS_PER_PMD,\index
+	extru_safe	\va,31-ASM_PMD_SHIFT,ASM_BITS_PER_PMD,\index
 #else
-# if defined(CONFIG_64BIT)
-	extrd,u		\va,63-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index
-  #else
-  # if PAGE_SIZE > 4096
-	extru		\va,31-ASM_PGDIR_SHIFT,32-ASM_PGDIR_SHIFT,\index
-  # else
-	extru		\va,31-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index
-  # endif
-# endif
+	extru_safe	\va,31-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index
 #endif
 	dep             %r0,31,PAGE_SHIFT,\pmd  /* clear offset */
 #if CONFIG_PGTABLE_LEVELS < 3
@@ -413,7 +405,7 @@
 	bb,>=,n		\pmd,_PxD_PRESENT_BIT,\fault
 	dep		%r0,31,PxD_FLAG_SHIFT,\pmd /* clear flags */
 	SHLREG		\pmd,PxD_VALUE_SHIFT,\pmd
-	extru		\va,31-PAGE_SHIFT,ASM_BITS_PER_PTE,\index
+	extru_safe	\va,31-PAGE_SHIFT,ASM_BITS_PER_PTE,\index
 	dep		%r0,31,PAGE_SHIFT,\pmd  /* clear offset */
 	shladd		\index,BITS_PER_PTE_ENTRY,\pmd,\pmd /* pmd is now pte */
 	.endm
@@ -974,8 +966,8 @@ intr_do_preempt:
 
 	/* current_thread_info()->preempt_count */
 	mfctl	%cr30, %r1
-	LDREG	TI_PRE_COUNT(%r1), %r19
-	cmpib,COND(<>)	0, %r19, intr_restore	/* if preempt_count > 0 */
+	ldw	TI_PRE_COUNT(%r1), %r19
+	cmpib,<>	0, %r19, intr_restore	/* if preempt_count > 0 */
 	nop				/* prev insn branched backwards */
 
 	/* check if we interrupted a critical path */
diff --git a/arch/parisc/kernel/patch.c b/arch/parisc/kernel/patch.c
index 80a0ab372802..799795bc4210 100644
--- a/arch/parisc/kernel/patch.c
+++ b/arch/parisc/kernel/patch.c
@@ -67,8 +67,8 @@ void __kprobes __patch_text_multiple(void *addr, u32 *insn, unsigned int len)
 	int mapped;
 
 	/* Make sure we don't have any aliases in cache */
-	flush_kernel_vmap_range(addr, len);
 	flush_icache_range(start, end);
+	flush_tlb_kernel_range(start, end);
 
 	p = fixmap = patch_map(addr, FIX_TEXT_POKE0, &flags, &mapped);
 
@@ -93,7 +93,6 @@ void __kprobes __patch_text_multiple(void *addr, u32 *insn, unsigned int len)
 	flush_kernel_vmap_range((void *)fixmap, (p-fixmap) * sizeof(*p));
 	if (mapped)
 		patch_unmap(FIX_TEXT_POKE0, &flags);
-	flush_icache_range(start, end);
 }
 
 void __kprobes __patch_text(void *addr, u32 insn)
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
index cf92ece20b75..0cd97fa004c5 100644
--- a/arch/parisc/kernel/smp.c
+++ b/arch/parisc/kernel/smp.c
@@ -228,11 +228,13 @@ static inline void
 send_IPI_allbutself(enum ipi_message_type op)
 {
 	int i;
-	
+
+	preempt_disable();
 	for_each_online_cpu(i) {
 		if (i != smp_processor_id())
 			send_IPI_single(i, op);
 	}
+	preempt_enable();
 }
 
 #ifdef CONFIG_KGDB
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
index 3f24a0af1e04..2f468292a545 100644
--- a/arch/parisc/kernel/syscall.S
+++ b/arch/parisc/kernel/syscall.S
@@ -74,7 +74,7 @@ ENTRY(linux_gateway_page)
 	/* ADDRESS 0xb0 to 0xb8, lws uses two insns for entry */
 	/* Light-weight-syscall entry must always be located at 0xb0 */
 	/* WARNING: Keep this number updated with table size changes */
-#define __NR_lws_entries (3)
+#define __NR_lws_entries (5)
 
 lws_entry:
 	gate	lws_start, %r0		/* increase privilege */
@@ -496,6 +496,11 @@ lws_start:
 	/* Jump to lws, lws table pointers already relocated */
 	be,n	0(%sr2,%r21)
 
+lws_stby_fault:
+	ldo	1(%r0),%r28
+	b	lws_exit
+	ldo	-EFAULT(%r0),%r21	/* set errno */
+
 lws_exit_nosys:
 	ldo	-ENOSYS(%r0),%r21		   /* set errno */
 	/* Fall through: Return to userspace */
@@ -567,15 +572,25 @@ lws_compare_and_swap32:
 #endif
 
 lws_compare_and_swap:
-	/* Load start of lock table */
-	ldil	L%lws_lock_start, %r20
-	ldo	R%lws_lock_start(%r20), %r28
+	/* Dirty cache line at r26 to avoid COW break in critical region */
+	b	3f
+1:	stbys,e	%r0, 0(%r26)
+2:	b,n	lws_stby_fault
+	ASM_EXCEPTIONTABLE_ENTRY(1b-linux_gateway_page, 2b-linux_gateway_page)
+
+	/* Calculate 8-bit hash index from virtual address */
+3:	extru_safe  %r26, 23, 8, %r28
+	extru_safe  %r26, 15, 8, %r1
+	xor	%r1, %r28, %r28
+	extru_safe  %r26, 7, 8, %r1
+	xor	%r1, %r28, %r20
 
-	/* Extract eight bits from r26 and hash lock (Bits 3-11) */
-	extru  %r26, 28, 8, %r20
+	/* Load start of lock table */
+	ldil	L%lws_lock_start, %r28
+	ldo	R%lws_lock_start(%r28), %r28
 
-	/* Find lock to use, the hash is either one of 0 to
-	   15, multiplied by 16 (keep it 16-byte aligned)
+	/* Find lock to use, the hash index is one of 0 to
+	   255, multiplied by 16 (keep it 16-byte aligned)
 	   and add to the lock table offset. */
 	shlw	%r20, 4, %r20
 	add	%r20, %r28, %r20
@@ -603,10 +618,20 @@ cas_nocontend:
 # endif
 /* ENABLE_LWS_DEBUG */
 
+	/* We disable interrupts around the critical region. However,
+	   the store instruction in the critical region might cause a
+	   COW break. The trap handler needs to re-enable interrupts
+	   when page faults are enabled as the process might sleep.
+	   When this happens, the lock may be held by a process for
+	   an extended period and affect unrelated processes because
+	   locks are shared. */
 	rsm	PSW_SM_I, %r0				/* Disable interrupts */
-	/* COW breaks can cause contention on UP systems */
+
+	/* Check lock first to minimize cache line bounce */
+	ldw	0(%sr2,%r20), %r28			/* Load the lock */
+	cmpb,=,n	%r0, %r28, cas_wouldblock	/* Spin if locked */
 	LDCW	0(%sr2,%r20), %r28			/* Try to acquire the lock */
-	cmpb,<>,n	%r0, %r28, cas_action		/* Did we get it? */
+	cmpb,<>,n	%r28, %r0,  cas_action		/* Did we get it? */
 cas_wouldblock:
 	ldo	2(%r0), %r28				/* 2nd case */
 	ssm	PSW_SM_I, %r0
@@ -621,7 +646,7 @@ cas_wouldblock:
 	*/
 
 	/* NOTES:
-		This all works becuse intr_do_signal
+		This all works because intr_do_signal
 		and schedule both check the return iasq
 		and see that we are on the kernel page
 		so this process is never scheduled off
@@ -629,6 +654,7 @@ cas_wouldblock:
 		thus it is wholly atomic from usrspaces
 		perspective
 	*/
+
 cas_action:
 #if defined CONFIG_SMP && ENABLE_LWS_DEBUG
 	/* DEBUG */
@@ -757,23 +783,49 @@ lws_compare_and_swap_2:
 #endif
 
 cas2_lock_start:
-	/* Load start of lock table */
-	ldil	L%lws_lock_start, %r20
-	ldo	R%lws_lock_start(%r20), %r28
+	/* Dirty cache line at r26 to avoid COW break in critical region */
+	copy	%r26, %r28
+#ifdef CONFIG_64BIT
+	depdi	0, 63, 2, %r28
+#else
+	depi	0, 31, 2, %r28
+#endif
+	b	3f
+1:	stbys,e	%r0, 0(%r28)
+2:	b,n	lws_stby_fault
+	ASM_EXCEPTIONTABLE_ENTRY(1b-linux_gateway_page, 2b-linux_gateway_page)
+
+	/* Calculate 8-bit hash index from virtual address */
+3:	extru_safe  %r26, 23, 8, %r28
+	extru_safe  %r26, 15, 8, %r1
+	xor	%r1, %r28, %r28
+	extru_safe  %r26, 7, 8, %r1
+	xor	%r1, %r28, %r20
 
-	/* Extract eight bits from r26 and hash lock (Bits 3-11) */
-	extru  %r26, 28, 8, %r20
+	/* Load start of lock table */
+	ldil	L%lws_lock_start, %r28
+	ldo	R%lws_lock_start(%r28), %r28
 
-	/* Find lock to use, the hash is either one of 0 to
-	   15, multiplied by 16 (keep it 16-byte aligned)
+	/* Find lock to use, the hash index is one of 0 to
+	   255, multiplied by 16 (keep it 16-byte aligned)
 	   and add to the lock table offset. */
 	shlw	%r20, 4, %r20
 	add	%r20, %r28, %r20
 
+	/* We disable interrupts around the critical region. However,
+	   the store instruction in the critical region might cause a
+	   COW break. The trap handler needs to re-enable interrupts
+	   when page faults are enabled as the process might sleep.
+	   When this happens, the lock may be held by a process for
+	   an extended period and affect unrelated processes because
+	   locks are shared. */
 	rsm	PSW_SM_I, %r0			/* Disable interrupts */
-	/* COW breaks can cause contention on UP systems */
+
+	/* Check lock first to minimize cache line bounce */
+	ldw	0(%sr2,%r20), %r28			/* Load the lock */
+	cmpb,=,n	%r0, %r28, cas2_wouldblock	/* Spin if locked */
 	LDCW	0(%sr2,%r20), %r28		/* Try to acquire the lock */
-	cmpb,<>,n	%r0, %r28, cas2_action	/* Did we get it? */
+	cmpb,<>,n	%r28, %r0,  cas2_action	/* Did we get it? */
 cas2_wouldblock:
 	ldo	2(%r0), %r28			/* 2nd case */
 	ssm	PSW_SM_I, %r0
@@ -788,7 +840,7 @@ cas2_wouldblock:
 	*/
 
 	/* NOTES:
-		This all works becuse intr_do_signal
+		This all works because intr_do_signal
 		and schedule both check the return iasq
 		and see that we are on the kernel page
 		so this process is never scheduled off
@@ -796,6 +848,7 @@ cas2_wouldblock:
 		thus it is wholly atomic from usrspaces
 		perspective
 	*/
+
 cas2_action:
 	/* Jump to the correct function */
 	blr	%r29, %r0
@@ -897,6 +950,342 @@ cas2_end:
 	ASM_EXCEPTIONTABLE_ENTRY(21b-linux_gateway_page, 22b-linux_gateway_page)
 #endif
 
+	/***************************************************
+		LWS atomic exchange.  When using using a synthesized CAS
+		operation, we need to perform atomic loads using the CAS
+		lock to ensure sequential consistency.
+
+		%r26 - Exchange address
+		%r25 - Size of the variable (0/1/2/3 for 8/16/32/64 bit)
+		%r24 - Address of new value
+		%r23 - Address of old value
+		%r28 - Return non-zero on failure
+		%r21 - Kernel error code
+
+		%r21 has the following meanings:
+
+		EAGAIN - Lock is busy, ldcw failed, try again.
+		EFAULT - Read failed.
+
+		Scratch: r20, r1
+
+	****************************************************/
+
+	/* ELF32 Process entry path */
+lws_atomic_xchg:
+#ifdef CONFIG_64BIT
+	/* Clip the input registers. We don't need to clip %r25 as we
+	   only use it for word operations */
+	depdi	0, 31, 32, %r26
+	depdi	0, 31, 32, %r25
+	depdi	0, 31, 32, %r24
+	depdi	0, 31, 32, %r23
+#endif
+
+	/* Check the validity of the size pointer */
+	subi,>>= 3, %r25, %r0
+	b,n	lws_exit_nosys
+
+	/* Dirty cache line at r26 to avoid COW break in critical region */
+	copy	%r26, %r28
+#ifdef CONFIG_64BIT
+	depdi	0, 63, 2, %r28
+#else
+	depi	0, 31, 2, %r28
+#endif
+	b	3f
+1:	stbys,e	%r0, 0(%r28)
+2:	b,n	lws_stby_fault
+	ASM_EXCEPTIONTABLE_ENTRY(1b-linux_gateway_page, 2b-linux_gateway_page)
+
+	/* Calculate 8-bit hash index from virtual address */
+3:	extru_safe  %r26, 23, 8, %r28
+	extru_safe  %r26, 15, 8, %r1
+	xor	%r1, %r28, %r28
+	extru_safe  %r26, 7, 8, %r1
+	xor	%r1, %r28, %r20
+
+	/* Load start of lock table */
+	ldil	L%lws_lock_start, %r28
+	ldo	R%lws_lock_start(%r28), %r28
+
+	/* Find lock to use, the hash index is one of 0 to
+	   255, multiplied by 16 (keep it 16-byte aligned)
+	   and add to the lock table offset. */
+	shlw	%r20, 4, %r20
+	add	%r20, %r28, %r20
+
+	shlw	%r25, 2, %r1
+
+	/* We disable interrupts around the critical region. However,
+	   the store instruction in the critical region might cause a
+	   COW break. The trap handler needs to re-enable interrupts
+	   when page faults are enabled as the process might sleep.
+	   When this happens, the lock may be held by a process for
+	   an extended period and affect unrelated processes because
+	   locks are shared. */
+	rsm	PSW_SM_I, %r0			/* Disable interrupts */
+
+	/* Check lock first to minimize cache line bounce */
+	ldw	0(%sr2,%r20), %r28		/* Load the lock */
+	cmpb,=,n	%r0, %r28, 1f		/* Spin if locked */
+	LDCW	0(%sr2,%r20), %r28		/* Try to acquire the lock */
+	cmpb,<>,n	%r28, %r0, atomic_xchg_action	/* Did we get it? */
+1:	ldo	2(%r0), %r28			/* 2nd case */
+	ssm	PSW_SM_I, %r0
+	b	lws_exit			/* Contended... */
+	ldo	-EAGAIN(%r0), %r21		/* Spin in userspace */
+
+	/* NOTES:
+		This all works because intr_do_signal
+		and schedule both check the return iasq
+		and see that we are on the kernel page
+		so this process is never scheduled off
+		or is ever sent any signal of any sort,
+		thus it is wholly atomic from usrspaces
+		perspective
+	*/
+
+atomic_xchg_action:
+	/* Jump to the correct function */
+	blr	%r1, %r0
+	/* Set %r28 as non-zero for now */
+	ldo	1(%r0),%r28
+
+	/* 8bit exchange */
+1:	ldb	0(%r26), %r1
+2:	stb	%r1, 0(%r23)
+3:	ldb	0(%r24), %r1
+4:	stb	%r1, 0(%r26)
+	b	atomic_xchg_end
+	copy	%r0, %r28
+	nop
+	nop
+
+	/* 16bit exchange */
+5:	ldh	0(%r26), %r1
+6:	sth	%r1, 0(%r23)
+7:	ldh	0(%r24), %r1
+8:	sth	%r1, 0(%r26)
+	b	atomic_xchg_end
+	copy	%r0, %r28
+	nop
+	nop
+
+	/* 32bit exchange */
+9:	ldw	0(%r26), %r1
+10:	stw	%r1, 0(%r23)
+11:	ldw	0(%r24), %r1
+12:	stw	%r1, 0(%r26)
+	b	atomic_xchg_end
+	copy	%r0, %r28
+	nop
+	nop
+
+	/* 64bit exchange */
+#ifdef CONFIG_64BIT
+13:	ldd	0(%r26), %r1
+14:	std	%r1, 0(%r23)
+15:	ldd	0(%r24), %r1
+16:	std	%r1, 0(%r26)
+#else
+13:	flddx	0(%r26), %fr4
+14:	fstdx	%fr4, 0(%r23)
+15:	flddx	0(%r24), %fr4
+16:	fstdx	%fr4, 0(%r26)
+#endif
+	copy	%r0, %r28
+
+atomic_xchg_end:
+	/* Free lock */
+	stw,ma	%r20, 0(%sr2,%r20)
+	/* Return to userspace, set no error */
+	b	lws_exit
+	copy	%r0, %r21
+
+17:
+	/* Error occurred on load or store */
+	/* Free lock */
+	stw,ma	%r20, 0(%sr2,%r20)
+	ldo	1(%r0),%r28
+	b	lws_exit
+	ldo	-EFAULT(%r0),%r21	/* set errno */
+
+	/* Exception table entries, for the load and store, return EFAULT.
+	   Each of the entries must be relocated. */
+	ASM_EXCEPTIONTABLE_ENTRY(1b-linux_gateway_page, 17b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(2b-linux_gateway_page, 17b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(3b-linux_gateway_page, 17b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(4b-linux_gateway_page, 17b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(5b-linux_gateway_page, 17b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(6b-linux_gateway_page, 17b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(7b-linux_gateway_page, 17b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(8b-linux_gateway_page, 17b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(9b-linux_gateway_page, 17b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(10b-linux_gateway_page, 17b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(11b-linux_gateway_page, 17b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(12b-linux_gateway_page, 17b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(13b-linux_gateway_page, 17b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(14b-linux_gateway_page, 17b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(15b-linux_gateway_page, 17b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(16b-linux_gateway_page, 17b-linux_gateway_page)
+
+	/***************************************************
+		LWS atomic store.  When using using a synthesized CAS
+		operation, we need to perform atomic loads using the CAS
+		lock to ensure sequential consistency.
+
+		%r26 - Address to store 
+		%r25 - Size of the variable (0/1/2/3 for 8/16/32/64 bit)
+		%r24 - Address of value to store
+		%r28 - Return non-zero on failure
+		%r21 - Kernel error code
+
+		%r21 has the following meanings:
+
+		EAGAIN - Lock is busy, ldcw failed, try again.
+		EFAULT - Read failed.
+
+		Scratch: r20, r1
+
+	****************************************************/
+
+	/* ELF32 Process entry path */
+lws_atomic_store:
+#ifdef CONFIG_64BIT
+	/* Clip the input registers. We don't need to clip %r25 as we
+	   only use it for word operations */
+	depdi	0, 31, 32, %r26
+	depdi	0, 31, 32, %r25
+	depdi	0, 31, 32, %r24
+#endif
+
+	/* Check the validity of the size pointer */
+	subi,>>= 3, %r25, %r0
+	b,n	lws_exit_nosys
+
+	shlw	%r25, 1, %r1
+
+	/* Dirty cache line at r26 to avoid COW break in critical region */
+	copy	%r26, %r28
+#ifdef CONFIG_64BIT
+	depdi	0, 63, 2, %r28
+#else
+	depi	0, 31, 2, %r28
+#endif
+	b	3f
+1:	stbys,e	%r0, 0(%r28)
+2:	b,n	lws_stby_fault
+	ASM_EXCEPTIONTABLE_ENTRY(1b-linux_gateway_page, 2b-linux_gateway_page)
+
+	/* Calculate 8-bit hash index from virtual address */
+3:	extru_safe  %r26, 23, 8, %r28
+	extru_safe  %r26, 15, 8, %r1
+	xor	%r1, %r28, %r28
+	extru_safe  %r26, 7, 8, %r1
+	xor	%r1, %r28, %r20
+
+	/* Load start of lock table */
+	ldil	L%lws_lock_start, %r28
+	ldo	R%lws_lock_start(%r28), %r28
+
+	/* Find lock to use, the hash index is one of 0 to
+	   255, multiplied by 16 (keep it 16-byte aligned)
+	   and add to the lock table offset. */
+	shlw	%r20, 4, %r20
+	add	%r20, %r28, %r20
+
+	shlw	%r25, 1, %r1
+
+	/* We disable interrupts around the critical region. However,
+	   the store instruction in the critical region might cause a
+	   COW break. The trap handler needs to re-enable interrupts
+	   when page faults are enabled as the process might sleep.
+	   When this happens, the lock may be held by a process for
+	   an extended period and affect unrelated processes because
+	   locks are shared. */
+	rsm	PSW_SM_I, %r0			/* Disable interrupts */
+
+	/* Check lock first to minimize cache line bounce */
+	ldw	0(%sr2,%r20), %r28		/* Load the lock */
+	cmpb,=,n	%r0, %r28, 1f		/* Spin if locked */
+	LDCW	0(%sr2,%r20), %r28		/* Try to acquire the lock */
+	cmpb,<>,n	%r0, %r28, atomic_store_action	/* Did we get it? */
+1:	ldo	2(%r0), %r28			/* 2nd case */
+	ssm	PSW_SM_I, %r0
+	b	lws_exit			/* Contended... */
+	ldo	-EAGAIN(%r0), %r21		/* Spin in userspace */
+
+	/* NOTES:
+		This all works because intr_do_signal
+		and schedule both check the return iasq
+		and see that we are on the kernel page
+		so this process is never scheduled off
+		or is ever sent any signal of any sort,
+		thus it is wholly atomic from usrspaces
+		perspective
+	*/
+
+atomic_store_action:
+	/* Jump to the correct function */
+	blr	%r1, %r0
+	/* Set %r28 as non-zero for now */
+	ldo	1(%r0),%r28
+
+	/* 8bit store */
+1:	ldb	0(%r24), %r1
+2:	stb	%r1, 0(%r26)
+	b	atomic_store_end
+	copy	%r0, %r28
+
+	/* 16bit store */
+3:	ldh	0(%r24), %r1
+4:	sth	%r1, 0(%r26)
+	b	atomic_store_end
+	copy	%r0, %r28
+
+	/* 32bit store */
+5:	ldw	0(%r24), %r1
+6:	stw	%r1, 0(%r26)
+	b	atomic_store_end
+	copy	%r0, %r28
+
+	/* 64bit store */
+#ifdef CONFIG_64BIT
+7:	ldd	0(%r24), %r1
+8:	std	%r1, 0(%r26)
+#else
+7:	flddx	0(%r24), %fr4
+8:	fstdx	%fr4, 0(%r26)
+#endif
+	copy	%r0, %r28
+
+atomic_store_end:
+	/* Free lock */
+	stw,ma	%r20, 0(%sr2,%r20)
+	/* Return to userspace, set no error */
+	b	lws_exit
+	copy	%r0, %r21
+
+9:
+	/* Error occurred on store */
+	/* Free lock */
+	stw,ma	%r20, 0(%sr2,%r20)
+	ldo	1(%r0),%r28
+	b	lws_exit
+	ldo	-EFAULT(%r0),%r21	/* set errno */
+
+	/* Exception table entries, return EFAULT.
+	   Each of the entries must be relocated. */
+	ASM_EXCEPTIONTABLE_ENTRY(1b-linux_gateway_page, 9b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(2b-linux_gateway_page, 9b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(3b-linux_gateway_page, 9b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(4b-linux_gateway_page, 9b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(5b-linux_gateway_page, 9b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(6b-linux_gateway_page, 9b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(7b-linux_gateway_page, 9b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(8b-linux_gateway_page, 9b-linux_gateway_page)
+
 	/* Make sure nothing else is placed on this page */
 	.align PAGE_SIZE
 END(linux_gateway_page)
@@ -916,6 +1305,8 @@ ENTRY(lws_table)
 	LWS_ENTRY(compare_and_swap32)		/* 0 - ELF32 Atomic 32bit CAS */
 	LWS_ENTRY(compare_and_swap64)		/* 1 - ELF64 Atomic 32bit CAS */
 	LWS_ENTRY(compare_and_swap_2)		/* 2 - ELF32 Atomic 64bit CAS */
+	LWS_ENTRY(atomic_xchg)			/* 3 - ELF32 Atomic Exchange */
+	LWS_ENTRY(atomic_store)			/* 4 - ELF32 Atomic Store */
 END(lws_table)
 	/* End of lws table */
 
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index 08e4d480abe1..08860a015811 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -249,27 +249,16 @@ void __init time_init(void)
 static int __init init_cr16_clocksource(void)
 {
 	/*
-	 * The cr16 interval timers are not syncronized across CPUs on
-	 * different sockets, so mark them unstable and lower rating on
-	 * multi-socket SMP systems.
+	 * The cr16 interval timers are not syncronized across CPUs, even if
+	 * they share the same socket.
 	 */
 	if (num_online_cpus() > 1 && !running_on_qemu) {
-		int cpu;
-		unsigned long cpu0_loc;
-		cpu0_loc = per_cpu(cpu_data, 0).cpu_loc;
-
-		for_each_online_cpu(cpu) {
-			if (cpu == 0)
-				continue;
-			if ((cpu0_loc != 0) &&
-			    (cpu0_loc == per_cpu(cpu_data, cpu).cpu_loc))
-				continue;
-
-			clocksource_cr16.name = "cr16_unstable";
-			clocksource_cr16.flags = CLOCK_SOURCE_UNSTABLE;
-			clocksource_cr16.rating = 0;
-			break;
-		}
+		/* mark sched_clock unstable */
+		clear_sched_clock_stable();
+
+		clocksource_cr16.name = "cr16_unstable";
+		clocksource_cr16.flags = CLOCK_SOURCE_UNSTABLE;
+		clocksource_cr16.rating = 0;
 	}
 
 	/* XXX: We may want to mark sched_clock stable here if cr16 clocks are
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index 8d8441d4562a..725dbf4554dd 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -479,9 +479,9 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
 	int si_code;
 
 	if (code == 1)
-	    pdc_console_restart();  /* switch back to pdc if HPMC */
-	else
-	    local_irq_enable();
+		pdc_console_restart();  /* switch back to pdc if HPMC */
+	else if (!irqs_disabled_flags(regs->gr[0]))
+		local_irq_enable();
 
 	/* Security check:
 	 * If the priority level is still user, and the
@@ -729,6 +729,8 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
 			}
 			mmap_read_unlock(current->mm);
 		}
+		/* CPU could not fetch instruction, so clear IIR stale value. */
+		regs->iir = 0xbaadf00d;
 		fallthrough;
 	case 27: 
 		/* Data memory protection ID trap */
@@ -782,13 +784,13 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
 	     * unless pagefault_disable() was called before.
 	     */
 
-	    if (fault_space == 0 && !faulthandler_disabled())
+	    if (faulthandler_disabled() || fault_space == 0)
 	    {
 		/* Clean up and return if in exception table. */
 		if (fixup_exception(regs))
 			return;
 		pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC);
-		parisc_terminate("Kernel Fault", regs, code, fault_address);
+		parisc_terminate("Kernel Fault", regs, code, 0);
 	    }
 	}
 
diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c
index 86a57fb0e6fa..34676658c040 100644
--- a/arch/parisc/kernel/unwind.c
+++ b/arch/parisc/kernel/unwind.c
@@ -309,7 +309,8 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
 				break;
 			}
 
-			if (get_user(tmp, (unsigned long *)(info->prev_sp - RP_OFFSET))) 
+			if (copy_from_kernel_nofault(&tmp,
+			    (void *)info->prev_sp - RP_OFFSET, sizeof(tmp)))
 				break;
 			info->prev_ip = tmp;
 			sp = info->prev_sp;
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index 3d208afd15bc..2769eb991f58 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -57,8 +57,6 @@ SECTIONS
 {
 	. = KERNEL_BINARY_TEXT_START;
 
-	_stext = .;	/* start of kernel text, includes init code & data */
-
 	__init_begin = .;
 	HEAD_TEXT_SECTION
 	MLONGCALL_DISCARD(INIT_TEXT_SECTION(8))
@@ -82,6 +80,7 @@ SECTIONS
 	/* freed after init ends here */
 
 	_text = .;		/* Text and read-only data */
+	_stext = .;
 	MLONGCALL_KEEP(INIT_TEXT_SECTION(8))
 	.text ALIGN(PAGE_SIZE) : {
 		TEXT_TEXT
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index bf33f4b0de40..c4721acb367b 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -341,7 +341,7 @@ static void __init setup_bootmem(void)
 
 static bool kernel_set_to_readonly;
 
-static void __init map_pages(unsigned long start_vaddr,
+static void map_pages(unsigned long start_vaddr,
 			     unsigned long start_paddr, unsigned long size,
 			     pgprot_t pgprot, int force)
 {
diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c
index ed3c4c42fc23..d68d05d5d383 100644
--- a/drivers/char/agp/parisc-agp.c
+++ b/drivers/char/agp/parisc-agp.c
@@ -281,7 +281,7 @@ agp_ioc_init(void __iomem *ioc_regs)
         return 0;
 }
 
-static int
+static int __init
 lba_find_capability(int cap)
 {
 	struct _parisc_agp_info *info = &parisc_agp_info;
@@ -366,7 +366,7 @@ parisc_agp_setup(void __iomem *ioc_hpa, void __iomem *lba_hpa)
 	return error;
 }
 
-static int
+static int __init
 find_quicksilver(struct device *dev, void *data)
 {
 	struct parisc_device **lba = data;
@@ -378,7 +378,7 @@ find_quicksilver(struct device *dev, void *data)
 	return 0;
 }
 
-static int
+static int __init
 parisc_agp_init(void)
 {
 	extern struct sba_device *sba_list;
