#ifndef _SYS_TRAPTRACE_H
#define _SYS_TRAPTRACE_H
#ifdef __cplusplus
extern "C" {
#endif
#define TRAP_TPGS (2 * PAGESIZE)
#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 HTRAP_TSIZE 0
#ifndef _ASM
typedef union {
struct {
caddr_t vaddr_base;
uint64_t paddr_base;
uint_t last_offset;
uint_t offset;
uint_t limit;
uchar_t asi;
} d;
char cache_linesize[64];
} TRAP_TRACE_CTL;
#ifdef _KERNEL
extern TRAP_TRACE_CTL trap_trace_ctl[];
extern int trap_trace_bufsize;
extern char trap_tr0[];
extern int trap_freeze;
extern caddr_t ttrace_buf;
extern int ttrace_index;
extern size_t calc_traptrace_sz(void);
extern void mach_htraptrace_setup(int);
extern void mach_htraptrace_configure(int);
extern void mach_htraptrace_cleanup(int);
#endif
#define TRAPTRACE_FREEZE trap_freeze = 1;
#define TRAPTRACE_UNFREEZE trap_freeze = 0;
#else
#include <sys/machthread.h>
#define TRAPTR_VBASE 0
#define TRAPTR_LAST_OFFSET 16
#define TRAPTR_OFFSET 20
#define TRAPTR_LIMIT 24
#define TRAPTR_PBASE 8
#define TRAPTR_ASIBUF 28
#define TRAPTR_SIZE_SHIFT 6
#define TRAPTR_SIZE (1<<TRAPTR_SIZE_SHIFT)
#define TRAPTR_ASI ASI_MEM
#ifdef TRAPTRACE_FORCE_TICK
#define GET_TRACE_TICK(reg, scr) \
rdpr %tick, reg;
#else
#define GET_TRACE_TICK(reg, scr) \
sethi %hi(traptrace_use_stick), reg; \
lduw [reg + %lo(traptrace_use_stick)], reg; \
\
brz,a reg, .+12; \
rdpr %tick, reg; \
rd %asr24, reg;
#endif
#define TRACE_PTR(ptr, scr1) \
sethi %hi(trap_freeze), ptr; \
ld [ptr + %lo(trap_freeze)], ptr; \
\
brnz,pn ptr, .+20; \
rdpr %pstate, scr1; \
andcc scr1, PSTATE_IE | PSTATE_AM, scr1; \
\
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; \
\
brnz,pn ptr, .+20; \
ld [scr1 + TRAPTR_LIMIT], ptr; \
tst ptr; \
\
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;
#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; \
\
brnz scr1, .+36; \
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];
#define TRACE_SAVE_TL_GL_REGS(addr, scr1) \
rdpr %tl, scr1; \
stha scr1, [addr + TRAP_ENT_TL]%asi
#define TRACE_SAVE_TL_VAL(addr, tl) \
stha tl, [addr + TRAP_ENT_TL]%asi
#define TRACE_SAVE_GL_VAL(addr, gl)
#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, scr3); \
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
#define TRACE_WIN_INFO(code, scr1, scr2, scr3) \
TRACE_PTR(scr1, scr2); \
GET_TRACE_TICK(scr2, scr3); \
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, scr3); \
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, scr3); \
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
#define FAULT_WINTRACE(scr1, scr2, scr3, type)
#define SYSTRAP_TRACE(scr1, scr2, scr3)
#endif
#endif
#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
#define TT_SC_RET 0x881
#define TT_SYS_RTT_PROM 0x5555
#define TT_SYS_RTT_PRIV 0x6666
#define TT_SYS_RTT_USER 0x7777
#define TT_INTR_EXIT 0x8888
#define TT_FSPILL_DEBUG 0x9999
#define TT_SERVE_INTR 0x6000
#define TT_XCALL 0xd000
#define TT_XCALL_CONT 0xdc00
#define TT_MMU_MISS 0x200
#define TT_SPURIOUS_INT 0x400
#ifdef __cplusplus
}
#endif
#endif