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