Blackfin arch: allow people to select the feature that is unavailable to the kernel

- allow people to select the feature that is unavailable to the kernel: NMI, JTAG, or CYCLES.
 - change default NMI handler to simply dump hardware trace buffer.
 - remove default NMI handler completely as calling into kernel code is not safe
   move example handler to wiki so people dont haphazardly copy and paste this stuff thinking its safe

Signed-off-by: Mike Frysinger <michael.frysinger@analog.com>
Signed-off-by: Bryan Wu <bryan.wu@analog.com>
This commit is contained in:
Mike Frysinger 2007-08-05 17:03:59 +08:00 committed by Bryan Wu
parent 0174dd59bb
commit f0b5d12f2b
11 changed files with 107 additions and 45 deletions

View File

@ -521,6 +521,52 @@ config BFIN_IDLE_LED_NUM
help help
Select the LED (marked on the board) for you to blink. Select the LED (marked on the board) for you to blink.
choice
prompt "Blackfin Exception Scratch Register"
default BFIN_SCRATCH_REG_RETN
help
Select the resource to reserve for the Exception handler:
- RETN: Non-Maskable Interrupt (NMI)
- RETE: Exception Return (JTAG/ICE)
- CYCLES: Performance counter
If you are unsure, please select "RETN".
config BFIN_SCRATCH_REG_RETN
bool "RETN"
help
Use the RETN register in the Blackfin exception handler
as a stack scratch register. This means you cannot
safely use NMI on the Blackfin while running Linux, but
you can debug the system with a JTAG ICE and use the
CYCLES performance registers.
If you are unsure, please select "RETN".
config BFIN_SCRATCH_REG_RETE
bool "RETE"
help
Use the RETE register in the Blackfin exception handler
as a stack scratch register. This means you cannot
safely use a JTAG ICE while debugging a Blackfin board,
but you can safely use the CYCLES performance registers
and the NMI.
If you are unsure, please select "RETN".
config BFIN_SCRATCH_REG_CYCLES
bool "CYCLES"
help
Use the CYCLES register in the Blackfin exception handler
as a stack scratch register. This means you cannot
safely use the CYCLES performance registers on a Blackfin
board at anytime, but you can debug the system with a JTAG
ICE and use the NMI.
If you are unsure, please select "RETN".
endchoice
# #
# Sorry - but you need to put the hex address here - # Sorry - but you need to put the hex address here -
# #

View File

@ -98,9 +98,8 @@ int show_interrupts(struct seq_file *p, void *v)
*/ */
#ifdef CONFIG_DO_IRQ_L1 #ifdef CONFIG_DO_IRQ_L1
asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)__attribute__((l1_text)); __attribute__((l1_text))
#endif #endif
asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
{ {
struct pt_regs *old_regs; struct pt_regs *old_regs;

View File

@ -53,10 +53,12 @@ __INIT
ENTRY(__start) ENTRY(__start)
/* R0: argument of command line string, passed from uboot, save it */ /* R0: argument of command line string, passed from uboot, save it */
R7 = R0; R7 = R0;
/* Set the SYSCFG register: /* Enable Cycle Counter and Nesting Of Interrupts */
* Enable Cycle Counter and Nesting Of Interrupts (3rd Bit) #ifdef CONFIG_BFIN_SCRATCH_REG_CYCLES
*/ R0 = SYSCFG_SNEN;
R0 = 0x36; #else
R0 = SYSCFG_SNEN | SYSCFG_CCEN;
#endif
SYSCFG = R0; SYSCFG = R0;
R0 = 0; R0 = 0;

View File

@ -51,10 +51,12 @@ __INIT
ENTRY(__start) ENTRY(__start)
/* R0: argument of command line string, passed from uboot, save it */ /* R0: argument of command line string, passed from uboot, save it */
R7 = R0; R7 = R0;
/* Set the SYSCFG register: /* Enable Cycle Counter and Nesting Of Interrupts */
* Enable Cycle Counter and Nesting Of Interrupts (3rd Bit) #ifdef CONFIG_BFIN_SCRATCH_REG_CYCLES
*/ R0 = SYSCFG_SNEN;
R0 = 0x36; #else
R0 = SYSCFG_SNEN | SYSCFG_CCEN;
#endif
SYSCFG = R0; SYSCFG = R0;
R0 = 0; R0 = 0;

View File

@ -50,9 +50,13 @@ ENTRY(__start)
ENTRY(__stext) ENTRY(__stext)
/* R0: argument of command line string, passed from uboot, save it */ /* R0: argument of command line string, passed from uboot, save it */
R7 = R0; R7 = R0;
/* Set the SYSCFG register */ /* Enable Cycle Counter and Nesting Of Interrupts */
R0 = 0x36; #ifdef CONFIG_BFIN_SCRATCH_REG_CYCLES
SYSCFG = R0; /*Enable Cycle Counter and Nesting Of Interrupts(3rd Bit)*/ R0 = SYSCFG_SNEN;
#else
R0 = SYSCFG_SNEN | SYSCFG_CCEN;
#endif
SYSCFG = R0;
R0 = 0; R0 = 0;
/* Clear Out All the data and pointer Registers*/ /* Clear Out All the data and pointer Registers*/

View File

@ -51,10 +51,12 @@ __INIT
ENTRY(__start) ENTRY(__start)
/* R0: argument of command line string, passed from uboot, save it */ /* R0: argument of command line string, passed from uboot, save it */
R7 = R0; R7 = R0;
/* Set the SYSCFG register: /* Enable Cycle Counter and Nesting Of Interrupts */
* Enable Cycle Counter and Nesting Of Interrupts (3rd Bit) #ifdef CONFIG_BFIN_SCRATCH_REG_CYCLES
*/ R0 = SYSCFG_SNEN;
R0 = 0x36; #else
R0 = SYSCFG_SNEN | SYSCFG_CCEN;
#endif
SYSCFG = R0; SYSCFG = R0;
R0 = 0; R0 = 0;

View File

@ -58,6 +58,14 @@
#include <asm/mach-common/context.S> #include <asm/mach-common/context.S>
#if defined(CONFIG_BFIN_SCRATCH_REG_RETN)
# define EX_SCRATCH_REG RETN
#elif defined(CONFIG_BFIN_SCRATCH_REG_RETE)
# define EX_SCRATCH_REG RETE
#else
# define EX_SCRATCH_REG CYCLES
#endif
#ifdef CONFIG_EXCPT_IRQ_SYSC_L1 #ifdef CONFIG_EXCPT_IRQ_SYSC_L1
.section .l1.text .section .l1.text
#else #else
@ -93,7 +101,7 @@ ENTRY(_ex_icplb)
call __cplb_hdr; call __cplb_hdr;
DEBUG_START_HWTRACE(p5, r7) DEBUG_START_HWTRACE(p5, r7)
RESTORE_ALL_SYS RESTORE_ALL_SYS
SP = RETN; SP = EX_SCRATCH_REG;
rtx; rtx;
ENDPROC(_ex_icplb) ENDPROC(_ex_icplb)
@ -102,7 +110,7 @@ ENTRY(_ex_syscall)
(R7:6,P5:4) = [sp++]; (R7:6,P5:4) = [sp++];
ASTAT = [sp++]; ASTAT = [sp++];
raise 15; /* invoked by TRAP #0, for sys call */ raise 15; /* invoked by TRAP #0, for sys call */
sp = retn; sp = EX_SCRATCH_REG;
rtx rtx
ENDPROC(_ex_syscall) ENDPROC(_ex_syscall)
@ -145,7 +153,7 @@ _return_from_exception:
#endif #endif
(R7:6,P5:4) = [sp++]; (R7:6,P5:4) = [sp++];
ASTAT = [sp++]; ASTAT = [sp++];
sp = retn; sp = EX_SCRATCH_REG;
rtx; rtx;
ENDPROC(_ex_soft_bp) ENDPROC(_ex_soft_bp)
@ -204,7 +212,7 @@ ENTRY(_ex_trap_c)
DEBUG_START_HWTRACE(p5, r7) DEBUG_START_HWTRACE(p5, r7)
(R7:6,P5:4) = [sp++]; (R7:6,P5:4) = [sp++];
ASTAT = [sp++]; ASTAT = [sp++];
SP = RETN; SP = EX_SCRATCH_REG;
raise 5; raise 5;
rtx; rtx;
ENDPROC(_ex_trap_c) ENDPROC(_ex_trap_c)
@ -279,7 +287,7 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/
* covered by a CPLB. Switch to an exception stack; use RETN as a * covered by a CPLB. Switch to an exception stack; use RETN as a
* scratch register (for want of a better option). * scratch register (for want of a better option).
*/ */
retn = sp; EX_SCRATCH_REG = sp;
sp.l = _exception_stack_top; sp.l = _exception_stack_top;
sp.h = _exception_stack_top; sp.h = _exception_stack_top;
/* Try to deal with syscalls quickly. */ /* Try to deal with syscalls quickly. */

View File

@ -177,27 +177,15 @@ ENTRY(_evt_ivhw)
jump .Lcommon_restore_context; jump .Lcommon_restore_context;
#endif #endif
/* interrupt routine for evt2 - 2. This is NMI. */ /* Interrupt routine for evt2 (NMI).
ENTRY(_evt_evt2) * We don't actually use this, so just return.
SAVE_CONTEXT * For inner circle type details, please see:
#ifdef CONFIG_FRAME_POINTER * http://docs.blackfin.uclinux.org/doku.php?id=linux:nmi
fp = 0; */
#endif ENTRY(_evt_nmi)
#if ANOMALY_05000283 .weak _evt_nmi
cc = r7 == r7;
p5.h = 0xffc0;
p5.l = 0x0014;
if cc jump 1f;
r7.l = W[p5];
1:
#endif
r0 = IRQ_NMI;
r1 = sp;
SP += -12;
call _asm_do_IRQ;
SP += 12;
RESTORE_CONTEXT
rtn; rtn;
ENDPROC(_evt_nmi)
/* interrupt routine for core timer - 6 */ /* interrupt routine for core timer - 6 */
ENTRY(_evt_timer) ENTRY(_evt_timer)

View File

@ -362,7 +362,11 @@ void __init init_exception_vectors(void)
{ {
SSYNC(); SSYNC();
bfin_write_EVT2(evt_evt2); /* cannot program in software:
* evt0 - emulation (jtag)
* evt1 - reset
*/
bfin_write_EVT2(evt_nmi);
bfin_write_EVT3(trap); bfin_write_EVT3(trap);
bfin_write_EVT5(evt_ivhw); bfin_write_EVT5(evt_ivhw);
bfin_write_EVT6(evt_timer); bfin_write_EVT6(evt_timer);

View File

@ -721,7 +721,11 @@ void __init init_exception_vectors(void)
{ {
SSYNC(); SSYNC();
bfin_write_EVT2(evt_evt2); /* cannot program in software:
* evt0 - emulation (jtag)
* evt1 - reset
*/
bfin_write_EVT2(evt_nmi);
bfin_write_EVT3(trap); bfin_write_EVT3(trap);
bfin_write_EVT5(evt_ivhw); bfin_write_EVT5(evt_ivhw);
bfin_write_EVT6(evt_timer); bfin_write_EVT6(evt_timer);

View File

@ -1,12 +1,15 @@
#ifndef _IRQ_HANDLER_H #ifndef _IRQ_HANDLER_H
#define _IRQ_HANDLER_H #define _IRQ_HANDLER_H
#include <linux/types.h>
#include <linux/linkage.h>
/* BASE LEVEL interrupt handler routines */ /* BASE LEVEL interrupt handler routines */
asmlinkage void evt_exception(void); asmlinkage void evt_exception(void);
asmlinkage void trap(void); asmlinkage void trap(void);
asmlinkage void evt_ivhw(void); asmlinkage void evt_ivhw(void);
asmlinkage void evt_timer(void); asmlinkage void evt_timer(void);
asmlinkage void evt_evt2(void); asmlinkage void evt_nmi(void);
asmlinkage void evt_evt7(void); asmlinkage void evt_evt7(void);
asmlinkage void evt_evt8(void); asmlinkage void evt_evt8(void);
asmlinkage void evt_evt9(void); asmlinkage void evt_evt9(void);