From: Andi K. <an...@fi...> - 2011-04-08 21:26:52
|
From: Andi Kleen <ak...@li...> The reference files from which the Intel event lists are generated from have various events that use the CMASK, INV or EDGE flags for the performance counters. This often allows to have a "more natural" counter versus a raw counter. This patch adds the infrastructure to add extra flags for a unit mask event. There is a new extra:... field in the unit mask declaration that declares them. Then a patched kernel can set these extra fields using a new file in oprofilefs. I'm submitting the small kernel patch needed for that separately. This patch adds the infrastructure needed to declare these extra flags, and also adds some of them to the Sandy Bridge events files. v2: Fixed review feedback Signed-off-by: Andi Kleen <ak...@li...> --- libop/op_events.c | 38 +++++++++++++++++++++++++++++++++ libop/op_events.h | 6 +++++ libop/op_xml_events.c | 4 +++ libop/op_xml_out.c | 3 +- libop/op_xml_out.h | 3 +- utils/opcontrol | 14 ++++++++++++ utils/ophelp.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++- 7 files changed, 121 insertions(+), 3 deletions(-) diff --git a/libop/op_events.c b/libop/op_events.c index 30c3207..8da023b 100644 --- a/libop/op_events.c +++ b/libop/op_events.c @@ -21,6 +21,7 @@ #include <string.h> #include <stdlib.h> #include <stdio.h> +#include <ctype.h> static LIST_HEAD(events_list); static LIST_HEAD(um_list); @@ -106,6 +107,34 @@ static void include_um(const char *start, const char *end) free(s); } +/* extra:cmask=12,inv,edge */ +unsigned parse_extra(const char *s) +{ + unsigned v, w; + int o; + + v = 0; + while (*s) { + if (isspace(*s)) + break; + if (strisprefix(s, "edge")) { + v |= EXTRA_EDGE; + s += 4; + } else if (strisprefix(s, "inv")) { + v |= EXTRA_INV; + s += 3; + } else if (sscanf(s, "cmask=%x%n", &w, &o) >= 1) { + v |= (w & EXTRA_CMASK_MASK) << EXTRA_CMASK_SHIFT; + s += o; + } else { + parse_error("Illegal extra field modifier"); + } + if (*s == ',') + ++s; + } + return v; +} + /* name:MESI type:bitmask default:0x0f */ static void parse_um(struct op_unit_mask * um, char const * line) { @@ -178,6 +207,7 @@ static void parse_um(struct op_unit_mask * um, char const * line) /* \t0x08 (M)odified cache state */ +/* \t0x08 extra:inv,cmask=... (M)odified cache state */ static void parse_um_entry(struct op_described_um * entry, char const * line) { char const * c = line; @@ -186,6 +216,14 @@ static void parse_um_entry(struct op_described_um * entry, char const * line) entry->value = parse_hex(c); c = skip_nonws(c); + c = skip_ws(c); + if (strisprefix(c, "extra:")) { + c += 6; + entry->extra = parse_extra(c); + c = skip_nonws(c); + } else + entry->extra = 0; + if (!*c) parse_error("invalid unit mask entry"); diff --git a/libop/op_events.h b/libop/op_events.h index 9ffdc49..3aaaba2 100644 --- a/libop/op_events.h +++ b/libop/op_events.h @@ -20,6 +20,11 @@ extern "C" { #include "op_types.h" #include "op_list.h" +#define EXTRA_EDGE (1U << 18) +#define EXTRA_INV (1U << 23) +#define EXTRA_CMASK_SHIFT 24 +#define EXTRA_CMASK_MASK 0xff + /** Describe an unit mask type. Events can optionally use a filter called * the unit mask. the mask type can be a bitmask or a discrete value */ enum unit_mask_type { @@ -39,6 +44,7 @@ struct op_unit_mask { enum unit_mask_type unit_type_mask; u32 default_mask; /**< only the gui use it */ struct op_described_um { + u32 extra; u32 value; char * desc; } um[MAX_UNIT_MASK]; diff --git a/libop/op_xml_events.c b/libop/op_xml_events.c index 1fcb01e..f573e02 100644 --- a/libop/op_xml_events.c +++ b/libop/op_xml_events.c @@ -103,6 +103,10 @@ void xml_help_for_event(struct op_event const * event) init_xml_str_attr(HELP_UNIT_MASK_DESC, event->unit->um[i].desc, buffer, MAX_BUFFER); + if (event->unit->um[i].extra) + init_xml_int_attr(HELP_UNIT_EXTRA_VALUE, + event->unit->um[i].extra, + buffer, MAX_BUFFER); close_xml_element(NONE, 0, buffer, MAX_BUFFER); } close_xml_element(HELP_UNIT_MASKS, 0, buffer, MAX_BUFFER); diff --git a/libop/op_xml_out.c b/libop/op_xml_out.c index f6d9042..0b3deea 100644 --- a/libop/op_xml_out.c +++ b/libop/op_xml_out.c @@ -83,7 +83,8 @@ char const * xml_tag_map[] = { "category", "unit_mask", "mask", - "desc" + "desc", + "extra" }; #define MAX_BUF_LEN 2048 diff --git a/libop/op_xml_out.h b/libop/op_xml_out.h index 4fb06df..544bd51 100644 --- a/libop/op_xml_out.h +++ b/libop/op_xml_out.h @@ -57,7 +57,8 @@ typedef enum { HELP_UNIT_MASKS_CATEGORY, HELP_UNIT_MASK, HELP_UNIT_MASK_VALUE, - HELP_UNIT_MASK_DESC + HELP_UNIT_MASK_DESC, + HELP_UNIT_EXTRA_VALUE, } tag_t; char const * xml_tag_name(tag_t tag); diff --git a/utils/opcontrol b/utils/opcontrol index 3a8a814..603172d 100644 --- a/utils/opcontrol +++ b/utils/opcontrol @@ -1353,6 +1353,10 @@ do_param_setup() set_ctr_param $f enabled 0 set_ctr_param $f event 0 set_ctr_param $f count 0 + + if test -d $MOUNT/$f/extra ; then + set_ctr_param $f extra 0 + fi done # Check if driver has IBS support @@ -1437,6 +1441,16 @@ do_param_setup() set_ctr_param $CTR kernel $KERNEL set_ctr_param $CTR user $USER set_ctr_param $CTR unit_mask $UNIT_MASK + + EXTRA=`$OPHELP --extra-mask $GOTEVENT` + if test "$EXTRA" -ne 0 ; then + if ! test -d $MOUNT/$CTR/extra ; then + echo >&2 "Warning: $GOTEVENT has extra mask, but kernel does not support extra field" + echo >&2 "Please update your kernel or use a different event. Will miscount." + else + set_ctr_param $CTR extra $EXTRA + fi + fi fi OPROFILED_EVENTS=${OPROFILED_EVENTS}$EVENT:$EVENT_VAL: OPROFILED_EVENTS=${OPROFILED_EVENTS}$CTR:$COUNT:$UNIT_MASK: diff --git a/utils/ophelp.c b/utils/ophelp.c index ce8bace..60b1662 100644 --- a/utils/ophelp.c +++ b/utils/ophelp.c @@ -143,6 +143,21 @@ static void help_for_event(struct op_event * event) event->unit->um[j].value); column = 14; word_wrap(14, &column, event->unit->um[j].desc); + if (event->unit->um[j].extra) { + u32 extra = event->unit->um[j].extra; + + word_wrap(14, &column, "(extra:"); + if (extra & EXTRA_EDGE) + word_wrap(14, &column, "edge"); + if (extra & EXTRA_INV) + word_wrap(14, &column, "inv"); + if ((extra >> EXTRA_CMASK_SHIFT) & EXTRA_CMASK_MASK) { + snprintf(buf, sizeof buf, "cmask=%x", + (extra >> EXTRA_CMASK_SHIFT) & EXTRA_CMASK_MASK); + word_wrap(14, &column, buf); + } + word_wrap(14, &column, ")"); + } putchar('\n'); } } @@ -274,6 +289,37 @@ static void show_unit_mask(void) printf("%d\n", event->unit->default_mask); } +static void show_extra_mask(void) +{ + unsigned i; + struct op_event * event; + size_t count; + unsigned extra; + + count = parse_events(parsed_events, num_chosen_events, chosen_events); + if (count > 1) { + fprintf(stderr, "More than one event specified.\n"); + exit(EXIT_FAILURE); + } + + event = find_event_by_name(parsed_events[0].name, + parsed_events[0].unit_mask, + 1); + if (!event) { + fprintf(stderr, "No such event found.\n"); + exit(EXIT_FAILURE); + } + + /* Not exact match is nothing */ + extra = 0; + for (i = 0; i < event->unit->num; i++) + if (event->unit->um[i].value == (unsigned)parsed_events[0].unit_mask) { + extra = event->unit->um[i].extra; + break; + } + + printf ("%d\n", extra); +} static void show_default_event(void) { @@ -293,6 +339,7 @@ static int get_cpu_type; static int check_events; static int unit_mask; static int get_default_event; +static int extra_mask; static struct poptOption options[] = { { "cpu-type", 'c', POPT_ARG_STRING, &cpu_string, 0, @@ -311,6 +358,8 @@ static struct poptOption options[] = { "show version", NULL, }, { "xml", 'X', POPT_ARG_NONE, &want_xml, 0, "list events as XML", NULL, }, + { "extra-mask", 'E', POPT_ARG_NONE, &extra_mask, 0, + "print extra mask for event", NULL, }, POPT_AUTOHELP { NULL, 0, 0, NULL, 0, NULL, NULL, }, }; @@ -412,7 +461,7 @@ int main(int argc, char const * argv[]) events = op_events(cpu_type); - if (!chosen_events && (unit_mask || check_events)) { + if (!chosen_events && (unit_mask || check_events || extra_mask)) { fprintf(stderr, "No events given.\n"); exit(EXIT_FAILURE); } @@ -422,6 +471,11 @@ int main(int argc, char const * argv[]) exit(EXIT_SUCCESS); } + if (extra_mask) { + show_extra_mask(); + exit(EXIT_SUCCESS); + } + if (check_events) { resolve_events(); exit(EXIT_SUCCESS); -- 1.7.4 |