Exposed SPARC iobus to userspace
[akaros.git] / kern / arch / sparc / trap_entry.S
1 #include <arch/sparc.h>
2 #include <arch/trap.h>
3 #include <arch/mmu.h>
4 #include <arch/trap_table.h>
5 #include <ros/memlayout.h>
6
7         .section        ".text"!,#alloc,#execinstr,#progbits
8         .align          4
9
10         .global tflush
11
12         .global handle_trap
13 handle_trap:
14
15         // At this point, %l1 = pc, %l2 = npc, and %l0/3/4/5
16         // might contain an active message.  so we only get %l6/%l7
17
18         // calculate stack pointer (-64 is space for window spill).
19         // sp = bootstacktop - core_id*KSTKSIZE - 64 - sizeof(trapframe_t).
20         // should you change this, make sure to change stack_fucked()
21         set     bootstacktop-64-SIZEOF_TRAPFRAME_T,%l6
22         mov     CORE_ID_REG,%l7
23         sll     %l7,KSTKSHIFT,%l7
24         sub     %l6,%l7,%l6
25
26         // see if trap came from kernel; if so, use that stack
27         // also preserve the psr, since we'll screw with the condition codes
28         mov     %psr,%l7
29         btst    PSR_PS,%l7
30         bne,a   1f
31          sub    %fp,64+SIZEOF_TRAPFRAME_T,%l6
32
33         // here is where we might do something with an active message
34
35 1:      mov     %l7,%l0
36         // At this point we may use %l3/4/5/7 as temporary regs
37
38         // is CWP valid?
39         and     %l0,PSR_CWP,%l4 ! %l4 = cwp
40         mov     1,%l7
41         sll     %l7,%l4,%l4     ! %l4 = 1 << cwp
42         mov     %wim,%l3
43         btst    %l3,%l4         ! (%wim & %l4) == 0?
44         be      2f
45          sethi  %hi(spill),%l7
46         jmpl    %lo(spill)+%l7,%l7      !no, spill a window
47          nop
48
49
50         // At this point we may use %o0-7, %l3/4/5/7 as temporary regs
51         // save the whole user context to a trapframe_t
52
53 2:      mov     %l0,%psr
54         mov     %l6,%sp
55         mov     %l1,%o1
56         mov     %l2,%o2
57         call    env_save_tf
58          add    %sp,64,%o0
59
60         // enable traps (but not interrupts)
61         or      %l0,PSR_PIL,%l3
62         wr      %l3,0,%psr
63         wr      %l3,PSR_ET,%psr
64
65         // spill all trapper's windows out to the stack.
66         // the 'save' may trap (triggering the spill),
67         // and if the stack is corrupted, the process may die
68         set     NWINDOWS,%g1
69         ld      [%g1],%g1
70         sub     %g1,1,%g2
71 5:      deccc   %g2
72         bne,a   5b
73 tflush:  save   %sp,0,%sp
74
75         // get our old cwp back (restore should NOT trap)
76         sub     %g1,1,%g2
77 6:      deccc   %g2
78         bne,a   6b
79          restore
80
81         // restore interrupt level
82         wr      %l0,PSR_ET,%psr
83
84         // call the handler and pass in the tf, message, and handler addr
85         add     %sp,64,%o0
86         call    trap
87          mov    %l5,%o1
88
89         // should never get here
90         unimp
91
92 // void env_save_tf(trapframe_t* tf, uint32_t trap_pc, uint32_t trap_npc)
93         .global env_save_tf
94 env_save_tf:
95
96         mov     %psr,%o4
97         st      %o4,[%o0+128]
98         st      %o1,[%o0+132]
99         st      %o2,[%o0+136]
100         mov     %wim,%o4
101         st      %o4,[%o0+140]
102         mov     %tbr,%o4
103         mov     %y,%o5
104         std     %o4,[%o0+144]
105         mov     %asr13,%o5
106         st      %o5,[%o0+152]
107
108         set     0x300,%o4
109         set     0x400,%o5
110         lda     [%o4] 4,%o4
111         lda     [%o5] 4,%o5
112         std     %o4,[%o0+160]
113         lda     [%g0] 2,%o4
114         mov     4,%o5
115         lda     [%o5] 2,%o5
116         std     %o4,[%o0+168]
117
118         std     %g0,[%o0+ 0]
119         std     %g2,[%o0+ 8]
120         std     %g4,[%o0+16]
121         std     %g6,[%o0+24]
122
123         mov     %o0,%g2
124
125         restore
126         std     %o0,[%g2+32]
127         std     %o2,[%g2+40]
128         std     %o4,[%g2+48]
129         std     %o6,[%g2+56]
130         std     %l0,[%g2+64]
131         std     %l2,[%g2+72]
132         std     %l4,[%g2+80]
133         std     %l6,[%g2+88]
134         std     %i0,[%g2+96]
135         std     %i2,[%g2+104]
136         std     %i4,[%g2+112]
137         std     %i6,[%g2+120]
138         save
139
140         retl
141          nop
142
143         .global env_pop_tf
144 env_pop_tf:
145
146         mov     %psr,%o1
147         btst    PSR_PS,%o1      ! return to kernel or user?
148         bne     1f
149
150         // we're returning to userspace.
151         wr      %o1,PSR_ET,%psr
152
153         // CWP = 0 (therefore 1 after rett), so set window 2 invalid
154         mov     0,%wim
155         mov     %o0,%g2
156         mov     %psr,%g1
157         andn    %g1,PSR_CWP,%g1
158         mov     %g1,%psr
159         mov     1<<2,%wim; nop
160         // time to restore user context and rett
161         ba      4f
162          mov    %g2,%o0
163
164 1:
165         // this general version of the code works for kernel and user,
166         // but it is slow because it spills the windows.
167
168         // first disable interrupts.
169         // since wrpsr/rdpsr is interruptible, all interrupt handlers
170         // must restore the psr to its interrupt-time value
171         or      %o1,PSR_PIL,%o2
172         wr      %o2,%psr
173
174         // spill all kernel windows to the stack
175         set     NWINDOWS,%g1
176         ld      [%g1],%g1
177         sub     %g1,1,%g2
178 5:      deccc   %g2
179         bne,a   5b
180          save   %sp,0,%sp
181
182         // get our old cwp back (restore should NOT trap)
183         sub     %g1,1,%g2
184 6:      deccc   %g2
185         bne,a   6b
186          restore
187         
188         // disable traps, and restore interrupt level
189         wr      %o2,PSR_ET,%psr
190         wr      %o1,PSR_ET,%psr
191
192         // if we did this right (and didn't get an NMI!),
193         // then (CWP+1) % NWINDOWS should be invalid.  fix that.
194         save
195         mov     %i0,%o0
196         mov     %o0,%g2
197
198 4:      // restore user context
199         restore
200         ldd     [%g2+32],%o0
201         ldd     [%g2+40],%o2
202         ldd     [%g2+48],%o4
203         ldd     [%g2+56],%o6
204         ldd     [%g2+64],%l0
205         ldd     [%g2+72],%l2
206         ldd     [%g2+80],%l4
207         ldd     [%g2+88],%l6
208         ldd     [%g2+96],%i0
209         ldd     [%g2+104],%i2
210         ldd     [%g2+112],%i4
211         ldd     [%g2+120],%i6
212         save
213
214         ld      [%o0+ 4],%g1
215         ldd     [%o0+ 8],%g2
216         ldd     [%o0+16],%g4
217         ldd     [%o0+24],%g6
218
219         ldd     [%o0+128],%l0
220         mov     %psr,%l2
221         and     %l2,PSR_CWP,%l2
222         andn    %l0,PSR_CWP,%l0
223         wr      %l2,%l0,%psr
224
225         ld      [%o0+136],%l2
226         ld      [%o0+148],%l5
227         mov     %l5,%y
228         ld      [%o0+152],%l5
229         mov %l5,%asr13
230
231         jmp     %l1
232         rett    %l2
233
234         .global handle_perfctr
235 handle_perfctr:
236         andn    %i0,7,%i1
237         lda     [%i1] 2,%i0
238         add     %i1,4,%i1
239         lda     [%i1] 2,%i1
240         jmp     %l2
241          rett   %l2+4