sh: Set up correct siginfo structures for page faults.

Remove the previous saving of fault codes into the thread_struct
as they are never used, and appeared to be inherited from x86.

Signed-off-by: Stuart Menefy <stuart.menefy@st.com>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
diff --git a/arch/sh/kernel/cpu/sh4/fpu.c b/arch/sh/kernel/cpu/sh4/fpu.c
index 378b488..7624677 100644
--- a/arch/sh/kernel/cpu/sh4/fpu.c
+++ b/arch/sh/kernel/cpu/sh4/fpu.c
@@ -282,11 +282,8 @@
 			grab_fpu(regs);
 			restore_fpu(tsk);
 			set_tsk_thread_flag(tsk, TIF_USEDFPU);
-		} else {
-			tsk->thread.trap_no = 11;
-			tsk->thread.error_code = 0;
+		} else
 			force_sig(SIGFPE, tsk);
-		}
 
 		regs->pc = nextpc;
 		return 1;
@@ -307,8 +304,6 @@
 
 	regs->pc += 2;
 	save_fpu(tsk, regs);
-	tsk->thread.trap_no = 11;
-	tsk->thread.error_code = 0;
 	force_sig(SIGFPE, tsk);
 }
 
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c
index b52037b..0ee2980 100644
--- a/arch/sh/kernel/traps.c
+++ b/arch/sh/kernel/traps.c
@@ -93,7 +93,7 @@
 
 	if (!user_mode(regs) || in_interrupt())
 		dump_mem("Stack: ", regs->regs[15], THREAD_SIZE +
-		 	 (unsigned long)task_stack_page(current));
+			 (unsigned long)task_stack_page(current));
 
 	bust_spinlocks(0);
 	spin_unlock_irq(&die_lock);
@@ -201,7 +201,7 @@
 		if (copy_to_user(dst,src,4))
 			goto fetch_fault;
 		ret = 0;
- 		break;
+		break;
 
 	case 2: /* mov.[bwl] to memory, possibly with pre-decrement */
 		if (instruction & 4)
@@ -225,7 +225,7 @@
 		if (copy_from_user(dst,src,4))
 			goto fetch_fault;
 		ret = 0;
- 		break;
+		break;
 
 	case 6:	/* mov.[bwl] from memory, possibly with post-increment */
 		src = (unsigned char*) *rm;
@@ -233,7 +233,7 @@
 			*rm += count;
 		dst = (unsigned char*) rn;
 		*(unsigned long*)dst = 0;
-		
+
 #ifdef __LITTLE_ENDIAN__
 		if (copy_from_user(dst, src, count))
 			goto fetch_fault;
@@ -244,7 +244,7 @@
 		}
 #else
 		dst += 4-count;
-		
+
 		if (copy_from_user(dst, src, count))
 			goto fetch_fault;
 
@@ -323,7 +323,8 @@
 			return -EFAULT;
 
 		/* kernel */
-		die("delay-slot-insn faulting in handle_unaligned_delayslot", regs, 0);
+		die("delay-slot-insn faulting in handle_unaligned_delayslot",
+		    regs, 0);
 	}
 
 	return handle_unaligned_ins(instruction,regs);
@@ -364,7 +365,8 @@
 	if (user_mode(regs) && handle_unaligned_notify_count>0) {
 		handle_unaligned_notify_count--;
 
-		printk("Fixing up unaligned userspace access in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
+		printk(KERN_NOTICE "Fixing up unaligned userspace access "
+		       "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
 		       current->comm,current->pid,(u16*)regs->pc,instruction);
 	}
 
@@ -499,7 +501,15 @@
 #endif
 
 /*
- * Handle various address error exceptions
+ * Handle various address error exceptions:
+ *  - instruction address error:
+ *       misaligned PC
+ *       PC >= 0x80000000 in user mode
+ *  - data address error (read and write)
+ *       misaligned data access
+ *       access to >= 0x80000000 is user mode
+ * Unfortuntaly we can't distinguish between instruction address error
+ * and data address errors caused by read acceses.
  */
 asmlinkage void do_address_error(struct pt_regs *regs,
 				 unsigned long writeaccess,
@@ -507,6 +517,7 @@
 {
 	unsigned long error_code = 0;
 	mm_segment_t oldfs;
+	siginfo_t info;
 #ifndef CONFIG_CPU_SH2A
 	u16 instruction;
 	int tmp;
@@ -520,22 +531,15 @@
 	oldfs = get_fs();
 
 	if (user_mode(regs)) {
+		int si_code = BUS_ADRERR;
+
 		local_irq_enable();
-		current->thread.error_code = error_code;
-#ifdef CONFIG_CPU_SH2
-		/*
-		 * On the SH-2, we only have a single vector for address
-		 * errors, there's no differentiating between a load error
-		 * and a store error.
-		 */
-		current->thread.trap_no = 9;
-#else
-		current->thread.trap_no = (writeaccess) ? 8 : 7;
-#endif
 
 		/* bad PC is not something we can fix */
-		if (regs->pc & 1)
+		if (regs->pc & 1) {
+			si_code = BUS_ADRALN;
 			goto uspace_segv;
+		}
 
 #ifndef CONFIG_CPU_SH2A
 		set_fs(USER_DS);
@@ -554,9 +558,16 @@
 			return; /* sorted */
 #endif
 
-	uspace_segv:
-		printk(KERN_NOTICE "Killing process \"%s\" due to unaligned access\n", current->comm);
-		force_sig(SIGSEGV, current);
+uspace_segv:
+		printk(KERN_NOTICE "Sending SIGBUS to \"%s\" due to unaligned "
+		       "access (PC %lx PR %lx)\n", current->comm, regs->pc,
+		       regs->pr);
+
+		info.si_signo = SIGBUS;
+		info.si_errno = 0;
+		info.si_code = si_code;
+		info.si_addr = (void *) address;
+		force_sig_info(SIGBUS, &info, current);
 	} else {
 		if (regs->pc & 1)
 			die("unaligned program counter", regs, error_code);
@@ -574,7 +585,9 @@
 		handle_unaligned_access(instruction, regs);
 		set_fs(oldfs);
 #else
-		printk(KERN_NOTICE "Killing process \"%s\" due to unaligned access\n", current->comm);
+		printk(KERN_NOTICE "Killing process \"%s\" due to unaligned "
+		       "access\n", current->comm);
+
 		force_sig(SIGSEGV, current);
 #endif
 	}
@@ -617,9 +630,6 @@
 	struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
 	siginfo_t info;
 
-	current->thread.trap_no = r4;
-	current->thread.error_code = 0;
-
 	switch (r4) {
 	case TRAP_DIVZERO_ERROR:
 		info.si_code = FPE_INTDIV;
@@ -662,7 +672,7 @@
 
 #ifdef CONFIG_SH_DSP
 	/* Check if it's a DSP instruction */
- 	if (is_dsp_inst(regs)) {
+	if (is_dsp_inst(regs)) {
 		/* Enable DSP mode, and restart instruction. */
 		regs->sr |= SR_DSP;
 		return;
@@ -672,8 +682,6 @@
 	lookup_exception_vector(error_code);
 
 	local_irq_enable();
-	tsk->thread.error_code = error_code;
-	tsk->thread.trap_no = TRAP_RESERVED_INST;
 	CHK_REMOTE_DEBUG(regs);
 	force_sig(SIGILL, tsk);
 	die_if_no_fixup("reserved instruction", regs, error_code);
@@ -745,8 +753,6 @@
 	lookup_exception_vector(error_code);
 
 	local_irq_enable();
-	tsk->thread.error_code = error_code;
-	tsk->thread.trap_no = TRAP_RESERVED_INST;
 	CHK_REMOTE_DEBUG(regs);
 	force_sig(SIGILL, tsk);
 	die_if_no_fixup("illegal slot instruction", regs, error_code);
@@ -805,7 +811,7 @@
 {
 	extern void *exception_handling_table[];
 	void *old_handler;
-	
+
 	old_handler = exception_handling_table[vec];
 	exception_handling_table[vec] = handler;
 	return old_handler;
@@ -841,7 +847,7 @@
 	set_exception_table_vec(TRAP_DIVZERO_ERROR, do_divide_error);
 	set_exception_table_vec(TRAP_DIVOVF_ERROR, do_divide_error);
 #endif
-		
+
 	/* Setup VBR for boot cpu */
 	per_cpu_trap_init();
 }
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c
index 68663b8..43bed2c 100644
--- a/arch/sh/mm/fault.c
+++ b/arch/sh/mm/fault.c
@@ -26,13 +26,16 @@
  * and the problem, and then passes it off to one of the appropriate
  * routines.
  */
-asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
-			      unsigned long address)
+asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
+					unsigned long writeaccess,
+					unsigned long address)
 {
 	struct task_struct *tsk;
 	struct mm_struct *mm;
 	struct vm_area_struct * vma;
 	unsigned long page;
+	int si_code;
+	siginfo_t info;
 
 #ifdef CONFIG_SH_KGDB
 	if (kgdb_nofault && kgdb_bus_err_hook)
@@ -41,6 +44,7 @@
 
 	tsk = current;
 	mm = tsk->mm;
+	si_code = SEGV_MAPERR;
 
 	/*
 	 * If we're in an interrupt or have no user
@@ -65,6 +69,7 @@
  * we can handle it..
  */
 good_area:
+	si_code = SEGV_ACCERR;
 	if (writeaccess) {
 		if (!(vma->vm_flags & VM_WRITE))
 			goto bad_area;
@@ -105,9 +110,11 @@
 	up_read(&mm->mmap_sem);
 
 	if (user_mode(regs)) {
-		tsk->thread.address = address;
-		tsk->thread.error_code = writeaccess;
-		force_sig(SIGSEGV, tsk);
+		info.si_signo = SIGSEGV;
+		info.si_errno = 0;
+		info.si_code = si_code;
+		info.si_addr = (void *) address;
+		force_sig_info(SIGSEGV, &info, tsk);
 		return;
 	}
 
@@ -166,10 +173,11 @@
 	 * Send a sigbus, regardless of whether we were in kernel
 	 * or user mode.
 	 */
-	tsk->thread.address = address;
-	tsk->thread.error_code = writeaccess;
-	tsk->thread.trap_no = 14;
-	force_sig(SIGBUS, tsk);
+	info.si_signo = SIGBUS;
+	info.si_errno = 0;
+	info.si_code = BUS_ADRERR;
+	info.si_addr = (void *)address;
+	force_sig_info(SIGBUS, &info, tsk);
 
 	/* Kernel mode? Handle exceptions or die */
 	if (!user_mode(regs))
diff --git a/include/asm-sh/processor.h b/include/asm-sh/processor.h
index da22ac3..4a90e7c 100644
--- a/include/asm-sh/processor.h
+++ b/include/asm-sh/processor.h
@@ -136,12 +136,11 @@
 };
 
 struct thread_struct {
+	/* Saved registers when thread is descheduled */
 	unsigned long sp;
 	unsigned long pc;
 
-	unsigned long trap_no, error_code;
-	unsigned long address;
-	/* Hardware debugging registers may come here */
+	/* Hardware debugging registers */
 	unsigned long ubc_pc;
 
 	/* floating point info */
@@ -156,12 +155,7 @@
 extern int ubc_usercnt;
 
 #define INIT_THREAD  {						\
-	sizeof(init_stack) + (long) &init_stack, /* sp */	\
-	0,					 /* pc */	\
-	0, 0,							\
-	0,							\
-	0,							\
-	{{{0,}},}				/* fpu state */	\
+	.sp = sizeof(init_stack) + (long) &init_stack,		\
 }
 
 /*