From: Linus Torvalds Date: Thu, 23 Oct 2008 17:05:40 +0000 (-0700) Subject: Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rric/oprofile X-Git-Tag: v2.6.28-rc1~35 X-Git-Url: http://www.pilppa.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=92fb83afd6664a6f8a05f990d264c998f9b99f69;hp=-c;p=linux-2.6-omap-h63xx.git Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rric/oprofile * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rric/oprofile: (21 commits) OProfile: Fix buffer synchronization for IBS oprofile: hotplug cpu fix oprofile: fixing whitespaces in arch/x86/oprofile/* oprofile: fixing whitespaces in arch/x86/oprofile/* oprofile: fixing whitespaces in drivers/oprofile/* x86/oprofile: add the logic for enabling additional IBS bits x86/oprofile: reordering functions in nmi_int.c x86/oprofile: removing unused function parameter in add_ibs_begin() oprofile: more whitespace fixes oprofile: whitespace fixes OProfile: Rename IBS sysfs dir into "ibs_op" OProfile: Rework string handling in setup_ibs_files() OProfile: Rework oprofile_add_ibs_sample() function oprofile: discover counters for op ppro too oprofile: Implement Intel architectural perfmon support oprofile: Don't report Nehalem as core_2 oprofile: drop const in num counters field Revert "Oprofile Multiplexing Patch" x86, oprofile: BUG: using smp_processor_id() in preemptible code x86/oprofile: fix on_each_cpu build error ... Manually fixed trivial conflicts in drivers/oprofile/{cpu_buffer.c,event_buffer.h} --- 92fb83afd6664a6f8a05f990d264c998f9b99f69 diff --combined drivers/oprofile/buffer_sync.c index 37681700b61,6c0c92a745d..b55cd23ffde --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@@ -41,7 -41,6 +41,6 @@@ static cpumask_t marked_cpus = CPU_MASK static DEFINE_SPINLOCK(task_mortuary); static void process_task_mortuary(void); - /* Take ownership of the task struct and place it on the * list for processing. Only after two full buffer syncs * does the task eventually get freed, because by then @@@ -341,7 -340,7 +340,7 @@@ static void add_trace_begin(void * Add IBS fetch and op entries to event buffer */ static void add_ibs_begin(struct oprofile_cpu_buffer *cpu_buf, int code, - int in_kernel, struct mm_struct *mm) + struct mm_struct *mm) { unsigned long rip; int i, count; @@@ -565,9 -564,11 +564,11 @@@ void sync_buffer(int cpu struct task_struct *new; unsigned long cookie = 0; int in_kernel = 1; - unsigned int i; sync_buffer_state state = sb_buffer_start; + #ifndef CONFIG_OPROFILE_IBS + unsigned int i; unsigned long available; + #endif mutex_lock(&buffer_mutex); @@@ -575,9 -576,13 +576,13 @@@ /* Remember, only we can modify tail_pos */ + #ifndef CONFIG_OPROFILE_IBS available = get_slots(cpu_buf); for (i = 0; i < available; ++i) { + #else + while (get_slots(cpu_buf)) { + #endif struct op_sample *s = &cpu_buf->buffer[cpu_buf->tail_pos]; if (is_code(s->eip)) { @@@ -593,12 -598,10 +598,10 @@@ #ifdef CONFIG_OPROFILE_IBS } else if (s->event == IBS_FETCH_BEGIN) { state = sb_bt_start; - add_ibs_begin(cpu_buf, - IBS_FETCH_CODE, in_kernel, mm); + add_ibs_begin(cpu_buf, IBS_FETCH_CODE, mm); } else if (s->event == IBS_OP_BEGIN) { state = sb_bt_start; - add_ibs_begin(cpu_buf, - IBS_OP_CODE, in_kernel, mm); + add_ibs_begin(cpu_buf, IBS_OP_CODE, mm); #endif } else { struct mm_struct *oldmm = mm; @@@ -628,27 -631,3 +631,27 @@@ mutex_unlock(&buffer_mutex); } + +/* The function can be used to add a buffer worth of data directly to + * the kernel buffer. The buffer is assumed to be a circular buffer. + * Take the entries from index start and end at index end, wrapping + * at max_entries. + */ +void oprofile_put_buff(unsigned long *buf, unsigned int start, + unsigned int stop, unsigned int max) +{ + int i; + + i = start; + + mutex_lock(&buffer_mutex); + while (i != stop) { + add_event_entry(buf[i++]); + + if (i >= max) + i = 0; + } + + mutex_unlock(&buffer_mutex); +} + diff --combined drivers/oprofile/cpu_buffer.c index 7ba39fe20a8,67bcc1c95e6..01d38e78cde --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@@ -22,7 -22,7 +22,7 @@@ #include #include #include - + #include "event_buffer.h" #include "cpu_buffer.h" #include "buffer_sync.h" @@@ -39,39 -39,26 +39,39 @@@ void free_cpu_buffers(void { int i; - for_each_online_cpu(i) { + for_each_possible_cpu(i) { vfree(per_cpu(cpu_buffer, i).buffer); per_cpu(cpu_buffer, i).buffer = NULL; } } +unsigned long oprofile_get_cpu_buffer_size(void) +{ + return fs_cpu_buffer_size; +} + +void oprofile_cpu_buffer_inc_smpl_lost(void) +{ + struct oprofile_cpu_buffer *cpu_buf + = &__get_cpu_var(cpu_buffer); + + cpu_buf->sample_lost_overflow++; +} + int alloc_cpu_buffers(void) { int i; - + unsigned long buffer_size = fs_cpu_buffer_size; - - for_each_online_cpu(i) { + + for_each_possible_cpu(i) { struct oprofile_cpu_buffer *b = &per_cpu(cpu_buffer, i); - + b->buffer = vmalloc_node(sizeof(struct op_sample) * buffer_size, cpu_to_node(i)); if (!b->buffer) goto fail; - + b->last_task = NULL; b->last_is_kernel = -1; b->tracing = 0; @@@ -125,7 -112,7 +125,7 @@@ void end_cpu_work(void } /* Resets the cpu buffer to a sane state. */ - void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf) + void cpu_buffer_reset(struct oprofile_cpu_buffer *cpu_buf) { /* reset these to invalid values; the next sample * collected will populate the buffer with proper @@@ -136,7 -123,7 +136,7 @@@ } /* compute number of available slots in cpu_buffer queue */ - static unsigned long nr_available_slots(struct oprofile_cpu_buffer const * b) + static unsigned long nr_available_slots(struct oprofile_cpu_buffer const *b) { unsigned long head = b->head_pos; unsigned long tail = b->tail_pos; @@@ -147,7 -134,7 +147,7 @@@ return tail + (b->buffer_size - head) - 1; } - static void increment_head(struct oprofile_cpu_buffer * b) + static void increment_head(struct oprofile_cpu_buffer *b) { unsigned long new_head = b->head_pos + 1; @@@ -162,17 -149,17 +162,17 @@@ } static inline void - add_sample(struct oprofile_cpu_buffer * cpu_buf, - unsigned long pc, unsigned long event) + add_sample(struct oprofile_cpu_buffer *cpu_buf, + unsigned long pc, unsigned long event) { - struct op_sample * entry = &cpu_buf->buffer[cpu_buf->head_pos]; + struct op_sample *entry = &cpu_buf->buffer[cpu_buf->head_pos]; entry->eip = pc; entry->event = event; increment_head(cpu_buf); } static inline void - add_code(struct oprofile_cpu_buffer * buffer, unsigned long value) + add_code(struct oprofile_cpu_buffer *buffer, unsigned long value) { add_sample(buffer, ESCAPE_CODE, value); } @@@ -186,10 -173,10 +186,10 @@@ * pc. We tag this in the buffer by generating kernel enter/exit * events whenever is_kernel changes */ - static int log_sample(struct oprofile_cpu_buffer * cpu_buf, unsigned long pc, + static int log_sample(struct oprofile_cpu_buffer *cpu_buf, unsigned long pc, int is_kernel, unsigned long event) { - struct task_struct * task; + struct task_struct *task; cpu_buf->sample_received++; @@@ -218,7 -205,7 +218,7 @@@ cpu_buf->last_task = task; add_code(cpu_buf, (unsigned long)task); } - + add_sample(cpu_buf, pc, event); return 1; } @@@ -235,7 -222,7 +235,7 @@@ static int oprofile_begin_trace(struct return 1; } - static void oprofile_end_trace(struct oprofile_cpu_buffer * cpu_buf) + static void oprofile_end_trace(struct oprofile_cpu_buffer *cpu_buf) { cpu_buf->tracing = 0; } @@@ -270,21 -257,23 +270,23 @@@ void oprofile_add_sample(struct pt_reg #ifdef CONFIG_OPROFILE_IBS - #define MAX_IBS_SAMPLE_SIZE 14 - static int log_ibs_sample(struct oprofile_cpu_buffer *cpu_buf, - unsigned long pc, int is_kernel, unsigned int *ibs, int ibs_code) + #define MAX_IBS_SAMPLE_SIZE 14 + + void oprofile_add_ibs_sample(struct pt_regs *const regs, + unsigned int *const ibs_sample, int ibs_code) { + int is_kernel = !user_mode(regs); + struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer); struct task_struct *task; cpu_buf->sample_received++; if (nr_available_slots(cpu_buf) < MAX_IBS_SAMPLE_SIZE) { + /* we can't backtrace since we lost the source of this event */ cpu_buf->sample_lost_overflow++; - return 0; + return; } - is_kernel = !!is_kernel; - /* notice a switch from user->kernel or vice versa */ if (cpu_buf->last_is_kernel != is_kernel) { cpu_buf->last_is_kernel = is_kernel; @@@ -294,7 -283,6 +296,6 @@@ /* notice a task switch */ if (!is_kernel) { task = current; - if (cpu_buf->last_task != task) { cpu_buf->last_task = task; add_code(cpu_buf, (unsigned long)task); @@@ -302,36 -290,17 +303,17 @@@ } add_code(cpu_buf, ibs_code); - add_sample(cpu_buf, ibs[0], ibs[1]); - add_sample(cpu_buf, ibs[2], ibs[3]); - add_sample(cpu_buf, ibs[4], ibs[5]); + add_sample(cpu_buf, ibs_sample[0], ibs_sample[1]); + add_sample(cpu_buf, ibs_sample[2], ibs_sample[3]); + add_sample(cpu_buf, ibs_sample[4], ibs_sample[5]); if (ibs_code == IBS_OP_BEGIN) { - add_sample(cpu_buf, ibs[6], ibs[7]); - add_sample(cpu_buf, ibs[8], ibs[9]); - add_sample(cpu_buf, ibs[10], ibs[11]); - } - - return 1; - } - - void oprofile_add_ibs_sample(struct pt_regs *const regs, - unsigned int * const ibs_sample, u8 code) - { - int is_kernel = !user_mode(regs); - unsigned long pc = profile_pc(regs); - - struct oprofile_cpu_buffer *cpu_buf = - &per_cpu(cpu_buffer, smp_processor_id()); - - if (!backtrace_depth) { - log_ibs_sample(cpu_buf, pc, is_kernel, ibs_sample, code); - return; + add_sample(cpu_buf, ibs_sample[6], ibs_sample[7]); + add_sample(cpu_buf, ibs_sample[8], ibs_sample[9]); + add_sample(cpu_buf, ibs_sample[10], ibs_sample[11]); } - /* if log_sample() fails we can't backtrace since we lost the source - * of this event */ - if (log_ibs_sample(cpu_buf, pc, is_kernel, ibs_sample, code)) + if (backtrace_depth) oprofile_ops.backtrace(regs, backtrace_depth); } @@@ -376,11 -345,16 +358,16 @@@ void oprofile_add_trace(unsigned long p */ static void wq_sync_buffer(struct work_struct *work) { - struct oprofile_cpu_buffer * b = + struct oprofile_cpu_buffer *b = container_of(work, struct oprofile_cpu_buffer, work.work); if (b->cpu != smp_processor_id()) { printk(KERN_DEBUG "WQ on CPU%d, prefer CPU%d\n", smp_processor_id(), b->cpu); + + if (!cpu_online(b->cpu)) { + cancel_delayed_work(&b->work); + return; + } } sync_buffer(b->cpu); diff --combined drivers/oprofile/event_buffer.h index 84bf324c577,00db2e66570..4e70749f8d1 --- a/drivers/oprofile/event_buffer.h +++ b/drivers/oprofile/event_buffer.h @@@ -10,20 -10,13 +10,20 @@@ #ifndef EVENT_BUFFER_H #define EVENT_BUFFER_H - #include + #include #include - + int alloc_event_buffer(void); void free_event_buffer(void); - + +/** + * Add data to the event buffer. + * The data passed is free-form, but typically consists of + * file offsets, dcookies, context information, and ESCAPE codes. + */ +void add_event_entry(unsigned long data); + /* wake up the process sleeping on the event file */ void wake_up_buffer_waiter(void); @@@ -31,10 -24,10 +31,10 @@@ #define NO_COOKIE 0UL extern const struct file_operations event_buffer_fops; - + /* mutex between sync_cpu_buffers() and the * file reading code. */ extern struct mutex buffer_mutex; - + #endif /* EVENT_BUFFER_H */