OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [i960/] [kernel/] [traps.c] - Rev 1765

Compare with Previous | Blame | View Log

/*
 *  linux/arch/i960/kernel/traps.c
 *
 *  Copyright (C) 1999		Keith Adams <kma@cse.ogi.edu>
 * 				Oregon Graduate Institute
 *
 *  Based on:
 *
 *  linux/arch/m68k/kernel/traps.c
 *
 *  Copyright (C) 1993, 1994 by Hamish Macdonald
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file COPYING in the main directory of this archive
 * for more details.
 */
 
/*
 * Sets up all exception vectors
 */
 
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/types.h>
#include <linux/a.out.h>
#include <linux/user.h>
#include <linux/string.h>
#include <linux/linkage.h>
 
#include <asm/setup.h>
#include <asm/system.h>
#include <asm/segment.h>
#include <asm/traps.h>
#include <asm/pgtable.h>
#include <asm/machdep.h>
#include <asm/i960jx.h>
#include <asm/mon960.h>
 
/* set fault handlers in fault table, syscall table */
void trap_init (void)
{
	int	ii;
	unsigned long** prcb = (unsigned long**) get_prcbptr();
	unsigned long* syscall_tab = prcb[5];
	unsigned long* fault_tab = prcb[0];
	extern void fault(void);
 
	/* faults use syscall table entry 1 (0 is for syscalls) */
	syscall_tab[13] = ((unsigned long) fault) | 0x2;
	for (ii=0; ii < 20; ii += 2) {
               /* leave trace trap to mon960; don't mess with reserved
                * fields. */
		if (ii == 2 || ii == 8 || ii == 12 || ii == 16 || ii == 18)
			continue;
 
		fault_tab[ii] = (1 << 2) | 2;	/* use syscall #1 */
		fault_tab[ii+1] = 0x27f;	/* magic number */
	}
}
 
void cfault(unsigned long* fault_rec, struct pt_regs* regs)
{
	int	ii;
	unsigned long wd = fault_rec[2];
	unsigned char type = (wd >> 16);
	unsigned char subtype = (unsigned char)(wd);
	char* nm = "<no fault>";
	int sig = 0;
 
	switch(type) {
		case 3:
			/* arithmetic fault */
			nm = "arithmetic error";
			sig = SIGFPE;
			break;
		case 5:
			/* constraint error? */
			nm = "constraint error";
			break;
		case 2:
			switch(subtype) {
				case 1:
					nm = "illegal instruction";
					sig = SIGILL;
					break;
				case 2:
					nm = "accessed bad address";
					sig = SIGSEGV;
					break;
				case 3:
					nm = "unaligned";
					sig = SIGBUS;
					break;
				case 4:
					nm = "invalid operand";
					sig = SIGILL;
					break;
			}
			break;
		case 7:
			nm = "protection fault";
			sig = SIGILL;
			break;
		case 1:
			nm = "trace fault";
			/* bugger: we need to do better tracing */
			break;
 
		case 0xa:
			nm = "type.mismatch";
			sig = SIGILL;
			break;
	}
 
	if (user_mode(regs)) {
		extern void leave_kernel(struct pt_regs* regs);
		if (sig) {
			current-> signal |= (1 << (sig -1));
		}
		leave_kernel(regs);
		return;
	}
 
	cli();
	/* Amuse the user. */
	printk("\n"
"              \\|/ ____ \\|/\n"
"              \"@'/ ,. \\`@\"\n"
"              /_| \\__/ |_\\\n"
"                 \\__U_/\n");
 
	printk("kernel fault: %s\n", nm);
	for (ii=0; ii < 4; ii++)
		printk("fault_rec: 0x%8x\n", fault_rec[ii]);
 
	show_regs(regs);
	stack_trace();
 
#ifdef CONFIG_MON960
	system_break();
#else
	for (;;) ;
#endif
}
 
void die_if_kernel(char* msg, struct pt_regs* regs, long err)
{
	if (user_mode(regs))
		return;
 
	/* Amuse the user. */
	printk(
"              \\|/ ____ \\|/\n"
"              \"@'/ ,. \\`@\"\n"
"              /_| \\__/ |_\\\n"
"                 \\__U_/\n");
 
	printk("%s: %04lx\n", msg, err & 0xffff);
	show_regs(regs);
	stack_trace();
 
	cli();
	for (;;) ;
}
 
/*
 * Print a quick n' dirty stack trace
 */
struct frameo {
	struct frameo*	pfp;
	unsigned long	sp;
	void*		rip;
};
 
void stack_trace(void)
{
	unsigned long fp;
 
	__asm__ __volatile__ ("flushreg; mov	pfp, %0" : "=r"(fp));
	stack_trace_from(fp);
}
 
void stack_trace_from(unsigned long ulfp)
{
	int	ii;
	long	flags;
	struct frameo* fp = (struct frameo*) ulfp;
 
	save_flags(flags);
	cli();
	printk("trace: fp == %p\n", fp);
	for (ii=1; fp && (ii <  50); ii++, fp=fp->pfp) {
		unsigned long type = ((unsigned long)fp) & 0xf;
		fp = ((unsigned long)fp) & ~0xf;
 
		switch(type) {
			case	1:
				printk("<f>");
				break;
 
			case 2:
			case 3:
				printk("<s>");
				break;
			case 7:
				printk("<i>");
		}
		printk("\t%8x", fp->rip);
		if (! (ii & 0x3))
			printk("\n");
	}
 
	if (!fp) {
		printk("<bottom of stack>\n");
	}
 
	printk("\n");
	restore_flags(flags);
}
 
void ckpt(int num, unsigned long val)
{
 
	printk("--------reached ckpt: %d\tval:0x%8x\n", num, val);
#if 0
	struct pt_regs* regs;
	asm("flushreg; subo 16, fp, %0" : "=r"(regs));
 
	show_regs(regs);
#endif
	printk("current stack trace:\n");
	stack_trace();
	printk("new stack strace:\n");
	stack_trace_from(val);
	printk("offset of ksp: 0x%8x\n", 
	       &(((struct task_struct*)0)->kernel_stack_page));
	printk("current ksp: 0x%8x\n", current->kernel_stack_page);
}
 
void system_break(void)
{
	long	flags;
 
	save_flags(flags);
	cli();
	mon_entry();
	restore_flags(flags);
}
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.