return;
/* Otherwise replace it */
- pmu_format_value(format->bits, val, vp, /*zero=*/true);
+ perf_pmu__format_pack(format->bits, val, vp, /*zero=*/true);
+}
+
+
+int evsel__get_config_val(const struct evsel *evsel, const char *config_name,
+ u64 *val)
+{
+ struct perf_pmu_format *format = pmu_find_format(&evsel->pmu->format, config_name);
+
+ if (!format || bitmap_empty(format->bits, PERF_PMU_FORMAT_BITS)) {
+ pr_err("Unknown/empty format name: %s\n", config_name);
+ *val = 0;
+ return -EINVAL;
+ }
+
+ switch (format->value) {
+ case PERF_PMU_FORMAT_VALUE_CONFIG:
+ *val = perf_pmu__format_unpack(format->bits,
+ evsel->core.attr.config);
+ return 0;
+ case PERF_PMU_FORMAT_VALUE_CONFIG1:
+ *val = perf_pmu__format_unpack(format->bits,
+ evsel->core.attr.config1);
+ return 0;
+ case PERF_PMU_FORMAT_VALUE_CONFIG2:
+ *val = perf_pmu__format_unpack(format->bits,
+ evsel->core.attr.config2);
+ return 0;
+ case PERF_PMU_FORMAT_VALUE_CONFIG3:
+ *val = perf_pmu__format_unpack(format->bits,
+ evsel->core.attr.config3);
+ return 0;
+ case PERF_PMU_FORMAT_VALUE_CONFIG4:
+ *val = perf_pmu__format_unpack(format->bits,
+ evsel->core.attr.config4);
+ return 0;
+ default:
+ pr_err("Unknown format value: %d\n", format->value);
+ *val = 0;
+ return -EINVAL;
+ }
}
void __weak arch_evsel__set_sample_weight(struct evsel *evsel)
}
}
+/*
+ * Unpacks a raw config[n] value using the sparse bitfield that defines a
+ * format attr. For example "config1:1,6-7,44" defines a 4 bit value across non
+ * contiguous bits and this function returns those 4 bits as a value.
+ */
+u64 perf_pmu__format_unpack(unsigned long *format, u64 config_val)
+{
+ int val_bit = 0;
+ u64 res = 0;
+ int fmt_bit;
+
+ for_each_set_bit(fmt_bit, format, PERF_PMU_FORMAT_BITS) {
+ if (config_val & (1ULL << fmt_bit))
+ res |= BIT_ULL(val_bit);
+
+ val_bit++;
+ }
+ return res;
+}
+
struct perf_pmu_format *pmu_find_format(const struct list_head *formats,
const char *name)
{
* Sets value based on the format definition (format parameter)
* and unformatted value (value parameter).
*/
-void pmu_format_value(unsigned long *format, __u64 value, __u64 *v, bool zero)
+void perf_pmu__format_pack(unsigned long *format, __u64 value, __u64 *v,
+ bool zero)
{
unsigned long fbit, vbit;
switch (term->type_term) {
case PARSE_EVENTS__TERM_TYPE_CONFIG:
assert(term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
- pmu_format_value(bits, term->val.num, &attr->config, zero);
+ perf_pmu__format_pack(bits, term->val.num, &attr->config, zero);
break;
case PARSE_EVENTS__TERM_TYPE_CONFIG1:
assert(term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
- pmu_format_value(bits, term->val.num, &attr->config1, zero);
+ perf_pmu__format_pack(bits, term->val.num, &attr->config1, zero);
break;
case PARSE_EVENTS__TERM_TYPE_CONFIG2:
assert(term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
- pmu_format_value(bits, term->val.num, &attr->config2, zero);
+ perf_pmu__format_pack(bits, term->val.num, &attr->config2, zero);
break;
case PARSE_EVENTS__TERM_TYPE_CONFIG3:
assert(term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
- pmu_format_value(bits, term->val.num, &attr->config3, zero);
+ perf_pmu__format_pack(bits, term->val.num, &attr->config3, zero);
break;
case PARSE_EVENTS__TERM_TYPE_CONFIG4:
assert(term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
- pmu_format_value(bits, term->val.num, &attr->config4, zero);
+ perf_pmu__format_pack(bits, term->val.num, &attr->config4, zero);
break;
case PARSE_EVENTS__TERM_TYPE_LEGACY_HARDWARE_CONFIG:
assert(term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
*/
}
- pmu_format_value(format->bits, val, vp, zero);
+ perf_pmu__format_pack(format->bits, val, vp, zero);
return 0;
}
u64 *alternate_hw_config, struct parse_events_error *err);
int perf_pmu__find_event(struct perf_pmu *pmu, const char *event, void *state, pmu_event_callback cb);
-void pmu_format_value(unsigned long *format, __u64 value, __u64 *v, bool zero);
+void perf_pmu__format_pack(unsigned long *format, __u64 value, __u64 *v,
+ bool zero);
struct perf_pmu_format *pmu_find_format(const struct list_head *formats,
const char *name);
void perf_pmu_format__set_value(void *format, int config, unsigned long *bits);
bool perf_pmu__has_format(const struct perf_pmu *pmu, const char *name);
int perf_pmu__for_each_format(struct perf_pmu *pmu, void *state, pmu_format_callback cb);
+u64 perf_pmu__format_unpack(unsigned long *format, u64 config_val);
bool is_pmu_core(const char *name);
bool perf_pmu__supports_legacy_cache(const struct perf_pmu *pmu);