summary refs log tree commit diff
path: root/arch/parisc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-06-29 11:30:45 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-29 11:30:45 -0700
commit4d3ce21fa9d2eaeda113aa2f9c2da80d972bef64 (patch)
tree9ffa5af467d6e9f6f6c8eb496489bf882613a459 /arch/parisc
parentb026188e8214ce87790730a56f3017d0bd222751 (diff)
parentc1a7a755be26f68d7f21ee769584149a96185ea8 (diff)
downloadlinux-4d3ce21fa9d2eaeda113aa2f9c2da80d972bef64.tar.gz
Merge master.kernel.org:/pub/scm/linux/kernel/git/kyle/parisc-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/kyle/parisc-2.6: (23 commits)
  [PARISC] Move os_id_to_string() inside #ifndef __ASSEMBLY__
  [PARISC] Fix do_gettimeofday() hang
  [PARISC] Fix PCREL22F relocation problem for most modules
  [PARISC] Refactor show_regs in traps.c
  [PARISC] Add os_id_to_string helper
  [PARISC] OS_ID_LINUX == 0x0006
  [PARISC] Ensure Space ID hashing is turned off
  [PARISC] Match show_cache_info with reality
  [PARISC] Remove unused macro fixup_branch in syscall.S
  [PARISC] Add is_compat_task() helper
  [PARISC] Update Thibaut Varene's CREDITS entry
  [PARISC] Reduce data footprint in pdc_stable.c
  [PARISC] pdc_stable version 0.30
  [PARISC] Work around machines which do not support chassis warnings
  [PARISC] PDC_CHASSIS is implemented on all machines
  [PARISC] Remove unconditional #define PIC in syscall macros
  [PARISC] Use MFIA in current_text_addr on pa2.0 processors
  [PARISC] Remove dead function pc_in_user_space
  [PARISC] Test ioc_needs_fdc variable instead of open coding
  [PARISC] Fix gcc 4.1 warnings in sba_iommu.c
  ...
Diffstat (limited to 'arch/parisc')
-rw-r--r--arch/parisc/kernel/cache.c28
-rw-r--r--arch/parisc/kernel/entry.S6
-rw-r--r--arch/parisc/kernel/firmware.c46
-rw-r--r--arch/parisc/kernel/module.c63
-rw-r--r--arch/parisc/kernel/pdc_chassis.c109
-rw-r--r--arch/parisc/kernel/ptrace.c8
-rw-r--r--arch/parisc/kernel/real2.S9
-rw-r--r--arch/parisc/kernel/setup.c5
-rw-r--r--arch/parisc/kernel/signal.c20
-rw-r--r--arch/parisc/kernel/syscall.S14
-rw-r--r--arch/parisc/kernel/time.c18
-rw-r--r--arch/parisc/kernel/traps.c84
-rw-r--r--arch/parisc/kernel/unaligned.c18
13 files changed, 281 insertions, 147 deletions
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index c057ad7605ba..bc7c4a4e26a1 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -97,15 +97,17 @@ update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte)
 void
 show_cache_info(struct seq_file *m)
 {
+	char buf[32];
+
 	seq_printf(m, "I-cache\t\t: %ld KB\n", 
 		cache_info.ic_size/1024 );
-	seq_printf(m, "D-cache\t\t: %ld KB (%s%s, %d-way associative)\n", 
+	if (cache_info.dc_loop == 1)
+		snprintf(buf, 32, "%lu-way associative", cache_info.dc_loop);
+	seq_printf(m, "D-cache\t\t: %ld KB (%s%s, %s)\n",
 		cache_info.dc_size/1024,
 		(cache_info.dc_conf.cc_wt ? "WT":"WB"),
 		(cache_info.dc_conf.cc_sh ? ", shared I/D":""),
-		(cache_info.dc_conf.cc_assoc)
-	);
-
+		((cache_info.dc_loop == 1) ? "direct mapped" : buf));
 	seq_printf(m, "ITLB entries\t: %ld\n" "DTLB entries\t: %ld%s\n",
 		cache_info.it_size,
 		cache_info.dt_size,
@@ -158,11 +160,11 @@ parisc_cache_init(void)
 		cache_info.dc_conf.cc_block,
 		cache_info.dc_conf.cc_line,
 		cache_info.dc_conf.cc_shift);
-	printk("	wt %d sh %d cst %d assoc %d\n",
+	printk("	wt %d sh %d cst %d hv %d\n",
 		cache_info.dc_conf.cc_wt,
 		cache_info.dc_conf.cc_sh,
 		cache_info.dc_conf.cc_cst,
-		cache_info.dc_conf.cc_assoc);
+		cache_info.dc_conf.cc_hv);
 
 	printk("IC  base 0x%lx stride 0x%lx count 0x%lx loop 0x%lx\n",
 		cache_info.ic_base,
@@ -176,11 +178,11 @@ parisc_cache_init(void)
 		cache_info.ic_conf.cc_block,
 		cache_info.ic_conf.cc_line,
 		cache_info.ic_conf.cc_shift);
-	printk("	wt %d sh %d cst %d assoc %d\n",
+	printk("	wt %d sh %d cst %d hv %d\n",
 		cache_info.ic_conf.cc_wt,
 		cache_info.ic_conf.cc_sh,
 		cache_info.ic_conf.cc_cst,
-		cache_info.ic_conf.cc_assoc);
+		cache_info.ic_conf.cc_hv);
 
 	printk("D-TLB conf: sh %d page %d cst %d aid %d pad1 %d \n",
 		cache_info.dt_conf.tc_sh,
@@ -234,7 +236,8 @@ parisc_cache_init(void)
 
 void disable_sr_hashing(void)
 {
-	int srhash_type;
+	int srhash_type, retval;
+	unsigned long space_bits;
 
 	switch (boot_cpu_data.cpu_type) {
 	case pcx: /* We shouldn't get this far.  setup.c should prevent it. */
@@ -260,6 +263,13 @@ void disable_sr_hashing(void)
 	}
 
 	disable_sr_hashing_asm(srhash_type);
+
+	retval = pdc_spaceid_bits(&space_bits);
+	/* If this procedure isn't implemented, don't panic. */
+	if (retval < 0 && retval != PDC_BAD_OPTION)
+		panic("pdc_spaceid_bits call failed.\n");
+	if (space_bits != 0)
+		panic("SpaceID hashing is still on!\n");
 }
 
 void flush_dcache_page(struct page *page)
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index d9e53cf0372b..630730c32a5a 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -1638,7 +1638,7 @@ dbit_trap_20w:
 	load32		PA(pa_dbit_lock),t0
 
 dbit_spin_20w:
-	ldcw            0(t0),t1
+	LDCW		0(t0),t1
 	cmpib,=         0,t1,dbit_spin_20w
 	nop
 
@@ -1674,7 +1674,7 @@ dbit_trap_11:
 	load32		PA(pa_dbit_lock),t0
 
 dbit_spin_11:
-	ldcw            0(t0),t1
+	LDCW		0(t0),t1
 	cmpib,=         0,t1,dbit_spin_11
 	nop
 
@@ -1714,7 +1714,7 @@ dbit_trap_20:
 	load32		PA(pa_dbit_lock),t0
 
 dbit_spin_20:
-	ldcw            0(t0),t1
+	LDCW		0(t0),t1
 	cmpib,=         0,t1,dbit_spin_20
 	nop
 
diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c
index 2dc06b8e1817..4398d2a95789 100644
--- a/arch/parisc/kernel/firmware.c
+++ b/arch/parisc/kernel/firmware.c
@@ -11,7 +11,7 @@
  * Copyright 1999 The Puffin Group, (Alex deVries, David Kennedy)
  * Copyright 2003 Grant Grundler <grundler parisc-linux org>
  * Copyright 2003,2004 Ryan Bradetich <rbrad@parisc-linux.org>
- * Copyright 2004 Thibaut VARENE <varenet@parisc-linux.org>
+ * Copyright 2004,2006 Thibaut VARENE <varenet@parisc-linux.org>
  *
  *    This program is free software; you can redistribute it and/or modify
  *    it under the terms of the GNU General Public License as published by
@@ -252,10 +252,8 @@ int pdc_pat_chassis_send_log(unsigned long state, unsigned long data)
 #endif
 
 /**
- * pdc_chassis_disp - Updates display
+ * pdc_chassis_disp - Updates chassis code
  * @retval: -1 on error, 0 on success
- *
- * Works on old PDC only (E class, others?)
  */
 int pdc_chassis_disp(unsigned long disp)
 {
@@ -269,6 +267,22 @@ int pdc_chassis_disp(unsigned long disp)
 }
 
 /**
+ * pdc_chassis_warn - Fetches chassis warnings
+ * @retval: -1 on error, 0 on success
+ */
+int pdc_chassis_warn(unsigned long *warn)
+{
+	int retval = 0;
+
+	spin_lock_irq(&pdc_lock);
+	retval = mem_pdc_call(PDC_CHASSIS, PDC_CHASSIS_WARN, __pa(pdc_result));
+	*warn = pdc_result[0];
+	spin_unlock_irq(&pdc_lock);
+
+	return retval;
+}
+
+/**
  * pdc_coproc_cfg - To identify coprocessors attached to the processor.
  * @pdc_coproc_info: Return buffer address.
  *
@@ -393,7 +407,9 @@ int pdc_model_info(struct pdc_model *model)
  * pdc_model_sysmodel - Get the system model name.
  * @name: A char array of at least 81 characters.
  *
- * Get system model name from PDC ROM (e.g. 9000/715 or 9000/778/B160L)
+ * Get system model name from PDC ROM (e.g. 9000/715 or 9000/778/B160L).
+ * Using OS_ID_HPUX will return the equivalent of the 'modelname' command
+ * on HP/UX.
  */
 int pdc_model_sysmodel(char *name)
 {
@@ -498,6 +514,26 @@ int pdc_cache_info(struct pdc_cache_info *cache_info)
         return retval;
 }
 
+/**
+ * pdc_spaceid_bits - Return whether Space ID hashing is turned on.
+ * @space_bits: Should be 0, if not, bad mojo!
+ *
+ * Returns information about Space ID hashing.
+ */
+int pdc_spaceid_bits(unsigned long *space_bits)
+{
+	int retval;
+
+	spin_lock_irq(&pdc_lock);
+	pdc_result[0] = 0;
+	retval = mem_pdc_call(PDC_CACHE, PDC_CACHE_RET_SPID, __pa(pdc_result), 0);
+	convert_to_wide(pdc_result);
+	*space_bits = pdc_result[0];
+	spin_unlock_irq(&pdc_lock);
+
+	return retval;
+}
+
 #ifndef CONFIG_PA20
 /**
  * pdc_btlb_info - Return block TLB information.
diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c
index f27cfe4771b8..aee311884f3f 100644
--- a/arch/parisc/kernel/module.c
+++ b/arch/parisc/kernel/module.c
@@ -89,6 +89,12 @@ static inline int is_local(struct module *me, void *loc)
 	return is_init(me, loc) || is_core(me, loc);
 }
 
+static inline int is_local_section(struct module *me, void *loc, void *dot)
+{
+	return (is_init(me, loc) && is_init(me, dot)) ||
+		(is_core(me, loc) && is_core(me, dot));
+}
+
 
 #ifndef __LP64__
 struct got_entry {
@@ -364,8 +370,14 @@ static Elf_Addr get_fdesc(struct module *me, unsigned long value)
 }
 #endif /* __LP64__ */
 
+enum elf_stub_type {
+	ELF_STUB_GOT,
+	ELF_STUB_MILLI,
+	ELF_STUB_DIRECT,
+};
+
 static Elf_Addr get_stub(struct module *me, unsigned long value, long addend,
-	int millicode, int init_section)
+	enum elf_stub_type stub_type, int init_section)
 {
 	unsigned long i;
 	struct stub_entry *stub;
@@ -396,7 +408,7 @@ static Elf_Addr get_stub(struct module *me, unsigned long value, long addend,
 	stub->insns[1] |= reassemble_17(rrsel(value, addend) / 4);
 
 #else
-/* for 64-bit we have two kinds of stubs:
+/* for 64-bit we have three kinds of stubs:
  * for normal function calls:
  * 	ldd 0(%dp),%dp
  * 	ldd 10(%dp), %r1
@@ -408,18 +420,23 @@ static Elf_Addr get_stub(struct module *me, unsigned long value, long addend,
  * 	ldo 0(%r1), %r1
  * 	ldd 10(%r1), %r1
  * 	bve,n (%r1)
+ *
+ * for direct branches (jumps between different section of the
+ * same module):
+ *	ldil 0, %r1
+ *	ldo 0(%r1), %r1
+ *	bve,n (%r1)
  */
-	if (!millicode)
-	{
+	switch (stub_type) {
+	case ELF_STUB_GOT:
 		stub->insns[0] = 0x537b0000;	/* ldd 0(%dp),%dp	*/
 		stub->insns[1] = 0x53610020;	/* ldd 10(%dp),%r1	*/
 		stub->insns[2] = 0xe820d000;	/* bve (%r1)		*/
 		stub->insns[3] = 0x537b0030;	/* ldd 18(%dp),%dp	*/
 
 		stub->insns[0] |= reassemble_14(get_got(me, value, addend) & 0x3fff);
-	}
-	else
-	{
+		break;
+	case ELF_STUB_MILLI:
 		stub->insns[0] = 0x20200000;	/* ldil 0,%r1		*/
 		stub->insns[1] = 0x34210000;	/* ldo 0(%r1), %r1	*/
 		stub->insns[2] = 0x50210020;	/* ldd 10(%r1),%r1	*/
@@ -427,7 +444,17 @@ static Elf_Addr get_stub(struct module *me, unsigned long value, long addend,
 
 		stub->insns[0] |= reassemble_21(lrsel(value, addend));
 		stub->insns[1] |= reassemble_14(rrsel(value, addend));
+		break;
+	case ELF_STUB_DIRECT:
+		stub->insns[0] = 0x20200000;    /* ldil 0,%r1           */
+		stub->insns[1] = 0x34210000;    /* ldo 0(%r1), %r1      */
+		stub->insns[2] = 0xe820d002;    /* bve,n (%r1)          */
+
+		stub->insns[0] |= reassemble_21(lrsel(value, addend));
+		stub->insns[1] |= reassemble_14(rrsel(value, addend));
+		break;
 	}
+
 #endif
 
 	return (Elf_Addr)stub;
@@ -539,14 +566,14 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
 			break;
 		case R_PARISC_PCREL17F:
 			/* 17-bit PC relative address */
-			val = get_stub(me, val, addend, 0, is_init(me, loc));
+			val = get_stub(me, val, addend, ELF_STUB_GOT, is_init(me, loc));
 			val = (val - dot - 8)/4;
 			CHECK_RELOC(val, 17)
 			*loc = (*loc & ~0x1f1ffd) | reassemble_17(val);
 			break;
 		case R_PARISC_PCREL22F:
 			/* 22-bit PC relative address; only defined for pa20 */
-			val = get_stub(me, val, addend, 0, is_init(me, loc));
+			val = get_stub(me, val, addend, ELF_STUB_GOT, is_init(me, loc));
 			DEBUGP("STUB FOR %s loc %lx+%lx at %lx\n", 
 			       strtab + sym->st_name, (unsigned long)loc, addend, 
 			       val)
@@ -643,13 +670,23 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
 			       strtab + sym->st_name,
 			       loc, val);
 			/* can we reach it locally? */
-			if(!is_local(me, (void *)val)) {
-				if (strncmp(strtab + sym->st_name, "$$", 2)
+			if(!is_local_section(me, (void *)val, (void *)dot)) {
+
+				if (is_local(me, (void *)val))
+					/* this is the case where the
+					 * symbol is local to the
+					 * module, but in a different
+					 * section, so stub the jump
+					 * in case it's more than 22
+					 * bits away */
+					val = get_stub(me, val, addend, ELF_STUB_DIRECT,
+						       is_init(me, loc));
+				else if (strncmp(strtab + sym->st_name, "$$", 2)
 				    == 0)
-					val = get_stub(me, val, addend, 1,
+					val = get_stub(me, val, addend, ELF_STUB_MILLI,
 						       is_init(me, loc));
 				else
-					val = get_stub(me, val, addend, 0,
+					val = get_stub(me, val, addend, ELF_STUB_GOT,
 						       is_init(me, loc));
 			}
 			DEBUGP("STUB FOR %s loc %lx, val %lx+%lx at %lx\n", 
diff --git a/arch/parisc/kernel/pdc_chassis.c b/arch/parisc/kernel/pdc_chassis.c
index a45e2e2ffd9f..d47ba1aa8253 100644
--- a/arch/parisc/kernel/pdc_chassis.c
+++ b/arch/parisc/kernel/pdc_chassis.c
@@ -1,8 +1,8 @@
 /* 
- *    interfaces to log Chassis Codes via PDC (firmware)
+ *    interfaces to Chassis Codes via PDC (firmware)
  *
  *    Copyright (C) 2002 Laurent Canet <canetl@esiee.fr>
- *    Copyright (C) 2002-2004 Thibaut VARENE <varenet@parisc-linux.org>
+ *    Copyright (C) 2002-2006 Thibaut VARENE <varenet@parisc-linux.org>
  *
  *    This program is free software; you can redistribute it and/or modify
  *    it under the terms of the GNU General Public License, version 2, as
@@ -16,6 +16,10 @@
  *    You should have received a copy of the GNU General Public License
  *    along with this program; if not, write to the Free Software
  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *    TODO: poll chassis warns, trigger (configurable) machine shutdown when
+ *    		needed.
+ *    	    Find out how to get Chassis warnings out of PAT boxes?
  */
 
 #undef PDC_CHASSIS_DEBUG
@@ -30,15 +34,16 @@
 #include <linux/reboot.h>
 #include <linux/notifier.h>
 #include <linux/cache.h>
+#include <linux/proc_fs.h>
 
 #include <asm/pdc_chassis.h>
 #include <asm/processor.h>
 #include <asm/pdc.h>
 #include <asm/pdcpat.h>
 
+#define PDC_CHASSIS_VER	"0.05"
 
 #ifdef CONFIG_PDC_CHASSIS
-static int pdc_chassis_old __read_mostly = 0;	
 static unsigned int pdc_chassis_enabled __read_mostly = 1;
 
 
@@ -64,7 +69,7 @@ __setup("pdcchassis=", pdc_chassis_setup);
  * Currently, only E class and A180 are known to work with this.
  * Inspired by Christoph Plattner
  */
-
+#if 0
 static void __init pdc_chassis_checkold(void)
 {
 	switch(CPU_HVERSION) {
@@ -73,7 +78,6 @@ static void __init pdc_chassis_checkold(void)
 		case 0x482:		/* E45 */
 		case 0x483:		/* E55 */
 		case 0x516:		/* A180 */
-			pdc_chassis_old = 1;
 			break;
 
 		default:
@@ -81,7 +85,7 @@ static void __init pdc_chassis_checkold(void)
 	}
 	DPRINTK(KERN_DEBUG "%s: pdc_chassis_checkold(); pdc_chassis_old = %d\n", __FILE__, pdc_chassis_old);
 }
-
+#endif
 
 /**
  * pdc_chassis_panic_event() - Called by the panic handler.
@@ -131,30 +135,20 @@ static struct notifier_block pdc_chassis_reboot_block = {
 void __init parisc_pdc_chassis_init(void)
 {
 #ifdef CONFIG_PDC_CHASSIS
-	int handle = 0;
 	if (likely(pdc_chassis_enabled)) {
 		DPRINTK(KERN_DEBUG "%s: parisc_pdc_chassis_init()\n", __FILE__);
 
 		/* Let see if we have something to handle... */
-		/* Check for PDC_PAT or old LED Panel */
-		pdc_chassis_checkold();
-		if (is_pdc_pat()) {
-			printk(KERN_INFO "Enabling PDC_PAT chassis codes support.\n");
-			handle = 1;
-		}
-		else if (unlikely(pdc_chassis_old)) {
-			printk(KERN_INFO "Enabling old style chassis LED panel support.\n");
-			handle = 1;
-		}
-
-		if (handle) {
-			/* initialize panic notifier chain */
-			atomic_notifier_chain_register(&panic_notifier_list,
-					&pdc_chassis_panic_block);
-
-			/* initialize reboot notifier chain */
-			register_reboot_notifier(&pdc_chassis_reboot_block);
-		}
+		printk(KERN_INFO "Enabling %s chassis codes support v%s\n",
+				is_pdc_pat() ? "PDC_PAT" : "regular",
+				PDC_CHASSIS_VER);
+
+		/* initialize panic notifier chain */
+		atomic_notifier_chain_register(&panic_notifier_list,
+				&pdc_chassis_panic_block);
+
+		/* initialize reboot notifier chain */
+		register_reboot_notifier(&pdc_chassis_reboot_block);
 	}
 #endif /* CONFIG_PDC_CHASSIS */
 }
@@ -215,9 +209,12 @@ int pdc_chassis_send_status(int message)
 			}
 		} else retval = -1;
 #else
-		if (unlikely(pdc_chassis_old)) {
+		if (1) {
 			switch (message) {
 				case PDC_CHASSIS_DIRECT_BSTART:
+					retval = pdc_chassis_disp(PDC_CHASSIS_DISP_DATA(OSTAT_INIT));
+					break;
+
 				case PDC_CHASSIS_DIRECT_BCOMPLETE:
 					retval = pdc_chassis_disp(PDC_CHASSIS_DISP_DATA(OSTAT_RUN));
 					break;
@@ -244,3 +241,61 @@ int pdc_chassis_send_status(int message)
 #endif /* CONFIG_PDC_CHASSIS */
 	return retval;
 }
+
+#ifdef CONFIG_PDC_CHASSIS_WARN
+#ifdef CONFIG_PROC_FS
+static int pdc_chassis_warn_pread(char *page, char **start, off_t off,
+		int count, int *eof, void *data)
+{
+	char *out = page;
+	int len, ret;
+	unsigned long warn;
+	u32 warnreg;
+
+	ret = pdc_chassis_warn(&warn);
+	if (ret != PDC_OK)
+		return -EIO;
+
+	warnreg = (warn & 0xFFFFFFFF);
+
+	if ((warnreg >> 24) & 0xFF)
+		out += sprintf(out, "Chassis component failure! (eg fan or PSU): 0x%.2x\n", ((warnreg >> 24) & 0xFF));
+
+	out += sprintf(out, "Battery: %s\n", (warnreg & 0x04) ? "Low!" : "OK");
+	out += sprintf(out, "Temp low: %s\n", (warnreg & 0x02) ? "Exceeded!" : "OK");
+	out += sprintf(out, "Temp mid: %s\n", (warnreg & 0x01) ? "Exceeded!" : "OK");
+
+	len = out - page - off;
+	if (len < count) {
+		*eof = 1;
+		if (len <= 0) return 0;
+	} else {
+		len = count;
+	}
+	*start = page + off;
+	return len;
+}
+
+static int __init pdc_chassis_create_procfs(void)
+{
+	unsigned long test;
+	int ret;
+
+	ret = pdc_chassis_warn(&test);
+	if ((ret == PDC_BAD_PROC) || (ret == PDC_BAD_OPTION)) {
+		/* seems that some boxes (eg L1000) do not implement this */
+		printk(KERN_INFO "Chassis warnings not supported.\n");
+		return 0;
+	}
+
+	printk(KERN_INFO "Enabling PDC chassis warnings support v%s\n",
+			PDC_CHASSIS_VER);
+	create_proc_read_entry("chassis", 0400, NULL, pdc_chassis_warn_pread,
+				NULL);
+	return 0;
+}
+
+__initcall(pdc_chassis_create_procfs);
+
+#endif /* CONFIG_PROC_FS */
+#endif /* CONFIG_PDC_CHASSIS_WARN */
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
index 413292f1a4a3..3f28de974556 100644
--- a/arch/parisc/kernel/ptrace.c
+++ b/arch/parisc/kernel/ptrace.c
@@ -91,7 +91,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 		int copied;
 
 #ifdef __LP64__
-		if (personality(child->personality) == PER_LINUX32) {
+		if (__is_compat_task(child)) {
 			unsigned int tmp;
 
 			addr &= 0xffffffffL;
@@ -123,7 +123,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 	case PTRACE_POKEDATA:
 		ret = 0;
 #ifdef __LP64__
-		if (personality(child->personality) == PER_LINUX32) {
+		if (__is_compat_task(child)) {
 			unsigned int tmp = (unsigned int)data;
 			DBG("sys_ptrace(POKE%s, %d, %lx, %lx)\n",
 				request == PTRACE_POKETEXT ? "TEXT" : "DATA",
@@ -146,7 +146,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 	case PTRACE_PEEKUSR: {
 		ret = -EIO;
 #ifdef __LP64__
-		if (personality(child->personality) == PER_LINUX32) {
+		if (__is_compat_task(child)) {
 			unsigned int tmp;
 
 			if (addr & (sizeof(int)-1))
@@ -205,7 +205,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 			goto out_tsk;
 		}
 #ifdef __LP64__
-		if (personality(child->personality) == PER_LINUX32) {
+		if (__is_compat_task(child)) {
 			if (addr & (sizeof(int)-1))
 				goto out_tsk;
 			if ((addr = translate_usr_offset(addr)) < 0)
diff --git a/arch/parisc/kernel/real2.S b/arch/parisc/kernel/real2.S
index 8c2859cca77e..453d01a9f971 100644
--- a/arch/parisc/kernel/real2.S
+++ b/arch/parisc/kernel/real2.S
@@ -276,15 +276,6 @@ r64_ret:
 
 #endif
 
-	.export pc_in_user_space
-	.text
-	/* Doesn't belong here but I couldn't find a nicer spot. */
-	/* Should never get called, only used by profile stuff in time.c */
-pc_in_user_space:
-	bv,n	0(%rp)
-	nop
-
-
 	.export __canonicalize_funcptr_for_compare
 	.text
 	/* http://lists.parisc-linux.org/hypermail/parisc-linux/10916.html
diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c
index 4a36ec3f6ac1..278f4b9f6a38 100644
--- a/arch/parisc/kernel/setup.c
+++ b/arch/parisc/kernel/setup.c
@@ -303,6 +303,8 @@ extern void eisa_init(void);
 
 static int __init parisc_init(void)
 {
+	u32 osid = (OS_ID_LINUX << 16);
+
 	parisc_proc_mkdir();
 	parisc_init_resources();
 	do_device_inventory();                  /* probe for hardware */
@@ -311,6 +313,9 @@ static int __init parisc_init(void)
 	
 	/* set up a new led state on systems shipped LED State panel */
 	pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BSTART);
+
+	/* tell PDC we're Linux. Nevermind failure. */
+	pdc_stable_write(0x40, &osid, sizeof(osid));
 	
 	processor_init();
 	printk(KERN_INFO "CPU(s): %d x %s at %d.%06d MHz\n",
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
index cc38edfd90c5..bb83880c5ee3 100644
--- a/arch/parisc/kernel/signal.c
+++ b/arch/parisc/kernel/signal.c
@@ -76,7 +76,7 @@ sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *r
 #ifdef __LP64__
 	compat_sigset_t newset32;
 
-	if(personality(current->personality) == PER_LINUX32){
+	if (is_compat_task()) {
 		/* XXX: Don't preclude handling different sized sigset_t's.  */
 		if (sigsetsize != sizeof(compat_sigset_t))
 			return -EINVAL;
@@ -153,7 +153,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
 	compat_sigset_t compat_set;
 	struct compat_rt_sigframe __user * compat_frame;
 	
-	if(personality(current->personality) == PER_LINUX32)
+	if (is_compat_task())
 		sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
 #endif
 
@@ -166,7 +166,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
 #ifdef __LP64__
 	compat_frame = (struct compat_rt_sigframe __user *)frame;
 	
-	if(personality(current->personality) == PER_LINUX32){
+	if (is_compat_task()) {
 		DBG(2,"sys_rt_sigreturn: ELF32 process.\n");
 		if (__copy_from_user(&compat_set, &compat_frame->uc.uc_sigmask, sizeof(compat_set)))
 			goto give_sigsegv;
@@ -186,7 +186,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
 
 	/* Good thing we saved the old gr[30], eh? */
 #ifdef __LP64__
-	if(personality(current->personality) == PER_LINUX32){
+	if (is_compat_task()) {
 		DBG(1,"sys_rt_sigreturn: compat_frame->uc.uc_mcontext 0x%p\n",
 				&compat_frame->uc.uc_mcontext);
 // FIXME: Load upper half from register file
@@ -315,7 +315,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 
 	compat_frame = (struct compat_rt_sigframe __user *)frame;
 	
-	if(personality(current->personality) == PER_LINUX32) {
+	if (is_compat_task()) {
 		DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &compat_frame->info);
 		err |= copy_siginfo_to_user32(&compat_frame->info, info);
 		DBG(1,"SETUP_RT_FRAME: 1\n");
@@ -392,7 +392,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	haddr = A(ka->sa.sa_handler);
 	/* The sa_handler may be a pointer to a function descriptor */
 #ifdef __LP64__
-	if(personality(current->personality) == PER_LINUX32) {
+	if (is_compat_task()) {
 #endif
 		if (haddr & PA_PLABEL_FDESC) {
 			Elf32_Fdesc fdesc;
@@ -427,19 +427,19 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	 */
 	sigframe_size = PARISC_RT_SIGFRAME_SIZE;
 #ifdef __LP64__
-	if(personality(current->personality) == PER_LINUX32)
+	if (is_compat_task())
 		sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
 #endif
 	if (in_syscall) {
 		regs->gr[31] = haddr;
 #ifdef __LP64__
-		if(personality(current->personality) == PER_LINUX)
+		if (personality(current->personality) == PER_LINUX)
 			sigframe_size |= 1;
 #endif
 	} else {
 		unsigned long psw = USER_PSW;
 #ifdef __LP64__
-		if(personality(current->personality) == PER_LINUX)
+		if (personality(current->personality) == PER_LINUX)
 			psw |= PSW_W;
 #endif
 
@@ -464,7 +464,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	regs->gr[26] = sig;               /* signal number */
 	
 #ifdef __LP64__
-	if(personality(current->personality) == PER_LINUX32){
+	if (is_compat_task()) {
 		regs->gr[25] = A(&compat_frame->info); /* siginfo pointer */
 		regs->gr[24] = A(&compat_frame->uc);   /* ucontext pointer */
 	} else
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
index 479d9a017cd1..9670a89c77fe 100644
--- a/arch/parisc/kernel/syscall.S
+++ b/arch/parisc/kernel/syscall.S
@@ -29,18 +29,6 @@
 	.level		1.1
 #endif
 
-#ifndef CONFIG_64BIT
-	.macro fixup_branch,lbl
-	b	    \lbl
-	.endm
-#else
-	.macro fixup_branch,lbl
-	ldil	    L%\lbl, %r1
-	ldo	    R%\lbl(%r1), %r1
-	bv,n        %r0(%r1)
-	.endm
-#endif
-
 	.text
 
 	.import syscall_exit,code
@@ -541,7 +529,7 @@ cas_nocontend:
 # endif
 /* ENABLE_LWS_DEBUG */
 
-	ldcw	0(%sr2,%r20), %r28			/* Try to acquire the lock */
+	LDCW	0(%sr2,%r20), %r28			/* Try to acquire the lock */
 	cmpb,<>,n	%r0, %r28, cas_action		/* Did we get it? */
 cas_wouldblock:
 	ldo	2(%r0), %r28				/* 2nd case */
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index 594930bc4bcf..eb35e1c0bb53 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -157,8 +157,22 @@ do_gettimeofday (struct timeval *tv)
 		usec += (xtime.tv_nsec / 1000);
 	} while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
 
-	while (usec >= 1000000) {
-		usec -= 1000000;
+	if (unlikely(usec > LONG_MAX)) {
+		/* This can happen if the gettimeoffset adjustment is
+		 * negative and xtime.tv_nsec is smaller than the
+		 * adjustment */
+		printk(KERN_ERR "do_gettimeofday() spurious xtime.tv_nsec of %ld\n", usec);
+		usec += USEC_PER_SEC;
+		--sec;
+		/* This should never happen, it means the negative
+		 * time adjustment was more than a second, so there's
+		 * something seriously wrong */
+		BUG_ON(usec > LONG_MAX);
+	}
+
+
+	while (usec >= USEC_PER_SEC) {
+		usec -= USEC_PER_SEC;
 		++sec;
 	}
 
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index ff200608c851..348344a84bf7 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -66,57 +66,42 @@ int printbinary(char *buf, unsigned long x, int nbits)
 #else
 #define RFMT "%08lx"
 #endif
+#define FFMT "%016llx"	/* fpregs are 64-bit always */
 
-void show_regs(struct pt_regs *regs)
+#define PRINTREGS(lvl,r,f,fmt,x)	\
+	printk("%s%s%02d-%02d  " fmt " " fmt " " fmt " " fmt "\n",	\
+		lvl, f, (x), (x+3), (r)[(x)+0], (r)[(x)+1],		\
+		(r)[(x)+2], (r)[(x)+3])
+
+static void print_gr(char *level, struct pt_regs *regs)
 {
 	int i;
-	char buf[128], *p;
-	char *level;
-	unsigned long cr30;
-	unsigned long cr31;
-	/* carlos says that gcc understands better memory in a struct,
-	 * and it makes our life easier with fpregs -- T-Bone */
-	struct { u32 sw[2]; } s;
-	
-	level = user_mode(regs) ? KERN_DEBUG : KERN_CRIT;
-
-	printk("%s\n", level); /* don't want to have that pretty register dump messed up */
+	char buf[64];
 
+	printk("%s\n", level);
 	printk("%s     YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI\n", level);
 	printbinary(buf, regs->gr[0], 32);
 	printk("%sPSW: %s %s\n", level, buf, print_tainted());
 
-	for (i = 0; i < 32; i += 4) {
-		int j;
-		p = buf;
-		p += sprintf(p, "%sr%02d-%02d ", level, i, i + 3);
-		for (j = 0; j < 4; j++) {
-			p += sprintf(p, " " RFMT, (i+j) == 0 ? 0 : regs->gr[i + j]);
-		}
-		printk("%s\n", buf);
-	}
+	for (i = 0; i < 32; i += 4)
+		PRINTREGS(level, regs->gr, "r", RFMT, i);
+}
 
-	for (i = 0; i < 8; i += 4) {
-		int j;
-		p = buf;
-		p += sprintf(p, "%ssr%d-%d  ", level, i, i + 3);
-		for (j = 0; j < 4; j++) {
-			p += sprintf(p, " " RFMT, regs->sr[i + j]);
-		}
-		printk("%s\n", buf);
-	}
+static void print_fr(char *level, struct pt_regs *regs)
+{
+	int i;
+	char buf[64];
+	struct { u32 sw[2]; } s;
 
 	/* FR are 64bit everywhere. Need to use asm to get the content
 	 * of fpsr/fper1, and we assume that we won't have a FP Identify
 	 * in our way, otherwise we're screwed.
 	 * The fldd is used to restore the T-bit if there was one, as the
 	 * store clears it anyway.
-	 * BTW, PA2.0 book says "thou shall not use fstw on FPSR/FPERs". */ 
-	__asm__ (
-		"fstd %%fr0,0(%1)	\n\t"
-		"fldd 0(%1),%%fr0	\n\t"
-		: "=m" (s) : "r" (&s) : "%r0"
-		);
+	 * PA2.0 book says "thou shall not use fstw on FPSR/FPERs" - T-Bone */
+	asm volatile ("fstd %%fr0,0(%1)	\n\t"
+		      "fldd 0(%1),%%fr0	\n\t"
+		      : "=m" (s) : "r" (&s) : "r0");
 
 	printk("%s\n", level);
 	printk("%s      VZOUICununcqcqcqcqcqcrmunTDVZOUI\n", level);
@@ -125,14 +110,25 @@ void show_regs(struct pt_regs *regs)
 	printk("%sFPER1: %08x\n", level, s.sw[1]);
 
 	/* here we'll print fr0 again, tho it'll be meaningless */
-	for (i = 0; i < 32; i += 4) {
-		int j;
-		p = buf;
-		p += sprintf(p, "%sfr%02d-%02d ", level, i, i + 3);
-		for (j = 0; j < 4; j++)
-			p += sprintf(p, " %016llx", (i+j) == 0 ? 0 : regs->fr[i+j]);
-		printk("%s\n", buf);
-	}
+	for (i = 0; i < 32; i += 4)
+		PRINTREGS(level, regs->fr, "fr", FFMT, i);
+}
+
+void show_regs(struct pt_regs *regs)
+{
+	int i;
+	char *level;
+	unsigned long cr30, cr31;
+
+	level = user_mode(regs) ? KERN_DEBUG : KERN_CRIT;
+
+	print_gr(level, regs);
+
+	for (i = 0; i < 8; i += 4)
+		PRINTREGS(level, regs->sr, "sr", RFMT, i);
+
+	if (user_mode(regs))
+		print_fr(level, regs);
 
 	cr30 = mfctl(30);
 	cr31 = mfctl(31);
diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c
index de0a1b21cb40..92328fbddb3e 100644
--- a/arch/parisc/kernel/unaligned.c
+++ b/arch/parisc/kernel/unaligned.c
@@ -43,6 +43,8 @@
 	"\tldil L%%" #lbl ", %%r1\n"			\
 	"\tldo R%%" #lbl "(%%r1), %%r1\n"		\
 	"\tbv,n %%r0(%%r1)\n"
+/* If you use FIXUP_BRANCH, then you must list this clobber */
+#define FIXUP_BRANCH_CLOBBER "r1"
 
 /* 1111 1100 0000 0000 0001 0011 1100 0000 */
 #define OPCODE1(a,b,c)	((a)<<26|(b)<<12|(c)<<6) 
@@ -157,7 +159,7 @@ static int emulate_ldh(struct pt_regs *regs, int toreg)
 "	.previous\n"
 	: "=r" (val), "=r" (ret)
 	: "0" (val), "r" (saddr), "r" (regs->isr)
-	: "r20" );
+	: "r20", FIXUP_BRANCH_CLOBBER );
 
 	DPRINTF("val = 0x" RFMT "\n", val);
 
@@ -202,7 +204,7 @@ static int emulate_ldw(struct pt_regs *regs, int toreg, int flop)
 "	.previous\n"
 	: "=r" (val), "=r" (ret)
 	: "0" (val), "r" (saddr), "r" (regs->isr)
-	: "r19", "r20" );
+	: "r19", "r20", FIXUP_BRANCH_CLOBBER );
 
 	DPRINTF("val = 0x" RFMT "\n", val);
 
@@ -253,7 +255,7 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
 "	.previous\n"
 	: "=r" (val), "=r" (ret)
 	: "0" (val), "r" (saddr), "r" (regs->isr)
-	: "r19", "r20" );
+	: "r19", "r20", FIXUP_BRANCH_CLOBBER );
 #else
     {
 	unsigned long valh=0,vall=0;
@@ -287,7 +289,7 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
 "	.previous\n"
 	: "=r" (valh), "=r" (vall), "=r" (ret)
 	: "0" (valh), "1" (vall), "r" (saddr), "r" (regs->isr)
-	: "r19", "r20" );
+	: "r19", "r20", FIXUP_BRANCH_CLOBBER );
 	val=((__u64)valh<<32)|(__u64)vall;
     }
 #endif
@@ -335,7 +337,7 @@ static int emulate_sth(struct pt_regs *regs, int frreg)
 "	.previous\n"
 	: "=r" (ret)
 	: "r" (val), "r" (regs->ior), "r" (regs->isr)
-	: "r19" );
+	: "r19", FIXUP_BRANCH_CLOBBER );
 
 	return ret;
 }
@@ -389,7 +391,7 @@ static int emulate_stw(struct pt_regs *regs, int frreg, int flop)
 "	.previous\n"
 	: "=r" (ret)
 	: "r" (val), "r" (regs->ior), "r" (regs->isr)
-	: "r19", "r20", "r21", "r22", "r1" );
+	: "r19", "r20", "r21", "r22", "r1", FIXUP_BRANCH_CLOBBER );
 
 	return 0;
 }
@@ -450,7 +452,7 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop)
 "	.previous\n"
 	: "=r" (ret)
 	: "r" (val), "r" (regs->ior), "r" (regs->isr)
-	: "r19", "r20", "r21", "r22", "r1" );
+	: "r19", "r20", "r21", "r22", "r1", FIXUP_BRANCH_CLOBBER );
 #else
     {
 	unsigned long valh=(val>>32),vall=(val&0xffffffffl);
@@ -495,7 +497,7 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop)
 "	.previous\n"
 	: "=r" (ret)
 	: "r" (valh), "r" (vall), "r" (regs->ior), "r" (regs->isr)
-	: "r19", "r20", "r21", "r1" );
+	: "r19", "r20", "r21", "r1", FIXUP_BRANCH_CLOBBER );
     }
 #endif