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 */
#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)
{
{
int i;
struct xenoprof_counter counter;
+ struct xenoprof_ibs_counter ibs_counter;
for (i=0; i<num_events; i++) {
counter.ind = i;
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)
}
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);
&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;
}
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
sync_buffer_state state = sb_buffer_start;
unsigned long available;
int domain_switch = 0;
+ int is_ibs_sample = 0;
mutex_lock(&buffer_mutex);
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);
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;
}
#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
#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)
#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
} 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__ */
/*