From: Keir Fraser Date: Mon, 2 Aug 2010 10:02:18 +0000 (+0100) Subject: xenoprofile: Add IBS support X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=e45b817be52b1cbd05d4004db66b234a397605b8;p=legacy%2Flinux-2.6.18-xen.git 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 --- diff --git a/arch/i386/oprofile/op_counter.h b/arch/i386/oprofile/op_counter.h index 2880b15c..11e9c008 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 cb6ae1e3..73418866 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 58a9c18b..7c6deb5b 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 6a887886..270868b9 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 67194204..bd3afc05 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/include/xen/interface/xenoprof.h b/include/xen/interface/xenoprof.h index 183078d8..451b8677 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__ */ /*