[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [linux-2.6.18-xen] xenoprofile: Add IBS support



# 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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.