PageRenderTime 26ms CodeModel.GetById 8ms app.highlight 14ms RepoModel.GetById 1ms app.codeStats 0ms

/arch/sparc64/kernel/winfixup.S

https://bitbucket.org/evzijst/gittest
Assembly | 417 lines | 411 code | 6 blank | 0 comment | 2 complexity | aca76786123188324fca1f2a1ed1fdac MD5 | raw file
  1/* $Id: winfixup.S,v 1.30 2002/02/09 19:49:30 davem Exp $
  2 *
  3 * winfixup.S: Handle cases where user stack pointer is found to be bogus.
  4 *
  5 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
  6 */
  7
  8#include <asm/asi.h>
  9#include <asm/head.h>
 10#include <asm/page.h>
 11#include <asm/ptrace.h>
 12#include <asm/processor.h>
 13#include <asm/spitfire.h>
 14#include <asm/thread_info.h>
 15
 16	.text
 17
 18set_pcontext:
 19cplus_winfixup_insn_1:
 20	sethi	%hi(0), %l1
 21	mov	PRIMARY_CONTEXT, %g1
 22	sllx	%l1, 32, %l1
 23cplus_winfixup_insn_2:
 24	sethi	%hi(0), %g2
 25	or	%l1, %g2, %l1
 26	stxa	%l1, [%g1] ASI_DMMU
 27	flush	%g6
 28	retl
 29	 nop
 30
 31cplus_wfinsn_1:
 32	sethi	%uhi(CTX_CHEETAH_PLUS_NUC), %l1
 33cplus_wfinsn_2:
 34	sethi	%hi(CTX_CHEETAH_PLUS_CTX0), %g2
 35
 36	.align	32
 37
 38	/* Here are the rules, pay attention.
 39	 *
 40	 * The kernel is disallowed from touching user space while
 41	 * the trap level is greater than zero, except for from within
 42	 * the window spill/fill handlers.  This must be followed
 43	 * so that we can easily detect the case where we tried to
 44	 * spill/fill with a bogus (or unmapped) user stack pointer.
 45	 *
 46	 * These are layed out in a special way for cache reasons,
 47	 * don't touch...
 48	 */
 49	.globl	fill_fixup, spill_fixup
 50fill_fixup:
 51	rdpr		%tstate, %g1
 52	andcc		%g1, TSTATE_PRIV, %g0
 53	or		%g4, FAULT_CODE_WINFIXUP, %g4
 54	be,pt		%xcc, window_scheisse_from_user_common
 55	 and		%g1, TSTATE_CWP, %g1
 56
 57	/* This is the extremely complex case, but it does happen from
 58	 * time to time if things are just right.  Essentially the restore
 59	 * done in rtrap right before going back to user mode, with tl=1
 60	 * and that levels trap stack registers all setup, took a fill trap,
 61	 * the user stack was not mapped in the tlb, and tlb miss occurred,
 62	 * the pte found was not valid, and a simple ref bit watch update
 63	 * could not satisfy the miss, so we got here.
 64	 *
 65	 * We must carefully unwind the state so we get back to tl=0, preserve
 66	 * all the register values we were going to give to the user.  Luckily
 67	 * most things are where they need to be, we also have the address
 68	 * which triggered the fault handy as well.
 69	 *
 70	 * Also note that we must preserve %l5 and %l6.  If the user was
 71	 * returning from a system call, we must make it look this way
 72	 * after we process the fill fault on the users stack.
 73	 *
 74	 * First, get into the window where the original restore was executed.
 75	 */
 76
 77	rdpr		%wstate, %g2			! Grab user mode wstate.
 78	wrpr		%g1, %cwp			! Get into the right window.
 79	sll		%g2, 3, %g2			! NORMAL-->OTHER
 80
 81	wrpr		%g0, 0x0, %canrestore		! Standard etrap stuff.
 82	wrpr		%g2, 0x0, %wstate		! This must be consistent.
 83	wrpr		%g0, 0x0, %otherwin		! We know this.
 84	call		set_pcontext			! Change contexts...
 85	 nop
 86	rdpr		%pstate, %l1			! Prepare to change globals.
 87	mov		%g6, %o7			! Get current.
 88
 89	andn		%l1, PSTATE_MM, %l1		! We want to be in RMO
 90	stb		%g4, [%g6 + TI_FAULT_CODE]
 91	stx		%g5, [%g6 + TI_FAULT_ADDR]
 92	wrpr		%g0, 0x0, %tl			! Out of trap levels.
 93	wrpr		%l1, (PSTATE_IE | PSTATE_AG | PSTATE_RMO), %pstate
 94	mov		%o7, %g6
 95	ldx		[%g6 + TI_TASK], %g4
 96#ifdef CONFIG_SMP
 97	mov		TSB_REG, %g1
 98	ldxa		[%g1] ASI_IMMU, %g5
 99#endif
100
101	/* This is the same as below, except we handle this a bit special
102	 * since we must preserve %l5 and %l6, see comment above.
103	 */
104	call		do_sparc64_fault
105	 add		%sp, PTREGS_OFF, %o0
106	ba,pt		%xcc, rtrap
107	 nop						! yes, nop is correct
108
109	/* Be very careful about usage of the alternate globals here.
110	 * You cannot touch %g4/%g5 as that has the fault information
111	 * should this be from usermode.  Also be careful for the case
112	 * where we get here from the save instruction in etrap.S when
113	 * coming from either user or kernel (does not matter which, it
114	 * is the same problem in both cases).  Essentially this means
115	 * do not touch %g7 or %g2 so we handle the two cases fine.
116	 */
117spill_fixup:
118	ldx		[%g6 + TI_FLAGS], %g1
119	andcc		%g1, _TIF_32BIT, %g0
120	ldub		[%g6 + TI_WSAVED], %g1
121
122	sll		%g1, 3, %g3
123	add		%g6, %g3, %g3
124	stx		%sp, [%g3 + TI_RWIN_SPTRS]
125	sll		%g1, 7, %g3
126	bne,pt		%xcc, 1f
127	 add		%g6, %g3, %g3
128	stx		%l0, [%g3 + TI_REG_WINDOW + 0x00]
129	stx		%l1, [%g3 + TI_REG_WINDOW + 0x08]
130
131	stx		%l2, [%g3 + TI_REG_WINDOW + 0x10]
132	stx		%l3, [%g3 + TI_REG_WINDOW + 0x18]
133	stx		%l4, [%g3 + TI_REG_WINDOW + 0x20]
134	stx		%l5, [%g3 + TI_REG_WINDOW + 0x28]
135	stx		%l6, [%g3 + TI_REG_WINDOW + 0x30]
136	stx		%l7, [%g3 + TI_REG_WINDOW + 0x38]
137	stx		%i0, [%g3 + TI_REG_WINDOW + 0x40]
138	stx		%i1, [%g3 + TI_REG_WINDOW + 0x48]
139
140	stx		%i2, [%g3 + TI_REG_WINDOW + 0x50]
141	stx		%i3, [%g3 + TI_REG_WINDOW + 0x58]
142	stx		%i4, [%g3 + TI_REG_WINDOW + 0x60]
143	stx		%i5, [%g3 + TI_REG_WINDOW + 0x68]
144	stx		%i6, [%g3 + TI_REG_WINDOW + 0x70]
145	b,pt		%xcc, 2f
146	 stx		%i7, [%g3 + TI_REG_WINDOW + 0x78]
1471:	stw		%l0, [%g3 + TI_REG_WINDOW + 0x00]
148
149	stw		%l1, [%g3 + TI_REG_WINDOW + 0x04]
150	stw		%l2, [%g3 + TI_REG_WINDOW + 0x08]
151	stw		%l3, [%g3 + TI_REG_WINDOW + 0x0c]
152	stw		%l4, [%g3 + TI_REG_WINDOW + 0x10]
153	stw		%l5, [%g3 + TI_REG_WINDOW + 0x14]
154	stw		%l6, [%g3 + TI_REG_WINDOW + 0x18]
155	stw		%l7, [%g3 + TI_REG_WINDOW + 0x1c]
156	stw		%i0, [%g3 + TI_REG_WINDOW + 0x20]
157
158	stw		%i1, [%g3 + TI_REG_WINDOW + 0x24]
159	stw		%i2, [%g3 + TI_REG_WINDOW + 0x28]
160	stw		%i3, [%g3 + TI_REG_WINDOW + 0x2c]
161	stw		%i4, [%g3 + TI_REG_WINDOW + 0x30]
162	stw		%i5, [%g3 + TI_REG_WINDOW + 0x34]
163	stw		%i6, [%g3 + TI_REG_WINDOW + 0x38]
164	stw		%i7, [%g3 + TI_REG_WINDOW + 0x3c]
1652:	add		%g1, 1, %g1
166
167	stb		%g1, [%g6 + TI_WSAVED]
168	rdpr		%tstate, %g1
169	andcc		%g1, TSTATE_PRIV, %g0
170	saved
171	and		%g1, TSTATE_CWP, %g1
172	be,pn		%xcc, window_scheisse_from_user_common
173	 mov		FAULT_CODE_WRITE | FAULT_CODE_DTLB | FAULT_CODE_WINFIXUP, %g4
174	retry
175
176window_scheisse_from_user_common:
177	stb		%g4, [%g6 + TI_FAULT_CODE]
178	stx		%g5, [%g6 + TI_FAULT_ADDR]
179	wrpr		%g1, %cwp
180	ba,pt		%xcc, etrap
181	 rd		%pc, %g7
182	call		do_sparc64_fault
183	 add		%sp, PTREGS_OFF, %o0
184	ba,a,pt		%xcc, rtrap_clr_l6
185
186	.globl		winfix_mna, fill_fixup_mna, spill_fixup_mna
187winfix_mna:
188	andn		%g3, 0x7f, %g3
189	add		%g3, 0x78, %g3
190	wrpr		%g3, %tnpc
191	done
192fill_fixup_mna:
193	rdpr		%tstate, %g1
194	andcc		%g1, TSTATE_PRIV, %g0
195	be,pt		%xcc, window_mna_from_user_common
196	 and		%g1, TSTATE_CWP, %g1
197
198	/* Please, see fill_fixup commentary about why we must preserve
199	 * %l5 and %l6 to preserve absolute correct semantics.
200	 */
201	rdpr		%wstate, %g2			! Grab user mode wstate.
202	wrpr		%g1, %cwp			! Get into the right window.
203	sll		%g2, 3, %g2			! NORMAL-->OTHER
204	wrpr		%g0, 0x0, %canrestore		! Standard etrap stuff.
205
206	wrpr		%g2, 0x0, %wstate		! This must be consistent.
207	wrpr		%g0, 0x0, %otherwin		! We know this.
208	call		set_pcontext			! Change contexts...
209	 nop
210	rdpr		%pstate, %l1			! Prepare to change globals.
211	mov		%g4, %o2			! Setup args for
212	mov		%g5, %o1			! final call to mem_address_unaligned.
213	andn		%l1, PSTATE_MM, %l1		! We want to be in RMO
214
215	mov		%g6, %o7			! Stash away current.
216	wrpr		%g0, 0x0, %tl			! Out of trap levels.
217	wrpr		%l1, (PSTATE_IE | PSTATE_AG | PSTATE_RMO), %pstate
218	mov		%o7, %g6			! Get current back.
219	ldx		[%g6 + TI_TASK], %g4		! Finish it.
220#ifdef CONFIG_SMP
221	mov		TSB_REG, %g1
222	ldxa		[%g1] ASI_IMMU, %g5
223#endif
224	call		mem_address_unaligned
225	 add		%sp, PTREGS_OFF, %o0
226
227	b,pt		%xcc, rtrap
228	 nop						! yes, the nop is correct
229spill_fixup_mna:
230	ldx		[%g6 + TI_FLAGS], %g1
231	andcc		%g1, _TIF_32BIT, %g0
232	ldub		[%g6 + TI_WSAVED], %g1
233	sll		%g1, 3, %g3
234	add		%g6, %g3, %g3
235	stx		%sp, [%g3 + TI_RWIN_SPTRS]
236
237	sll		%g1, 7, %g3
238	bne,pt		%xcc, 1f
239	 add		%g6, %g3, %g3
240	stx		%l0, [%g3 + TI_REG_WINDOW + 0x00]
241	stx		%l1, [%g3 + TI_REG_WINDOW + 0x08]
242	stx		%l2, [%g3 + TI_REG_WINDOW + 0x10]
243	stx		%l3, [%g3 + TI_REG_WINDOW + 0x18]
244	stx		%l4, [%g3 + TI_REG_WINDOW + 0x20]
245
246	stx		%l5, [%g3 + TI_REG_WINDOW + 0x28]
247	stx		%l6, [%g3 + TI_REG_WINDOW + 0x30]
248	stx		%l7, [%g3 + TI_REG_WINDOW + 0x38]
249	stx		%i0, [%g3 + TI_REG_WINDOW + 0x40]
250	stx		%i1, [%g3 + TI_REG_WINDOW + 0x48]
251	stx		%i2, [%g3 + TI_REG_WINDOW + 0x50]
252	stx		%i3, [%g3 + TI_REG_WINDOW + 0x58]
253	stx		%i4, [%g3 + TI_REG_WINDOW + 0x60]
254
255	stx		%i5, [%g3 + TI_REG_WINDOW + 0x68]
256	stx		%i6, [%g3 + TI_REG_WINDOW + 0x70]
257	stx		%i7, [%g3 + TI_REG_WINDOW + 0x78]
258	b,pt		%xcc, 2f
259	 add		%g1, 1, %g1
2601:	std		%l0, [%g3 + TI_REG_WINDOW + 0x00]
261	std		%l2, [%g3 + TI_REG_WINDOW + 0x08]
262	std		%l4, [%g3 + TI_REG_WINDOW + 0x10]
263
264	std		%l6, [%g3 + TI_REG_WINDOW + 0x18]
265	std		%i0, [%g3 + TI_REG_WINDOW + 0x20]
266	std		%i2, [%g3 + TI_REG_WINDOW + 0x28]
267	std		%i4, [%g3 + TI_REG_WINDOW + 0x30]
268	std		%i6, [%g3 + TI_REG_WINDOW + 0x38]
269	add		%g1, 1, %g1
2702:	stb		%g1, [%g6 + TI_WSAVED]
271	rdpr		%tstate, %g1
272
273	andcc		%g1, TSTATE_PRIV, %g0
274	saved
275	be,pn		%xcc, window_mna_from_user_common
276	 and		%g1, TSTATE_CWP, %g1
277	retry
278window_mna_from_user_common:
279	wrpr		%g1, %cwp
280	sethi		%hi(109f), %g7
281	ba,pt		%xcc, etrap
282109:	 or		%g7, %lo(109b), %g7
283	mov		%l4, %o2
284	mov		%l5, %o1
285	call		mem_address_unaligned
286	 add		%sp, PTREGS_OFF, %o0
287	ba,pt		%xcc, rtrap
288	 clr		%l6
289	
290	/* These are only needed for 64-bit mode processes which
291	 * put their stack pointer into the VPTE area and there
292	 * happens to be a VPTE tlb entry mapped there during
293	 * a spill/fill trap to that stack frame.
294	 */
295	.globl		winfix_dax, fill_fixup_dax, spill_fixup_dax
296winfix_dax:
297	andn		%g3, 0x7f, %g3
298	add		%g3, 0x74, %g3
299	wrpr		%g3, %tnpc
300	done
301fill_fixup_dax:
302	rdpr		%tstate, %g1
303	andcc		%g1, TSTATE_PRIV, %g0
304	be,pt		%xcc, window_dax_from_user_common
305	 and		%g1, TSTATE_CWP, %g1
306
307	/* Please, see fill_fixup commentary about why we must preserve
308	 * %l5 and %l6 to preserve absolute correct semantics.
309	 */
310	rdpr		%wstate, %g2			! Grab user mode wstate.
311	wrpr		%g1, %cwp			! Get into the right window.
312	sll		%g2, 3, %g2			! NORMAL-->OTHER
313	wrpr		%g0, 0x0, %canrestore		! Standard etrap stuff.
314
315	wrpr		%g2, 0x0, %wstate		! This must be consistent.
316	wrpr		%g0, 0x0, %otherwin		! We know this.
317	call		set_pcontext			! Change contexts...
318	 nop
319	rdpr		%pstate, %l1			! Prepare to change globals.
320	mov		%g4, %o1			! Setup args for
321	mov		%g5, %o2			! final call to data_access_exception.
322	andn		%l1, PSTATE_MM, %l1		! We want to be in RMO
323
324	mov		%g6, %o7			! Stash away current.
325	wrpr		%g0, 0x0, %tl			! Out of trap levels.
326	wrpr		%l1, (PSTATE_IE | PSTATE_AG | PSTATE_RMO), %pstate
327	mov		%o7, %g6			! Get current back.
328	ldx		[%g6 + TI_TASK], %g4		! Finish it.
329#ifdef CONFIG_SMP
330	mov		TSB_REG, %g1
331	ldxa		[%g1] ASI_IMMU, %g5
332#endif
333	call		data_access_exception
334	 add		%sp, PTREGS_OFF, %o0
335
336	b,pt		%xcc, rtrap
337	 nop						! yes, the nop is correct
338spill_fixup_dax:
339	ldx		[%g6 + TI_FLAGS], %g1
340	andcc		%g1, _TIF_32BIT, %g0
341	ldub		[%g6 + TI_WSAVED], %g1
342	sll		%g1, 3, %g3
343	add		%g6, %g3, %g3
344	stx		%sp, [%g3 + TI_RWIN_SPTRS]
345
346	sll		%g1, 7, %g3
347	bne,pt		%xcc, 1f
348	 add		%g6, %g3, %g3
349	stx		%l0, [%g3 + TI_REG_WINDOW + 0x00]
350	stx		%l1, [%g3 + TI_REG_WINDOW + 0x08]
351	stx		%l2, [%g3 + TI_REG_WINDOW + 0x10]
352	stx		%l3, [%g3 + TI_REG_WINDOW + 0x18]
353	stx		%l4, [%g3 + TI_REG_WINDOW + 0x20]
354
355	stx		%l5, [%g3 + TI_REG_WINDOW + 0x28]
356	stx		%l6, [%g3 + TI_REG_WINDOW + 0x30]
357	stx		%l7, [%g3 + TI_REG_WINDOW + 0x38]
358	stx		%i0, [%g3 + TI_REG_WINDOW + 0x40]
359	stx		%i1, [%g3 + TI_REG_WINDOW + 0x48]
360	stx		%i2, [%g3 + TI_REG_WINDOW + 0x50]
361	stx		%i3, [%g3 + TI_REG_WINDOW + 0x58]
362	stx		%i4, [%g3 + TI_REG_WINDOW + 0x60]
363
364	stx		%i5, [%g3 + TI_REG_WINDOW + 0x68]
365	stx		%i6, [%g3 + TI_REG_WINDOW + 0x70]
366	stx		%i7, [%g3 + TI_REG_WINDOW + 0x78]
367	b,pt		%xcc, 2f
368	 add		%g1, 1, %g1
3691:	std		%l0, [%g3 + TI_REG_WINDOW + 0x00]
370	std		%l2, [%g3 + TI_REG_WINDOW + 0x08]
371	std		%l4, [%g3 + TI_REG_WINDOW + 0x10]
372
373	std		%l6, [%g3 + TI_REG_WINDOW + 0x18]
374	std		%i0, [%g3 + TI_REG_WINDOW + 0x20]
375	std		%i2, [%g3 + TI_REG_WINDOW + 0x28]
376	std		%i4, [%g3 + TI_REG_WINDOW + 0x30]
377	std		%i6, [%g3 + TI_REG_WINDOW + 0x38]
378	add		%g1, 1, %g1
3792:	stb		%g1, [%g6 + TI_WSAVED]
380	rdpr		%tstate, %g1
381
382	andcc		%g1, TSTATE_PRIV, %g0
383	saved
384	be,pn		%xcc, window_dax_from_user_common
385	 and		%g1, TSTATE_CWP, %g1
386	retry
387window_dax_from_user_common:
388	wrpr		%g1, %cwp
389	sethi		%hi(109f), %g7
390	ba,pt		%xcc, etrap
391109:	 or		%g7, %lo(109b), %g7
392	mov		%l4, %o1
393	mov		%l5, %o2
394	call		data_access_exception
395	 add		%sp, PTREGS_OFF, %o0
396	ba,pt		%xcc, rtrap
397	 clr		%l6
398	
399
400	.globl		cheetah_plus_patch_winfixup
401cheetah_plus_patch_winfixup:
402	sethi			%hi(cplus_wfinsn_1), %o0
403	sethi			%hi(cplus_winfixup_insn_1), %o2
404	lduw			[%o0 + %lo(cplus_wfinsn_1)], %o1
405	or			%o2, %lo(cplus_winfixup_insn_1), %o2
406	stw			%o1, [%o2]
407	flush			%o2
408
409	sethi			%hi(cplus_wfinsn_2), %o0
410	sethi			%hi(cplus_winfixup_insn_2), %o2
411	lduw			[%o0 + %lo(cplus_wfinsn_2)], %o1
412	or			%o2, %lo(cplus_winfixup_insn_2), %o2
413	stw			%o1, [%o2]
414	flush			%o2
415
416	retl
417	 nop