aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/mach-common/entry.S
diff options
context:
space:
mode:
authorBryan Wu <bryan.wu@analog.com>2007-05-06 17:50:22 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-07 15:12:58 -0400
commit1394f03221790a988afc3e4b3cb79f2e477246a9 (patch)
tree2c1963c9a4f2d84a5e021307fde240c5d567cf70 /arch/blackfin/mach-common/entry.S
parent73243284463a761e04d69d22c7516b2be7de096c (diff)
blackfin architecture
This adds support for the Analog Devices Blackfin processor architecture, and currently supports the BF533, BF532, BF531, BF537, BF536, BF534, and BF561 (Dual Core) devices, with a variety of development platforms including those avaliable from Analog Devices (BF533-EZKit, BF533-STAMP, BF537-STAMP, BF561-EZKIT), and Bluetechnix! Tinyboards. The Blackfin architecture was jointly developed by Intel and Analog Devices Inc. (ADI) as the Micro Signal Architecture (MSA) core and introduced it in December of 2000. Since then ADI has put this core into its Blackfin processor family of devices. The Blackfin core has the advantages of a clean, orthogonal,RISC-like microprocessor instruction set. It combines a dual-MAC (Multiply/Accumulate), state-of-the-art signal processing engine and single-instruction, multiple-data (SIMD) multimedia capabilities into a single instruction-set architecture. The Blackfin architecture, including the instruction set, is described by the ADSP-BF53x/BF56x Blackfin Processor Programming Reference http://blackfin.uclinux.org/gf/download/frsrelease/29/2549/Blackfin_PRM.pdf The Blackfin processor is already supported by major releases of gcc, and there are binary and source rpms/tarballs for many architectures at: http://blackfin.uclinux.org/gf/project/toolchain/frs There is complete documentation, including "getting started" guides available at: http://docs.blackfin.uclinux.org/ which provides links to the sources and patches you will need in order to set up a cross-compiling environment for bfin-linux-uclibc This patch, as well as the other patches (toolchain, distribution, uClibc) are actively supported by Analog Devices Inc, at: http://blackfin.uclinux.org/ We have tested this on LTP, and our test plan (including pass/fails) can be found at: http://docs.blackfin.uclinux.org/doku.php?id=testing_the_linux_kernel [m.kozlowski@tuxland.pl: balance parenthesis in blackfin header files] Signed-off-by: Bryan Wu <bryan.wu@analog.com> Signed-off-by: Mariusz Kozlowski <m.kozlowski@tuxland.pl> Signed-off-by: Aubrey Li <aubrey.li@analog.com> Signed-off-by: Jie Zhang <jie.zhang@analog.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/blackfin/mach-common/entry.S')
-rw-r--r--arch/blackfin/mach-common/entry.S1207
1 files changed, 1207 insertions, 0 deletions
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
new file mode 100644
index 000000000000..8eb0a9023482
--- /dev/null
+++ b/arch/blackfin/mach-common/entry.S
@@ -0,0 +1,1207 @@
1/*
2 * File: arch/blackfin/mach-common/entry.S
3 * Based on:
4 * Author: Linus Torvalds
5 *
6 * Created: ?
7 * Description: contains the system-call and fault low-level handling routines.
8 * This also contains the timer-interrupt handler, as well as all
9 * interrupts and faults that can result in a task-switch.
10 *
11 * Modified:
12 * Copyright 2004-2006 Analog Devices Inc.
13 *
14 * Bugs: Enter bugs at http://blackfin.uclinux.org/
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, see the file COPYING, or write
28 * to the Free Software Foundation, Inc.,
29 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 */
31
32/*
33 * 25-Dec-2004 - LG Soft India
34 * 1. Fix in return_from_int, to make sure any pending
35 * system call in ILAT for this process to get
36 * executed, otherwise in case context switch happens,
37 * system call of first process (i.e in ILAT) will be
38 * carried forward to the switched process.
39 * 2. Removed Constant references for the following
40 * a. IPEND
41 * b. EXCAUSE mask
42 * c. PAGE Mask
43 */
44
45/*
46 * NOTE: This code handles signal-recognition, which happens every time
47 * after a timer-interrupt and after each system call.
48 */
49
50
51#include <linux/linkage.h>
52#include <asm/blackfin.h>
53#include <asm/unistd.h>
54#include <asm/errno.h>
55#include <asm/thread_info.h> /* TIF_NEED_RESCHED */
56#include <asm/asm-offsets.h>
57
58#include <asm/mach-common/context.S>
59
60#ifdef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE
61 /*
62 * TODO: this should be proper save/restore, but for now
63 * we'll just cheat and use 0x1/0x13
64 */
65# define DEBUG_START_HWTRACE \
66 P5.l = LO(TBUFCTL); \
67 P5.h = HI(TBUFCTL); \
68 R7 = 0x13; \
69 [P5] = R7;
70# define DEBUG_STOP_HWTRACE \
71 P5.l = LO(TBUFCTL); \
72 P5.h = HI(TBUFCTL); \
73 R7 = 0x01; \
74 [P5] = R7;
75#else
76# define DEBUG_START_HWTRACE
77# define DEBUG_STOP_HWTRACE
78#endif
79
80#ifdef CONFIG_EXCPT_IRQ_SYSC_L1
81.section .l1.text
82#else
83.text
84#endif
85
86/* Slightly simplified and streamlined entry point for CPLB misses.
87 * This one does not lower the level to IRQ5, and thus can be used to
88 * patch up CPLB misses on the kernel stack.
89 */
90ENTRY(_ex_dcplb)
91#if defined(ANOMALY_05000261)
92 /*
93 * Work around an anomaly: if we see a new DCPLB fault, return
94 * without doing anything. Then, if we get the same fault again,
95 * handle it.
96 */
97 p5.l = _last_cplb_fault_retx;
98 p5.h = _last_cplb_fault_retx;
99 r7 = [p5];
100 r6 = retx;
101 [p5] = r6;
102 cc = r6 == r7;
103 if !cc jump _return_from_exception;
104 /* fall through */
105#endif
106
107ENTRY(_ex_icplb)
108 (R7:6,P5:4) = [sp++];
109 ASTAT = [sp++];
110 SAVE_ALL_SYS
111 call __cplb_hdr;
112 DEBUG_START_HWTRACE
113 RESTORE_ALL_SYS
114 SP = RETN;
115 rtx;
116
117ENTRY(_ex_spinlock)
118 /* Transform this into a syscall - twiddle the syscall vector. */
119 p5.l = lo(EVT15);
120 p5.h = hi(EVT15);
121 r7.l = _spinlock_bh;
122 r7.h = _spinlock_bh;
123 [p5] = r7;
124 csync;
125 /* Fall through. */
126
127ENTRY(_ex_syscall)
128 DEBUG_START_HWTRACE
129 (R7:6,P5:4) = [sp++];
130 ASTAT = [sp++];
131 raise 15; /* invoked by TRAP #0, for sys call */
132 sp = retn;
133 rtx
134
135ENTRY(_spinlock_bh)
136 SAVE_ALL_SYS
137 /* To end up here, vector 15 was changed - so we have to change it
138 * back.
139 */
140 p0.l = lo(EVT15);
141 p0.h = hi(EVT15);
142 p1.l = _evt_system_call;
143 p1.h = _evt_system_call;
144 [p0] = p1;
145 csync;
146 r0 = [sp + PT_R0];
147 sp += -12;
148 call _sys_bfin_spinlock;
149 sp += 12;
150 [SP + PT_R0] = R0;
151 RESTORE_ALL_SYS
152 rti;
153
154ENTRY(_ex_soft_bp)
155 r7 = retx;
156 r7 += -2;
157 retx = r7;
158 jump.s _ex_trap_c;
159
160ENTRY(_ex_single_step)
161 r7 = retx;
162 r6 = reti;
163 cc = r7 == r6;
164 if cc jump _return_from_exception
165 r7 = syscfg;
166 bitclr (r7, 0);
167 syscfg = R7;
168
169 p5.l = lo(IPEND);
170 p5.h = hi(IPEND);
171 r6 = [p5];
172 cc = bittst(r6, 5);
173 if !cc jump _ex_trap_c;
174 p4.l = lo(EVT5);
175 p4.h = hi(EVT5);
176 r6.h = _exception_to_level5;
177 r6.l = _exception_to_level5;
178 r7 = [p4];
179 cc = r6 == r7;
180 if !cc jump _ex_trap_c;
181
182_return_from_exception:
183 DEBUG_START_HWTRACE
184 (R7:6,P5:4) = [sp++];
185 ASTAT = [sp++];
186 sp = retn;
187 rtx;
188
189ENTRY(_handle_bad_cplb)
190 /* To get here, we just tried and failed to change a CPLB
191 * so, handle things in trap_c (C code), by lowering to
192 * IRQ5, just like we normally do. Since this is not a
193 * "normal" return path, we have a do alot of stuff to
194 * the stack to get ready so, we can fall through - we
195 * need to make a CPLB exception look like a normal exception
196 */
197
198 DEBUG_START_HWTRACE
199 RESTORE_ALL_SYS
200 [--sp] = ASTAT;
201 [--sp] = (R7:6, P5:4);
202
203ENTRY(_ex_trap_c)
204 /* Call C code (trap_c) to handle the exception, which most
205 * likely involves sending a signal to the current process.
206 * To avoid double faults, lower our priority to IRQ5 first.
207 */
208 P5.h = _exception_to_level5;
209 P5.l = _exception_to_level5;
210 p4.l = lo(EVT5);
211 p4.h = hi(EVT5);
212 [p4] = p5;
213 csync;
214
215 /* Disable all interrupts, but make sure level 5 is enabled so
216 * we can switch to that level. Save the old mask. */
217 cli r6;
218 p4.l = _excpt_saved_imask;
219 p4.h = _excpt_saved_imask;
220 [p4] = r6;
221 r6 = 0x3f;
222 sti r6;
223
224 /* Save the excause into a circular buffer, in case the instruction
225 * which caused this excecptions causes others.
226 */
227 P5.l = _in_ptr_excause;
228 P5.h = _in_ptr_excause;
229 R7 = [P5];
230 R7 += 4;
231 R6 = 0xF;
232 R7 = R7 & R6;
233 [P5] = R7;
234 R6.l = _excause_circ_buf;
235 R6.h = _excause_circ_buf;
236 R7 = R7 + R6;
237 p5 = R7;
238 R6 = SEQSTAT;
239 [P5] = R6;
240
241 DEBUG_START_HWTRACE
242 (R7:6,P5:4) = [sp++];
243 ASTAT = [sp++];
244 SP = RETN;
245 raise 5;
246 rtx;
247
248ENTRY(_exception_to_level5)
249 SAVE_ALL_SYS
250
251 /* Restore interrupt mask. We haven't pushed RETI, so this
252 * doesn't enable interrupts until we return from this handler. */
253 p4.l = _excpt_saved_imask;
254 p4.h = _excpt_saved_imask;
255 r6 = [p4];
256 sti r6;
257
258 /* Restore the hardware error vector. */
259 P5.h = _evt_ivhw;
260 P5.l = _evt_ivhw;
261 p4.l = lo(EVT5);
262 p4.h = hi(EVT5);
263 [p4] = p5;
264 csync;
265
266 p2.l = lo(IPEND);
267 p2.h = hi(IPEND);
268 csync;
269 r0 = [p2]; /* Read current IPEND */
270 [sp + PT_IPEND] = r0; /* Store IPEND */
271
272 /* Pop the excause from the circular buffer and push it on the stack
273 * (in the right place - if you change the location of SEQSTAT, you
274 * must change this offset.
275 */
276.L_excep_to_5_again:
277 P5.l = _out_ptr_excause;
278 P5.h = _out_ptr_excause;
279 R7 = [P5];
280 R7 += 4;
281 R6 = 0xF;
282 R7 = R7 & R6;
283 [P5] = R7;
284 R6.l = _excause_circ_buf;
285 R6.h = _excause_circ_buf;
286 R7 = R7 + R6;
287 P5 = R7;
288 R1 = [P5];
289 [SP + 8] = r1;
290
291 r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */
292 SP += -12;
293 call _trap_c;
294 SP += 12;
295
296 /* See if anything else is in the exception buffer
297 * if there is, process it
298 */
299 P5.l = _out_ptr_excause;
300 P5.h = _out_ptr_excause;
301 P4.l = _in_ptr_excause;
302 P4.h = _in_ptr_excause;
303 R6 = [P5];
304 R7 = [P4];
305 CC = R6 == R7;
306 if ! CC JUMP .L_excep_to_5_again
307
308 call _ret_from_exception;
309 RESTORE_ALL_SYS
310 rti;
311
312ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/
313 /* Since the kernel stack can be anywhere, it's not guaranteed to be
314 * covered by a CPLB. Switch to an exception stack; use RETN as a
315 * scratch register (for want of a better option).
316 */
317 retn = sp;
318 sp.l = _exception_stack_top;
319 sp.h = _exception_stack_top;
320 /* Try to deal with syscalls quickly. */
321 [--sp] = ASTAT;
322 [--sp] = (R7:6, P5:4);
323 DEBUG_STOP_HWTRACE
324 r7 = SEQSTAT; /* reason code is in bit 5:0 */
325 r6.l = lo(SEQSTAT_EXCAUSE);
326 r6.h = hi(SEQSTAT_EXCAUSE);
327 r7 = r7 & r6;
328 p5.h = _extable;
329 p5.l = _extable;
330 p4 = r7;
331 p5 = p5 + (p4 << 2);
332 p4 = [p5];
333 jump (p4);
334
335.Lbadsys:
336 r7 = -ENOSYS; /* signextending enough */
337 [sp + PT_R0] = r7; /* return value from system call */
338 jump .Lsyscall_really_exit;
339
340ENTRY(_kernel_execve)
341 link SIZEOF_PTREGS;
342 p0 = sp;
343 r3 = SIZEOF_PTREGS / 4;
344 r4 = 0(x);
3450:
346 [p0++] = r4;
347 r3 += -1;
348 cc = r3 == 0;
349 if !cc jump 0b (bp);
350
351 p0 = sp;
352 sp += -16;
353 [sp + 12] = p0;
354 call _do_execve;
355 SP += 16;
356 cc = r0 == 0;
357 if ! cc jump 1f;
358 /* Success. Copy our temporary pt_regs to the top of the kernel
359 * stack and do a normal exception return.
360 */
361 r1 = sp;
362 r0 = (-KERNEL_STACK_SIZE) (x);
363 r1 = r1 & r0;
364 p2 = r1;
365 p3 = [p2];
366 r0 = KERNEL_STACK_SIZE - 4 (z);
367 p1 = r0;
368 p1 = p1 + p2;
369
370 p0 = fp;
371 r4 = [p0--];
372 r3 = SIZEOF_PTREGS / 4;
3730:
374 r4 = [p0--];
375 [p1--] = r4;
376 r3 += -1;
377 cc = r3 == 0;
378 if ! cc jump 0b (bp);
379
380 r0 = (KERNEL_STACK_SIZE - SIZEOF_PTREGS) (z);
381 p1 = r0;
382 p1 = p1 + p2;
383 sp = p1;
384 r0 = syscfg;
385 [SP + PT_SYSCFG] = r0;
386 [p3 + (TASK_THREAD + THREAD_KSP)] = sp;
387
388 RESTORE_CONTEXT;
389 rti;
3901:
391 unlink;
392 rts;
393
394ENTRY(_system_call)
395 /* Store IPEND */
396 p2.l = lo(IPEND);
397 p2.h = hi(IPEND);
398 csync;
399 r0 = [p2];
400 [sp + PT_IPEND] = r0;
401
402 /* Store RETS for now */
403 r0 = rets;
404 [sp + PT_RESERVED] = r0;
405 /* Set the stack for the current process */
406 r7 = sp;
407 r6.l = lo(ALIGN_PAGE_MASK);
408 r6.h = hi(ALIGN_PAGE_MASK);
409 r7 = r7 & r6; /* thread_info */
410 p2 = r7;
411 p2 = [p2];
412
413 [p2+(TASK_THREAD+THREAD_KSP)] = sp;
414
415 /* Check the System Call */
416 r7 = __NR_syscall;
417 /* System call number is passed in P0 */
418 r6 = p0;
419 cc = r6 < r7;
420 if ! cc jump .Lbadsys;
421
422 /* are we tracing syscalls?*/
423 r7 = sp;
424 r6.l = lo(ALIGN_PAGE_MASK);
425 r6.h = hi(ALIGN_PAGE_MASK);
426 r7 = r7 & r6;
427 p2 = r7;
428 r7 = [p2+TI_FLAGS];
429 CC = BITTST(r7,TIF_SYSCALL_TRACE);
430 if CC JUMP _sys_trace;
431
432 /* Execute the appropriate system call */
433
434 p4 = p0;
435 p5.l = _sys_call_table;
436 p5.h = _sys_call_table;
437 p5 = p5 + (p4 << 2);
438 r0 = [sp + PT_R0];
439 r1 = [sp + PT_R1];
440 r2 = [sp + PT_R2];
441 p5 = [p5];
442
443 [--sp] = r5;
444 [--sp] = r4;
445 [--sp] = r3;
446 SP += -12;
447 call (p5);
448 SP += 24;
449 [sp + PT_R0] = r0;
450
451.Lresume_userspace:
452 r7 = sp;
453 r4.l = lo(ALIGN_PAGE_MASK);
454 r4.h = hi(ALIGN_PAGE_MASK);
455 r7 = r7 & r4; /* thread_info->flags */
456 p5 = r7;
457.Lresume_userspace_1:
458 /* Disable interrupts. */
459 [--sp] = reti;
460 reti = [sp++];
461
462 r7 = [p5 + TI_FLAGS];
463 r4.l = lo(_TIF_WORK_MASK);
464 r4.h = hi(_TIF_WORK_MASK);
465 r7 = r7 & r4;
466
467.Lsyscall_resched:
468 cc = BITTST(r7, TIF_NEED_RESCHED);
469 if !cc jump .Lsyscall_sigpending;
470
471 /* Reenable interrupts. */
472 [--sp] = reti;
473 r0 = [sp++];
474
475 SP += -12;
476 call _schedule;
477 SP += 12;
478
479 jump .Lresume_userspace_1;
480
481.Lsyscall_sigpending:
482 cc = BITTST(r7, TIF_RESTORE_SIGMASK);
483 if cc jump .Lsyscall_do_signals;
484 cc = BITTST(r7, TIF_SIGPENDING);
485 if !cc jump .Lsyscall_really_exit;
486.Lsyscall_do_signals:
487 /* Reenable interrupts. */
488 [--sp] = reti;
489 r0 = [sp++];
490
491 r0 = sp;
492 SP += -12;
493 call _do_signal;
494 SP += 12;
495
496.Lsyscall_really_exit:
497 r5 = [sp + PT_RESERVED];
498 rets = r5;
499 rts;
500
501_sys_trace:
502 call _syscall_trace;
503
504 /* Execute the appropriate system call */
505
506 p4 = [SP + PT_P0];
507 p5.l = _sys_call_table;
508 p5.h = _sys_call_table;
509 p5 = p5 + (p4 << 2);
510 r0 = [sp + PT_R0];
511 r1 = [sp + PT_R1];
512 r2 = [sp + PT_R2];
513 r3 = [sp + PT_R3];
514 r4 = [sp + PT_R4];
515 r5 = [sp + PT_R5];
516 p5 = [p5];
517
518 [--sp] = r5;
519 [--sp] = r4;
520 [--sp] = r3;
521 SP += -12;
522 call (p5);
523 SP += 24;
524 [sp + PT_R0] = r0;
525
526 call _syscall_trace;
527 jump .Lresume_userspace;
528
529ENTRY(_resume)
530 /*
531 * Beware - when entering resume, prev (the current task) is
532 * in r0, next (the new task) is in r1.
533 */
534 p0 = r0;
535 p1 = r1;
536 [--sp] = rets;
537 [--sp] = fp;
538 [--sp] = (r7:4, p5:3);
539
540 /* save usp */
541 p2 = usp;
542 [p0+(TASK_THREAD+THREAD_USP)] = p2;
543
544 /* save current kernel stack pointer */
545 [p0+(TASK_THREAD+THREAD_KSP)] = sp;
546
547 /* save program counter */
548 r1.l = _new_old_task;
549 r1.h = _new_old_task;
550 [p0+(TASK_THREAD+THREAD_PC)] = r1;
551
552 /* restore the kernel stack pointer */
553 sp = [p1+(TASK_THREAD+THREAD_KSP)];
554
555 /* restore user stack pointer */
556 p0 = [p1+(TASK_THREAD+THREAD_USP)];
557 usp = p0;
558
559 /* restore pc */
560 p0 = [p1+(TASK_THREAD+THREAD_PC)];
561 jump (p0);
562
563 /*
564 * Following code actually lands up in a new (old) task.
565 */
566
567_new_old_task:
568 (r7:4, p5:3) = [sp++];
569 fp = [sp++];
570 rets = [sp++];
571
572 /*
573 * When we come out of resume, r0 carries "old" task, becuase we are
574 * in "new" task.
575 */
576 rts;
577
578ENTRY(_ret_from_exception)
579 p2.l = lo(IPEND);
580 p2.h = hi(IPEND);
581
582 csync;
583 r0 = [p2];
584 [sp + PT_IPEND] = r0;
585
5861:
587 r1 = 0x37(Z);
588 r2 = ~r1;
589 r2.h = 0;
590 r0 = r2 & r0;
591 cc = r0 == 0;
592 if !cc jump 4f; /* if not return to user mode, get out */
593
594 /* Make sure any pending system call or deferred exception
595 * return in ILAT for this process to get executed, otherwise
596 * in case context switch happens, system call of
597 * first process (i.e in ILAT) will be carried
598 * forward to the switched process
599 */
600
601 p2.l = lo(ILAT);
602 p2.h = hi(ILAT);
603 r0 = [p2];
604 r1 = (EVT_IVG14 | EVT_IVG15) (z);
605 r0 = r0 & r1;
606 cc = r0 == 0;
607 if !cc jump 5f;
608
609 /* Set the stack for the current process */
610 r7 = sp;
611 r4.l = lo(ALIGN_PAGE_MASK);
612 r4.h = hi(ALIGN_PAGE_MASK);
613 r7 = r7 & r4; /* thread_info->flags */
614 p5 = r7;
615 r7 = [p5 + TI_FLAGS];
616 r4.l = lo(_TIF_WORK_MASK);
617 r4.h = hi(_TIF_WORK_MASK);
618 r7 = r7 & r4;
619 cc = r7 == 0;
620 if cc jump 4f;
621
622 p0.l = lo(EVT15);
623 p0.h = hi(EVT15);
624 p1.l = _schedule_and_signal;
625 p1.h = _schedule_and_signal;
626 [p0] = p1;
627 csync;
628 raise 15; /* raise evt14 to do signal or reschedule */
6294:
630 r0 = syscfg;
631 bitclr(r0, 0);
632 syscfg = r0;
6335:
634 rts;
635
636ENTRY(_return_from_int)
637 /* If someone else already raised IRQ 15, do nothing. */
638 csync;
639 p2.l = lo(ILAT);
640 p2.h = hi(ILAT);
641 r0 = [p2];
642 cc = bittst (r0, EVT_IVG15_P);
643 if cc jump 2f;
644
645 /* if not return to user mode, get out */
646 p2.l = lo(IPEND);
647 p2.h = hi(IPEND);
648 r0 = [p2];
649 r1 = 0x17(Z);
650 r2 = ~r1;
651 r2.h = 0;
652 r0 = r2 & r0;
653 r1 = 1;
654 r1 = r0 - r1;
655 r2 = r0 & r1;
656 cc = r2 == 0;
657 if !cc jump 2f;
658
659 /* Lower the interrupt level to 15. */
660 p0.l = lo(EVT15);
661 p0.h = hi(EVT15);
662 p1.l = _schedule_and_signal_from_int;
663 p1.h = _schedule_and_signal_from_int;
664 [p0] = p1;
665 csync;
666#if defined(ANOMALY_05000281)
667 r0.l = lo(CONFIG_BOOT_LOAD);
668 r0.h = hi(CONFIG_BOOT_LOAD);
669 reti = r0;
670#endif
671 r0 = 0x801f (z);
672 STI r0;
673 raise 15; /* raise evt15 to do signal or reschedule */
674 rti;
6752:
676 rts;
677
678ENTRY(_lower_to_irq14)
679#if defined(ANOMALY_05000281)
680 r0.l = lo(CONFIG_BOOT_LOAD);
681 r0.h = hi(CONFIG_BOOT_LOAD);
682 reti = r0;
683#endif
684 r0 = 0x401f;
685 sti r0;
686 raise 14;
687 rti;
688ENTRY(_evt14_softirq)
689#ifdef CONFIG_DEBUG_HWERR
690 r0 = 0x3f;
691 sti r0;
692#else
693 cli r0;
694#endif
695 [--sp] = RETI;
696 SP += 4;
697 rts;
698
699_schedule_and_signal_from_int:
700 /* To end up here, vector 15 was changed - so we have to change it
701 * back.
702 */
703 p0.l = lo(EVT15);
704 p0.h = hi(EVT15);
705 p1.l = _evt_system_call;
706 p1.h = _evt_system_call;
707 [p0] = p1;
708 csync;
709 p1 = rets;
710 [sp + PT_RESERVED] = p1;
711
712 p0.l = _irq_flags;
713 p0.h = _irq_flags;
714 r0 = [p0];
715 sti r0;
716
717 jump.s .Lresume_userspace;
718
719_schedule_and_signal:
720 SAVE_CONTEXT_SYSCALL
721 /* To end up here, vector 15 was changed - so we have to change it
722 * back.
723 */
724 p0.l = lo(EVT15);
725 p0.h = hi(EVT15);
726 p1.l = _evt_system_call;
727 p1.h = _evt_system_call;
728 [p0] = p1;
729 csync;
730 p0.l = 1f;
731 p0.h = 1f;
732 [sp + PT_RESERVED] = P0;
733 call .Lresume_userspace;
7341:
735 RESTORE_CONTEXT
736 rti;
737
738/* Make sure when we start, that the circular buffer is initialized properly
739 * R0 and P0 are call clobbered, so we can use them here.
740 */
741ENTRY(_init_exception_buff)
742 r0 = 0;
743 p0.h = _in_ptr_excause;
744 p0.l = _in_ptr_excause;
745 [p0] = r0;
746 p0.h = _out_ptr_excause;
747 p0.l = _out_ptr_excause;
748 [p0] = r0;
749 rts;
750
751/*
752 * Put these in the kernel data section - that should always be covered by
753 * a CPLB. This is needed to ensure we don't get double fault conditions
754 */
755
756#ifdef CONFIG_SYSCALL_TAB_L1
757.section .l1.data
758#else
759.data
760#endif
761ALIGN
762_extable:
763 /* entry for each EXCAUSE[5:0]
764 * This table bmust be in sync with the table in ./kernel/traps.c
765 * EXCPT instruction can provide 4 bits of EXCAUSE, allowing 16 to be user defined
766 */
767 .long _ex_syscall; /* 0x00 - User Defined - Linux Syscall */
768 .long _ex_soft_bp /* 0x01 - User Defined - Software breakpoint */
769 .long _ex_trap_c /* 0x02 - User Defined */
770 .long _ex_trap_c /* 0x03 - User Defined - Atomic test and set service */
771 .long _ex_spinlock /* 0x04 - User Defined */
772 .long _ex_trap_c /* 0x05 - User Defined */
773 .long _ex_trap_c /* 0x06 - User Defined */
774 .long _ex_trap_c /* 0x07 - User Defined */
775 .long _ex_trap_c /* 0x08 - User Defined */
776 .long _ex_trap_c /* 0x09 - User Defined */
777 .long _ex_trap_c /* 0x0A - User Defined */
778 .long _ex_trap_c /* 0x0B - User Defined */
779 .long _ex_trap_c /* 0x0C - User Defined */
780 .long _ex_trap_c /* 0x0D - User Defined */
781 .long _ex_trap_c /* 0x0E - User Defined */
782 .long _ex_trap_c /* 0x0F - User Defined */
783 .long _ex_single_step /* 0x10 - HW Single step */
784 .long _ex_trap_c /* 0x11 - Trace Buffer Full */
785 .long _ex_trap_c /* 0x12 - Reserved */
786 .long _ex_trap_c /* 0x13 - Reserved */
787 .long _ex_trap_c /* 0x14 - Reserved */
788 .long _ex_trap_c /* 0x15 - Reserved */
789 .long _ex_trap_c /* 0x16 - Reserved */
790 .long _ex_trap_c /* 0x17 - Reserved */
791 .long _ex_trap_c /* 0x18 - Reserved */
792 .long _ex_trap_c /* 0x19 - Reserved */
793 .long _ex_trap_c /* 0x1A - Reserved */
794 .long _ex_trap_c /* 0x1B - Reserved */
795 .long _ex_trap_c /* 0x1C - Reserved */
796 .long _ex_trap_c /* 0x1D - Reserved */
797 .long _ex_trap_c /* 0x1E - Reserved */
798 .long _ex_trap_c /* 0x1F - Reserved */
799 .long _ex_trap_c /* 0x20 - Reserved */
800 .long _ex_trap_c /* 0x21 - Undefined Instruction */
801 .long _ex_trap_c /* 0x22 - Illegal Instruction Combination */
802 .long _ex_dcplb /* 0x23 - Data CPLB Protection Violation */
803 .long _ex_trap_c /* 0x24 - Data access misaligned */
804 .long _ex_trap_c /* 0x25 - Unrecoverable Event */
805 .long _ex_dcplb /* 0x26 - Data CPLB Miss */
806 .long _ex_trap_c /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero */
807 .long _ex_trap_c /* 0x28 - Emulation Watchpoint */
808 .long _ex_trap_c /* 0x29 - Instruction fetch access error (535 only) */
809 .long _ex_trap_c /* 0x2A - Instruction fetch misaligned */
810 .long _ex_icplb /* 0x2B - Instruction CPLB protection Violation */
811 .long _ex_icplb /* 0x2C - Instruction CPLB miss */
812 .long _ex_trap_c /* 0x2D - Instruction CPLB Multiple Hits */
813 .long _ex_trap_c /* 0x2E - Illegal use of Supervisor Resource */
814 .long _ex_trap_c /* 0x2E - Illegal use of Supervisor Resource */
815 .long _ex_trap_c /* 0x2F - Reserved */
816 .long _ex_trap_c /* 0x30 - Reserved */
817 .long _ex_trap_c /* 0x31 - Reserved */
818 .long _ex_trap_c /* 0x32 - Reserved */
819 .long _ex_trap_c /* 0x33 - Reserved */
820 .long _ex_trap_c /* 0x34 - Reserved */
821 .long _ex_trap_c /* 0x35 - Reserved */
822 .long _ex_trap_c /* 0x36 - Reserved */
823 .long _ex_trap_c /* 0x37 - Reserved */
824 .long _ex_trap_c /* 0x38 - Reserved */
825 .long _ex_trap_c /* 0x39 - Reserved */
826 .long _ex_trap_c /* 0x3A - Reserved */
827 .long _ex_trap_c /* 0x3B - Reserved */
828 .long _ex_trap_c /* 0x3C - Reserved */
829 .long _ex_trap_c /* 0x3D - Reserved */
830 .long _ex_trap_c /* 0x3E - Reserved */
831 .long _ex_trap_c /* 0x3F - Reserved */
832
833ALIGN
834ENTRY(_sys_call_table)
835 .long _sys_ni_syscall /* 0 - old "setup()" system call*/
836 .long _sys_exit
837 .long _sys_fork
838 .long _sys_read
839 .long _sys_write
840 .long _sys_open /* 5 */
841 .long _sys_close
842 .long _sys_ni_syscall /* old waitpid */
843 .long _sys_creat
844 .long _sys_link
845 .long _sys_unlink /* 10 */
846 .long _sys_execve
847 .long _sys_chdir
848 .long _sys_time
849 .long _sys_mknod
850 .long _sys_chmod /* 15 */
851 .long _sys_chown /* chown16 */
852 .long _sys_ni_syscall /* old break syscall holder */
853 .long _sys_ni_syscall /* old stat */
854 .long _sys_lseek
855 .long _sys_getpid /* 20 */
856 .long _sys_mount
857 .long _sys_ni_syscall /* old umount */
858 .long _sys_setuid
859 .long _sys_getuid
860 .long _sys_stime /* 25 */
861 .long _sys_ptrace
862 .long _sys_alarm
863 .long _sys_ni_syscall /* old fstat */
864 .long _sys_pause
865 .long _sys_ni_syscall /* old utime */ /* 30 */
866 .long _sys_ni_syscall /* old stty syscall holder */
867 .long _sys_ni_syscall /* old gtty syscall holder */
868 .long _sys_access
869 .long _sys_nice
870 .long _sys_ni_syscall /* 35 */ /* old ftime syscall holder */
871 .long _sys_sync
872 .long _sys_kill
873 .long _sys_rename
874 .long _sys_mkdir
875 .long _sys_rmdir /* 40 */
876 .long _sys_dup
877 .long _sys_pipe
878 .long _sys_times
879 .long _sys_ni_syscall /* old prof syscall holder */
880 .long _sys_brk /* 45 */
881 .long _sys_setgid
882 .long _sys_getgid
883 .long _sys_ni_syscall /* old sys_signal */
884 .long _sys_geteuid /* geteuid16 */
885 .long _sys_getegid /* getegid16 */ /* 50 */
886 .long _sys_acct
887 .long _sys_umount /* recycled never used phys() */
888 .long _sys_ni_syscall /* old lock syscall holder */
889 .long _sys_ioctl
890 .long _sys_fcntl /* 55 */
891 .long _sys_ni_syscall /* old mpx syscall holder */
892 .long _sys_setpgid
893 .long _sys_ni_syscall /* old ulimit syscall holder */
894 .long _sys_ni_syscall /* old old uname */
895 .long _sys_umask /* 60 */
896 .long _sys_chroot
897 .long _sys_ustat
898 .long _sys_dup2
899 .long _sys_getppid
900 .long _sys_getpgrp /* 65 */
901 .long _sys_setsid
902 .long _sys_ni_syscall /* old sys_sigaction */
903 .long _sys_sgetmask
904 .long _sys_ssetmask
905 .long _sys_setreuid /* setreuid16 */ /* 70 */
906 .long _sys_setregid /* setregid16 */
907 .long _sys_ni_syscall /* old sys_sigsuspend */
908 .long _sys_ni_syscall /* old sys_sigpending */
909 .long _sys_sethostname
910 .long _sys_setrlimit /* 75 */
911 .long _sys_ni_syscall /* old getrlimit */
912 .long _sys_getrusage
913 .long _sys_gettimeofday
914 .long _sys_settimeofday
915 .long _sys_getgroups /* getgroups16 */ /* 80 */
916 .long _sys_setgroups /* setgroups16 */
917 .long _sys_ni_syscall /* old_select */
918 .long _sys_symlink
919 .long _sys_ni_syscall /* old lstat */
920 .long _sys_readlink /* 85 */
921 .long _sys_uselib
922 .long _sys_ni_syscall /* sys_swapon */
923 .long _sys_reboot
924 .long _sys_ni_syscall /* old_readdir */
925 .long _sys_ni_syscall /* sys_mmap */ /* 90 */
926 .long _sys_munmap
927 .long _sys_truncate
928 .long _sys_ftruncate
929 .long _sys_fchmod
930 .long _sys_fchown /* fchown16 */ /* 95 */
931 .long _sys_getpriority
932 .long _sys_setpriority
933 .long _sys_ni_syscall /* old profil syscall holder */
934 .long _sys_statfs
935 .long _sys_fstatfs /* 100 */
936 .long _sys_ni_syscall
937 .long _sys_ni_syscall /* old sys_socketcall */
938 .long _sys_syslog
939 .long _sys_setitimer
940 .long _sys_getitimer /* 105 */
941 .long _sys_newstat
942 .long _sys_newlstat
943 .long _sys_newfstat
944 .long _sys_ni_syscall /* old uname */
945 .long _sys_ni_syscall /* iopl for i386 */ /* 110 */
946 .long _sys_vhangup
947 .long _sys_ni_syscall /* obsolete idle() syscall */
948 .long _sys_ni_syscall /* vm86old for i386 */
949 .long _sys_wait4
950 .long _sys_ni_syscall /* 115 */ /* sys_swapoff */
951 .long _sys_sysinfo
952 .long _sys_ni_syscall /* old sys_ipc */
953 .long _sys_fsync
954 .long _sys_ni_syscall /* old sys_sigreturn */
955 .long _sys_clone /* 120 */
956 .long _sys_setdomainname
957 .long _sys_newuname
958 .long _sys_ni_syscall /* old sys_modify_ldt */
959 .long _sys_adjtimex
960 .long _sys_ni_syscall /* 125 */ /* sys_mprotect */
961 .long _sys_ni_syscall /* old sys_sigprocmask */
962 .long _sys_ni_syscall /* old "creat_module" */
963 .long _sys_init_module
964 .long _sys_delete_module
965 .long _sys_ni_syscall /* 130: old "get_kernel_syms" */
966 .long _sys_quotactl
967 .long _sys_getpgid
968 .long _sys_fchdir
969 .long _sys_bdflush
970 .long _sys_ni_syscall /* 135 */ /* sys_sysfs */
971 .long _sys_personality
972 .long _sys_ni_syscall /* for afs_syscall */
973 .long _sys_setfsuid /* setfsuid16 */
974 .long _sys_setfsgid /* setfsgid16 */
975 .long _sys_llseek /* 140 */
976 .long _sys_getdents
977 .long _sys_ni_syscall /* sys_select */
978 .long _sys_flock
979 .long _sys_ni_syscall /* sys_msync */
980 .long _sys_readv /* 145 */
981 .long _sys_writev
982 .long _sys_getsid
983 .long _sys_fdatasync
984 .long _sys_sysctl
985 .long _sys_ni_syscall /* 150 */ /* sys_mlock */
986 .long _sys_ni_syscall /* sys_munlock */
987 .long _sys_ni_syscall /* sys_mlockall */
988 .long _sys_ni_syscall /* sys_munlockall */
989 .long _sys_sched_setparam
990 .long _sys_sched_getparam /* 155 */
991 .long _sys_sched_setscheduler
992 .long _sys_sched_getscheduler
993 .long _sys_sched_yield
994 .long _sys_sched_get_priority_max
995 .long _sys_sched_get_priority_min /* 160 */
996 .long _sys_sched_rr_get_interval
997 .long _sys_nanosleep
998 .long _sys_ni_syscall /* sys_mremap */
999 .long _sys_setresuid /* setresuid16 */
1000 .long _sys_getresuid /* getresuid16 */ /* 165 */
1001 .long _sys_ni_syscall /* for vm86 */
1002 .long _sys_ni_syscall /* old "query_module" */
1003 .long _sys_ni_syscall /* sys_poll */
1004 .long _sys_ni_syscall /* sys_nfsservctl */
1005 .long _sys_setresgid /* setresgid16 */ /* 170 */
1006 .long _sys_getresgid /* getresgid16 */
1007 .long _sys_prctl
1008 .long _sys_rt_sigreturn
1009 .long _sys_rt_sigaction
1010 .long _sys_rt_sigprocmask /* 175 */
1011 .long _sys_rt_sigpending
1012 .long _sys_rt_sigtimedwait
1013 .long _sys_rt_sigqueueinfo
1014 .long _sys_rt_sigsuspend
1015 .long _sys_pread64 /* 180 */
1016 .long _sys_pwrite64
1017 .long _sys_lchown /* lchown16 */
1018 .long _sys_getcwd
1019 .long _sys_capget
1020 .long _sys_capset /* 185 */
1021 .long _sys_sigaltstack
1022 .long _sys_sendfile
1023 .long _sys_ni_syscall /* streams1 */
1024 .long _sys_ni_syscall /* streams2 */
1025 .long _sys_vfork /* 190 */
1026 .long _sys_getrlimit
1027 .long _sys_mmap2
1028 .long _sys_truncate64
1029 .long _sys_ftruncate64
1030 .long _sys_stat64 /* 195 */
1031 .long _sys_lstat64
1032 .long _sys_fstat64
1033 .long _sys_chown
1034 .long _sys_getuid
1035 .long _sys_getgid /* 200 */
1036 .long _sys_geteuid
1037 .long _sys_getegid
1038 .long _sys_setreuid
1039 .long _sys_setregid
1040 .long _sys_getgroups /* 205 */
1041 .long _sys_setgroups
1042 .long _sys_fchown
1043 .long _sys_setresuid
1044 .long _sys_getresuid
1045 .long _sys_setresgid /* 210 */
1046 .long _sys_getresgid
1047 .long _sys_lchown
1048 .long _sys_setuid
1049 .long _sys_setgid
1050 .long _sys_setfsuid /* 215 */
1051 .long _sys_setfsgid
1052 .long _sys_pivot_root
1053 .long _sys_ni_syscall /* sys_mincore */
1054 .long _sys_ni_syscall /* sys_madvise */
1055 .long _sys_getdents64 /* 220 */
1056 .long _sys_fcntl64
1057 .long _sys_ni_syscall /* reserved for TUX */
1058 .long _sys_ni_syscall
1059 .long _sys_gettid
1060 .long _sys_ni_syscall /* 225 */ /* sys_readahead */
1061 .long _sys_setxattr
1062 .long _sys_lsetxattr
1063 .long _sys_fsetxattr
1064 .long _sys_getxattr
1065 .long _sys_lgetxattr /* 230 */
1066 .long _sys_fgetxattr
1067 .long _sys_listxattr
1068 .long _sys_llistxattr
1069 .long _sys_flistxattr
1070 .long _sys_removexattr /* 235 */
1071 .long _sys_lremovexattr
1072 .long _sys_fremovexattr
1073 .long _sys_tkill
1074 .long _sys_sendfile64
1075 .long _sys_futex /* 240 */
1076 .long _sys_sched_setaffinity
1077 .long _sys_sched_getaffinity
1078 .long _sys_ni_syscall /* sys_set_thread_area */
1079 .long _sys_ni_syscall /* sys_get_thread_area */
1080 .long _sys_io_setup /* 245 */
1081 .long _sys_io_destroy
1082 .long _sys_io_getevents
1083 .long _sys_io_submit
1084 .long _sys_io_cancel
1085 .long _sys_ni_syscall /* 250 */ /* sys_alloc_hugepages */
1086 .long _sys_ni_syscall /* sys_freec_hugepages */
1087 .long _sys_exit_group
1088 .long _sys_lookup_dcookie
1089 .long _sys_bfin_spinlock
1090 .long _sys_epoll_create /* 255 */
1091 .long _sys_epoll_ctl
1092 .long _sys_epoll_wait
1093 .long _sys_ni_syscall /* remap_file_pages */
1094 .long _sys_set_tid_address
1095 .long _sys_timer_create /* 260 */
1096 .long _sys_timer_settime
1097 .long _sys_timer_gettime
1098 .long _sys_timer_getoverrun
1099 .long _sys_timer_delete
1100 .long _sys_clock_settime /* 265 */
1101 .long _sys_clock_gettime
1102 .long _sys_clock_getres
1103 .long _sys_clock_nanosleep
1104 .long _sys_statfs64
1105 .long _sys_fstatfs64 /* 270 */
1106 .long _sys_tgkill
1107 .long _sys_utimes
1108 .long _sys_fadvise64_64
1109 .long _sys_ni_syscall /* vserver */
1110 .long _sys_ni_syscall /* 275, mbind */
1111 .long _sys_ni_syscall /* get_mempolicy */
1112 .long _sys_ni_syscall /* set_mempolicy */
1113 .long _sys_mq_open
1114 .long _sys_mq_unlink
1115 .long _sys_mq_timedsend /* 280 */
1116 .long _sys_mq_timedreceive
1117 .long _sys_mq_notify
1118 .long _sys_mq_getsetattr
1119 .long _sys_ni_syscall /* kexec_load */
1120 .long _sys_waitid /* 285 */
1121 .long _sys_add_key
1122 .long _sys_request_key
1123 .long _sys_keyctl
1124 .long _sys_ioprio_set
1125 .long _sys_ioprio_get /* 290 */
1126 .long _sys_inotify_init
1127 .long _sys_inotify_add_watch
1128 .long _sys_inotify_rm_watch
1129 .long _sys_ni_syscall /* migrate_pages */
1130 .long _sys_openat /* 295 */
1131 .long _sys_mkdirat
1132 .long _sys_mknodat
1133 .long _sys_fchownat
1134 .long _sys_futimesat
1135 .long _sys_fstatat64 /* 300 */
1136 .long _sys_unlinkat
1137 .long _sys_renameat
1138 .long _sys_linkat
1139 .long _sys_symlinkat
1140 .long _sys_readlinkat /* 305 */
1141 .long _sys_fchmodat
1142 .long _sys_faccessat
1143 .long _sys_pselect6
1144 .long _sys_ppoll
1145 .long _sys_unshare /* 310 */
1146 .long _sys_sram_alloc
1147 .long _sys_sram_free
1148 .long _sys_dma_memcpy
1149 .long _sys_accept
1150 .long _sys_bind /* 315 */
1151 .long _sys_connect
1152 .long _sys_getpeername
1153 .long _sys_getsockname
1154 .long _sys_getsockopt
1155 .long _sys_listen /* 320 */
1156 .long _sys_recv
1157 .long _sys_recvfrom
1158 .long _sys_recvmsg
1159 .long _sys_send
1160 .long _sys_sendmsg /* 325 */
1161 .long _sys_sendto
1162 .long _sys_setsockopt
1163 .long _sys_shutdown
1164 .long _sys_socket
1165 .long _sys_socketpair /* 330 */
1166 .long _sys_semctl
1167 .long _sys_semget
1168 .long _sys_semop
1169 .long _sys_msgctl
1170 .long _sys_msgget /* 335 */
1171 .long _sys_msgrcv
1172 .long _sys_msgsnd
1173 .long _sys_shmat
1174 .long _sys_shmctl
1175 .long _sys_shmdt /* 340 */
1176 .long _sys_shmget
1177 .rept NR_syscalls-(.-_sys_call_table)/4
1178 .long _sys_ni_syscall
1179 .endr
1180_excpt_saved_imask:
1181 .long 0;
1182
1183_exception_stack:
1184 .rept 1024
1185 .long 0;
1186 .endr
1187_exception_stack_top:
1188
1189#if defined(ANOMALY_05000261)
1190/* Used by the assembly entry point to work around an anomaly. */
1191_last_cplb_fault_retx:
1192 .long 0;
1193#endif
1194/*
1195 * Single instructions can have multiple faults, which need to be
1196 * handled by traps.c, in irq5. We store the exception cause to ensure
1197 * we don't miss a double fault condition
1198 */
1199ENTRY(_in_ptr_excause)
1200 .long 0;
1201ENTRY(_out_ptr_excause)
1202 .long 0;
1203ALIGN
1204ENTRY(_excause_circ_buf)
1205 .rept 4
1206 .long 0
1207 .endr