From bd2172f58094b3f8afa017e68f3f0b57577824e1 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 16 Dec 2008 16:19:54 +0100 Subject: oprofile: rename kernel-wide identifiers This patch renames kernel-wide identifiers to something more oprofile specific names. Cc: Andrew Morton Signed-off-by: Robert Richter --- drivers/oprofile/cpu_buffer.c | 12 ++++++------ drivers/oprofile/event_buffer.c | 4 ++-- drivers/oprofile/oprof.c | 4 ++-- drivers/oprofile/oprof.h | 8 ++++---- drivers/oprofile/oprofile_files.c | 27 ++++++++++++++------------- 5 files changed, 28 insertions(+), 27 deletions(-) (limited to 'drivers/oprofile') diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index 61090969158f..fcf96f608d86 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -66,7 +66,7 @@ void free_cpu_buffers(void) unsigned long oprofile_get_cpu_buffer_size(void) { - return fs_cpu_buffer_size; + return oprofile_cpu_buffer_size; } void oprofile_cpu_buffer_inc_smpl_lost(void) @@ -81,7 +81,7 @@ int alloc_cpu_buffers(void) { int i; - unsigned long buffer_size = fs_cpu_buffer_size; + unsigned long buffer_size = oprofile_cpu_buffer_size; op_ring_buffer_read = ring_buffer_alloc(buffer_size, OP_BUFFER_FLAGS); if (!op_ring_buffer_read) @@ -238,7 +238,7 @@ void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs, { struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer); - if (!backtrace_depth) { + if (!oprofile_backtrace_depth) { log_sample(cpu_buf, pc, is_kernel, event); return; } @@ -251,7 +251,7 @@ void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs, * source of this event */ if (log_sample(cpu_buf, pc, is_kernel, event)) - oprofile_ops.backtrace(regs, backtrace_depth); + oprofile_ops.backtrace(regs, oprofile_backtrace_depth); oprofile_end_trace(cpu_buf); } @@ -308,8 +308,8 @@ void oprofile_add_ibs_sample(struct pt_regs * const regs, if (fail) goto fail; - if (backtrace_depth) - oprofile_ops.backtrace(regs, backtrace_depth); + if (oprofile_backtrace_depth) + oprofile_ops.backtrace(regs, oprofile_backtrace_depth); return; diff --git a/drivers/oprofile/event_buffer.c b/drivers/oprofile/event_buffer.c index 191a3202cecc..2b7ae366ceb1 100644 --- a/drivers/oprofile/event_buffer.c +++ b/drivers/oprofile/event_buffer.c @@ -73,8 +73,8 @@ int alloc_event_buffer(void) unsigned long flags; spin_lock_irqsave(&oprofilefs_lock, flags); - buffer_size = fs_buffer_size; - buffer_watershed = fs_buffer_watershed; + buffer_size = oprofile_buffer_size; + buffer_watershed = oprofile_buffer_watershed; spin_unlock_irqrestore(&oprofilefs_lock, flags); if (buffer_watershed >= buffer_size) diff --git a/drivers/oprofile/oprof.c b/drivers/oprofile/oprof.c index cd375907f26f..3cffce90f82a 100644 --- a/drivers/oprofile/oprof.c +++ b/drivers/oprofile/oprof.c @@ -23,7 +23,7 @@ struct oprofile_operations oprofile_ops; unsigned long oprofile_started; -unsigned long backtrace_depth; +unsigned long oprofile_backtrace_depth; static unsigned long is_setup; static DEFINE_MUTEX(start_mutex); @@ -172,7 +172,7 @@ int oprofile_set_backtrace(unsigned long val) goto out; } - backtrace_depth = val; + oprofile_backtrace_depth = val; out: mutex_unlock(&start_mutex); diff --git a/drivers/oprofile/oprof.h b/drivers/oprofile/oprof.h index 5df0c21a608f..c288d3c24b50 100644 --- a/drivers/oprofile/oprof.h +++ b/drivers/oprofile/oprof.h @@ -21,12 +21,12 @@ void oprofile_stop(void); struct oprofile_operations; -extern unsigned long fs_buffer_size; -extern unsigned long fs_cpu_buffer_size; -extern unsigned long fs_buffer_watershed; +extern unsigned long oprofile_buffer_size; +extern unsigned long oprofile_cpu_buffer_size; +extern unsigned long oprofile_buffer_watershed; extern struct oprofile_operations oprofile_ops; extern unsigned long oprofile_started; -extern unsigned long backtrace_depth; +extern unsigned long oprofile_backtrace_depth; struct super_block; struct dentry; diff --git a/drivers/oprofile/oprofile_files.c b/drivers/oprofile/oprofile_files.c index d8201998b0b7..5d36ffc30dd5 100644 --- a/drivers/oprofile/oprofile_files.c +++ b/drivers/oprofile/oprofile_files.c @@ -14,17 +14,18 @@ #include "oprofile_stats.h" #include "oprof.h" -#define FS_BUFFER_SIZE_DEFAULT 131072 -#define FS_CPU_BUFFER_SIZE_DEFAULT 8192 -#define FS_BUFFER_WATERSHED_DEFAULT 32768 /* FIXME: tune */ +#define BUFFER_SIZE_DEFAULT 131072 +#define CPU_BUFFER_SIZE_DEFAULT 8192 +#define BUFFER_WATERSHED_DEFAULT 32768 /* FIXME: tune */ -unsigned long fs_buffer_size; -unsigned long fs_cpu_buffer_size; -unsigned long fs_buffer_watershed; +unsigned long oprofile_buffer_size; +unsigned long oprofile_cpu_buffer_size; +unsigned long oprofile_buffer_watershed; static ssize_t depth_read(struct file *file, char __user *buf, size_t count, loff_t *offset) { - return oprofilefs_ulong_to_user(backtrace_depth, buf, count, offset); + return oprofilefs_ulong_to_user(oprofile_backtrace_depth, buf, count, + offset); } @@ -125,16 +126,16 @@ static const struct file_operations dump_fops = { void oprofile_create_files(struct super_block *sb, struct dentry *root) { /* reinitialize default values */ - fs_buffer_size = FS_BUFFER_SIZE_DEFAULT; - fs_cpu_buffer_size = FS_CPU_BUFFER_SIZE_DEFAULT; - fs_buffer_watershed = FS_BUFFER_WATERSHED_DEFAULT; + oprofile_buffer_size = BUFFER_SIZE_DEFAULT; + oprofile_cpu_buffer_size = CPU_BUFFER_SIZE_DEFAULT; + oprofile_buffer_watershed = BUFFER_WATERSHED_DEFAULT; oprofilefs_create_file(sb, root, "enable", &enable_fops); oprofilefs_create_file_perm(sb, root, "dump", &dump_fops, 0666); oprofilefs_create_file(sb, root, "buffer", &event_buffer_fops); - oprofilefs_create_ulong(sb, root, "buffer_size", &fs_buffer_size); - oprofilefs_create_ulong(sb, root, "buffer_watershed", &fs_buffer_watershed); - oprofilefs_create_ulong(sb, root, "cpu_buffer_size", &fs_cpu_buffer_size); + oprofilefs_create_ulong(sb, root, "buffer_size", &oprofile_buffer_size); + oprofilefs_create_ulong(sb, root, "buffer_watershed", &oprofile_buffer_watershed); + oprofilefs_create_ulong(sb, root, "cpu_buffer_size", &oprofile_cpu_buffer_size); oprofilefs_create_file(sb, root, "cpu_type", &cpu_type_fops); oprofilefs_create_file(sb, root, "backtrace_depth", &depth_fops); oprofilefs_create_file(sb, root, "pointer_size", &pointer_size_fops); -- cgit v1.2.3-59-g8ed1b From 6d2c53f3cd81e33eec17aa99845d43e599986982 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Wed, 24 Dec 2008 16:53:53 +0100 Subject: oprofile: rename cpu buffer functions This patch renames cpu buffer functions to something more oprofile specific names. Functions will be moved to the global name space. Cc: Andrew Morton Signed-off-by: Robert Richter --- drivers/oprofile/buffer_sync.c | 10 +++++----- drivers/oprofile/cpu_buffer.c | 4 ++-- drivers/oprofile/cpu_buffer.h | 10 +++++----- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/oprofile') diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index 737bd9484822..d295d92b57f0 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -331,7 +331,7 @@ static void add_ibs_begin(int cpu, int code, struct mm_struct *mm) off_t offset; struct op_sample *sample; - sample = cpu_buffer_read_entry(cpu); + sample = op_cpu_buffer_read_entry(cpu); if (!sample) goto Error; rip = sample->eip; @@ -370,7 +370,7 @@ static void add_ibs_begin(int cpu, int code, struct mm_struct *mm) count = IBS_OP_CODE_SIZE; /*IBS OP is 5 int64s*/ for (i = 0; i < count; i++) { - sample = cpu_buffer_read_entry(cpu); + sample = op_cpu_buffer_read_entry(cpu); if (!sample) goto Error; add_event_entry(sample->eip); @@ -537,11 +537,11 @@ void sync_buffer(int cpu) add_cpu_switch(cpu); - cpu_buffer_reset(cpu); - available = cpu_buffer_entries(cpu); + op_cpu_buffer_reset(cpu); + available = op_cpu_buffer_entries(cpu); for (i = 0; i < available; ++i) { - struct op_sample *s = cpu_buffer_read_entry(cpu); + struct op_sample *s = op_cpu_buffer_read_entry(cpu); if (!s) break; diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index fcf96f608d86..e52c085cd186 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -152,14 +152,14 @@ add_sample(struct oprofile_cpu_buffer *cpu_buf, struct op_entry entry; int ret; - ret = cpu_buffer_write_entry(&entry); + ret = op_cpu_buffer_write_entry(&entry); if (ret) return ret; entry.sample->eip = pc; entry.sample->event = event; - ret = cpu_buffer_write_commit(&entry); + ret = op_cpu_buffer_write_commit(&entry); if (ret) return ret; diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h index aacb0f0bc566..83d491e273fe 100644 --- a/drivers/oprofile/cpu_buffer.h +++ b/drivers/oprofile/cpu_buffer.h @@ -64,7 +64,7 @@ DECLARE_PER_CPU(struct oprofile_cpu_buffer, cpu_buffer); * reset these to invalid values; the next sample collected will * populate the buffer with proper values to initialize the buffer */ -static inline void cpu_buffer_reset(int cpu) +static inline void op_cpu_buffer_reset(int cpu) { struct oprofile_cpu_buffer *cpu_buf = &per_cpu(cpu_buffer, cpu); @@ -72,7 +72,7 @@ static inline void cpu_buffer_reset(int cpu) cpu_buf->last_task = NULL; } -static inline int cpu_buffer_write_entry(struct op_entry *entry) +static inline int op_cpu_buffer_write_entry(struct op_entry *entry) { entry->event = ring_buffer_lock_reserve(op_ring_buffer_write, sizeof(struct op_sample), @@ -88,13 +88,13 @@ static inline int cpu_buffer_write_entry(struct op_entry *entry) return 0; } -static inline int cpu_buffer_write_commit(struct op_entry *entry) +static inline int op_cpu_buffer_write_commit(struct op_entry *entry) { return ring_buffer_unlock_commit(op_ring_buffer_write, entry->event, entry->irq_flags); } -static inline struct op_sample *cpu_buffer_read_entry(int cpu) +static inline struct op_sample *op_cpu_buffer_read_entry(int cpu) { struct ring_buffer_event *e; e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL); @@ -111,7 +111,7 @@ static inline struct op_sample *cpu_buffer_read_entry(int cpu) } /* "acquire" as many cpu buffer slots as we can */ -static inline unsigned long cpu_buffer_entries(int cpu) +static inline unsigned long op_cpu_buffer_entries(int cpu) { return ring_buffer_entries_cpu(op_ring_buffer_read, cpu) + ring_buffer_entries_cpu(op_ring_buffer_write, cpu); -- cgit v1.2.3-59-g8ed1b From 9966718daee592fbdc523703b2d8200009642506 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 16 Dec 2008 16:19:54 +0100 Subject: oprofile: remove ring buffer inline functions in cpu_buffer.h This patch moves ring buffer inline functions to cpu_buffer.c. Cc: Andrew Morton Signed-off-by: Robert Richter --- drivers/oprofile/cpu_buffer.c | 48 +++++++++++++++++++++++++++++++++++++++-- drivers/oprofile/cpu_buffer.h | 50 ++++--------------------------------------- 2 files changed, 50 insertions(+), 48 deletions(-) (limited to 'drivers/oprofile') diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index e52c085cd186..cd67d4dd30b7 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -45,8 +45,8 @@ * can be changed to a single buffer solution when the ring buffer * access is implemented as non-locking atomic code. */ -struct ring_buffer *op_ring_buffer_read; -struct ring_buffer *op_ring_buffer_write; +static struct ring_buffer *op_ring_buffer_read; +static struct ring_buffer *op_ring_buffer_write; DEFINE_PER_CPU(struct oprofile_cpu_buffer, cpu_buffer); static void wq_sync_buffer(struct work_struct *work); @@ -145,6 +145,50 @@ void end_cpu_work(void) flush_scheduled_work(); } +int op_cpu_buffer_write_entry(struct op_entry *entry) +{ + entry->event = ring_buffer_lock_reserve(op_ring_buffer_write, + sizeof(struct op_sample), + &entry->irq_flags); + if (entry->event) + entry->sample = ring_buffer_event_data(entry->event); + else + entry->sample = NULL; + + if (!entry->sample) + return -ENOMEM; + + return 0; +} + +int op_cpu_buffer_write_commit(struct op_entry *entry) +{ + return ring_buffer_unlock_commit(op_ring_buffer_write, entry->event, + entry->irq_flags); +} + +struct op_sample *op_cpu_buffer_read_entry(int cpu) +{ + struct ring_buffer_event *e; + e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL); + if (e) + return ring_buffer_event_data(e); + if (ring_buffer_swap_cpu(op_ring_buffer_read, + op_ring_buffer_write, + cpu)) + return NULL; + e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL); + if (e) + return ring_buffer_event_data(e); + return NULL; +} + +unsigned long op_cpu_buffer_entries(int cpu) +{ + return ring_buffer_entries_cpu(op_ring_buffer_read, cpu) + + ring_buffer_entries_cpu(op_ring_buffer_write, cpu); +} + static inline int add_sample(struct oprofile_cpu_buffer *cpu_buf, unsigned long pc, unsigned long event) diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h index 83d491e273fe..cd28abc06960 100644 --- a/drivers/oprofile/cpu_buffer.h +++ b/drivers/oprofile/cpu_buffer.h @@ -54,8 +54,6 @@ struct oprofile_cpu_buffer { struct delayed_work work; }; -extern struct ring_buffer *op_ring_buffer_read; -extern struct ring_buffer *op_ring_buffer_write; DECLARE_PER_CPU(struct oprofile_cpu_buffer, cpu_buffer); /* @@ -72,50 +70,10 @@ static inline void op_cpu_buffer_reset(int cpu) cpu_buf->last_task = NULL; } -static inline int op_cpu_buffer_write_entry(struct op_entry *entry) -{ - entry->event = ring_buffer_lock_reserve(op_ring_buffer_write, - sizeof(struct op_sample), - &entry->irq_flags); - if (entry->event) - entry->sample = ring_buffer_event_data(entry->event); - else - entry->sample = NULL; - - if (!entry->sample) - return -ENOMEM; - - return 0; -} - -static inline int op_cpu_buffer_write_commit(struct op_entry *entry) -{ - return ring_buffer_unlock_commit(op_ring_buffer_write, entry->event, - entry->irq_flags); -} - -static inline struct op_sample *op_cpu_buffer_read_entry(int cpu) -{ - struct ring_buffer_event *e; - e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL); - if (e) - return ring_buffer_event_data(e); - if (ring_buffer_swap_cpu(op_ring_buffer_read, - op_ring_buffer_write, - cpu)) - return NULL; - e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL); - if (e) - return ring_buffer_event_data(e); - return NULL; -} - -/* "acquire" as many cpu buffer slots as we can */ -static inline unsigned long op_cpu_buffer_entries(int cpu) -{ - return ring_buffer_entries_cpu(op_ring_buffer_read, cpu) - + ring_buffer_entries_cpu(op_ring_buffer_write, cpu); -} +int op_cpu_buffer_write_entry(struct op_entry *entry); +int op_cpu_buffer_write_commit(struct op_entry *entry); +struct op_sample *op_cpu_buffer_read_entry(int cpu); +unsigned long op_cpu_buffer_entries(int cpu); /* transient events for the CPU buffer -> event buffer */ #define CPU_IS_KERNEL 1 -- cgit v1.2.3-59-g8ed1b From 300157768f050dabc73a99d958b504282088a132 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 23 Dec 2008 01:35:12 +0100 Subject: oprofile: reordering some code in cpu_buffer.c Reordering code to keep alloc/free functions together. Signed-off-by: Robert Richter --- drivers/oprofile/cpu_buffer.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/oprofile') diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index cd67d4dd30b7..b353b19bd786 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -54,16 +54,6 @@ static void wq_sync_buffer(struct work_struct *work); #define DEFAULT_TIMER_EXPIRE (HZ / 10) static int work_enabled; -void free_cpu_buffers(void) -{ - if (op_ring_buffer_read) - ring_buffer_free(op_ring_buffer_read); - op_ring_buffer_read = NULL; - if (op_ring_buffer_write) - ring_buffer_free(op_ring_buffer_write); - op_ring_buffer_write = NULL; -} - unsigned long oprofile_get_cpu_buffer_size(void) { return oprofile_cpu_buffer_size; @@ -77,6 +67,16 @@ void oprofile_cpu_buffer_inc_smpl_lost(void) cpu_buf->sample_lost_overflow++; } +void free_cpu_buffers(void) +{ + if (op_ring_buffer_read) + ring_buffer_free(op_ring_buffer_read); + op_ring_buffer_read = NULL; + if (op_ring_buffer_write) + ring_buffer_free(op_ring_buffer_write); + op_ring_buffer_write = NULL; +} + int alloc_cpu_buffers(void) { int i; -- cgit v1.2.3-59-g8ed1b From d45d23bed4bf7b25b7dcc336552a251db1aa1279 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 16 Dec 2008 12:00:10 +0100 Subject: oprofile: add inline function __oprofile_add_ext_sample() This patch adds the inline function __oprofile_add_ext_sample() to cpu_buffer.c and thus reduces overhead when calling oprofile_add_sample(). Signed-off-by: Robert Richter --- drivers/oprofile/cpu_buffer.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers/oprofile') diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index b353b19bd786..9e66c384e016 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -277,8 +277,9 @@ static void oprofile_end_trace(struct oprofile_cpu_buffer *cpu_buf) cpu_buf->tracing = 0; } -void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs, - unsigned long event, int is_kernel) +static inline void +__oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs, + unsigned long event, int is_kernel) { struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer); @@ -299,12 +300,18 @@ void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs, oprofile_end_trace(cpu_buf); } +void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs, + unsigned long event, int is_kernel) +{ + __oprofile_add_ext_sample(pc, regs, event, is_kernel); +} + void oprofile_add_sample(struct pt_regs * const regs, unsigned long event) { int is_kernel = !user_mode(regs); unsigned long pc = profile_pc(regs); - oprofile_add_ext_sample(pc, regs, event, is_kernel); + __oprofile_add_ext_sample(pc, regs, event, is_kernel); } #ifdef CONFIG_OPROFILE_IBS -- cgit v1.2.3-59-g8ed1b From 9741b309bb4493eedd3cdb5c97b566338a0da2cc Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Thu, 18 Dec 2008 19:44:20 +0100 Subject: oprofile: simplify add_sample() This patch removes add_us_sample() and simplifies add_sample(). Code is much more readable now. Signed-off-by: Robert Richter --- drivers/oprofile/buffer_sync.c | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) (limited to 'drivers/oprofile') diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index d295d92b57f0..0abe29e7e4c7 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -392,11 +392,29 @@ static void add_sample_entry(unsigned long offset, unsigned long event) } -static int add_us_sample(struct mm_struct *mm, struct op_sample *s) +/* + * Add a sample to the global event buffer. If possible the + * sample is converted into a persistent dentry/offset pair + * for later lookup from userspace. Return 0 on failure. + */ +static int +add_sample(struct mm_struct *mm, struct op_sample *s, int in_kernel) { unsigned long cookie; off_t offset; + if (in_kernel) { + add_sample_entry(s->eip, s->event); + return 1; + } + + /* add userspace sample */ + + if (!mm) { + atomic_inc(&oprofile_stats.sample_lost_no_mm); + return 0; + } + cookie = lookup_dcookie(mm, s->eip, &offset); if (cookie == INVALID_COOKIE) { @@ -415,25 +433,6 @@ static int add_us_sample(struct mm_struct *mm, struct op_sample *s) } -/* Add a sample to the global event buffer. If possible the - * sample is converted into a persistent dentry/offset pair - * for later lookup from userspace. - */ -static int -add_sample(struct mm_struct *mm, struct op_sample *s, int in_kernel) -{ - if (in_kernel) { - add_sample_entry(s->eip, s->event); - return 1; - } else if (mm) { - return add_us_sample(mm, s); - } else { - atomic_inc(&oprofile_stats.sample_lost_no_mm); - } - return 0; -} - - static void release_mm(struct mm_struct *mm) { if (!mm) -- cgit v1.2.3-59-g8ed1b From 317f33bce6d43367a2fd170bc87ba18a88d2621d Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Thu, 18 Dec 2008 19:44:20 +0100 Subject: oprofile: simplify sync_buffer() Make code more readable. No functional changes. Signed-off-by: Robert Richter --- drivers/oprofile/buffer_sync.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'drivers/oprofile') diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index 0abe29e7e4c7..22cdb5108360 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -579,12 +579,20 @@ void sync_buffer(int cpu) add_user_ctx_switch(new, cookie); break; } - } else if (state >= sb_bt_start && - !add_sample(mm, s, in_kernel)) { - if (state == sb_bt_start) { - state = sb_bt_ignore; - atomic_inc(&oprofile_stats.bt_lost_no_mapping); - } + continue; + } + + if (state < sb_bt_start) + /* ignore sample */ + continue; + + if (add_sample(mm, s, in_kernel)) + continue; + + /* ignore backtraces if failed to add a sample */ + if (state == sb_bt_start) { + state = sb_bt_ignore; + atomic_inc(&oprofile_stats.bt_lost_no_mapping); } } release_mm(mm); -- cgit v1.2.3-59-g8ed1b From 6352d92dec0c4b833c12a169e86762c05d0396f3 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Thu, 18 Dec 2008 22:09:13 +0100 Subject: oprofile: simplify oprofile_begin_trace() This patch removes the unused return parameter in oprofile_begin_trace(). Also, oprofile_begin_trace() and oprofile_end_trace() are inline now. Signed-off-by: Robert Richter --- drivers/oprofile/cpu_buffer.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/oprofile') diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index 9e66c384e016..435bd6e08d5b 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -265,14 +265,13 @@ fail: return 0; } -static int oprofile_begin_trace(struct oprofile_cpu_buffer *cpu_buf) +static inline void oprofile_begin_trace(struct oprofile_cpu_buffer *cpu_buf) { add_code(cpu_buf, CPU_TRACE_BEGIN); cpu_buf->tracing = 1; - return 1; } -static void oprofile_end_trace(struct oprofile_cpu_buffer *cpu_buf) +static inline void oprofile_end_trace(struct oprofile_cpu_buffer *cpu_buf) { cpu_buf->tracing = 0; } @@ -288,8 +287,7 @@ __oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs, return; } - if (!oprofile_begin_trace(cpu_buf)) - return; + oprofile_begin_trace(cpu_buf); /* * if log_sample() fail we can't backtrace since we lost the @@ -297,6 +295,7 @@ __oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs, */ if (log_sample(cpu_buf, pc, is_kernel, event)) oprofile_ops.backtrace(regs, oprofile_backtrace_depth); + oprofile_end_trace(cpu_buf); } -- cgit v1.2.3-59-g8ed1b From 3967e93e063d7ee608f465cbccb65abb518e9d33 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 30 Dec 2008 05:10:58 +0100 Subject: oprofile: simplify add_sample() in cpu_buffer.c Signed-off-by: Robert Richter --- drivers/oprofile/cpu_buffer.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/oprofile') diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index 435bd6e08d5b..d92f0020502e 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -203,11 +203,7 @@ add_sample(struct oprofile_cpu_buffer *cpu_buf, entry.sample->eip = pc; entry.sample->event = event; - ret = op_cpu_buffer_write_commit(&entry); - if (ret) - return ret; - - return 0; + return op_cpu_buffer_write_commit(&entry); } static inline int -- cgit v1.2.3-59-g8ed1b From dbe6e2835e32461e7d592077947081c32f3da1d5 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 16 Dec 2008 11:01:18 +0100 Subject: oprofile: simplify add_ibs_begin() Signed-off-by: Robert Richter --- drivers/oprofile/buffer_sync.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/oprofile') diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index 22cdb5108360..7415d2e6b3a1 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -333,7 +333,7 @@ static void add_ibs_begin(int cpu, int code, struct mm_struct *mm) sample = op_cpu_buffer_read_entry(cpu); if (!sample) - goto Error; + return; rip = sample->eip; #ifdef __LP64__ @@ -372,15 +372,12 @@ static void add_ibs_begin(int cpu, int code, struct mm_struct *mm) for (i = 0; i < count; i++) { sample = op_cpu_buffer_read_entry(cpu); if (!sample) - goto Error; + return; add_event_entry(sample->eip); add_event_entry(sample->event); } return; - -Error: - return; } #endif -- cgit v1.2.3-59-g8ed1b From 8d15df84a42b140a8262a325b987a283ef9f5f63 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Wed, 24 Dec 2008 15:42:58 +0100 Subject: oprofile: remove unused components in struct oprofile_cpu_buffer Signed-off-by: Robert Richter --- drivers/oprofile/cpu_buffer.c | 2 -- drivers/oprofile/cpu_buffer.h | 2 -- 2 files changed, 4 deletions(-) (limited to 'drivers/oprofile') diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index d92f0020502e..b426ae8ad2e2 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -97,8 +97,6 @@ int alloc_cpu_buffers(void) b->last_is_kernel = -1; b->tracing = 0; b->buffer_size = buffer_size; - b->tail_pos = 0; - b->head_pos = 0; b->sample_received = 0; b->sample_lost_overflow = 0; b->backtrace_aborted = 0; diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h index cd28abc06960..65b763ad72da 100644 --- a/drivers/oprofile/cpu_buffer.h +++ b/drivers/oprofile/cpu_buffer.h @@ -40,8 +40,6 @@ struct op_entry { }; struct oprofile_cpu_buffer { - volatile unsigned long head_pos; - volatile unsigned long tail_pos; unsigned long buffer_size; struct task_struct *last_task; int last_is_kernel; -- cgit v1.2.3-59-g8ed1b From f4ff2364417f0092e49f6a3aa474549a56697f2d Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Mon, 5 Jan 2009 11:27:52 +0100 Subject: oprofile: remove unused ibs macro Signed-off-by: Robert Richter --- drivers/oprofile/cpu_buffer.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/oprofile') diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index b426ae8ad2e2..8ae37c9d0ec4 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -309,8 +309,6 @@ void oprofile_add_sample(struct pt_regs * const regs, unsigned long event) #ifdef CONFIG_OPROFILE_IBS -#define MAX_IBS_SAMPLE_SIZE 14 - void oprofile_add_ibs_sample(struct pt_regs * const regs, unsigned int * const ibs_sample, int ibs_code) { -- cgit v1.2.3-59-g8ed1b From 8350c78734e67ac1f8bfd4eb14b70ff4d01a9a12 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Fri, 19 Dec 2008 12:59:28 +0100 Subject: oprofile: remove backtrace code for ibs This code is broken since a TRACE_BEGIN_CODE is never sent to the daemon. The data becomes corrupt since the backtrace is interpreted as ibs sample. Signed-off-by: Robert Richter --- drivers/oprofile/buffer_sync.c | 2 -- drivers/oprofile/cpu_buffer.c | 10 ++-------- 2 files changed, 2 insertions(+), 10 deletions(-) (limited to 'drivers/oprofile') diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index 7415d2e6b3a1..e61e25fda1ad 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -557,11 +557,9 @@ void sync_buffer(int cpu) break; #ifdef CONFIG_OPROFILE_IBS case IBS_FETCH_BEGIN: - state = sb_bt_start; add_ibs_begin(cpu, IBS_FETCH_CODE, mm); break; case IBS_OP_BEGIN: - state = sb_bt_start; add_ibs_begin(cpu, IBS_OP_CODE, mm); break; #endif diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index 8ae37c9d0ec4..92bf8c0d86fe 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -347,17 +347,11 @@ void oprofile_add_ibs_sample(struct pt_regs * const regs, fail = fail || add_sample(cpu_buf, ibs_sample[10], ibs_sample[11]); } - if (fail) - goto fail; - - if (oprofile_backtrace_depth) - oprofile_ops.backtrace(regs, oprofile_backtrace_depth); - - return; + if (!fail) + return; fail: cpu_buf->sample_lost_overflow++; - return; } #endif -- cgit v1.2.3-59-g8ed1b From 6368a1f4d99fe9a1990ef3f04ab2d2ce9dad0a7c Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Mon, 29 Dec 2008 18:44:21 +0100 Subject: oprofile: making add_sample_entry() inline Signed-off-by: Robert Richter --- drivers/oprofile/buffer_sync.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/oprofile') diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index e61e25fda1ad..bf8fcc7163da 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -382,7 +382,7 @@ static void add_ibs_begin(int cpu, int code, struct mm_struct *mm) #endif -static void add_sample_entry(unsigned long offset, unsigned long event) +static inline void add_sample_entry(unsigned long offset, unsigned long event) { add_event_entry(offset); add_event_entry(event); -- cgit v1.2.3-59-g8ed1b From d0e233846dcef56ae78f6d8fd0e0cba85a2a1489 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 23 Dec 2008 04:03:05 +0100 Subject: oprofile: rename add_sample() in cpu_buffer.c Rename the fucntion to op_add_sample() since there is a collision with another one with the same name in buffer_sync.c. Signed-off-by: Robert Richter --- drivers/oprofile/cpu_buffer.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/oprofile') diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index 92bf8c0d86fe..ac79f6676033 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -188,8 +188,8 @@ unsigned long op_cpu_buffer_entries(int cpu) } static inline int -add_sample(struct oprofile_cpu_buffer *cpu_buf, - unsigned long pc, unsigned long event) +op_add_sample(struct oprofile_cpu_buffer *cpu_buf, + unsigned long pc, unsigned long event) { struct op_entry entry; int ret; @@ -207,7 +207,7 @@ add_sample(struct oprofile_cpu_buffer *cpu_buf, static inline int add_code(struct oprofile_cpu_buffer *buffer, unsigned long value) { - return add_sample(buffer, ESCAPE_CODE, value); + return op_add_sample(buffer, ESCAPE_CODE, value); } /* This must be safe from any context. It's safe writing here @@ -249,7 +249,7 @@ static int log_sample(struct oprofile_cpu_buffer *cpu_buf, unsigned long pc, goto fail; } - if (add_sample(cpu_buf, pc, event)) + if (op_add_sample(cpu_buf, pc, event)) goto fail; return 1; @@ -337,14 +337,14 @@ void oprofile_add_ibs_sample(struct pt_regs * const regs, } fail = fail || add_code(cpu_buf, ibs_code); - fail = fail || add_sample(cpu_buf, ibs_sample[0], ibs_sample[1]); - fail = fail || add_sample(cpu_buf, ibs_sample[2], ibs_sample[3]); - fail = fail || add_sample(cpu_buf, ibs_sample[4], ibs_sample[5]); + fail = fail || op_add_sample(cpu_buf, ibs_sample[0], ibs_sample[1]); + fail = fail || op_add_sample(cpu_buf, ibs_sample[2], ibs_sample[3]); + fail = fail || op_add_sample(cpu_buf, ibs_sample[4], ibs_sample[5]); if (ibs_code == IBS_OP_BEGIN) { - fail = fail || add_sample(cpu_buf, ibs_sample[6], ibs_sample[7]); - fail = fail || add_sample(cpu_buf, ibs_sample[8], ibs_sample[9]); - fail = fail || add_sample(cpu_buf, ibs_sample[10], ibs_sample[11]); + fail = fail || op_add_sample(cpu_buf, ibs_sample[6], ibs_sample[7]); + fail = fail || op_add_sample(cpu_buf, ibs_sample[8], ibs_sample[9]); + fail = fail || op_add_sample(cpu_buf, ibs_sample[10], ibs_sample[11]); } if (!fail) @@ -376,7 +376,7 @@ void oprofile_add_trace(unsigned long pc) if (pc == ESCAPE_CODE) goto fail; - if (add_sample(cpu_buf, pc, 0)) + if (op_add_sample(cpu_buf, pc, 0)) goto fail; return; -- cgit v1.2.3-59-g8ed1b From d358e75fc40cc3bbab11654ba0a88b232c543d12 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Mon, 5 Jan 2009 13:14:04 +0100 Subject: oprofile: rename variables in add_ibs_begin() This unifies usage of variable names within oprofile. Signed-off-by: Robert Richter --- drivers/oprofile/buffer_sync.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/oprofile') diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index bf8fcc7163da..21fd249b6e0b 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -325,36 +325,36 @@ static void add_trace_begin(void) */ static void add_ibs_begin(int cpu, int code, struct mm_struct *mm) { - unsigned long rip; + unsigned long pc; int i, count; - unsigned long ibs_cookie = 0; + unsigned long cookie = 0; off_t offset; struct op_sample *sample; sample = op_cpu_buffer_read_entry(cpu); if (!sample) return; - rip = sample->eip; + pc = sample->eip; #ifdef __LP64__ - rip += sample->event << 32; + pc += sample->event << 32; #endif if (mm) { - ibs_cookie = lookup_dcookie(mm, rip, &offset); + cookie = lookup_dcookie(mm, pc, &offset); - if (ibs_cookie == NO_COOKIE) - offset = rip; - if (ibs_cookie == INVALID_COOKIE) { + if (cookie == NO_COOKIE) + offset = pc; + if (cookie == INVALID_COOKIE) { atomic_inc(&oprofile_stats.sample_lost_no_mapping); - offset = rip; + offset = pc; } - if (ibs_cookie != last_cookie) { - add_cookie_switch(ibs_cookie); - last_cookie = ibs_cookie; + if (cookie != last_cookie) { + add_cookie_switch(cookie); + last_cookie = cookie; } } else - offset = rip; + offset = pc; add_event_entry(ESCAPE_CODE); add_event_entry(code); -- cgit v1.2.3-59-g8ed1b From 2cc28b9f261dd28d69767a34682ce55a27d928ed Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Thu, 25 Dec 2008 17:26:07 +0100 Subject: oprofile: add op_cpu_buffer_write_reserve() This function prepares the cpu buffer to write a sample. Struct op_entry is used during operations on the ring buffer while struct op_sample contains the data that is stored in the ring buffer. Struct entry can be uninitialized. The function reserves a data array that is specified by size. Use op_cpu_buffer_write_commit() after preparing the sample. In case of errors a null pointer is returned, otherwise the pointer to the sample. Signed-off-by: Robert Richter --- drivers/oprofile/cpu_buffer.c | 43 ++++++++++++++++++++++++++++++------------- drivers/oprofile/cpu_buffer.h | 9 +++++++-- 2 files changed, 37 insertions(+), 15 deletions(-) (limited to 'drivers/oprofile') diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index ac79f6676033..934ff159e70e 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -1,11 +1,12 @@ /** * @file cpu_buffer.c * - * @remark Copyright 2002 OProfile authors + * @remark Copyright 2002-2009 OProfile authors * @remark Read the file COPYING * * @author John Levon * @author Barry Kasindorf + * @author Robert Richter * * Each CPU has a local buffer that stores PC value/event * pairs. We also log context switches when we notice them. @@ -143,20 +144,36 @@ void end_cpu_work(void) flush_scheduled_work(); } -int op_cpu_buffer_write_entry(struct op_entry *entry) +/* + * This function prepares the cpu buffer to write a sample. + * + * Struct op_entry is used during operations on the ring buffer while + * struct op_sample contains the data that is stored in the ring + * buffer. Struct entry can be uninitialized. The function reserves a + * data array that is specified by size. Use + * op_cpu_buffer_write_commit() after preparing the sample. In case of + * errors a null pointer is returned, otherwise the pointer to the + * sample. + * + */ +struct op_sample +*op_cpu_buffer_write_reserve(struct op_entry *entry, unsigned long size) { - entry->event = ring_buffer_lock_reserve(op_ring_buffer_write, - sizeof(struct op_sample), - &entry->irq_flags); + entry->event = ring_buffer_lock_reserve + (op_ring_buffer_write, sizeof(struct op_sample) + + size * sizeof(entry->sample->data[0]), &entry->irq_flags); if (entry->event) entry->sample = ring_buffer_event_data(entry->event); else entry->sample = NULL; if (!entry->sample) - return -ENOMEM; + return NULL; - return 0; + entry->size = size; + entry->data = entry->sample->data; + + return entry->sample; } int op_cpu_buffer_write_commit(struct op_entry *entry) @@ -192,14 +209,14 @@ op_add_sample(struct oprofile_cpu_buffer *cpu_buf, unsigned long pc, unsigned long event) { struct op_entry entry; - int ret; + struct op_sample *sample; - ret = op_cpu_buffer_write_entry(&entry); - if (ret) - return ret; + sample = op_cpu_buffer_write_reserve(&entry, 0); + if (!sample) + return -ENOMEM; - entry.sample->eip = pc; - entry.sample->event = event; + sample->eip = pc; + sample->event = event; return op_cpu_buffer_write_commit(&entry); } diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h index 65b763ad72da..2d4bfdeb7fba 100644 --- a/drivers/oprofile/cpu_buffer.h +++ b/drivers/oprofile/cpu_buffer.h @@ -1,10 +1,11 @@ /** * @file cpu_buffer.h * - * @remark Copyright 2002 OProfile authors + * @remark Copyright 2002-2009 OProfile authors * @remark Read the file COPYING * * @author John Levon + * @author Robert Richter */ #ifndef OPROFILE_CPU_BUFFER_H @@ -31,12 +32,15 @@ void end_cpu_work(void); struct op_sample { unsigned long eip; unsigned long event; + unsigned long data[0]; }; struct op_entry { struct ring_buffer_event *event; struct op_sample *sample; unsigned long irq_flags; + unsigned long size; + unsigned long *data; }; struct oprofile_cpu_buffer { @@ -68,7 +72,8 @@ static inline void op_cpu_buffer_reset(int cpu) cpu_buf->last_task = NULL; } -int op_cpu_buffer_write_entry(struct op_entry *entry); +struct op_sample +*op_cpu_buffer_write_reserve(struct op_entry *entry, unsigned long size); int op_cpu_buffer_write_commit(struct op_entry *entry); struct op_sample *op_cpu_buffer_read_entry(int cpu); unsigned long op_cpu_buffer_entries(int cpu); -- cgit v1.2.3-59-g8ed1b From 2d87b14cf8d0b07720de26d90789d02124141616 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 30 Dec 2008 04:10:46 +0100 Subject: oprofile: modify op_cpu_buffer_read_entry() This implements the support of samples with attached data. Signed-off-by: Robert Richter --- drivers/oprofile/buffer_sync.c | 23 +++++++++++++---------- drivers/oprofile/cpu_buffer.c | 14 +++++++++++--- drivers/oprofile/cpu_buffer.h | 2 +- 3 files changed, 25 insertions(+), 14 deletions(-) (limited to 'drivers/oprofile') diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index 21fd249b6e0b..908202afbae9 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -329,9 +329,10 @@ static void add_ibs_begin(int cpu, int code, struct mm_struct *mm) int i, count; unsigned long cookie = 0; off_t offset; + struct op_entry entry; struct op_sample *sample; - sample = op_cpu_buffer_read_entry(cpu); + sample = op_cpu_buffer_read_entry(&entry, cpu); if (!sample) return; pc = sample->eip; @@ -370,7 +371,7 @@ static void add_ibs_begin(int cpu, int code, struct mm_struct *mm) count = IBS_OP_CODE_SIZE; /*IBS OP is 5 int64s*/ for (i = 0; i < count; i++) { - sample = op_cpu_buffer_read_entry(cpu); + sample = op_cpu_buffer_read_entry(&entry, cpu); if (!sample) return; add_event_entry(sample->eip); @@ -528,6 +529,8 @@ void sync_buffer(int cpu) sync_buffer_state state = sb_buffer_start; unsigned int i; unsigned long available; + struct op_entry entry; + struct op_sample *sample; mutex_lock(&buffer_mutex); @@ -537,19 +540,19 @@ void sync_buffer(int cpu) available = op_cpu_buffer_entries(cpu); for (i = 0; i < available; ++i) { - struct op_sample *s = op_cpu_buffer_read_entry(cpu); - if (!s) + sample = op_cpu_buffer_read_entry(&entry, cpu); + if (!sample) break; - if (is_code(s->eip)) { - switch (s->event) { + if (is_code(sample->eip)) { + switch (sample->event) { case 0: case CPU_IS_KERNEL: /* kernel/userspace switch */ - in_kernel = s->event; + in_kernel = sample->event; if (state == sb_buffer_start) state = sb_sample_start; - add_kernel_ctx_switch(s->event); + add_kernel_ctx_switch(sample->event); break; case CPU_TRACE_BEGIN: state = sb_bt_start; @@ -566,7 +569,7 @@ void sync_buffer(int cpu) default: /* userspace context switch */ oldmm = mm; - new = (struct task_struct *)s->event; + new = (struct task_struct *)sample->event; release_mm(oldmm); mm = take_tasks_mm(new); if (mm != oldmm) @@ -581,7 +584,7 @@ void sync_buffer(int cpu) /* ignore sample */ continue; - if (add_sample(mm, s, in_kernel)) + if (add_sample(mm, sample, in_kernel)) continue; /* ignore backtraces if failed to add a sample */ diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index 934ff159e70e..400f7fcffdbe 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -182,20 +182,28 @@ int op_cpu_buffer_write_commit(struct op_entry *entry) entry->irq_flags); } -struct op_sample *op_cpu_buffer_read_entry(int cpu) +struct op_sample *op_cpu_buffer_read_entry(struct op_entry *entry, int cpu) { struct ring_buffer_event *e; e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL); if (e) - return ring_buffer_event_data(e); + goto event; if (ring_buffer_swap_cpu(op_ring_buffer_read, op_ring_buffer_write, cpu)) return NULL; e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL); if (e) - return ring_buffer_event_data(e); + goto event; return NULL; + +event: + entry->event = e; + entry->sample = ring_buffer_event_data(e); + entry->size = (ring_buffer_event_length(e) - sizeof(struct op_sample)) + / sizeof(entry->sample->data[0]); + entry->data = entry->sample->data; + return entry->sample; } unsigned long op_cpu_buffer_entries(int cpu) diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h index 2d4bfdeb7fba..d7c0545ef8b2 100644 --- a/drivers/oprofile/cpu_buffer.h +++ b/drivers/oprofile/cpu_buffer.h @@ -75,7 +75,7 @@ static inline void op_cpu_buffer_reset(int cpu) struct op_sample *op_cpu_buffer_write_reserve(struct op_entry *entry, unsigned long size); int op_cpu_buffer_write_commit(struct op_entry *entry); -struct op_sample *op_cpu_buffer_read_entry(int cpu); +struct op_sample *op_cpu_buffer_read_entry(struct op_entry *entry, int cpu); unsigned long op_cpu_buffer_entries(int cpu); /* transient events for the CPU buffer -> event buffer */ -- cgit v1.2.3-59-g8ed1b From ae735e9964b4584923f2997d98a8d80ae9c1a75c Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Thu, 25 Dec 2008 17:26:07 +0100 Subject: oprofile: rework implementation of cpu buffer events Special events such as task or context switches are marked with an escape code in the cpu buffer followed by an event code or a task identifier. There is one escape code per event. To make escape sequences also available for data samples the internal cpu buffer format must be changed. The current implementation does not allow the extension of event codes since this would lead to collisions with the task identifiers. To avoid this, this patch introduces an event mask that allows the storage of multiple events with one escape code. Now, task identifiers are stored in the data section of the sample. The implementation also allows the usage of custom data in a sample. As a side effect the new code is much more readable and easier to understand. Signed-off-by: Robert Richter --- arch/x86/oprofile/op_model_amd.c | 8 +-- drivers/oprofile/buffer_sync.c | 42 ++++++------ drivers/oprofile/cpu_buffer.c | 139 +++++++++++++++++++++------------------ drivers/oprofile/cpu_buffer.h | 12 ++-- 4 files changed, 106 insertions(+), 95 deletions(-) (limited to 'drivers/oprofile') diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c index 423a95438cbc..f101724db80a 100644 --- a/arch/x86/oprofile/op_model_amd.c +++ b/arch/x86/oprofile/op_model_amd.c @@ -2,7 +2,7 @@ * @file op_model_amd.c * athlon / K7 / K8 / Family 10h model-specific MSR operations * - * @remark Copyright 2002-2008 OProfile authors + * @remark Copyright 2002-2009 OProfile authors * @remark Read the file COPYING * * @author John Levon @@ -10,7 +10,7 @@ * @author Graydon Hoare * @author Robert Richter * @author Barry Kasindorf -*/ + */ #include #include @@ -62,8 +62,8 @@ static unsigned long reset_value[NUM_COUNTERS]; /* Codes used in cpu_buffer.c */ /* This produces duplicate code, need to be fixed */ -#define IBS_FETCH_BEGIN 3 -#define IBS_OP_BEGIN 4 +#define IBS_FETCH_BEGIN (1UL << 4) +#define IBS_OP_BEGIN (1UL << 5) /* * The function interface needs to be fixed, something like add diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index 908202afbae9..d969bb13a252 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -1,11 +1,12 @@ /** * @file buffer_sync.c * - * @remark Copyright 2002 OProfile authors + * @remark Copyright 2002-2009 OProfile authors * @remark Read the file COPYING * * @author John Levon * @author Barry Kasindorf + * @author Robert Richter * * This is the core of the buffer management. Each * CPU buffer is processed and entered into the @@ -529,6 +530,7 @@ void sync_buffer(int cpu) sync_buffer_state state = sb_buffer_start; unsigned int i; unsigned long available; + unsigned long flags; struct op_entry entry; struct op_sample *sample; @@ -545,38 +547,34 @@ void sync_buffer(int cpu) break; if (is_code(sample->eip)) { - switch (sample->event) { - case 0: - case CPU_IS_KERNEL: + flags = sample->event; + if (flags & TRACE_BEGIN) { + state = sb_bt_start; + add_trace_begin(); + } + if (flags & KERNEL_CTX_SWITCH) { /* kernel/userspace switch */ - in_kernel = sample->event; + in_kernel = flags & IS_KERNEL; if (state == sb_buffer_start) state = sb_sample_start; - add_kernel_ctx_switch(sample->event); - break; - case CPU_TRACE_BEGIN: - state = sb_bt_start; - add_trace_begin(); - break; -#ifdef CONFIG_OPROFILE_IBS - case IBS_FETCH_BEGIN: - add_ibs_begin(cpu, IBS_FETCH_CODE, mm); - break; - case IBS_OP_BEGIN: - add_ibs_begin(cpu, IBS_OP_CODE, mm); - break; -#endif - default: + add_kernel_ctx_switch(flags & IS_KERNEL); + } + if (flags & USER_CTX_SWITCH) { /* userspace context switch */ oldmm = mm; - new = (struct task_struct *)sample->event; + new = (struct task_struct *)sample->data[0]; release_mm(oldmm); mm = take_tasks_mm(new); if (mm != oldmm) cookie = get_exec_dcookie(mm); add_user_ctx_switch(new, cookie); - break; } +#ifdef CONFIG_OPROFILE_IBS + if (flags & IBS_FETCH_BEGIN) + add_ibs_begin(cpu, IBS_FETCH_CODE, mm); + if (flags & IBS_OP_BEGIN) + add_ibs_begin(cpu, IBS_OP_CODE, mm); +#endif continue; } diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index 400f7fcffdbe..e859d23cfc57 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -212,6 +212,59 @@ unsigned long op_cpu_buffer_entries(int cpu) + ring_buffer_entries_cpu(op_ring_buffer_write, cpu); } +static int +op_add_code(struct oprofile_cpu_buffer *cpu_buf, unsigned long backtrace, + int is_kernel, struct task_struct *task) +{ + struct op_entry entry; + struct op_sample *sample; + unsigned long flags; + int size; + + flags = 0; + + if (backtrace) + flags |= TRACE_BEGIN; + + /* notice a switch from user->kernel or vice versa */ + is_kernel = !!is_kernel; + if (cpu_buf->last_is_kernel != is_kernel) { + cpu_buf->last_is_kernel = is_kernel; + flags |= KERNEL_CTX_SWITCH; + if (is_kernel) + flags |= IS_KERNEL; + } + + /* notice a task switch */ + if (cpu_buf->last_task != task) { + cpu_buf->last_task = task; + flags |= USER_CTX_SWITCH; + } + + if (!flags) + /* nothing to do */ + return 0; + + if (flags & USER_CTX_SWITCH) + size = 1; + else + size = 0; + + sample = op_cpu_buffer_write_reserve(&entry, size); + if (!sample) + return -ENOMEM; + + sample->eip = ESCAPE_CODE; + sample->event = flags; + + if (size) + sample->data[0] = (unsigned long)task; + + op_cpu_buffer_write_commit(&entry); + + return 0; +} + static inline int op_add_sample(struct oprofile_cpu_buffer *cpu_buf, unsigned long pc, unsigned long event) @@ -229,26 +282,18 @@ op_add_sample(struct oprofile_cpu_buffer *cpu_buf, return op_cpu_buffer_write_commit(&entry); } -static inline int -add_code(struct oprofile_cpu_buffer *buffer, unsigned long value) -{ - return op_add_sample(buffer, ESCAPE_CODE, value); -} - -/* This must be safe from any context. It's safe writing here - * because of the head/tail separation of the writer and reader - * of the CPU buffer. +/* + * This must be safe from any context. * * is_kernel is needed because on some architectures you cannot * tell if you are in kernel or user space simply by looking at * 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, - int is_kernel, unsigned long event) +static int +log_sample(struct oprofile_cpu_buffer *cpu_buf, unsigned long pc, + unsigned long backtrace, int is_kernel, unsigned long event) { - struct task_struct *task; - cpu_buf->sample_received++; if (pc == ESCAPE_CODE) { @@ -256,23 +301,8 @@ static int log_sample(struct oprofile_cpu_buffer *cpu_buf, unsigned long pc, return 0; } - is_kernel = !!is_kernel; - - task = current; - - /* notice a switch from user->kernel or vice versa */ - if (cpu_buf->last_is_kernel != is_kernel) { - cpu_buf->last_is_kernel = is_kernel; - if (add_code(cpu_buf, is_kernel)) - goto fail; - } - - /* notice a task switch */ - if (cpu_buf->last_task != task) { - cpu_buf->last_task = task; - if (add_code(cpu_buf, (unsigned long)task)) - goto fail; - } + if (op_add_code(cpu_buf, backtrace, is_kernel, current)) + goto fail; if (op_add_sample(cpu_buf, pc, event)) goto fail; @@ -286,7 +316,6 @@ fail: static inline void oprofile_begin_trace(struct oprofile_cpu_buffer *cpu_buf) { - add_code(cpu_buf, CPU_TRACE_BEGIN); cpu_buf->tracing = 1; } @@ -300,21 +329,21 @@ __oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs, unsigned long event, int is_kernel) { struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer); - - if (!oprofile_backtrace_depth) { - log_sample(cpu_buf, pc, is_kernel, event); - return; - } - - oprofile_begin_trace(cpu_buf); + unsigned long backtrace = oprofile_backtrace_depth; /* * if log_sample() fail we can't backtrace since we lost the * source of this event */ - if (log_sample(cpu_buf, pc, is_kernel, event)) - oprofile_ops.backtrace(regs, oprofile_backtrace_depth); + if (!log_sample(cpu_buf, pc, backtrace, is_kernel, event)) + /* failed */ + return; + if (!backtrace) + return; + + oprofile_begin_trace(cpu_buf); + oprofile_ops.backtrace(regs, backtrace); oprofile_end_trace(cpu_buf); } @@ -339,29 +368,14 @@ void oprofile_add_ibs_sample(struct pt_regs * const regs, { int is_kernel = !user_mode(regs); struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer); - struct task_struct *task; int fail = 0; cpu_buf->sample_received++; - /* notice a switch from user->kernel or vice versa */ - if (cpu_buf->last_is_kernel != is_kernel) { - if (add_code(cpu_buf, is_kernel)) - goto fail; - cpu_buf->last_is_kernel = is_kernel; - } + /* backtraces disabled for ibs */ + fail = fail || op_add_code(cpu_buf, 0, is_kernel, current); - /* notice a task switch */ - if (!is_kernel) { - task = current; - if (cpu_buf->last_task != task) { - if (add_code(cpu_buf, (unsigned long)task)) - goto fail; - cpu_buf->last_task = task; - } - } - - fail = fail || add_code(cpu_buf, ibs_code); + fail = fail || op_add_sample(cpu_buf, ESCAPE_CODE, ibs_code); fail = fail || op_add_sample(cpu_buf, ibs_sample[0], ibs_sample[1]); fail = fail || op_add_sample(cpu_buf, ibs_sample[2], ibs_sample[3]); fail = fail || op_add_sample(cpu_buf, ibs_sample[4], ibs_sample[5]); @@ -372,11 +386,8 @@ void oprofile_add_ibs_sample(struct pt_regs * const regs, fail = fail || op_add_sample(cpu_buf, ibs_sample[10], ibs_sample[11]); } - if (!fail) - return; - -fail: - cpu_buf->sample_lost_overflow++; + if (fail) + cpu_buf->sample_lost_overflow++; } #endif @@ -384,7 +395,7 @@ fail: void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event) { struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer); - log_sample(cpu_buf, pc, is_kernel, event); + log_sample(cpu_buf, pc, 0, is_kernel, event); } void oprofile_add_trace(unsigned long pc) diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h index d7c0545ef8b2..e634dcf2f26f 100644 --- a/drivers/oprofile/cpu_buffer.h +++ b/drivers/oprofile/cpu_buffer.h @@ -78,10 +78,12 @@ int op_cpu_buffer_write_commit(struct op_entry *entry); struct op_sample *op_cpu_buffer_read_entry(struct op_entry *entry, int cpu); unsigned long op_cpu_buffer_entries(int cpu); -/* transient events for the CPU buffer -> event buffer */ -#define CPU_IS_KERNEL 1 -#define CPU_TRACE_BEGIN 2 -#define IBS_FETCH_BEGIN 3 -#define IBS_OP_BEGIN 4 +/* extra data flags */ +#define KERNEL_CTX_SWITCH (1UL << 0) +#define IS_KERNEL (1UL << 1) +#define TRACE_BEGIN (1UL << 2) +#define USER_CTX_SWITCH (1UL << 3) +#define IBS_FETCH_BEGIN (1UL << 4) +#define IBS_OP_BEGIN (1UL << 5) #endif /* OPROFILE_CPU_BUFFER_H */ -- cgit v1.2.3-59-g8ed1b From d9928c25a6960cf128c2078a89fe6f8e0180ff60 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Thu, 25 Dec 2008 17:26:07 +0100 Subject: oprofile: add op_cpu_buffer_add_data() This function can be used to attach data to a sample. It returns the remaining free buffer size that has been reserved with op_cpu_buffer_write_reserve(). Signed-off-by: Robert Richter --- drivers/oprofile/cpu_buffer.c | 2 +- drivers/oprofile/cpu_buffer.h | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers/oprofile') diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index e859d23cfc57..1b6590746be4 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -258,7 +258,7 @@ op_add_code(struct oprofile_cpu_buffer *cpu_buf, unsigned long backtrace, sample->event = flags; if (size) - sample->data[0] = (unsigned long)task; + op_cpu_buffer_add_data(&entry, (unsigned long)task); op_cpu_buffer_write_commit(&entry); diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h index e634dcf2f26f..e178dd2799c4 100644 --- a/drivers/oprofile/cpu_buffer.h +++ b/drivers/oprofile/cpu_buffer.h @@ -78,6 +78,18 @@ int op_cpu_buffer_write_commit(struct op_entry *entry); struct op_sample *op_cpu_buffer_read_entry(struct op_entry *entry, int cpu); unsigned long op_cpu_buffer_entries(int cpu); +/* returns the remaining free size of data in the entry */ +static inline +int op_cpu_buffer_add_data(struct op_entry *entry, unsigned long val) +{ + if (!entry->size) + return 0; + *entry->data = val; + entry->size--; + entry->data++; + return entry->size; +} + /* extra data flags */ #define KERNEL_CTX_SWITCH (1UL << 0) #define IS_KERNEL (1UL << 1) -- cgit v1.2.3-59-g8ed1b From bd7dc46f770d317ada1348294ff1f319243b803b Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 6 Jan 2009 03:56:50 +0100 Subject: oprofile: add op_cpu_buffer_get_data() This function provides access to attached data of a sample. It returns the size of data including the current value. Also, op_cpu_buffer_get_size() is available to check if there is data attached. Signed-off-by: Robert Richter --- drivers/oprofile/buffer_sync.c | 6 ++++-- drivers/oprofile/cpu_buffer.h | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) (limited to 'drivers/oprofile') diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index d969bb13a252..f9031d31eeb7 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -524,6 +524,7 @@ void sync_buffer(int cpu) { struct mm_struct *mm = NULL; struct mm_struct *oldmm; + unsigned long val; struct task_struct *new; unsigned long cookie = 0; int in_kernel = 1; @@ -559,10 +560,11 @@ void sync_buffer(int cpu) state = sb_sample_start; add_kernel_ctx_switch(flags & IS_KERNEL); } - if (flags & USER_CTX_SWITCH) { + if (flags & USER_CTX_SWITCH + && op_cpu_buffer_get_data(&entry, &val)) { /* userspace context switch */ + new = (struct task_struct *)val; oldmm = mm; - new = (struct task_struct *)sample->data[0]; release_mm(oldmm); mm = take_tasks_mm(new); if (mm != oldmm) diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h index e178dd2799c4..f34376046573 100644 --- a/drivers/oprofile/cpu_buffer.h +++ b/drivers/oprofile/cpu_buffer.h @@ -90,6 +90,26 @@ int op_cpu_buffer_add_data(struct op_entry *entry, unsigned long val) return entry->size; } +/* returns the size of data in the entry */ +static inline +int op_cpu_buffer_get_size(struct op_entry *entry) +{ + return entry->size; +} + +/* returns 0 if empty or the size of data including the current value */ +static inline +int op_cpu_buffer_get_data(struct op_entry *entry, unsigned long *val) +{ + int size = entry->size; + if (!size) + return 0; + *val = *entry->data; + entry->size--; + entry->data++; + return size; +} + /* extra data flags */ #define KERNEL_CTX_SWITCH (1UL << 0) #define IS_KERNEL (1UL << 1) -- cgit v1.2.3-59-g8ed1b From 1acda878e20ea0cd3708ba66dca67d52eaafdd2b Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Mon, 5 Jan 2009 10:35:31 +0100 Subject: oprofile: use new data sample format for ibs The new ring buffer implementation allows the storage of samples with different size. This patch implements the usage of the new sample format to store ibs samples in the cpu buffer. Until now, writing to the cpu buffer could lead to incomplete sampling sequences since IBS samples were transfered in multiple samples. Due to a full buffer, data could be lost at any time. This can't happen any more since the complete data is reserved in advance and then stored in a single sample. Signed-off-by: Robert Richter --- arch/x86/oprofile/op_model_amd.c | 119 ++++++++++++++------------------------- drivers/oprofile/buffer_sync.c | 53 ++++------------- drivers/oprofile/cpu_buffer.c | 39 +++++++------ drivers/oprofile/cpu_buffer.h | 2 - 4 files changed, 76 insertions(+), 137 deletions(-) (limited to 'drivers/oprofile') diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c index f101724db80a..cf310aeb462c 100644 --- a/arch/x86/oprofile/op_model_amd.c +++ b/arch/x86/oprofile/op_model_amd.c @@ -22,6 +22,7 @@ #include "op_x86_model.h" #include "op_counter.h" +#include "../../../drivers/oprofile/cpu_buffer.h" #define NUM_COUNTERS 4 #define NUM_CONTROLS 4 @@ -60,51 +61,16 @@ static unsigned long reset_value[NUM_COUNTERS]; #define IBS_OP_LOW_VALID_BIT (1ULL<<18) /* bit 18 */ #define IBS_OP_LOW_ENABLE (1ULL<<17) /* bit 17 */ -/* Codes used in cpu_buffer.c */ -/* This produces duplicate code, need to be fixed */ -#define IBS_FETCH_BEGIN (1UL << 4) -#define IBS_OP_BEGIN (1UL << 5) - /* * The function interface needs to be fixed, something like add * data. Should then be added to linux/oprofile.h. */ -extern void -oprofile_add_ibs_sample(struct pt_regs * const regs, - unsigned int * const ibs_sample, int ibs_code); - -struct ibs_fetch_sample { - /* MSRC001_1031 IBS Fetch Linear Address Register */ - unsigned int ibs_fetch_lin_addr_low; - unsigned int ibs_fetch_lin_addr_high; - /* MSRC001_1030 IBS Fetch Control Register */ - unsigned int ibs_fetch_ctl_low; - unsigned int ibs_fetch_ctl_high; - /* MSRC001_1032 IBS Fetch Physical Address Register */ - unsigned int ibs_fetch_phys_addr_low; - unsigned int ibs_fetch_phys_addr_high; -}; +extern +void oprofile_add_data(struct op_entry *entry, struct pt_regs * const regs, + unsigned long pc, int code, int size); -struct ibs_op_sample { - /* MSRC001_1034 IBS Op Logical Address Register (IbsRIP) */ - unsigned int ibs_op_rip_low; - unsigned int ibs_op_rip_high; - /* MSRC001_1035 IBS Op Data Register */ - unsigned int ibs_op_data1_low; - unsigned int ibs_op_data1_high; - /* MSRC001_1036 IBS Op Data 2 Register */ - unsigned int ibs_op_data2_low; - unsigned int ibs_op_data2_high; - /* MSRC001_1037 IBS Op Data 3 Register */ - unsigned int ibs_op_data3_low; - unsigned int ibs_op_data3_high; - /* MSRC001_1038 IBS DC Linear Address Register (IbsDcLinAd) */ - unsigned int ibs_dc_linear_low; - unsigned int ibs_dc_linear_high; - /* MSRC001_1039 IBS DC Physical Address Register (IbsDcPhysAd) */ - unsigned int ibs_dc_phys_low; - unsigned int ibs_dc_phys_high; -}; +#define IBS_FETCH_SIZE 6 +#define IBS_OP_SIZE 12 static int has_ibs; /* AMD Family10h and later */ @@ -197,9 +163,9 @@ static inline int op_amd_handle_ibs(struct pt_regs * const regs, struct op_msrs const * const msrs) { - unsigned int low, high; - struct ibs_fetch_sample ibs_fetch; - struct ibs_op_sample ibs_op; + u32 low, high; + u64 msr; + struct op_entry entry; if (!has_ibs) return 1; @@ -207,21 +173,19 @@ op_amd_handle_ibs(struct pt_regs * const regs, if (ibs_config.fetch_enabled) { rdmsr(MSR_AMD64_IBSFETCHCTL, low, high); if (high & IBS_FETCH_HIGH_VALID_BIT) { - ibs_fetch.ibs_fetch_ctl_high = high; - ibs_fetch.ibs_fetch_ctl_low = low; - rdmsr(MSR_AMD64_IBSFETCHLINAD, low, high); - ibs_fetch.ibs_fetch_lin_addr_high = high; - ibs_fetch.ibs_fetch_lin_addr_low = low; - rdmsr(MSR_AMD64_IBSFETCHPHYSAD, low, high); - ibs_fetch.ibs_fetch_phys_addr_high = high; - ibs_fetch.ibs_fetch_phys_addr_low = low; - - oprofile_add_ibs_sample(regs, - (unsigned int *)&ibs_fetch, - IBS_FETCH_BEGIN); + rdmsrl(MSR_AMD64_IBSFETCHLINAD, msr); + oprofile_add_data(&entry, regs, msr, IBS_FETCH_CODE, + IBS_FETCH_SIZE); + op_cpu_buffer_add_data(&entry, (u32)msr); + op_cpu_buffer_add_data(&entry, (u32)(msr >> 32)); + op_cpu_buffer_add_data(&entry, low); + op_cpu_buffer_add_data(&entry, high); + rdmsrl(MSR_AMD64_IBSFETCHPHYSAD, msr); + op_cpu_buffer_add_data(&entry, (u32)msr); + op_cpu_buffer_add_data(&entry, (u32)(msr >> 32)); + op_cpu_buffer_write_commit(&entry); /* reenable the IRQ */ - rdmsr(MSR_AMD64_IBSFETCHCTL, low, high); high &= ~IBS_FETCH_HIGH_VALID_BIT; high |= IBS_FETCH_HIGH_ENABLE; low &= IBS_FETCH_LOW_MAX_CNT_MASK; @@ -232,30 +196,29 @@ op_amd_handle_ibs(struct pt_regs * const regs, if (ibs_config.op_enabled) { rdmsr(MSR_AMD64_IBSOPCTL, low, high); if (low & IBS_OP_LOW_VALID_BIT) { - rdmsr(MSR_AMD64_IBSOPRIP, low, high); - ibs_op.ibs_op_rip_low = low; - ibs_op.ibs_op_rip_high = high; - rdmsr(MSR_AMD64_IBSOPDATA, low, high); - ibs_op.ibs_op_data1_low = low; - ibs_op.ibs_op_data1_high = high; - rdmsr(MSR_AMD64_IBSOPDATA2, low, high); - ibs_op.ibs_op_data2_low = low; - ibs_op.ibs_op_data2_high = high; - rdmsr(MSR_AMD64_IBSOPDATA3, low, high); - ibs_op.ibs_op_data3_low = low; - ibs_op.ibs_op_data3_high = high; - rdmsr(MSR_AMD64_IBSDCLINAD, low, high); - ibs_op.ibs_dc_linear_low = low; - ibs_op.ibs_dc_linear_high = high; - rdmsr(MSR_AMD64_IBSDCPHYSAD, low, high); - ibs_op.ibs_dc_phys_low = low; - ibs_op.ibs_dc_phys_high = high; + rdmsrl(MSR_AMD64_IBSOPRIP, msr); + oprofile_add_data(&entry, regs, msr, IBS_OP_CODE, + IBS_OP_SIZE); + op_cpu_buffer_add_data(&entry, (u32)msr); + op_cpu_buffer_add_data(&entry, (u32)(msr >> 32)); + rdmsrl(MSR_AMD64_IBSOPDATA, msr); + op_cpu_buffer_add_data(&entry, (u32)msr); + op_cpu_buffer_add_data(&entry, (u32)(msr >> 32)); + rdmsrl(MSR_AMD64_IBSOPDATA2, msr); + op_cpu_buffer_add_data(&entry, (u32)msr); + op_cpu_buffer_add_data(&entry, (u32)(msr >> 32)); + rdmsrl(MSR_AMD64_IBSOPDATA3, msr); + op_cpu_buffer_add_data(&entry, (u32)msr); + op_cpu_buffer_add_data(&entry, (u32)(msr >> 32)); + rdmsrl(MSR_AMD64_IBSDCLINAD, msr); + op_cpu_buffer_add_data(&entry, (u32)msr); + op_cpu_buffer_add_data(&entry, (u32)(msr >> 32)); + rdmsrl(MSR_AMD64_IBSDCPHYSAD, msr); + op_cpu_buffer_add_data(&entry, (u32)msr); + op_cpu_buffer_add_data(&entry, (u32)(msr >> 32)); + op_cpu_buffer_write_commit(&entry); /* reenable the IRQ */ - oprofile_add_ibs_sample(regs, - (unsigned int *)&ibs_op, - IBS_OP_BEGIN); - rdmsr(MSR_AMD64_IBSOPCTL, low, high); high = 0; low &= ~IBS_OP_LOW_VALID_BIT; low |= IBS_OP_LOW_ENABLE; diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index f9031d31eeb7..d692fdc1a211 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -318,29 +318,18 @@ static void add_trace_begin(void) #ifdef CONFIG_OPROFILE_IBS -#define IBS_FETCH_CODE_SIZE 2 -#define IBS_OP_CODE_SIZE 5 - -/* - * Add IBS fetch and op entries to event buffer - */ -static void add_ibs_begin(int cpu, int code, struct mm_struct *mm) +static void add_data(struct op_entry *entry, struct mm_struct *mm) { - unsigned long pc; - int i, count; - unsigned long cookie = 0; + unsigned long code, pc, val; + unsigned long cookie; off_t offset; - struct op_entry entry; - struct op_sample *sample; - sample = op_cpu_buffer_read_entry(&entry, cpu); - if (!sample) + if (!op_cpu_buffer_get_data(entry, &code)) + return; + if (!op_cpu_buffer_get_data(entry, &pc)) + return; + if (!op_cpu_buffer_get_size(entry)) return; - pc = sample->eip; - -#ifdef __LP64__ - pc += sample->event << 32; -#endif if (mm) { cookie = lookup_dcookie(mm, pc, &offset); @@ -362,24 +351,8 @@ static void add_ibs_begin(int cpu, int code, struct mm_struct *mm) add_event_entry(code); add_event_entry(offset); /* Offset from Dcookie */ - /* we send the Dcookie offset, but send the raw Linear Add also*/ - add_event_entry(sample->eip); - add_event_entry(sample->event); - - if (code == IBS_FETCH_CODE) - count = IBS_FETCH_CODE_SIZE; /*IBS FETCH is 2 int64s*/ - else - count = IBS_OP_CODE_SIZE; /*IBS OP is 5 int64s*/ - - for (i = 0; i < count; i++) { - sample = op_cpu_buffer_read_entry(&entry, cpu); - if (!sample) - return; - add_event_entry(sample->eip); - add_event_entry(sample->event); - } - - return; + while (op_cpu_buffer_get_data(entry, &val)) + add_event_entry(val); } #endif @@ -572,10 +545,8 @@ void sync_buffer(int cpu) add_user_ctx_switch(new, cookie); } #ifdef CONFIG_OPROFILE_IBS - if (flags & IBS_FETCH_BEGIN) - add_ibs_begin(cpu, IBS_FETCH_CODE, mm); - if (flags & IBS_OP_BEGIN) - add_ibs_begin(cpu, IBS_OP_CODE, mm); + if (op_cpu_buffer_get_size(&entry)) + add_data(&entry, mm); #endif continue; } diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index 1b6590746be4..ddba9d01f09b 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -363,31 +363,38 @@ void oprofile_add_sample(struct pt_regs * const regs, unsigned long event) #ifdef CONFIG_OPROFILE_IBS -void oprofile_add_ibs_sample(struct pt_regs * const regs, - unsigned int * const ibs_sample, int ibs_code) +/* + * Add samples with data to the ring buffer. + * + * Use op_cpu_buffer_add_data(&entry, val) to add data and + * op_cpu_buffer_write_commit(&entry) to commit the sample. + */ +void oprofile_add_data(struct op_entry *entry, struct pt_regs * const regs, + unsigned long pc, int code, int size) { + struct op_sample *sample; int is_kernel = !user_mode(regs); struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer); - int fail = 0; cpu_buf->sample_received++; - /* backtraces disabled for ibs */ - fail = fail || op_add_code(cpu_buf, 0, is_kernel, current); + /* no backtraces for samples with data */ + if (op_add_code(cpu_buf, 0, is_kernel, current)) + goto fail; - fail = fail || op_add_sample(cpu_buf, ESCAPE_CODE, ibs_code); - fail = fail || op_add_sample(cpu_buf, ibs_sample[0], ibs_sample[1]); - fail = fail || op_add_sample(cpu_buf, ibs_sample[2], ibs_sample[3]); - fail = fail || op_add_sample(cpu_buf, ibs_sample[4], ibs_sample[5]); + sample = op_cpu_buffer_write_reserve(entry, size + 2); + if (!sample) + goto fail; + sample->eip = ESCAPE_CODE; + sample->event = 0; /* no flags */ - if (ibs_code == IBS_OP_BEGIN) { - fail = fail || op_add_sample(cpu_buf, ibs_sample[6], ibs_sample[7]); - fail = fail || op_add_sample(cpu_buf, ibs_sample[8], ibs_sample[9]); - fail = fail || op_add_sample(cpu_buf, ibs_sample[10], ibs_sample[11]); - } + op_cpu_buffer_add_data(entry, code); + op_cpu_buffer_add_data(entry, pc); + + return; - if (fail) - cpu_buf->sample_lost_overflow++; +fail: + cpu_buf->sample_lost_overflow++; } #endif diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h index f34376046573..525cc4d13d8d 100644 --- a/drivers/oprofile/cpu_buffer.h +++ b/drivers/oprofile/cpu_buffer.h @@ -115,7 +115,5 @@ int op_cpu_buffer_get_data(struct op_entry *entry, unsigned long *val) #define IS_KERNEL (1UL << 1) #define TRACE_BEGIN (1UL << 2) #define USER_CTX_SWITCH (1UL << 3) -#define IBS_FETCH_BEGIN (1UL << 4) -#define IBS_OP_BEGIN (1UL << 5) #endif /* OPROFILE_CPU_BUFFER_H */ -- cgit v1.2.3-59-g8ed1b From ebf8d974e298018f0b4ee02b1b097bf5500d3d27 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Wed, 7 Jan 2009 00:20:57 +0100 Subject: oprofile: remove #ifdef CONFIG_OPROFILE_IBS in non-ibs code The ifdefs can be removed since the code is no longer ibs specific and can be used for other purposes as well. IBS specific code is only in op_model_amd.c. Signed-off-by: Robert Richter --- drivers/oprofile/buffer_sync.c | 6 ------ drivers/oprofile/cpu_buffer.c | 4 ---- 2 files changed, 10 deletions(-) (limited to 'drivers/oprofile') diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index d692fdc1a211..ac014cb27915 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -316,8 +316,6 @@ static void add_trace_begin(void) add_event_entry(TRACE_BEGIN_CODE); } -#ifdef CONFIG_OPROFILE_IBS - static void add_data(struct op_entry *entry, struct mm_struct *mm) { unsigned long code, pc, val; @@ -355,8 +353,6 @@ static void add_data(struct op_entry *entry, struct mm_struct *mm) add_event_entry(val); } -#endif - static inline void add_sample_entry(unsigned long offset, unsigned long event) { add_event_entry(offset); @@ -544,10 +540,8 @@ void sync_buffer(int cpu) cookie = get_exec_dcookie(mm); add_user_ctx_switch(new, cookie); } -#ifdef CONFIG_OPROFILE_IBS if (op_cpu_buffer_get_size(&entry)) add_data(&entry, mm); -#endif continue; } diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index ddba9d01f09b..b846af632c81 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -361,8 +361,6 @@ void oprofile_add_sample(struct pt_regs * const regs, unsigned long event) __oprofile_add_ext_sample(pc, regs, event, is_kernel); } -#ifdef CONFIG_OPROFILE_IBS - /* * Add samples with data to the ring buffer. * @@ -397,8 +395,6 @@ fail: cpu_buf->sample_lost_overflow++; } -#endif - void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event) { struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer); -- cgit v1.2.3-59-g8ed1b From 14f0ca8eaea42a5b5a69cfcb699665dd2618db5f Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Wed, 7 Jan 2009 21:50:22 +0100 Subject: oprofile: make new cpu buffer functions part of the api This patch creates the new functions oprofile_write_reserve() oprofile_add_data() oprofile_write_commit() and makes them part of the oprofile api. Signed-off-by: Robert Richter --- arch/x86/oprofile/op_model_amd.c | 57 +++++++++++++++++----------------------- drivers/oprofile/cpu_buffer.c | 17 +++++++++--- drivers/oprofile/cpu_buffer.h | 8 +----- include/linux/oprofile.h | 18 +++++++++++++ 4 files changed, 57 insertions(+), 43 deletions(-) (limited to 'drivers/oprofile') diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c index cf310aeb462c..8fdf06e4edf9 100644 --- a/arch/x86/oprofile/op_model_amd.c +++ b/arch/x86/oprofile/op_model_amd.c @@ -22,7 +22,6 @@ #include "op_x86_model.h" #include "op_counter.h" -#include "../../../drivers/oprofile/cpu_buffer.h" #define NUM_COUNTERS 4 #define NUM_CONTROLS 4 @@ -61,14 +60,6 @@ static unsigned long reset_value[NUM_COUNTERS]; #define IBS_OP_LOW_VALID_BIT (1ULL<<18) /* bit 18 */ #define IBS_OP_LOW_ENABLE (1ULL<<17) /* bit 17 */ -/* - * The function interface needs to be fixed, something like add - * data. Should then be added to linux/oprofile.h. - */ -extern -void oprofile_add_data(struct op_entry *entry, struct pt_regs * const regs, - unsigned long pc, int code, int size); - #define IBS_FETCH_SIZE 6 #define IBS_OP_SIZE 12 @@ -174,16 +165,16 @@ op_amd_handle_ibs(struct pt_regs * const regs, rdmsr(MSR_AMD64_IBSFETCHCTL, low, high); if (high & IBS_FETCH_HIGH_VALID_BIT) { rdmsrl(MSR_AMD64_IBSFETCHLINAD, msr); - oprofile_add_data(&entry, regs, msr, IBS_FETCH_CODE, - IBS_FETCH_SIZE); - op_cpu_buffer_add_data(&entry, (u32)msr); - op_cpu_buffer_add_data(&entry, (u32)(msr >> 32)); - op_cpu_buffer_add_data(&entry, low); - op_cpu_buffer_add_data(&entry, high); + oprofile_write_reserve(&entry, regs, msr, + IBS_FETCH_CODE, IBS_FETCH_SIZE); + oprofile_add_data(&entry, (u32)msr); + oprofile_add_data(&entry, (u32)(msr >> 32)); + oprofile_add_data(&entry, low); + oprofile_add_data(&entry, high); rdmsrl(MSR_AMD64_IBSFETCHPHYSAD, msr); - op_cpu_buffer_add_data(&entry, (u32)msr); - op_cpu_buffer_add_data(&entry, (u32)(msr >> 32)); - op_cpu_buffer_write_commit(&entry); + oprofile_add_data(&entry, (u32)msr); + oprofile_add_data(&entry, (u32)(msr >> 32)); + oprofile_write_commit(&entry); /* reenable the IRQ */ high &= ~IBS_FETCH_HIGH_VALID_BIT; @@ -197,26 +188,26 @@ op_amd_handle_ibs(struct pt_regs * const regs, rdmsr(MSR_AMD64_IBSOPCTL, low, high); if (low & IBS_OP_LOW_VALID_BIT) { rdmsrl(MSR_AMD64_IBSOPRIP, msr); - oprofile_add_data(&entry, regs, msr, IBS_OP_CODE, - IBS_OP_SIZE); - op_cpu_buffer_add_data(&entry, (u32)msr); - op_cpu_buffer_add_data(&entry, (u32)(msr >> 32)); + oprofile_write_reserve(&entry, regs, msr, + IBS_OP_CODE, IBS_OP_SIZE); + oprofile_add_data(&entry, (u32)msr); + oprofile_add_data(&entry, (u32)(msr >> 32)); rdmsrl(MSR_AMD64_IBSOPDATA, msr); - op_cpu_buffer_add_data(&entry, (u32)msr); - op_cpu_buffer_add_data(&entry, (u32)(msr >> 32)); + oprofile_add_data(&entry, (u32)msr); + oprofile_add_data(&entry, (u32)(msr >> 32)); rdmsrl(MSR_AMD64_IBSOPDATA2, msr); - op_cpu_buffer_add_data(&entry, (u32)msr); - op_cpu_buffer_add_data(&entry, (u32)(msr >> 32)); + oprofile_add_data(&entry, (u32)msr); + oprofile_add_data(&entry, (u32)(msr >> 32)); rdmsrl(MSR_AMD64_IBSOPDATA3, msr); - op_cpu_buffer_add_data(&entry, (u32)msr); - op_cpu_buffer_add_data(&entry, (u32)(msr >> 32)); + oprofile_add_data(&entry, (u32)msr); + oprofile_add_data(&entry, (u32)(msr >> 32)); rdmsrl(MSR_AMD64_IBSDCLINAD, msr); - op_cpu_buffer_add_data(&entry, (u32)msr); - op_cpu_buffer_add_data(&entry, (u32)(msr >> 32)); + oprofile_add_data(&entry, (u32)msr); + oprofile_add_data(&entry, (u32)(msr >> 32)); rdmsrl(MSR_AMD64_IBSDCPHYSAD, msr); - op_cpu_buffer_add_data(&entry, (u32)msr); - op_cpu_buffer_add_data(&entry, (u32)(msr >> 32)); - op_cpu_buffer_write_commit(&entry); + oprofile_add_data(&entry, (u32)msr); + oprofile_add_data(&entry, (u32)(msr >> 32)); + oprofile_write_commit(&entry); /* reenable the IRQ */ high = 0; diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index b846af632c81..2e03b6d796d3 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -364,10 +364,11 @@ void oprofile_add_sample(struct pt_regs * const regs, unsigned long event) /* * Add samples with data to the ring buffer. * - * Use op_cpu_buffer_add_data(&entry, val) to add data and - * op_cpu_buffer_write_commit(&entry) to commit the sample. + * Use oprofile_add_data(&entry, val) to add data and + * oprofile_write_commit(&entry) to commit the sample. */ -void oprofile_add_data(struct op_entry *entry, struct pt_regs * const regs, +void +oprofile_write_reserve(struct op_entry *entry, struct pt_regs * const regs, unsigned long pc, int code, int size) { struct op_sample *sample; @@ -395,6 +396,16 @@ fail: cpu_buf->sample_lost_overflow++; } +int oprofile_add_data(struct op_entry *entry, unsigned long val) +{ + return op_cpu_buffer_add_data(entry, val); +} + +int oprofile_write_commit(struct op_entry *entry) +{ + return op_cpu_buffer_write_commit(entry); +} + void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event) { struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer); diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h index 525cc4d13d8d..63f81c44846a 100644 --- a/drivers/oprofile/cpu_buffer.h +++ b/drivers/oprofile/cpu_buffer.h @@ -35,13 +35,7 @@ struct op_sample { unsigned long data[0]; }; -struct op_entry { - struct ring_buffer_event *event; - struct op_sample *sample; - unsigned long irq_flags; - unsigned long size; - unsigned long *data; -}; +struct op_entry; struct oprofile_cpu_buffer { unsigned long buffer_size; diff --git a/include/linux/oprofile.h b/include/linux/oprofile.h index 1ce9fe572e51..1d9518bc4c58 100644 --- a/include/linux/oprofile.h +++ b/include/linux/oprofile.h @@ -164,4 +164,22 @@ void oprofile_put_buff(unsigned long *buf, unsigned int start, unsigned long oprofile_get_cpu_buffer_size(void); void oprofile_cpu_buffer_inc_smpl_lost(void); +/* cpu buffer functions */ + +struct op_sample; + +struct op_entry { + struct ring_buffer_event *event; + struct op_sample *sample; + unsigned long irq_flags; + unsigned long size; + unsigned long *data; +}; + +void oprofile_write_reserve(struct op_entry *entry, + struct pt_regs * const regs, + unsigned long pc, int code, int size); +int oprofile_add_data(struct op_entry *entry, unsigned long val); +int oprofile_write_commit(struct op_entry *entry); + #endif /* OPROFILE_H */ -- cgit v1.2.3-59-g8ed1b