Lines Matching +full:event +full:- +full:name

1 // SPDX-License-Identifier: GPL-2.0-or-later
9 #define pr_fmt(fmt) "hv-24x7: " fmt
21 #include <asm/papr-sysparm.h>
25 #include "hv-24x7.h"
26 #include "hv-24x7-catalog.h"
27 #include "hv-common.h"
43 #include "hv-24x7-domains.h" in domain_is_valid()
57 #include "hv-24x7-domains.h" in is_physical_domain()
77 * chip details through the get-system-parameter rtas call.
96 int ntypes = be16_to_cpup((__be16 *)&buf->val[0]); in read_24x7_sys_info()
97 int len = be16_to_cpu(buf->len); in read_24x7_sys_info()
100 phys_sockets = be16_to_cpup((__be16 *)&buf->val[2]); in read_24x7_sys_info()
101 phys_chipspersocket = be16_to_cpup((__be16 *)&buf->val[4]); in read_24x7_sys_info()
102 phys_coresperchip = be16_to_cpup((__be16 *)&buf->val[6]); in read_24x7_sys_info()
109 /* Domains for which more than one result element are returned for each event. */
147 * - Think of the hcall as an interface to a 4d array of counters:
148 * - x = domains
149 * - y = indexes in the domain (core, chip, vcpu, node, etc)
150 * - z = offset into the counter space
151 * - w = lpars (guest vms, "logical partitions")
152 * - A single request is: x,y,y_last,z,z_last,w,w_last
153 * - this means we can retrieve a rectangle of counters in y,z for a single x.
155 * - Things to consider (ignoring w):
156 * - input cost_per_request = 16
157 * - output cost_per_result(ys,zs) = 8 + 8 * ys + ys * zs
158 * - limited number of requests per hcall (must fit into 4K bytes)
159 * - 4k = 16 [buffer header] - 16 [request size] * request_count
160 * - 255 requests per hcall
161 * - sometimes it will be more efficient to read extra data and discard
166 * perf stat -e 'hv_24x7/domain=2,offset=8,vcpu=0,lpar=0xffffffff/'
169 /* u3 0-6, one of HV_24X7_PERF_DOMAIN */
195 .name = "format",
200 .name = "events",
205 .name = "event_descs",
210 .name = "event_long_descs",
236 return (H24x7_DATA_BUFFER_SIZE - sizeof(struct hv_24x7_request_buffer)) in max_num_requests()
242 *len = be16_to_cpu(ev->event_name_len) - 2; in event_name()
243 return (char *)ev->remainder; in event_name()
248 unsigned int nl = be16_to_cpu(ev->event_name_len); in event_desc()
249 __be16 *desc_len = (__be16 *)(ev->remainder + nl - 2); in event_desc()
251 *len = be16_to_cpu(*desc_len) - 2; in event_desc()
252 return (char *)ev->remainder + nl; in event_desc()
257 unsigned int nl = be16_to_cpu(ev->event_name_len); in event_long_desc()
258 __be16 *desc_len_ = (__be16 *)(ev->remainder + nl - 2); in event_long_desc()
260 __be16 *long_desc_len = (__be16 *)(ev->remainder + nl + desc_len - 2); in event_long_desc()
262 *len = be16_to_cpu(*long_desc_len) - 2; in event_long_desc()
263 return (char *)ev->remainder + nl + desc_len; in event_long_desc()
276 * - padding for desc, name, and long/detailed desc is required to be '\0'
280 * Otherwise return the address of the byte just following the event.
287 unsigned int nl = be16_to_cpu(ev->event_name_len); in event_end()
290 pr_debug("%s: name length too short: %d", __func__, nl); in event_end()
300 dl_ = (__be16 *)(ev->remainder + nl - 2); in event_end()
315 ldl_ = (__be16 *)(ev->remainder + nl + dl - 2); in event_end()
353 * Each event we find in the catalog, will have a sysfs entry. Format the
354 * data for this sysfs entry based on the event's domain.
362 * the Core events with 'domain=?' so the perf-tool can error check required
376 * perf stat -e hv_24x7/HPM_PCYC,offset=0x20/
383 * - Specifying values for parameters with "=?" is required.
385 * - Specifying (i.e overriding) values for other parameters
388 static char *event_fmt(struct hv_24x7_event_data *event, unsigned int domain) in event_fmt() argument
416 be16_to_cpu(event->event_counter_offs) + in event_fmt()
417 be16_to_cpu(event->event_group_record_offs), in event_fmt()
452 static struct attribute *device_str_attr_create_(char *name, char *str) in device_str_attr_create_() argument
459 sysfs_attr_init(&attr->attr.attr); in device_str_attr_create_()
461 attr->var = str; in device_str_attr_create_()
462 attr->attr.attr.name = name; in device_str_attr_create_()
463 attr->attr.attr.mode = 0444; in device_str_attr_create_()
464 attr->attr.show = device_show_string; in device_str_attr_create_()
466 return &attr->attr.attr; in device_str_attr_create_()
470 * Allocate and initialize strings representing event attributes.
478 static struct attribute *device_str_attr_create(char *name, int name_max, in device_str_attr_create() argument
490 n = kasprintf(GFP_KERNEL, "%.*s", name_max, name); in device_str_attr_create()
492 n = kasprintf(GFP_KERNEL, "%.*s__%d", name_max, name, in device_str_attr_create()
510 struct hv_24x7_event_data *event, in event_to_attr() argument
519 pr_warn("catalog event %u has invalid domain %u\n", in event_to_attr()
524 val = event_fmt(event, domain); in event_to_attr()
528 ev_name = event_name(event, &event_name_len); in event_to_attr()
551 static struct attribute *event_to_desc_attr(struct hv_24x7_event_data *event, in event_to_desc_attr() argument
555 char *name = event_name(event, &nl); in event_to_desc_attr() local
556 char *desc = event_desc(event, &dl); in event_to_desc_attr()
562 return device_str_attr_create(name, nl, nonce, desc, dl); in event_to_desc_attr()
566 event_to_long_desc_attr(struct hv_24x7_event_data *event, int nonce) in event_to_long_desc_attr() argument
569 char *name = event_name(event, &nl); in event_to_long_desc_attr() local
570 char *desc = event_long_desc(event, &dl); in event_to_long_desc_attr()
576 return device_str_attr_create(name, nl, nonce, desc, dl); in event_to_long_desc_attr()
580 struct hv_24x7_event_data *event, int nonce) in event_data_to_attrs() argument
582 *attrs = event_to_attr(ix, event, event->domain, nonce); in event_data_to_attrs()
584 return -1; in event_data_to_attrs()
592 const char *name; member
603 return -1; in memord()
618 return -1; in ev_uniq_ord()
622 static int event_uniq_add(struct rb_root *root, const char *name, int nl, in event_uniq_add() argument
625 struct rb_node **new = &(root->rb_node), *parent = NULL; in event_uniq_add()
634 result = ev_uniq_ord(name, nl, domain, it->name, it->nl, in event_uniq_add()
635 it->domain); in event_uniq_add()
639 new = &((*new)->rb_left); in event_uniq_add()
641 new = &((*new)->rb_right); in event_uniq_add()
643 it->ct++; in event_uniq_add()
644 pr_info("found a duplicate event %.*s, ct=%u\n", nl, in event_uniq_add()
645 name, it->ct); in event_uniq_add()
646 return it->ct; in event_uniq_add()
652 return -ENOMEM; in event_uniq_add()
655 .name = name, in event_uniq_add()
662 rb_link_node(&data->node, parent, new); in event_uniq_add()
663 rb_insert_color(&data->node, root); in event_uniq_add()
665 /* data->ct */ in event_uniq_add()
683 * ensure the event structure's sizes are self consistent and don't cause us to
684 * read outside of the event
686 * On success, return the event length in bytes.
687 * Otherwise, return -1 (and print as appropriate).
689 static ssize_t catalog_event_len_validate(struct hv_24x7_event_data *event, in catalog_event_len_validate() argument
699 return -1; in catalog_event_len_validate()
702 pr_devel("catalog event data has %zu bytes of padding after last event\n", in catalog_event_len_validate()
703 event_data_bytes - offset); in catalog_event_len_validate()
704 return -1; in catalog_event_len_validate()
707 if (!event_fixed_portion_is_within(event, end)) { in catalog_event_len_validate()
708 pr_warn("event %zu fixed portion is not within range\n", in catalog_event_len_validate()
710 return -1; in catalog_event_len_validate()
713 ev_len = be16_to_cpu(event->length); in catalog_event_len_validate()
716 pr_info("event %zu has length %zu not divisible by 16: event=%pK\n", in catalog_event_len_validate()
717 event_idx, ev_len, event); in catalog_event_len_validate()
719 ev_end = (__u8 *)event + ev_len; in catalog_event_len_validate()
721 pr_warn("event %zu has .length=%zu, ends after buffer end: ev_end=%pK > end=%pK, offset=%zu\n", in catalog_event_len_validate()
724 return -1; in catalog_event_len_validate()
727 calc_ev_end = event_end(event, end); in catalog_event_len_validate()
729 …pr_warn("event %zu has a calculated length which exceeds buffer length %zu: event=%pK end=%pK, off… in catalog_event_len_validate()
730 event_idx, event_data_bytes, event, end, in catalog_event_len_validate()
732 return -1; in catalog_event_len_validate()
736 pr_warn("event %zu exceeds its own length: event=%pK, end=%pK, offset=%zu, calc_ev_end=%pK\n", in catalog_event_len_validate()
737 event_idx, event, ev_end, offset, calc_ev_end); in catalog_event_len_validate()
738 return -1; in catalog_event_len_validate()
747 static bool ignore_event(const char *name) in ignore_event() argument
749 return strncmp(name, "RESERVED", 8) == 0; in ignore_event()
770 struct hv_24x7_event_data *event; in create_events_from_catalog() local
775 ret = -ENOMEM; in create_events_from_catalog()
781 ret = -EIO; in create_events_from_catalog()
785 catalog_version_num = be64_to_cpu(page_0->version); in create_events_from_catalog()
786 catalog_page_len = be32_to_cpu(page_0->length); in create_events_from_catalog()
790 ret = -EIO; in create_events_from_catalog()
796 event_entry_count = be16_to_cpu(page_0->event_entry_count); in create_events_from_catalog()
797 event_data_offs = be16_to_cpu(page_0->event_data_offs); in create_events_from_catalog()
798 event_data_len = be16_to_cpu(page_0->event_data_len); in create_events_from_catalog()
806 || (MAX_4K - event_data_offs < event_data_len)) { in create_events_from_catalog()
807 pr_err("invalid event data offs %zu and/or len %zu\n", in create_events_from_catalog()
809 ret = -EIO; in create_events_from_catalog()
814 pr_err("event data %zu-%zu does not fit inside catalog 0-%zu\n", in create_events_from_catalog()
818 ret = -EIO; in create_events_from_catalog()
822 if (SIZE_MAX - 1 < event_entry_count) { in create_events_from_catalog()
824 ret = -EIO; in create_events_from_catalog()
831 * event data can span several pages, events can cross between these in create_events_from_catalog()
836 pr_err("could not allocate event data\n"); in create_events_from_catalog()
837 ret = -ENOMEM; in create_events_from_catalog()
855 pr_err("Failed to get event data in page %zu: rc=%ld\n", in create_events_from_catalog()
857 ret = -EIO; in create_events_from_catalog()
866 for (junk_events = 0, event = event_data, event_idx = 0, attr_max = 0; in create_events_from_catalog()
868 event_idx++, event = (void *)event + ev_len) { in create_events_from_catalog()
869 size_t offset = (void *)event - (void *)event_data; in create_events_from_catalog()
870 char *name; in create_events_from_catalog() local
873 ev_len = catalog_event_len_validate(event, event_idx, in create_events_from_catalog()
880 name = event_name(event, &nl); in create_events_from_catalog()
882 if (ignore_event(name)) { in create_events_from_catalog()
886 if (event->event_group_record_len == 0) { in create_events_from_catalog()
887 pr_devel("invalid event %zu (%.*s): group_record_len == 0, skipping\n", in create_events_from_catalog()
888 event_idx, nl, name); in create_events_from_catalog()
893 if (!catalog_entry_domain_is_valid(event->domain)) { in create_events_from_catalog()
894 pr_info("event %zu (%.*s) has invalid domain %d\n", in create_events_from_catalog()
895 event_idx, nl, name, event->domain); in create_events_from_catalog()
905 …pr_warn("event buffer ended before listed # of events were parsed (got %zu, wanted %zu, junk %zu)\… in create_events_from_catalog()
910 ret = -ENOMEM; in create_events_from_catalog()
917 ret = -ENOMEM; in create_events_from_catalog()
924 ret = -ENOMEM; in create_events_from_catalog()
930 event = event_data, event_idx = 0; in create_events_from_catalog()
932 event_idx++, ev_len = be16_to_cpu(event->length), in create_events_from_catalog()
933 event = (void *)event + ev_len) { in create_events_from_catalog()
934 char *name; in create_events_from_catalog() local
941 if (event->event_group_record_len == 0) in create_events_from_catalog()
943 if (!catalog_entry_domain_is_valid(event->domain)) in create_events_from_catalog()
946 name = event_name(event, &nl); in create_events_from_catalog()
947 if (ignore_event(name)) in create_events_from_catalog()
950 nonce = event_uniq_add(&ev_uniq, name, nl, event->domain); in create_events_from_catalog()
952 event, nonce); in create_events_from_catalog()
954 pr_warn("event %zu (%.*s) creation failure, skipping\n", in create_events_from_catalog()
955 event_idx, nl, name); in create_events_from_catalog()
959 event_descs[desc_ct] = event_to_desc_attr(event, nonce); in create_events_from_catalog()
963 event_to_long_desc_attr(event, nonce); in create_events_from_catalog()
969 pr_info("read %zu catalog entries, created %zu event attrs (%zu failures), %zu descs\n", in create_events_from_catalog()
1015 return -ENOMEM; in catalog_read()
1019 ret = -EIO; in catalog_read()
1023 catalog_version_num = be64_to_cpu(page_0->version); in catalog_read()
1024 catalog_page_len = be32_to_cpu(page_0->length); in catalog_read()
1037 ret = -EIO; in catalog_read()
1042 copy_len = 4096 - offset_in_page; in catalog_read()
1094 return -ENOMEM; \
1097 ret = -EIO; \
1108 (unsigned long long)be64_to_cpu(page_0->version));
1110 (unsigned long long)be32_to_cpu(page_0->length) * 4096);
1143 .name = "interface",
1168 request_buffer->interface_version = interface_version; in init_24x7_request()
1169 /* memset above set request_buffer->num_requests to 0 */ in init_24x7_request()
1193 req = request_buffer->requests; in make_24x7_request()
1195 req->performance_domain, req->data_offset, in make_24x7_request()
1196 req->starting_ix, req->starting_lpar_ix, in make_24x7_request()
1197 ret, ret, result_buffer->detailed_rc, in make_24x7_request()
1198 result_buffer->failing_request_ix); in make_24x7_request()
1199 return -EIO; in make_24x7_request()
1206 * Add the given @event to the next slot in the 24x7 request_buffer.
1212 static int add_event_to_24x7_request(struct perf_event *event, in add_event_to_24x7_request() argument
1220 if (request_buffer->num_requests >= in add_event_to_24x7_request()
1221 max_num_requests(request_buffer->interface_version)) { in add_event_to_24x7_request()
1223 request_buffer->num_requests); in add_event_to_24x7_request()
1224 return -EINVAL; in add_event_to_24x7_request()
1227 switch (event_get_domain(event)) { in add_event_to_24x7_request()
1229 idx = event_get_chip(event); in add_event_to_24x7_request()
1232 idx = event_get_core(event); in add_event_to_24x7_request()
1235 idx = event_get_vcpu(event); in add_event_to_24x7_request()
1238 req_size = H24x7_REQUEST_SIZE(request_buffer->interface_version); in add_event_to_24x7_request()
1240 i = request_buffer->num_requests++; in add_event_to_24x7_request()
1241 req = (void *) request_buffer->requests + i * req_size; in add_event_to_24x7_request()
1243 req->performance_domain = event_get_domain(event); in add_event_to_24x7_request()
1244 req->data_size = cpu_to_be16(8); in add_event_to_24x7_request()
1245 req->data_offset = cpu_to_be32(event_get_offset(event)); in add_event_to_24x7_request()
1246 req->starting_lpar_ix = cpu_to_be16(event_get_lpar(event)); in add_event_to_24x7_request()
1247 req->max_num_lpars = cpu_to_be16(1); in add_event_to_24x7_request()
1248 req->starting_ix = cpu_to_be16(idx); in add_event_to_24x7_request()
1249 req->max_ix = cpu_to_be16(1); in add_event_to_24x7_request()
1251 if (request_buffer->interface_version > 1) { in add_event_to_24x7_request()
1252 if (domain_needs_aggregation(req->performance_domain)) in add_event_to_24x7_request()
1253 req->max_num_thread_groups = -1; in add_event_to_24x7_request()
1254 else if (req->performance_domain != HV_PERF_DOMAIN_PHYS_CHIP) { in add_event_to_24x7_request()
1255 req->starting_thread_group_ix = idx % 2; in add_event_to_24x7_request()
1256 req->max_num_thread_groups = 1; in add_event_to_24x7_request()
1264 * get_count_from_result - get event count from all result elements in result
1266 * If the event corresponding to this result needs aggregation of the result
1269 * @event: Event associated with @res.
1272 * @countp: Output variable containing the event count.
1275 static int get_count_from_result(struct perf_event *event, in get_count_from_result() argument
1280 u16 num_elements = be16_to_cpu(res->num_elements_returned); in get_count_from_result()
1281 u16 data_size = be16_to_cpu(res->result_element_data_size); in get_count_from_result()
1292 res->result_ix); in get_count_from_result()
1295 *next = (struct hv_24x7_result *) res->elements; in get_count_from_result()
1297 return -ENODATA; in get_count_from_result()
1303 * Except when an event needs aggregation, in which case there are more. in get_count_from_result()
1306 !domain_needs_aggregation(event_get_domain(event))) { in get_count_from_result()
1308 res->result_ix, num_elements); in get_count_from_result()
1310 return -EIO; in get_count_from_result()
1315 res->result_ix, data_size); in get_count_from_result()
1317 return -ENOTSUPP; in get_count_from_result()
1320 if (resb->interface_version == 1) in get_count_from_result()
1328 for (i = count = 0, element_data = res->elements + data_offset; in get_count_from_result()
1337 *next = element_data - data_offset; in get_count_from_result()
1342 static int single_24x7_request(struct perf_event *event, u64 *count) in single_24x7_request() argument
1356 ret = add_event_to_24x7_request(event, request_buffer); in single_24x7_request()
1365 ret = get_count_from_result(event, result_buffer, in single_24x7_request()
1366 result_buffer->results, count, NULL); in single_24x7_request()
1375 static int h_24x7_event_init(struct perf_event *event) in h_24x7_event_init() argument
1382 /* Not our event */ in h_24x7_event_init()
1383 if (event->attr.type != event->pmu->type) in h_24x7_event_init()
1384 return -ENOENT; in h_24x7_event_init()
1387 if (event_get_reserved1(event) || in h_24x7_event_init()
1388 event_get_reserved2(event) || in h_24x7_event_init()
1389 event_get_reserved3(event)) { in h_24x7_event_init()
1391 event->attr.config, in h_24x7_event_init()
1392 event_get_reserved1(event), in h_24x7_event_init()
1393 event->attr.config1, in h_24x7_event_init()
1394 event_get_reserved2(event), in h_24x7_event_init()
1395 event->attr.config2, in h_24x7_event_init()
1396 event_get_reserved3(event)); in h_24x7_event_init()
1397 return -EINVAL; in h_24x7_event_init()
1401 if (has_branch_stack(event)) in h_24x7_event_init()
1402 return -EOPNOTSUPP; in h_24x7_event_init()
1405 if (event_get_offset(event) % 8) { in h_24x7_event_init()
1407 return -EINVAL; in h_24x7_event_init()
1410 domain = event_get_domain(event); in h_24x7_event_init()
1413 return -EINVAL; in h_24x7_event_init()
1419 return -EIO; in h_24x7_event_init()
1424 (event_get_lpar(event) != event_get_lpar_max()))) { in h_24x7_event_init()
1427 event_get_lpar(event)); in h_24x7_event_init()
1428 return -EACCES; in h_24x7_event_init()
1431 /* Get the initial value of the counter for this event */ in h_24x7_event_init()
1432 if (single_24x7_request(event, &ct)) { in h_24x7_event_init()
1434 return -EIO; in h_24x7_event_init()
1436 (void)local64_xchg(&event->hw.prev_count, ct); in h_24x7_event_init()
1441 static u64 h_24x7_get_value(struct perf_event *event) in h_24x7_get_value() argument
1445 if (single_24x7_request(event, &ct)) in h_24x7_get_value()
1446 /* We checked this in event init, shouldn't fail here... */ in h_24x7_get_value()
1452 static void update_event_count(struct perf_event *event, u64 now) in update_event_count() argument
1456 prev = local64_xchg(&event->hw.prev_count, now); in update_event_count()
1457 local64_add(now - prev, &event->count); in update_event_count()
1460 static void h_24x7_event_read(struct perf_event *event) in h_24x7_event_read() argument
1485 ret = add_event_to_24x7_request(event, request_buffer); in h_24x7_event_read()
1490 * Associate the event with the HCALL request index, in h_24x7_event_read()
1491 * so ->commit_txn() can quickly find/update count. in h_24x7_event_read()
1493 i = request_buffer->num_requests - 1; in h_24x7_event_read()
1496 h24x7hw->events[i] = event; in h_24x7_event_read()
1502 now = h_24x7_get_value(event); in h_24x7_event_read()
1503 update_event_count(event, now); in h_24x7_event_read()
1507 static void h_24x7_event_start(struct perf_event *event, int flags) in h_24x7_event_start() argument
1510 local64_set(&event->hw.prev_count, h_24x7_get_value(event)); in h_24x7_event_start()
1513 static void h_24x7_event_stop(struct perf_event *event, int flags) in h_24x7_event_stop() argument
1515 h_24x7_event_read(event); in h_24x7_event_stop()
1518 static int h_24x7_event_add(struct perf_event *event, int flags) in h_24x7_event_add() argument
1521 h_24x7_event_start(event, flags); in h_24x7_event_add()
1567 * and dont need/support ADD transactions. Clear ->txn_flags but otherwise
1572 * the event counts.
1603 /* Go through results in the result buffer to update event counts. */ in h_24x7_event_commit_txn()
1604 for (i = 0, res = result_buffer->results; in h_24x7_event_commit_txn()
1605 i < result_buffer->num_results; i++, res = next_res) { in h_24x7_event_commit_txn()
1606 struct perf_event *event = h24x7hw->events[res->result_ix]; in h_24x7_event_commit_txn() local
1608 ret = get_count_from_result(event, result_buffer, res, &count, in h_24x7_event_commit_txn()
1613 update_event_count(event, count); in h_24x7_event_commit_txn()
1641 .name = "hv_24x7",
1676 return -1; in ppc_hv_24x7_cpu_offline()
1703 return -ENODEV; in hv_24x7_init()
1722 return -ENODEV; in hv_24x7_init()
1725 hv_page_cache = kmem_cache_create("hv-page-4096", 4096, 4096, 0, NULL); in hv_24x7_init()
1727 return -ENOMEM; in hv_24x7_init()
1744 r = perf_pmu_register(&h_24x7_pmu, h_24x7_pmu.name, -1); in hv_24x7_init()