diff --git a/arch/i386/oprofile/op_counter.h b/arch/i386/oprofile/op_counter.h index 2880b15..11e9c00 100644 --- a/arch/i386/oprofile/op_counter.h +++ b/arch/i386/oprofile/op_counter.h @@ -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 --git a/arch/i386/oprofile/xenoprof.c b/arch/i386/oprofile/xenoprof.c index cb6ae1e..7341886 100644 --- a/arch/i386/oprofile/xenoprof.c +++ b/arch/i386/oprofile/xenoprof.c @@ -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; itail_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 --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index 58a9c18..7c6deb5 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -201,7 +201,10 @@ static int log_sample(struct oprofile_cpu_buffer * cpu_buf, unsigned long pc, 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 --git a/drivers/oprofile/event_buffer.h b/drivers/oprofile/event_buffer.h index 6a88788..270868b 100644 --- a/drivers/oprofile/event_buffer.h +++ b/drivers/oprofile/event_buffer.h @@ -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 --git a/drivers/oprofile/oprofile_files.c b/drivers/oprofile/oprofile_files.c index 6719420..bd3afc0 100644 --- a/drivers/oprofile/oprofile_files.c +++ b/drivers/oprofile/oprofile_files.c @@ -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 --git a/drivers/xen/xenoprof/xenoprofile.c b/drivers/xen/xenoprof/xenoprofile.c diff --git a/include/xen/interface/xenoprof.h b/include/xen/interface/xenoprof.h index 183078d..451b867 100644 --- a/include/xen/interface/xenoprof.h +++ b/include/xen/interface/xenoprof.h @@ -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__ */ /*