fixed sparc atomics; added sparc newlib
[akaros.git] / kern / arch / sparc / trap.c
1 #include <arch/arch.h>
2 #include <assert.h>
3 #include <arch/trap.h>
4 #include <string.h>
5 #include <process.h>
6 #include <syscall.h>
7 #include <monitor.h>
8 #include <manager.h>
9 #include <smp.h>
10
11 #ifdef __DEPUTY__
12 #pragma nodeputy
13 #endif
14
15 void
16 idt_init(void)
17 {
18 }
19
20 void
21 sysenter_init(void)
22 {
23 }
24
25 void
26 trap_handled(void)
27 {
28         if(current)
29                 proc_startcore(current,&current->env_tf);
30         else if(core_id() == 0)
31                 manager();
32         else
33                 smp_idle();
34 }
35
36 void
37 (IN_HANDLER print_trapframe)(trapframe_t *tf)
38 {
39         int i, len;
40         char buf[1024];
41
42         len = snprintf(buf,sizeof(buf),"TRAP frame at %p on core %d\n",
43                        tf, core_id());
44
45         for(i = 0; i < 8; i++)
46         {
47                 len += snprintf(buf+len,sizeof(buf)-len,
48                                 "  g%d   0x%08x  o%d   0x%08x"
49                                 "  l%d   0x%08x  i%d 0x%08x\n",
50                                 i,tf->gpr[i],i,tf->gpr[i+8],
51                                 i,tf->gpr[i+16],i,tf->gpr[i+24]);
52         }
53
54         len += snprintf(buf+len,sizeof(buf)-len,
55                         "  psr  0x%08x  pc   0x%08x  npc  0x%08x  wim  0x%08x\n",
56                         tf->psr,tf->pc,tf->npc,tf->wim);
57         len += snprintf(buf+len,sizeof(buf)-len,
58                         "  tbr  0x%08x  y    0x%08x  fsr  0x%08x  far  0x%08x\n",
59                         tf->tbr,tf->y,tf->fault_status,tf->fault_addr);
60         len += snprintf(buf+len,sizeof(buf)-len,
61                         "  timestamp  %21lld\n",tf->timestamp);
62
63         cprintf("%s",buf);
64 }
65
66 #define TRAPNAME_MAX    32
67
68 char*
69 get_trapname(uint8_t tt, char buf[TRAPNAME_MAX])
70 {
71         const char* trapnames[] = {
72                 [0x00] "reset",
73                 [0x01] "instruction access exception",
74                 [0x02] "illegal instruction",
75                 [0x03] "privileged instruction",
76                 [0x04] "floating point disabled",
77                 [0x05] "window overflow",
78                 [0x06] "window underflow",
79                 [0x07] "memory address not aligned",
80                 [0x08] "floating point exception",
81                 [0x09] "data access exception",
82                 [0x20] "register access error",
83                 [0x21] "instruction access error",
84                 [0x24] "coprocessor disabled",
85                 [0x25] "unimplemented FLUSH",
86                 [0x28] "coprocessor exception",
87                 [0x29] "data access error",
88                 [0x2A] "division by zero",
89                 [0x2B] "data store error",
90                 [0x2C] "data MMU miss",
91                 [0x3C] "instruction MMU miss"
92         };
93
94         if(tt >= 0x80)
95                 snprintf(buf,TRAPNAME_MAX,"user trap 0x%02x",tt);
96         else if(tt >= 0x10 && tt < 0x20)
97                 snprintf(buf,TRAPNAME_MAX,"interrupt 0x%x",tt-0x10);
98         else if(tt >= sizeof(trapnames)/sizeof(trapnames[0]) || !trapnames[tt])
99                 snprintf(buf,TRAPNAME_MAX,"(unknown trap 0x%02x)",tt);
100         else
101                 strcpy(buf,trapnames[tt]);
102
103         return buf;
104 }
105
106 void
107 trap(trapframe_t* state, active_message_t* msg,
108      void (*handler)(trapframe_t*,active_message_t*))
109 {
110         // TODO: this will change with multicore processes
111         if(current)
112         {
113                 current->env_tf = *state;
114                 handler(&current->env_tf,msg);
115         }
116         else
117                 handler(state,msg);
118 }
119
120 void
121 handle_active_message(trapframe_t* state, active_message_t* message)
122 {
123         uint32_t src = message->srcid, a0 = message->arg0, a1 = message->arg1;
124         uint32_t a2 = message->arg2;
125         (message->pc)(state,src,a0,a1,a2);
126         env_pop_tf(state);
127 }
128
129 void
130 unhandled_trap(trapframe_t* state)
131 {
132         char buf[TRAPNAME_MAX];
133         uint32_t trap_type = (state->tbr >> 4) & 0xFF;
134         get_trapname(trap_type,buf);
135
136         print_trapframe(state);
137
138         if(state->psr & PSR_PS)
139                 panic("Unhandled trap in kernel!\nTrap type: %s",buf);
140         else
141         {
142                 warn("Unhandled trap in user!\nTrap type: %s",buf);
143                 assert(current);
144                 env_destroy(current);
145                 panic("I shouldn't have gotten here!");
146         }
147 }
148
149 void
150 stack_fucked(trapframe_t* state)
151 {
152         // see if the problem arose when flushing out
153         // windows during handle_trap
154         extern uint32_t tflush;
155         if(state->pc == (uint32_t)&tflush)
156         {
157                 // if so, copy original trap state, except for trap type
158                 uint32_t tbr = state->tbr;
159                 *state = *(trapframe_t*)(state->gpr[14]+64);
160                 state->tbr = tbr;
161         }
162         unhandled_trap(state);
163 }
164
165 void
166 stack_misaligned(trapframe_t* state)
167 {
168         state->tbr = state->tbr & ~0xFFF | 0x070;
169         stack_fucked(state);
170 }
171
172 void
173 stack_pagefault(trapframe_t* state)
174 {
175         state->tbr = state->tbr & ~0xFFF | 0x090;
176         stack_fucked(state);
177 }
178
179 void
180 address_unaligned(trapframe_t* state)
181 {
182         unhandled_trap(state);
183 }
184
185 void
186 access_exception(trapframe_t* state)
187 {
188         unhandled_trap(state);
189 }
190
191 void
192 fp_exception(trapframe_t* state)
193 {
194         unhandled_trap(state);
195 }
196
197 void
198 fp_disabled(trapframe_t* state)
199 {
200         if(state->psr & PSR_PS)
201                 panic("kernel executed an FP instruction!");
202
203         state->psr |= PSR_EF;
204         env_pop_tf(state);
205 }
206
207 void
208 handle_syscall(trapframe_t* state)
209 {
210         uint32_t num = state->gpr[1];
211         uint32_t a1 = state->gpr[8];
212         uint32_t a2 = state->gpr[9];
213         uint32_t a3 = state->gpr[10];
214         uint32_t a4 = state->gpr[11];
215         uint32_t a5 = state->gpr[12];
216
217         // advance pc (else we reexecute the syscall)
218         state->pc = state->npc;
219         state->npc += 4;
220
221         env_push_ancillary_state(current);
222
223         state->gpr[8] = syscall(current,num,a1,a2,a3,a4,a5);
224
225         trap_handled();
226 }
227
228 void
229 flush_windows()
230 {
231         register int foo asm("g1");
232         register int nwin asm("g2");
233         extern int NWINDOWS;
234
235         nwin = NWINDOWS;
236         foo = nwin;
237
238         asm volatile ("1: deccc %0; bne,a 1b; save %%sp,-64,%%sp"
239                       : "=r"(foo) : "r"(foo));
240
241         foo = nwin;
242         asm volatile ("1: deccc %0; bne,a 1b; restore"
243                       : "=r"(foo) : "r"(foo));
244 }
245    
246 void
247 handle_flushw(trapframe_t* state)
248 {
249         flush_windows();
250         state->pc = state->npc;
251         state->npc += 4;
252         env_pop_tf(state);
253 }
254
255 void
256 handle_breakpoint(trapframe_t* state)
257 {
258         // advance the pc
259         state->pc = state->npc;
260         state->npc += 4;
261
262         env_push_ancillary_state(current);
263
264         // run the monitor
265         monitor(state);
266
267         assert(0);
268 }