# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1280743338 -3600
# Node ID 042c8cd710810204049ea8194f1bb95e74949a1d
# Parent 2893229a53a0a3aa6663d96e7c877e43936a3c8e
xenoprofile: Add IBS support
Add IBS support for AMD family 10h processors. The major
implementation is derived from latest Linux. Two hypercalls are added,
which is necessary for IBS feature detection and user mode parameter
read.
Signed-off-by: Wei Wang <wei.wang2@xxxxxxx>
---
arch/i386/oprofile/op_counter.h | 11 ++++++
arch/i386/oprofile/xenoprof.c | 47 ++++++++++++++++++++++++++-
drivers/oprofile/buffer_sync.c | 66 +++++++++++++++++++++++++++++++++++++-
drivers/oprofile/cpu_buffer.c | 5 ++
drivers/oprofile/event_buffer.h | 2 +
drivers/oprofile/oprofile_files.c | 2 -
include/xen/interface/xenoprof.h | 17 ++++++++-
7 files changed, 144 insertions(+), 6 deletions(-)
diff -r 2893229a53a0 -r 042c8cd71081 arch/i386/oprofile/op_counter.h
--- a/arch/i386/oprofile/op_counter.h Mon Jul 26 10:40:00 2010 +0100
+++ b/arch/i386/oprofile/op_counter.h Mon Aug 02 11:02:18 2010 +0100
@@ -26,4 +26,15 @@ struct op_counter_config {
extern struct op_counter_config counter_config[];
+/* AMD IBS configuration */
+struct op_ibs_config {
+ unsigned long op_enabled;
+ unsigned long fetch_enabled;
+ unsigned long max_cnt_fetch;
+ unsigned long max_cnt_op;
+ unsigned long rand_en;
+ unsigned long dispatched_ops;
+};
+
+extern struct op_ibs_config ibs_config;
#endif /* OP_COUNTER_H */
diff -r 2893229a53a0 -r 042c8cd71081 arch/i386/oprofile/xenoprof.c
--- a/arch/i386/oprofile/xenoprof.c Mon Jul 26 10:40:00 2010 +0100
+++ b/arch/i386/oprofile/xenoprof.c Mon Aug 02 11:02:18 2010 +0100
@@ -27,6 +27,7 @@
#include "op_counter.h"
static unsigned int num_events = 0;
+static int ibs_caps = 0;
void __init xenoprof_arch_init_counter(struct xenoprof_init *init)
{
@@ -43,6 +44,7 @@ void xenoprof_arch_counter(void)
{
int i;
struct xenoprof_counter counter;
+ struct xenoprof_ibs_counter ibs_counter;
for (i=0; i<num_events; i++) {
counter.ind = i;
@@ -55,6 +57,17 @@ void xenoprof_arch_counter(void)
WARN_ON(HYPERVISOR_xenoprof_op(XENOPROF_counter,
&counter));
}
+
+ if (ibs_caps) {
+ ibs_counter.op_enabled = ibs_config.op_enabled;
+ ibs_counter.fetch_enabled = ibs_config.fetch_enabled;
+ ibs_counter.max_cnt_fetch = ibs_config.max_cnt_fetch;
+ ibs_counter.max_cnt_op = ibs_config.max_cnt_op;
+ ibs_counter.rand_en = ibs_config.rand_en;
+ ibs_counter.dispatched_ops = ibs_config.dispatched_ops;
+ WARN_ON(HYPERVISOR_xenoprof_op(XENOPROF_ibs_counter,
+ &ibs_counter));
+ }
}
void xenoprof_arch_start(void)
@@ -140,13 +153,16 @@ out:
}
struct op_counter_config counter_config[OP_MAX_COUNTER];
+struct op_ibs_config ibs_config;
+
+#define IBS_CAPS_OPCNT (1LL<<4)
int xenoprof_create_files(struct super_block * sb, struct dentry * root)
{
unsigned int i;
+ struct dentry * dir;
for (i = 0; i < num_events; ++i) {
- struct dentry * dir;
char buf[2];
snprintf(buf, 2, "%d", i);
@@ -165,6 +181,35 @@ int xenoprof_create_files(struct super_b
&counter_config[i].user);
}
+ /* AMD IBS support */
+ ibs_caps = HYPERVISOR_xenoprof_op(XENOPROF_get_ibs_caps, NULL);
+ if (!ibs_caps)
+ return 0;
+
+ /* setup some reasonable defaults */
+ ibs_config.max_cnt_fetch = 250000;
+ ibs_config.fetch_enabled = 0;
+ ibs_config.max_cnt_op = 250000;
+ ibs_config.op_enabled = 0;
+ ibs_config.dispatched_ops = 0;
+
+ dir = oprofilefs_mkdir(sb, root, "ibs_fetch");
+ oprofilefs_create_ulong(sb, dir, "enable",
+ &ibs_config.fetch_enabled);
+ oprofilefs_create_ulong(sb, dir, "max_count",
+ &ibs_config.max_cnt_fetch);
+ oprofilefs_create_ulong(sb, dir, "rand_enable",
+ &ibs_config.rand_en);
+
+ dir = oprofilefs_mkdir(sb, root, "ibs_op");
+ oprofilefs_create_ulong(sb, dir, "enable",
+ &ibs_config.op_enabled);
+ oprofilefs_create_ulong(sb, dir, "max_count",
+ &ibs_config.max_cnt_op);
+ if (ibs_caps & IBS_CAPS_OPCNT)
+ oprofilefs_create_ulong(sb, dir, "dispatched_ops",
+ &ibs_config.dispatched_ops);
+
return 0;
}
diff -r 2893229a53a0 -r 042c8cd71081 drivers/oprofile/buffer_sync.c
--- a/drivers/oprofile/buffer_sync.c Mon Jul 26 10:40:00 2010 +0100
+++ b/drivers/oprofile/buffer_sync.c Mon Aug 02 11:02:18 2010 +0100
@@ -498,6 +498,67 @@ static void mark_done(int cpu)
cpus_clear(marked_cpus);
}
+/* Add IBS samples into event buffer */
+#define IBS_FETCH_SIZE 8
+#define IBS_OP_SIZE 14
+
+static inline struct
+op_sample * get_next_slot(struct oprofile_cpu_buffer * cpu_buf, int next)
+{
+ int pos;
+ pos = cpu_buf->tail_pos + next;
+ if (pos >= cpu_buf->buffer_size)
+ pos = pos - cpu_buf->buffer_size;
+
+ return &cpu_buf->buffer[pos];
+}
+
+static int add_ibs_data(int cpu, struct mm_struct *mm, int cpu_mode)
+{
+ struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[cpu];
+ struct op_sample * s;
+
+ unsigned long cookie;
+ off_t offset;
+ int size, i, code;
+
+ s = get_next_slot(cpu_buf, 1);
+
+ if (s->eip == IBS_FETCH_CODE)
+ size = IBS_FETCH_SIZE;
+ else if (s->eip == IBS_OP_CODE)
+ size = IBS_OP_SIZE;
+ else
+ return 0;
+
+ code = s->eip;
+ s = get_next_slot(cpu_buf, 2);
+
+ if (mm)
+ {
+ cookie = lookup_dcookie(mm, s->eip, &offset);
+ if (cookie != last_cookie) {
+ add_cookie_switch(cookie);
+ last_cookie = cookie;
+ }
+ }
+ else {
+ offset=s->eip;
+ }
+ add_event_entry(ESCAPE_CODE);
+ add_event_entry(code);
+ add_event_entry(offset);
+
+ /* The first 3 slots are ESCAPE_CODE, code and offset,
+ so here we start from slot 4 */
+
+ for (i = 3; i <= size; ++i) {
+ s = get_next_slot(cpu_buf, i);
+ add_event_entry(s->eip);
+ }
+
+ return size;
+}
/* FIXME: this is not sufficient if we implement syscall barrier backtrace
* traversal, the code switch to sb_sample_start at first kernel enter/exit
@@ -527,6 +588,7 @@ void sync_buffer(int cpu)
sync_buffer_state state = sb_buffer_start;
unsigned long available;
int domain_switch = 0;
+ int is_ibs_sample = 0;
mutex_lock(&buffer_mutex);
@@ -568,12 +630,14 @@ void sync_buffer(int cpu)
cookie = get_exec_dcookie(mm);
add_user_ctx_switch(new, cookie);
}
+ is_ibs_sample = add_ibs_data(cpu, mm, cpu_mode);
+
} else {
if (domain_switch) {
cpu_current_domain[cpu] = s->eip;
add_domain_switch(s->eip);
domain_switch = 0;
- } else {
+ } else if (!is_ibs_sample) {
if (cpu_current_domain[cpu] !=
COORDINATOR_DOMAIN) {
add_sample_entry(s->eip, s->event);
diff -r 2893229a53a0 -r 042c8cd71081 drivers/oprofile/cpu_buffer.c
--- a/drivers/oprofile/cpu_buffer.c Mon Jul 26 10:40:00 2010 +0100
+++ b/drivers/oprofile/cpu_buffer.c Mon Aug 02 11:02:18 2010 +0100
@@ -201,7 +201,10 @@ static int log_sample(struct oprofile_cp
cpu_buf->last_task = task;
add_code(cpu_buf, (unsigned long)task);
}
-
+
+ if (pc == IBS_FETCH_CODE || pc == IBS_OP_CODE)
+ add_code(cpu_buf, cpu_mode);
+
add_sample(cpu_buf, pc, event);
return 1;
}
diff -r 2893229a53a0 -r 042c8cd71081 drivers/oprofile/event_buffer.h
--- a/drivers/oprofile/event_buffer.h Mon Jul 26 10:40:00 2010 +0100
+++ b/drivers/oprofile/event_buffer.h Mon Aug 02 11:02:18 2010 +0100
@@ -36,6 +36,8 @@ void wake_up_buffer_waiter(void);
#define TRACE_END_CODE 9
#define XEN_ENTER_SWITCH_CODE 10
#define DOMAIN_SWITCH_CODE 11
+#define IBS_FETCH_CODE 13
+#define IBS_OP_CODE 14
#define INVALID_COOKIE ~0UL
#define NO_COOKIE 0UL
diff -r 2893229a53a0 -r 042c8cd71081 drivers/oprofile/oprofile_files.c
--- a/drivers/oprofile/oprofile_files.c Mon Jul 26 10:40:00 2010 +0100
+++ b/drivers/oprofile/oprofile_files.c Mon Aug 02 11:02:18 2010 +0100
@@ -21,7 +21,7 @@
#include "oprof.h"
unsigned long fs_buffer_size = 131072;
-unsigned long fs_cpu_buffer_size = 8192;
+unsigned long fs_cpu_buffer_size = 131072;
unsigned long fs_buffer_watershed = 32768; /* FIXME: tune */
static ssize_t depth_read(struct file * file, char __user * buf, size_t count,
loff_t * offset)
diff -r 2893229a53a0 -r 042c8cd71081 include/xen/interface/xenoprof.h
--- a/include/xen/interface/xenoprof.h Mon Jul 26 10:40:00 2010 +0100
+++ b/include/xen/interface/xenoprof.h Mon Aug 02 11:02:18 2010 +0100
@@ -50,7 +50,11 @@
#define XENOPROF_shutdown 13
#define XENOPROF_get_buffer 14
#define XENOPROF_set_backtrace 15
-#define XENOPROF_last_op 15
+/* AMD IBS support */
+#define XENOPROF_get_ibs_caps 16
+#define XENOPROF_ibs_counter 17
+
+#define XENOPROF_last_op 17
#define MAX_OPROF_EVENTS 32
#define MAX_OPROF_DOMAINS 25
@@ -124,7 +128,16 @@ typedef struct xenoprof_passive {
} xenoprof_passive_t;
DEFINE_XEN_GUEST_HANDLE(xenoprof_passive_t);
-
+struct xenoprof_ibs_counter {
+ uint64_t op_enabled;
+ uint64_t fetch_enabled;
+ uint64_t max_cnt_fetch;
+ uint64_t max_cnt_op;
+ uint64_t rand_en;
+ uint64_t dispatched_ops;
+};
+typedef struct xenoprof_ibs_counter xenoprof_ibs_counter_t;
+DEFINE_XEN_GUEST_HANDLE(xenoprof_ibs_counter_t);
#endif /* __XEN_PUBLIC_XENOPROF_H__ */
/*
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|