c925cf0b80
Long ago, PT_TRACESYS_OFF and friends were introduced as hard defines to avoid straight constants in assembler parts of linux m68k. They are not used anymore, and were not updated to follow changes in linux kernel. Remove them. When similar constants are needed, they are now generated using asm-offsets.c. Signed-off-by: Philippe De Muyter <phdm@macqel.be> Acked-by: Mike Frysinger <vapier@gentoo.org> Acked-by: Geert Uytterhoeven <geert@linux-m68k.org> Acked-by: Greg Ungerer <gerg@uclinux.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
179 lines
5.3 KiB
C
179 lines
5.3 KiB
C
/*
|
|
* Copyright 2004-2009 Analog Devices Inc.
|
|
*
|
|
* Licensed under the GPL-2 or later.
|
|
*/
|
|
|
|
#ifndef __BFIN_ENTRY_H
|
|
#define __BFIN_ENTRY_H
|
|
|
|
#include <asm/setup.h>
|
|
#include <asm/page.h>
|
|
|
|
#ifdef __ASSEMBLY__
|
|
|
|
#define LFLUSH_I_AND_D 0x00000808
|
|
#define LSIGTRAP 5
|
|
|
|
/*
|
|
* NOTE! The single-stepping code assumes that all interrupt handlers
|
|
* start by saving SYSCFG on the stack with their first instruction.
|
|
*/
|
|
|
|
/* This one is used for exceptions, emulation, and NMI. It doesn't push
|
|
RETI and doesn't do cli. */
|
|
#define SAVE_ALL_SYS save_context_no_interrupts
|
|
/* This is used for all normal interrupts. It saves a minimum of registers
|
|
to the stack, loads the IRQ number, and jumps to common code. */
|
|
#ifdef CONFIG_IPIPE
|
|
# define LOAD_IPIPE_IPEND \
|
|
P0.l = lo(IPEND); \
|
|
P0.h = hi(IPEND); \
|
|
R1 = [P0];
|
|
#else
|
|
# define LOAD_IPIPE_IPEND
|
|
#endif
|
|
|
|
/*
|
|
* Workaround for anomalies 05000283 and 05000315
|
|
*/
|
|
#if ANOMALY_05000283 || ANOMALY_05000315
|
|
# define ANOMALY_283_315_WORKAROUND(preg, dreg) \
|
|
cc = dreg == dreg; \
|
|
preg.h = HI(CHIPID); \
|
|
preg.l = LO(CHIPID); \
|
|
if cc jump 1f; \
|
|
dreg.l = W[preg]; \
|
|
1:
|
|
#else
|
|
# define ANOMALY_283_315_WORKAROUND(preg, dreg)
|
|
#endif /* ANOMALY_05000283 || ANOMALY_05000315 */
|
|
|
|
#ifndef CONFIG_EXACT_HWERR
|
|
/* As a debugging aid - we save IPEND when DEBUG_KERNEL is on,
|
|
* otherwise it is a waste of cycles.
|
|
*/
|
|
# ifndef CONFIG_DEBUG_KERNEL
|
|
#define INTERRUPT_ENTRY(N) \
|
|
[--sp] = SYSCFG; \
|
|
[--sp] = P0; /*orig_p0*/ \
|
|
[--sp] = R0; /*orig_r0*/ \
|
|
[--sp] = (R7:0,P5:0); \
|
|
R0 = (N); \
|
|
LOAD_IPIPE_IPEND \
|
|
jump __common_int_entry;
|
|
# else /* CONFIG_DEBUG_KERNEL */
|
|
#define INTERRUPT_ENTRY(N) \
|
|
[--sp] = SYSCFG; \
|
|
[--sp] = P0; /*orig_p0*/ \
|
|
[--sp] = R0; /*orig_r0*/ \
|
|
[--sp] = (R7:0,P5:0); \
|
|
p0.l = lo(IPEND); \
|
|
p0.h = hi(IPEND); \
|
|
r1 = [p0]; \
|
|
R0 = (N); \
|
|
LOAD_IPIPE_IPEND \
|
|
jump __common_int_entry;
|
|
# endif /* CONFIG_DEBUG_KERNEL */
|
|
|
|
/* For timer interrupts, we need to save IPEND, since the user_mode
|
|
*macro accesses it to determine where to account time.
|
|
*/
|
|
#define TIMER_INTERRUPT_ENTRY(N) \
|
|
[--sp] = SYSCFG; \
|
|
[--sp] = P0; /*orig_p0*/ \
|
|
[--sp] = R0; /*orig_r0*/ \
|
|
[--sp] = (R7:0,P5:0); \
|
|
p0.l = lo(IPEND); \
|
|
p0.h = hi(IPEND); \
|
|
r1 = [p0]; \
|
|
R0 = (N); \
|
|
jump __common_int_entry;
|
|
#else /* CONFIG_EXACT_HWERR is defined */
|
|
|
|
/* if we want hardware error to be exact, we need to do a SSYNC (which forces
|
|
* read/writes to complete to the memory controllers), and check to see that
|
|
* caused a pending HW error condition. If so, we assume it was caused by user
|
|
* space, by setting the same interrupt that we are in (so it goes off again)
|
|
* and context restore, and a RTI (without servicing anything). This should
|
|
* cause the pending HWERR to fire, and when that is done, this interrupt will
|
|
* be re-serviced properly.
|
|
* As you can see by the code - we actually need to do two SSYNCS - one to
|
|
* make sure the read/writes complete, and another to make sure the hardware
|
|
* error is recognized by the core.
|
|
*
|
|
* The extra nop before the SSYNC is to make sure we work around 05000244,
|
|
* since the 283/315 workaround includes a branch to the end
|
|
*/
|
|
#define INTERRUPT_ENTRY(N) \
|
|
[--sp] = SYSCFG; \
|
|
[--sp] = P0; /*orig_p0*/ \
|
|
[--sp] = R0; /*orig_r0*/ \
|
|
[--sp] = (R7:0,P5:0); \
|
|
R1 = ASTAT; \
|
|
ANOMALY_283_315_WORKAROUND(p0, r0) \
|
|
P0.L = LO(ILAT); \
|
|
P0.H = HI(ILAT); \
|
|
NOP; \
|
|
SSYNC; \
|
|
SSYNC; \
|
|
R0 = [P0]; \
|
|
CC = BITTST(R0, EVT_IVHW_P); \
|
|
IF CC JUMP 1f; \
|
|
ASTAT = R1; \
|
|
p0.l = lo(IPEND); \
|
|
p0.h = hi(IPEND); \
|
|
r1 = [p0]; \
|
|
R0 = (N); \
|
|
LOAD_IPIPE_IPEND \
|
|
jump __common_int_entry; \
|
|
1: ASTAT = R1; \
|
|
RAISE N; \
|
|
(R7:0, P5:0) = [SP++]; \
|
|
SP += 0x8; \
|
|
SYSCFG = [SP++]; \
|
|
CSYNC; \
|
|
RTI;
|
|
|
|
#define TIMER_INTERRUPT_ENTRY(N) \
|
|
[--sp] = SYSCFG; \
|
|
[--sp] = P0; /*orig_p0*/ \
|
|
[--sp] = R0; /*orig_r0*/ \
|
|
[--sp] = (R7:0,P5:0); \
|
|
R1 = ASTAT; \
|
|
ANOMALY_283_315_WORKAROUND(p0, r0) \
|
|
P0.L = LO(ILAT); \
|
|
P0.H = HI(ILAT); \
|
|
NOP; \
|
|
SSYNC; \
|
|
SSYNC; \
|
|
R0 = [P0]; \
|
|
CC = BITTST(R0, EVT_IVHW_P); \
|
|
IF CC JUMP 1f; \
|
|
ASTAT = R1; \
|
|
p0.l = lo(IPEND); \
|
|
p0.h = hi(IPEND); \
|
|
r1 = [p0]; \
|
|
R0 = (N); \
|
|
jump __common_int_entry; \
|
|
1: ASTAT = R1; \
|
|
RAISE N; \
|
|
(R7:0, P5:0) = [SP++]; \
|
|
SP += 0x8; \
|
|
SYSCFG = [SP++]; \
|
|
CSYNC; \
|
|
RTI;
|
|
#endif /* CONFIG_EXACT_HWERR */
|
|
|
|
/* This one pushes RETI without using CLI. Interrupts are enabled. */
|
|
#define SAVE_CONTEXT_SYSCALL save_context_syscall
|
|
#define SAVE_CONTEXT save_context_with_interrupts
|
|
#define SAVE_CONTEXT_CPLB save_context_cplb
|
|
|
|
#define RESTORE_ALL_SYS restore_context_no_interrupts
|
|
#define RESTORE_CONTEXT restore_context_with_interrupts
|
|
#define RESTORE_CONTEXT_CPLB restore_context_cplb
|
|
|
|
#endif /* __ASSEMBLY__ */
|
|
#endif /* __BFIN_ENTRY_H */
|