1 /* arch/sparc/kernel/entry.S: Sparc trap low-level entry points. 2 * 3 * Sparc traps are so ugly, this code is going to go through a lot 4 * of changes as I find out more interesting things. See head.S for 5 * the trap table and how it works, this will show you how we get 6 * to these routines. 7 * 8 * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) 9 */ 10
11 #include <asm/head.h>
12
13 .text
14 .align 4
15
16 /* Default trap handler */ 17 .globl my_trap_handler
18 my_trap_handler:
19 rd %wim, %l4
20 or %g0, 0x1, %l5
21 sll %l5, %l0, %l5
22 cmp %l4, %l5 ! are we in the invalid register?
23
24 #if 0 /* work in progress */ 25 be wash_trap_win
26 #endif 27
28 nop
29 or %%g0, %l3, %o0
30 call _do_hw_interrupt
31 or %%g0, %%g0, %o1
32 wr %l0, 0x20, %psr ! re-enable traps and reset the condition codes
33 nop
34 nop
35 nop ! click our heels three times, "no place like home"
36 jmp %l1
37 rett %l2
38
39 /* This is cheese and only works reliably if not coming from userland. */ 40 .globl fill_window_entry
41 fill_window_entry:
42 wr %g0, 0, %wim ! let us into the invalid window
43 ! without inducing another trap
44 restore
45 nop
46 nop ! no guarentees until 3 insns later
47 restore
48 restore %g0, 1, %l1
49 rd %psr, %l0
50 sll %l1, %l0, %l0
51 wr %l0, 0, %wim
52 save %g0, %g0, %g0
53
54 /* load up the window */ 55 ldd [%sp], %l0
56 ldd [%sp + 8], %l2
57 ldd [%sp + 16], %l4
58 ldd [%sp + 24], %l6
59 ldd [%sp + 32], %i0
60 ldd [%sp + 40], %i2
61 ldd [%sp + 48], %i4
62 ldd [%sp + 56], %i6
63
64 save %g0, %g0, %g0
65 save %g0, %g0, %g0
66 jmp %l1
67 rett %l2
68
69 /* Cheese number two, give this a bad stack pointer and get scared. */ 70 .globl spill_window_entry
71 spill_window_entry:
72 save %g0, %g0, %g0 ! save into next 'valid' window
73 std %l0, [%sp] ! acquire some scratch registers
74 rd %psr, %l0
75 or %g0, 0x1, %l1
76 sll %l1, %l0, %l0
77 wr %l0, 0, %wim ! make window we are saving the 'invalid' one
78 std %l2, [%sp + 8]
79 std %l4, [%sp + 16]
80 std %l6, [%sp + 24]
81 std %i0, [%sp + 32]
82 std %i2, [%sp + 40]
83 std %i4, [%sp + 48]
84 std %i6, [%sp + 56]
85 restore ! restore back into the window we want to use
86 jmp %l1
87 rett %l2 ! return from spill handler
88
89
90 /* This is where most generic traps enter, the registers should be: 91 %l0 == %psr 92 %l1 == %pc 93 %l2 == %npc 94 %l4 == trap_type 95 %l7 == trap_handler 96 */ 97
98 trap_entry:
99 srl %l0, 0x6, %l5 ! shift over to previous priv bit
100 andcc %l5, 0x1, %g0 ! 1 == from kernel 0 == from user
101 bz 2f
102 nop ! we dont handle users yet ;-(
103
104 or %g0, 0x1, %l5
105 sll %l5, %l0, %l5 ! a trick, only least 5 bits are
106 ! significant in a register shift
107 ! count.
108 rd %wim, %l6
109 andcc %l6, %l5, %g0 ! if (((1<<CWP)&(%wim))==1) we are
110 ! in an 'invalid' window
111 bz,a 3f
112 sub %fp, C_STACK+80, %sp ! cool, just set stack and go
113 ! this window is valid to use
114
115 /* we aparently need to clean the trap window, inline this for speed */ 116 or %g0, %g7, %l7 ! set up g6 and g7 for scratch
117 or %g0, %g6, %l6
118
119 save %g0, %g0, %g0 ! enter next window after the invalid one
120 std %l0, [%sp] ! and store it on the stack for later
121 std %l2, [%sp + 8] ! retrieval
122 std %l4, [%sp + 16]
123 std %l6, [%sp + 24]
124 std %i0, [%sp + 32]
125 std %i2, [%sp + 40]
126 std %i4, [%sp + 48]
127 std %i6, [%sp + 56]
128
129 rd %psr, %g7 ! read the current window pointer
130 or %g0, 0x1, %g6 ! and mask it over into the %wim
131 sll %g6, %g7, %g6 ! value
132 wr %g6, 0, %wim ! make this window the now 'invalid' one
133 and %g6, 31, %g6
134 restore ! re-enter the trap window, it is ok now
135
136 or %g0, %l6, %g6 ! bring back in the old temporaries
137 or %g0, %l7, %g7 ! to the locals they were in
138
139 b 3f
140 sub %fp, C_STACK+80, %sp ! fix stack pointer
141
142
143 /* for now if we get a from-user trap you lose... */ 144
145 .data
146 .align 4
147
148 tfu_youlose: .asciz "trap from userland, you lose...\n"
149
150 .align 4
151 .text
152
153 2:
154 sethi %hi(tfu_youlose), %o0
155 sethi %hi(prom_printf), %o1
156 ld [%o1 + %lo(prom_printf)], %o1
157 call %o1
158 or %o0, %lo(tfu_youlose), %o0
159
160 sethi %hi(prom_halt), %o1
161 ld [%o1 + %lo(prom_halt)], %o1
162 call %o1 ! its over
163 nop
164
165 /* nop and just return, here is where I would jump to the 166 * appropriate handler. 167 */ 168
169 jmp %1
170 rett %l2
171 nop