1576a65b6SJiri Olsa // SPDX-License-Identifier: GPL-2.0 226226a97SJiri Olsa #include <stdbool.h> 3576a65b6SJiri Olsa #include <assert.h> 43744ca1eSArnaldo Carvalho de Melo #include <errno.h> 53744ca1eSArnaldo Carvalho de Melo #include <stdlib.h> 63744ca1eSArnaldo Carvalho de Melo #include <string.h> 7fc393839SJiri Olsa #include "metricgroup.h" 8fdf1e29bSIan Rogers #include "cpumap.h" 9fdf1e29bSIan Rogers #include "cputopo.h" 10fc393839SJiri Olsa #include "debug.h" 11576a65b6SJiri Olsa #include "expr.h" 1226226a97SJiri Olsa #include "expr-bison.h" 1326226a97SJiri Olsa #include "expr-flex.h" 14bd560973SIan Rogers #include "util/hashmap.h" 153613f6c1SIan Rogers #include "smt.h" 16bc2373a5SKan Liang #include "tsc.h" 17c3bf86f1SIan Rogers #include <api/fs/fs.h> 180a515a06SMiaoqian Lin #include <linux/err.h> 19ded80bdaSIan Rogers #include <linux/kernel.h> 20fc393839SJiri Olsa #include <linux/zalloc.h> 21fc393839SJiri Olsa #include <ctype.h> 223613f6c1SIan Rogers #include <math.h> 23acef233bSJing Zhang #include "pmu.h" 2426226a97SJiri Olsa 2526226a97SJiri Olsa #ifdef PARSER_DEBUG 2626226a97SJiri Olsa extern int expr_debug; 2726226a97SJiri Olsa #endif 28576a65b6SJiri Olsa 2929396cd5SIan Rogers struct expr_id_data { 3029396cd5SIan Rogers union { 319aba0adaSIan Rogers struct { 3229396cd5SIan Rogers double val; 339aba0adaSIan Rogers int source_count; 349aba0adaSIan Rogers } val; 3529396cd5SIan Rogers struct { 3629396cd5SIan Rogers double val; 3729396cd5SIan Rogers const char *metric_name; 3829396cd5SIan Rogers const char *metric_expr; 3929396cd5SIan Rogers } ref; 4029396cd5SIan Rogers }; 4129396cd5SIan Rogers 4229396cd5SIan Rogers enum { 4329396cd5SIan Rogers /* Holding a double value. */ 4429396cd5SIan Rogers EXPR_ID_DATA__VALUE, 4529396cd5SIan Rogers /* Reference to another metric. */ 4629396cd5SIan Rogers EXPR_ID_DATA__REF, 4729396cd5SIan Rogers /* A reference but the value has been computed. */ 4829396cd5SIan Rogers EXPR_ID_DATA__REF_VALUE, 4929396cd5SIan Rogers } kind; 5029396cd5SIan Rogers }; 5129396cd5SIan Rogers 52c302378bSEduard Zingerman static size_t key_hash(long key, void *ctx __maybe_unused) 53576a65b6SJiri Olsa { 54ded80bdaSIan Rogers const char *str = (const char *)key; 55ded80bdaSIan Rogers size_t hash = 0; 56576a65b6SJiri Olsa 57ded80bdaSIan Rogers while (*str != '\0') { 58ded80bdaSIan Rogers hash *= 31; 59ded80bdaSIan Rogers hash += *str; 60ded80bdaSIan Rogers str++; 61ded80bdaSIan Rogers } 62ded80bdaSIan Rogers return hash; 63ded80bdaSIan Rogers } 64ded80bdaSIan Rogers 65c302378bSEduard Zingerman static bool key_equal(long key1, long key2, void *ctx __maybe_unused) 66ded80bdaSIan Rogers { 67ded80bdaSIan Rogers return !strcmp((const char *)key1, (const char *)key2); 68ded80bdaSIan Rogers } 69ded80bdaSIan Rogers 70114a9d6eSIan Rogers struct hashmap *ids__new(void) 71114a9d6eSIan Rogers { 729f3c16a4SMiaoqian Lin struct hashmap *hash; 739f3c16a4SMiaoqian Lin 749f3c16a4SMiaoqian Lin hash = hashmap__new(key_hash, key_equal, NULL); 759f3c16a4SMiaoqian Lin if (IS_ERR(hash)) 769f3c16a4SMiaoqian Lin return NULL; 779f3c16a4SMiaoqian Lin return hash; 78114a9d6eSIan Rogers } 79114a9d6eSIan Rogers 80114a9d6eSIan Rogers void ids__free(struct hashmap *ids) 81114a9d6eSIan Rogers { 82114a9d6eSIan Rogers struct hashmap_entry *cur; 83114a9d6eSIan Rogers size_t bkt; 84114a9d6eSIan Rogers 85114a9d6eSIan Rogers if (ids == NULL) 86114a9d6eSIan Rogers return; 87114a9d6eSIan Rogers 88114a9d6eSIan Rogers hashmap__for_each_entry(ids, cur, bkt) { 89*a77f8184SArnaldo Carvalho de Melo zfree(&cur->pkey); 90*a77f8184SArnaldo Carvalho de Melo zfree(&cur->pvalue); 91114a9d6eSIan Rogers } 92114a9d6eSIan Rogers 93114a9d6eSIan Rogers hashmap__free(ids); 94114a9d6eSIan Rogers } 95114a9d6eSIan Rogers 9680be6434SIan Rogers int ids__insert(struct hashmap *ids, const char *id) 97332603c2SJiri Olsa { 98332603c2SJiri Olsa struct expr_id_data *data_ptr = NULL, *old_data = NULL; 99332603c2SJiri Olsa char *old_key = NULL; 100332603c2SJiri Olsa int ret; 101332603c2SJiri Olsa 102c302378bSEduard Zingerman ret = hashmap__set(ids, id, data_ptr, &old_key, &old_data); 103332603c2SJiri Olsa if (ret) 104332603c2SJiri Olsa free(data_ptr); 105332603c2SJiri Olsa free(old_key); 106332603c2SJiri Olsa free(old_data); 107332603c2SJiri Olsa return ret; 108332603c2SJiri Olsa } 109332603c2SJiri Olsa 110114a9d6eSIan Rogers struct hashmap *ids__union(struct hashmap *ids1, struct hashmap *ids2) 111114a9d6eSIan Rogers { 112114a9d6eSIan Rogers size_t bkt; 113114a9d6eSIan Rogers struct hashmap_entry *cur; 114114a9d6eSIan Rogers int ret; 115114a9d6eSIan Rogers struct expr_id_data *old_data = NULL; 116114a9d6eSIan Rogers char *old_key = NULL; 117114a9d6eSIan Rogers 118114a9d6eSIan Rogers if (!ids1) 119114a9d6eSIan Rogers return ids2; 120114a9d6eSIan Rogers 121114a9d6eSIan Rogers if (!ids2) 122114a9d6eSIan Rogers return ids1; 123114a9d6eSIan Rogers 124114a9d6eSIan Rogers if (hashmap__size(ids1) < hashmap__size(ids2)) { 125114a9d6eSIan Rogers struct hashmap *tmp = ids1; 126114a9d6eSIan Rogers 127114a9d6eSIan Rogers ids1 = ids2; 128114a9d6eSIan Rogers ids2 = tmp; 129114a9d6eSIan Rogers } 130114a9d6eSIan Rogers hashmap__for_each_entry(ids2, cur, bkt) { 131c302378bSEduard Zingerman ret = hashmap__set(ids1, cur->key, cur->value, &old_key, &old_data); 132114a9d6eSIan Rogers free(old_key); 133114a9d6eSIan Rogers free(old_data); 134114a9d6eSIan Rogers 135114a9d6eSIan Rogers if (ret) { 136114a9d6eSIan Rogers hashmap__free(ids1); 137114a9d6eSIan Rogers hashmap__free(ids2); 138114a9d6eSIan Rogers return NULL; 139114a9d6eSIan Rogers } 140114a9d6eSIan Rogers } 141114a9d6eSIan Rogers hashmap__free(ids2); 142114a9d6eSIan Rogers return ids1; 143114a9d6eSIan Rogers } 144114a9d6eSIan Rogers 145114a9d6eSIan Rogers /* Caller must make sure id is allocated */ 146114a9d6eSIan Rogers int expr__add_id(struct expr_parse_ctx *ctx, const char *id) 147114a9d6eSIan Rogers { 14880be6434SIan Rogers return ids__insert(ctx->ids, id); 149114a9d6eSIan Rogers } 150114a9d6eSIan Rogers 151332603c2SJiri Olsa /* Caller must make sure id is allocated */ 152070b3b5aSJiri Olsa int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val) 153ded80bdaSIan Rogers { 1549aba0adaSIan Rogers return expr__add_id_val_source_count(ctx, id, val, /*source_count=*/1); 1559aba0adaSIan Rogers } 1569aba0adaSIan Rogers 1579aba0adaSIan Rogers /* Caller must make sure id is allocated */ 1589aba0adaSIan Rogers int expr__add_id_val_source_count(struct expr_parse_ctx *ctx, const char *id, 1599aba0adaSIan Rogers double val, int source_count) 1609aba0adaSIan Rogers { 161070b3b5aSJiri Olsa struct expr_id_data *data_ptr = NULL, *old_data = NULL; 162ded80bdaSIan Rogers char *old_key = NULL; 163ded80bdaSIan Rogers int ret; 164ded80bdaSIan Rogers 165070b3b5aSJiri Olsa data_ptr = malloc(sizeof(*data_ptr)); 166070b3b5aSJiri Olsa if (!data_ptr) 167ded80bdaSIan Rogers return -ENOMEM; 1689aba0adaSIan Rogers data_ptr->val.val = val; 1699aba0adaSIan Rogers data_ptr->val.source_count = source_count; 17029396cd5SIan Rogers data_ptr->kind = EXPR_ID_DATA__VALUE; 171332603c2SJiri Olsa 172c302378bSEduard Zingerman ret = hashmap__set(ctx->ids, id, data_ptr, &old_key, &old_data); 17360e10c00SJiri Olsa if (ret) 17460e10c00SJiri Olsa free(data_ptr); 175ded80bdaSIan Rogers free(old_key); 176070b3b5aSJiri Olsa free(old_data); 177ded80bdaSIan Rogers return ret; 178ded80bdaSIan Rogers } 179ded80bdaSIan Rogers 180fc393839SJiri Olsa int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref) 181fc393839SJiri Olsa { 182fc393839SJiri Olsa struct expr_id_data *data_ptr = NULL, *old_data = NULL; 183fc393839SJiri Olsa char *old_key = NULL; 184715b824fSIan Rogers char *name; 185fc393839SJiri Olsa int ret; 186fc393839SJiri Olsa 187fc393839SJiri Olsa data_ptr = zalloc(sizeof(*data_ptr)); 188fc393839SJiri Olsa if (!data_ptr) 189fc393839SJiri Olsa return -ENOMEM; 190fc393839SJiri Olsa 191fc393839SJiri Olsa name = strdup(ref->metric_name); 192fc393839SJiri Olsa if (!name) { 193fc393839SJiri Olsa free(data_ptr); 194fc393839SJiri Olsa return -ENOMEM; 195fc393839SJiri Olsa } 196fc393839SJiri Olsa 197fc393839SJiri Olsa /* 198fc393839SJiri Olsa * Intentionally passing just const char pointers, 199fc393839SJiri Olsa * originally from 'struct pmu_event' object. 200fc393839SJiri Olsa * We don't need to change them, so there's no 201fc393839SJiri Olsa * need to create our own copy. 202fc393839SJiri Olsa */ 203fc393839SJiri Olsa data_ptr->ref.metric_name = ref->metric_name; 204fc393839SJiri Olsa data_ptr->ref.metric_expr = ref->metric_expr; 20529396cd5SIan Rogers data_ptr->kind = EXPR_ID_DATA__REF; 206fc393839SJiri Olsa 207c302378bSEduard Zingerman ret = hashmap__set(ctx->ids, name, data_ptr, &old_key, &old_data); 208fc393839SJiri Olsa if (ret) 209fc393839SJiri Olsa free(data_ptr); 210fc393839SJiri Olsa 211fc393839SJiri Olsa pr_debug2("adding ref metric %s: %s\n", 212fc393839SJiri Olsa ref->metric_name, ref->metric_expr); 213fc393839SJiri Olsa 214fc393839SJiri Olsa free(old_key); 215fc393839SJiri Olsa free(old_data); 216fc393839SJiri Olsa return ret; 217fc393839SJiri Olsa } 218fc393839SJiri Olsa 2195c5f5e83SJiri Olsa int expr__get_id(struct expr_parse_ctx *ctx, const char *id, 2205c5f5e83SJiri Olsa struct expr_id_data **data) 221ded80bdaSIan Rogers { 222c302378bSEduard Zingerman return hashmap__find(ctx->ids, id, data) ? 0 : -1; 223576a65b6SJiri Olsa } 224576a65b6SJiri Olsa 225798c3f4aSIan Rogers bool expr__subset_of_ids(struct expr_parse_ctx *haystack, 226798c3f4aSIan Rogers struct expr_parse_ctx *needles) 227798c3f4aSIan Rogers { 228798c3f4aSIan Rogers struct hashmap_entry *cur; 229798c3f4aSIan Rogers size_t bkt; 230798c3f4aSIan Rogers struct expr_id_data *data; 231798c3f4aSIan Rogers 232798c3f4aSIan Rogers hashmap__for_each_entry(needles->ids, cur, bkt) { 233c302378bSEduard Zingerman if (expr__get_id(haystack, cur->pkey, &data)) 234798c3f4aSIan Rogers return false; 235798c3f4aSIan Rogers } 236798c3f4aSIan Rogers return true; 237798c3f4aSIan Rogers } 238798c3f4aSIan Rogers 239798c3f4aSIan Rogers 240acf71b05SJiri Olsa int expr__resolve_id(struct expr_parse_ctx *ctx, const char *id, 241acf71b05SJiri Olsa struct expr_id_data **datap) 242acf71b05SJiri Olsa { 243acf71b05SJiri Olsa struct expr_id_data *data; 244acf71b05SJiri Olsa 245acf71b05SJiri Olsa if (expr__get_id(ctx, id, datap) || !*datap) { 246acf71b05SJiri Olsa pr_debug("%s not found\n", id); 247acf71b05SJiri Olsa return -1; 248acf71b05SJiri Olsa } 249acf71b05SJiri Olsa 250acf71b05SJiri Olsa data = *datap; 251acf71b05SJiri Olsa 25229396cd5SIan Rogers switch (data->kind) { 25329396cd5SIan Rogers case EXPR_ID_DATA__VALUE: 2549aba0adaSIan Rogers pr_debug2("lookup(%s): val %f\n", id, data->val.val); 25529396cd5SIan Rogers break; 25629396cd5SIan Rogers case EXPR_ID_DATA__REF: 25729396cd5SIan Rogers pr_debug2("lookup(%s): ref metric name %s\n", id, 25829396cd5SIan Rogers data->ref.metric_name); 259acf71b05SJiri Olsa pr_debug("processing metric: %s ENTRY\n", id); 26029396cd5SIan Rogers data->kind = EXPR_ID_DATA__REF_VALUE; 261fa831fbbSIan Rogers if (expr__parse(&data->ref.val, ctx, data->ref.metric_expr)) { 262acf71b05SJiri Olsa pr_debug("%s failed to count\n", id); 263acf71b05SJiri Olsa return -1; 264acf71b05SJiri Olsa } 2659aba0adaSIan Rogers pr_debug("processing metric: %s EXIT: %f\n", id, data->ref.val); 26629396cd5SIan Rogers break; 26729396cd5SIan Rogers case EXPR_ID_DATA__REF_VALUE: 26829396cd5SIan Rogers pr_debug2("lookup(%s): ref val %f metric name %s\n", id, 26929396cd5SIan Rogers data->ref.val, data->ref.metric_name); 27029396cd5SIan Rogers break; 27129396cd5SIan Rogers default: 27229396cd5SIan Rogers assert(0); /* Unreachable. */ 273acf71b05SJiri Olsa } 274acf71b05SJiri Olsa 275acf71b05SJiri Olsa return 0; 276acf71b05SJiri Olsa } 277acf71b05SJiri Olsa 2783fd29fa6SJiri Olsa void expr__del_id(struct expr_parse_ctx *ctx, const char *id) 2793fd29fa6SJiri Olsa { 2803fd29fa6SJiri Olsa struct expr_id_data *old_val = NULL; 2813fd29fa6SJiri Olsa char *old_key = NULL; 2823fd29fa6SJiri Olsa 283c302378bSEduard Zingerman hashmap__delete(ctx->ids, id, &old_key, &old_val); 2843fd29fa6SJiri Olsa free(old_key); 2853fd29fa6SJiri Olsa free(old_val); 2863fd29fa6SJiri Olsa } 2873fd29fa6SJiri Olsa 288cb94a02eSIan Rogers struct expr_parse_ctx *expr__ctx_new(void) 289576a65b6SJiri Olsa { 290cb94a02eSIan Rogers struct expr_parse_ctx *ctx; 291cb94a02eSIan Rogers 292cb94a02eSIan Rogers ctx = malloc(sizeof(struct expr_parse_ctx)); 293cb94a02eSIan Rogers if (!ctx) 294cb94a02eSIan Rogers return NULL; 295cb94a02eSIan Rogers 296cb94a02eSIan Rogers ctx->ids = hashmap__new(key_hash, key_equal, NULL); 2970a515a06SMiaoqian Lin if (IS_ERR(ctx->ids)) { 2980a515a06SMiaoqian Lin free(ctx); 2990a515a06SMiaoqian Lin return NULL; 3000a515a06SMiaoqian Lin } 3011725e9cdSIan Rogers ctx->sctx.user_requested_cpu_list = NULL; 3021a6abddeSIan Rogers ctx->sctx.runtime = 0; 3031725e9cdSIan Rogers ctx->sctx.system_wide = false; 30480be6434SIan Rogers 305cb94a02eSIan Rogers return ctx; 306ded80bdaSIan Rogers } 307ded80bdaSIan Rogers 308ded80bdaSIan Rogers void expr__ctx_clear(struct expr_parse_ctx *ctx) 309ded80bdaSIan Rogers { 310ded80bdaSIan Rogers struct hashmap_entry *cur; 311ded80bdaSIan Rogers size_t bkt; 312ded80bdaSIan Rogers 313cb94a02eSIan Rogers hashmap__for_each_entry(ctx->ids, cur, bkt) { 314*a77f8184SArnaldo Carvalho de Melo zfree(&cur->pkey); 315*a77f8184SArnaldo Carvalho de Melo zfree(&cur->pvalue); 316ded80bdaSIan Rogers } 317cb94a02eSIan Rogers hashmap__clear(ctx->ids); 318cb94a02eSIan Rogers } 319cb94a02eSIan Rogers 320cb94a02eSIan Rogers void expr__ctx_free(struct expr_parse_ctx *ctx) 321cb94a02eSIan Rogers { 322cb94a02eSIan Rogers struct hashmap_entry *cur; 323cb94a02eSIan Rogers size_t bkt; 324cb94a02eSIan Rogers 3251725e9cdSIan Rogers if (!ctx) 3261725e9cdSIan Rogers return; 3271725e9cdSIan Rogers 328*a77f8184SArnaldo Carvalho de Melo zfree(&ctx->sctx.user_requested_cpu_list); 329cb94a02eSIan Rogers hashmap__for_each_entry(ctx->ids, cur, bkt) { 330*a77f8184SArnaldo Carvalho de Melo zfree(&cur->pkey); 331*a77f8184SArnaldo Carvalho de Melo zfree(&cur->pvalue); 332cb94a02eSIan Rogers } 333cb94a02eSIan Rogers hashmap__free(ctx->ids); 334cb94a02eSIan Rogers free(ctx); 335576a65b6SJiri Olsa } 33626226a97SJiri Olsa 33726226a97SJiri Olsa static int 338aecce63eSJiri Olsa __expr__parse(double *val, struct expr_parse_ctx *ctx, const char *expr, 339fa831fbbSIan Rogers bool compute_ids) 34026226a97SJiri Olsa { 34126226a97SJiri Olsa YY_BUFFER_STATE buffer; 34226226a97SJiri Olsa void *scanner; 34326226a97SJiri Olsa int ret; 34426226a97SJiri Olsa 345acf71b05SJiri Olsa pr_debug2("parsing metric: %s\n", expr); 346acf71b05SJiri Olsa 3471a6abddeSIan Rogers ret = expr_lex_init_extra(&ctx->sctx, &scanner); 34826226a97SJiri Olsa if (ret) 34926226a97SJiri Olsa return ret; 35026226a97SJiri Olsa 35126226a97SJiri Olsa buffer = expr__scan_string(expr, scanner); 35226226a97SJiri Olsa 35326226a97SJiri Olsa #ifdef PARSER_DEBUG 35426226a97SJiri Olsa expr_debug = 1; 355e5e0e635SIan Rogers expr_set_debug(1, scanner); 35626226a97SJiri Olsa #endif 35726226a97SJiri Olsa 3583f965a7dSIan Rogers ret = expr_parse(val, ctx, compute_ids, scanner); 35926226a97SJiri Olsa 36026226a97SJiri Olsa expr__flush_buffer(buffer, scanner); 36126226a97SJiri Olsa expr__delete_buffer(buffer, scanner); 36226226a97SJiri Olsa expr_lex_destroy(scanner); 36326226a97SJiri Olsa return ret; 36426226a97SJiri Olsa } 36526226a97SJiri Olsa 366ded80bdaSIan Rogers int expr__parse(double *final_val, struct expr_parse_ctx *ctx, 367fa831fbbSIan Rogers const char *expr) 36826226a97SJiri Olsa { 369fa831fbbSIan Rogers return __expr__parse(final_val, ctx, expr, /*compute_ids=*/false) ? -1 : 0; 37026226a97SJiri Olsa } 37126226a97SJiri Olsa 3727e06a5e3SIan Rogers int expr__find_ids(const char *expr, const char *one, 373fa831fbbSIan Rogers struct expr_parse_ctx *ctx) 37426226a97SJiri Olsa { 375fa831fbbSIan Rogers int ret = __expr__parse(NULL, ctx, expr, /*compute_ids=*/true); 37626226a97SJiri Olsa 3773fd29fa6SJiri Olsa if (one) 3783fd29fa6SJiri Olsa expr__del_id(ctx, one); 37926226a97SJiri Olsa 380ded80bdaSIan Rogers return ret; 38126226a97SJiri Olsa } 38229396cd5SIan Rogers 38329396cd5SIan Rogers double expr_id_data__value(const struct expr_id_data *data) 38429396cd5SIan Rogers { 38529396cd5SIan Rogers if (data->kind == EXPR_ID_DATA__VALUE) 3869aba0adaSIan Rogers return data->val.val; 38729396cd5SIan Rogers assert(data->kind == EXPR_ID_DATA__REF_VALUE); 38829396cd5SIan Rogers return data->ref.val; 38929396cd5SIan Rogers } 3903613f6c1SIan Rogers 3919aba0adaSIan Rogers double expr_id_data__source_count(const struct expr_id_data *data) 3929aba0adaSIan Rogers { 3939aba0adaSIan Rogers assert(data->kind == EXPR_ID_DATA__VALUE); 3949aba0adaSIan Rogers return data->val.source_count; 3959aba0adaSIan Rogers } 3969aba0adaSIan Rogers 397bc2373a5SKan Liang #if !defined(__i386__) && !defined(__x86_64__) 398bc2373a5SKan Liang double arch_get_tsc_freq(void) 399bc2373a5SKan Liang { 400bc2373a5SKan Liang return 0.0; 401bc2373a5SKan Liang } 402bc2373a5SKan Liang #endif 403bc2373a5SKan Liang 404c3bf86f1SIan Rogers static double has_pmem(void) 405c3bf86f1SIan Rogers { 406c3bf86f1SIan Rogers static bool has_pmem, cached; 407c3bf86f1SIan Rogers const char *sysfs = sysfs__mountpoint(); 408c3bf86f1SIan Rogers char path[PATH_MAX]; 409c3bf86f1SIan Rogers 410c3bf86f1SIan Rogers if (!cached) { 411c3bf86f1SIan Rogers snprintf(path, sizeof(path), "%s/firmware/acpi/tables/NFIT", sysfs); 412c3bf86f1SIan Rogers has_pmem = access(path, F_OK) == 0; 413c3bf86f1SIan Rogers cached = true; 414c3bf86f1SIan Rogers } 415c3bf86f1SIan Rogers return has_pmem ? 1.0 : 0.0; 416c3bf86f1SIan Rogers } 417c3bf86f1SIan Rogers 4181725e9cdSIan Rogers double expr__get_literal(const char *literal, const struct expr_scanner_ctx *ctx) 4193613f6c1SIan Rogers { 420207f7df7SIan Rogers const struct cpu_topology *topology; 421f56ef30aSIan Rogers double result = NAN; 422fdf1e29bSIan Rogers 423f56ef30aSIan Rogers if (!strcmp("#num_cpus", literal)) { 424f56ef30aSIan Rogers result = cpu__max_present_cpu().cpu; 425f56ef30aSIan Rogers goto out; 426f56ef30aSIan Rogers } 427fdf1e29bSIan Rogers 428bc2373a5SKan Liang if (!strcasecmp("#system_tsc_freq", literal)) { 429bc2373a5SKan Liang result = arch_get_tsc_freq(); 430bc2373a5SKan Liang goto out; 431bc2373a5SKan Liang } 432bc2373a5SKan Liang 433fdf1e29bSIan Rogers /* 434fdf1e29bSIan Rogers * Assume that topology strings are consistent, such as CPUs "0-1" 435fdf1e29bSIan Rogers * wouldn't be listed as "0,1", and so after deduplication the number of 436fdf1e29bSIan Rogers * these strings gives an indication of the number of packages, dies, 437fdf1e29bSIan Rogers * etc. 438fdf1e29bSIan Rogers */ 43909b73fe9SIan Rogers if (!strcasecmp("#smt_on", literal)) { 440207f7df7SIan Rogers result = smt_on() ? 1.0 : 0.0; 44109b73fe9SIan Rogers goto out; 44209b73fe9SIan Rogers } 4431725e9cdSIan Rogers if (!strcmp("#core_wide", literal)) { 444207f7df7SIan Rogers result = core_wide(ctx->system_wide, ctx->user_requested_cpu_list) 4451725e9cdSIan Rogers ? 1.0 : 0.0; 4461725e9cdSIan Rogers goto out; 4471725e9cdSIan Rogers } 448f56ef30aSIan Rogers if (!strcmp("#num_packages", literal)) { 449207f7df7SIan Rogers topology = online_topology(); 450f56ef30aSIan Rogers result = topology->package_cpus_lists; 451f56ef30aSIan Rogers goto out; 452f56ef30aSIan Rogers } 453f56ef30aSIan Rogers if (!strcmp("#num_dies", literal)) { 454207f7df7SIan Rogers topology = online_topology(); 455f56ef30aSIan Rogers result = topology->die_cpus_lists; 456f56ef30aSIan Rogers goto out; 457f56ef30aSIan Rogers } 458f56ef30aSIan Rogers if (!strcmp("#num_cores", literal)) { 459207f7df7SIan Rogers topology = online_topology(); 460f56ef30aSIan Rogers result = topology->core_cpus_lists; 461f56ef30aSIan Rogers goto out; 462f56ef30aSIan Rogers } 463acef233bSJing Zhang if (!strcmp("#slots", literal)) { 464acef233bSJing Zhang result = perf_pmu__cpu_slots_per_cycle(); 465acef233bSJing Zhang goto out; 466acef233bSJing Zhang } 467c3bf86f1SIan Rogers if (!strcmp("#has_pmem", literal)) { 468c3bf86f1SIan Rogers result = has_pmem(); 469c3bf86f1SIan Rogers goto out; 470c3bf86f1SIan Rogers } 471fdf1e29bSIan Rogers 4723613f6c1SIan Rogers pr_err("Unrecognized literal '%s'", literal); 473f56ef30aSIan Rogers out: 474f56ef30aSIan Rogers pr_debug2("literal: %s = %f\n", literal, result); 475f56ef30aSIan Rogers return result; 4763613f6c1SIan Rogers } 477