diff options
Diffstat (limited to 'usr/src/uts/sun4u/sys/traptrace.h')
| -rw-r--r-- | usr/src/uts/sun4u/sys/traptrace.h | 435 |
1 files changed, 435 insertions, 0 deletions
diff --git a/usr/src/uts/sun4u/sys/traptrace.h b/usr/src/uts/sun4u/sys/traptrace.h new file mode 100644 index 0000000000..9bf2076229 --- /dev/null +++ b/usr/src/uts/sun4u/sys/traptrace.h @@ -0,0 +1,435 @@ +/* + * 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. + */ + +#ifndef _SYS_TRAPTRACE_H +#define _SYS_TRAPTRACE_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Trap tracing. If TRAPTRACE is defined, every trap records info + * in a circular buffer. Define TRAPTRACE in Makefile.$ARCH. + * + * Trap trace records are TRAP_ENT_SIZE bytes, consisting of the + * %tick, %tl, %tt, %tpc, %tstate, %sp, and a few other words: + * + * struct trap_trace_record { + * ushort_t tl, tt; + * long pc; + * int64_t tstate, tick; + * long sp, tr, f1, f2, f3, f4; + * }; + * + * Note that for UltraSparc III and beyond %stick is used in place of %tick + * unless compiled with TRAPTRACE_FORCE_TICK. + * + * Auxilliary entries (not of just a trap), have obvious non-%tt values in + * the TRAP_ENT_TT field + */ + +#define TRAP_TPGS (2 * PAGESIZE) /* default size is two pages */ + +#ifndef _ASM + +struct trap_trace_record { + uint16_t tt_tl; + uint16_t tt_tt; + uintptr_t tt_tpc; + uint64_t tt_tstate; + uint64_t tt_tick; + uintptr_t tt_sp; + uintptr_t tt_tr; + uintptr_t tt_f1; + uintptr_t tt_f2; + uintptr_t tt_f3; + uintptr_t tt_f4; +}; + +#define TRAP_TSIZE ((TRAP_TPGS / sizeof (struct trap_trace_record)) * \ + sizeof (struct trap_trace_record)) + +#else + +#define TRAP_TSIZE ((TRAP_TPGS / TRAP_ENT_SIZE) * TRAP_ENT_SIZE) + +#endif + +#define TRAP_TBUF_SIZE TRAP_TSIZE + +/* + * Trap tracing buffer header. + */ + +#ifndef _ASM + +/* + * Example buffer header stored in locore.s: + * + * (the actual implementation could be .skip TRAPTR_SIZE*NCPU) + */ +typedef union { + struct { + caddr_t vaddr_base; /* virtual address of top of buffer */ + uint64_t paddr_base; /* physical address of buffer */ + uint_t last_offset; /* to "know" what trace completed */ + uint_t offset; /* current index into buffer (bytes) */ + uint_t limit; /* upper limit on index */ + uchar_t asi; /* cache for real asi */ + } d; + char cache_linesize[64]; +} TRAP_TRACE_CTL; + +#ifdef _KERNEL + +extern TRAP_TRACE_CTL trap_trace_ctl[]; /* allocated in locore.s */ +extern int trap_trace_bufsize; /* default buffer size */ +extern char trap_tr0[]; /* prealloc buf for boot cpu */ +extern int trap_freeze; /* freeze the trap trace */ +extern caddr_t ttrace_buf; /* buffer bop alloced */ +extern int ttrace_index; /* index used */ +extern caddr_t trap_trace_alloc(caddr_t); +extern void htrap_trace_setup(caddr_t, int); +extern void htrap_trace_register(int); + +#endif + +/* + * freeze the trap trace + */ +#define TRAPTRACE_FREEZE trap_freeze = 1; +#define TRAPTRACE_UNFREEZE trap_freeze = 0; + +#else /* _ASM */ + +#include <sys/machthread.h> + +/* + * Offsets of words in trap_trace_ctl: + */ +/* + * XXX This should be done with genassym + */ +#define TRAPTR_VBASE 0 /* virtual address of buffer */ +#define TRAPTR_LAST_OFFSET 16 /* last completed trace entry */ +#define TRAPTR_OFFSET 20 /* next trace entry pointer */ +#define TRAPTR_LIMIT 24 /* pointer past end of buffer */ +#define TRAPTR_PBASE 8 /* start of buffer */ +#define TRAPTR_ASIBUF 28 /* cache of current asi */ +#define TRAPTR_SIZE_SHIFT 6 /* shift count -- per CPU indexing */ +#define TRAPTR_SIZE (1<<TRAPTR_SIZE_SHIFT) + +#define TRAPTR_ASI ASI_MEM /* ASI to use for TRAPTR access */ + +/* + * Use new %stick register for UltraSparc III and beyond for + * sane debugging of mixed speed CPU systems. Use TRAPTRACE_FORCE_TICK + * for finer granularity on same speed systems. + * + * Note the label-less branches used due to contraints of where + * and when trap trace macros are used. + */ +#ifdef TRAPTRACE_FORCE_TICK +#define GET_TRACE_TICK(reg) \ + rdpr %tick, reg; +#else +#define GET_TRACE_TICK(reg) \ + sethi %hi(traptrace_use_stick), reg; \ + lduw [reg + %lo(traptrace_use_stick)], reg; \ + /* CSTYLED */ \ + brz,a reg, .+12; \ + rdpr %tick, reg; \ + rd %asr24, reg; +#endif + +/* + * TRACE_PTR(ptr, scr1) - get trap trace entry physical pointer. + * ptr is the register to receive the trace pointer. + * scr1 is a different register to be used as scratch. + * TRACING now needs a known processor state. Hence the assertion. + * NOTE: this caches and resets %asi + */ +#define TRACE_PTR(ptr, scr1) \ + sethi %hi(trap_freeze), ptr; \ + ld [ptr + %lo(trap_freeze)], ptr; \ + /* CSTYLED */ \ + brnz,pn ptr, .+20; /* skip assertion */ \ + rdpr %pstate, scr1; \ + andcc scr1, PSTATE_IE | PSTATE_AM, scr1; \ + /* CSTYLED */ \ + bne,a,pn %icc, trace_ptr_panic; \ + rd %pc, %g1; \ + CPU_INDEX(scr1, ptr); \ + sll scr1, TRAPTR_SIZE_SHIFT, scr1; \ + set trap_trace_ctl, ptr; \ + add ptr, scr1, scr1; \ + rd %asi, ptr; \ + stb ptr, [scr1 + TRAPTR_ASIBUF]; \ + sethi %hi(trap_freeze), ptr; \ + ld [ptr + %lo(trap_freeze)], ptr; \ + /* CSTYLED */ \ + brnz,pn ptr, .+20; /* skip assertion */ \ + ld [scr1 + TRAPTR_LIMIT], ptr; \ + tst ptr; \ + /* CSTYLED */ \ + be,a,pn %icc, trace_ptr_panic; \ + rd %pc, %g1; \ + ldx [scr1 + TRAPTR_PBASE], ptr; \ + ld [scr1 + TRAPTR_OFFSET], scr1; \ + wr %g0, TRAPTR_ASI, %asi; \ + add ptr, scr1, ptr; + +/* + * TRACE_NEXT(scr1, scr2, scr3) - advance the trap trace pointer. + * scr1, scr2, scr3 are scratch registers. + * This routine will skip updating the trap pointers if the + * global freeze register is set (e.g. in panic). + * (we also restore the asi register) + */ +#define TRACE_NEXT(scr1, scr2, scr3) \ + CPU_INDEX(scr2, scr1); \ + sll scr2, TRAPTR_SIZE_SHIFT, scr2; \ + set trap_trace_ctl, scr1; \ + add scr1, scr2, scr2; \ + ldub [scr2 + TRAPTR_ASIBUF], scr1; \ + wr %g0, scr1, %asi; \ + sethi %hi(trap_freeze), scr1; \ + ld [scr1 + %lo(trap_freeze)], scr1; \ + /* CSTYLED */ \ + brnz scr1, .+36; /* skip update on freeze */ \ + ld [scr2 + TRAPTR_OFFSET], scr1; \ + ld [scr2 + TRAPTR_LIMIT], scr3; \ + st scr1, [scr2 + TRAPTR_LAST_OFFSET]; \ + add scr1, TRAP_ENT_SIZE, scr1; \ + sub scr3, TRAP_ENT_SIZE, scr3; \ + cmp scr1, scr3; \ + movge %icc, 0, scr1; \ + st scr1, [scr2 + TRAPTR_OFFSET]; + +/* + * macro to save %tl to trap trace record at addr + */ +#define TRACE_SAVE_TL_GL_REGS(addr, scr1) \ + rdpr %tl, scr1; \ + stha scr1, [addr + TRAP_ENT_TL]%asi + +/* + * macro to save tl to trap trace record at addr + */ +#define TRACE_SAVE_TL_VAL(addr, tl) \ + stha tl, [addr + TRAP_ENT_TL]%asi + +/* + * dummy macro + */ +#define TRACE_SAVE_GL_VAL(addr, gl) + + +/* + * Trace macro for sys_trap return entries: + * prom_rtt, priv_rtt, and user_rtt + * %l7 - regs + * %l6 - trap %pil for prom_rtt and priv_rtt; THREAD_REG for user_rtt + */ +#define TRACE_RTT(code, scr1, scr2, scr3, scr4) \ + rdpr %pstate, scr4; \ + andn scr4, PSTATE_IE | PSTATE_AM, scr3; \ + wrpr %g0, scr3, %pstate; \ + TRACE_PTR(scr1, scr2); \ + GET_TRACE_TICK(scr2); \ + stxa scr2, [scr1 + TRAP_ENT_TICK]%asi; \ + rdpr %tl, scr2; \ + stha scr2, [scr1 + TRAP_ENT_TL]%asi; \ + set code, scr2; \ + stha scr2, [scr1 + TRAP_ENT_TT]%asi; \ + ldn [%l7 + PC_OFF], scr2; \ + stna scr2, [scr1 + TRAP_ENT_TPC]%asi; \ + ldx [%l7 + TSTATE_OFF], scr2; \ + stxa scr2, [scr1 + TRAP_ENT_TSTATE]%asi; \ + stna %sp, [scr1 + TRAP_ENT_SP]%asi; \ + stna %l6, [scr1 + TRAP_ENT_TR]%asi; \ + stna %l7, [scr1 + TRAP_ENT_F1]%asi; \ + ldn [THREAD_REG + T_CPU], scr2; \ + ld [scr2 + CPU_BASE_SPL], scr2; \ + stna scr2, [scr1 + TRAP_ENT_F2]%asi; \ + mov MMU_SCONTEXT, scr2; \ + ldxa [scr2]ASI_DMMU, scr2; \ + stna scr2, [scr1 + TRAP_ENT_F3]%asi; \ + rdpr %cwp, scr2; \ + stna scr2, [scr1 + TRAP_ENT_F4]%asi; \ + TRACE_NEXT(scr1, scr2, scr3); \ + wrpr %g0, scr4, %pstate + +/* + * Trace macro for spill and fill trap handlers + * tl and tt fields indicate which spill handler is entered + */ +#define TRACE_WIN_INFO(code, scr1, scr2, scr3) \ + TRACE_PTR(scr1, scr2); \ + GET_TRACE_TICK(scr2); \ + stxa scr2, [scr1 + TRAP_ENT_TICK]%asi; \ + rdpr %tl, scr2; \ + stha scr2, [scr1 + TRAP_ENT_TL]%asi; \ + rdpr %tt, scr2; \ + set code, scr3; \ + or scr2, scr3, scr2; \ + stha scr2, [scr1 + TRAP_ENT_TT]%asi; \ + rdpr %tstate, scr2; \ + stxa scr2, [scr1 + TRAP_ENT_TSTATE]%asi; \ + stna %sp, [scr1 + TRAP_ENT_SP]%asi; \ + rdpr %tpc, scr2; \ + stna scr2, [scr1 + TRAP_ENT_TPC]%asi; \ + set TT_FSPILL_DEBUG, scr2; \ + stna scr2, [scr1 + TRAP_ENT_TR]%asi; \ + rdpr %pstate, scr2; \ + stna scr2, [scr1 + TRAP_ENT_F1]%asi; \ + rdpr %cwp, scr2; \ + sll scr2, 24, scr2; \ + rdpr %cansave, scr3; \ + sll scr3, 16, scr3; \ + or scr2, scr3, scr2; \ + rdpr %canrestore, scr3; \ + or scr2, scr3, scr2; \ + stna scr2, [scr1 + TRAP_ENT_F2]%asi; \ + rdpr %otherwin, scr2; \ + sll scr2, 24, scr2; \ + rdpr %cleanwin, scr3; \ + sll scr3, 16, scr3; \ + or scr2, scr3, scr2; \ + rdpr %wstate, scr3; \ + or scr2, scr3, scr2; \ + stna scr2, [scr1 + TRAP_ENT_F3]%asi; \ + stna %o7, [scr1 + TRAP_ENT_F4]%asi; \ + TRACE_NEXT(scr1, scr2, scr3) + +#ifdef TRAPTRACE + +#define FAULT_WINTRACE(scr1, scr2, scr3, type) \ + TRACE_PTR(scr1, scr2); \ + GET_TRACE_TICK(scr2); \ + stxa scr2, [scr1 + TRAP_ENT_TICK]%asi; \ + rdpr %tl, scr2; \ + stha scr2, [scr1 + TRAP_ENT_TL]%asi; \ + set type, scr2; \ + stha scr2, [scr1 + TRAP_ENT_TT]%asi; \ + rdpr %tpc, scr2; \ + stna scr2, [scr1 + TRAP_ENT_TPC]%asi; \ + rdpr %tstate, scr2; \ + stxa scr2, [scr1 + TRAP_ENT_TSTATE]%asi; \ + stna %sp, [scr1 + TRAP_ENT_SP]%asi; \ + stna %g0, [scr1 + TRAP_ENT_TR]%asi; \ + stna %g0, [scr1 + TRAP_ENT_F1]%asi; \ + stna %g4, [scr1 + TRAP_ENT_F2]%asi; \ + rdpr %pil, scr2; \ + stna scr2, [scr1 + TRAP_ENT_F3]%asi; \ + stna %g0, [scr1 + TRAP_ENT_F4]%asi; \ + TRACE_NEXT(scr1, scr2, scr3) + +#define SYSTRAP_TT 0x1300 + +#define SYSTRAP_TRACE(scr1, scr2, scr3) \ + TRACE_PTR(scr1, scr2); \ + GET_TRACE_TICK(scr2); \ + stxa scr2, [scr1 + TRAP_ENT_TICK]%asi; \ + rdpr %tl, scr2; \ + stha scr2, [scr1 + TRAP_ENT_TL]%asi; \ + set SYSTRAP_TT, scr3; \ + rdpr %tt, scr2; \ + or scr3, scr2, scr2; \ + stha scr2, [scr1 + TRAP_ENT_TT]%asi; \ + rdpr %tpc, scr2; \ + stna scr2, [scr1 + TRAP_ENT_TPC]%asi; \ + rdpr %tstate, scr2; \ + stxa scr2, [scr1 + TRAP_ENT_TSTATE]%asi; \ + stna %g1, [scr1 + TRAP_ENT_SP]%asi; \ + stna %g2, [scr1 + TRAP_ENT_TR]%asi; \ + stna %g3, [scr1 + TRAP_ENT_F1]%asi; \ + stna %g4, [scr1 + TRAP_ENT_F2]%asi; \ + rdpr %pil, scr2; \ + stna scr2, [scr1 + TRAP_ENT_F3]%asi; \ + rdpr %cwp, scr2; \ + stna scr2, [scr1 + TRAP_ENT_F4]%asi; \ + TRACE_NEXT(scr1, scr2, scr3) + +#else /* TRAPTRACE */ + +#define FAULT_WINTRACE(scr1, scr2, scr3, type) +#define SYSTRAP_TRACE(scr1, scr2, scr3) + +#endif /* TRAPTRACE */ + +#endif /* _ASM */ + +/* + * Trap trace codes used in place of a %tbr value when more than one + * entry is made by a trap. The general scheme is that the trap-type is + * in the same position as in the TT, and the low-order bits indicate + * which precise entry is being made. + */ + +#define TT_F32_SN0 0x1084 +#define TT_F64_SN0 0x1088 +#define TT_F32_NT0 0x1094 +#define TT_F64_NT0 0x1098 +#define TT_F32_SO0 0x10A4 +#define TT_F64_SO0 0x10A8 +#define TT_F32_FN0 0x10C4 +#define TT_F64_FN0 0x10C8 +#define TT_F32_SN1 0x1284 +#define TT_F64_SN1 0x1288 +#define TT_F32_NT1 0x1294 +#define TT_F64_NT1 0x1298 +#define TT_F32_SO1 0x12A4 +#define TT_F64_SO1 0x12A8 +#define TT_F32_FN1 0x12C4 +#define TT_F64_FN1 0x12C8 + +#define TT_SC_ENTR 0x880 /* enter system call */ +#define TT_SC_RET 0x881 /* system call normal return */ + +#define TT_SYS_RTT_PROM 0x5555 /* return from trap to prom */ +#define TT_SYS_RTT_PRIV 0x6666 /* return from trap to privilege */ +#define TT_SYS_RTT_USER 0x7777 /* return from trap to user */ + +#define TT_INTR_EXIT 0x8888 /* interrupt thread exit (no pinned thread) */ +#define TT_FSPILL_DEBUG 0x9999 /* fill/spill debugging */ + +#define TT_SERVE_INTR 0x6000 /* SERVE_INTR */ +#define TT_XCALL 0xd000 /* xcall/xtrap */ +#define TT_XCALL_CONT 0xdc00 /* continuation of an xcall/xtrap record */ + +#define TT_MMU_MISS 0x200 /* or'd into %tt to indicate a miss */ +#define TT_SPURIOUS_INT 0x400 /* or'd into %tt for spurious intr. */ + + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_TRAPTRACE_H */ |
