#ifndef __arch_profile_brcma_h__ #define __arch_profile_brcma_h__ #include #include #include enum _norm_factor { NORMED_BY_FREQUENCY = 0, NORMED_BY_CYCLE, NORMED_BY_INSTRUCTION, NORMED_MAX }; struct _perfcount_options { char *name; enum _norm_factor norm_factor; }; #if defined(CONFIG_AVM_FASTIRQ) #define PROFILING_IN_FIQ #define PROFILING_MAX_PERF_REGISTER (6 + 1) /* we treat the cycle counter like a performance counter */ #define PROFILING_PERF_REGISTERMASK ((1 << 6) - 1) #define PROFILING_CYCLE_REGISTER (PROFILING_MAX_PERF_REGISTER - 1) #define PROFILING_TRIGGER_SHIFT 9 #define PROFILING_TRIGGER_MASK ((1 << PROFILING_TRIGGER_SHIFT) - 1) /*--- Range: 512 us ---*/ #if defined (CONFIG_AVM_FASTIRQ_ARCH_ARM_COMMON) #include #include #include #include #else #include #include #include #include #endif /*--------------------------------------------------------------------------------*\ * Liste mit Round-Robin-Performance-Counter pro CPU \*--------------------------------------------------------------------------------*/ struct _roundrobin_perf_ctrlstat { unsigned int perf_ctrl[PROFILING_MAX_PERF_REGISTER]; unsigned long long sum_perf_time[PROFILING_MAX_PERF_REGISTER]; unsigned long long sum_perf_count[PROFILING_MAX_PERF_REGISTER]; const char *prefix; struct _roundrobin_perf_ctrlstat *next; }; extern const struct _roundrobin_perf_ctrlstat roundrobin_performance[]; unsigned int array_size_roundrobin_performance(void); #endif/*--- #if defined(CONFIG_AVM_FASTIRQ) ---*/ extern const struct _perfcount_options performance_counter_options[PM_EVENT_LAST]; #define PROFILE_TIMER_ID_BY_ID(id) ((id) & 0xF) #define PROFILE_CPU_ID_BY_ID(id) (((id) >> 4) & 0xF) #define PROFILE_IRQ_ID_BY_ID(id) (((id) >> 8)) #define PROFILE_BUILD_ID(cpu, timer, irq) ((timer) | ((cpu) << 4) | ((irq) << 8)) #define INITIAL_EVENT_CNT_SETUP() \ arm_performance_counter_action("set 0 1"); /*--- PM_EVENT_L1I_CACHE_REFILL --- */ \ arm_performance_counter_action("set 1 3"); /*--- PM_EVENT_L1D_CACHE_REFILL --- */ \ arm_performance_counter_action("set 2 129"); /*--- PM_EVENT_EXT_MEM_WRITE_STALL --- */ \ arm_performance_counter_action("set 3 104"); /*--- PM_EVENT_INST_RETIRED --- */ \ /*--------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------*/ static const struct _cpucore_profile arm_cpu_config[2] = { { cpu_nr_offset: 0, vpe_nr: 1, next_core: &arm_cpu_config[1] }, { cpu_nr_offset: 1, vpe_nr: 1, next_core: NULL }, }; #define PROFILING_PERFORMANCE_COUNTER_SUPPORT /*--------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------*/ static inline void arch_profile_perfcnt_on(unsigned int on) { union __performance_monitor_control C; if(on){ C.Register = read_p15_performance_monitor_control(); C.Bits.CycleCounterDivider = 0; C.Bits.EnableBit = 1; write_p15_performance_monitor_control(C.Register); write_p15_performance_count_enable(0x8000000F); p15_reset_performance_counter(0); p15_reset_performance_counter(1); p15_reset_performance_counter(2); p15_reset_performance_counter(3); p15_reset_performance_counter(4); p15_reset_performance_counter(5); write_p15_cycle_counter(0); } else { C.Register = read_p15_performance_monitor_control(); C.Bits.EnableBit = 0; write_p15_performance_monitor_control(C.Register); write_p15_performance_count_enable(0); } } /*--------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------*/ static inline unsigned int arch_profile_perfcnt1(void) { return read_p15_performance_counter(0); } /*--------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------*/ static inline unsigned int arch_profile_perfcnt2(void) { return read_p15_performance_counter(1); } /*--------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------*/ static inline int arch_is_linux_cpu(unsigned int core __maybe_unused, unsigned int tc __maybe_unused) { return 1; } /*--------------------------------------------------------------------------------*\ * benoetigt, da sonst irqs nicht angeschaltet werden \*--------------------------------------------------------------------------------*/ static void dummy_timer_handler(unsigned long param __maybe_unused){ printk(KERN_INFO"%s\n", __func__); } /*--------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------*/ #if defined(CONFIG_AVM_FASTIRQ) static int last_timer_id = -1; static int shared_timer = 0; static inline int arch_setup_timer_firq(int cpu, irqreturn_t (*lfirqfunc)(int irq, void *handle), void *handle) { int irqid; char txt[64]; int timerid = ext_timer_alloc_only(-1, dummy_timer_handler, 0); if(timerid < 0) { if( last_timer_id < 0 ) { printk(KERN_ERR "no timer for cpu#%d\n", cpu); return timerid; } else { shared_timer = 1; timerid = last_timer_id; } } last_timer_id = timerid; ext_timer_stop(timerid); ext_timer_set_mode(timerid, EXT_TIMER_MODE_ONESHOT); irqid = INTERRUPT_ID_TIMER + timerid; snprintf(txt, sizeof(txt), "Profiling"); if( avm_request_fiq_on(cpu, irqid, lfirqfunc, 0, txt, handle) >= 0 ) { avm_gic_fiq_setup(irqid, 1 << cpu, FIQ_PRIO_PROFILING, 1, 0); if(!shared_timer) { printk(KERN_ERR "%s: timerid=%u irqid=%u cpu%u\n", __func__, timerid, irqid, cpu); } else { printk(KERN_ERR "%s: timerid=%u irqid=%u additional cpu%u\n", __func__, timerid, irqid, cpu); } return PROFILE_BUILD_ID(cpu, timerid, irqid); } return -1; } /*--------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------*/ static inline void arch_free_timer_firq(int id, void *handle) { if(id < 0) { return; } avm_free_fiq_on(PROFILE_CPU_ID_BY_ID(id), PROFILE_IRQ_ID_BY_ID(id), handle); ext_timer_free(PROFILE_TIMER_ID_BY_ID(id)); last_timer_id = -1; shared_timer = 0; } #endif/*--- #if defined(CONFIG_AVM_FASTIRQ) ---*/ /*--------------------------------------------------------------------------------*\ * timer in usec \*--------------------------------------------------------------------------------*/ static inline void arch_set_next_trigger(unsigned int next_us, int id) { int cpuid = PROFILE_CPU_ID_BY_ID(id); int timerid = PROFILE_TIMER_ID_BY_ID(id); int irqid = PROFILE_IRQ_ID_BY_ID(id); int c = 0; if(id < 0) { return; } /*--- printk(KERN_INFO"%s: id=%x -> timerid=%u\n", __func__, id, timerid); ---*/ ext_timer_stop(timerid); /* Target Routing Round Robin zur nächsten CPU stellen */ set_ICDIPTR(irqid, (1 << (((c = cpuid + 1) >= NR_CPUS) ? 0 : c)), IS_NOT_ATOMIC); ext_timer_set_period(timerid, next_us); ext_timer_start(timerid); } #endif/*--- #ifndef __arch_profile_brcma_h__ ---*/