patch-2.3.16 linux/arch/sh/kernel/traps.c

Next file: linux/arch/sh/lib/Makefile
Previous file: linux/arch/sh/kernel/time.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.15/linux/arch/sh/kernel/traps.c linux/arch/sh/kernel/traps.c
@@ -0,0 +1,128 @@
+/*
+ *  linux/arch/sh/traps.c
+ *
+ *  SuperH version: Copyright (C) 1999  Niibe Yutaka
+ */
+
+/*
+ * 'Traps.c' handles hardware traps and faults after we have saved some
+ * state in 'entry.S'.
+ */
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/spinlock.h>
+#include <asm/atomic.h>
+
+static inline void console_verbose(void)
+{
+	extern int console_loglevel;
+	console_loglevel = 15;
+}
+
+#define DO_ERROR(trapnr, signr, str, name, tsk) \
+asmlinkage void do_##name(unsigned long r4, unsigned long r5, \
+			  unsigned long r6, unsigned long r7, \
+			  struct pt_regs regs) \
+{ \
+	unsigned long error_code; \
+ \
+	asm volatile("stc	r2_bank,%0": "=r" (error_code)); \
+	sti(); \
+	regs.syscall_nr = -1; \
+	tsk->thread.error_code = error_code; \
+	tsk->thread.trap_no = trapnr; \
+	force_sig(signr, tsk); \
+	die_if_no_fixup(str,&regs,error_code); \
+}
+
+/*
+ * These constants are for searching for possible module text
+ * segments.  VMALLOC_OFFSET comes from mm/vmalloc.c; MODULE_RANGE is
+ * a guess of how much space is likely to be vmalloced.
+ */
+#define VMALLOC_OFFSET (8*1024*1024)
+#define MODULE_RANGE (8*1024*1024)
+
+static void show_registers(struct pt_regs *regs)
+{/* Not implemented yet. */
+}	
+
+spinlock_t die_lock;
+
+void die(const char * str, struct pt_regs * regs, long err)
+{
+	console_verbose();
+	spin_lock_irq(&die_lock);
+	printk("%s: %04lx\n", str, err & 0xffff);
+	show_registers(regs);
+	spin_unlock_irq(&die_lock);
+	do_exit(SIGSEGV);
+}
+
+static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
+{
+	if (!user_mode(regs))
+		die(str, regs, err);
+}
+
+static void die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
+{
+	if (!user_mode(regs))
+	{
+		unsigned long fixup;
+		fixup = search_exception_table(regs->pc);
+		if (fixup) {
+			regs->pc = fixup;
+			return;
+		}
+		die(str, regs, err);
+	}
+}
+
+DO_ERROR( 7, SIGSEGV, "address error (load)", address_error_load, current)
+DO_ERROR( 8, SIGSEGV, "address error (store)", address_error_store, current)
+DO_ERROR(12, SIGILL,  "reserved instruction", reserved_inst, current)
+DO_ERROR(13, SIGILL,  "illegal slot instruction", illegal_slot_inst, current)
+
+asmlinkage void do_exception_error (unsigned long r4, unsigned long r5,
+				    unsigned long r6, unsigned long r7,
+				    struct pt_regs regs)
+{
+	long ex;
+	asm volatile("stc	r2_bank,%0" : "=r" (ex));
+	die_if_kernel("exception", &regs, ex);
+}
+
+void __init trap_init(void)
+{
+	extern void *vbr_base;
+	extern void *exception_handling_table[14];
+
+	exception_handling_table[7] = (void *)do_address_error_load;
+	exception_handling_table[8] = (void *)do_address_error_store;
+	exception_handling_table[12] = (void *)do_reserved_inst;
+	exception_handling_table[13] = (void *)do_illegal_slot_inst;
+
+	/* NOTE: The VBR value should be at P1
+	   (or P2, virtural "fixed" address space).
+	   It's definitely should not in physical address.  */
+
+	asm volatile("ldc	%0,vbr"
+		     : /* no output */
+		     : "r" (&vbr_base)
+		     : "memory");
+}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)