Fixed cpu_halt on SPARC
[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,%l0
29         btst    PSR_PS,%l0
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         // At this point we may use %l3/4/5/7 as temporary regs
36 1:
37         // is CWP valid?
38         and     %l0,PSR_CWP,%l4 ! %l4 = cwp
39         mov     1,%l7
40         sll     %l7,%l4,%l4     ! %l4 = 1 << cwp
41         mov     %wim,%l3
42         btst    %l3,%l4         ! (%wim & %l4) == 0?
43         be      2f
44          sethi  %hi(spill),%l7
45         jmpl    %lo(spill)+%l7,%l7      !no, spill a window
46          nop
47
48         // At this point we may use %o0-7, %l3/4/5/7 as temporary regs
49         // save the whole user context to a trapframe_t
50
51 2:
52         mov     %l6,%sp
53         mov     %l1,%o1
54         mov     %l2,%o2
55         mov     %l0,%psr                        ! restore condition codes before saving trapframe
56         call    env_save_tf
57          add    %sp,64,%o0
58
59         // enable traps (but not interrupts)
60         or      %l0,PSR_PIL,%g3
61         wr      %g3,0,%psr
62         wr      %g3,PSR_ET,%psr
63
64         // spill all trapper's windows out to the stack.
65         // the 'save' may trap (triggering the spill),
66         // and if the stack is corrupted, the process may die
67         mov     %sp,%g4
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         mov     %g4,%sp 
75         wr      %g3,PSR_ET,%psr
76
77         // call the handler and pass in the tf and handler address
78         call    %l5
79          add    %sp,64,%o0
80
81         // fallthrough to env_pop_tf, which is right below this function
82         add     %sp,64,%o0
83
84         // this routine only works for returning to userspace.
85         // right now, there's no mechanism to resume kernel operation after
86         // a fault
87         .global env_pop_tf
88 env_pop_tf:
89         mov     %psr,%o1
90         wr      %o1,PSR_ET,%psr
91
92         // CWP = 0 (therefore 1 after rett), so set window 2 invalid
93         mov     1<<2,%wim
94         ld      [%o0+128],%o1
95         mov     %o0,%g2
96         andn    %o1,PSR_CWP,%o1
97         mov     %o1,%psr
98         nop; nop; nop
99         mov     %g2,%o0
100
101 4:      // restore user context
102         restore
103         ldd     [%g2+32],%o0
104         ldd     [%g2+40],%o2
105         ldd     [%g2+48],%o4
106         ldd     [%g2+56],%o6
107         ldd     [%g2+64],%l0
108         ldd     [%g2+72],%l2
109         ldd     [%g2+80],%l4
110         ldd     [%g2+88],%l6
111         ldd     [%g2+96],%i0
112         ldd     [%g2+104],%i2
113         ldd     [%g2+112],%i4
114         ldd     [%g2+120],%i6
115         save
116
117         ld      [%o0+ 4],%g1
118         ldd     [%o0+ 8],%g2
119         ldd     [%o0+16],%g4
120         ldd     [%o0+24],%g6
121
122         ld      [%o0+132],%l1
123         ld      [%o0+136],%l2
124         ld      [%o0+148],%l5
125         mov     %l5,%y
126         ld      [%o0+152],%l5
127         mov     %l5,%asr13
128
129         jmp     %l1
130         rett    %l2
131
132 // void env_save_tf(trapframe_t* tf, uint32_t trap_pc, uint32_t trap_npc)
133         .global env_save_tf
134 env_save_tf:
135
136         mov     %psr,%o4
137         st      %o4,[%o0+128]
138         st      %o1,[%o0+132]
139         st      %o2,[%o0+136]
140         mov     %wim,%o4
141         st      %o4,[%o0+140]
142         mov     %tbr,%o4
143         mov     %y,%o5
144         std     %o4,[%o0+144]
145         mov     %asr13,%o5
146         st      %o5,[%o0+152]
147
148         set     0x300,%o4
149         set     0x400,%o5
150         lda     [%o4] 4,%o4
151         lda     [%o5] 4,%o5
152         std     %o4,[%o0+160]
153         lda     [%g0] 2,%o4
154         mov     4,%o5
155         lda     [%o5] 2,%o5
156         std     %o4,[%o0+168]
157
158         # try to read out the faulting insn (in no-fault mode)
159         andn    %o1,3,%o1
160         lda     [%g0] 4,%o2
161         or      %o2,2,%o3
162         sta     %o3,[%g0] 4
163         mov     -1,%o3
164         ld      [%o1],%o3
165         st      %o3,[%o0+156]
166         sta     %o2,[%g0] 4
167         mov     0x300,%o4
168         lda     [%o4] 4,%g0
169
170         std     %g0,[%o0+ 0]
171         std     %g2,[%o0+ 8]
172         std     %g4,[%o0+16]
173         std     %g6,[%o0+24]
174
175         mov     %o0,%g2
176
177         restore
178         std     %o0,[%g2+32]
179         std     %o2,[%g2+40]
180         std     %o4,[%g2+48]
181         std     %o6,[%g2+56]
182         std     %l0,[%g2+64]
183         std     %l2,[%g2+72]
184         std     %l4,[%g2+80]
185         std     %l6,[%g2+88]
186         std     %i0,[%g2+96]
187         std     %i2,[%g2+104]
188         std     %i4,[%g2+112]
189         std     %i6,[%g2+120]
190         save
191
192         retl
193          nop
194
195         .global handle_perfctr
196 handle_perfctr:
197         andn    %i0,7,%i1
198         lda     [%i1] 2,%i0
199         add     %i1,4,%i1
200         lda     [%i1] 2,%i1
201         jmp     %l2
202          rett   %l2+4
203
204         // we make cpu_halt a linker symbol so we know if we were halted.
205         // if we were halted, we should return to PC+4, not PC.
206         .global cpu_halt
207 cpu_halt:
208         ba,a cpu_halt
209         retl
210          nop