summaryrefslogtreecommitdiff
path: root/drivers/oprofile
diff options
context:
space:
mode:
authorRobert Richter <robert.richter@amd.com>2009-01-05 09:35:31 (GMT)
committerRobert Richter <robert.richter@amd.com>2009-01-07 21:47:23 (GMT)
commit1acda878e20ea0cd3708ba66dca67d52eaafdd2b (patch)
tree97eb93396efc357f91dbd0ce080a5df51f29fd9b /drivers/oprofile
parentbd7dc46f770d317ada1348294ff1f319243b803b (diff)
downloadlinux-1acda878e20ea0cd3708ba66dca67d52eaafdd2b.tar.xz
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 <robert.richter@amd.com>
Diffstat (limited to 'drivers/oprofile')
-rw-r--r--drivers/oprofile/buffer_sync.c53
-rw-r--r--drivers/oprofile/cpu_buffer.c39
-rw-r--r--drivers/oprofile/cpu_buffer.h2
3 files changed, 35 insertions, 59 deletions
diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
index f9031d3..d692fdc 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 1b65907..ddba9d0 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 f343760..525cc4d 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 */