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