source: mainline/kernel/arch/sparc32/src/trap_table.S@ 3f596c9

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 3f596c9 was 3f596c9, checked in by Jakub Klama <jakub.klama@…>, 12 years ago

Bugfixing preemptive trap handlers.

  • Property mode set to 100644
File size: 13.3 KB
Line 
1#
2# Copyright (c) 2013 Jakub Klama
3# All rights reserved.
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions
7# are met:
8#
9# - Redistributions of source code must retain the above copyright
10# notice, this list of conditions and the following disclaimer.
11# - Redistributions in binary form must reproduce the above copyright
12# notice, this list of conditions and the following disclaimer in the
13# documentation and/or other materials provided with the distribution.
14# - The name of the author may not be used to endorse or promote products
15# derived from this software without specific prior written permission.
16#
17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27#
28
29#include <arch/trap.h>
30
31.text
32
33.global trap_table
34.global reset_trap
35.global preemptible_trap
36.global interrupt_trap
37.global syscall_trap
38.global window_overflow_trap
39.global window_underflow_trap
40.global write_to_invalid
41
42.macro get_wim_number reg
43 clr \reg
44 mov %wim, %g5
451: andcc %g5, 1, %g0
46 bne 2f
47 nop
48 srl %g5, 1, %g5
49 inc \reg
50 b 1b
512: nop
52
53.endm
54
55.macro get_cwp reg
56 mov %psr, \reg
57 and \reg, 0x7, \reg
58.endm
59
60.macro switch_to_invalid saved_wim, saved_psr
61 get_wim_number %l3
62 mov %wim, \saved_wim ! save WIM
63 mov %g0, %wim ! clear WIM
64 mov %psr, \saved_psr ! read PSR
65 and \saved_psr, 0xfffffff0, %l4
66 or %l4, %l3, %l3 ! set CWP
67 mov %l3, %psr ! write PSR
68 nop
69 nop
70 nop
71 nop ! wait for PSR to be effective
72.endm
73
74.macro switch_back wim, psr
75 mov \wim, %wim ! saved WIM
76 mov \psr, %psr ! saved PSR
77 nop
78 nop
79 nop
80 nop
81.endm
82
83/* Save next window to kernel stack or UWB */
84.macro inline_save_kernel
85 set 0x80000100, %g2
86 set 'k', %g1
87 sta %g1, [%g2] 0x1c
88 save
89 std %l0, [%sp + 0]
90 std %l2, [%sp + 8]
91 std %l4, [%sp + 16]
92 std %l6, [%sp + 24]
93 std %i0, [%sp + 32]
94 std %i2, [%sp + 40]
95 std %i4, [%sp + 48]
96 std %i6, [%sp + 56]
97 restore
98.endm
99
100.macro inline_save_uspace uwb
101 set 0x80000100, %g2
102 set 'u', %g1
103 sta %g1, [%g2] 0x1c
104 save
105 ld [\uwb], %g1
106 std %l0, [%g1 + 0]
107 std %l2, [%g1 + 8]
108 std %l4, [%g1 + 16]
109 std %l6, [%g1 + 24]
110 std %i0, [%g1 + 32]
111 std %i2, [%g1 + 40]
112 std %i4, [%g1 + 48]
113 std %i6, [%g1 + 56]
114 add \uwb, 64, \uwb
115 restore
116.endm
117
118/* Restore window from kernel stack or UWB */
119.macro inline_restore_kernel
120 save
121 ldd [%sp + 0], %l0
122 ldd [%sp + 8], %l2
123 ldd [%sp + 16], %l4
124 ldd [%sp + 24], %l6
125 ldd [%sp + 32], %i0
126 ldd [%sp + 40], %i2
127 ldd [%sp + 48], %i4
128 ldd [%sp + 56], %i6
129 restore
130.endm
131
132.macro inline_restore_uspace uwb
133 save
134 ld [\uwb], %g1
135 std %l0, [%g1 + 0]
136 std %l2, [%g1 + 8]
137 std %l4, [%g1 + 16]
138 std %l6, [%g1 + 24]
139 std %i0, [%g1 + 32]
140 std %i2, [%g1 + 40]
141 std %i4, [%g1 + 48]
142 std %i6, [%g1 + 56]
143 sub \uwb, 64, \uwb
144 restore
145.endm
146
147.macro if_from_kernel label
148 mov %psr, %g2
149 and %g2, (1 << 6), %g2
150 cmp %g2, 0
151 bne \label
152 nop
153.endm
154
155write_to_invalid:
156 ! Write value 1
157 mov %o0, %g7
158 switch_to_invalid %g3, %g4
159 mov %g7, %l5
160 switch_back %g3, %g4
161 ! Write value 2
162 mov %o1, %g7
163 switch_to_invalid %g3, %g4
164 mov %g7, %l6
165 switch_back %g3, %g4
166 ! Write value 3
167 mov %o2, %g7
168 switch_to_invalid %g3, %g4
169 mov %g7, %l7
170 switch_back %g3, %g4
171 retl
172 nop
173
174reset_trap:
175 set 0x80000100, %l0
176 set 'r', %l1
177 sta %l1, [%l0] 0x1c
178 rett
179
180window_overflow_trap:
181 /* rotate WIM on bit right, we have 8 windows */
182 mov %wim, %l3
183 sll %l3, 7, %l4
184 srl %l3, 1, %l3
185 or %l3, %l4, %l3
186 and %l3, 0xff, %l3
187
188 /* disable WIM traps */
189 mov %g0,%wim
190 nop; nop; nop
191
192 /* Save invalid window data */
193 mov %l5, %g5 ! kernel stack pointer
194 mov %l6, %g6 ! kernel wbuf
195 mov %l7, %g7
196
197 /* Check whether previous mode was usermode */
198 and %l0, (1 << 6), %l0
199 cmp %l0, 0
200 beq 1f
201 nop
202
203 /* kernel: */
204 /* we should check whether window needs to be saved
205 * to kernel stack or uwb
206 */
207 cmp %g7, 0
208 bne 2f
209 nop
210
211 /* dump registers to stack */
212 save
213 st %l0, [%sp + 0] ! XXX
214 std %l0, [%sp + 0]
215 std %l2, [%sp + 8]
216 std %l4, [%sp + 16]
217 std %l6, [%sp + 24]
218 std %i0, [%sp + 32]
219 std %i2, [%sp + 40]
220 std %i4, [%sp + 48]
221 std %i6, [%sp + 56]
222 b 3f
223 nop
224
2251: /* uspace: */
226 /* set uspace window mark */
227 mov %psr, %g7
228 and %g7, 0x7, %g7
229 inc %g7
230
2312: save
232 std %l0, [%g6 + 0]
233 std %l2, [%g6 + 8]
234 std %l4, [%g6 + 16]
235 std %l6, [%g6 + 24]
236 std %i0, [%g6 + 32]
237 std %i2, [%g6 + 40]
238 std %i4, [%g6 + 48]
239 std %i6, [%g6 + 56]
240 add %g4, 64, %g4
241
242 /* check whether it's the last user window to be saved */
243 mov %psr, %l4
244 and %l4, 0x7, %l4
245 inc %l4
246 cmp %g7, %l4
247 bne 3f
248 nop
249
250 /* clear uspace window mark */
251 clr %g7
252
2533: /* back to where we should be */
254 mov %g5, %l5
255 mov %g6, %l6
256 mov %g7, %l7
257 restore
258
259 /* set new value of window */
260 mov %l3,%wim
261 nop; nop; nop
262
263 /* go home */
264 jmp %l1
265 rett %l2
266
267window_underflow_trap:
268 /* rotate WIM on bit LEFT, we have 8 windows */
269 mov %wim,%l3
270 srl %l3,7,%l4
271 sll %l3,1,%l3
272 or %l3,%l4,%l3
273 and %l3, 0xff,%l3
274
275 /* disable WIM traps */
276 mov %g0,%wim
277 nop; nop; nop
278
279 /* Check whether previous mode was usermode */
280 mov %psr, %l0
281 and %l0, (1 << 6), %l0
282 cmp %l0, 0
283 beq 1f
284 nop
285
286 restore
287 restore
288 mov %l5, %g5 ! kernel stack pointer
289 mov %l6, %g6 ! kernel wbuf
290 mov %l7, %g7
291
292 ldd [%sp + 0], %l0
293 ldd [%sp + 8], %l2
294 ldd [%sp + 16], %l4
295 ldd [%sp + 24], %l6
296 ldd [%sp + 32], %i0
297 ldd [%sp + 40], %i2
298 ldd [%sp + 48], %i4
299 ldd [%sp + 56], %i6
300 b 2f
301 nop
302
3031: restore
304 restore
305 mov %l5, %g5 ! kernel stack pointer
306 mov %l6, %g6 ! kernel wbuf
307 mov %l7, %g7
308 sub %g6, 64, %g6
309 ldd [%g6 + 0], %l0
310 ldd [%g6 + 8], %l2
311 ldd [%g6 + 16], %l4
312 ldd [%g6 + 24], %l6
313 ldd [%g6 + 32], %i0
314 ldd [%g6 + 40], %i2
315 ldd [%g6 + 48], %i4
316 ldd [%g6 + 56], %i6
317
3182: /* Restore invalid window data */
319 restore
320 mov %g5, %l5
321 mov %g6, %l6
322 mov %g7, %l7
323 save
324 save
325 save
326
327 /* Set new value of window */
328 mov %l3,%wim
329 nop; nop; nop
330
331 /* go home */
332 jmp %l1
333 rett %l2
334
335preemptible_trap:
336 /* Check whether we landed in invalid window */
337 get_wim_number %g6
338 get_cwp %g7
339 cmp %g6, %g7
340 bne 4f
341 nop
342
343 /* We are in invalid window. Check whether previous mode was usermode */
344 if_from_kernel 3f
345
346 /* Trap originated from uspace */
347 /* Kernel stack pointer is at %l5, uwb is at %l6 */
348 inline_save_uspace %l6
349
350 /* set uspace window mark */
351 mov %psr, %l7
352 and %l7, 0x7, %l7
353 inc %l7
354
3553: /* Trap originated from kernel */
356 inline_save_kernel
357
3584: /* Check whether previous mode was usermode */
359 if_from_kernel 5f
360
361 /* Load kernel stack pointer from invalid window */
362 switch_to_invalid %g5, %g6
363 /* set uspace window mark */
364 mov %g6, %l7
365 and %l7, 0x7, %l7
366 inc %l7
367 /* Save stack pointer */
368 mov %l5, %g7
369 switch_back %g5, %g6
370 mov %g7, %sp
371// mov %sp, %fp
372
3735: /* Set up stack frame */
374 sub %sp, 112, %sp
375
376 /* Save trap data on stack */
377 mov %psr, %l0
378 st %l1, [%sp + 92]
379 st %l2, [%sp + 96]
380 st %l0, [%sp + 100]
381
382 /* Enable traps */
383 mov %psr, %l0
384 or %l0, (1 << 5), %l0
385 mov %l0, %psr
386 nop
387 nop
388 nop
389 nop
390
391 /* Jump to actual subroutine */
392 call %o2
393 sub %fp, 12, %o1
394
395 /* Return from handler */
396 ld [%sp + 92], %l1
397 ld [%sp + 96], %l2
398 ld [%sp + 100], %l0
399 mov %l0, %psr
400 nop
401 nop
402 nop
403 nop
404 nop
405
406 /* If trap originated from uspace, clear uspace window mark */
407 if_from_kernel 6f
408 switch_to_invalid %g5, %g6
409 clr %l7
410 switch_back %g5, %g6
411
4126: jmp %l1
413 rett %l2
414
415interrupt_trap:
416 mov %psr, %l0
417
418 /* Check whether previous mode was usermode */
419 and %l0, (1 << 6), %l0
420 cmp %l0, 0
421 bne 1f
422 nop
423
424 /* Set up stack */
425 set kernel_sp, %l4
426 ld [%l4], %sp
427 mov %sp, %fp
4281: sub %sp, 112, %sp
429
430 /* Save trap data on stack */
431 mov %psr, %l0
432 st %l1, [%fp - 4]
433 st %l2, [%fp - 8]
434 st %l0, [%fp - 12]
435
436 /* Enable traps */
437 mov %psr, %l0
438 or %l0, (1 << 5), %l0
439 mov %l0, %psr
440 nop
441 nop
442 nop
443 nop
444
445 /* Jump to actual subroutine */
446 mov %g2, %o0
447 call exc_dispatch
448 sub %fp, 12, %o1
449
450 /* Return from handler */
451 ld [%fp - 4], %l1
452 ld [%fp - 8], %l2
453 ld [%fp - 12], %l0
454 mov %l0, %psr
455 nop
456 nop
457 nop
458 nop
459 nop
460 jmp %l1
461 rett %l2
462
463syscall_trap:
464 /* Check whether we landed in invalid window */
465 get_wim_number %g6
466 get_cwp %g7
467 cmp %g6, %g7
468 bne 4f
469 nop
470
471 /* We are in invalid window. Check whether previous mode was usermode */
472 if_from_kernel 3f
473
474 /* Kernel stack pointer is at %l5, uwb is at %l6 */
475 inline_save_uspace %l6
4763: inline_save_kernel
477
4784: /* Check whether previous mode was usermode */
479 if_from_kernel 5f
480
481 /* Load kernel stack pointer from invalid window */
482 switch_to_invalid %g5, %g6
483 restore
484 mov %l5, %g7 ! stack pointer
485 switch_back %g5, %g6
486 mov %g7, %sp
487 mov %sp, %fp
4885: sub %sp, 112, %sp
489
490 /* Save trap data on stack */
491 mov %psr, %l0
492 st %l1, [%fp - 4]
493 st %l2, [%fp - 8]
494 st %l0, [%fp - 12]
495
496 /* Enable traps */
497 mov %psr, %l0
498 or %l0, (1 << 5), %l0
499 mov %l0, %psr
500 nop
501 nop
502 nop
503 nop
504
505 /* Jump to actual subroutine */
506 sub %o0, 0x80, %o0
507 st %o0, [ %sp + 92 ]
508 mov %i0, %o0
509 mov %i1, %o1
510 mov %i2, %o2
511 mov %i3, %o3
512 mov %i4, %o4
513 call syscall
514 mov %i5, %o5
515
516 /* Return from handler */
517 ld [%fp - 4], %l1
518 ld [%fp - 8], %l2
519 ld [%fp - 12], %l0
520 mov %l0, %psr
521 nop
522 nop
523 nop
524 nop
525 nop
526 jmp %l2
527 rett %l2 + 4
528
529#define STRAP(_vector, _handler) \
530 .org trap_table + _vector * TRAP_ENTRY_SIZE; \
531 mov %psr, %l0 ; \
532 sethi %hi(_handler), %l4 ; \
533 jmp %lo(_handler) + %l4 ; \
534 nop
535
536#define TRAP(_vector, _handler) \
537 .org trap_table + _vector * TRAP_ENTRY_SIZE; \
538 set _vector, %o0 ; \
539 sethi %hi(_handler), %o2 ; \
540 b preemptible_trap ; \
541 or %o2, %lo(_handler), %o2 ;
542
543#define SYSCALL(_vector) \
544 .org trap_table + _vector * TRAP_ENTRY_SIZE; \
545 set _vector, %o0 ; \
546 b syscall_trap ; \
547 nop ;
548
549#define INTERRUPT(_vector, _priority) \
550 .org trap_table + _vector * TRAP_ENTRY_SIZE; \
551 mov %psr, %l0 ; \
552 mov _priority, %g2 ; \
553 b interrupt_trap ; \
554 nop ;
555
556#define BADTRAP(_vector) \
557 .org trap_table + _vector * TRAP_ENTRY_SIZE ; \
558 ta 0 ;
559
560.align TRAP_TABLE_SIZE
561trap_table:
562 STRAP(0x0, reset_trap)
563 TRAP(0x1, instruction_access_exception)
564 TRAP(0x2, illegal_instruction)
565 TRAP(0x3, privileged_instruction)
566 TRAP(0x4, fp_disabled)
567 STRAP(0x5, window_overflow_trap)
568 STRAP(0x6, window_underflow_trap)
569 TRAP(0x7, mem_address_not_aligned)
570 TRAP(0x8, fp_exception)
571 TRAP(0x9, data_access_exception)
572 TRAP(0xa, tag_overflow)
573 BADTRAP(0xb)
574 BADTRAP(0xc)
575 BADTRAP(0xd)
576 BADTRAP(0xe)
577 BADTRAP(0xf)
578 BADTRAP(0x10)
579 INTERRUPT(0x11, 1)
580 INTERRUPT(0x12, 2)
581 INTERRUPT(0x13, 3)
582 INTERRUPT(0x14, 4)
583 INTERRUPT(0x15, 5)
584 INTERRUPT(0x16, 6)
585 INTERRUPT(0x17, 7)
586 INTERRUPT(0x18, 8)
587 INTERRUPT(0x19, 9)
588 INTERRUPT(0x1a, 10)
589 INTERRUPT(0x1b, 11)
590 INTERRUPT(0x1c, 12)
591 INTERRUPT(0x1d, 13)
592 INTERRUPT(0x1e, 14)
593 INTERRUPT(0x1f, 15)
594 TRAP(0x21, instruction_access_error)
595 BADTRAP(0x22)
596 BADTRAP(0x23)
597 BADTRAP(0x24)
598 BADTRAP(0x25)
599 BADTRAP(0x26)
600 BADTRAP(0x27)
601 BADTRAP(0x28)
602 TRAP(0x29, data_access_error)
603 TRAP(0x2a, division_by_zero)
604 TRAP(0x2b, data_store_error)
605 TRAP(0x2c, data_access_mmu_miss)
606 BADTRAP(0x2d)
607 BADTRAP(0x2e)
608 BADTRAP(0x2f)
609 BADTRAP(0x30)
610 BADTRAP(0x31)
611 BADTRAP(0x32)
612 BADTRAP(0x33)
613 BADTRAP(0x34)
614 BADTRAP(0x35)
615 BADTRAP(0x36)
616 BADTRAP(0x37)
617 BADTRAP(0x38)
618 BADTRAP(0x39)
619 BADTRAP(0x3a)
620 BADTRAP(0x3b)
621 BADTRAP(0x3c)
622 BADTRAP(0x3d)
623 BADTRAP(0x3e)
624 BADTRAP(0x3f)
625 BADTRAP(0x40)
626 BADTRAP(0x41)
627 BADTRAP(0x42)
628 BADTRAP(0x43)
629 BADTRAP(0x44)
630 BADTRAP(0x45)
631 BADTRAP(0x46)
632 BADTRAP(0x47)
633 BADTRAP(0x48)
634 BADTRAP(0x49)
635 BADTRAP(0x4a)
636 BADTRAP(0x4b)
637 BADTRAP(0x4c)
638 BADTRAP(0x4d)
639 BADTRAP(0x4e)
640 BADTRAP(0x4f)
641 BADTRAP(0x50)
642 BADTRAP(0x51)
643 BADTRAP(0x52)
644 BADTRAP(0x53)
645 BADTRAP(0x54)
646 BADTRAP(0x55)
647 BADTRAP(0x56)
648 BADTRAP(0x57)
649 BADTRAP(0x58)
650 BADTRAP(0x59)
651 BADTRAP(0x5a)
652 BADTRAP(0x5b)
653 BADTRAP(0x5c)
654 BADTRAP(0x5d)
655 BADTRAP(0x5e)
656 BADTRAP(0x5f)
657 BADTRAP(0x60)
658 BADTRAP(0x61)
659 BADTRAP(0x62)
660 BADTRAP(0x63)
661 BADTRAP(0x64)
662 BADTRAP(0x65)
663 BADTRAP(0x66)
664 BADTRAP(0x67)
665 BADTRAP(0x68)
666 BADTRAP(0x69)
667 BADTRAP(0x6a)
668 BADTRAP(0x6b)
669 BADTRAP(0x6c)
670 BADTRAP(0x6d)
671 BADTRAP(0x6e)
672 BADTRAP(0x6f)
673 BADTRAP(0x70)
674 BADTRAP(0x71)
675 BADTRAP(0x72)
676 BADTRAP(0x73)
677 BADTRAP(0x74)
678 BADTRAP(0x75)
679 BADTRAP(0x76)
680 BADTRAP(0x77)
681 BADTRAP(0x78)
682 BADTRAP(0x79)
683 BADTRAP(0x7a)
684 BADTRAP(0x7b)
685 BADTRAP(0x7c)
686 BADTRAP(0x7d)
687 BADTRAP(0x7e)
688 BADTRAP(0x7f)
689 SYSCALL(0x80)
690 SYSCALL(0x81)
691 SYSCALL(0x82)
692 SYSCALL(0x83)
693 SYSCALL(0x84)
694 SYSCALL(0x85)
695 SYSCALL(0x86)
696 SYSCALL(0x87)
697 SYSCALL(0x88)
698 SYSCALL(0x89)
699 SYSCALL(0x8a)
700 SYSCALL(0x8b)
701 SYSCALL(0x8c)
702 SYSCALL(0x8d)
703 SYSCALL(0x8e)
704 SYSCALL(0x8f)
705 SYSCALL(0x90)
706 SYSCALL(0x91)
707 SYSCALL(0x92)
708 SYSCALL(0x93)
709 SYSCALL(0x94)
710 SYSCALL(0x95)
711 SYSCALL(0x96)
712 SYSCALL(0x97)
713 SYSCALL(0x98)
714 SYSCALL(0x99)
715 SYSCALL(0x9a)
716 SYSCALL(0x9b)
717 SYSCALL(0x9c)
718 SYSCALL(0x9d)
719 SYSCALL(0x9e)
720 SYSCALL(0x9f)
721 SYSCALL(0xa0)
722 SYSCALL(0xa1)
723 SYSCALL(0xa2)
724 SYSCALL(0xa3)
725 SYSCALL(0xa4)
726 SYSCALL(0xa5)
727 SYSCALL(0xa6)
728 SYSCALL(0xa7)
729 SYSCALL(0xa8)
730 SYSCALL(0xa9)
Note: See TracBrowser for help on using the repository browser.