xref: /openbmc/linux/arch/sparc/kernel/rtrap_32.S (revision ef136bc9)
1d670bd4fSSam Ravnborg/*
2d670bd4fSSam Ravnborg * rtrap.S: Return from Sparc trap low-level code.
3d670bd4fSSam Ravnborg *
4d670bd4fSSam Ravnborg * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
5d670bd4fSSam Ravnborg */
6d670bd4fSSam Ravnborg
7d670bd4fSSam Ravnborg#include <asm/page.h>
8d670bd4fSSam Ravnborg#include <asm/ptrace.h>
9d670bd4fSSam Ravnborg#include <asm/psr.h>
10d670bd4fSSam Ravnborg#include <asm/asi.h>
11d670bd4fSSam Ravnborg#include <asm/smp.h>
12d670bd4fSSam Ravnborg#include <asm/contregs.h>
13d670bd4fSSam Ravnborg#include <asm/winmacro.h>
14d670bd4fSSam Ravnborg#include <asm/asmmacro.h>
15d670bd4fSSam Ravnborg#include <asm/thread_info.h>
16d670bd4fSSam Ravnborg
17d670bd4fSSam Ravnborg#define t_psr     l0
18d670bd4fSSam Ravnborg#define t_pc      l1
19d670bd4fSSam Ravnborg#define t_npc     l2
20d670bd4fSSam Ravnborg#define t_wim     l3
21d670bd4fSSam Ravnborg#define twin_tmp1 l4
22d670bd4fSSam Ravnborg#define glob_tmp  g4
23d670bd4fSSam Ravnborg#define curptr    g6
24d670bd4fSSam Ravnborg
25d670bd4fSSam Ravnborg	/* 7 WINDOW SPARC PATCH INSTRUCTIONS */
26d670bd4fSSam Ravnborg	.globl	rtrap_7win_patch1, rtrap_7win_patch2, rtrap_7win_patch3
27d670bd4fSSam Ravnborg	.globl	rtrap_7win_patch4, rtrap_7win_patch5
28d670bd4fSSam Ravnborgrtrap_7win_patch1:	srl	%t_wim, 0x6, %glob_tmp
29d670bd4fSSam Ravnborgrtrap_7win_patch2:	and	%glob_tmp, 0x7f, %glob_tmp
30d670bd4fSSam Ravnborgrtrap_7win_patch3:	srl	%g1, 7, %g2
31d670bd4fSSam Ravnborgrtrap_7win_patch4:	srl	%g2, 6, %g2
32d670bd4fSSam Ravnborgrtrap_7win_patch5:	and	%g1, 0x7f, %g1
33d670bd4fSSam Ravnborg	/* END OF PATCH INSTRUCTIONS */
34d670bd4fSSam Ravnborg
35d670bd4fSSam Ravnborg	/* We need to check for a few things which are:
36d670bd4fSSam Ravnborg	 * 1) The need to call schedule() because this
37d670bd4fSSam Ravnborg	 *    processes quantum is up.
38d670bd4fSSam Ravnborg	 * 2) Pending signals for this process, if any
39d670bd4fSSam Ravnborg	 *    exist we need to call do_signal() to do
40d670bd4fSSam Ravnborg	 *    the needy.
41d670bd4fSSam Ravnborg	 *
42d670bd4fSSam Ravnborg	 * Else we just check if the rett would land us
43d670bd4fSSam Ravnborg	 * in an invalid window, if so we need to grab
44d670bd4fSSam Ravnborg	 * it off the user/kernel stack first.
45d670bd4fSSam Ravnborg	 */
46d670bd4fSSam Ravnborg
47d670bd4fSSam Ravnborg	.globl	ret_trap_entry, rtrap_patch1, rtrap_patch2
48d670bd4fSSam Ravnborg	.globl	rtrap_patch3, rtrap_patch4, rtrap_patch5
49d670bd4fSSam Ravnborg	.globl	ret_trap_lockless_ipi
50d670bd4fSSam Ravnborgret_trap_entry:
51d670bd4fSSam Ravnborgret_trap_lockless_ipi:
52d670bd4fSSam Ravnborg	andcc	%t_psr, PSR_PS, %g0
53d670bd4fSSam Ravnborg	sethi	%hi(PSR_SYSCALL), %g1
54d670bd4fSSam Ravnborg	be	1f
55d670bd4fSSam Ravnborg	 andn	%t_psr, %g1, %t_psr
56d670bd4fSSam Ravnborg
57d670bd4fSSam Ravnborg	wr	%t_psr, 0x0, %psr
58d670bd4fSSam Ravnborg	b	ret_trap_kernel
59d670bd4fSSam Ravnborg	 nop
60d670bd4fSSam Ravnborg
61d670bd4fSSam Ravnborg1:
62d670bd4fSSam Ravnborg	ld	[%curptr + TI_FLAGS], %g2
63d670bd4fSSam Ravnborg	andcc	%g2, (_TIF_NEED_RESCHED), %g0
64d670bd4fSSam Ravnborg	be	signal_p
65d670bd4fSSam Ravnborg	 nop
66d670bd4fSSam Ravnborg
67d670bd4fSSam Ravnborg	call	schedule
68d670bd4fSSam Ravnborg	 nop
69d670bd4fSSam Ravnborg
70d670bd4fSSam Ravnborg	ld	[%curptr + TI_FLAGS], %g2
71d670bd4fSSam Ravnborgsignal_p:
72d670bd4fSSam Ravnborg	andcc	%g2, _TIF_DO_NOTIFY_RESUME_MASK, %g0
73d670bd4fSSam Ravnborg	bz,a	ret_trap_continue
74d670bd4fSSam Ravnborg	 ld	[%sp + STACKFRAME_SZ + PT_PSR], %t_psr
75d670bd4fSSam Ravnborg
76d670bd4fSSam Ravnborg	mov	%g2, %o2
77d670bd4fSSam Ravnborg	mov	%l5, %o1
78d670bd4fSSam Ravnborg	call	do_notify_resume
79d670bd4fSSam Ravnborg	 add	%sp, STACKFRAME_SZ, %o0	! pt_regs ptr
80d670bd4fSSam Ravnborg
81caebf910SAl Viro	b	signal_p
82caebf910SAl Viro	 ld	[%curptr + TI_FLAGS], %g2
83caebf910SAl Viro
84d670bd4fSSam Ravnborgret_trap_continue:
85d670bd4fSSam Ravnborg	sethi	%hi(PSR_SYSCALL), %g1
86d670bd4fSSam Ravnborg	andn	%t_psr, %g1, %t_psr
87d670bd4fSSam Ravnborg	wr	%t_psr, 0x0, %psr
88d670bd4fSSam Ravnborg	WRITE_PAUSE
89d670bd4fSSam Ravnborg
90d670bd4fSSam Ravnborg	ld	[%curptr + TI_W_SAVED], %twin_tmp1
91d670bd4fSSam Ravnborg	orcc	%g0, %twin_tmp1, %g0
92d670bd4fSSam Ravnborg	be	ret_trap_nobufwins
93d670bd4fSSam Ravnborg	 nop
94d670bd4fSSam Ravnborg
95d670bd4fSSam Ravnborg	wr	%t_psr, PSR_ET, %psr
96d670bd4fSSam Ravnborg	WRITE_PAUSE
97d670bd4fSSam Ravnborg
98d670bd4fSSam Ravnborg	mov	1, %o1
99d670bd4fSSam Ravnborg	call	try_to_clear_window_buffer
100d670bd4fSSam Ravnborg	 add	%sp, STACKFRAME_SZ, %o0
101d670bd4fSSam Ravnborg
102d670bd4fSSam Ravnborg	b	signal_p
103d670bd4fSSam Ravnborg	 ld	[%curptr + TI_FLAGS], %g2
104d670bd4fSSam Ravnborg
105d670bd4fSSam Ravnborgret_trap_nobufwins:
106d670bd4fSSam Ravnborg	/* Load up the user's out registers so we can pull
107d670bd4fSSam Ravnborg	 * a window from the stack, if necessary.
108d670bd4fSSam Ravnborg	 */
109d670bd4fSSam Ravnborg	LOAD_PT_INS(sp)
110d670bd4fSSam Ravnborg
111d670bd4fSSam Ravnborg	/* If there are already live user windows in the
112d670bd4fSSam Ravnborg	 * set we can return from trap safely.
113d670bd4fSSam Ravnborg	 */
114d670bd4fSSam Ravnborg	ld	[%curptr + TI_UWINMASK], %twin_tmp1
115d670bd4fSSam Ravnborg	orcc	%g0, %twin_tmp1, %g0
116d670bd4fSSam Ravnborg	bne	ret_trap_userwins_ok
117d670bd4fSSam Ravnborg	 nop
118d670bd4fSSam Ravnborg
119d670bd4fSSam Ravnborg		/* Calculate new %wim, we have to pull a register
120d670bd4fSSam Ravnborg		 * window from the users stack.
121d670bd4fSSam Ravnborg		 */
122d670bd4fSSam Ravnborgret_trap_pull_one_window:
123d670bd4fSSam Ravnborg		rd	%wim, %t_wim
124d670bd4fSSam Ravnborg		sll	%t_wim, 0x1, %twin_tmp1
125d670bd4fSSam Ravnborgrtrap_patch1:	srl	%t_wim, 0x7, %glob_tmp
126d670bd4fSSam Ravnborg		or	%glob_tmp, %twin_tmp1, %glob_tmp
127d670bd4fSSam Ravnborgrtrap_patch2:	and	%glob_tmp, 0xff, %glob_tmp
128d670bd4fSSam Ravnborg
129d670bd4fSSam Ravnborg		wr	%glob_tmp, 0x0, %wim
130d670bd4fSSam Ravnborg
131d670bd4fSSam Ravnborg	/* Here comes the architecture specific
132d670bd4fSSam Ravnborg	 * branch to the user stack checking routine
133d670bd4fSSam Ravnborg	 * for return from traps.
134d670bd4fSSam Ravnborg	 */
135ef136bc9SSam Ravnborg	b	srmmu_rett_stackchk
136d670bd4fSSam Ravnborg	 andcc	%fp, 0x7, %g0
137d670bd4fSSam Ravnborg
138d670bd4fSSam Ravnborgret_trap_userwins_ok:
139d670bd4fSSam Ravnborg	LOAD_PT_PRIV(sp, t_psr, t_pc, t_npc)
140d670bd4fSSam Ravnborg	or	%t_pc, %t_npc, %g2
141d670bd4fSSam Ravnborg	andcc	%g2, 0x3, %g0
142d670bd4fSSam Ravnborg	sethi	%hi(PSR_SYSCALL), %g2
143d670bd4fSSam Ravnborg	be	1f
144d670bd4fSSam Ravnborg	 andn	%t_psr, %g2, %t_psr
145d670bd4fSSam Ravnborg
146d670bd4fSSam Ravnborg	b	ret_trap_unaligned_pc
147d670bd4fSSam Ravnborg	 add	%sp, STACKFRAME_SZ, %o0
148d670bd4fSSam Ravnborg
149d670bd4fSSam Ravnborg1:
150d670bd4fSSam Ravnborg	LOAD_PT_YREG(sp, g1)
151d670bd4fSSam Ravnborg	LOAD_PT_GLOBALS(sp)
152d670bd4fSSam Ravnborg
153d670bd4fSSam Ravnborg	wr	%t_psr, 0x0, %psr
154d670bd4fSSam Ravnborg	WRITE_PAUSE
155d670bd4fSSam Ravnborg
156d670bd4fSSam Ravnborg	jmp	%t_pc
157d670bd4fSSam Ravnborg	rett	%t_npc
158d670bd4fSSam Ravnborg
159d670bd4fSSam Ravnborgret_trap_unaligned_pc:
160d670bd4fSSam Ravnborg	ld	[%sp + STACKFRAME_SZ + PT_PC], %o1
161d670bd4fSSam Ravnborg	ld	[%sp + STACKFRAME_SZ + PT_NPC], %o2
162d670bd4fSSam Ravnborg	ld	[%sp + STACKFRAME_SZ + PT_PSR], %o3
163d670bd4fSSam Ravnborg
164d670bd4fSSam Ravnborg	wr	%t_wim, 0x0, %wim		! or else...
165d670bd4fSSam Ravnborg
166d670bd4fSSam Ravnborg	wr	%t_psr, PSR_ET, %psr
167d670bd4fSSam Ravnborg	WRITE_PAUSE
168d670bd4fSSam Ravnborg
169d670bd4fSSam Ravnborg	call	do_memaccess_unaligned
170d670bd4fSSam Ravnborg	 nop
171d670bd4fSSam Ravnborg
172d670bd4fSSam Ravnborg	b	signal_p
173d670bd4fSSam Ravnborg	 ld	[%curptr + TI_FLAGS], %g2
174d670bd4fSSam Ravnborg
175d670bd4fSSam Ravnborgret_trap_kernel:
176d670bd4fSSam Ravnborg		/* Will the rett land us in the invalid window? */
177d670bd4fSSam Ravnborg		mov	2, %g1
178d670bd4fSSam Ravnborg		sll	%g1, %t_psr, %g1
179d670bd4fSSam Ravnborgrtrap_patch3:	srl	%g1, 8, %g2
180d670bd4fSSam Ravnborg		or	%g1, %g2, %g1
181d670bd4fSSam Ravnborg		rd	%wim, %g2
182d670bd4fSSam Ravnborg		andcc	%g2, %g1, %g0
183d670bd4fSSam Ravnborg		be	1f		! Nope, just return from the trap
184d670bd4fSSam Ravnborg		 sll	%g2, 0x1, %g1
185d670bd4fSSam Ravnborg
186d670bd4fSSam Ravnborg		/* We have to grab a window before returning. */
187d670bd4fSSam Ravnborgrtrap_patch4:	srl	%g2, 7,  %g2
188d670bd4fSSam Ravnborg		or	%g1, %g2, %g1
189d670bd4fSSam Ravnborgrtrap_patch5:	and	%g1, 0xff, %g1
190d670bd4fSSam Ravnborg
191d670bd4fSSam Ravnborg	wr	%g1, 0x0, %wim
192d670bd4fSSam Ravnborg
193d670bd4fSSam Ravnborg	/* Grrr, make sure we load from the right %sp... */
194d670bd4fSSam Ravnborg	LOAD_PT_ALL(sp, t_psr, t_pc, t_npc, g1)
195d670bd4fSSam Ravnborg
196d670bd4fSSam Ravnborg	restore	%g0, %g0, %g0
197d670bd4fSSam Ravnborg	LOAD_WINDOW(sp)
198d670bd4fSSam Ravnborg	b	2f
199d670bd4fSSam Ravnborg	 save	%g0, %g0, %g0
200d670bd4fSSam Ravnborg
201d670bd4fSSam Ravnborg	/* Reload the entire frame in case this is from a
202d670bd4fSSam Ravnborg	 * kernel system call or whatever...
203d670bd4fSSam Ravnborg	 */
204d670bd4fSSam Ravnborg1:
205d670bd4fSSam Ravnborg	LOAD_PT_ALL(sp, t_psr, t_pc, t_npc, g1)
206d670bd4fSSam Ravnborg2:
207d670bd4fSSam Ravnborg	sethi	%hi(PSR_SYSCALL), %twin_tmp1
208d670bd4fSSam Ravnborg	andn	%t_psr, %twin_tmp1, %t_psr
209d670bd4fSSam Ravnborg	wr	%t_psr, 0x0, %psr
210d670bd4fSSam Ravnborg	WRITE_PAUSE
211d670bd4fSSam Ravnborg
212d670bd4fSSam Ravnborg	jmp	%t_pc
213d670bd4fSSam Ravnborg	rett	%t_npc
214d670bd4fSSam Ravnborg
215d670bd4fSSam Ravnborgret_trap_user_stack_is_bolixed:
216d670bd4fSSam Ravnborg	wr	%t_wim, 0x0, %wim
217d670bd4fSSam Ravnborg
218d670bd4fSSam Ravnborg	wr	%t_psr, PSR_ET, %psr
219d670bd4fSSam Ravnborg	WRITE_PAUSE
220d670bd4fSSam Ravnborg
221d670bd4fSSam Ravnborg	call	window_ret_fault
222d670bd4fSSam Ravnborg	 add	%sp, STACKFRAME_SZ, %o0
223d670bd4fSSam Ravnborg
224d670bd4fSSam Ravnborg	b	signal_p
225d670bd4fSSam Ravnborg	 ld	[%curptr + TI_FLAGS], %g2
226d670bd4fSSam Ravnborg
227d670bd4fSSam Ravnborg	.globl	srmmu_rett_stackchk
228d670bd4fSSam Ravnborgsrmmu_rett_stackchk:
229d670bd4fSSam Ravnborg	bne	ret_trap_user_stack_is_bolixed
230d670bd4fSSam Ravnborg	 sethi   %hi(PAGE_OFFSET), %g1
231d670bd4fSSam Ravnborg	cmp	%g1, %fp
232d670bd4fSSam Ravnborg	bleu	ret_trap_user_stack_is_bolixed
233d670bd4fSSam Ravnborg	 mov	AC_M_SFSR, %g1
234d670bd4fSSam Ravnborg	lda	[%g1] ASI_M_MMUREGS, %g0
235d670bd4fSSam Ravnborg
236d670bd4fSSam Ravnborg	lda	[%g0] ASI_M_MMUREGS, %g1
237d670bd4fSSam Ravnborg	or	%g1, 0x2, %g1
238d670bd4fSSam Ravnborg	sta	%g1, [%g0] ASI_M_MMUREGS
239d670bd4fSSam Ravnborg
240d670bd4fSSam Ravnborg	restore	%g0, %g0, %g0
241d670bd4fSSam Ravnborg
242d670bd4fSSam Ravnborg	LOAD_WINDOW(sp)
243d670bd4fSSam Ravnborg
244d670bd4fSSam Ravnborg	save	%g0, %g0, %g0
245d670bd4fSSam Ravnborg
246d670bd4fSSam Ravnborg	andn	%g1, 0x2, %g1
247d670bd4fSSam Ravnborg	sta	%g1, [%g0] ASI_M_MMUREGS
248d670bd4fSSam Ravnborg
249d670bd4fSSam Ravnborg	mov	AC_M_SFAR, %g2
250d670bd4fSSam Ravnborg	lda	[%g2] ASI_M_MMUREGS, %g2
251d670bd4fSSam Ravnborg
252d670bd4fSSam Ravnborg	mov	AC_M_SFSR, %g1
253d670bd4fSSam Ravnborg	lda	[%g1] ASI_M_MMUREGS, %g1
254d670bd4fSSam Ravnborg	andcc	%g1, 0x2, %g0
255d670bd4fSSam Ravnborg	be	ret_trap_userwins_ok
256d670bd4fSSam Ravnborg	 nop
257d670bd4fSSam Ravnborg
258d670bd4fSSam Ravnborg	b,a	ret_trap_user_stack_is_bolixed
259