blob: 226a163a5c2f373849e1ac813b2a378498c245ae [file] [log] [blame]
* Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
* vineetg: Feb 2008
* System Event Logging APIs
#include <asm/event-log.h>
#ifdef __ASSEMBLY__
.macro TAKE_SNAP_ASM reg_scratch, reg_ptr, type
.macro TAKE_SNAP_C_FROM_ASM type
#include <asm/asm-offsets.h>
.macro TAKE_SNAP_ASM reg_scratch, reg_ptr, type
/* Earlier we used to save only reg_scratch and clobber reg_ptr and rely
* on caller to understand this. Too mcuh trouble.
* Now we save both
st \reg_scratch, [tmp_save_reg]
st \reg_ptr, [tmp_save_reg2]
ld \reg_ptr, [timeline_ctr]
; hack to detect if we are trying to overflow the circular log buffer
brne \reg_ptr, MAX_SNAPS, 1f
flag 1
mpyu \reg_ptr, \reg_ptr, EVLOG_RECORD_SZ
;8001821c: ld r6,[0x8024ba98]
;80018228: add1 r2,r6,r6
;80018230: add2 r2,r6,r2
;80018234: asl r8,r2,2
;80018238: add r5,r8,0x8023ea64
;80018240: st r4,[r5,32]
; add1 \reg_scratch, \reg_ptr, \reg_ptr
; add2 \reg_scratch, \reg_ptr, \reg_scratch
; asl \reg_ptr, \reg_scratch, 2
add \reg_ptr, timeline_log, \reg_ptr
;############ Common data ##########
; TIMER1 count in timeline_log[timeline_ctr].time
lr \reg_scratch, [ARC_REG_TIMER1_CNT]
st \reg_scratch, [\reg_ptr, EVLOG_FIELD_TIME]
; current task ptr in timeline_log[timeline_ctr].task
ld \reg_scratch, [_current_task]
ld \reg_scratch, [\reg_scratch, TASK_TGID]
st \reg_scratch, [\reg_ptr, EVLOG_FIELD_TASK]
; Type of event (Intr/Excp/Trap etc)
mov \reg_scratch, \type
st \reg_scratch, [\reg_ptr, EVLOG_FIELD_EVENT_ID]
; save SP at time of exception
st sp, [\reg_ptr, EVLOG_FIELD_SP]
st 0, [\reg_ptr, EVLOG_FIELD_EXTRA]
st 0, [\reg_ptr, EVLOG_FIELD_CAUSE]
st 0, [\reg_ptr, EVLOG_FIELD_EXTRA3]
lr \reg_scratch, [status32]
st \reg_scratch, [\reg_ptr, EVLOG_FIELD_EXTRA2]
;############ Event specific data ##########
; save additional info depending on data point
; in timeline_log[timeline_ctr].cause
mov \reg_scratch, \type
and.f 0, \reg_scratch, EVENT_CLASS_EXIT
bz 1f
// Stuff to do for all kernel exit events
ld \reg_scratch, [sp, PT_status32]
st \reg_scratch, [\reg_ptr, EVLOG_FIELD_EXTRA]
// SP in log->sp
// ld \reg_scratch, [sp, PT_sp]
// preempt count in log->sp
and \reg_scratch, sp, ~(0x2000-1)
ld \reg_scratch, [\reg_scratch, THREAD_INFO_PREEMPT_COUNT ]
st \reg_scratch, [\reg_ptr, EVLOG_FIELD_SP]
ld \reg_scratch, [sp, PT_ret]
st \reg_scratch, [\reg_ptr, EVLOG_FIELD_EFA]
mov \reg_scratch, \type
/* for Trap, Syscall number */
cmp \reg_scratch, SNAP_TRAP_IN
bnz 3f
st r8, [\reg_ptr, EVLOG_FIELD_CAUSE]
lr \reg_scratch, [erstatus]
st \reg_scratch, [\reg_ptr, EVLOG_FIELD_EXTRA]
j 99f
/* For Exceptions (TLB/ProtV etc)*/
cmp \reg_scratch, SNAP_EXCP_IN
bnz 6f
lr \reg_scratch, [ecr]
st \reg_scratch, [\reg_ptr, EVLOG_FIELD_CAUSE]
lr \reg_scratch, [eret]
st \reg_scratch, [\reg_ptr, EVLOG_FIELD_EFA]
lr \reg_scratch, [erstatus]
st \reg_scratch, [\reg_ptr, EVLOG_FIELD_EXTRA]
lr \reg_scratch, [efa]
st \reg_scratch, [\reg_ptr, EVLOG_FIELD_EXTRA3]
j 99f
6: /* for Interrupts, IRQ */
cmp \reg_scratch, SNAP_INTR_OUT
bnz 7f
lr \reg_scratch, [icause1]
st \reg_scratch, [\reg_ptr, EVLOG_FIELD_CAUSE]
j 99f
cmp \reg_scratch, SNAP_INTR_OUT2
bnz 8f
lr \reg_scratch, [icause2]
st \reg_scratch, [\reg_ptr, EVLOG_FIELD_CAUSE]
j 99f
cmp \reg_scratch, SNAP_EXCP_OUT_FAST
bnz 9f
lr \reg_scratch, [erstatus]
st \reg_scratch, [\reg_ptr, EVLOG_FIELD_EXTRA]
j 99f
// place holder for next
/* increment timeline_ctr with mode on max */
ld \reg_scratch, [timeline_ctr]
add \reg_scratch, \reg_scratch, 1
and \reg_scratch, \reg_scratch, MAX_SNAPS_MASK
st \reg_scratch, [timeline_ctr]
/* Restore back orig scratch reg */
ld \reg_scratch, [tmp_save_reg]
ld \reg_ptr, [tmp_save_reg2]
/* Macro to invoke a "C" routine from assmebler.
* Makes the ISR/Event hanlder look so much clean
.macro TAKE_SNAP_C_FROM_ASM type
mov r0, \type
bl take_snap2
#endif /* __ASSEMBLY__ */