Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * arch/alpha/kernel/entry.S | |
3 | * | |
4 | * Kernel entry-points. | |
5 | */ | |
6 | ||
e2d5df93 | 7 | #include <asm/asm-offsets.h> |
1da177e4 LT |
8 | #include <asm/thread_info.h> |
9 | #include <asm/pal.h> | |
10 | #include <asm/errno.h> | |
11 | #include <asm/unistd.h> | |
12 | ||
13 | .text | |
14 | .set noat | |
231b0bed | 15 | .cfi_sections .debug_frame |
1da177e4 LT |
16 | |
17 | /* Stack offsets. */ | |
18 | #define SP_OFF 184 | |
19 | #define SWITCH_STACK_SIZE 320 | |
20 | ||
231b0bed RH |
21 | .macro CFI_START_OSF_FRAME func |
22 | .align 4 | |
23 | .globl \func | |
24 | .type \func,@function | |
25 | \func: | |
26 | .cfi_startproc simple | |
27 | .cfi_return_column 64 | |
28 | .cfi_def_cfa $sp, 48 | |
29 | .cfi_rel_offset 64, 8 | |
30 | .cfi_rel_offset $gp, 16 | |
31 | .cfi_rel_offset $16, 24 | |
32 | .cfi_rel_offset $17, 32 | |
33 | .cfi_rel_offset $18, 40 | |
34 | .endm | |
35 | ||
36 | .macro CFI_END_OSF_FRAME func | |
37 | .cfi_endproc | |
38 | .size \func, . - \func | |
39 | .endm | |
40 | ||
1da177e4 LT |
41 | /* |
42 | * This defines the normal kernel pt-regs layout. | |
43 | * | |
44 | * regs 9-15 preserved by C code | |
45 | * regs 16-18 saved by PAL-code | |
46 | * regs 29-30 saved and set up by PAL-code | |
47 | * JRP - Save regs 16-18 in a special area of the stack, so that | |
48 | * the palcode-provided values are available to the signal handler. | |
49 | */ | |
50 | ||
231b0bed RH |
51 | .macro SAVE_ALL |
52 | subq $sp, SP_OFF, $sp | |
53 | .cfi_adjust_cfa_offset SP_OFF | |
54 | stq $0, 0($sp) | |
55 | stq $1, 8($sp) | |
56 | stq $2, 16($sp) | |
57 | stq $3, 24($sp) | |
58 | stq $4, 32($sp) | |
59 | stq $28, 144($sp) | |
60 | .cfi_rel_offset $0, 0 | |
61 | .cfi_rel_offset $1, 8 | |
62 | .cfi_rel_offset $2, 16 | |
63 | .cfi_rel_offset $3, 24 | |
64 | .cfi_rel_offset $4, 32 | |
65 | .cfi_rel_offset $28, 144 | |
66 | lda $2, alpha_mv | |
67 | stq $5, 40($sp) | |
68 | stq $6, 48($sp) | |
69 | stq $7, 56($sp) | |
70 | stq $8, 64($sp) | |
71 | stq $19, 72($sp) | |
72 | stq $20, 80($sp) | |
73 | stq $21, 88($sp) | |
74 | ldq $2, HAE_CACHE($2) | |
75 | stq $22, 96($sp) | |
76 | stq $23, 104($sp) | |
77 | stq $24, 112($sp) | |
78 | stq $25, 120($sp) | |
79 | stq $26, 128($sp) | |
80 | stq $27, 136($sp) | |
81 | stq $2, 152($sp) | |
82 | stq $16, 160($sp) | |
83 | stq $17, 168($sp) | |
1da177e4 | 84 | stq $18, 176($sp) |
231b0bed RH |
85 | .cfi_rel_offset $5, 40 |
86 | .cfi_rel_offset $6, 48 | |
87 | .cfi_rel_offset $7, 56 | |
88 | .cfi_rel_offset $8, 64 | |
89 | .cfi_rel_offset $19, 72 | |
90 | .cfi_rel_offset $20, 80 | |
91 | .cfi_rel_offset $21, 88 | |
92 | .cfi_rel_offset $22, 96 | |
93 | .cfi_rel_offset $23, 104 | |
94 | .cfi_rel_offset $24, 112 | |
95 | .cfi_rel_offset $25, 120 | |
96 | .cfi_rel_offset $26, 128 | |
97 | .cfi_rel_offset $27, 136 | |
98 | .endm | |
99 | ||
100 | .macro RESTORE_ALL | |
101 | lda $19, alpha_mv | |
102 | ldq $0, 0($sp) | |
103 | ldq $1, 8($sp) | |
104 | ldq $2, 16($sp) | |
105 | ldq $3, 24($sp) | |
106 | ldq $21, 152($sp) | |
107 | ldq $20, HAE_CACHE($19) | |
108 | ldq $4, 32($sp) | |
109 | ldq $5, 40($sp) | |
110 | ldq $6, 48($sp) | |
111 | ldq $7, 56($sp) | |
112 | subq $20, $21, $20 | |
113 | ldq $8, 64($sp) | |
114 | beq $20, 99f | |
115 | ldq $20, HAE_REG($19) | |
116 | stq $21, HAE_CACHE($19) | |
117 | stq $21, 0($20) | |
118 | 99: ldq $19, 72($sp) | |
119 | ldq $20, 80($sp) | |
120 | ldq $21, 88($sp) | |
121 | ldq $22, 96($sp) | |
122 | ldq $23, 104($sp) | |
123 | ldq $24, 112($sp) | |
124 | ldq $25, 120($sp) | |
125 | ldq $26, 128($sp) | |
126 | ldq $27, 136($sp) | |
127 | ldq $28, 144($sp) | |
1da177e4 | 128 | addq $sp, SP_OFF, $sp |
231b0bed RH |
129 | .cfi_restore $0 |
130 | .cfi_restore $1 | |
131 | .cfi_restore $2 | |
132 | .cfi_restore $3 | |
133 | .cfi_restore $4 | |
134 | .cfi_restore $5 | |
135 | .cfi_restore $6 | |
136 | .cfi_restore $7 | |
137 | .cfi_restore $8 | |
138 | .cfi_restore $19 | |
139 | .cfi_restore $20 | |
140 | .cfi_restore $21 | |
141 | .cfi_restore $22 | |
142 | .cfi_restore $23 | |
143 | .cfi_restore $24 | |
144 | .cfi_restore $25 | |
145 | .cfi_restore $26 | |
146 | .cfi_restore $27 | |
147 | .cfi_restore $28 | |
148 | .cfi_adjust_cfa_offset -SP_OFF | |
149 | .endm | |
150 | ||
151 | .macro DO_SWITCH_STACK | |
152 | bsr $1, do_switch_stack | |
153 | .cfi_adjust_cfa_offset SWITCH_STACK_SIZE | |
154 | .cfi_rel_offset $9, 0 | |
155 | .cfi_rel_offset $10, 8 | |
156 | .cfi_rel_offset $11, 16 | |
157 | .cfi_rel_offset $12, 24 | |
158 | .cfi_rel_offset $13, 32 | |
159 | .cfi_rel_offset $14, 40 | |
160 | .cfi_rel_offset $15, 48 | |
161 | /* We don't really care about the FP registers for debugging. */ | |
162 | .endm | |
163 | ||
164 | .macro UNDO_SWITCH_STACK | |
165 | bsr $1, undo_switch_stack | |
166 | .cfi_restore $9 | |
167 | .cfi_restore $10 | |
168 | .cfi_restore $11 | |
169 | .cfi_restore $12 | |
170 | .cfi_restore $13 | |
171 | .cfi_restore $14 | |
172 | .cfi_restore $15 | |
173 | .cfi_adjust_cfa_offset -SWITCH_STACK_SIZE | |
174 | .endm | |
1da177e4 LT |
175 | |
176 | /* | |
177 | * Non-syscall kernel entry points. | |
178 | */ | |
179 | ||
231b0bed | 180 | CFI_START_OSF_FRAME entInt |
1da177e4 LT |
181 | SAVE_ALL |
182 | lda $8, 0x3fff | |
183 | lda $26, ret_from_sys_call | |
184 | bic $sp, $8, $8 | |
185 | mov $sp, $19 | |
186 | jsr $31, do_entInt | |
231b0bed | 187 | CFI_END_OSF_FRAME entInt |
1da177e4 | 188 | |
231b0bed | 189 | CFI_START_OSF_FRAME entArith |
1da177e4 LT |
190 | SAVE_ALL |
191 | lda $8, 0x3fff | |
192 | lda $26, ret_from_sys_call | |
193 | bic $sp, $8, $8 | |
194 | mov $sp, $18 | |
195 | jsr $31, do_entArith | |
231b0bed | 196 | CFI_END_OSF_FRAME entArith |
1da177e4 | 197 | |
231b0bed | 198 | CFI_START_OSF_FRAME entMM |
1da177e4 LT |
199 | SAVE_ALL |
200 | /* save $9 - $15 so the inline exception code can manipulate them. */ | |
201 | subq $sp, 56, $sp | |
231b0bed | 202 | .cfi_adjust_cfa_offset 56 |
1da177e4 LT |
203 | stq $9, 0($sp) |
204 | stq $10, 8($sp) | |
205 | stq $11, 16($sp) | |
206 | stq $12, 24($sp) | |
207 | stq $13, 32($sp) | |
208 | stq $14, 40($sp) | |
209 | stq $15, 48($sp) | |
231b0bed RH |
210 | .cfi_rel_offset $9, 0 |
211 | .cfi_rel_offset $10, 8 | |
212 | .cfi_rel_offset $11, 16 | |
213 | .cfi_rel_offset $12, 24 | |
214 | .cfi_rel_offset $13, 32 | |
215 | .cfi_rel_offset $14, 40 | |
216 | .cfi_rel_offset $15, 48 | |
1da177e4 LT |
217 | addq $sp, 56, $19 |
218 | /* handle the fault */ | |
219 | lda $8, 0x3fff | |
220 | bic $sp, $8, $8 | |
221 | jsr $26, do_page_fault | |
222 | /* reload the registers after the exception code played. */ | |
223 | ldq $9, 0($sp) | |
224 | ldq $10, 8($sp) | |
225 | ldq $11, 16($sp) | |
226 | ldq $12, 24($sp) | |
227 | ldq $13, 32($sp) | |
228 | ldq $14, 40($sp) | |
229 | ldq $15, 48($sp) | |
230 | addq $sp, 56, $sp | |
231b0bed RH |
231 | .cfi_restore $9 |
232 | .cfi_restore $10 | |
233 | .cfi_restore $11 | |
234 | .cfi_restore $12 | |
235 | .cfi_restore $13 | |
236 | .cfi_restore $14 | |
237 | .cfi_restore $15 | |
238 | .cfi_adjust_cfa_offset -56 | |
1da177e4 LT |
239 | /* finish up the syscall as normal. */ |
240 | br ret_from_sys_call | |
231b0bed | 241 | CFI_END_OSF_FRAME entMM |
1da177e4 | 242 | |
231b0bed | 243 | CFI_START_OSF_FRAME entIF |
1da177e4 LT |
244 | SAVE_ALL |
245 | lda $8, 0x3fff | |
246 | lda $26, ret_from_sys_call | |
247 | bic $sp, $8, $8 | |
248 | mov $sp, $17 | |
249 | jsr $31, do_entIF | |
231b0bed | 250 | CFI_END_OSF_FRAME entIF |
1da177e4 | 251 | |
231b0bed | 252 | CFI_START_OSF_FRAME entUna |
1da177e4 | 253 | lda $sp, -256($sp) |
231b0bed | 254 | .cfi_adjust_cfa_offset 256 |
1da177e4 | 255 | stq $0, 0($sp) |
231b0bed RH |
256 | .cfi_rel_offset $0, 0 |
257 | .cfi_remember_state | |
1da177e4 LT |
258 | ldq $0, 256($sp) /* get PS */ |
259 | stq $1, 8($sp) | |
260 | stq $2, 16($sp) | |
261 | stq $3, 24($sp) | |
262 | and $0, 8, $0 /* user mode? */ | |
263 | stq $4, 32($sp) | |
264 | bne $0, entUnaUser /* yup -> do user-level unaligned fault */ | |
265 | stq $5, 40($sp) | |
266 | stq $6, 48($sp) | |
267 | stq $7, 56($sp) | |
268 | stq $8, 64($sp) | |
269 | stq $9, 72($sp) | |
270 | stq $10, 80($sp) | |
271 | stq $11, 88($sp) | |
272 | stq $12, 96($sp) | |
273 | stq $13, 104($sp) | |
274 | stq $14, 112($sp) | |
275 | stq $15, 120($sp) | |
276 | /* 16-18 PAL-saved */ | |
277 | stq $19, 152($sp) | |
278 | stq $20, 160($sp) | |
279 | stq $21, 168($sp) | |
280 | stq $22, 176($sp) | |
281 | stq $23, 184($sp) | |
282 | stq $24, 192($sp) | |
283 | stq $25, 200($sp) | |
284 | stq $26, 208($sp) | |
285 | stq $27, 216($sp) | |
286 | stq $28, 224($sp) | |
d70ddac1 | 287 | mov $sp, $19 |
1da177e4 | 288 | stq $gp, 232($sp) |
231b0bed RH |
289 | .cfi_rel_offset $1, 1*8 |
290 | .cfi_rel_offset $2, 2*8 | |
291 | .cfi_rel_offset $3, 3*8 | |
292 | .cfi_rel_offset $4, 4*8 | |
293 | .cfi_rel_offset $5, 5*8 | |
294 | .cfi_rel_offset $6, 6*8 | |
295 | .cfi_rel_offset $7, 7*8 | |
296 | .cfi_rel_offset $8, 8*8 | |
297 | .cfi_rel_offset $9, 9*8 | |
298 | .cfi_rel_offset $10, 10*8 | |
299 | .cfi_rel_offset $11, 11*8 | |
300 | .cfi_rel_offset $12, 12*8 | |
301 | .cfi_rel_offset $13, 13*8 | |
302 | .cfi_rel_offset $14, 14*8 | |
303 | .cfi_rel_offset $15, 15*8 | |
304 | .cfi_rel_offset $19, 19*8 | |
305 | .cfi_rel_offset $20, 20*8 | |
306 | .cfi_rel_offset $21, 21*8 | |
307 | .cfi_rel_offset $22, 22*8 | |
308 | .cfi_rel_offset $23, 23*8 | |
309 | .cfi_rel_offset $24, 24*8 | |
310 | .cfi_rel_offset $25, 25*8 | |
311 | .cfi_rel_offset $26, 26*8 | |
312 | .cfi_rel_offset $27, 27*8 | |
313 | .cfi_rel_offset $28, 28*8 | |
314 | .cfi_rel_offset $29, 29*8 | |
1da177e4 LT |
315 | lda $8, 0x3fff |
316 | stq $31, 248($sp) | |
317 | bic $sp, $8, $8 | |
318 | jsr $26, do_entUna | |
319 | ldq $0, 0($sp) | |
320 | ldq $1, 8($sp) | |
321 | ldq $2, 16($sp) | |
322 | ldq $3, 24($sp) | |
323 | ldq $4, 32($sp) | |
324 | ldq $5, 40($sp) | |
325 | ldq $6, 48($sp) | |
326 | ldq $7, 56($sp) | |
327 | ldq $8, 64($sp) | |
328 | ldq $9, 72($sp) | |
329 | ldq $10, 80($sp) | |
330 | ldq $11, 88($sp) | |
331 | ldq $12, 96($sp) | |
332 | ldq $13, 104($sp) | |
333 | ldq $14, 112($sp) | |
334 | ldq $15, 120($sp) | |
335 | /* 16-18 PAL-saved */ | |
336 | ldq $19, 152($sp) | |
337 | ldq $20, 160($sp) | |
338 | ldq $21, 168($sp) | |
339 | ldq $22, 176($sp) | |
340 | ldq $23, 184($sp) | |
341 | ldq $24, 192($sp) | |
342 | ldq $25, 200($sp) | |
343 | ldq $26, 208($sp) | |
344 | ldq $27, 216($sp) | |
345 | ldq $28, 224($sp) | |
346 | ldq $gp, 232($sp) | |
347 | lda $sp, 256($sp) | |
231b0bed RH |
348 | .cfi_restore $1 |
349 | .cfi_restore $2 | |
350 | .cfi_restore $3 | |
351 | .cfi_restore $4 | |
352 | .cfi_restore $5 | |
353 | .cfi_restore $6 | |
354 | .cfi_restore $7 | |
355 | .cfi_restore $8 | |
356 | .cfi_restore $9 | |
357 | .cfi_restore $10 | |
358 | .cfi_restore $11 | |
359 | .cfi_restore $12 | |
360 | .cfi_restore $13 | |
361 | .cfi_restore $14 | |
362 | .cfi_restore $15 | |
363 | .cfi_restore $19 | |
364 | .cfi_restore $20 | |
365 | .cfi_restore $21 | |
366 | .cfi_restore $22 | |
367 | .cfi_restore $23 | |
368 | .cfi_restore $24 | |
369 | .cfi_restore $25 | |
370 | .cfi_restore $26 | |
371 | .cfi_restore $27 | |
372 | .cfi_restore $28 | |
373 | .cfi_restore $29 | |
374 | .cfi_adjust_cfa_offset -256 | |
1da177e4 | 375 | call_pal PAL_rti |
1da177e4 LT |
376 | |
377 | .align 4 | |
1da177e4 | 378 | entUnaUser: |
231b0bed | 379 | .cfi_restore_state |
1da177e4 LT |
380 | ldq $0, 0($sp) /* restore original $0 */ |
381 | lda $sp, 256($sp) /* pop entUna's stack frame */ | |
231b0bed RH |
382 | .cfi_restore $0 |
383 | .cfi_adjust_cfa_offset -256 | |
1da177e4 LT |
384 | SAVE_ALL /* setup normal kernel stack */ |
385 | lda $sp, -56($sp) | |
231b0bed | 386 | .cfi_adjust_cfa_offset 56 |
1da177e4 LT |
387 | stq $9, 0($sp) |
388 | stq $10, 8($sp) | |
389 | stq $11, 16($sp) | |
390 | stq $12, 24($sp) | |
391 | stq $13, 32($sp) | |
392 | stq $14, 40($sp) | |
393 | stq $15, 48($sp) | |
231b0bed RH |
394 | .cfi_rel_offset $9, 0 |
395 | .cfi_rel_offset $10, 8 | |
396 | .cfi_rel_offset $11, 16 | |
397 | .cfi_rel_offset $12, 24 | |
398 | .cfi_rel_offset $13, 32 | |
399 | .cfi_rel_offset $14, 40 | |
400 | .cfi_rel_offset $15, 48 | |
1da177e4 LT |
401 | lda $8, 0x3fff |
402 | addq $sp, 56, $19 | |
403 | bic $sp, $8, $8 | |
404 | jsr $26, do_entUnaUser | |
405 | ldq $9, 0($sp) | |
406 | ldq $10, 8($sp) | |
407 | ldq $11, 16($sp) | |
408 | ldq $12, 24($sp) | |
409 | ldq $13, 32($sp) | |
410 | ldq $14, 40($sp) | |
411 | ldq $15, 48($sp) | |
412 | lda $sp, 56($sp) | |
231b0bed RH |
413 | .cfi_restore $9 |
414 | .cfi_restore $10 | |
415 | .cfi_restore $11 | |
416 | .cfi_restore $12 | |
417 | .cfi_restore $13 | |
418 | .cfi_restore $14 | |
419 | .cfi_restore $15 | |
420 | .cfi_adjust_cfa_offset -56 | |
1da177e4 | 421 | br ret_from_sys_call |
231b0bed | 422 | CFI_END_OSF_FRAME entUna |
1da177e4 | 423 | |
231b0bed | 424 | CFI_START_OSF_FRAME entDbg |
1da177e4 LT |
425 | SAVE_ALL |
426 | lda $8, 0x3fff | |
427 | lda $26, ret_from_sys_call | |
428 | bic $sp, $8, $8 | |
429 | mov $sp, $16 | |
430 | jsr $31, do_entDbg | |
231b0bed | 431 | CFI_END_OSF_FRAME entDbg |
1da177e4 LT |
432 | \f |
433 | /* | |
434 | * The system call entry point is special. Most importantly, it looks | |
435 | * like a function call to userspace as far as clobbered registers. We | |
436 | * do preserve the argument registers (for syscall restarts) and $26 | |
437 | * (for leaf syscall functions). | |
438 | * | |
439 | * So much for theory. We don't take advantage of this yet. | |
440 | * | |
441 | * Note that a0-a2 are not saved by PALcode as with the other entry points. | |
442 | */ | |
443 | ||
444 | .align 4 | |
445 | .globl entSys | |
231b0bed RH |
446 | .type entSys, @function |
447 | .cfi_startproc simple | |
448 | .cfi_return_column 64 | |
449 | .cfi_def_cfa $sp, 48 | |
450 | .cfi_rel_offset 64, 8 | |
451 | .cfi_rel_offset $gp, 16 | |
1da177e4 LT |
452 | entSys: |
453 | SAVE_ALL | |
454 | lda $8, 0x3fff | |
455 | bic $sp, $8, $8 | |
456 | lda $4, NR_SYSCALLS($31) | |
457 | stq $16, SP_OFF+24($sp) | |
458 | lda $5, sys_call_table | |
459 | lda $27, sys_ni_syscall | |
460 | cmpult $0, $4, $4 | |
461 | ldl $3, TI_FLAGS($8) | |
462 | stq $17, SP_OFF+32($sp) | |
463 | s8addq $0, $5, $5 | |
464 | stq $18, SP_OFF+40($sp) | |
231b0bed RH |
465 | .cfi_rel_offset $16, SP_OFF+24 |
466 | .cfi_rel_offset $17, SP_OFF+32 | |
467 | .cfi_rel_offset $18, SP_OFF+40 | |
1da177e4 LT |
468 | blbs $3, strace |
469 | beq $4, 1f | |
470 | ldq $27, 0($5) | |
471 | 1: jsr $26, ($27), alpha_ni_syscall | |
472 | ldgp $gp, 0($26) | |
473 | blt $0, $syscall_error /* the call failed */ | |
474 | stq $0, 0($sp) | |
475 | stq $31, 72($sp) /* a3=0 => no error */ | |
476 | ||
477 | .align 4 | |
231b0bed | 478 | .globl ret_from_sys_call |
1da177e4 | 479 | ret_from_sys_call: |
cb450766 | 480 | cmovne $26, 0, $18 /* $18 = 0 => non-restartable */ |
1da177e4 LT |
481 | ldq $0, SP_OFF($sp) |
482 | and $0, 8, $0 | |
77edffb6 | 483 | beq $0, ret_to_kernel |
494486a1 | 484 | ret_to_user: |
1da177e4 LT |
485 | /* Make sure need_resched and sigpending don't change between |
486 | sampling and the rti. */ | |
487 | lda $16, 7 | |
488 | call_pal PAL_swpipl | |
cb450766 AV |
489 | ldl $17, TI_FLAGS($8) |
490 | and $17, _TIF_WORK_MASK, $2 | |
494486a1 | 491 | bne $2, work_pending |
1da177e4 | 492 | restore_all: |
231b0bed | 493 | .cfi_remember_state |
1da177e4 LT |
494 | RESTORE_ALL |
495 | call_pal PAL_rti | |
496 | ||
77edffb6 | 497 | ret_to_kernel: |
231b0bed | 498 | .cfi_restore_state |
77edffb6 AV |
499 | lda $16, 7 |
500 | call_pal PAL_swpipl | |
501 | br restore_all | |
502 | ||
1da177e4 LT |
503 | .align 3 |
504 | $syscall_error: | |
505 | /* | |
506 | * Some system calls (e.g., ptrace) can return arbitrary | |
507 | * values which might normally be mistaken as error numbers. | |
508 | * Those functions must zero $0 (v0) directly in the stack | |
509 | * frame to indicate that a negative return value wasn't an | |
510 | * error number.. | |
511 | */ | |
cb450766 AV |
512 | ldq $18, 0($sp) /* old syscall nr (zero if success) */ |
513 | beq $18, $ret_success | |
1da177e4 | 514 | |
cb450766 | 515 | ldq $19, 72($sp) /* .. and this a3 */ |
1da177e4 LT |
516 | subq $31, $0, $0 /* with error in v0 */ |
517 | addq $31, 1, $1 /* set a3 for errno return */ | |
518 | stq $0, 0($sp) | |
519 | mov $31, $26 /* tell "ret_from_sys_call" we can restart */ | |
520 | stq $1, 72($sp) /* a3 for return */ | |
521 | br ret_from_sys_call | |
522 | ||
523 | $ret_success: | |
524 | stq $0, 0($sp) | |
525 | stq $31, 72($sp) /* a3=0 => no error */ | |
526 | br ret_from_sys_call | |
1da177e4 LT |
527 | |
528 | /* | |
529 | * Do all cleanup when returning from all interrupts and system calls. | |
530 | * | |
531 | * Arguments: | |
1da177e4 | 532 | * $8: current. |
cb450766 AV |
533 | * $17: TI_FLAGS. |
534 | * $18: The old syscall number, or zero if this is not a return | |
1da177e4 | 535 | * from a syscall that errored and is possibly restartable. |
cb450766 | 536 | * $19: The old a3 value |
1da177e4 LT |
537 | */ |
538 | ||
539 | .align 4 | |
231b0bed | 540 | .type work_pending, @function |
1da177e4 | 541 | work_pending: |
cb450766 | 542 | and $17, _TIF_NOTIFY_RESUME | _TIF_SIGPENDING, $2 |
7721d3c2 | 543 | bne $2, $work_notifysig |
1da177e4 LT |
544 | |
545 | $work_resched: | |
7721d3c2 AV |
546 | /* |
547 | * We can get here only if we returned from syscall without SIGPENDING | |
548 | * or got through work_notifysig already. Either case means no syscall | |
cb450766 | 549 | * restarts for us, so let $18 and $19 burn. |
7721d3c2 | 550 | */ |
1da177e4 | 551 | jsr $26, schedule |
cb450766 | 552 | mov 0, $18 |
7721d3c2 | 553 | br ret_to_user |
1da177e4 LT |
554 | |
555 | $work_notifysig: | |
b927b3e2 | 556 | mov $sp, $16 |
231b0bed | 557 | DO_SWITCH_STACK |
6972d6f2 | 558 | jsr $26, do_work_pending |
231b0bed | 559 | UNDO_SWITCH_STACK |
6972d6f2 | 560 | br restore_all |
1da177e4 LT |
561 | |
562 | /* | |
563 | * PTRACE syscall handler | |
564 | */ | |
565 | ||
566 | .align 4 | |
231b0bed | 567 | .type strace, @function |
1da177e4 LT |
568 | strace: |
569 | /* set up signal stack, call syscall_trace */ | |
231b0bed | 570 | DO_SWITCH_STACK |
12f79be9 | 571 | jsr $26, syscall_trace_enter /* returns the syscall number */ |
231b0bed | 572 | UNDO_SWITCH_STACK |
1da177e4 | 573 | |
12f79be9 | 574 | /* get the arguments back.. */ |
1da177e4 LT |
575 | ldq $16, SP_OFF+24($sp) |
576 | ldq $17, SP_OFF+32($sp) | |
577 | ldq $18, SP_OFF+40($sp) | |
578 | ldq $19, 72($sp) | |
579 | ldq $20, 80($sp) | |
580 | ldq $21, 88($sp) | |
581 | ||
582 | /* get the system call pointer.. */ | |
583 | lda $1, NR_SYSCALLS($31) | |
584 | lda $2, sys_call_table | |
585 | lda $27, alpha_ni_syscall | |
586 | cmpult $0, $1, $1 | |
587 | s8addq $0, $2, $2 | |
588 | beq $1, 1f | |
589 | ldq $27, 0($2) | |
590 | 1: jsr $26, ($27), sys_gettimeofday | |
53293638 | 591 | ret_from_straced: |
1da177e4 LT |
592 | ldgp $gp, 0($26) |
593 | ||
594 | /* check return.. */ | |
595 | blt $0, $strace_error /* the call failed */ | |
596 | stq $31, 72($sp) /* a3=0 => no error */ | |
597 | $strace_success: | |
598 | stq $0, 0($sp) /* save return value */ | |
599 | ||
231b0bed | 600 | DO_SWITCH_STACK |
12f79be9 | 601 | jsr $26, syscall_trace_leave |
231b0bed | 602 | UNDO_SWITCH_STACK |
1da177e4 LT |
603 | br $31, ret_from_sys_call |
604 | ||
605 | .align 3 | |
606 | $strace_error: | |
cb450766 AV |
607 | ldq $18, 0($sp) /* old syscall nr (zero if success) */ |
608 | beq $18, $strace_success | |
609 | ldq $19, 72($sp) /* .. and this a3 */ | |
1da177e4 LT |
610 | |
611 | subq $31, $0, $0 /* with error in v0 */ | |
612 | addq $31, 1, $1 /* set a3 for errno return */ | |
613 | stq $0, 0($sp) | |
614 | stq $1, 72($sp) /* a3 for return */ | |
615 | ||
231b0bed | 616 | DO_SWITCH_STACK |
cb450766 AV |
617 | mov $18, $9 /* save old syscall number */ |
618 | mov $19, $10 /* save old a3 */ | |
12f79be9 | 619 | jsr $26, syscall_trace_leave |
cb450766 AV |
620 | mov $9, $18 |
621 | mov $10, $19 | |
231b0bed | 622 | UNDO_SWITCH_STACK |
1da177e4 LT |
623 | |
624 | mov $31, $26 /* tell "ret_from_sys_call" we can restart */ | |
625 | br ret_from_sys_call | |
231b0bed | 626 | CFI_END_OSF_FRAME entSys |
1da177e4 LT |
627 | \f |
628 | /* | |
629 | * Save and restore the switch stack -- aka the balance of the user context. | |
630 | */ | |
631 | ||
632 | .align 4 | |
231b0bed RH |
633 | .type do_switch_stack, @function |
634 | .cfi_startproc simple | |
635 | .cfi_return_column 64 | |
636 | .cfi_def_cfa $sp, 0 | |
637 | .cfi_register 64, $1 | |
1da177e4 LT |
638 | do_switch_stack: |
639 | lda $sp, -SWITCH_STACK_SIZE($sp) | |
231b0bed | 640 | .cfi_adjust_cfa_offset SWITCH_STACK_SIZE |
1da177e4 LT |
641 | stq $9, 0($sp) |
642 | stq $10, 8($sp) | |
643 | stq $11, 16($sp) | |
644 | stq $12, 24($sp) | |
645 | stq $13, 32($sp) | |
646 | stq $14, 40($sp) | |
647 | stq $15, 48($sp) | |
648 | stq $26, 56($sp) | |
649 | stt $f0, 64($sp) | |
650 | stt $f1, 72($sp) | |
651 | stt $f2, 80($sp) | |
652 | stt $f3, 88($sp) | |
653 | stt $f4, 96($sp) | |
654 | stt $f5, 104($sp) | |
655 | stt $f6, 112($sp) | |
656 | stt $f7, 120($sp) | |
657 | stt $f8, 128($sp) | |
658 | stt $f9, 136($sp) | |
659 | stt $f10, 144($sp) | |
660 | stt $f11, 152($sp) | |
661 | stt $f12, 160($sp) | |
662 | stt $f13, 168($sp) | |
663 | stt $f14, 176($sp) | |
664 | stt $f15, 184($sp) | |
665 | stt $f16, 192($sp) | |
666 | stt $f17, 200($sp) | |
667 | stt $f18, 208($sp) | |
668 | stt $f19, 216($sp) | |
669 | stt $f20, 224($sp) | |
670 | stt $f21, 232($sp) | |
671 | stt $f22, 240($sp) | |
672 | stt $f23, 248($sp) | |
673 | stt $f24, 256($sp) | |
674 | stt $f25, 264($sp) | |
675 | stt $f26, 272($sp) | |
676 | stt $f27, 280($sp) | |
677 | mf_fpcr $f0 # get fpcr | |
678 | stt $f28, 288($sp) | |
679 | stt $f29, 296($sp) | |
680 | stt $f30, 304($sp) | |
681 | stt $f0, 312($sp) # save fpcr in slot of $f31 | |
682 | ldt $f0, 64($sp) # dont let "do_switch_stack" change fp state. | |
683 | ret $31, ($1), 1 | |
231b0bed RH |
684 | .cfi_endproc |
685 | .size do_switch_stack, .-do_switch_stack | |
1da177e4 LT |
686 | |
687 | .align 4 | |
231b0bed RH |
688 | .type undo_switch_stack, @function |
689 | .cfi_startproc simple | |
690 | .cfi_def_cfa $sp, 0 | |
691 | .cfi_register 64, $1 | |
1da177e4 LT |
692 | undo_switch_stack: |
693 | ldq $9, 0($sp) | |
694 | ldq $10, 8($sp) | |
695 | ldq $11, 16($sp) | |
696 | ldq $12, 24($sp) | |
697 | ldq $13, 32($sp) | |
698 | ldq $14, 40($sp) | |
699 | ldq $15, 48($sp) | |
700 | ldq $26, 56($sp) | |
701 | ldt $f30, 312($sp) # get saved fpcr | |
702 | ldt $f0, 64($sp) | |
703 | ldt $f1, 72($sp) | |
704 | ldt $f2, 80($sp) | |
705 | ldt $f3, 88($sp) | |
706 | mt_fpcr $f30 # install saved fpcr | |
707 | ldt $f4, 96($sp) | |
708 | ldt $f5, 104($sp) | |
709 | ldt $f6, 112($sp) | |
710 | ldt $f7, 120($sp) | |
711 | ldt $f8, 128($sp) | |
712 | ldt $f9, 136($sp) | |
713 | ldt $f10, 144($sp) | |
714 | ldt $f11, 152($sp) | |
715 | ldt $f12, 160($sp) | |
716 | ldt $f13, 168($sp) | |
717 | ldt $f14, 176($sp) | |
718 | ldt $f15, 184($sp) | |
719 | ldt $f16, 192($sp) | |
720 | ldt $f17, 200($sp) | |
721 | ldt $f18, 208($sp) | |
722 | ldt $f19, 216($sp) | |
723 | ldt $f20, 224($sp) | |
724 | ldt $f21, 232($sp) | |
725 | ldt $f22, 240($sp) | |
726 | ldt $f23, 248($sp) | |
727 | ldt $f24, 256($sp) | |
728 | ldt $f25, 264($sp) | |
729 | ldt $f26, 272($sp) | |
730 | ldt $f27, 280($sp) | |
731 | ldt $f28, 288($sp) | |
732 | ldt $f29, 296($sp) | |
733 | ldt $f30, 304($sp) | |
734 | lda $sp, SWITCH_STACK_SIZE($sp) | |
735 | ret $31, ($1), 1 | |
231b0bed RH |
736 | .cfi_endproc |
737 | .size undo_switch_stack, .-undo_switch_stack | |
1da177e4 LT |
738 | \f |
739 | /* | |
740 | * The meat of the context switch code. | |
741 | */ | |
742 | ||
743 | .align 4 | |
744 | .globl alpha_switch_to | |
231b0bed RH |
745 | .type alpha_switch_to, @function |
746 | .cfi_startproc | |
1da177e4 | 747 | alpha_switch_to: |
231b0bed | 748 | DO_SWITCH_STACK |
1da177e4 LT |
749 | call_pal PAL_swpctx |
750 | lda $8, 0x3fff | |
231b0bed | 751 | UNDO_SWITCH_STACK |
1da177e4 LT |
752 | bic $sp, $8, $8 |
753 | mov $17, $0 | |
754 | ret | |
231b0bed RH |
755 | .cfi_endproc |
756 | .size alpha_switch_to, .-alpha_switch_to | |
1da177e4 LT |
757 | |
758 | /* | |
759 | * New processes begin life here. | |
760 | */ | |
761 | ||
762 | .globl ret_from_fork | |
763 | .align 4 | |
764 | .ent ret_from_fork | |
765 | ret_from_fork: | |
766 | lda $26, ret_from_sys_call | |
767 | mov $17, $16 | |
768 | jmp $31, schedule_tail | |
769 | .end ret_from_fork | |
770 | ||
771 | /* | |
cba1ec7e | 772 | * ... and new kernel threads - here |
1da177e4 LT |
773 | */ |
774 | .align 4 | |
cba1ec7e AV |
775 | .globl ret_from_kernel_thread |
776 | .ent ret_from_kernel_thread | |
777 | ret_from_kernel_thread: | |
778 | mov $17, $16 | |
779 | jsr $26, schedule_tail | |
780 | mov $9, $27 | |
781 | mov $10, $16 | |
782 | jsr $26, ($9) | |
44f4b56b AV |
783 | mov $31, $19 /* to disable syscall restarts */ |
784 | br $31, ret_to_user | |
5522be6a | 785 | .end ret_from_kernel_thread |
44f4b56b | 786 | |
1da177e4 LT |
787 | \f |
788 | /* | |
789 | * Special system calls. Most of these are special in that they either | |
790 | * have to play switch_stack games or in some way use the pt_regs struct. | |
791 | */ | |
dfe09ae0 AV |
792 | |
793 | .macro fork_like name | |
1da177e4 | 794 | .align 4 |
dfe09ae0 AV |
795 | .globl alpha_\name |
796 | .ent alpha_\name | |
797 | alpha_\name: | |
1da177e4 | 798 | .prologue 0 |
1da177e4 | 799 | bsr $1, do_switch_stack |
dfe09ae0 | 800 | jsr $26, sys_\name |
e0e431aa AV |
801 | ldq $26, 56($sp) |
802 | lda $sp, SWITCH_STACK_SIZE($sp) | |
1da177e4 | 803 | ret |
dfe09ae0 AV |
804 | .end alpha_\name |
805 | .endm | |
1da177e4 | 806 | |
dfe09ae0 AV |
807 | fork_like fork |
808 | fork_like vfork | |
809 | fork_like clone | |
1da177e4 LT |
810 | |
811 | .align 4 | |
812 | .globl sys_sigreturn | |
813 | .ent sys_sigreturn | |
814 | sys_sigreturn: | |
815 | .prologue 0 | |
53293638 AV |
816 | lda $9, ret_from_straced |
817 | cmpult $26, $9, $9 | |
1da177e4 LT |
818 | lda $sp, -SWITCH_STACK_SIZE($sp) |
819 | jsr $26, do_sigreturn | |
53293638 | 820 | bne $9, 1f |
12f79be9 | 821 | jsr $26, syscall_trace_leave |
53293638 | 822 | 1: br $1, undo_switch_stack |
1da177e4 LT |
823 | br ret_from_sys_call |
824 | .end sys_sigreturn | |
825 | ||
826 | .align 4 | |
827 | .globl sys_rt_sigreturn | |
828 | .ent sys_rt_sigreturn | |
829 | sys_rt_sigreturn: | |
830 | .prologue 0 | |
53293638 AV |
831 | lda $9, ret_from_straced |
832 | cmpult $26, $9, $9 | |
1da177e4 LT |
833 | lda $sp, -SWITCH_STACK_SIZE($sp) |
834 | jsr $26, do_rt_sigreturn | |
53293638 | 835 | bne $9, 1f |
12f79be9 | 836 | jsr $26, syscall_trace_leave |
53293638 | 837 | 1: br $1, undo_switch_stack |
1da177e4 LT |
838 | br ret_from_sys_call |
839 | .end sys_rt_sigreturn | |
840 | ||
1da177e4 LT |
841 | .align 4 |
842 | .globl alpha_ni_syscall | |
843 | .ent alpha_ni_syscall | |
844 | alpha_ni_syscall: | |
845 | .prologue 0 | |
846 | /* Special because it also implements overflow handling via | |
847 | syscall number 0. And if you recall, zero is a special | |
848 | trigger for "not an error". Store large non-zero there. */ | |
849 | lda $0, -ENOSYS | |
850 | unop | |
851 | stq $0, 0($sp) | |
852 | ret | |
853 | .end alpha_ni_syscall |