xref: /onnv-gate/usr/src/uts/sparc/dtrace/dtrace_asm.s (revision 3677:b34b45f03271)
10Sstevel@tonic-gate/*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*3677Ssudheer * Common Development and Distribution License (the "License").
6*3677Ssudheer * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate/*
22*3677Ssudheer * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate#pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate
280Sstevel@tonic-gate#if defined(lint) || defined(__lint)
290Sstevel@tonic-gate#include <sys/dtrace_impl.h>
300Sstevel@tonic-gate#else
310Sstevel@tonic-gate#include <sys/asm_linkage.h>
320Sstevel@tonic-gate#include <sys/privregs.h>
330Sstevel@tonic-gate#include <sys/fsr.h>
340Sstevel@tonic-gate#include <sys/asi.h>
35*3677Ssudheer#include "assym.h"
360Sstevel@tonic-gate#endif
370Sstevel@tonic-gate
380Sstevel@tonic-gate#if defined(lint) || defined(__lint)
390Sstevel@tonic-gate
400Sstevel@tonic-gateint
410Sstevel@tonic-gatedtrace_getipl(void)
420Sstevel@tonic-gate{ return (0); }
430Sstevel@tonic-gate
440Sstevel@tonic-gate#else	/* lint */
450Sstevel@tonic-gate
460Sstevel@tonic-gate	ENTRY_NP(dtrace_getipl)
470Sstevel@tonic-gate	retl
480Sstevel@tonic-gate	rdpr	%pil, %o0
490Sstevel@tonic-gate	SET_SIZE(dtrace_getipl)
500Sstevel@tonic-gate
510Sstevel@tonic-gate#endif	/* lint */
520Sstevel@tonic-gate
530Sstevel@tonic-gate#if defined(lint) || defined(__lint)
540Sstevel@tonic-gate
550Sstevel@tonic-gateuint_t
560Sstevel@tonic-gatedtrace_getotherwin(void)
570Sstevel@tonic-gate{ return (0); }
580Sstevel@tonic-gate
590Sstevel@tonic-gate#else	/* lint */
600Sstevel@tonic-gate
610Sstevel@tonic-gate	ENTRY_NP(dtrace_getotherwin)
620Sstevel@tonic-gate	retl
630Sstevel@tonic-gate	rdpr	%otherwin, %o0
640Sstevel@tonic-gate	SET_SIZE(dtrace_getotherwin)
650Sstevel@tonic-gate
660Sstevel@tonic-gate#endif	/* lint */
670Sstevel@tonic-gate
680Sstevel@tonic-gate#if defined(lint) || defined(__lint)
690Sstevel@tonic-gate
700Sstevel@tonic-gateuint_t
710Sstevel@tonic-gatedtrace_getfprs(void)
720Sstevel@tonic-gate{ return (0); }
730Sstevel@tonic-gate
740Sstevel@tonic-gate#else	/* lint */
750Sstevel@tonic-gate
760Sstevel@tonic-gate	ENTRY_NP(dtrace_getfprs)
770Sstevel@tonic-gate	retl
780Sstevel@tonic-gate	rd	%fprs, %o0
790Sstevel@tonic-gate	SET_SIZE(dtrace_getfprs)
800Sstevel@tonic-gate
810Sstevel@tonic-gate#endif	/* lint */
820Sstevel@tonic-gate
830Sstevel@tonic-gate#if defined(lint) || defined(__lint)
840Sstevel@tonic-gate
850Sstevel@tonic-gate/*ARGSUSED*/
860Sstevel@tonic-gatevoid
870Sstevel@tonic-gatedtrace_getfsr(uint64_t *val)
880Sstevel@tonic-gate{}
890Sstevel@tonic-gate
900Sstevel@tonic-gate#else	/* lint */
910Sstevel@tonic-gate
920Sstevel@tonic-gate	ENTRY_NP(dtrace_getfsr)
930Sstevel@tonic-gate	rdpr	%pstate, %o1
940Sstevel@tonic-gate	andcc	%o1, PSTATE_PEF, %g0
950Sstevel@tonic-gate	bz,pn	%xcc, 1f
960Sstevel@tonic-gate	nop
970Sstevel@tonic-gate	rd	%fprs, %o1
980Sstevel@tonic-gate	andcc	%o1, FPRS_FEF, %g0
990Sstevel@tonic-gate	bz,pn	%xcc, 1f
1000Sstevel@tonic-gate	nop
1010Sstevel@tonic-gate	retl
1020Sstevel@tonic-gate	stx	%fsr, [%o0]
1030Sstevel@tonic-gate1:
1040Sstevel@tonic-gate	retl
1050Sstevel@tonic-gate	stx	%g0, [%o0]
1060Sstevel@tonic-gate	SET_SIZE(dtrace_getfsr)
1070Sstevel@tonic-gate
1080Sstevel@tonic-gate#endif	/* lint */
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate#if defined(lint) || defined(__lint)
1110Sstevel@tonic-gate
1120Sstevel@tonic-gategreg_t
1130Sstevel@tonic-gatedtrace_getfp(void)
1140Sstevel@tonic-gate{ return (0); }
1150Sstevel@tonic-gate
1160Sstevel@tonic-gate#else	/* lint */
1170Sstevel@tonic-gate
1180Sstevel@tonic-gate	ENTRY_NP(dtrace_getfp)
1190Sstevel@tonic-gate	retl
1200Sstevel@tonic-gate	mov	%fp, %o0
1210Sstevel@tonic-gate	SET_SIZE(dtrace_getfp)
1220Sstevel@tonic-gate
1230Sstevel@tonic-gate#endif	/* lint */
1240Sstevel@tonic-gate
1250Sstevel@tonic-gate#if defined(lint) || defined(__lint)
1260Sstevel@tonic-gate
1270Sstevel@tonic-gatevoid
1280Sstevel@tonic-gatedtrace_flush_user_windows(void)
1290Sstevel@tonic-gate{}
1300Sstevel@tonic-gate
1310Sstevel@tonic-gate#else
1320Sstevel@tonic-gate
1330Sstevel@tonic-gate	ENTRY_NP(dtrace_flush_user_windows)
1340Sstevel@tonic-gate	rdpr	%otherwin, %g1
1350Sstevel@tonic-gate	brz	%g1, 3f
1360Sstevel@tonic-gate	clr	%g2
1370Sstevel@tonic-gate1:
1380Sstevel@tonic-gate	save	%sp, -WINDOWSIZE, %sp
1390Sstevel@tonic-gate	rdpr	%otherwin, %g1
1400Sstevel@tonic-gate	brnz	%g1, 1b
1410Sstevel@tonic-gate	add	%g2, 1, %g2
1420Sstevel@tonic-gate2:
1430Sstevel@tonic-gate	sub	%g2, 1, %g2		! restore back to orig window
1440Sstevel@tonic-gate	brnz	%g2, 2b
1450Sstevel@tonic-gate	restore
1460Sstevel@tonic-gate3:
1470Sstevel@tonic-gate	retl
1480Sstevel@tonic-gate	nop
1490Sstevel@tonic-gate	SET_SIZE(dtrace_flush_user_windows)
1500Sstevel@tonic-gate
1510Sstevel@tonic-gate#endif	/* lint */
1520Sstevel@tonic-gate
1530Sstevel@tonic-gate#if defined(lint) || defined(__lint)
1540Sstevel@tonic-gate
1550Sstevel@tonic-gateuint32_t
1560Sstevel@tonic-gatedtrace_cas32(uint32_t *target, uint32_t cmp, uint32_t new)
1570Sstevel@tonic-gate{
1580Sstevel@tonic-gate	uint32_t old;
1590Sstevel@tonic-gate
1600Sstevel@tonic-gate	if ((old = *target) == cmp)
1610Sstevel@tonic-gate		*target = new;
1620Sstevel@tonic-gate	return (old);
1630Sstevel@tonic-gate}
1640Sstevel@tonic-gate
1650Sstevel@tonic-gatevoid *
1660Sstevel@tonic-gatedtrace_casptr(void *target, void *cmp, void *new)
1670Sstevel@tonic-gate{
1680Sstevel@tonic-gate	void *old;
1690Sstevel@tonic-gate
1700Sstevel@tonic-gate	if ((old = *(void **)target) == cmp)
1710Sstevel@tonic-gate		*(void **)target = new;
1720Sstevel@tonic-gate	return (old);
1730Sstevel@tonic-gate}
1740Sstevel@tonic-gate
1750Sstevel@tonic-gate#else	/* lint */
1760Sstevel@tonic-gate
1770Sstevel@tonic-gate	ENTRY(dtrace_cas32)
1780Sstevel@tonic-gate	cas	[%o0], %o1, %o2
1790Sstevel@tonic-gate	retl
1800Sstevel@tonic-gate	mov	%o2, %o0
1810Sstevel@tonic-gate	SET_SIZE(dtrace_cas32)
1820Sstevel@tonic-gate
1830Sstevel@tonic-gate	ENTRY(dtrace_casptr)
1840Sstevel@tonic-gate	casn	[%o0], %o1, %o2
1850Sstevel@tonic-gate	retl
1860Sstevel@tonic-gate	mov	%o2, %o0
1870Sstevel@tonic-gate	SET_SIZE(dtrace_casptr)
1880Sstevel@tonic-gate
1890Sstevel@tonic-gate#endif	/* lint */
1900Sstevel@tonic-gate
1910Sstevel@tonic-gate#if defined(lint)
1920Sstevel@tonic-gate
1930Sstevel@tonic-gate/*ARGSUSED*/
1940Sstevel@tonic-gateuintptr_t
1950Sstevel@tonic-gatedtrace_caller(int aframes)
1960Sstevel@tonic-gate{
1970Sstevel@tonic-gate	return (0);
1980Sstevel@tonic-gate}
1990Sstevel@tonic-gate
2000Sstevel@tonic-gate#else	/* lint */
2010Sstevel@tonic-gate
2020Sstevel@tonic-gate	ENTRY(dtrace_caller)
2030Sstevel@tonic-gate	sethi	%hi(nwin_minus_one), %g4
2040Sstevel@tonic-gate	ld	[%g4 + %lo(nwin_minus_one)], %g4
2050Sstevel@tonic-gate	rdpr	%canrestore, %g2
2060Sstevel@tonic-gate	cmp	%g2, %o0
2070Sstevel@tonic-gate	bl	%icc, 1f
2080Sstevel@tonic-gate	rdpr	%cwp, %g1
2090Sstevel@tonic-gate	sub	%g1, %o0, %g3
2100Sstevel@tonic-gate	brgez,a,pt %g3, 0f
2110Sstevel@tonic-gate	wrpr	%g3, %cwp
2120Sstevel@tonic-gate
2130Sstevel@tonic-gate	!
2140Sstevel@tonic-gate	! CWP minus the number of frames is negative; we must perform the
2150Sstevel@tonic-gate	! arithmetic modulo MAXWIN.
2160Sstevel@tonic-gate	!
2170Sstevel@tonic-gate	add	%g4, %g3, %g3
2180Sstevel@tonic-gate	inc	%g3
2190Sstevel@tonic-gate	wrpr	%g3, %cwp
2200Sstevel@tonic-gate0:
2210Sstevel@tonic-gate	mov	%i7, %g4
2220Sstevel@tonic-gate	wrpr	%g1, %cwp
2230Sstevel@tonic-gate	retl
2240Sstevel@tonic-gate	mov	%g4, %o0
2250Sstevel@tonic-gate1:
2260Sstevel@tonic-gate	!
2270Sstevel@tonic-gate	! The caller has been flushed to the stack.  This is unlikely
2280Sstevel@tonic-gate	! (interrupts are disabled in dtrace_probe()), but possible (the
2290Sstevel@tonic-gate	! interrupt inducing the spill may have been taken before the
2300Sstevel@tonic-gate	! call to dtrace_probe()).
2310Sstevel@tonic-gate	!
2320Sstevel@tonic-gate	retl
2330Sstevel@tonic-gate	mov	-1, %o0
2340Sstevel@tonic-gate	SET_SIZE(dtrace_caller)
2350Sstevel@tonic-gate
2360Sstevel@tonic-gate#endif
2370Sstevel@tonic-gate
2380Sstevel@tonic-gate#if defined(lint)
2390Sstevel@tonic-gate
2400Sstevel@tonic-gate/*ARGSUSED*/
2410Sstevel@tonic-gateint
2420Sstevel@tonic-gatedtrace_fish(int aframes, int reg, uintptr_t *regval)
2430Sstevel@tonic-gate{
2440Sstevel@tonic-gate	return (0);
2450Sstevel@tonic-gate}
2460Sstevel@tonic-gate
2470Sstevel@tonic-gate#else	/* lint */
2480Sstevel@tonic-gate
2490Sstevel@tonic-gate	ENTRY(dtrace_fish)
2500Sstevel@tonic-gate
2510Sstevel@tonic-gate	rd	%pc, %g5
2520Sstevel@tonic-gate	ba	0f
2530Sstevel@tonic-gate	add	%g5, 12, %g5
2540Sstevel@tonic-gate	mov	%l0, %g4
2550Sstevel@tonic-gate	mov	%l1, %g4
2560Sstevel@tonic-gate	mov	%l2, %g4
2570Sstevel@tonic-gate	mov	%l3, %g4
2580Sstevel@tonic-gate	mov	%l4, %g4
2590Sstevel@tonic-gate	mov	%l5, %g4
2600Sstevel@tonic-gate	mov	%l6, %g4
2610Sstevel@tonic-gate	mov	%l7, %g4
2620Sstevel@tonic-gate	mov	%i0, %g4
2630Sstevel@tonic-gate	mov	%i1, %g4
2640Sstevel@tonic-gate	mov	%i2, %g4
2650Sstevel@tonic-gate	mov	%i3, %g4
2660Sstevel@tonic-gate	mov	%i4, %g4
2670Sstevel@tonic-gate	mov	%i5, %g4
2680Sstevel@tonic-gate	mov	%i6, %g4
2690Sstevel@tonic-gate	mov	%i7, %g4
2700Sstevel@tonic-gate0:
2710Sstevel@tonic-gate	sub	%o1, 16, %o1		! Can only retrieve %l's and %i's
2720Sstevel@tonic-gate	sll	%o1, 2, %o1		! Multiply by instruction size
2730Sstevel@tonic-gate	add	%g5, %o1, %g5		! %g5 now contains the instr. to pick
2740Sstevel@tonic-gate
2750Sstevel@tonic-gate	sethi	%hi(nwin_minus_one), %g4
2760Sstevel@tonic-gate	ld	[%g4 + %lo(nwin_minus_one)], %g4
2770Sstevel@tonic-gate
2780Sstevel@tonic-gate	!
2790Sstevel@tonic-gate	! First we need to see if the frame that we're fishing in is still
2800Sstevel@tonic-gate	! contained in the register windows.
2810Sstevel@tonic-gate	!
2820Sstevel@tonic-gate	rdpr	%canrestore, %g2
2830Sstevel@tonic-gate	cmp	%g2, %o0
2840Sstevel@tonic-gate	bl	%icc, 2f
2850Sstevel@tonic-gate	rdpr	%cwp, %g1
2860Sstevel@tonic-gate	sub	%g1, %o0, %g3
2870Sstevel@tonic-gate	brgez,a,pt %g3, 0f
2880Sstevel@tonic-gate	wrpr	%g3, %cwp
2890Sstevel@tonic-gate
2900Sstevel@tonic-gate	!
2910Sstevel@tonic-gate	! CWP minus the number of frames is negative; we must perform the
2920Sstevel@tonic-gate	! arithmetic modulo MAXWIN.
2930Sstevel@tonic-gate	!
2940Sstevel@tonic-gate	add	%g4, %g3, %g3
2950Sstevel@tonic-gate	inc	%g3
2960Sstevel@tonic-gate	wrpr	%g3, %cwp
2970Sstevel@tonic-gate0:
2980Sstevel@tonic-gate	jmp	%g5
2990Sstevel@tonic-gate	ba	1f
3000Sstevel@tonic-gate1:
3010Sstevel@tonic-gate	wrpr	%g1, %cwp
3020Sstevel@tonic-gate	stn	%g4, [%o2]
3030Sstevel@tonic-gate	retl
3040Sstevel@tonic-gate	clr	%o0			! Success; return 0.
3050Sstevel@tonic-gate2:
3060Sstevel@tonic-gate	!
3070Sstevel@tonic-gate	! The frame that we're looking for has been flushed to the stack; the
3080Sstevel@tonic-gate	! caller will be forced to
3090Sstevel@tonic-gate	!
3100Sstevel@tonic-gate	retl
3110Sstevel@tonic-gate	add	%g2, 1, %o0		! Failure; return deepest frame + 1
3120Sstevel@tonic-gate	SET_SIZE(dtrace_fish)
3130Sstevel@tonic-gate
3140Sstevel@tonic-gate#endif
3150Sstevel@tonic-gate
3160Sstevel@tonic-gate#if defined(lint)
3170Sstevel@tonic-gate
3180Sstevel@tonic-gate/*ARGSUSED*/
3190Sstevel@tonic-gatevoid
320*3677Ssudheerdtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size,
321*3677Ssudheer    volatile uint16_t *flags)
3220Sstevel@tonic-gate{}
3230Sstevel@tonic-gate
3240Sstevel@tonic-gate#else
3250Sstevel@tonic-gate
3260Sstevel@tonic-gate	ENTRY(dtrace_copyin)
3270Sstevel@tonic-gate	tst	%o2
328*3677Ssudheer	bz	2f
3290Sstevel@tonic-gate	clr	%g1
3300Sstevel@tonic-gate	lduba	[%o0 + %g1]ASI_USER, %g2
3310Sstevel@tonic-gate0:
332*3677Ssudheer	! check for an error if the count is 4k-aligned
333*3677Ssudheer	andcc	%g1, 0xfff, %g0
334*3677Ssudheer	bnz,pt	%icc, 1f
3350Sstevel@tonic-gate	stub	%g2, [%o1 + %g1]
336*3677Ssudheer	lduh	[%o3], %g3
337*3677Ssudheer	andcc	%g3, CPU_DTRACE_BADADDR, %g0
338*3677Ssudheer	bnz,pn	%icc, 2f
339*3677Ssudheer	nop
340*3677Ssudheer1:
3410Sstevel@tonic-gate	inc	%g1
3420Sstevel@tonic-gate	cmp	%g1, %o2
3430Sstevel@tonic-gate	bl,a	0b
3440Sstevel@tonic-gate	lduba	[%o0 + %g1]ASI_USER, %g2
345*3677Ssudheer2:
3460Sstevel@tonic-gate	retl
3470Sstevel@tonic-gate	nop
3480Sstevel@tonic-gate
3490Sstevel@tonic-gate	SET_SIZE(dtrace_copyin)
3500Sstevel@tonic-gate
3510Sstevel@tonic-gate#endif
3520Sstevel@tonic-gate
3530Sstevel@tonic-gate#if defined(lint)
3540Sstevel@tonic-gate
3550Sstevel@tonic-gate/*ARGSUSED*/
3560Sstevel@tonic-gatevoid
357*3677Ssudheerdtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
358*3677Ssudheer    volatile  uint16_t *flags)
3590Sstevel@tonic-gate{}
3600Sstevel@tonic-gate
3610Sstevel@tonic-gate#else
3620Sstevel@tonic-gate
3630Sstevel@tonic-gate	ENTRY(dtrace_copyinstr)
3640Sstevel@tonic-gate	tst	%o2
365*3677Ssudheer	bz	2f
3660Sstevel@tonic-gate	clr	%g1
3670Sstevel@tonic-gate	lduba	[%o0 + %g1]ASI_USER, %g2
3680Sstevel@tonic-gate0:
3690Sstevel@tonic-gate	stub	%g2, [%o1 + %g1]		! Store byte
370*3677Ssudheer
371*3677Ssudheer	! check for an error if the count is 4k-aligned
372*3677Ssudheer	andcc	%g1, 0xfff, %g0
373*3677Ssudheer	bnz,pt	%icc, 1f
374*3677Ssudheer	inc	%g1
375*3677Ssudheer	lduh	[%o3], %g3
376*3677Ssudheer	andcc	%g3, CPU_DTRACE_BADADDR, %g0
377*3677Ssudheer	bnz,pn	%icc, 2f
378*3677Ssudheer	nop
379*3677Ssudheer1:
3800Sstevel@tonic-gate	cmp	%g2, 0				! Was that '\0'?
381*3677Ssudheer	be	2f				! If so, we're done
3820Sstevel@tonic-gate	cmp	%g1, %o2			! Compare to limit
3830Sstevel@tonic-gate	bl,a	0b				! If less, take another lap
3840Sstevel@tonic-gate	lduba	[%o0 + %g1]ASI_USER, %g2	!   delay: load user byte
385*3677Ssudheer2:
3860Sstevel@tonic-gate	retl
3870Sstevel@tonic-gate	nop
3880Sstevel@tonic-gate
3890Sstevel@tonic-gate	SET_SIZE(dtrace_copyinstr)
3900Sstevel@tonic-gate
3910Sstevel@tonic-gate#endif
3920Sstevel@tonic-gate
3930Sstevel@tonic-gate#if defined(lint)
3940Sstevel@tonic-gate
3950Sstevel@tonic-gate/*ARGSUSED*/
3960Sstevel@tonic-gatevoid
397*3677Ssudheerdtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size,
398*3677Ssudheer    volatile  uint16_t *flags)
3990Sstevel@tonic-gate{}
4000Sstevel@tonic-gate
4010Sstevel@tonic-gate#else
4020Sstevel@tonic-gate
4030Sstevel@tonic-gate	ENTRY(dtrace_copyout)
4040Sstevel@tonic-gate	tst	%o2
405*3677Ssudheer	bz	2f
4060Sstevel@tonic-gate	clr	%g1
4070Sstevel@tonic-gate	ldub	[%o0 + %g1], %g2
4080Sstevel@tonic-gate0:
409*3677Ssudheer	! check for an error if the count is 4k-aligned
410*3677Ssudheer	andcc	%g1, 0xfff, %g0
411*3677Ssudheer	bnz,pt	%icc, 1f
4120Sstevel@tonic-gate	stba	%g2, [%o1 + %g1]ASI_USER
413*3677Ssudheer	lduh	[%o3], %g3
414*3677Ssudheer	andcc	%g3, CPU_DTRACE_BADADDR, %g0
415*3677Ssudheer	bnz,pn	%icc, 2f
416*3677Ssudheer	nop
417*3677Ssudheer1:
4180Sstevel@tonic-gate	inc	%g1
4190Sstevel@tonic-gate	cmp	%g1, %o2
4200Sstevel@tonic-gate	bl,a	0b
4210Sstevel@tonic-gate	ldub	[%o0 + %g1], %g2
422*3677Ssudheer2:
4230Sstevel@tonic-gate	retl
4240Sstevel@tonic-gate	nop
4250Sstevel@tonic-gate	SET_SIZE(dtrace_copyout)
4260Sstevel@tonic-gate
4270Sstevel@tonic-gate#endif
4280Sstevel@tonic-gate
4290Sstevel@tonic-gate#if defined(lint)
4300Sstevel@tonic-gate
4310Sstevel@tonic-gate/*ARGSUSED*/
4320Sstevel@tonic-gatevoid
433*3677Ssudheerdtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size,
434*3677Ssudheer    volatile  uint16_t *flags)
4350Sstevel@tonic-gate{}
4360Sstevel@tonic-gate
4370Sstevel@tonic-gate#else
4380Sstevel@tonic-gate
4390Sstevel@tonic-gate	ENTRY(dtrace_copyoutstr)
4400Sstevel@tonic-gate	tst	%o2
441*3677Ssudheer	bz	2f
4420Sstevel@tonic-gate	clr	%g1
4430Sstevel@tonic-gate	ldub	[%o0 + %g1], %g2
4440Sstevel@tonic-gate0:
4450Sstevel@tonic-gate	stba	%g2, [%o1 + %g1]ASI_USER
446*3677Ssudheer
447*3677Ssudheer	! check for an error if the count is 4k-aligned
448*3677Ssudheer	andcc	%g1, 0xfff, %g0
449*3677Ssudheer	bnz,pt  %icc, 1f
450*3677Ssudheer	inc	%g1
451*3677Ssudheer	lduh	[%o3], %g3
452*3677Ssudheer	andcc	%g3, CPU_DTRACE_BADADDR, %g0
453*3677Ssudheer	bnz,pn	%icc, 2f
454*3677Ssudheer	nop
455*3677Ssudheer1:
4560Sstevel@tonic-gate	cmp	%g2, 0
457*3677Ssudheer	be	2f
4580Sstevel@tonic-gate	cmp	%g1, %o2
4590Sstevel@tonic-gate	bl,a	0b
4600Sstevel@tonic-gate	ldub	[%o0 + %g1], %g2
461*3677Ssudheer2:
4620Sstevel@tonic-gate	retl
4630Sstevel@tonic-gate	nop
4640Sstevel@tonic-gate	SET_SIZE(dtrace_copyoutstr)
4650Sstevel@tonic-gate
4660Sstevel@tonic-gate#endif
4670Sstevel@tonic-gate
4680Sstevel@tonic-gate#if defined(lint)
4690Sstevel@tonic-gate
4700Sstevel@tonic-gate/*ARGSUSED*/
4710Sstevel@tonic-gateuintptr_t
4720Sstevel@tonic-gatedtrace_fulword(void *addr)
4730Sstevel@tonic-gate{ return (0); }
4740Sstevel@tonic-gate
4750Sstevel@tonic-gate#else
4760Sstevel@tonic-gate
4770Sstevel@tonic-gate	ENTRY(dtrace_fulword)
4780Sstevel@tonic-gate	clr	%o1
4790Sstevel@tonic-gate	ldna	[%o0]ASI_USER, %o1
4800Sstevel@tonic-gate	retl
4810Sstevel@tonic-gate	mov	%o1, %o0
4820Sstevel@tonic-gate	SET_SIZE(dtrace_fulword)
4830Sstevel@tonic-gate
4840Sstevel@tonic-gate#endif
4850Sstevel@tonic-gate
4860Sstevel@tonic-gate#if defined(lint)
4870Sstevel@tonic-gate
4880Sstevel@tonic-gate/*ARGSUSED*/
4890Sstevel@tonic-gateuint8_t
4900Sstevel@tonic-gatedtrace_fuword8(void *addr)
4910Sstevel@tonic-gate{ return (0); }
4920Sstevel@tonic-gate
4930Sstevel@tonic-gate#else
4940Sstevel@tonic-gate
4950Sstevel@tonic-gate	ENTRY(dtrace_fuword8)
4960Sstevel@tonic-gate	clr	%o1
4970Sstevel@tonic-gate	lduba	[%o0]ASI_USER, %o1
4980Sstevel@tonic-gate	retl
4990Sstevel@tonic-gate	mov	%o1, %o0
5000Sstevel@tonic-gate	SET_SIZE(dtrace_fuword8)
5010Sstevel@tonic-gate
5020Sstevel@tonic-gate#endif
5030Sstevel@tonic-gate
5040Sstevel@tonic-gate#if defined(lint)
5050Sstevel@tonic-gate
5060Sstevel@tonic-gate/*ARGSUSED*/
5070Sstevel@tonic-gateuint16_t
5080Sstevel@tonic-gatedtrace_fuword16(void *addr)
5090Sstevel@tonic-gate{ return (0); }
5100Sstevel@tonic-gate
5110Sstevel@tonic-gate#else
5120Sstevel@tonic-gate
5130Sstevel@tonic-gate	ENTRY(dtrace_fuword16)
5140Sstevel@tonic-gate	clr	%o1
5150Sstevel@tonic-gate	lduha	[%o0]ASI_USER, %o1
5160Sstevel@tonic-gate	retl
5170Sstevel@tonic-gate	mov	%o1, %o0
5180Sstevel@tonic-gate	SET_SIZE(dtrace_fuword16)
5190Sstevel@tonic-gate
5200Sstevel@tonic-gate#endif
5210Sstevel@tonic-gate
5220Sstevel@tonic-gate#if defined(lint)
5230Sstevel@tonic-gate
5240Sstevel@tonic-gate/*ARGSUSED*/
5250Sstevel@tonic-gateuint32_t
5260Sstevel@tonic-gatedtrace_fuword32(void *addr)
5270Sstevel@tonic-gate{ return (0); }
5280Sstevel@tonic-gate
5290Sstevel@tonic-gate#else
5300Sstevel@tonic-gate
5310Sstevel@tonic-gate	ENTRY(dtrace_fuword32)
5320Sstevel@tonic-gate	clr	%o1
5330Sstevel@tonic-gate	lda	[%o0]ASI_USER, %o1
5340Sstevel@tonic-gate	retl
5350Sstevel@tonic-gate	mov	%o1, %o0
5360Sstevel@tonic-gate	SET_SIZE(dtrace_fuword32)
5370Sstevel@tonic-gate
5380Sstevel@tonic-gate#endif
5390Sstevel@tonic-gate
5400Sstevel@tonic-gate#if defined(lint)
5410Sstevel@tonic-gate
5420Sstevel@tonic-gate/*ARGSUSED*/
5430Sstevel@tonic-gateuint64_t
5440Sstevel@tonic-gatedtrace_fuword64(void *addr)
5450Sstevel@tonic-gate{ return (0); }
5460Sstevel@tonic-gate
5470Sstevel@tonic-gate#else
5480Sstevel@tonic-gate
5490Sstevel@tonic-gate	ENTRY(dtrace_fuword64)
5500Sstevel@tonic-gate	clr	%o1
5510Sstevel@tonic-gate	ldxa	[%o0]ASI_USER, %o1
5520Sstevel@tonic-gate	retl
5530Sstevel@tonic-gate	mov	%o1, %o0
5540Sstevel@tonic-gate	SET_SIZE(dtrace_fuword64)
5550Sstevel@tonic-gate
5560Sstevel@tonic-gate#endif
5570Sstevel@tonic-gate
5580Sstevel@tonic-gate#if defined(lint)
5590Sstevel@tonic-gate
5600Sstevel@tonic-gate/*ARGSUSED*/
5610Sstevel@tonic-gateint
5620Sstevel@tonic-gatedtrace_getupcstack_top(uint64_t *pcstack, int pcstack_limit, uintptr_t *sp)
5630Sstevel@tonic-gate{ return (0); }
5640Sstevel@tonic-gate
5650Sstevel@tonic-gate#else
5660Sstevel@tonic-gate
5670Sstevel@tonic-gate	/*
5680Sstevel@tonic-gate	 * %g1	pcstack
5690Sstevel@tonic-gate	 * %g2	current window
5700Sstevel@tonic-gate	 * %g3	maxwin (nwindows - 1)
5710Sstevel@tonic-gate	 * %g4	saved %cwp (so we can get back to the original window)
5720Sstevel@tonic-gate	 * %g5	iteration count
5730Sstevel@tonic-gate	 * %g6	saved %fp
5740Sstevel@tonic-gate	 *
5750Sstevel@tonic-gate	 * %o0	pcstack / return value (iteration count)
5760Sstevel@tonic-gate	 * %o1	pcstack_limit
5770Sstevel@tonic-gate	 * %o2	last_fp
5780Sstevel@tonic-gate	 */
5790Sstevel@tonic-gate
5800Sstevel@tonic-gate	ENTRY(dtrace_getupcstack_top)
5810Sstevel@tonic-gate	mov	%o0, %g1		! we need the pcstack pointer while
5820Sstevel@tonic-gate					! we're visiting other windows
5830Sstevel@tonic-gate
5840Sstevel@tonic-gate	rdpr	%otherwin, %g5		! compute the number of iterations
5850Sstevel@tonic-gate	cmp	%g5, %o1		! (windows to observe) by taking the
5860Sstevel@tonic-gate	movg	%icc, %o1, %g5		! min of %otherwin and pcstack_limit
5870Sstevel@tonic-gate
5880Sstevel@tonic-gate	brlez,a,pn %g5, 2f		! return 0 if count <= 0
5890Sstevel@tonic-gate	clr	%o0
5900Sstevel@tonic-gate
5910Sstevel@tonic-gate	sethi	%hi(nwin_minus_one), %g3 ! hang onto maxwin since we'll need
5920Sstevel@tonic-gate	ld	[%g3 + %lo(nwin_minus_one)], %g3 ! it for our modular arithmetic
5930Sstevel@tonic-gate
5940Sstevel@tonic-gate	rdpr	%cwp, %g4		! remember our window so we can return
5950Sstevel@tonic-gate	rdpr	%canrestore, %g2	! compute the first non-user window
596191Sahl	subcc	%g4, %g2, %g2		! current = %cwp - %canrestore
5970Sstevel@tonic-gate
5980Sstevel@tonic-gate	bge,pt	%xcc, 1f		! good to go if current is >= 0
5990Sstevel@tonic-gate	mov	%g5, %o0		! we need to return the count
6000Sstevel@tonic-gate
6010Sstevel@tonic-gate	add	%g2, %g3, %g2		! normalize our current window if it's
6020Sstevel@tonic-gate	add	%g2, 1, %g2		! less than zero
6030Sstevel@tonic-gate
6040Sstevel@tonic-gate	! note that while it's tempting, we can't execute restore to decrement
6050Sstevel@tonic-gate	! the %cwp by one (mod nwindows) because we're in the user's windows
6060Sstevel@tonic-gate1:
6070Sstevel@tonic-gate	deccc	%g2			! decrement the current window
6080Sstevel@tonic-gate	movl	%xcc, %g3, %g2		! normalize if it's negative (-1)
6090Sstevel@tonic-gate
6100Sstevel@tonic-gate	wrpr	%g2, %cwp		! change windows
6110Sstevel@tonic-gate
6120Sstevel@tonic-gate	stx	%i7, [%g1]		! stash the return address in pcstack
6130Sstevel@tonic-gate
6140Sstevel@tonic-gate	deccc	%g5			! decrement the count
6150Sstevel@tonic-gate	bnz,pt	%icc, 1b		! we iterate until the count reaches 0
6160Sstevel@tonic-gate	add	%g1, 8, %g1		! increment the pcstack pointer
6170Sstevel@tonic-gate
6180Sstevel@tonic-gate	mov	%i6, %g6		! stash the last frame pointer we
6190Sstevel@tonic-gate					! encounter so the caller can
6200Sstevel@tonic-gate					! continue the stack walk in memory
6210Sstevel@tonic-gate
6220Sstevel@tonic-gate	wrpr	%g4, %cwp		! change back to the original window
6230Sstevel@tonic-gate
6240Sstevel@tonic-gate	stn	%g6, [%o2]		! return the last frame pointer
6250Sstevel@tonic-gate
6260Sstevel@tonic-gate2:
6270Sstevel@tonic-gate	retl
6280Sstevel@tonic-gate	nop
6290Sstevel@tonic-gate	SET_SIZE(dtrace_getupcstack_top)
6300Sstevel@tonic-gate
6310Sstevel@tonic-gate#endif
6320Sstevel@tonic-gate
633191Sahl#if defined(lint)
634191Sahl
635191Sahl/*ARGSUSED*/
636191Sahlint
637191Sahldtrace_getustackdepth_top(uintptr_t *sp)
638191Sahl{ return (0); }
639191Sahl
640191Sahl#else
641191Sahl
642191Sahl	ENTRY(dtrace_getustackdepth_top)
643191Sahl	mov	%o0, %o2
644191Sahl	rdpr	%otherwin, %o0
645191Sahl
646191Sahl	brlez,a,pn %o0, 2f		! return 0 if there are no user wins
647191Sahl	clr	%o0
648191Sahl
649191Sahl	rdpr	%cwp, %g4		! remember our window so we can return
650191Sahl	rdpr	%canrestore, %g2	! compute the first user window
651191Sahl	sub	%g4, %g2, %g2		! current = %cwp - %canrestore -
652191Sahl	subcc	%g2, %o0, %g2		!     %otherwin
653191Sahl
654191Sahl	bge,pt	%xcc, 1f		! normalize the window if necessary
655191Sahl	sethi	%hi(nwin_minus_one), %g3
656191Sahl	ld	[%g3 + %lo(nwin_minus_one)], %g3
657191Sahl	add	%g2, %g3, %g2
658191Sahl	add	%g2, 1, %g2
659191Sahl
660191Sahl1:
661191Sahl	wrpr	%g2, %cwp		! change to the first user window
662191Sahl	mov	%i6, %g6		! stash the frame pointer
663191Sahl	wrpr	%g4, %cwp		! change back to the original window
664191Sahl
665191Sahl	stn	%g6, [%o2]		! return the frame pointer
666191Sahl
667191Sahl2:
668191Sahl	retl
669191Sahl	nop
670191Sahl	SET_SIZE(dtrace_getustackdepth_top)
671191Sahl
672191Sahl#endif
673191Sahl
6740Sstevel@tonic-gate#if defined(lint) || defined(__lint)
6750Sstevel@tonic-gate
6760Sstevel@tonic-gate/* ARGSUSED */
6770Sstevel@tonic-gateulong_t
6780Sstevel@tonic-gatedtrace_getreg_win(uint_t reg, uint_t depth)
6790Sstevel@tonic-gate{ return (0); }
6800Sstevel@tonic-gate
6810Sstevel@tonic-gate#else	/* lint */
6820Sstevel@tonic-gate
6830Sstevel@tonic-gate	ENTRY(dtrace_getreg_win)
6840Sstevel@tonic-gate	sub	%o0, 16, %o0
6850Sstevel@tonic-gate	cmp	%o0, 16			! %o0 must begin in the range [16..32)
6860Sstevel@tonic-gate	blu,pt	%xcc, 1f
6870Sstevel@tonic-gate	nop
6880Sstevel@tonic-gate	retl
6890Sstevel@tonic-gate	clr	%o0
6900Sstevel@tonic-gate
6910Sstevel@tonic-gate1:
6920Sstevel@tonic-gate	set	dtrace_getreg_win_table, %g3
6930Sstevel@tonic-gate	sll	%o0, 2, %o0
6940Sstevel@tonic-gate	add	%g3, %o0, %g3
6950Sstevel@tonic-gate
6960Sstevel@tonic-gate	rdpr	%canrestore, %o3
6970Sstevel@tonic-gate	rdpr	%cwp, %g2
6980Sstevel@tonic-gate
6990Sstevel@tonic-gate	! Set %cwp to be (%cwp - %canrestore - %o1) mod NWINDOWS
7000Sstevel@tonic-gate
7010Sstevel@tonic-gate	sub	%g2, %o3, %o2		! %o2 is %cwp - %canrestore
7020Sstevel@tonic-gate	subcc	%o2, %o1, %o4
7030Sstevel@tonic-gate	bge,a,pn %xcc, 2f
7040Sstevel@tonic-gate	wrpr	%o4, %cwp
7050Sstevel@tonic-gate
7060Sstevel@tonic-gate	sethi	%hi(nwin_minus_one), %o3
7070Sstevel@tonic-gate	ld	[%o3 + %lo(nwin_minus_one)], %o3
7080Sstevel@tonic-gate
7090Sstevel@tonic-gate	add	%o2, %o3, %o4
7100Sstevel@tonic-gate	wrpr	%o4, %cwp
7110Sstevel@tonic-gate2:
7120Sstevel@tonic-gate	jmp	%g3
7130Sstevel@tonic-gate	ba	3f
7140Sstevel@tonic-gate3:
7150Sstevel@tonic-gate	wrpr	%g2, %cwp
7160Sstevel@tonic-gate	retl
7170Sstevel@tonic-gate	mov	%g1, %o0
7180Sstevel@tonic-gate
7190Sstevel@tonic-gatedtrace_getreg_win_table:
7200Sstevel@tonic-gate	mov	%l0, %g1
7210Sstevel@tonic-gate	mov	%l1, %g1
7220Sstevel@tonic-gate	mov	%l2, %g1
7230Sstevel@tonic-gate	mov	%l3, %g1
7240Sstevel@tonic-gate	mov	%l4, %g1
7250Sstevel@tonic-gate	mov	%l5, %g1
7260Sstevel@tonic-gate	mov	%l6, %g1
7270Sstevel@tonic-gate	mov	%l7, %g1
7280Sstevel@tonic-gate	mov	%i0, %g1
7290Sstevel@tonic-gate	mov	%i1, %g1
7300Sstevel@tonic-gate	mov	%i2, %g1
7310Sstevel@tonic-gate	mov	%i3, %g1
7320Sstevel@tonic-gate	mov	%i4, %g1
7330Sstevel@tonic-gate	mov	%i5, %g1
7340Sstevel@tonic-gate	mov	%i6, %g1
7350Sstevel@tonic-gate	mov	%i7, %g1
7360Sstevel@tonic-gate	SET_SIZE(dtrace_getreg_win)
7370Sstevel@tonic-gate
7380Sstevel@tonic-gate#endif	/* lint */
7390Sstevel@tonic-gate
7400Sstevel@tonic-gate#if defined(lint) || defined(__lint)
7410Sstevel@tonic-gate
7420Sstevel@tonic-gate/* ARGSUSED */
7430Sstevel@tonic-gatevoid
7440Sstevel@tonic-gatedtrace_putreg_win(uint_t reg, ulong_t value)
7450Sstevel@tonic-gate{}
7460Sstevel@tonic-gate
7470Sstevel@tonic-gate#else	/* lint */
7480Sstevel@tonic-gate
7490Sstevel@tonic-gate	ENTRY(dtrace_putreg_win)
7500Sstevel@tonic-gate	sub	%o0, 16, %o0
7510Sstevel@tonic-gate	cmp	%o0, 16			! %o0 must be in the range [16..32)
7520Sstevel@tonic-gate	blu,pt	%xcc, 1f
7530Sstevel@tonic-gate	nop
7540Sstevel@tonic-gate	retl
7550Sstevel@tonic-gate	nop
7560Sstevel@tonic-gate
7570Sstevel@tonic-gate1:
7580Sstevel@tonic-gate	mov	%o1, %g1		! move the value into a global register
7590Sstevel@tonic-gate
7600Sstevel@tonic-gate	set	dtrace_putreg_table, %g3
7610Sstevel@tonic-gate	sll	%o0, 2, %o0
7620Sstevel@tonic-gate	add	%g3, %o0, %g3
7630Sstevel@tonic-gate
7640Sstevel@tonic-gate	rdpr	%canrestore, %o3
7650Sstevel@tonic-gate	rdpr	%cwp, %g2
7660Sstevel@tonic-gate
7670Sstevel@tonic-gate	! Set %cwp to be (%cwp - %canrestore - 1) mod NWINDOWS
7680Sstevel@tonic-gate
7690Sstevel@tonic-gate	sub	%g2, %o3, %o2		! %o2 is %cwp - %canrestore
7700Sstevel@tonic-gate	subcc	%o2, 1, %o4
7710Sstevel@tonic-gate	bge,a,pn %xcc, 2f
7720Sstevel@tonic-gate	wrpr	%o4, %cwp
7730Sstevel@tonic-gate
7740Sstevel@tonic-gate	sethi	%hi(nwin_minus_one), %o3
7750Sstevel@tonic-gate	ld	[%o3 + %lo(nwin_minus_one)], %o3
7760Sstevel@tonic-gate	add	%o2, %o3, %o4
7770Sstevel@tonic-gate	wrpr	%o4, %cwp
7780Sstevel@tonic-gate2:
7790Sstevel@tonic-gate	jmp	%g3
7800Sstevel@tonic-gate	ba	3f
7810Sstevel@tonic-gate3:
7820Sstevel@tonic-gate	wrpr	%g2, %cwp
7830Sstevel@tonic-gate	retl
7840Sstevel@tonic-gate	nop
7850Sstevel@tonic-gate
7860Sstevel@tonic-gatedtrace_putreg_table:
7870Sstevel@tonic-gate	mov	%g1, %l0
7880Sstevel@tonic-gate	mov	%g1, %l1
7890Sstevel@tonic-gate	mov	%g1, %l2
7900Sstevel@tonic-gate	mov	%g1, %l3
7910Sstevel@tonic-gate	mov	%g1, %l4
7920Sstevel@tonic-gate	mov	%g1, %l5
7930Sstevel@tonic-gate	mov	%g1, %l6
7940Sstevel@tonic-gate	mov	%g1, %l7
7950Sstevel@tonic-gate	mov	%g1, %i0
7960Sstevel@tonic-gate	mov	%g1, %i1
7970Sstevel@tonic-gate	mov	%g1, %i2
7980Sstevel@tonic-gate	mov	%g1, %i3
7990Sstevel@tonic-gate	mov	%g1, %i4
8000Sstevel@tonic-gate	mov	%g1, %i5
8010Sstevel@tonic-gate	mov	%g1, %i6
8020Sstevel@tonic-gate	mov	%g1, %i7
8030Sstevel@tonic-gate	SET_SIZE(dtrace_putreg_win)
8040Sstevel@tonic-gate
8050Sstevel@tonic-gate#endif	/* lint */
8060Sstevel@tonic-gate
8070Sstevel@tonic-gate#if defined(lint) || defined(__lint)
8080Sstevel@tonic-gate
8090Sstevel@tonic-gate/*ARGSUSED*/
8100Sstevel@tonic-gatevoid
8110Sstevel@tonic-gatedtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which,
8120Sstevel@tonic-gate    int fault, int fltoffs, uintptr_t illval)
8130Sstevel@tonic-gate{}
8140Sstevel@tonic-gate
8150Sstevel@tonic-gate#else	/* lint */
8160Sstevel@tonic-gate
8170Sstevel@tonic-gate	ENTRY(dtrace_probe_error)
8180Sstevel@tonic-gate	save	%sp, -SA(MINFRAME), %sp
8190Sstevel@tonic-gate	sethi	%hi(dtrace_probeid_error), %l0
8200Sstevel@tonic-gate	ld	[%l0 + %lo(dtrace_probeid_error)], %o0
8210Sstevel@tonic-gate	mov	%i0, %o1
8220Sstevel@tonic-gate	mov	%i1, %o2
8230Sstevel@tonic-gate	mov	%i2, %o3
8240Sstevel@tonic-gate	mov	%i3, %o4
8250Sstevel@tonic-gate	call	dtrace_probe
8260Sstevel@tonic-gate	mov	%i4, %o5
8270Sstevel@tonic-gate	ret
8280Sstevel@tonic-gate	restore
8290Sstevel@tonic-gate	SET_SIZE(dtrace_probe_error)
8300Sstevel@tonic-gate
8310Sstevel@tonic-gate#endif
832