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

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

Fixed moving from/to invalid window and register window corruption in
preemptible_trap.

  • Property mode set to 100644
File size: 13.4 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 std %l0, [%sp + 0]
214 std %l2, [%sp + 8]
215 std %l4, [%sp + 16]
216 std %l6, [%sp + 24]
217 std %i0, [%sp + 32]
218 std %i2, [%sp + 40]
219 std %i4, [%sp + 48]
220 std %i6, [%sp + 56]
221 b 3f
222 nop
223
2241: /* uspace: */
225 /* set uspace window mark */
226 mov %psr, %g7
227 and %g7, 0x7, %g7
228 inc %g7
229
230 /* dump registers to uwb */
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
2423: /* back to where we should be */
243 mov %g5, %l5
244 mov %g6, %l6
245 mov %g7, %l7
246 restore
247
248 /* set new value of window */
249 mov %l3,%wim
250 nop; nop; nop
251
252 /* go home */
253 jmp %l1
254 rett %l2
255
256window_underflow_trap:
257 /* rotate WIM on bit LEFT, we have 8 windows */
258 mov %wim,%l3
259 srl %l3,7,%l4
260 sll %l3,1,%l3
261 or %l3,%l4,%l3
262 and %l3, 0xff,%l3
263
264 /* disable WIM traps */
265 mov %g0,%wim
266 nop; nop; nop
267
268 /* Check whether previous mode was usermode */
269 mov %psr, %l0
270 and %l0, (1 << 6), %l0
271 cmp %l0, 0
272 beq 1f
273 nop
274
275 /* load registers from stack */
276 restore
277 restore
278 /* Save invalid window data */
279 mov %l5, %g5 ! kernel stack pointer
280 mov %l6, %g6 ! kernel wbuf
281 mov %l7, %g7
282
283 /* we should check whether window needs to be saved
284 * to kernel stack or uwb
285 */
286 cmp %g7, 0
287 bne 3f
288 nop
289
290 ldd [%sp + 0], %l0
291 ldd [%sp + 8], %l2
292 ldd [%sp + 16], %l4
293 ldd [%sp + 24], %l6
294 ldd [%sp + 32], %i0
295 ldd [%sp + 40], %i2
296 ldd [%sp + 48], %i4
297 ldd [%sp + 56], %i6
298 b 2f
299 nop
300
301 /* load registers from uwb */
3021: restore
303 restore
304 /* Save invalid window data */
305 mov %l5, %g5 ! kernel stack pointer
306 mov %l6, %g6 ! kernel wbuf
307 mov %l7, %g7
3083: 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 %psr, %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
373 /* Set secondary invalid window mark */
374 add %g7, 1, %l7
375
3765: /* Set up stack frame */
377 sub %sp, 112, %sp
378
379 /* Save trap data on stack */
380 mov %psr, %l0
381 st %l1, [%fp - 4]
382 st %l2, [%fp - 8]
383 st %l0, [%fp - 12]
384
385 /* Enable traps */
386 mov %psr, %l0
387 or %l0, (1 << 5), %l0
388 mov %l0, %psr
389 nop
390 nop
391 nop
392 nop
393
394 /* Jump to actual subroutine */
395 call %o2
396 sub %fp, 12, %o1
397
398 /* Return from handler */
399 ld [%fp - 4], %l1
400 ld [%fp - 8], %l2
401 ld [%fp - 12], %l0
402 mov %l0, %psr
403 nop
404 nop
405 nop
406 nop
407 nop
408
409 /* If trap originated from uspace, clear uspace window mark */
410 if_from_kernel 6f
411 switch_to_invalid %g5, %g6
412 clr %l7
413 switch_back %g5, %g6
414
4156: jmp %l1
416 rett %l2
417
418interrupt_trap:
419 mov %psr, %l0
420
421 /* Check whether previous mode was usermode */
422 and %l0, (1 << 6), %l0
423 cmp %l0, 0
424 bne 1f
425 nop
426
427 /* Set up stack */
428 set kernel_sp, %l4
429 ld [%l4], %sp
430 mov %sp, %fp
4311: sub %sp, 112, %sp
432
433 /* Save trap data on stack */
434 mov %psr, %l0
435 st %l1, [%fp - 4]
436 st %l2, [%fp - 8]
437 st %l0, [%fp - 12]
438
439 /* Enable traps */
440 mov %psr, %l0
441 or %l0, (1 << 5), %l0
442 mov %l0, %psr
443 nop
444 nop
445 nop
446 nop
447
448 /* Jump to actual subroutine */
449 mov %g2, %o0
450 call exc_dispatch
451 sub %fp, 12, %o1
452
453 /* Return from handler */
454 ld [%fp - 4], %l1
455 ld [%fp - 8], %l2
456 ld [%fp - 12], %l0
457 mov %l0, %psr
458 nop
459 nop
460 nop
461 nop
462 nop
463 jmp %l1
464 rett %l2
465
466syscall_trap:
467 /* Check whether we landed in invalid window */
468 get_wim_number %g6
469 get_cwp %g7
470 cmp %g6, %g7
471 bne 4f
472 nop
473
474 /* We are in invalid window. Check whether previous mode was usermode */
475 if_from_kernel 3f
476
477 /* Kernel stack pointer is at %l5, uwb is at %l6 */
478 inline_save_uspace %l6
4793: inline_save_kernel
480
4814: /* Check whether previous mode was usermode */
482 if_from_kernel 5f
483
484 /* Load kernel stack pointer from invalid window */
485 switch_to_invalid %g5, %g6
486 restore
487 mov %l5, %g7 ! stack pointer
488 switch_back %g5, %g6
489 mov %g7, %sp
490 mov %sp, %fp
4915: sub %sp, 112, %sp
492
493 /* Save trap data on stack */
494 mov %psr, %l0
495 st %l1, [%fp - 4]
496 st %l2, [%fp - 8]
497 st %l0, [%fp - 12]
498
499 /* Enable traps */
500 mov %psr, %l0
501 or %l0, (1 << 5), %l0
502 mov %l0, %psr
503 nop
504 nop
505 nop
506 nop
507
508 /* Jump to actual subroutine */
509 sub %o0, 0x80, %o0
510 st %o0, [ %sp + 92 ]
511 mov %i0, %o0
512 mov %i1, %o1
513 mov %i2, %o2
514 mov %i3, %o3
515 mov %i4, %o4
516 call syscall
517 mov %i5, %o5
518
519 /* Return from handler */
520 ld [%fp - 4], %l1
521 ld [%fp - 8], %l2
522 ld [%fp - 12], %l0
523 mov %l0, %psr
524 nop
525 nop
526 nop
527 nop
528 nop
529 jmp %l2
530 rett %l2 + 4
531
532#define STRAP(_vector, _handler) \
533 .org trap_table + _vector * TRAP_ENTRY_SIZE; \
534 mov %psr, %l0 ; \
535 sethi %hi(_handler), %l4 ; \
536 jmp %lo(_handler) + %l4 ; \
537 nop
538
539#define TRAP(_vector, _handler) \
540 .org trap_table + _vector * TRAP_ENTRY_SIZE; \
541 set _vector, %o0 ; \
542 sethi %hi(_handler), %o2 ; \
543 b preemptible_trap ; \
544 or %o2, %lo(_handler), %o2 ;
545
546#define SYSCALL(_vector) \
547 .org trap_table + _vector * TRAP_ENTRY_SIZE; \
548 set _vector, %o0 ; \
549 b syscall_trap ; \
550 nop ;
551
552#define INTERRUPT(_vector, _priority) \
553 .org trap_table + _vector * TRAP_ENTRY_SIZE; \
554 mov %psr, %l0 ; \
555 mov _priority, %g2 ; \
556 b interrupt_trap ; \
557 nop ;
558
559#define BADTRAP(_vector) \
560 .org trap_table + _vector * TRAP_ENTRY_SIZE ; \
561 ta 0 ;
562
563.align TRAP_TABLE_SIZE
564trap_table:
565 STRAP(0x0, reset_trap)
566 TRAP(0x1, instruction_access_exception)
567 TRAP(0x2, illegal_instruction)
568 TRAP(0x3, privileged_instruction)
569 TRAP(0x4, fp_disabled)
570 STRAP(0x5, window_overflow_trap)
571 STRAP(0x6, window_underflow_trap)
572 TRAP(0x7, mem_address_not_aligned)
573 TRAP(0x8, fp_exception)
574 TRAP(0x9, data_access_exception)
575 TRAP(0xa, tag_overflow)
576 BADTRAP(0xb)
577 BADTRAP(0xc)
578 BADTRAP(0xd)
579 BADTRAP(0xe)
580 BADTRAP(0xf)
581 BADTRAP(0x10)
582 INTERRUPT(0x11, 1)
583 INTERRUPT(0x12, 2)
584 INTERRUPT(0x13, 3)
585 INTERRUPT(0x14, 4)
586 INTERRUPT(0x15, 5)
587 INTERRUPT(0x16, 6)
588 INTERRUPT(0x17, 7)
589 INTERRUPT(0x18, 8)
590 INTERRUPT(0x19, 9)
591 INTERRUPT(0x1a, 10)
592 INTERRUPT(0x1b, 11)
593 INTERRUPT(0x1c, 12)
594 INTERRUPT(0x1d, 13)
595 INTERRUPT(0x1e, 14)
596 INTERRUPT(0x1f, 15)
597 TRAP(0x21, instruction_access_error)
598 BADTRAP(0x22)
599 BADTRAP(0x23)
600 BADTRAP(0x24)
601 BADTRAP(0x25)
602 BADTRAP(0x26)
603 BADTRAP(0x27)
604 BADTRAP(0x28)
605 TRAP(0x29, data_access_error)
606 TRAP(0x2a, division_by_zero)
607 TRAP(0x2b, data_store_error)
608 TRAP(0x2c, data_access_mmu_miss)
609 BADTRAP(0x2d)
610 BADTRAP(0x2e)
611 BADTRAP(0x2f)
612 BADTRAP(0x30)
613 BADTRAP(0x31)
614 BADTRAP(0x32)
615 BADTRAP(0x33)
616 BADTRAP(0x34)
617 BADTRAP(0x35)
618 BADTRAP(0x36)
619 BADTRAP(0x37)
620 BADTRAP(0x38)
621 BADTRAP(0x39)
622 BADTRAP(0x3a)
623 BADTRAP(0x3b)
624 BADTRAP(0x3c)
625 BADTRAP(0x3d)
626 BADTRAP(0x3e)
627 BADTRAP(0x3f)
628 BADTRAP(0x40)
629 BADTRAP(0x41)
630 BADTRAP(0x42)
631 BADTRAP(0x43)
632 BADTRAP(0x44)
633 BADTRAP(0x45)
634 BADTRAP(0x46)
635 BADTRAP(0x47)
636 BADTRAP(0x48)
637 BADTRAP(0x49)
638 BADTRAP(0x4a)
639 BADTRAP(0x4b)
640 BADTRAP(0x4c)
641 BADTRAP(0x4d)
642 BADTRAP(0x4e)
643 BADTRAP(0x4f)
644 BADTRAP(0x50)
645 BADTRAP(0x51)
646 BADTRAP(0x52)
647 BADTRAP(0x53)
648 BADTRAP(0x54)
649 BADTRAP(0x55)
650 BADTRAP(0x56)
651 BADTRAP(0x57)
652 BADTRAP(0x58)
653 BADTRAP(0x59)
654 BADTRAP(0x5a)
655 BADTRAP(0x5b)
656 BADTRAP(0x5c)
657 BADTRAP(0x5d)
658 BADTRAP(0x5e)
659 BADTRAP(0x5f)
660 BADTRAP(0x60)
661 BADTRAP(0x61)
662 BADTRAP(0x62)
663 BADTRAP(0x63)
664 BADTRAP(0x64)
665 BADTRAP(0x65)
666 BADTRAP(0x66)
667 BADTRAP(0x67)
668 BADTRAP(0x68)
669 BADTRAP(0x69)
670 BADTRAP(0x6a)
671 BADTRAP(0x6b)
672 BADTRAP(0x6c)
673 BADTRAP(0x6d)
674 BADTRAP(0x6e)
675 BADTRAP(0x6f)
676 BADTRAP(0x70)
677 BADTRAP(0x71)
678 BADTRAP(0x72)
679 BADTRAP(0x73)
680 BADTRAP(0x74)
681 BADTRAP(0x75)
682 BADTRAP(0x76)
683 BADTRAP(0x77)
684 BADTRAP(0x78)
685 BADTRAP(0x79)
686 BADTRAP(0x7a)
687 BADTRAP(0x7b)
688 BADTRAP(0x7c)
689 BADTRAP(0x7d)
690 BADTRAP(0x7e)
691 BADTRAP(0x7f)
692 SYSCALL(0x80)
693 SYSCALL(0x81)
694 SYSCALL(0x82)
695 SYSCALL(0x83)
696 SYSCALL(0x84)
697 SYSCALL(0x85)
698 SYSCALL(0x86)
699 SYSCALL(0x87)
700 SYSCALL(0x88)
701 SYSCALL(0x89)
702 SYSCALL(0x8a)
703 SYSCALL(0x8b)
704 SYSCALL(0x8c)
705 SYSCALL(0x8d)
706 SYSCALL(0x8e)
707 SYSCALL(0x8f)
708 SYSCALL(0x90)
709 SYSCALL(0x91)
710 SYSCALL(0x92)
711 SYSCALL(0x93)
712 SYSCALL(0x94)
713 SYSCALL(0x95)
714 SYSCALL(0x96)
715 SYSCALL(0x97)
716 SYSCALL(0x98)
717 SYSCALL(0x99)
718 SYSCALL(0x9a)
719 SYSCALL(0x9b)
720 SYSCALL(0x9c)
721 SYSCALL(0x9d)
722 SYSCALL(0x9e)
723 SYSCALL(0x9f)
724 SYSCALL(0xa0)
725 SYSCALL(0xa1)
726 SYSCALL(0xa2)
727 SYSCALL(0xa3)
728 SYSCALL(0xa4)
729 SYSCALL(0xa5)
730 SYSCALL(0xa6)
731 SYSCALL(0xa7)
732 SYSCALL(0xa8)
733 SYSCALL(0xa9)
Note: See TracBrowser for help on using the repository browser.