/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #if defined(lint) || defined(__lint) #include #else #include #include #include #include #endif #if defined(lint) || defined(__lint) int dtrace_getipl(void) { return (0); } #else /* lint */ ENTRY_NP(dtrace_getipl) retl rdpr %pil, %o0 SET_SIZE(dtrace_getipl) #endif /* lint */ #if defined(lint) || defined(__lint) uint_t dtrace_getotherwin(void) { return (0); } #else /* lint */ ENTRY_NP(dtrace_getotherwin) retl rdpr %otherwin, %o0 SET_SIZE(dtrace_getotherwin) #endif /* lint */ #if defined(lint) || defined(__lint) uint_t dtrace_getfprs(void) { return (0); } #else /* lint */ ENTRY_NP(dtrace_getfprs) retl rd %fprs, %o0 SET_SIZE(dtrace_getfprs) #endif /* lint */ #if defined(lint) || defined(__lint) /*ARGSUSED*/ void dtrace_getfsr(uint64_t *val) {} #else /* lint */ ENTRY_NP(dtrace_getfsr) rdpr %pstate, %o1 andcc %o1, PSTATE_PEF, %g0 bz,pn %xcc, 1f nop rd %fprs, %o1 andcc %o1, FPRS_FEF, %g0 bz,pn %xcc, 1f nop retl stx %fsr, [%o0] 1: retl stx %g0, [%o0] SET_SIZE(dtrace_getfsr) #endif /* lint */ #if defined(lint) || defined(__lint) greg_t dtrace_getfp(void) { return (0); } #else /* lint */ ENTRY_NP(dtrace_getfp) retl mov %fp, %o0 SET_SIZE(dtrace_getfp) #endif /* lint */ #if defined(lint) || defined(__lint) void dtrace_flush_user_windows(void) {} #else ENTRY_NP(dtrace_flush_user_windows) rdpr %otherwin, %g1 brz %g1, 3f clr %g2 1: save %sp, -WINDOWSIZE, %sp rdpr %otherwin, %g1 brnz %g1, 1b add %g2, 1, %g2 2: sub %g2, 1, %g2 ! restore back to orig window brnz %g2, 2b restore 3: retl nop SET_SIZE(dtrace_flush_user_windows) #endif /* lint */ #if defined(lint) || defined(__lint) uint32_t dtrace_cas32(uint32_t *target, uint32_t cmp, uint32_t new) { uint32_t old; if ((old = *target) == cmp) *target = new; return (old); } void * dtrace_casptr(void *target, void *cmp, void *new) { void *old; if ((old = *(void **)target) == cmp) *(void **)target = new; return (old); } #else /* lint */ ENTRY(dtrace_cas32) cas [%o0], %o1, %o2 retl mov %o2, %o0 SET_SIZE(dtrace_cas32) ENTRY(dtrace_casptr) casn [%o0], %o1, %o2 retl mov %o2, %o0 SET_SIZE(dtrace_casptr) #endif /* lint */ #if defined(lint) /*ARGSUSED*/ uintptr_t dtrace_caller(int aframes) { return (0); } #else /* lint */ ENTRY(dtrace_caller) sethi %hi(nwin_minus_one), %g4 ld [%g4 + %lo(nwin_minus_one)], %g4 rdpr %canrestore, %g2 cmp %g2, %o0 bl %icc, 1f rdpr %cwp, %g1 sub %g1, %o0, %g3 brgez,a,pt %g3, 0f wrpr %g3, %cwp ! ! CWP minus the number of frames is negative; we must perform the ! arithmetic modulo MAXWIN. ! add %g4, %g3, %g3 inc %g3 wrpr %g3, %cwp 0: mov %i7, %g4 wrpr %g1, %cwp retl mov %g4, %o0 1: ! ! The caller has been flushed to the stack. This is unlikely ! (interrupts are disabled in dtrace_probe()), but possible (the ! interrupt inducing the spill may have been taken before the ! call to dtrace_probe()). ! retl mov -1, %o0 SET_SIZE(dtrace_caller) #endif #if defined(lint) /*ARGSUSED*/ int dtrace_fish(int aframes, int reg, uintptr_t *regval) { return (0); } #else /* lint */ ENTRY(dtrace_fish) rd %pc, %g5 ba 0f add %g5, 12, %g5 mov %l0, %g4 mov %l1, %g4 mov %l2, %g4 mov %l3, %g4 mov %l4, %g4 mov %l5, %g4 mov %l6, %g4 mov %l7, %g4 mov %i0, %g4 mov %i1, %g4 mov %i2, %g4 mov %i3, %g4 mov %i4, %g4 mov %i5, %g4 mov %i6, %g4 mov %i7, %g4 0: sub %o1, 16, %o1 ! Can only retrieve %l's and %i's sll %o1, 2, %o1 ! Multiply by instruction size add %g5, %o1, %g5 ! %g5 now contains the instr. to pick sethi %hi(nwin_minus_one), %g4 ld [%g4 + %lo(nwin_minus_one)], %g4 ! ! First we need to see if the frame that we're fishing in is still ! contained in the register windows. ! rdpr %canrestore, %g2 cmp %g2, %o0 bl %icc, 2f rdpr %cwp, %g1 sub %g1, %o0, %g3 brgez,a,pt %g3, 0f wrpr %g3, %cwp ! ! CWP minus the number of frames is negative; we must perform the ! arithmetic modulo MAXWIN. ! add %g4, %g3, %g3 inc %g3 wrpr %g3, %cwp 0: jmp %g5 ba 1f 1: wrpr %g1, %cwp stn %g4, [%o2] retl clr %o0 ! Success; return 0. 2: ! ! The frame that we're looking for has been flushed to the stack; the ! caller will be forced to ! retl add %g2, 1, %o0 ! Failure; return deepest frame + 1 SET_SIZE(dtrace_fish) #endif #if defined(lint) /*ARGSUSED*/ void dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size) {} #else ENTRY(dtrace_copyin) tst %o2 bz 1f clr %g1 lduba [%o0 + %g1]ASI_USER, %g2 0: stub %g2, [%o1 + %g1] inc %g1 cmp %g1, %o2 bl,a 0b lduba [%o0 + %g1]ASI_USER, %g2 1: retl nop SET_SIZE(dtrace_copyin) #endif #if defined(lint) /*ARGSUSED*/ void dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size) {} #else ENTRY(dtrace_copyinstr) tst %o2 bz 1f clr %g1 lduba [%o0 + %g1]ASI_USER, %g2 0: stub %g2, [%o1 + %g1] ! Store byte cmp %g2, 0 ! Was that '\0'? be 1f ! If so, we're done inc %g1 ! Increment offset cmp %g1, %o2 ! Compare to limit bl,a 0b ! If less, take another lap lduba [%o0 + %g1]ASI_USER, %g2 ! delay: load user byte 1: retl nop SET_SIZE(dtrace_copyinstr) #endif #if defined(lint) /*ARGSUSED*/ void dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size) {} #else ENTRY(dtrace_copyout) tst %o2 bz 1f clr %g1 ldub [%o0 + %g1], %g2 0: stba %g2, [%o1 + %g1]ASI_USER inc %g1 cmp %g1, %o2 bl,a 0b ldub [%o0 + %g1], %g2 1: retl nop SET_SIZE(dtrace_copyout) #endif #if defined(lint) /*ARGSUSED*/ void dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size) {} #else ENTRY(dtrace_copyoutstr) tst %o2 bz 1f clr %g1 ldub [%o0 + %g1], %g2 0: stba %g2, [%o1 + %g1]ASI_USER cmp %g2, 0 be 1f inc %g1 cmp %g1, %o2 bl,a 0b ldub [%o0 + %g1], %g2 1: retl nop SET_SIZE(dtrace_copyoutstr) #endif #if defined(lint) /*ARGSUSED*/ uintptr_t dtrace_fulword(void *addr) { return (0); } #else ENTRY(dtrace_fulword) clr %o1 ldna [%o0]ASI_USER, %o1 retl mov %o1, %o0 SET_SIZE(dtrace_fulword) #endif #if defined(lint) /*ARGSUSED*/ uint8_t dtrace_fuword8(void *addr) { return (0); } #else ENTRY(dtrace_fuword8) clr %o1 lduba [%o0]ASI_USER, %o1 retl mov %o1, %o0 SET_SIZE(dtrace_fuword8) #endif #if defined(lint) /*ARGSUSED*/ uint16_t dtrace_fuword16(void *addr) { return (0); } #else ENTRY(dtrace_fuword16) clr %o1 lduha [%o0]ASI_USER, %o1 retl mov %o1, %o0 SET_SIZE(dtrace_fuword16) #endif #if defined(lint) /*ARGSUSED*/ uint32_t dtrace_fuword32(void *addr) { return (0); } #else ENTRY(dtrace_fuword32) clr %o1 lda [%o0]ASI_USER, %o1 retl mov %o1, %o0 SET_SIZE(dtrace_fuword32) #endif #if defined(lint) /*ARGSUSED*/ uint64_t dtrace_fuword64(void *addr) { return (0); } #else ENTRY(dtrace_fuword64) clr %o1 ldxa [%o0]ASI_USER, %o1 retl mov %o1, %o0 SET_SIZE(dtrace_fuword64) #endif #if defined(lint) /*ARGSUSED*/ int dtrace_getupcstack_top(uint64_t *pcstack, int pcstack_limit, uintptr_t *sp) { return (0); } #else /* * %g1 pcstack * %g2 current window * %g3 maxwin (nwindows - 1) * %g4 saved %cwp (so we can get back to the original window) * %g5 iteration count * %g6 saved %fp * * %o0 pcstack / return value (iteration count) * %o1 pcstack_limit * %o2 last_fp */ ENTRY(dtrace_getupcstack_top) mov %o0, %g1 ! we need the pcstack pointer while ! we're visiting other windows rdpr %otherwin, %g5 ! compute the number of iterations cmp %g5, %o1 ! (windows to observe) by taking the movg %icc, %o1, %g5 ! min of %otherwin and pcstack_limit brlez,a,pn %g5, 2f ! return 0 if count <= 0 clr %o0 sethi %hi(nwin_minus_one), %g3 ! hang onto maxwin since we'll need ld [%g3 + %lo(nwin_minus_one)], %g3 ! it for our modular arithmetic rdpr %cwp, %g4 ! remember our window so we can return rdpr %canrestore, %g2 ! compute the first non-user window subcc %g4, %g2, %g2 ! current = %cwp - %otherwin bge,pt %xcc, 1f ! good to go if current is >= 0 mov %g5, %o0 ! we need to return the count add %g2, %g3, %g2 ! normalize our current window if it's add %g2, 1, %g2 ! less than zero ! note that while it's tempting, we can't execute restore to decrement ! the %cwp by one (mod nwindows) because we're in the user's windows 1: deccc %g2 ! decrement the current window movl %xcc, %g3, %g2 ! normalize if it's negative (-1) wrpr %g2, %cwp ! change windows stx %i7, [%g1] ! stash the return address in pcstack deccc %g5 ! decrement the count bnz,pt %icc, 1b ! we iterate until the count reaches 0 add %g1, 8, %g1 ! increment the pcstack pointer mov %i6, %g6 ! stash the last frame pointer we ! encounter so the caller can ! continue the stack walk in memory wrpr %g4, %cwp ! change back to the original window stn %g6, [%o2] ! return the last frame pointer 2: retl nop SET_SIZE(dtrace_getupcstack_top) #endif #if defined(lint) || defined(__lint) /* ARGSUSED */ ulong_t dtrace_getreg_win(uint_t reg, uint_t depth) { return (0); } #else /* lint */ ENTRY(dtrace_getreg_win) sub %o0, 16, %o0 cmp %o0, 16 ! %o0 must begin in the range [16..32) blu,pt %xcc, 1f nop retl clr %o0 1: set dtrace_getreg_win_table, %g3 sll %o0, 2, %o0 add %g3, %o0, %g3 rdpr %canrestore, %o3 rdpr %cwp, %g2 ! Set %cwp to be (%cwp - %canrestore - %o1) mod NWINDOWS sub %g2, %o3, %o2 ! %o2 is %cwp - %canrestore subcc %o2, %o1, %o4 bge,a,pn %xcc, 2f wrpr %o4, %cwp sethi %hi(nwin_minus_one), %o3 ld [%o3 + %lo(nwin_minus_one)], %o3 add %o2, %o3, %o4 wrpr %o4, %cwp 2: jmp %g3 ba 3f 3: wrpr %g2, %cwp retl mov %g1, %o0 dtrace_getreg_win_table: mov %l0, %g1 mov %l1, %g1 mov %l2, %g1 mov %l3, %g1 mov %l4, %g1 mov %l5, %g1 mov %l6, %g1 mov %l7, %g1 mov %i0, %g1 mov %i1, %g1 mov %i2, %g1 mov %i3, %g1 mov %i4, %g1 mov %i5, %g1 mov %i6, %g1 mov %i7, %g1 SET_SIZE(dtrace_getreg_win) #endif /* lint */ #if defined(lint) || defined(__lint) /* ARGSUSED */ void dtrace_putreg_win(uint_t reg, ulong_t value) {} #else /* lint */ ENTRY(dtrace_putreg_win) sub %o0, 16, %o0 cmp %o0, 16 ! %o0 must be in the range [16..32) blu,pt %xcc, 1f nop retl nop 1: mov %o1, %g1 ! move the value into a global register set dtrace_putreg_table, %g3 sll %o0, 2, %o0 add %g3, %o0, %g3 rdpr %canrestore, %o3 rdpr %cwp, %g2 ! Set %cwp to be (%cwp - %canrestore - 1) mod NWINDOWS sub %g2, %o3, %o2 ! %o2 is %cwp - %canrestore subcc %o2, 1, %o4 bge,a,pn %xcc, 2f wrpr %o4, %cwp sethi %hi(nwin_minus_one), %o3 ld [%o3 + %lo(nwin_minus_one)], %o3 add %o2, %o3, %o4 wrpr %o4, %cwp 2: jmp %g3 ba 3f 3: wrpr %g2, %cwp retl nop dtrace_putreg_table: mov %g1, %l0 mov %g1, %l1 mov %g1, %l2 mov %g1, %l3 mov %g1, %l4 mov %g1, %l5 mov %g1, %l6 mov %g1, %l7 mov %g1, %i0 mov %g1, %i1 mov %g1, %i2 mov %g1, %i3 mov %g1, %i4 mov %g1, %i5 mov %g1, %i6 mov %g1, %i7 SET_SIZE(dtrace_putreg_win) #endif /* lint */ #if defined(lint) || defined(__lint) /*ARGSUSED*/ void dtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which, int fault, int fltoffs, uintptr_t illval) {} #else /* lint */ ENTRY(dtrace_probe_error) save %sp, -SA(MINFRAME), %sp sethi %hi(dtrace_probeid_error), %l0 ld [%l0 + %lo(dtrace_probeid_error)], %o0 mov %i0, %o1 mov %i1, %o2 mov %i2, %o3 mov %i3, %o4 call dtrace_probe mov %i4, %o5 ret restore SET_SIZE(dtrace_probe_error) #endif