diff options
Diffstat (limited to 'libop')
-rw-r--r-- | libop/op_cpu_type.c | 11 | ||||
-rw-r--r-- | libop/op_cpu_type.h | 7 | ||||
-rw-r--r-- | libop/op_events.c | 8 | ||||
-rw-r--r-- | libop/op_hw_specific.h | 15 | ||||
-rw-r--r-- | libop/op_xml_events.c | 69 | ||||
-rw-r--r-- | libop/op_xml_out.c | 198 | ||||
-rw-r--r-- | libop/op_xml_out.h | 11 |
7 files changed, 184 insertions, 135 deletions
diff --git a/libop/op_cpu_type.c b/libop/op_cpu_type.c index e168b43..4633fd1 100644 --- a/libop/op_cpu_type.c +++ b/libop/op_cpu_type.c @@ -51,7 +51,7 @@ static struct cpu_descr const cpu_descrs[MAX_CPU_TYPE] = { { "MIPS 20K", "mips/20K", CPU_MIPS_20K, 1}, { "MIPS 24K", "mips/24K", CPU_MIPS_24K, 2}, { "MIPS 25K", "mips/25K", CPU_MIPS_25K, 2}, - { "MIPS 34K", "mips/34K", CPU_MIPS_34K, 4}, + { "MIPS 34K", "mips/34K", CPU_MIPS_34K, 2}, { "MIPS 5K", "mips/5K", CPU_MIPS_5K, 2}, { "MIPS R10000", "mips/r10000", CPU_MIPS_R10000, 2 }, { "MIPS R12000", "mips/r12000", CPU_MIPS_R12000, 4 }, @@ -70,18 +70,23 @@ static struct cpu_descr const cpu_descrs[MAX_CPU_TYPE] = { { "ppc64 Cell Broadband Engine", "ppc64/cell-be", CPU_PPC64_CELL, 8 }, { "AMD64 family10", "x86-64/family10", CPU_FAMILY10, 4 }, { "ppc64 PA6T", "ppc64/pa6t", CPU_PPC64_PA6T, 6 }, - { "ARM MPCore", "arm/mpcore", CPU_ARM_MPCORE, 2 }, + { "ARM 11MPCore", "arm/mpcore", CPU_ARM_MPCORE, 2 }, { "ARM V6 PMU", "arm/armv6", CPU_ARM_V6, 3 }, { "ppc64 POWER5++", "ppc64/power5++", CPU_PPC64_POWER5pp, 6 }, { "e300", "ppc/e300", CPU_PPC_E300, 4 }, { "AVR32", "avr32", CPU_AVR32, 3 }, - { "ARM V7 PMNC", "arm/armv7", CPU_ARM_V7, 5 }, + { "ARM Cortex-A8", "arm/armv7", CPU_ARM_V7, 5 }, { "Intel Architectural Perfmon", "i386/arch_perfmon", CPU_ARCH_PERFMON, 0}, { "AMD64 family11h", "x86-64/family11h", CPU_FAMILY11H, 4 }, { "ppc64 POWER7", "ppc64/power7", CPU_PPC64_POWER7, 6 }, { "ppc64 compat version 1", "ppc64/ibm-compat-v1", CPU_PPC64_IBM_COMPAT_V1, 4 }, { "Intel Core/i7", "i386/core_i7", CPU_CORE_I7, 4 }, { "Intel Atom", "i386/atom", CPU_ATOM, 2 }, + { "Loongson2", "mips/loongson2", CPU_MIPS_LOONGSON2, 2 }, + { "Intel Nehalem microarchitecture", "i386/nehalem", CPU_NEHALEM, 4 }, + { "ARM Cortex-A9", "arm/armv7-ca9", CPU_ARM_V7_CA9, 7 }, + { "MIPS 74K", "mips/74K", CPU_MIPS_74K, 4}, + { "MIPS 1004K", "mips/1004K", CPU_MIPS_1004K, 2}, }; static size_t const nr_cpu_descrs = sizeof(cpu_descrs) / sizeof(struct cpu_descr); diff --git a/libop/op_cpu_type.h b/libop/op_cpu_type.h index 133a4f8..990e213 100644 --- a/libop/op_cpu_type.h +++ b/libop/op_cpu_type.h @@ -72,13 +72,18 @@ typedef enum { CPU_PPC64_POWER5pp, /**< ppc64 Power5++ family */ CPU_PPC_E300, /**< e300 */ CPU_AVR32, /**< AVR32 */ - CPU_ARM_V7, /**< ARM V7 */ + CPU_ARM_V7, /**< ARM Cortex-A8 */ CPU_ARCH_PERFMON, /**< Intel architectural perfmon */ CPU_FAMILY11H, /**< AMD family 11h */ CPU_PPC64_POWER7, /**< ppc64 POWER7 family */ CPU_PPC64_IBM_COMPAT_V1, /**< IBM PPC64 processor compat mode version 1 */ CPU_CORE_I7, /* Intel Core i7, Nehalem */ CPU_ATOM, /* First generation Intel Atom */ + CPU_MIPS_LOONGSON2, /* < loongson2 family */ + CPU_NEHALEM, /* Intel Nehalem microarchitecture */ + CPU_ARM_V7_CA9, /**< ARM Cortex-A9 */ + CPU_MIPS_74K, /**< MIPS 74K */ + CPU_MIPS_1004K, /**< MIPS 1004K */ MAX_CPU_TYPE } op_cpu; diff --git a/libop/op_events.c b/libop/op_events.c index ad95d86..c3fcf57 100644 --- a/libop/op_events.c +++ b/libop/op_events.c @@ -970,6 +970,8 @@ void op_default_event(op_cpu cpu_type, struct op_default_event_descr * descr) case CPU_FAMILY11H: case CPU_ATOM: case CPU_CORE_I7: + case CPU_NEHALEM: + case CPU_MIPS_LOONGSON2: descr->name = "CPU_CLK_UNHALTED"; break; @@ -1005,6 +1007,7 @@ void op_default_event(op_cpu cpu_type, struct op_default_event_descr * descr) case CPU_ARM_MPCORE: case CPU_ARM_V6: case CPU_ARM_V7: + case CPU_ARM_V7_CA9: case CPU_AVR32: descr->name = "CPU_CYCLES"; break; @@ -1029,10 +1032,9 @@ void op_default_event(op_cpu cpu_type, struct op_default_event_descr * descr) break; case CPU_MIPS_24K: - descr->name = "INSTRUCTIONS"; - break; - case CPU_MIPS_34K: + case CPU_MIPS_74K: + case CPU_MIPS_1004K: descr->name = "INSTRUCTIONS"; break; diff --git a/libop/op_hw_specific.h b/libop/op_hw_specific.h index b1e3b4c..35080ad 100644 --- a/libop/op_hw_specific.h +++ b/libop/op_hw_specific.h @@ -20,8 +20,7 @@ static inline int cpuid_vendor(char *vnd) char v[12]; } v; unsigned eax; - asm volatile( "pushl %%ebx; cpuid; movl %%ebx, %1; popl %%ebx" - : "=a" (eax), "=S" (v.b), "=c" (v.c), "=d" (v.d) : "0" (0)); + asm("cpuid" : "=a" (eax), "=b" (v.b), "=c" (v.c), "=d" (v.d) : "0" (0)); return !strncmp(v.v, vnd, 12); } @@ -47,8 +46,7 @@ static inline void workaround_nehalem_aaj79(unsigned *ebx) if (!cpuid_vendor("GenuineIntel")) return; - asm volatile( "pushl %%ebx; cpuid; movl %%ebx, %1; popl %%ebx" - : "=a" (v.eax) : "0" (1) : "ecx","edx"); + asm("cpuid" : "=a" (v.eax) : "0" (1) : "ecx","ebx","edx"); model = (v.ext_model << 4) + v.model; if (v.family != 6 || model != 26 || v.stepping > 4) return; @@ -59,8 +57,7 @@ static inline unsigned arch_get_filter(op_cpu cpu_type) { if (cpu_type == CPU_ARCH_PERFMON) { unsigned ebx, eax; - asm volatile( "pushl %%ebx; cpuid; movl %%ebx, %1; popl %%ebx" - : "=a" (eax), "=S" (ebx) : "0" (0xa) : "ecx","edx"); + asm("cpuid" : "=a" (eax), "=b" (ebx) : "0" (0xa) : "ecx","edx"); workaround_nehalem_aaj79(&ebx); return ebx & num_to_mask(eax >> 24); } @@ -71,8 +68,7 @@ static inline int arch_num_counters(op_cpu cpu_type) { if (cpu_type == CPU_ARCH_PERFMON) { unsigned v; - asm volatile( "pushl %%ebx; cpuid; movl %%eax, %1; popl %%ebx" - : "=a" (v) : "0" (0xa) : "ecx","edx"); + asm("cpuid" : "=a" (v) : "0" (0xa) : "ebx","ecx","edx"); return (v >> 8) & 0xff; } return -1; @@ -81,8 +77,7 @@ static inline int arch_num_counters(op_cpu cpu_type) static inline unsigned arch_get_counter_mask(void) { unsigned v; - asm volatile( "pushl %%ebx; cpuid; movl %%ebx, %1; popl %%ebx" - : "=a" (v) : "0" (0xa) : "ecx","edx"); + asm("cpuid" : "=a" (v) : "0" (0xa) : "ebx","ecx","edx"); return num_to_mask((v >> 8) & 0xff); } diff --git a/libop/op_xml_events.c b/libop/op_xml_events.c index 5b9ac7d..67fc0a5 100644 --- a/libop/op_xml_events.c +++ b/libop/op_xml_events.c @@ -16,38 +16,38 @@ #include "op_xml_out.h" static op_cpu cpu_type; -#define MAX_BUFFER 4096 +#define MAX_BUFFER 16384 +static char buffer[MAX_BUFFER]; + void open_xml_events(char const * title, char const * doc, op_cpu the_cpu_type) { char const * schema_version = "1.0"; - char buffer[MAX_BUFFER]; buffer[0] = '\0'; cpu_type = the_cpu_type; - open_xml_element(HELP_EVENTS, 0, buffer); - open_xml_element(HELP_HEADER, 1, buffer); - init_xml_str_attr(HELP_TITLE, title, buffer); - init_xml_str_attr(SCHEMA_VERSION, schema_version, buffer); - init_xml_str_attr(HELP_DOC, doc, buffer); - close_xml_element(NONE, 0, buffer); + open_xml_element(HELP_EVENTS, 0, buffer, MAX_BUFFER); + open_xml_element(HELP_HEADER, 1, buffer, MAX_BUFFER); + init_xml_str_attr(HELP_TITLE, title, buffer, MAX_BUFFER); + init_xml_str_attr(SCHEMA_VERSION, schema_version, buffer, MAX_BUFFER); + init_xml_str_attr(HELP_DOC, doc, buffer, MAX_BUFFER); + close_xml_element(NONE, 0, buffer, MAX_BUFFER); printf("%s", buffer); } void close_xml_events(void) { - char buffer[MAX_BUFFER]; - buffer[0] = '\0'; - close_xml_element(HELP_EVENTS, 0, buffer); + close_xml_element(HELP_EVENTS, 0, buffer, MAX_BUFFER); printf("%s", buffer); } -static void xml_do_arch_specific_event_help(struct op_event const * event, - char * buffer) +static void xml_do_arch_specific_event_help(struct op_event const *event, + char *buffer, size_t size) { switch (cpu_type) { case CPU_PPC64_CELL: - init_xml_int_attr(HELP_EVENT_GROUP, event->val / 100, buffer); + init_xml_int_attr(HELP_EVENT_GROUP, event->val / 100, buffer, + size); break; default: break; @@ -60,34 +60,41 @@ void xml_help_for_event(struct op_event const * event) uint i; int nr_counters; int has_nested = strcmp(event->unit->name, "zero"); - char buffer[MAX_BUFFER]; buffer[0] = '\0'; - open_xml_element(HELP_EVENT, 1, buffer); - init_xml_str_attr(HELP_EVENT_NAME, event->name, buffer); - xml_do_arch_specific_event_help(event, buffer); - init_xml_str_attr(HELP_EVENT_DESC, event->desc, buffer); + open_xml_element(HELP_EVENT, 1, buffer, MAX_BUFFER); + init_xml_str_attr(HELP_EVENT_NAME, event->name, buffer, MAX_BUFFER); + xml_do_arch_specific_event_help(event, buffer, MAX_BUFFER); + init_xml_str_attr(HELP_EVENT_DESC, event->desc, buffer, MAX_BUFFER); nr_counters = op_get_nr_counters(cpu_type); - init_xml_int_attr(HELP_COUNTER_MASK, event->counter_mask, buffer); - init_xml_int_attr(HELP_MIN_COUNT, event->min_count, buffer); + init_xml_int_attr(HELP_COUNTER_MASK, event->counter_mask, buffer, + MAX_BUFFER); + if (event->ext) + init_xml_str_attr(HELP_EXT, event->ext, buffer, MAX_BUFFER); + init_xml_int_attr(HELP_MIN_COUNT, event->min_count, + buffer, MAX_BUFFER); if (has_nested) { - close_xml_element(NONE, 1, buffer); - open_xml_element(HELP_UNIT_MASKS, 1, buffer); - init_xml_int_attr(HELP_DEFAULT_MASK, event->unit->default_mask, buffer); - close_xml_element(NONE, 1, buffer); + close_xml_element(NONE, 1, buffer, MAX_BUFFER); + open_xml_element(HELP_UNIT_MASKS, 1, buffer, MAX_BUFFER); + init_xml_int_attr(HELP_DEFAULT_MASK, event->unit->default_mask, + buffer, MAX_BUFFER); + close_xml_element(NONE, 1, buffer, MAX_BUFFER); for (i = 0; i < event->unit->num; i++) { - open_xml_element(HELP_UNIT_MASK, 1, buffer); + open_xml_element(HELP_UNIT_MASK, 1, buffer, MAX_BUFFER); init_xml_int_attr(HELP_UNIT_MASK_VALUE, - event->unit->um[i].value, buffer); + event->unit->um[i].value, + buffer, MAX_BUFFER); init_xml_str_attr(HELP_UNIT_MASK_DESC, - event->unit->um[i].desc, buffer); - close_xml_element(NONE, 0, buffer); + event->unit->um[i].desc, + buffer, MAX_BUFFER); + close_xml_element(NONE, 0, buffer, MAX_BUFFER); } - close_xml_element(HELP_UNIT_MASKS, 0, buffer); + close_xml_element(HELP_UNIT_MASKS, 0, buffer, MAX_BUFFER); } - close_xml_element(has_nested ? HELP_EVENT : NONE, has_nested, buffer); + close_xml_element(has_nested ? HELP_EVENT : NONE, has_nested, + buffer, MAX_BUFFER); printf("%s", buffer); } diff --git a/libop/op_xml_out.c b/libop/op_xml_out.c index d779c45..b12919e 100644 --- a/libop/op_xml_out.c +++ b/libop/op_xml_out.c @@ -77,6 +77,7 @@ char const * xml_tag_map[] = { "desc", "counter_mask", "min_count", + "ext", "unit_masks", "default", "unit_mask", @@ -91,143 +92,176 @@ char const * xml_tag_name(tag_t tag) } -void open_xml_element(tag_t tag, int with_attrs, char * buffer) +void open_xml_element(tag_t tag, int with_attrs, char *buffer, size_t max) { - char const * tag_name = xml_tag_name(tag); - unsigned int const max_len = strlen(tag_name) + 3; - char tmp_buf[MAX_BUF_LEN]; + char *buf; + int size, ret; - if (max_len >= sizeof(tmp_buf)) - fprintf(stderr,"Warning: open_xml_element: buffer overflow %d\n", max_len); + buffer[max - 1] = '\0'; + size = strlen(buffer); + buf = &buffer[size]; + size = max - 1 - size; - if (snprintf(tmp_buf, sizeof(tmp_buf), "<%s%s", tag_name, - (with_attrs ? " " : ">\n")) < 0) { + ret = snprintf(buf, size, "<%s%s", xml_tag_name(tag), + (with_attrs ? " " : ">\n")); + + if (ret < 0 || ret >= size) { fprintf(stderr,"open_xml_element: snprintf failed\n"); exit(EXIT_FAILURE); } - strncat(buffer, tmp_buf, sizeof(tmp_buf)); } -void close_xml_element(tag_t tag, int has_nested, char * buffer) +void close_xml_element(tag_t tag, int has_nested, char *buffer, size_t max) { - char const * tag_name = xml_tag_name(tag); - unsigned int const max_len = strlen(tag_name) + 3; - char tmp_buf[MAX_BUF_LEN]; + char *buf; + int size, ret; - if (max_len >= sizeof(tmp_buf)) - fprintf(stderr,"Warning: close_xml_element: buffer overflow %d\n", max_len); + buffer[max - 1] = '\0'; + size = strlen(buffer); + buf = &buffer[size]; + size = max - 1 - size; - if (tag == NONE) { - if (snprintf(tmp_buf, sizeof(tmp_buf), "%s\n", (has_nested ? ">" : "/>")) < 0) { - fprintf(stderr, "close_xml_element: snprintf failed\n"); - exit(EXIT_FAILURE); - } - } else { - if (snprintf(tmp_buf, sizeof(tmp_buf), "</%s>\n", tag_name) < 0) { - fprintf(stderr, "close_xml_element: snprintf failed\n"); - exit(EXIT_FAILURE); - } + if (tag == NONE) + ret = snprintf(buf, size, "%s\n", (has_nested ? ">" : "/>")); + else + ret = snprintf(buf, size, "</%s>\n", xml_tag_name(tag)); + + if (ret < 0 || ret >= size) { + fprintf(stderr, "close_xml_element: snprintf failed\n"); + exit(EXIT_FAILURE); } - strncat(buffer, tmp_buf, sizeof(tmp_buf)); } -void init_xml_int_attr(tag_t attr, int value, char * buffer) +void init_xml_int_attr(tag_t attr, int value, char *buffer, size_t max) { - char const * attr_name = xml_tag_name(attr); - char tmp_buf[MAX_BUF_LEN]; - unsigned int const max_len = strlen(attr_name) + 50; + char *buf; + int size, ret; - if (max_len >= sizeof(tmp_buf)) { - fprintf(stderr, - "Warning: init_xml_int_attr: buffer overflow %d\n", max_len); - } + buffer[max - 1] = '\0'; + size = strlen(buffer); + buf = &buffer[size]; + size = max - 1 - size; + ret = snprintf(buf, size, " %s=\"%d\"", xml_tag_name(attr), value); - if (snprintf(tmp_buf, sizeof(tmp_buf), " %s=\"%d\"", attr_name, value) < 0) { + if (ret < 0 || ret >= size) { fprintf(stderr,"init_xml_int_attr: snprintf failed\n"); exit(EXIT_FAILURE); } - strncat(buffer, tmp_buf, sizeof(tmp_buf)); } -void init_xml_dbl_attr(tag_t attr, double value, char * buffer) +void init_xml_dbl_attr(tag_t attr, double value, char *buffer, size_t max) { - char const * attr_name = xml_tag_name(attr); - unsigned int const max_len = strlen(attr_name) + 50; - char tmp_buf[MAX_BUF_LEN]; + char *buf; + int size, ret; + + buffer[max - 1] = '\0'; + size = strlen(buffer); + buf = &buffer[size]; + size = max - 1 - size; - if (max_len >= sizeof(tmp_buf)) - fprintf(stderr, "Warning: init_xml_dbl_attr: buffer overflow %d\n", max_len); + ret = snprintf(buf, size, " %s=\"%.2f\"", xml_tag_name(attr), value); - if (snprintf(tmp_buf, sizeof(tmp_buf), " %s=\"%.2f\"", attr_name, value) < 0) { + if (ret < 0 || ret >= size) { fprintf(stderr, "init_xml_dbl_attr: snprintf failed\n"); exit(EXIT_FAILURE); } - strncat(buffer, tmp_buf, sizeof(tmp_buf)); } -static char * xml_quote(char const * str, char * quote_buf) +static void xml_quote(char const *str, char *buffer, size_t max) { - int i; - int pos = 0; - int len = strlen(str); + char *buf; + char *quote; + char *pos = (char*)str; + size_t size; + int ret; - - quote_buf[pos++] = '"'; + buffer[max - 1] = '\0'; + size = strlen(buffer); + buf = &buffer[size]; + size = max - 1 - size; - for (i = 0; i < len; i++) { - if (pos >= MAX_BUF_LEN - 10) { - fprintf(stderr,"quote_str: buffer overflow %d\n", pos); - exit(EXIT_FAILURE); - } + if (size < strlen(pos) + 2) + goto Error; - switch(str[i]) { + *buf = '"'; + buf++; + size--; + + while (*pos) { + switch(*pos) { case '&': - strncpy(quote_buf + pos, "&", 5); - pos += 5; + quote = "&"; break; case '<': - strncpy(quote_buf + pos, "<", 4); - pos += 4; + quote = "<"; break; case '>': - strncpy(quote_buf + pos, ">", 4); - pos += 4; + quote = ">"; break; case '"': - strncpy(quote_buf + pos, """, 6); - pos += 6; + quote = """; break; default: - quote_buf[pos++] = str[i]; - break; + *buf = *pos; + pos++; + buf++; + size--; + continue; } + + pos++; + ret = snprintf(buf, size, "%s", quote); + if (ret < 0 || ret >= (int)size) + goto Error; + buf += ret; + size -= ret; + if (size < strlen(pos)) + goto Error; } - quote_buf[pos++] = '"'; - quote_buf[pos++] = '\0'; - return quote_buf; + if (!size) + goto Error; + + *buf = '"'; + buf++; + *buf = '\0'; + + return; + +Error: + fprintf(stderr,"quote_str: buffer overflow\n"); + exit(EXIT_FAILURE); } -void init_xml_str_attr(tag_t attr, char const * str, char * buffer) +void init_xml_str_attr(tag_t attr, char const *str, char *buffer, size_t max) { - char tmp_buf[MAX_BUF_LEN]; - char quote_buf[MAX_BUF_LEN]; - char const * attr_name = xml_tag_name(attr); - char const * quote_str = xml_quote(str, quote_buf); - const unsigned int max_len = strlen(attr_name) + strlen(quote_str) + 10; + char *buf; + int size, ret; - if (max_len >= sizeof(tmp_buf)) - fprintf(stderr, "Warning: init_xml_str_attr: buffer overflow %d\n", max_len); + buffer[max - 1] = '\0'; + size = strlen(buffer); + buf = &buffer[size]; + size = max - 1 - size; - if (snprintf(tmp_buf, sizeof(tmp_buf), " %s=""%s""", attr_name, quote_str) < 0) { - fprintf(stderr,"init_xml_str_attr: snprintf failed\n"); - exit(EXIT_FAILURE); - } - strncat(buffer, tmp_buf, sizeof(tmp_buf)); + ret = snprintf(buf, size, " %s=", xml_tag_name(attr)); + if (ret < 0 || ret >= size) + goto Error; + + buf += ret; + size -= ret; + + if (!size) + goto Error; + + xml_quote(str, buf, size); + return; +Error: + fprintf(stderr,"init_xml_str_attr: snprintf failed\n"); + exit(EXIT_FAILURE); } diff --git a/libop/op_xml_out.h b/libop/op_xml_out.h index 52e8d8f..b0188b2 100644 --- a/libop/op_xml_out.h +++ b/libop/op_xml_out.h @@ -51,6 +51,7 @@ typedef enum { HELP_EVENT_DESC, HELP_COUNTER_MASK, HELP_MIN_COUNT, + HELP_EXT, HELP_UNIT_MASKS, HELP_DEFAULT_MASK, HELP_UNIT_MASK, @@ -59,11 +60,11 @@ typedef enum { } tag_t; char const * xml_tag_name(tag_t tag); -void open_xml_element(tag_t tag, int with_attrs, char * result); -void close_xml_element(tag_t tag, int has_nested, char * result); -void init_xml_int_attr(tag_t attr, int value, char * result); -void init_xml_dbl_attr(tag_t attr, double value, char * result); -void init_xml_str_attr(tag_t attr, char const * str, char * result); +void open_xml_element(tag_t tag, int with_attrs, char *buffer, size_t size); +void close_xml_element(tag_t tag, int has_nested, char *buffer, size_t size); +void init_xml_int_attr(tag_t attr, int value, char *buffer, size_t size); +void init_xml_dbl_attr(tag_t attr, double value, char *buffer, size_t size); +void init_xml_str_attr(tag_t attr, char const *str, char *buffer, size_t size); #ifdef __cplusplus } |