Mike Dodd | 8cfa702 | 2010-11-17 11:12:26 -0800 | [diff] [blame] | 1 | /** |
| 2 | * @file oprofile.h |
| 3 | * Main driver code |
| 4 | * |
| 5 | * @remark Copyright 2002 OProfile authors |
| 6 | * @remark Read the file COPYING |
| 7 | * |
| 8 | * @author John Levon |
| 9 | * @author Philippe Elie |
| 10 | */ |
| 11 | |
| 12 | #ifndef OPROFILE_H |
| 13 | #define OPROFILE_H |
| 14 | |
| 15 | #include <linux/version.h> |
| 16 | #include <linux/module.h> |
| 17 | #include <linux/config.h> |
| 18 | #include <linux/kernel.h> |
| 19 | #include <linux/init.h> |
| 20 | #include <linux/slab.h> |
| 21 | #include <linux/delay.h> |
| 22 | #include <linux/vmalloc.h> |
| 23 | #include <linux/sched.h> |
| 24 | #include <linux/sysctl.h> |
| 25 | #include <linux/smp_lock.h> |
| 26 | |
| 27 | #include <asm/uaccess.h> |
| 28 | |
| 29 | #include "compat.h" |
| 30 | |
| 31 | #include "op_config_24.h" |
| 32 | #include "op_hw_config.h" |
| 33 | #include "op_interface.h" |
| 34 | #include "op_cpu_type.h" |
| 35 | |
| 36 | #undef min |
| 37 | #undef max |
| 38 | |
| 39 | #define streq(a, b) (!strcmp((a), (b))) |
| 40 | |
| 41 | /* per-cpu dynamic data */ |
| 42 | struct _oprof_data { |
| 43 | /* eviction buffer */ |
| 44 | struct op_sample * buffer; |
| 45 | /* nr. in buffer */ |
| 46 | uint buf_size; |
| 47 | /* we try to wakeup when nextbuf >= buf_watermark */ |
| 48 | uint buf_watermark; |
| 49 | /* next in buffer (atomic) */ |
| 50 | uint nextbuf; |
| 51 | /* number of IRQs for this CPU */ |
| 52 | uint nr_irq; |
| 53 | /* buffer overflow cumulated size */ |
| 54 | uint nr_buffer_overflow; |
| 55 | /* reset counter values */ |
| 56 | uint ctr_count[OP_MAX_COUNTERS]; |
| 57 | }; |
| 58 | |
| 59 | /* reflect /proc/sys/dev/oprofile/#counter files */ |
| 60 | struct oprof_counter { |
| 61 | int count; |
| 62 | int enabled; |
| 63 | int event; |
| 64 | int kernel; |
| 65 | int user; |
| 66 | int unit_mask; |
| 67 | }; |
| 68 | |
| 69 | /* reflect /proc/sys/dev/oprofile files */ |
| 70 | struct oprof_sysctl { |
| 71 | /* nr. in eviction buffser */ |
| 72 | int buf_size; |
| 73 | /* sysctl dump */ |
| 74 | int dump; |
| 75 | /* dump and stop */ |
| 76 | int dump_stop; |
| 77 | /* nr. in note buffer */ |
| 78 | int note_size; |
| 79 | /* nr. interrupts occured */ |
| 80 | int nr_interrupts; |
| 81 | /* the cpu core type: CPU_PPRO, CPU_PII ... */ |
| 82 | int cpu_type; |
| 83 | /* nr note buffer overflow */ |
| 84 | int nr_note_buffer_overflow; |
| 85 | /* nr buffer overflow */ |
| 86 | int nr_buffer_overflow; |
| 87 | /* counter setup */ |
| 88 | struct oprof_counter ctr[OP_MAX_COUNTERS]; |
| 89 | }; |
| 90 | |
| 91 | /** |
| 92 | * A interrupt handler must implement these routines. |
| 93 | * When an interrupt arrives, it must eventually call |
| 94 | * op_do_profile(). |
| 95 | */ |
| 96 | struct op_int_operations { |
| 97 | /* initialise the interrupt handler on module load. |
| 98 | * On failure deinit handler is not called so all resources |
| 99 | * allocated by init() must be freed before returning an error code |
| 100 | * (or 0 on success) |
| 101 | */ |
| 102 | int (*init)(void); |
| 103 | /* deinitialise on module unload */ |
| 104 | void (*deinit)(void); |
| 105 | /* add any handler-specific sysctls at the position given by @next. Return 0 on success */ |
| 106 | int (*add_sysctls)(ctl_table * next); |
| 107 | /* remove handler-specific sysctls */ |
| 108 | void (*remove_sysctls)(ctl_table * next); |
| 109 | /* check given profiling parameters are correct. Return 0 on success */ |
| 110 | int (*check_params)(void); |
| 111 | /* setup the handler from profiling parameters. Return 0 on success */ |
| 112 | int (*setup)(void); |
| 113 | /* start profiling on all CPUs */ |
| 114 | void (*start)(void); |
| 115 | /* stop profiling on all CPUs */ |
| 116 | void (*stop)(void); |
| 117 | /* start profiling on the given CPU */ |
| 118 | void (*start_cpu)(uint); |
| 119 | /* stop profiling on the given CPU */ |
| 120 | void (*stop_cpu)(uint); |
| 121 | }; |
| 122 | |
| 123 | /* maximum depth of dname trees - this is just a page */ |
| 124 | #define DNAME_STACK_MAX 1024 |
| 125 | |
| 126 | /* oprof_start() copy here the sysctl settable parameters */ |
| 127 | extern struct oprof_sysctl sysctl; |
| 128 | |
| 129 | int oprof_init(void); |
| 130 | void oprof_exit(void); |
| 131 | unsigned long is_map_ready(void); |
| 132 | int oprof_hash_map_open(void); |
| 133 | int oprof_hash_map_release(void); |
| 134 | int oprof_hash_map_mmap(struct file * file, struct vm_area_struct * vma); |
| 135 | int oprof_map_open(void); |
| 136 | int oprof_map_release(void); |
| 137 | int oprof_init_hashmap(void); |
| 138 | void oprof_free_hashmap(void); |
| 139 | |
| 140 | /* used by interrupt handlers if the underlined harware doesn't support |
| 141 | * performance counter */ |
| 142 | extern struct op_int_operations op_rtc_ops; |
| 143 | |
| 144 | void op_do_profile(uint cpu, long eip, long irq_enabled, int ctr); |
| 145 | extern struct _oprof_data oprof_data[NR_CPUS]; |
| 146 | extern struct oprof_sysctl sysctl_parms; |
| 147 | extern int lproc_dointvec(ctl_table * table, int write, struct file * filp, void * buffer, size_t * lenp); |
| 148 | |
| 149 | /* functionality provided by the architecture dependent file */ |
| 150 | /* must return OP_RTC if the hardware doesn't support something like |
| 151 | * perf counter */ |
| 152 | op_cpu get_cpu_type(void); |
| 153 | /* return an interface pointer, this function is called only if get_cpu_type |
| 154 | * doesn't return OP_RTC */ |
| 155 | struct op_int_operations const * op_int_interface(void); |
| 156 | /* intercept the needed syscall */ |
| 157 | void op_intercept_syscalls(void); |
| 158 | void op_restore_syscalls(void); |
| 159 | void op_save_syscalls(void); |
| 160 | |
| 161 | #endif /* OPROFILE_H */ |