ec58efc130e677cb5b688b691715e0d4d0a5761c
[pandora-kernel.git] / arch / blackfin / include / asm / entry.h
1 #ifndef __BFIN_ENTRY_H
2 #define __BFIN_ENTRY_H
3
4 #include <asm/setup.h>
5 #include <asm/page.h>
6
7 #ifdef __ASSEMBLY__
8
9 #define LFLUSH_I_AND_D  0x00000808
10 #define LSIGTRAP        5
11
12 /* process bits for task_struct.flags */
13 #define PF_TRACESYS_OFF 3
14 #define PF_TRACESYS_BIT 5
15 #define PF_PTRACED_OFF  3
16 #define PF_PTRACED_BIT  4
17 #define PF_DTRACE_OFF   1
18 #define PF_DTRACE_BIT   5
19
20 /*
21  * NOTE!  The single-stepping code assumes that all interrupt handlers
22  * start by saving SYSCFG on the stack with their first instruction.
23  */
24
25 /* This one is used for exceptions, emulation, and NMI.  It doesn't push
26    RETI and doesn't do cli.  */
27 #define SAVE_ALL_SYS            save_context_no_interrupts
28 /* This is used for all normal interrupts.  It saves a minimum of registers
29    to the stack, loads the IRQ number, and jumps to common code.  */
30 #ifdef CONFIG_IPIPE
31 # define LOAD_IPIPE_IPEND \
32         P0.l = lo(IPEND); \
33         P0.h = hi(IPEND); \
34         R1 = [P0];
35 #else
36 # define LOAD_IPIPE_IPEND
37 #endif
38
39 #ifndef CONFIG_EXACT_HWERR
40 /* As a debugging aid - we save IPEND when DEBUG_KERNEL is on,
41  * otherwise it is a waste of cycles.
42  */
43 # ifndef CONFIG_DEBUG_KERNEL
44 #define INTERRUPT_ENTRY(N)                                              \
45     [--sp] = SYSCFG;                                                    \
46     [--sp] = P0;        /*orig_p0*/                                     \
47     [--sp] = R0;        /*orig_r0*/                                     \
48     [--sp] = (R7:0,P5:0);                                               \
49     R0 = (N);                                                           \
50     LOAD_IPIPE_IPEND                                                    \
51     jump __common_int_entry;
52 # else /* CONFIG_DEBUG_KERNEL */
53 #define INTERRUPT_ENTRY(N)                                              \
54     [--sp] = SYSCFG;                                                    \
55     [--sp] = P0;        /*orig_p0*/                                     \
56     [--sp] = R0;        /*orig_r0*/                                     \
57     [--sp] = (R7:0,P5:0);                                               \
58     p0.l = lo(IPEND);                                                   \
59     p0.h = hi(IPEND);                                                   \
60     r1 = [p0];                                                          \
61     R0 = (N);                                                           \
62     LOAD_IPIPE_IPEND                                                    \
63     jump __common_int_entry;
64 # endif /* CONFIG_DEBUG_KERNEL */
65
66 /* For timer interrupts, we need to save IPEND, since the user_mode
67  *macro accesses it to determine where to account time.
68  */
69 #define TIMER_INTERRUPT_ENTRY(N)                                        \
70     [--sp] = SYSCFG;                                                    \
71     [--sp] = P0;        /*orig_p0*/                                     \
72     [--sp] = R0;        /*orig_r0*/                                     \
73     [--sp] = (R7:0,P5:0);                                               \
74     p0.l = lo(IPEND);                                                   \
75     p0.h = hi(IPEND);                                                   \
76     r1 = [p0];                                                          \
77     R0 = (N);                                                           \
78     jump __common_int_entry;
79 #else /* CONFIG_EXACT_HWERR is defined */
80
81 /* if we want hardware error to be exact, we need to do a SSYNC (which forces
82  * read/writes to complete to the memory controllers), and check to see that
83  * caused a pending HW error condition. If so, we assume it was caused by user
84  * space, by setting the same interrupt that we are in (so it goes off again)
85  * and context restore, and a RTI (without servicing anything). This should
86  * cause the pending HWERR to fire, and when that is done, this interrupt will
87  * be re-serviced properly.
88  * As you can see by the code - we actually need to do two SSYNCS - one to
89  * make sure the read/writes complete, and another to make sure the hardware
90  * error is recognized by the core.
91  */
92 #define INTERRUPT_ENTRY(N)                                              \
93     SSYNC;                                                              \
94     SSYNC;                                                              \
95     [--sp] = SYSCFG;                                                    \
96     [--sp] = P0;        /*orig_p0*/                                     \
97     [--sp] = R0;        /*orig_r0*/                                     \
98     [--sp] = (R7:0,P5:0);                                               \
99     R1 = ASTAT;                                                         \
100     P0.L = LO(ILAT);                                                    \
101     P0.H = HI(ILAT);                                                    \
102     R0 = [P0];                                                          \
103     CC = BITTST(R0, EVT_IVHW_P);                                        \
104     IF CC JUMP 1f;                                                      \
105     ASTAT = R1;                                                         \
106     p0.l = lo(IPEND);                                                   \
107     p0.h = hi(IPEND);                                                   \
108     r1 = [p0];                                                          \
109     R0 = (N);                                                           \
110     LOAD_IPIPE_IPEND                                                    \
111     jump __common_int_entry;                                            \
112 1:  ASTAT = R1;                                                         \
113     RAISE N;                                                            \
114     (R7:0, P5:0) = [SP++];                                              \
115     SP += 0x8;                                                          \
116     SYSCFG = [SP++];                                                    \
117     CSYNC;                                                              \
118     RTI;
119
120 #define TIMER_INTERRUPT_ENTRY(N)                                        \
121     SSYNC;                                                              \
122     SSYNC;                                                              \
123     [--sp] = SYSCFG;                                                    \
124     [--sp] = P0;        /*orig_p0*/                                     \
125     [--sp] = R0;        /*orig_r0*/                                     \
126     [--sp] = (R7:0,P5:0);                                               \
127     R1 = ASTAT;                                                         \
128     P0.L = LO(ILAT);                                                    \
129     P0.H = HI(ILAT);                                                    \
130     R0 = [P0];                                                          \
131     CC = BITTST(R0, EVT_IVHW_P);                                        \
132     IF CC JUMP 1f;                                                      \
133     ASTAT = R1;                                                         \
134     p0.l = lo(IPEND);                                                   \
135     p0.h = hi(IPEND);                                                   \
136     r1 = [p0];                                                          \
137     R0 = (N);                                                           \
138     jump __common_int_entry;                                            \
139 1:  ASTAT = R1;                                                         \
140     RAISE N;                                                            \
141     (R7:0, P5:0) = [SP++];                                              \
142     SP += 0x8;                                                          \
143     SYSCFG = [SP++];                                                    \
144     CSYNC;                                                              \
145     RTI;
146 #endif  /* CONFIG_EXACT_HWERR */
147
148 /* This one pushes RETI without using CLI.  Interrupts are enabled.  */
149 #define SAVE_CONTEXT_SYSCALL    save_context_syscall
150 #define SAVE_CONTEXT            save_context_with_interrupts
151 #define SAVE_CONTEXT_CPLB       save_context_cplb
152
153 #define RESTORE_ALL_SYS         restore_context_no_interrupts
154 #define RESTORE_CONTEXT         restore_context_with_interrupts
155 #define RESTORE_CONTEXT_CPLB    restore_context_cplb
156
157 #endif                          /* __ASSEMBLY__ */
158 #endif                          /* __BFIN_ENTRY_H */