/** * @file oprofile.h * Main driver code * * @remark Copyright 2002 OProfile authors * @remark Read the file COPYING * * @author John Levon * @author Philippe Elie */ #ifndef OPROFILE_H #define OPROFILE_H #include <linux/version.h> #include <linux/module.h> #include <linux/config.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/delay.h> #include <linux/vmalloc.h> #include <linux/sched.h> #include <linux/sysctl.h> #include <linux/smp_lock.h> #include <asm/uaccess.h> #include "compat.h" #include "op_config_24.h" #include "op_hw_config.h" #include "op_interface.h" #include "op_cpu_type.h" #undef min #undef max #define streq(a, b) (!strcmp((a), (b))) /* per-cpu dynamic data */ struct _oprof_data { /* eviction buffer */ struct op_sample * buffer; /* nr. in buffer */ uint buf_size; /* we try to wakeup when nextbuf >= buf_watermark */ uint buf_watermark; /* next in buffer (atomic) */ uint nextbuf; /* number of IRQs for this CPU */ uint nr_irq; /* buffer overflow cumulated size */ uint nr_buffer_overflow; /* reset counter values */ uint ctr_count[OP_MAX_COUNTERS]; }; /* reflect /proc/sys/dev/oprofile/#counter files */ struct oprof_counter { int count; int enabled; int event; int kernel; int user; int unit_mask; }; /* reflect /proc/sys/dev/oprofile files */ struct oprof_sysctl { /* nr. in eviction buffser */ int buf_size; /* sysctl dump */ int dump; /* dump and stop */ int dump_stop; /* nr. in note buffer */ int note_size; /* nr. interrupts occured */ int nr_interrupts; /* the cpu core type: CPU_PPRO, CPU_PII ... */ int cpu_type; /* nr note buffer overflow */ int nr_note_buffer_overflow; /* nr buffer overflow */ int nr_buffer_overflow; /* counter setup */ struct oprof_counter ctr[OP_MAX_COUNTERS]; }; /** * A interrupt handler must implement these routines. * When an interrupt arrives, it must eventually call * op_do_profile(). */ struct op_int_operations { /* initialise the interrupt handler on module load. * On failure deinit handler is not called so all resources * allocated by init() must be freed before returning an error code * (or 0 on success) */ int (*init)(void); /* deinitialise on module unload */ void (*deinit)(void); /* add any handler-specific sysctls at the position given by @next. Return 0 on success */ int (*add_sysctls)(ctl_table * next); /* remove handler-specific sysctls */ void (*remove_sysctls)(ctl_table * next); /* check given profiling parameters are correct. Return 0 on success */ int (*check_params)(void); /* setup the handler from profiling parameters. Return 0 on success */ int (*setup)(void); /* start profiling on all CPUs */ void (*start)(void); /* stop profiling on all CPUs */ void (*stop)(void); /* start profiling on the given CPU */ void (*start_cpu)(uint); /* stop profiling on the given CPU */ void (*stop_cpu)(uint); }; /* maximum depth of dname trees - this is just a page */ #define DNAME_STACK_MAX 1024 /* oprof_start() copy here the sysctl settable parameters */ extern struct oprof_sysctl sysctl; int oprof_init(void); void oprof_exit(void); unsigned long is_map_ready(void); int oprof_hash_map_open(void); int oprof_hash_map_release(void); int oprof_hash_map_mmap(struct file * file, struct vm_area_struct * vma); int oprof_map_open(void); int oprof_map_release(void); int oprof_init_hashmap(void); void oprof_free_hashmap(void); /* used by interrupt handlers if the underlined harware doesn't support * performance counter */ extern struct op_int_operations op_rtc_ops; void op_do_profile(uint cpu, long eip, long irq_enabled, int ctr); extern struct _oprof_data oprof_data[NR_CPUS]; extern struct oprof_sysctl sysctl_parms; extern int lproc_dointvec(ctl_table * table, int write, struct file * filp, void * buffer, size_t * lenp); /* functionality provided by the architecture dependent file */ /* must return OP_RTC if the hardware doesn't support something like * perf counter */ op_cpu get_cpu_type(void); /* return an interface pointer, this function is called only if get_cpu_type * doesn't return OP_RTC */ struct op_int_operations const * op_int_interface(void); /* intercept the needed syscall */ void op_intercept_syscalls(void); void op_restore_syscalls(void); void op_save_syscalls(void); #endif /* OPROFILE_H */