#include #include #include /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ #if defined(CONFIG_AVM_SIMPLE_PROFILING) #include #include # define PROFILE_BUFFER_LEN (CONFIG_AVM_PROFILING_TRACE_MODE * 1024) struct _simple_profiling { struct _avm_profile_data data[PROFILE_BUFFER_LEN]; atomic_t pos; unsigned int len; unsigned int enabled; } simple_profiling; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ unsigned int avm_simple_profiling(struct pt_regs *regs, unsigned int irq_num) { unsigned int pos, epc, time; if(simple_profiling.enabled == 0) return; #if defined(CONFIG_ARM) epc = regs->ARM_pc; #endif /*--- #if defined(CONFIG_ARM) ---*/ #if defined(CONFIG_MIPS) epc = regs->cp0_epc; #endif /*--- #if defined(CONFIG_MIPS) ---*/ time = avm_profile_counter(); pos = atomic_inc_return(&(simple_profiling.pos)) - 1; if(pos >= simple_profiling.len - 1) { simple_profiling.enabled = 0; printk("[simple_profiling] buffer full: %u entries recorded\n", simple_profiling.len); } simple_profiling.data[pos].type = avm_profile_data_type_code_address_info; simple_profiling.data[pos].curr = current; simple_profiling.data[pos].id = irq_num; simple_profiling.data[pos].addr = epc; simple_profiling.data[pos].time = time; return time; } EXPORT_SYMBOL(avm_simple_profiling); /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void avm_simple_profiling_log(enum _avm_profile_data_type type, unsigned int addr, unsigned int id) { unsigned int pos, time; struct sk_buff *skb; if(simple_profiling.enabled == 0) return; time = avm_profile_counter(); pos = atomic_inc_return(&(simple_profiling.pos)) - 1; if(pos >= simple_profiling.len - 1) { simple_profiling.enabled = 0; printk("[simple_profiling] buffer full: %u entries recorded\n", simple_profiling.len); } switch(type) { default: case avm_profile_data_type_free: case avm_profile_data_type_unknown: break; case avm_profile_data_type_text: case avm_profile_data_type_code_address_info: case avm_profile_data_type_data_address_info: simple_profiling.data[pos].type = type; simple_profiling.data[pos].addr = addr; simple_profiling.data[pos].time = time; break; case avm_profile_data_type_trace_skb: skb = (struct sk_buff *)addr; simple_profiling.data[pos].type = type; simple_profiling.data[pos].id = id; simple_profiling.data[pos].addr = skb->uniq_id; simple_profiling.data[pos].time = time; break; case avm_profile_data_type_hw_irq_begin: case avm_profile_data_type_hw_irq_end: case avm_profile_data_type_sw_irq_begin: case avm_profile_data_type_sw_irq_end: case avm_profile_data_type_timer_begin: case avm_profile_data_type_timer_end: case avm_profile_data_type_tasklet_begin: case avm_profile_data_type_tasklet_end: case avm_profile_data_type_workitem_begin: case avm_profile_data_type_workitem_end: simple_profiling.data[pos].type = type; simple_profiling.data[pos].id = id; simple_profiling.data[pos].addr = addr; simple_profiling.data[pos].time = time; break; } } EXPORT_SYMBOL(avm_simple_profiling_log); /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void avm_simple_profiling_text(const char *text) { unsigned int pos; if(simple_profiling.enabled == 0) return; pos = atomic_inc_return(&(simple_profiling.pos)) - 1; if(pos >= simple_profiling.len - 1) { simple_profiling.enabled = 0; printk("[simple_profiling] buffer full: %u entries recorded\n", simple_profiling.len); } simple_profiling.data[pos].type = avm_profile_data_type_text; simple_profiling.data[pos].time = avm_profile_counter(); simple_profiling.data[pos].addr = text; return; } EXPORT_SYMBOL(avm_simple_profiling_text); /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ struct _avm_profile_data *avm_simple_profiling_enable(unsigned int on, unsigned int *count) { if(on) { simple_profiling.enabled = 0; atomic_set(&(simple_profiling.pos), 0); simple_profiling.enabled = 1; if(count) *count = 0; return NULL; } simple_profiling.enabled = 0; if(count) *count = simple_profiling.pos.counter; printk("[simple_profiling] off: %u entries\n", simple_profiling.pos.counter); return simple_profiling.data; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int avm_simple_profiling_init(void) { simple_profiling.len = PROFILE_BUFFER_LEN; simple_profiling.enabled = 0; atomic_set(&(simple_profiling.pos), 0); printk("[simple_profiling] %u entries %u min\n", simple_profiling.len, CONFIG_AVM_PROFILING_TRACE_MODE); return 0; } module_init(avm_simple_profiling_init); #endif /*--- #if defined(CONFIG_AVM_SIMPLE_PROFILING) ---*/