📄 dtrace_asm.s
字号:
/* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only. * See the file usr/src/LICENSING.NOTICE in this distribution or * http://www.opensolaris.org/license/ for details. */#pragma ident "@(#)dtrace_asm.s 1.3 04/11/17 SMI"#if defined(lint) || defined(__lint)#include <sys/dtrace_impl.h>#else#include <sys/asm_linkage.h>#include <sys/privregs.h>#include <sys/fsr.h>#include <sys/asi.h>#endif#if defined(lint) || defined(__lint)intdtrace_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_tdtrace_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_tdtrace_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*/voiddtrace_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_tdtrace_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)voiddtrace_flush_user_windows(void){}#else ENTRY_NP(dtrace_flush_user_windows) rdpr %otherwin, %g1 brz %g1, 3f clr %g21: save %sp, -WINDOWSIZE, %sp rdpr %otherwin, %g1 brnz %g1, 1b add %g2, 1, %g22: sub %g2, 1, %g2 ! restore back to orig window brnz %g2, 2b restore3: retl nop SET_SIZE(dtrace_flush_user_windows)#endif /* lint */#if defined(lint) || defined(__lint)uint32_tdtrace_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_tdtrace_caller(int aframes){ return (0);}#else /* lint */ ENTRY(dtrace_caller) rdpr %ver, %g4 and %g4, VER_MAXWIN, %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, %cwp0: mov %i7, %g4 wrpr %g1, %cwp retl mov %g4, %o01: ! ! 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*/intdtrace_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, %g40: 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 rdpr %ver, %g4 and %g4, VER_MAXWIN, %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, %cwp0: jmp %g5 ba 1f1: 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*/voiddtrace_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, %g20: stub %g2, [%o1 + %g1] inc %g1 cmp %g1, %o2 bl,a 0b lduba [%o0 + %g1]ASI_USER, %g21: retl nop SET_SIZE(dtrace_copyin)#endif#if defined(lint)/*ARGSUSED*/voiddtrace_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, %g20: 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 byte1: retl nop SET_SIZE(dtrace_copyinstr)#endif#if defined(lint)/*ARGSUSED*/voiddtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size){}#else ENTRY(dtrace_copyout) tst %o2 bz 1f clr %g1 ldub [%o0 + %g1], %g20: stba %g2, [%o1 + %g1]ASI_USER inc %g1 cmp %g1, %o2 bl,a 0b ldub [%o0 + %g1], %g21: retl nop SET_SIZE(dtrace_copyout)#endif #if defined(lint)/*ARGSUSED*/voiddtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size){}#else ENTRY(dtrace_copyoutstr) tst %o2 bz 1f clr %g1 ldub [%o0 + %g1], %g20: stba %g2, [%o1 + %g1]ASI_USER cmp %g2, 0 be 1f inc %g1 cmp %g1, %o2 bl,a 0b ldub [%o0 + %g1], %g21: retl nop SET_SIZE(dtrace_copyoutstr)#endif#if defined(lint)/*ARGSUSED*/uintptr_tdtrace_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_tdtrace_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_tdtrace_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_tdtrace_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_tdtrace_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*/intdtrace_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 rdpr %ver, %g3 ! hang onto maxwin since we'll need and %g3, VER_MAXWIN, %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 windows1: subcc %g2, 1, %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 subcc %g5, 1, %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 pointer2: retl nop SET_SIZE(dtrace_getupcstack_top)#endif#if defined(lint) || defined(__lint)/* ARGSUSED */ulong_tdtrace_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 %o01: 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 rdpr %ver, %o3 and %o3, VER_MAXWIN, %o3 add %o2, %o3, %o4 wrpr %o4, %cwp2: jmp %g3 ba 3f3: wrpr %g2, %cwp retl mov %g1, %o0dtrace_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 */voiddtrace_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 nop1: 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 rdpr %ver, %o3 and %o3, VER_MAXWIN, %o3 add %o2, %o3, %o4 wrpr %o4, %cwp2: jmp %g3 ba 3f3: wrpr %g2, %cwp retl nopdtrace_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*/voiddtrace_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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -