blackfin: fix copy_from_user()
[linux-2.6-block.git] / arch / blackfin / include / asm / context.S
CommitLineData
1394f032 1/*
96f1050d 2 * Copyright 2007-2009 Analog Devices Inc.
1394f032 3 *
96f1050d 4 * Licensed under the GPL-2 or later.
1394f032
BW
5 */
6
0893f125
BS
7/*
8 * NOTE! The single-stepping code assumes that all interrupt handlers
9 * start by saving SYSCFG on the stack with their first instruction.
10 */
11
1394f032
BW
12/*
13 * Code to save processor context.
14 * We even save the register which are preserved by a function call
15 * - r4, r5, r6, r7, p3, p4, p5
16 */
17.macro save_context_with_interrupts
18 [--sp] = SYSCFG;
19
20 [--sp] = P0; /*orig_p0*/
21 [--sp] = R0; /*orig_r0*/
22
23 [--sp] = ( R7:0, P5:0 );
24 [--sp] = fp;
25 [--sp] = usp;
26
27 [--sp] = i0;
28 [--sp] = i1;
29 [--sp] = i2;
30 [--sp] = i3;
31
32 [--sp] = m0;
33 [--sp] = m1;
34 [--sp] = m2;
35 [--sp] = m3;
36
37 [--sp] = l0;
38 [--sp] = l1;
39 [--sp] = l2;
40 [--sp] = l3;
41
42 [--sp] = b0;
43 [--sp] = b1;
44 [--sp] = b2;
45 [--sp] = b3;
46 [--sp] = a0.x;
47 [--sp] = a0.w;
48 [--sp] = a1.x;
49 [--sp] = a1.w;
50
51 [--sp] = LC0;
52 [--sp] = LC1;
53 [--sp] = LT0;
54 [--sp] = LT1;
55 [--sp] = LB0;
56 [--sp] = LB1;
57
58 [--sp] = ASTAT;
59
60 [--sp] = r0; /* Skip reserved */
61 [--sp] = RETS;
62 r0 = RETI;
63 [--sp] = r0;
64 [--sp] = RETX;
65 [--sp] = RETN;
66 [--sp] = RETE;
67 [--sp] = SEQSTAT;
68 [--sp] = r0; /* Skip IPEND as well. */
69 /* Switch to other method of keeping interrupts disabled. */
70#ifdef CONFIG_DEBUG_HWERR
71 r0 = 0x3f;
72 sti r0;
73#else
74 cli r0;
441504df
YL
75#endif
76#ifdef CONFIG_TRACE_IRQFLAGS
77 sp += -12;
78 call _trace_hardirqs_off;
79 sp += 12;
1394f032
BW
80#endif
81 [--sp] = RETI; /*orig_pc*/
82 /* Clear all L registers. */
83 r0 = 0 (x);
84 l0 = r0;
85 l1 = r0;
86 l2 = r0;
87 l3 = r0;
88.endm
89
90.macro save_context_syscall
91 [--sp] = SYSCFG;
92
93 [--sp] = P0; /*orig_p0*/
94 [--sp] = R0; /*orig_r0*/
95 [--sp] = ( R7:0, P5:0 );
96 [--sp] = fp;
97 [--sp] = usp;
98
99 [--sp] = i0;
100 [--sp] = i1;
101 [--sp] = i2;
102 [--sp] = i3;
103
104 [--sp] = m0;
105 [--sp] = m1;
106 [--sp] = m2;
107 [--sp] = m3;
108
109 [--sp] = l0;
110 [--sp] = l1;
111 [--sp] = l2;
112 [--sp] = l3;
113
114 [--sp] = b0;
115 [--sp] = b1;
116 [--sp] = b2;
117 [--sp] = b3;
118 [--sp] = a0.x;
119 [--sp] = a0.w;
120 [--sp] = a1.x;
121 [--sp] = a1.w;
122
123 [--sp] = LC0;
124 [--sp] = LC1;
125 [--sp] = LT0;
126 [--sp] = LT1;
127 [--sp] = LB0;
128 [--sp] = LB1;
129
130 [--sp] = ASTAT;
131
132 [--sp] = r0; /* Skip reserved */
133 [--sp] = RETS;
134 r0 = RETI;
135 [--sp] = r0;
136 [--sp] = RETX;
137 [--sp] = RETN;
138 [--sp] = RETE;
139 [--sp] = SEQSTAT;
140 [--sp] = r0; /* Skip IPEND as well. */
141 [--sp] = RETI; /*orig_pc*/
142 /* Clear all L registers. */
143 r0 = 0 (x);
144 l0 = r0;
145 l1 = r0;
146 l2 = r0;
147 l3 = r0;
148.endm
149
150.macro save_context_no_interrupts
151 [--sp] = SYSCFG;
152 [--sp] = P0; /* orig_p0 */
153 [--sp] = R0; /* orig_r0 */
154 [--sp] = ( R7:0, P5:0 );
155 [--sp] = fp;
156 [--sp] = usp;
157
158 [--sp] = i0;
159 [--sp] = i1;
160 [--sp] = i2;
161 [--sp] = i3;
162
163 [--sp] = m0;
164 [--sp] = m1;
165 [--sp] = m2;
166 [--sp] = m3;
167
168 [--sp] = l0;
169 [--sp] = l1;
170 [--sp] = l2;
171 [--sp] = l3;
172
173 [--sp] = b0;
174 [--sp] = b1;
175 [--sp] = b2;
176 [--sp] = b3;
177 [--sp] = a0.x;
178 [--sp] = a0.w;
179 [--sp] = a1.x;
180 [--sp] = a1.w;
181
182 [--sp] = LC0;
183 [--sp] = LC1;
184 [--sp] = LT0;
185 [--sp] = LT1;
186 [--sp] = LB0;
187 [--sp] = LB1;
188
189 [--sp] = ASTAT;
190
191#ifdef CONFIG_KGDB
192 fp = 0(Z);
193 r1 = sp;
194 r1 += 60;
195 r1 += 60;
196 r1 += 60;
197 [--sp] = r1;
198#else
199 [--sp] = r0; /* Skip reserved */
200#endif
201 [--sp] = RETS;
202 r0 = RETI;
203 [--sp] = r0;
204 [--sp] = RETX;
205 [--sp] = RETN;
206 [--sp] = RETE;
207 [--sp] = SEQSTAT;
ad863a9d
RG
208#ifdef CONFIG_DEBUG_KERNEL
209 p1.l = lo(IPEND);
210 p1.h = hi(IPEND);
211 r1 = [p1];
1394f032
BW
212 [--sp] = r1;
213#else
214 [--sp] = r0; /* Skip IPEND as well. */
215#endif
216 [--sp] = r0; /*orig_pc*/
217 /* Clear all L registers. */
218 r0 = 0 (x);
219 l0 = r0;
220 l1 = r0;
221 l2 = r0;
222 l3 = r0;
223.endm
224
225.macro restore_context_no_interrupts
226 sp += 4; /* Skip orig_pc */
227 sp += 4; /* Skip IPEND */
228 SEQSTAT = [sp++];
229 RETE = [sp++];
230 RETN = [sp++];
231 RETX = [sp++];
232 r0 = [sp++];
233 RETI = r0; /* Restore RETI indirectly when in exception */
234 RETS = [sp++];
235
236 sp += 4; /* Skip Reserved */
237
238 ASTAT = [sp++];
239
240 LB1 = [sp++];
241 LB0 = [sp++];
242 LT1 = [sp++];
243 LT0 = [sp++];
244 LC1 = [sp++];
245 LC0 = [sp++];
246
247 a1.w = [sp++];
248 a1.x = [sp++];
249 a0.w = [sp++];
250 a0.x = [sp++];
251 b3 = [sp++];
252 b2 = [sp++];
253 b1 = [sp++];
254 b0 = [sp++];
255
256 l3 = [sp++];
257 l2 = [sp++];
258 l1 = [sp++];
259 l0 = [sp++];
260
261 m3 = [sp++];
262 m2 = [sp++];
263 m1 = [sp++];
264 m0 = [sp++];
265
266 i3 = [sp++];
267 i2 = [sp++];
268 i1 = [sp++];
269 i0 = [sp++];
270
271 sp += 4;
272 fp = [sp++];
273
274 ( R7 : 0, P5 : 0) = [ SP ++ ];
275 sp += 8; /* Skip orig_r0/orig_p0 */
276 SYSCFG = [sp++];
277.endm
278
279.macro restore_context_with_interrupts
280 sp += 4; /* Skip orig_pc */
281 sp += 4; /* Skip IPEND */
282 SEQSTAT = [sp++];
283 RETE = [sp++];
284 RETN = [sp++];
285 RETX = [sp++];
286 RETI = [sp++];
441504df
YL
287
288#ifdef CONFIG_TRACE_IRQFLAGS
289 sp += -12;
290 call _trace_hardirqs_on;
291 sp += 12;
292#endif
293
1394f032
BW
294 RETS = [sp++];
295
6b3087c6
GY
296#ifdef CONFIG_SMP
297 GET_PDA(p0, r0);
298 r0 = [p0 + PDA_IRQFLAGS];
299#else
40059784
MF
300 p0.h = _bfin_irq_flags;
301 p0.l = _bfin_irq_flags;
1394f032 302 r0 = [p0];
6b3087c6 303#endif
1394f032
BW
304 sti r0;
305
306 sp += 4; /* Skip Reserved */
307
308 ASTAT = [sp++];
309
310 LB1 = [sp++];
311 LB0 = [sp++];
312 LT1 = [sp++];
313 LT0 = [sp++];
314 LC1 = [sp++];
315 LC0 = [sp++];
316
317 a1.w = [sp++];
318 a1.x = [sp++];
319 a0.w = [sp++];
320 a0.x = [sp++];
321 b3 = [sp++];
322 b2 = [sp++];
323 b1 = [sp++];
324 b0 = [sp++];
325
326 l3 = [sp++];
327 l2 = [sp++];
328 l1 = [sp++];
329 l0 = [sp++];
330
331 m3 = [sp++];
332 m2 = [sp++];
333 m1 = [sp++];
334 m0 = [sp++];
335
336 i3 = [sp++];
337 i2 = [sp++];
338 i1 = [sp++];
339 i0 = [sp++];
340
341 sp += 4;
342 fp = [sp++];
343
344 ( R7 : 0, P5 : 0) = [ SP ++ ];
345 sp += 8; /* Skip orig_r0/orig_p0 */
346 csync;
347 SYSCFG = [sp++];
348 csync;
349.endm
dbdf20db
BS
350
351.macro save_context_cplb
352 [--sp] = (R7:0, P5:0);
353 [--sp] = fp;
354
355 [--sp] = a0.x;
356 [--sp] = a0.w;
357 [--sp] = a1.x;
358 [--sp] = a1.w;
359
360 [--sp] = LC0;
361 [--sp] = LC1;
362 [--sp] = LT0;
363 [--sp] = LT1;
364 [--sp] = LB0;
365 [--sp] = LB1;
366
367 [--sp] = RETS;
368.endm
369
370.macro restore_context_cplb
371 RETS = [sp++];
372
373 LB1 = [sp++];
374 LB0 = [sp++];
375 LT1 = [sp++];
376 LT0 = [sp++];
377 LC1 = [sp++];
378 LC0 = [sp++];
379
380 a1.w = [sp++];
381 a1.x = [sp++];
382 a0.w = [sp++];
383 a0.x = [sp++];
384
385 fp = [sp++];
386
387 (R7:0, P5:0) = [SP++];
388.endm
d86bfb16
BS
389
390.macro pseudo_long_call func:req, scratch:req
391#ifdef CONFIG_ROMKERNEL
392 \scratch\().l = \func;
393 \scratch\().h = \func;
394 call (\scratch);
395#else
396 call \func;
397#endif
398.endm
c7e48e1e
SZ
399
400#if defined(CONFIG_BFIN_SCRATCH_REG_RETN)
401# define EX_SCRATCH_REG RETN
402#elif defined(CONFIG_BFIN_SCRATCH_REG_RETE)
403# define EX_SCRATCH_REG RETE
404#else
405# define EX_SCRATCH_REG CYCLES
406#endif
407