-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Michal Simek
committed
Mar 27, 2009
1 parent
7fa3945
commit 4b2c755
Showing
4 changed files
with
679 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
--- | ||
refs/heads/master: 945ce1bc54e40aa0a659226b6e79a0bce065945f | ||
refs/heads/master: c4df4bc155bbe18fb91800bb9d29499a4fb211ad |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
/* | ||
* Preliminary support for HW exception handing for Microblaze | ||
* | ||
* Copyright (C) 2008 Michal Simek | ||
* Copyright (C) 2008 PetaLogix | ||
* Copyright (C) 2005 John Williams <jwilliams@itee.uq.edu.au> | ||
* | ||
* 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. | ||
*/ | ||
|
||
#ifndef _ASM_MICROBLAZE_EXCEPTIONS_H | ||
#define _ASM_MICROBLAZE_EXCEPTIONS_H | ||
|
||
#ifdef __KERNEL__ | ||
#ifndef __ASSEMBLY__ | ||
|
||
/* Macros to enable and disable HW exceptions in the MSR */ | ||
/* Define MSR enable bit for HW exceptions */ | ||
#define HWEX_MSR_BIT (1 << 8) | ||
|
||
#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR | ||
#define __enable_hw_exceptions() \ | ||
__asm__ __volatile__ (" msrset r0, %0; \ | ||
nop;" \ | ||
: \ | ||
: "i" (HWEX_MSR_BIT) \ | ||
: "memory") | ||
|
||
#define __disable_hw_exceptions() \ | ||
__asm__ __volatile__ (" msrclr r0, %0; \ | ||
nop;" \ | ||
: \ | ||
: "i" (HWEX_MSR_BIT) \ | ||
: "memory") | ||
#else /* !CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */ | ||
#define __enable_hw_exceptions() \ | ||
__asm__ __volatile__ (" \ | ||
mfs r12, rmsr; \ | ||
nop; \ | ||
ori r12, r12, %0; \ | ||
mts rmsr, r12; \ | ||
nop;" \ | ||
: \ | ||
: "i" (HWEX_MSR_BIT) \ | ||
: "memory", "r12") | ||
|
||
#define __disable_hw_exceptions() \ | ||
__asm__ __volatile__ (" \ | ||
mfs r12, rmsr; \ | ||
nop; \ | ||
andi r12, r12, ~%0; \ | ||
mts rmsr, r12; \ | ||
nop;" \ | ||
: \ | ||
: "i" (HWEX_MSR_BIT) \ | ||
: "memory", "r12") | ||
#endif /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */ | ||
|
||
asmlinkage void full_exception(struct pt_regs *regs, unsigned int type, | ||
int fsr, int addr); | ||
|
||
#if defined(CONFIG_XMON) | ||
extern void xmon(struct pt_regs *regs); | ||
extern int xmon_bpt(struct pt_regs *regs); | ||
extern int xmon_sstep(struct pt_regs *regs); | ||
extern int xmon_iabr_match(struct pt_regs *regs); | ||
extern int xmon_dabr_match(struct pt_regs *regs); | ||
extern void (*xmon_fault_handler)(struct pt_regs *regs); | ||
|
||
void (*debugger)(struct pt_regs *regs) = xmon; | ||
int (*debugger_bpt)(struct pt_regs *regs) = xmon_bpt; | ||
int (*debugger_sstep)(struct pt_regs *regs) = xmon_sstep; | ||
int (*debugger_iabr_match)(struct pt_regs *regs) = xmon_iabr_match; | ||
int (*debugger_dabr_match)(struct pt_regs *regs) = xmon_dabr_match; | ||
void (*debugger_fault_handler)(struct pt_regs *regs); | ||
#elif defined(CONFIG_KGDB) | ||
void (*debugger)(struct pt_regs *regs); | ||
int (*debugger_bpt)(struct pt_regs *regs); | ||
int (*debugger_sstep)(struct pt_regs *regs); | ||
int (*debugger_iabr_match)(struct pt_regs *regs); | ||
int (*debugger_dabr_match)(struct pt_regs *regs); | ||
void (*debugger_fault_handler)(struct pt_regs *regs); | ||
#else | ||
#define debugger(regs) do { } while (0) | ||
#define debugger_bpt(regs) 0 | ||
#define debugger_sstep(regs) 0 | ||
#define debugger_iabr_match(regs) 0 | ||
#define debugger_dabr_match(regs) 0 | ||
#define debugger_fault_handler ((void (*)(struct pt_regs *))0) | ||
#endif | ||
|
||
#endif /*__ASSEMBLY__ */ | ||
#endif /* __KERNEL__ */ | ||
#endif /* _ASM_MICROBLAZE_EXCEPTIONS_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
/* | ||
* HW exception handling | ||
* | ||
* Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu> | ||
* Copyright (C) 2008 PetaLogix | ||
* | ||
* 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. | ||
*/ | ||
|
||
/* | ||
* This file handles the architecture-dependent parts of hardware exceptions | ||
*/ | ||
|
||
#include <linux/kernel.h> | ||
#include <linux/signal.h> | ||
#include <linux/sched.h> | ||
#include <linux/kallsyms.h> | ||
#include <linux/module.h> | ||
|
||
#include <asm/exceptions.h> | ||
#include <asm/entry.h> /* For KM CPU var */ | ||
#include <asm/uaccess.h> | ||
#include <asm/errno.h> | ||
#include <asm/ptrace.h> | ||
#include <asm/current.h> | ||
|
||
#define MICROBLAZE_ILL_OPCODE_EXCEPTION 0x02 | ||
#define MICROBLAZE_IBUS_EXCEPTION 0x03 | ||
#define MICROBLAZE_DBUS_EXCEPTION 0x04 | ||
#define MICROBLAZE_DIV_ZERO_EXCEPTION 0x05 | ||
#define MICROBLAZE_FPU_EXCEPTION 0x06 | ||
#define MICROBLAZE_PRIVILEG_EXCEPTION 0x07 | ||
|
||
static DEFINE_SPINLOCK(die_lock); | ||
|
||
void die(const char *str, struct pt_regs *fp, long err) | ||
{ | ||
console_verbose(); | ||
spin_lock_irq(&die_lock); | ||
printk(KERN_WARNING "Oops: %s, sig: %ld\n", str, err); | ||
show_regs(fp); | ||
spin_unlock_irq(&die_lock); | ||
/* do_exit() should take care of panic'ing from an interrupt | ||
* context so we don't handle it here | ||
*/ | ||
do_exit(err); | ||
} | ||
|
||
void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) | ||
{ | ||
siginfo_t info; | ||
|
||
if (kernel_mode(regs)) { | ||
debugger(regs); | ||
die("Exception in kernel mode", regs, signr); | ||
} | ||
info.si_signo = signr; | ||
info.si_errno = 0; | ||
info.si_code = code; | ||
info.si_addr = (void __user *) addr; | ||
force_sig_info(signr, &info, current); | ||
} | ||
|
||
asmlinkage void full_exception(struct pt_regs *regs, unsigned int type, | ||
int fsr, int addr) | ||
{ | ||
#if 0 | ||
printk(KERN_WARNING "Exception %02x in %s mode, FSR=%08x PC=%08x ESR=%08x\n", | ||
type, user_mode(regs) ? "user" : "kernel", fsr, | ||
(unsigned int) regs->pc, (unsigned int) regs->esr); | ||
#endif | ||
|
||
switch (type & 0x1F) { | ||
case MICROBLAZE_ILL_OPCODE_EXCEPTION: | ||
_exception(SIGILL, regs, ILL_ILLOPC, addr); | ||
break; | ||
case MICROBLAZE_IBUS_EXCEPTION: | ||
if (user_mode(regs)) { | ||
printk(KERN_WARNING "Instruction bus error exception in user mode.\n"); | ||
_exception(SIGBUS, regs, BUS_ADRERR, addr); | ||
return; | ||
} | ||
printk(KERN_WARNING "Instruction bus error exception in kernel mode.\n"); | ||
die("bus exception", regs, SIGBUS); | ||
break; | ||
case MICROBLAZE_DBUS_EXCEPTION: | ||
if (user_mode(regs)) { | ||
printk(KERN_WARNING "Data bus error exception in user mode.\n"); | ||
_exception(SIGBUS, regs, BUS_ADRERR, addr); | ||
return; | ||
} | ||
printk(KERN_WARNING "Data bus error exception in kernel mode.\n"); | ||
die("bus exception", regs, SIGBUS); | ||
break; | ||
case MICROBLAZE_DIV_ZERO_EXCEPTION: | ||
printk(KERN_WARNING "Divide by zero exception\n"); | ||
_exception(SIGILL, regs, ILL_ILLOPC, addr); | ||
break; | ||
|
||
case MICROBLAZE_FPU_EXCEPTION: | ||
/* IEEE FP exception */ | ||
/* I removed fsr variable and use code var for storing fsr */ | ||
if (fsr & FSR_IO) | ||
fsr = FPE_FLTINV; | ||
else if (fsr & FSR_OF) | ||
fsr = FPE_FLTOVF; | ||
else if (fsr & FSR_UF) | ||
fsr = FPE_FLTUND; | ||
else if (fsr & FSR_DZ) | ||
fsr = FPE_FLTDIV; | ||
else if (fsr & FSR_DO) | ||
fsr = FPE_FLTRES; | ||
_exception(SIGFPE, regs, fsr, addr); | ||
break; | ||
|
||
default: | ||
printk(KERN_WARNING "Unexpected exception %02x " | ||
"PC=%08x in %s mode\n", type, (unsigned int) addr, | ||
kernel_mode(regs) ? "kernel" : "user"); | ||
} | ||
return; | ||
} |
Oops, something went wrong.