xref: /openbmc/linux/tools/perf/util/expr.c (revision a77f8184)
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