source: mainline/kernel/arch/sparc32/src/trap_table.S@ 9f9d7250

lfn serial ticket/834-toolchain-update topic/fix-logger-deadlock topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 9f9d7250 was 9f9d7250, checked in by Jakub Klama <jakub.klama@…>, 13 years ago
  • Properly implement inline_restores with respect to preserve invalid window variables
  • Fix some next bugs in preemptible trap handler
  • Property mode set to 100644
File size: 14.0 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 mov %wim, %g2
86 mov %g0, %wim
87 save
88 std %l0, [%sp + 0]
89 std %l2, [%sp + 8]
90 std %l4, [%sp + 16]
91 std %l6, [%sp + 24]
92 std %i0, [%sp + 32]
93 std %i2, [%sp + 40]
94 std %i4, [%sp + 48]
95 std %i6, [%sp + 56]
96 restore
97 mov %g2, %wim
98.endm
99
100.macro inline_save_uspace uwb
101 mov %wim, %g2
102 mov %g0, %wim
103 save
104 std %l0, [\uwb + 0]
105 std %l2, [\uwb + 8]
106 std %l4, [\uwb + 16]
107 std %l6, [\uwb + 24]
108 std %i0, [\uwb + 32]
109 std %i2, [\uwb + 40]
110 std %i4, [\uwb + 48]
111 std %i6, [\uwb + 56]
112 add \uwb, 64, \uwb
113 restore
114 mov %g2, %wim
115.endm
116
117/* Restore window from kernel stack or UWB */
118.macro inline_restore_kernel
119 mov %wim, %l3
120 sll %l3, 7, %l4
121 srl %l3, 1, %l3
122 or %l3, %l4, %l3
123 and %l3, 0xff, %l3
124
125 mov %g0, %wim
126 restore
127 mov %l5, %g5
128 mov %l6, %g6
129 mov %l7, %g7
130 restore
131 mov %g5, %l5
132 mov %g6, %l6
133 mov %g7, %l7
134 save
135
136 ldd [%sp + 0], %l0
137 ldd [%sp + 8], %l2
138 ldd [%sp + 16], %l4
139 ldd [%sp + 24], %l6
140 ldd [%sp + 32], %i0
141 ldd [%sp + 40], %i2
142 ldd [%sp + 48], %i4
143 ldd [%sp + 56], %i6
144 save
145
146 mov %l3, %wim
147.endm
148
149.macro inline_restore_uspace uwb
150 mov %wim, %l3
151 sll %l3, 7, %l4
152 srl %l3, 1, %l3
153 or %l3, %l4, %l3
154 and %l3, 0xff, %l3
155
156 mov %g0, %wim
157 restore
158 mov %l5, %g5
159 mov %l6, %g6
160 mov %l7, %g7
161 restore
162 mov %g5, %l5
163 mov %g6, %l6
164 mov %g7, %l7
165 save
166
167 ldd [\uwb + 0], %l0
168 ldd [\uwb + 8], %l2
169 ldd [\uwb + 16], %l4
170 ldd [\uwb + 24], %l6
171 ldd [\uwb + 32], %i0
172 ldd [\uwb + 40], %i2
173 ldd [\uwb + 48], %i4
174 ldd [\uwb + 56], %i6
175 sub \uwb, 64, \uwb
176 save
177
178 mov %l3, %wim
179.endm
180
181.macro if_from_kernel label
182 mov %psr, %g2
183 and %g2, (1 << 6), %g2
184 cmp %g2, 0
185 bne \label
186 nop
187.endm
188
189write_to_invalid:
190 ! Write value 1
191 mov %o0, %g7
192 switch_to_invalid %g3, %g4
193 mov %g7, %l5
194 switch_back %g3, %g4
195 ! Write value 2
196 mov %o1, %g7
197 switch_to_invalid %g3, %g4
198 mov %g7, %l6
199 switch_back %g3, %g4
200 ! Write value 3
201 mov %o2, %g7
202 switch_to_invalid %g3, %g4
203 mov %g7, %l7
204 switch_back %g3, %g4
205 retl
206 nop
207
208reset_trap:
209 set 0x80000100, %l0
210 set 'r', %l1
211 sta %l1, [%l0] 0x1c
212 rett
213
214window_overflow_trap:
215 /* rotate WIM on bit right, we have 8 windows */
216 mov %wim, %l3
217 sll %l3, 7, %l4
218 srl %l3, 1, %l3
219 or %l3, %l4, %l3
220 and %l3, 0xff, %l3
221
222 /* disable WIM traps */
223 mov %g0,%wim
224 nop; nop; nop
225
226 /* Save invalid window data */
227 mov %l5, %g5 ! kernel stack pointer
228 mov %l6, %g6 ! kernel wbuf
229 mov %l7, %g7
230
231 /* Check whether previous mode was usermode */
232 and %l0, (1 << 6), %l0
233 cmp %l0, 0
234 beq 1f
235 nop
236
237 /* kernel: */
238 /* we should check whether window needs to be saved
239 * to kernel stack or uwb
240 */
241 cmp %g7, 0
242 bne 2f
243 nop
244
245 /* dump registers to stack */
246 save
247 st %l0, [%sp + 0] ! XXX
248 std %l0, [%sp + 0]
249 std %l2, [%sp + 8]
250 std %l4, [%sp + 16]
251 std %l6, [%sp + 24]
252 std %i0, [%sp + 32]
253 std %i2, [%sp + 40]
254 std %i4, [%sp + 48]
255 std %i6, [%sp + 56]
256 b 3f
257 nop
258
2591: /* uspace: */
260 /* set uspace window mark */
261 mov %psr, %g7
262 and %g7, 0x7, %g7
263 inc %g7
264
2652: save
266 std %l0, [%g6 + 0]
267 std %l2, [%g6 + 8]
268 std %l4, [%g6 + 16]
269 std %l6, [%g6 + 24]
270 std %i0, [%g6 + 32]
271 std %i2, [%g6 + 40]
272 std %i4, [%g6 + 48]
273 std %i6, [%g6 + 56]
274 add %g4, 64, %g4
275
276 /* check whether it's the last user window to be saved */
277 mov %psr, %l4
278 and %l4, 0x7, %l4
279 inc %l4
280 cmp %g7, %l4
281 bne 3f
282 nop
283
284 /* clear uspace window mark */
285 clr %g7
286
2873: /* back to where we should be */
288 mov %g5, %l5
289 mov %g6, %l6
290 mov %g7, %l7
291 restore
292
293 /* set new value of window */
294 mov %l3,%wim
295 nop; nop; nop
296
297 /* go home */
298 jmp %l1
299 rett %l2
300
301window_underflow_trap:
302 /* rotate WIM on bit LEFT, we have 8 windows */
303 mov %wim,%l3
304 srl %l3,7,%l4
305 sll %l3,1,%l3
306 or %l3,%l4,%l3
307 and %l3, 0xff,%l3
308
309 /* disable WIM traps */
310 mov %g0,%wim
311 nop; nop; nop
312
313 /* Check whether previous mode was usermode */
314 mov %psr, %l0
315 and %l0, (1 << 6), %l0
316 cmp %l0, 0
317 beq 1f
318 nop
319
320 restore
321 restore
322 mov %l5, %g5 ! kernel stack pointer
323 mov %l6, %g6 ! kernel wbuf
324 mov %l7, %g7
325
326 ldd [%sp + 0], %l0
327 ldd [%sp + 8], %l2
328 ldd [%sp + 16], %l4
329 ldd [%sp + 24], %l6
330 ldd [%sp + 32], %i0
331 ldd [%sp + 40], %i2
332 ldd [%sp + 48], %i4
333 ldd [%sp + 56], %i6
334 b 2f
335 nop
336
3371: restore
338 restore
339 mov %l5, %g5 ! kernel stack pointer
340 mov %l6, %g6 ! kernel wbuf
341 mov %l7, %g7
342 sub %g6, 64, %g6
343 ldd [%g6 + 0], %l0
344 ldd [%g6 + 8], %l2
345 ldd [%g6 + 16], %l4
346 ldd [%g6 + 24], %l6
347 ldd [%g6 + 32], %i0
348 ldd [%g6 + 40], %i2
349 ldd [%g6 + 48], %i4
350 ldd [%g6 + 56], %i6
351
3522: /* Restore invalid window data */
353 restore
354 mov %g5, %l5
355 mov %g6, %l6
356 mov %g7, %l7
357 save
358 save
359 save
360
361 /* Set new value of window */
362 mov %l3,%wim
363 nop; nop; nop
364
365 /* go home */
366 jmp %l1
367 rett %l2
368
369preemptible_trap:
370 /* Check whether we landed in invalid window */
371 get_wim_number %g6
372 get_cwp %g7
373 cmp %g6, %g7
374 bne 4f
375 nop
376
377 /* We are in invalid window. Check whether previous mode was usermode */
378 if_from_kernel 3f
379
380 /* Trap originated from uspace */
381 /* Kernel stack pointer is at %l5, uwb is at %l6 */
382 inline_save_uspace %l6
383
384 /* set uspace window mark */
385 mov %psr, %l7
386 and %l7, 0x7, %l7
387 inc %l7
388
3893: /* Trap originated from kernel */
390 inline_save_kernel
391
3924: /* Check whether previous mode was usermode */
393 if_from_kernel 5f
394
395 /* Load kernel stack pointer from invalid window */
396 switch_to_invalid %g5, %g6
397 /* set uspace window mark */
398 mov %g6, %l7
399 and %l7, 0x7, %l7
400 inc %l7
401 /* Save stack pointer */
402 mov %l5, %g7
403 switch_back %g5, %g6
404 mov %g7, %sp
405// mov %sp, %fp
406
4075: /* Set up stack frame */
408 sub %sp, 112, %sp
409
410 /* Save trap data on stack */
411 mov %psr, %l0
412 st %l1, [%sp + 92]
413 st %l2, [%sp + 96]
414 st %l0, [%sp + 100]
415
416 /* Enable traps */
417 mov %psr, %l0
418 or %l0, (1 << 5), %l0
419 mov %l0, %psr
420 nop
421 nop
422 nop
423 nop
424
425 /* Jump to actual subroutine */
426 call %o2
427 sub %fp, 12, %o1
428
429 /* Return from handler */
430 ld [%sp + 92], %l1
431 ld [%sp + 96], %l2
432 ld [%sp + 100], %l0
433 mov %l0, %psr
434 nop
435 nop
436 nop
437 nop
438 nop
439
440 /* If trap originated from uspace, clear uspace window mark and save uwb address for future use */
441 if_from_kernel 6f
442 switch_to_invalid %g5, %g6
443 clr %l7
444 mov %l6, %g7
445 switch_back %g5, %g6
446 mov %g7, %g1
447
448 /* If next window is invalid, do inline restore */
4496: get_wim_number %g6
450 get_cwp %g7
451 inc %g7
452 cmp %g6, %g7
453 bne 8f
454
455 if_from_kernel 7f
456
457 inline_restore_uspace %g1
458 b 8f
459 nop
460
4617: inline_restore_kernel
462
4638: jmp %l1
464 rett %l2
465
466interrupt_trap:
467 mov %psr, %l0
468
469 /* Check whether previous mode was usermode */
470 and %l0, (1 << 6), %l0
471 cmp %l0, 0
472 bne 1f
473 nop
474
475 /* Set up stack */
476 set kernel_sp, %l4
477 ld [%l4], %sp
478 mov %sp, %fp
4791: sub %sp, 112, %sp
480
481 /* Save trap data on stack */
482 mov %psr, %l0
483 st %l1, [%fp - 4]
484 st %l2, [%fp - 8]
485 st %l0, [%fp - 12]
486
487 /* Enable traps */
488 mov %psr, %l0
489 or %l0, (1 << 5), %l0
490 mov %l0, %psr
491 nop
492 nop
493 nop
494 nop
495
496 /* Jump to actual subroutine */
497 mov %g2, %o0
498 call exc_dispatch
499 sub %fp, 12, %o1
500
501 /* Return from handler */
502 ld [%fp - 4], %l1
503 ld [%fp - 8], %l2
504 ld [%fp - 12], %l0
505 mov %l0, %psr
506 nop
507 nop
508 nop
509 nop
510 nop
511 jmp %l1
512 rett %l2
513
514syscall_trap:
515 /* Check whether we landed in invalid window */
516 get_wim_number %g6
517 get_cwp %g7
518 cmp %g6, %g7
519 bne 4f
520 nop
521
522 /* We are in invalid window. Check whether previous mode was usermode */
523 if_from_kernel 3f
524
525 /* Kernel stack pointer is at %l5, uwb is at %l6 */
526 inline_save_uspace %l6
5273: inline_save_kernel
528
5294: /* Check whether previous mode was usermode */
530 if_from_kernel 5f
531
532 /* Load kernel stack pointer from invalid window */
533 switch_to_invalid %g5, %g6
534 restore
535 mov %l5, %g7 ! stack pointer
536 switch_back %g5, %g6
537 mov %g7, %sp
538 mov %sp, %fp
5395: sub %sp, 112, %sp
540
541 /* Save trap data on stack */
542 mov %psr, %l0
543 st %l1, [%fp - 4]
544 st %l2, [%fp - 8]
545 st %l0, [%fp - 12]
546
547 /* Enable traps */
548 mov %psr, %l0
549 or %l0, (1 << 5), %l0
550 mov %l0, %psr
551 nop
552 nop
553 nop
554 nop
555
556 /* Jump to actual subroutine */
557 sub %o0, 0x80, %o0
558 st %o0, [ %sp + 92 ]
559 mov %i0, %o0
560 mov %i1, %o1
561 mov %i2, %o2
562 mov %i3, %o3
563 mov %i4, %o4
564 call syscall
565 mov %i5, %o5
566
567 /* Return from handler */
568 ld [%fp - 4], %l1
569 ld [%fp - 8], %l2
570 ld [%fp - 12], %l0
571 mov %l0, %psr
572 nop
573 nop
574 nop
575 nop
576 nop
577 jmp %l2
578 rett %l2 + 4
579
580#define STRAP(_vector, _handler) \
581 .org trap_table + _vector * TRAP_ENTRY_SIZE; \
582 mov %psr, %l0 ; \
583 sethi %hi(_handler), %l4 ; \
584 jmp %lo(_handler) + %l4 ; \
585 nop
586
587#define TRAP(_vector, _handler) \
588 .org trap_table + _vector * TRAP_ENTRY_SIZE; \
589 set _vector, %o0 ; \
590 sethi %hi(_handler), %o2 ; \
591 b preemptible_trap ; \
592 or %o2, %lo(_handler), %o2 ;
593
594#define SYSCALL(_vector) \
595 .org trap_table + _vector * TRAP_ENTRY_SIZE; \
596 set _vector, %o0 ; \
597 b syscall_trap ; \
598 nop ;
599
600#define INTERRUPT(_vector, _priority) \
601 .org trap_table + _vector * TRAP_ENTRY_SIZE; \
602 mov %psr, %l0 ; \
603 mov _priority, %g2 ; \
604 b interrupt_trap ; \
605 nop ;
606
607#define BADTRAP(_vector) \
608 .org trap_table + _vector * TRAP_ENTRY_SIZE ; \
609 ta 0 ;
610
611.align TRAP_TABLE_SIZE
612trap_table:
613 STRAP(0x0, reset_trap)
614 TRAP(0x1, instruction_access_exception)
615 TRAP(0x2, illegal_instruction)
616 TRAP(0x3, privileged_instruction)
617 TRAP(0x4, fp_disabled)
618 STRAP(0x5, window_overflow_trap)
619 STRAP(0x6, window_underflow_trap)
620 TRAP(0x7, mem_address_not_aligned)
621 TRAP(0x8, fp_exception)
622 TRAP(0x9, data_access_exception)
623 TRAP(0xa, tag_overflow)
624 BADTRAP(0xb)
625 BADTRAP(0xc)
626 BADTRAP(0xd)
627 BADTRAP(0xe)
628 BADTRAP(0xf)
629 BADTRAP(0x10)
630 INTERRUPT(0x11, 1)
631 INTERRUPT(0x12, 2)
632 INTERRUPT(0x13, 3)
633 INTERRUPT(0x14, 4)
634 INTERRUPT(0x15, 5)
635 INTERRUPT(0x16, 6)
636 INTERRUPT(0x17, 7)
637 INTERRUPT(0x18, 8)
638 INTERRUPT(0x19, 9)
639 INTERRUPT(0x1a, 10)
640 INTERRUPT(0x1b, 11)
641 INTERRUPT(0x1c, 12)
642 INTERRUPT(0x1d, 13)
643 INTERRUPT(0x1e, 14)
644 INTERRUPT(0x1f, 15)
645 TRAP(0x21, instruction_access_error)
646 BADTRAP(0x22)
647 BADTRAP(0x23)
648 BADTRAP(0x24)
649 BADTRAP(0x25)
650 BADTRAP(0x26)
651 BADTRAP(0x27)
652 BADTRAP(0x28)
653 TRAP(0x29, data_access_error)
654 TRAP(0x2a, division_by_zero)
655 TRAP(0x2b, data_store_error)
656 TRAP(0x2c, data_access_mmu_miss)
657 BADTRAP(0x2d)
658 BADTRAP(0x2e)
659 BADTRAP(0x2f)
660 BADTRAP(0x30)
661 BADTRAP(0x31)
662 BADTRAP(0x32)
663 BADTRAP(0x33)
664 BADTRAP(0x34)
665 BADTRAP(0x35)
666 BADTRAP(0x36)
667 BADTRAP(0x37)
668 BADTRAP(0x38)
669 BADTRAP(0x39)
670 BADTRAP(0x3a)
671 BADTRAP(0x3b)
672 BADTRAP(0x3c)
673 BADTRAP(0x3d)
674 BADTRAP(0x3e)
675 BADTRAP(0x3f)
676 BADTRAP(0x40)
677 BADTRAP(0x41)
678 BADTRAP(0x42)
679 BADTRAP(0x43)
680 BADTRAP(0x44)
681 BADTRAP(0x45)
682 BADTRAP(0x46)
683 BADTRAP(0x47)
684 BADTRAP(0x48)
685 BADTRAP(0x49)
686 BADTRAP(0x4a)
687 BADTRAP(0x4b)
688 BADTRAP(0x4c)
689 BADTRAP(0x4d)
690 BADTRAP(0x4e)
691 BADTRAP(0x4f)
692 BADTRAP(0x50)
693 BADTRAP(0x51)
694 BADTRAP(0x52)
695 BADTRAP(0x53)
696 BADTRAP(0x54)
697 BADTRAP(0x55)
698 BADTRAP(0x56)
699 BADTRAP(0x57)
700 BADTRAP(0x58)
701 BADTRAP(0x59)
702 BADTRAP(0x5a)
703 BADTRAP(0x5b)
704 BADTRAP(0x5c)
705 BADTRAP(0x5d)
706 BADTRAP(0x5e)
707 BADTRAP(0x5f)
708 BADTRAP(0x60)
709 BADTRAP(0x61)
710 BADTRAP(0x62)
711 BADTRAP(0x63)
712 BADTRAP(0x64)
713 BADTRAP(0x65)
714 BADTRAP(0x66)
715 BADTRAP(0x67)
716 BADTRAP(0x68)
717 BADTRAP(0x69)
718 BADTRAP(0x6a)
719 BADTRAP(0x6b)
720 BADTRAP(0x6c)
721 BADTRAP(0x6d)
722 BADTRAP(0x6e)
723 BADTRAP(0x6f)
724 BADTRAP(0x70)
725 BADTRAP(0x71)
726 BADTRAP(0x72)
727 BADTRAP(0x73)
728 BADTRAP(0x74)
729 BADTRAP(0x75)
730 BADTRAP(0x76)
731 BADTRAP(0x77)
732 BADTRAP(0x78)
733 BADTRAP(0x79)
734 BADTRAP(0x7a)
735 BADTRAP(0x7b)
736 BADTRAP(0x7c)
737 BADTRAP(0x7d)
738 BADTRAP(0x7e)
739 BADTRAP(0x7f)
740 SYSCALL(0x80)
741 SYSCALL(0x81)
742 SYSCALL(0x82)
743 SYSCALL(0x83)
744 SYSCALL(0x84)
745 SYSCALL(0x85)
746 SYSCALL(0x86)
747 SYSCALL(0x87)
748 SYSCALL(0x88)
749 SYSCALL(0x89)
750 SYSCALL(0x8a)
751 SYSCALL(0x8b)
752 SYSCALL(0x8c)
753 SYSCALL(0x8d)
754 SYSCALL(0x8e)
755 SYSCALL(0x8f)
756 SYSCALL(0x90)
757 SYSCALL(0x91)
758 SYSCALL(0x92)
759 SYSCALL(0x93)
760 SYSCALL(0x94)
761 SYSCALL(0x95)
762 SYSCALL(0x96)
763 SYSCALL(0x97)
764 SYSCALL(0x98)
765 SYSCALL(0x99)
766 SYSCALL(0x9a)
767 SYSCALL(0x9b)
768 SYSCALL(0x9c)
769 SYSCALL(0x9d)
770 SYSCALL(0x9e)
771 SYSCALL(0x9f)
772 SYSCALL(0xa0)
773 SYSCALL(0xa1)
774 SYSCALL(0xa2)
775 SYSCALL(0xa3)
776 SYSCALL(0xa4)
777 SYSCALL(0xa5)
778 SYSCALL(0xa6)
779 SYSCALL(0xa7)
780 SYSCALL(0xa8)
781 SYSCALL(0xa9)
Note: See TracBrowser for help on using the repository browser.