From nobody Mon Jul 04 18:09:18 2022 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 0F4F91C3ED5A; Mon, 4 Jul 2022 18:09:20 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4LcDMz06cbz4k88; Mon, 4 Jul 2022 18:09:18 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1656958159; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=03I5AhLN1UUqYPThnCglIjcTB+vSQQx7mlCg74BKyTQ=; b=v5xrzBP/8bn0OpL+PQkptN56AwZGrb6DkiJXJL0OkCyU26x5cfPx7fTOAXYne7YZWKgtgm zA9RCf46JF+w5sj64wiwjprq1KEw9Cz2ysQDhkatbYJr4UWAwjBhp+aDfCvv9Nc/94BHfI 7ORbiBCCDZioka8Q65RF9eL4etNNKbxrRZEilOO9wE5JTpPrTq7T0r0BbJhyo9Seg8tmEr tNtW1E+i3DOKnS8N5t7zdEPdAZNpYkjI8b27i9GRy9IeeCsJKeUpMIXvRjnxjfCUFnJufV /HDziYlpMlewC3msvfX2W1F7fADNJrAVJNRBtILMUkc50YjRa36BQuDJIgfolg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4A8A615EEF; Mon, 4 Jul 2022 18:09:18 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 264I9IwT064307; Mon, 4 Jul 2022 18:09:18 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 264I9IuK064306; Mon, 4 Jul 2022 18:09:18 GMT (envelope-from git) Date: Mon, 4 Jul 2022 18:09:18 GMT Message-Id: <202207041809.264I9IuK064306@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Alexander Motin Subject: git: cc2310bd2a62 - stable/13 - libpmc: jevents: Sync with the latest Linux kernel. List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-branches@freebsd.org X-BeenThere: dev-commits-src-branches@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: mav X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: cc2310bd2a62af53af40ffb1aea7b72cd5e4531e Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1656958159; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=03I5AhLN1UUqYPThnCglIjcTB+vSQQx7mlCg74BKyTQ=; b=f1KAc4fRZ96t79SYPk4vQEwbaDfPptVm2dQ4sJP04Bts2fxPxSnG6Cru2A+oJhckcG9wM4 Gy9iBXZVgMba2FEQ+moosWJvGBDnnnV9mdlc9bka0cRN1r5oEdukvL4slJS4UyfqqwPBOm nglQ+284S8n0sV9SFTLmYCk7zxgSXtqrhWl3UDowxJdsbcsjR9Mhg5Q6mgT5CBeoyKXXW6 Aorw1/BlttAUM4IjX+el4+WbsKag3zJamu3lLrs67j5R4oliZaw3aGtbL50JjmzJHC40jW koUjmglUxkyQBmzZG93lAbeG0Xju77ULwmfULpMtiuGjSsirQcNKKMHFBpMKtg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1656958159; a=rsa-sha256; cv=none; b=psaz3pBZDoNezldDcFY2e8gh5ym54/qXrwESBRStVIRpMO659n9QP9a+A14iSvUp5sr4GX G1eIZS/RsT9qjsOj/oVp2QqrIbLAzgbDub7Z2pTPndqHk8I/AMG36ZZujzI5vawXBmfKym umpS3flwg6A4kdun2DglQFlGIU1SWxBscgKDquCvTkKsvPJhl1ifyS+jkzDAgzpgwid1ZA HB/rj3iu2QcNij1LV0bZm+taVJDMbeeLQkuBnmFbR4z94F2AWsxai8Gl+ieXzKvfPQ005+ qMkfVLq/HsmAINZbTyg+54OTMLDL2y2zYYQBJLnYJjf25AciOCE+VvO04Z+DmQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch stable/13 has been updated by mav: URL: https://cgit.FreeBSD.org/src/commit/?id=cc2310bd2a62af53af40ffb1aea7b72cd5e4531e commit cc2310bd2a62af53af40ffb1aea7b72cd5e4531e Author: Alexander Motin AuthorDate: 2022-05-30 18:07:31 +0000 Commit: Alexander Motin CommitDate: 2022-07-04 17:48:09 +0000 libpmc: jevents: Sync with the latest Linux kernel. commit f4df0dbbe62ee8e4405a57b27ccd54393971c773 Date: Wed May 25 22:04:10 2022 +0800 MFC after: 1 month (cherry picked from commit 62ff619dcc3540659a319be71c9a489f1659e14a) --- .../pmu-events/arch/test/arch-std-events.json | 8 + .../pmu-events/arch/test/test_soc/cpu/branch.json | 12 + .../pmu-events/arch/test/test_soc/cpu/cache.json | 5 + .../pmu-events/arch/test/test_soc/cpu/other.json | 26 + .../pmu-events/arch/test/test_soc/cpu/uncore.json | 58 ++ .../pmu-events/arch/test/test_soc/sys/uncore.json | 16 + lib/libpmc/pmu-events/jevents.c | 599 +++++++++++++-------- lib/libpmc/pmu-events/jevents.h | 14 - lib/libpmc/pmu-events/jsmn.c | 43 +- lib/libpmc/pmu-events/pmu-events.h | 21 +- 10 files changed, 569 insertions(+), 233 deletions(-) diff --git a/lib/libpmc/pmu-events/arch/test/arch-std-events.json b/lib/libpmc/pmu-events/arch/test/arch-std-events.json new file mode 100644 index 000000000000..43f6f729d6ae --- /dev/null +++ b/lib/libpmc/pmu-events/arch/test/arch-std-events.json @@ -0,0 +1,8 @@ +[ + { + "PublicDescription": "Attributable Level 3 cache access, read", + "EventCode": "0x40", + "EventName": "L3_CACHE_RD", + "BriefDescription": "L3 cache access, read" + } +] diff --git a/lib/libpmc/pmu-events/arch/test/test_soc/cpu/branch.json b/lib/libpmc/pmu-events/arch/test/test_soc/cpu/branch.json new file mode 100644 index 000000000000..93ddfd8053ca --- /dev/null +++ b/lib/libpmc/pmu-events/arch/test/test_soc/cpu/branch.json @@ -0,0 +1,12 @@ +[ + { + "EventName": "bp_l1_btb_correct", + "EventCode": "0x8a", + "BriefDescription": "L1 BTB Correction." + }, + { + "EventName": "bp_l2_btb_correct", + "EventCode": "0x8b", + "BriefDescription": "L2 BTB Correction." + } +] diff --git a/lib/libpmc/pmu-events/arch/test/test_soc/cpu/cache.json b/lib/libpmc/pmu-events/arch/test/test_soc/cpu/cache.json new file mode 100644 index 000000000000..036d0efdb2bb --- /dev/null +++ b/lib/libpmc/pmu-events/arch/test/test_soc/cpu/cache.json @@ -0,0 +1,5 @@ +[ + { + "ArchStdEvent": "L3_CACHE_RD" + } +] \ No newline at end of file diff --git a/lib/libpmc/pmu-events/arch/test/test_soc/cpu/other.json b/lib/libpmc/pmu-events/arch/test/test_soc/cpu/other.json new file mode 100644 index 000000000000..7d53d7ecd723 --- /dev/null +++ b/lib/libpmc/pmu-events/arch/test/test_soc/cpu/other.json @@ -0,0 +1,26 @@ +[ + { + "EventCode": "0x6", + "Counter": "0,1", + "UMask": "0x80", + "EventName": "SEGMENT_REG_LOADS.ANY", + "SampleAfterValue": "200000", + "BriefDescription": "Number of segment register loads." + }, + { + "EventCode": "0x9", + "Counter": "0,1", + "UMask": "0x20", + "EventName": "DISPATCH_BLOCKED.ANY", + "SampleAfterValue": "200000", + "BriefDescription": "Memory cluster signals to block micro-op dispatch for any reason" + }, + { + "EventCode": "0x3A", + "Counter": "0,1", + "UMask": "0x0", + "EventName": "EIST_TRANS", + "SampleAfterValue": "200000", + "BriefDescription": "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions" + } +] \ No newline at end of file diff --git a/lib/libpmc/pmu-events/arch/test/test_soc/cpu/uncore.json b/lib/libpmc/pmu-events/arch/test/test_soc/cpu/uncore.json new file mode 100644 index 000000000000..41bac1c6a008 --- /dev/null +++ b/lib/libpmc/pmu-events/arch/test/test_soc/cpu/uncore.json @@ -0,0 +1,58 @@ +[ + { + "EventCode": "0x02", + "EventName": "uncore_hisi_ddrc.flux_wcmd", + "BriefDescription": "DDRC write commands", + "PublicDescription": "DDRC write commands", + "Unit": "hisi_sccl,ddrc" + }, + { + "Unit": "CBO", + "EventCode": "0x22", + "UMask": "0x81", + "EventName": "UNC_CBO_XSNP_RESPONSE.MISS_EVICTION", + "BriefDescription": "A cross-core snoop resulted from L3 Eviction which misses in some processor core.", + "PublicDescription": "A cross-core snoop resulted from L3 Eviction which misses in some processor core.", + "Counter": "0,1", + "CounterMask": "0", + "Invert": "0", + "EdgeDetect": "0" + }, + { + "Unit": "CBO", + "EventCode": "0xE0", + "UMask": "0x00", + "EventName": "event-hyphen", + "BriefDescription": "UNC_CBO_HYPHEN", + "PublicDescription": "UNC_CBO_HYPHEN" + }, + { + "Unit": "CBO", + "EventCode": "0xC0", + "UMask": "0x00", + "EventName": "event-two-hyph", + "BriefDescription": "UNC_CBO_TWO_HYPH", + "PublicDescription": "UNC_CBO_TWO_HYPH" + }, + { + "EventCode": "0x7", + "EventName": "uncore_hisi_l3c.rd_hit_cpipe", + "BriefDescription": "Total read hits", + "PublicDescription": "Total read hits", + "Unit": "hisi_sccl,l3c" + }, + { + "EventCode": "0x12", + "EventName": "uncore_imc_free_running.cache_miss", + "BriefDescription": "Total cache misses", + "PublicDescription": "Total cache misses", + "Unit": "imc_free_running" + }, + { + "EventCode": "0x34", + "EventName": "uncore_imc.cache_hits", + "BriefDescription": "Total cache hits", + "PublicDescription": "Total cache hits", + "Unit": "imc" + } +] diff --git a/lib/libpmc/pmu-events/arch/test/test_soc/sys/uncore.json b/lib/libpmc/pmu-events/arch/test/test_soc/sys/uncore.json new file mode 100644 index 000000000000..c7e7528db315 --- /dev/null +++ b/lib/libpmc/pmu-events/arch/test/test_soc/sys/uncore.json @@ -0,0 +1,16 @@ +[ + { + "BriefDescription": "ddr write-cycles event", + "EventCode": "0x2b", + "EventName": "sys_ddr_pmu.write_cycles", + "Unit": "sys_ddr_pmu", + "Compat": "v8" + }, + { + "BriefDescription": "ccn read-cycles event", + "ConfigCode": "0x2c", + "EventName": "sys_ccn_pmu.read_cycles", + "Unit": "sys_ccn_pmu", + "Compat": "0x01" + } +] diff --git a/lib/libpmc/pmu-events/jevents.c b/lib/libpmc/pmu-events/jevents.c index b411329dd35a..5a296031451e 100644 --- a/lib/libpmc/pmu-events/jevents.c +++ b/lib/libpmc/pmu-events/jevents.c @@ -26,9 +26,6 @@ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - * */ #include @@ -50,17 +47,64 @@ #include "list.h" #include "jsmn.h" #include "json.h" -#include "jevents.h" +#include "pmu-events.h" static int nftw_ordered(const char *path, int (*fn)(const char *, const struct stat *, int, struct FTW *), int nfds, int ftwflags); +#define nftw nftw_ordered _Noreturn void _Exit(int); +char *get_cpu_str(void); int verbose; static char *prog; +struct json_event { + char *name; + char *compat; + char *event; + char *desc; + char *long_desc; + char *pmu; + char *unit; + char *perpkg; + char *aggr_mode; + char *metric_expr; + char *metric_name; + char *metric_group; + char *deprecated; + char *metric_constraint; +}; + +static enum aggr_mode_class convert(const char *aggr_mode) +{ + if (!strcmp(aggr_mode, "PerCore")) + return PerCore; + else if (!strcmp(aggr_mode, "PerChip")) + return PerChip; + + pr_err("%s: Wrong AggregationMode value '%s'\n", prog, aggr_mode); + return -1; +} + +static LIST_HEAD(sys_event_tables); + +struct sys_event_table { + struct list_head list; + char *soc_id; +}; + +static void free_sys_event_tables(void) +{ + struct sys_event_table *et, *next; + + list_for_each_entry_safe(et, next, &sys_event_tables, list) { + free(et->soc_id); + free(et); + } +} + int eprintf(int level, int var, const char *fmt, ...) { @@ -79,11 +123,6 @@ int eprintf(int level, int var, const char *fmt, ...) return ret; } -__attribute__((weak)) char *get_cpu_str(void) -{ - return NULL; -} - static void addfield(char *map, char **dst, const char *sep, const char *a, jsmntok_t *bt) { @@ -145,7 +184,7 @@ static char *fixregex(char *s) return s; /* allocate space for a new string */ - fixed = (char *) malloc(len + 1); + fixed = (char *) malloc(len + esc_count + 1); if (!fixed) return NULL; @@ -174,23 +213,6 @@ static struct msrmap { { NULL, NULL } }; -static struct field { - const char *field; - const char *kernel; -} fields[] = { - { "UMask", "umask=" }, - { "CounterMask", "cmask=" }, - { "Invert", "inv=" }, - { "AnyThread", "any=" }, - { "EdgeDetect", "edge=" }, - { "SampleAfterValue", "period=" }, - { "FCMask", "fc_mask=" }, - { "PortMask", "ch_mask=" }, - { "L3ThreadMask", "l3_thread_mask=" }, - { "L3SliceMask", "l3_slice_mask=" }, - { NULL, NULL } -}; - static void cut_comma(char *map, jsmntok_t *newval) { int i; @@ -202,21 +224,6 @@ static void cut_comma(char *map, jsmntok_t *newval) } } -static int match_field(char *map, jsmntok_t *field, int nz, - char **event, jsmntok_t *val) -{ - struct field *f; - jsmntok_t newval = *val; - - for (f = fields; f->field; f++) - if (json_streq(map, field, f->field) && nz) { - cut_comma(map, &newval); - addfield(map, event, ",", f->kernel, &newval); - return 1; - } - return 0; -} - static struct msrmap *lookup_msr(char *map, jsmntok_t *val) { jsmntok_t newval = *val; @@ -243,7 +250,15 @@ static struct map { { "QPI LL", "uncore_qpi" }, { "SBO", "uncore_sbox" }, { "iMPH-U", "uncore_arb" }, + { "CPU-M-CF", "cpum_cf" }, + { "CPU-M-SF", "cpum_sf" }, { "UPI LL", "uncore_upi" }, + { "hisi_sicl,cpa", "hisi_sicl,cpa"}, + { "hisi_sccl,ddrc", "hisi_sccl,ddrc" }, + { "hisi_sccl,hha", "hisi_sccl,hha" }, + { "hisi_sccl,l3c", "hisi_sccl,l3c" }, + /* it's not realistic to keep adding these, we need something more scalable ... */ + { "imx8_ddr", "imx8_ddr" }, { "L3PMC", "amd_l3" }, { "DFPMC", "amd_df" }, { "cpu_core", "cpu_core" }, @@ -301,7 +316,7 @@ static char *get_topic(void) return tp; } -static int add_topic(const char *bname) +static int add_topic(char *bname) { free(topic); topic = strdup(bname); @@ -322,19 +337,15 @@ static int close_table; static void print_events_table_prefix(FILE *fp, const char *tblname) { - fprintf(fp, "static struct pmu_event %s[] = {\n", tblname); + fprintf(fp, "static const struct pmu_event %s[] = {\n", tblname); close_table = 1; } -static int print_events_table_entry(void *data, char *name, const char *event, - char *desc, char *long_desc, - char *pmu, char *unit, char *perpkg, - char *metric_expr, - char *metric_name, char *metric_group) +static int print_events_table_entry(void *data, struct json_event *je) { struct perf_entry_data *pd = data; FILE *outfp = pd->outfp; - char *etopic = pd->topic; + char *topic_local = pd->topic; /* * TODO: Remove formatting chars after debugging to reduce @@ -342,26 +353,34 @@ static int print_events_table_entry(void *data, char *name, const char *event, */ fprintf(outfp, "{\n"); - if (name) - fprintf(outfp, "\t.name = \"%s\",\n", name); - if (event) - fprintf(outfp, "\t.event = \"%s\",\n", event); - fprintf(outfp, "\t.desc = \"%s\",\n", desc); - fprintf(outfp, "\t.topic = \"%s\",\n", etopic); - if (long_desc && long_desc[0]) - fprintf(outfp, "\t.long_desc = \"%s\",\n", long_desc); - if (pmu) - fprintf(outfp, "\t.pmu = \"%s\",\n", pmu); - if (unit) - fprintf(outfp, "\t.unit = \"%s\",\n", unit); - if (perpkg) - fprintf(outfp, "\t.perpkg = \"%s\",\n", perpkg); - if (metric_expr) - fprintf(outfp, "\t.metric_expr = \"%s\",\n", metric_expr); - if (metric_name) - fprintf(outfp, "\t.metric_name = \"%s\",\n", metric_name); - if (metric_group) - fprintf(outfp, "\t.metric_group = \"%s\",\n", metric_group); + if (je->name) + fprintf(outfp, "\t.name = \"%s\",\n", je->name); + if (je->event) + fprintf(outfp, "\t.event = \"%s\",\n", je->event); + fprintf(outfp, "\t.desc = \"%s\",\n", je->desc); + if (je->compat) + fprintf(outfp, "\t.compat = \"%s\",\n", je->compat); + fprintf(outfp, "\t.topic = \"%s\",\n", topic_local); + if (je->long_desc && je->long_desc[0]) + fprintf(outfp, "\t.long_desc = \"%s\",\n", je->long_desc); + if (je->pmu) + fprintf(outfp, "\t.pmu = \"%s\",\n", je->pmu); + if (je->unit) + fprintf(outfp, "\t.unit = \"%s\",\n", je->unit); + if (je->perpkg) + fprintf(outfp, "\t.perpkg = \"%s\",\n", je->perpkg); + if (je->aggr_mode) + fprintf(outfp, "\t.aggr_mode = \"%d\",\n", convert(je->aggr_mode)); + if (je->metric_expr) + fprintf(outfp, "\t.metric_expr = \"%s\",\n", je->metric_expr); + if (je->metric_name) + fprintf(outfp, "\t.metric_name = \"%s\",\n", je->metric_name); + if (je->metric_group) + fprintf(outfp, "\t.metric_group = \"%s\",\n", je->metric_group); + if (je->deprecated) + fprintf(outfp, "\t.deprecated = \"%s\",\n", je->deprecated); + if (je->metric_constraint) + fprintf(outfp, "\t.metric_constraint = \"%s\",\n", je->metric_constraint); fprintf(outfp, "},\n"); return 0; @@ -371,27 +390,31 @@ struct event_struct { struct list_head list; char *name; char *event; + char *compat; char *desc; char *long_desc; char *pmu; char *unit; char *perpkg; + char *aggr_mode; char *metric_expr; char *metric_name; char *metric_group; + char *deprecated; + char *metric_constraint; }; -#define ADD_EVENT_FIELD(field) do { if (field) { \ - es->field = strdup(field); \ +#define ADD_EVENT_FIELD(field) do { if (je->field) { \ + es->field = strdup(je->field); \ if (!es->field) \ goto out_free; \ } } while (0) #define FREE_EVENT_FIELD(field) free(es->field) -#define TRY_FIXUP_FIELD(field) do { if (es->field && !*field) {\ - *field = strdup(es->field); \ - if (!*field) \ +#define TRY_FIXUP_FIELD(field) do { if (es->field && !je->field) {\ + je->field = strdup(es->field); \ + if (!je->field) \ return -ENOMEM; \ } } while (0) @@ -403,9 +426,11 @@ struct event_struct { op(pmu); \ op(unit); \ op(perpkg); \ + op(aggr_mode); \ op(metric_expr); \ op(metric_name); \ op(metric_group); \ + op(deprecated); \ } while (0) static LIST_HEAD(arch_std_events); @@ -416,15 +441,12 @@ static void free_arch_std_events(void) list_for_each_entry_safe(es, next, &arch_std_events, list) { FOR_ALL_EVENT_STRUCT_FIELDS(FREE_EVENT_FIELD); - list_del(&es->list); + list_del_init(&es->list); free(es); } } -static int save_arch_std_events(void *data __unused, char *name, const char *event, - char *desc, char *long_desc, char *pmu, - char *unit, char *perpkg, char *metric_expr, - char *metric_name, char *metric_group) +static int save_arch_std_events(void *data __unused, struct json_event *je) { struct event_struct *es; @@ -458,18 +480,19 @@ static struct fixed { const char *name; const char *event; } fixed[] = { - { "inst_retired.any", "event=0xc0" }, - { "inst_retired.any_p", "event=0xc0" }, - { "cpu_clk_unhalted.ref", "event=0x0,umask=0x03" }, - { "cpu_clk_unhalted.thread", "event=0x3c" }, - { "cpu_clk_unhalted.thread_any", "event=0x3c,any=1" }, + { "inst_retired.any", "event=0xc0,period=2000003" }, + { "inst_retired.any_p", "event=0xc0,period=2000003" }, + { "cpu_clk_unhalted.ref", "event=0x0,umask=0x03,period=2000003" }, + { "cpu_clk_unhalted.thread", "event=0x3c,period=2000003" }, + { "cpu_clk_unhalted.core", "event=0x3c,period=2000003" }, + { "cpu_clk_unhalted.thread_any", "event=0x3c,any=1,period=2000003" }, { NULL, NULL}, }; /* * Handle different fixed counter encodings between JSON and perf. */ -static const char *real_event(const char *name, char *event) +static char *real_event(const char *name, char *event) { int i; @@ -478,27 +501,20 @@ static const char *real_event(const char *name, char *event) for (i = 0; fixed[i].name; i++) if (!strcasecmp(name, fixed[i].name)) - return fixed[i].event; + return (char *)fixed[i].event; return event; } static int -try_fixup(const char *fn, char *arch_std, char **event, char **desc, - char **name, char **long_desc, char **pmu, char **filter __unused, - char **perpkg, char **unit, char **metric_expr, char **metric_name, - char **metric_group, unsigned long long eventcode) +try_fixup(const char *fn, char *arch_std, struct json_event *je, char **event) { /* try to find matching event from arch standard values */ struct event_struct *es; list_for_each_entry(es, &arch_std_events, list) { if (!strcmp(arch_std, es->name)) { - if (!eventcode && es->event) { - /* allow EventCode to be overridden */ - free(*event); - *event = NULL; - } FOR_ALL_EVENT_STRUCT_FIELDS(TRY_FIXUP_FIELD); + *event = je->event; return 0; } } @@ -509,13 +525,9 @@ try_fixup(const char *fn, char *arch_std, char **event, char **desc, } /* Call func with each event in the json file */ -int json_events(const char *fn, - int (*func)(void *data, char *name, const char *event, char *desc, - char *long_desc, - char *pmu, char *unit, char *perpkg, - char *metric_expr, - char *metric_name, char *metric_group), - void *data) +static int json_events(const char *fn, + int (*func)(void *data, struct json_event *je), + void *data) { int err; size_t size; @@ -533,22 +545,26 @@ int json_events(const char *fn, EXPECT(tokens->type == JSMN_ARRAY, tokens, "expected top level array"); tok = tokens + 1; for (i = 0; i < tokens->size; i++) { - char *event = NULL, *desc = NULL, *name = NULL; - char *long_desc = NULL; + char *event = NULL; char *extra_desc = NULL; - char *pmu = NULL; char *filter = NULL; - char *perpkg = NULL; - char *unit = NULL; - char *metric_expr = NULL; - char *metric_name = NULL; - char *metric_group = NULL; + struct json_event je = {}; char *arch_std = NULL; unsigned long long eventcode = 0; + unsigned long long configcode = 0; struct msrmap *msr = NULL; jsmntok_t *msrval = NULL; jsmntok_t *precise = NULL; jsmntok_t *obj = tok++; + bool configcode_present = false; + char *umask = NULL; + char *cmask = NULL; + char *inv = NULL; + char *any = NULL; + char *edge = NULL; + char *period = NULL; + char *fc_mask = NULL; + char *ch_mask = NULL; EXPECT(obj->type == JSMN_OBJECT, obj, "expected object"); for (j = 0; j < obj->size; j += 2) { @@ -564,27 +580,50 @@ int json_events(const char *fn, "Expected string value"); nz = !json_streq(map, val, "0"); - if (match_field(map, field, nz, &event, val)) { - /* ok */ + /* match_field */ + if (json_streq(map, field, "UMask") && nz) { + addfield(map, &umask, "", "umask=", val); + } else if (json_streq(map, field, "CounterMask") && nz) { + addfield(map, &cmask, "", "cmask=", val); + } else if (json_streq(map, field, "Invert") && nz) { + addfield(map, &inv, "", "inv=", val); + } else if (json_streq(map, field, "AnyThread") && nz) { + addfield(map, &any, "", "any=", val); + } else if (json_streq(map, field, "EdgeDetect") && nz) { + addfield(map, &edge, "", "edge=", val); + } else if (json_streq(map, field, "SampleAfterValue") && nz) { + addfield(map, &period, "", "period=", val); + } else if (json_streq(map, field, "FCMask") && nz) { + addfield(map, &fc_mask, "", "fc_mask=", val); + } else if (json_streq(map, field, "PortMask") && nz) { + addfield(map, &ch_mask, "", "ch_mask=", val); } else if (json_streq(map, field, "EventCode")) { char *code = NULL; addfield(map, &code, "", "", val); eventcode |= strtoul(code, NULL, 0); free(code); + } else if (json_streq(map, field, "ConfigCode")) { + char *code = NULL; + addfield(map, &code, "", "", val); + configcode |= strtoul(code, NULL, 0); + free(code); + configcode_present = true; } else if (json_streq(map, field, "ExtSel")) { char *code = NULL; addfield(map, &code, "", "", val); - eventcode |= strtoul(code, NULL, 0) << 21; + eventcode |= strtoul(code, NULL, 0) << 8; free(code); } else if (json_streq(map, field, "EventName")) { - addfield(map, &name, "", "", val); + addfield(map, &je.name, "", "", val); + } else if (json_streq(map, field, "Compat")) { + addfield(map, &je.compat, "", "", val); } else if (json_streq(map, field, "BriefDescription")) { - addfield(map, &desc, "", "", val); - fixdesc(desc); + addfield(map, &je.desc, "", "", val); + fixdesc(je.desc); } else if (json_streq(map, field, "PublicDescription")) { - addfield(map, &long_desc, "", "", val); - fixdesc(long_desc); + addfield(map, &je.long_desc, "", "", val); + fixdesc(je.long_desc); } else if (json_streq(map, field, "PEBS") && nz) { precise = val; } else if (json_streq(map, field, "MSRIndex") && nz) { @@ -604,31 +643,32 @@ int json_events(const char *fn, ppmu = field_to_perf(unit_to_pmu, map, val); if (ppmu) { - pmu = strdup(ppmu); + je.pmu = strdup(ppmu); } else { - if (!pmu) - pmu = strdup("uncore_"); - addfield(map, &pmu, "", "", val); - for (s = pmu; *s; s++) + if (!je.pmu) + je.pmu = strdup("uncore_"); + addfield(map, &je.pmu, "", "", val); + for (s = je.pmu; *s; s++) *s = tolower(*s); } - addfield(map, &desc, ". ", "Unit: ", NULL); - addfield(map, &desc, "", pmu, NULL); - addfield(map, &desc, "", " ", NULL); } else if (json_streq(map, field, "Filter")) { addfield(map, &filter, "", "", val); } else if (json_streq(map, field, "ScaleUnit")) { - addfield(map, &unit, "", "", val); + addfield(map, &je.unit, "", "", val); } else if (json_streq(map, field, "PerPkg")) { - addfield(map, &perpkg, "", "", val); + addfield(map, &je.perpkg, "", "", val); + } else if (json_streq(map, field, "AggregationMode")) { + addfield(map, &je.aggr_mode, "", "", val); + } else if (json_streq(map, field, "Deprecated")) { + addfield(map, &je.deprecated, "", "", val); } else if (json_streq(map, field, "MetricName")) { - addfield(map, &metric_name, "", "", val); + addfield(map, &je.metric_name, "", "", val); } else if (json_streq(map, field, "MetricGroup")) { - addfield(map, &metric_group, "", "", val); + addfield(map, &je.metric_group, "", "", val); + } else if (json_streq(map, field, "MetricConstraint")) { + addfield(map, &je.metric_constraint, "", "", val); } else if (json_streq(map, field, "MetricExpr")) { - addfield(map, &metric_expr, "", "", val); - for (s = metric_expr; *s; s++) - *s = tolower(*s); + addfield(map, &je.metric_expr, "", "", val); } else if (json_streq(map, field, "ArchStdEvent")) { addfield(map, &arch_std, "", "", val); for (s = arch_std; *s; s++) @@ -636,7 +676,7 @@ int json_events(const char *fn, } /* ignore unknown fields */ } - if (precise && desc && !strstr(desc, "(Precise Event)")) { + if (precise && je.desc && !strstr(je.desc, "(Precise Event)")) { if (json_streq(map, precise, "2")) addfield(map, &extra_desc, " ", "(Must be precise)", NULL); @@ -644,46 +684,80 @@ int json_events(const char *fn, addfield(map, &extra_desc, " ", "(Precise event)", NULL); } - snprintf(buf, sizeof(buf), "event=%#llx", eventcode); + if (configcode_present) + snprintf(buf, sizeof buf, "config=%#llx", configcode); + else + snprintf(buf, sizeof buf, "event=%#llx", eventcode); addfield(map, &event, ",", buf, NULL); - if (desc && extra_desc) - addfield(map, &desc, " ", extra_desc, NULL); - if (long_desc && extra_desc) - addfield(map, &long_desc, " ", extra_desc, NULL); + if (any) + addfield(map, &event, ",", any, NULL); + if (ch_mask) + addfield(map, &event, ",", ch_mask, NULL); + if (cmask) + addfield(map, &event, ",", cmask, NULL); + if (edge) + addfield(map, &event, ",", edge, NULL); + if (fc_mask) + addfield(map, &event, ",", fc_mask, NULL); + if (inv) + addfield(map, &event, ",", inv, NULL); + if (period) + addfield(map, &event, ",", period, NULL); + if (umask) + addfield(map, &event, ",", umask, NULL); + + if (je.desc && extra_desc) + addfield(map, &je.desc, " ", extra_desc, NULL); + if (je.long_desc && extra_desc) + addfield(map, &je.long_desc, " ", extra_desc, NULL); + if (je.pmu) { + addfield(map, &je.desc, ". ", "Unit: ", NULL); + addfield(map, &je.desc, "", je.pmu, NULL); + addfield(map, &je.desc, "", " ", NULL); + } if (filter) addfield(map, &event, ",", filter, NULL); if (msr != NULL) addfield(map, &event, ",", msr->pname, msrval); - if (name) - fixname(name); + if (je.name) + fixname(je.name); if (arch_std) { /* * An arch standard event is referenced, so try to * fixup any unassigned values. */ - err = try_fixup(fn, arch_std, &event, &desc, &name, - &long_desc, &pmu, &filter, &perpkg, - &unit, &metric_expr, &metric_name, - &metric_group, eventcode); + err = try_fixup(fn, arch_std, &je, &event); if (err) goto free_strings; } - err = func(data, name, real_event(name, event), desc, long_desc, - pmu, unit, perpkg, metric_expr, metric_name, metric_group); + je.event = real_event(je.name, event); + err = func(data, &je); free_strings: + free(umask); + free(cmask); + free(inv); + free(any); + free(edge); + free(period); + free(fc_mask); + free(ch_mask); free(event); - free(desc); - free(name); - free(long_desc); + free(je.desc); + free(je.name); + free(je.compat); + free(je.long_desc); free(extra_desc); - free(pmu); + free(je.pmu); free(filter); - free(perpkg); - free(unit); - free(metric_expr); - free(metric_name); - free(metric_group); + free(je.perpkg); + free(je.aggr_mode); + free(je.deprecated); + free(je.unit); + free(je.metric_expr); + free(je.metric_name); + free(je.metric_group); + free(je.metric_constraint); free(arch_std); if (err) @@ -697,14 +771,13 @@ out_free: return err; } -static char *file_name_to_table_name(const char *fname) +static char *file_name_to_table_name(char *fname) { unsigned int i; int n; int c; char *tblname; - /* * Ensure tablename starts with alphabetic character. * Derive rest of table name from basename of the JSON file, @@ -726,11 +799,9 @@ static char *file_name_to_table_name(const char *fname) tblname[i] = '\0'; break; } else if (!isalnum(c) && c != '_') { - char *tmp = strdup(fname); - pr_err("%s: Invalid character '%c' in file name %s\n", - prog, c, basename(tmp)); + pr_err("%s: Invalid character '%c' in file name '%s'\n", + prog, c, fname); free(tblname); - free(tmp); tblname = NULL; break; } @@ -739,9 +810,18 @@ static char *file_name_to_table_name(const char *fname) return tblname; } +static bool is_sys_dir(char *fname) +{ + size_t len = strlen(fname), len2 = strlen("/sys"); + + if (len2 > len) + return false; + return !strcmp(fname+len-len2, "/sys"); +} + static void print_mapping_table_prefix(FILE *outfp) { - fprintf(outfp, "struct pmu_events_map pmu_events_map[] = {\n"); + fprintf(outfp, "const struct pmu_events_map pmu_events_map[] = {\n"); } static void print_mapping_table_suffix(FILE *outfp) @@ -760,6 +840,47 @@ static void print_mapping_table_suffix(FILE *outfp) fprintf(outfp, "};\n"); } +static void print_mapping_test_table(FILE *outfp) +{ + /* + * Print the terminating, NULL entry. + */ + fprintf(outfp, "{\n"); + fprintf(outfp, "\t.cpuid = \"testcpu\",\n"); + fprintf(outfp, "\t.version = \"v1\",\n"); + fprintf(outfp, "\t.type = \"core\",\n"); + fprintf(outfp, "\t.table = pme_test_soc_cpu,\n"); + fprintf(outfp, "},\n"); +} + +static void print_system_event_mapping_table_prefix(FILE *outfp) +{ + fprintf(outfp, "\nconst struct pmu_sys_events pmu_sys_event_tables[] = {"); +} + +static void print_system_event_mapping_table_suffix(FILE *outfp) +{ + fprintf(outfp, "\n\t{\n\t\t.table = 0\n\t},"); + fprintf(outfp, "\n};\n"); +} + +static int process_system_event_tables(FILE *outfp) +{ + struct sys_event_table *sys_event_table; + + print_system_event_mapping_table_prefix(outfp); + + list_for_each_entry(sys_event_table, &sys_event_tables, list) { + fprintf(outfp, "\n\t{\n\t\t.table = %s,\n\t\t.name = \"%s\",\n\t},", + sys_event_table->soc_id, + sys_event_table->soc_id); + } + + print_system_event_mapping_table_suffix(outfp); + + return 0; +} + static int process_mapfile(FILE *outfp, char *fpath) { int n = 16384; @@ -768,6 +889,7 @@ static int process_mapfile(FILE *outfp, char *fpath) char *line, *p; int line_num; char *tblname; + int ret = 0; pr_info("%s: Processing mapfile %s\n", prog, fpath); @@ -806,9 +928,8 @@ static int process_mapfile(FILE *outfp, char *fpath) /* TODO Deal with lines longer than 16K */ pr_info("%s: Mapfile %s: line %d too long, aborting\n", prog, fpath, line_num); - free(line); - fclose(mapfp); - return -1; + ret = -1; + goto out; } line[strlen(line)-1] = '\0'; @@ -837,10 +958,11 @@ static int process_mapfile(FILE *outfp, char *fpath) } out: + print_mapping_test_table(outfp); print_mapping_table_suffix(outfp); - free(line); fclose(mapfp); - return 0; + free(line); + return ret; } /* @@ -864,6 +986,8 @@ static void create_empty_mapping(const char *output_file) fprintf(outfp, "#include \"pmu-events/pmu-events.h\"\n"); print_mapping_table_prefix(outfp); print_mapping_table_suffix(outfp); + print_system_event_mapping_table_prefix(outfp); + print_system_event_mapping_table_suffix(outfp); fclose(outfp); } @@ -908,8 +1032,7 @@ static int is_leaf_dir(const char *fpath) char path[PATH_MAX]; struct stat st; - snprintf(path, sizeof(path), "%s/%s", fpath, - dir->d_name); + snprintf(path, sizeof(path), "%s/%s", fpath, dir->d_name); *** 443 LINES SKIPPED ***