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

1 // SPDX-License-Identifier: GPL-2.0-or-later
9 #define pr_fmt(fmt) "hv-24x7: " fmt
24 #include "hv-24x7.h"
25 #include "hv-24x7-catalog.h"
26 #include "hv-common.h"
42 #include "hv-24x7-domains.h" in domain_is_valid()
56 #include "hv-24x7-domains.h" in is_physical_domain()
78 * chip details through the get-system-parameter rtas call.
94 call_status = rtas_call(rtas_token("ibm,get-system-parameter"), 3, 1, in read_24x7_sys_info()
101 pr_err("Error calling get-system-parameter %d\n", in read_24x7_sys_info()
122 /* Domains for which more than one result element are returned for each event. */
160 * - Think of the hcall as an interface to a 4d array of counters:
161 * - x = domains
162 * - y = indexes in the domain (core, chip, vcpu, node, etc)
163 * - z = offset into the counter space
164 * - w = lpars (guest vms, "logical partitions")
165 * - A single request is: x,y,y_last,z,z_last,w,w_last
166 * - this means we can retrieve a rectangle of counters in y,z for a single x.
168 * - Things to consider (ignoring w):
169 * - input cost_per_request = 16
170 * - output cost_per_result(ys,zs) = 8 + 8 * ys + ys * zs
171 * - limited number of requests per hcall (must fit into 4K bytes)
172 * - 4k = 16 [buffer header] - 16 [request size] * request_count
173 * - 255 requests per hcall
174 * - sometimes it will be more efficient to read extra data and discard
179 * perf stat -e 'hv_24x7/domain=2,offset=8,vcpu=0,lpar=0xffffffff/'
182 /* u3 0-6, one of HV_24X7_PERF_DOMAIN */
208 .name = "format",
213 .name = "events",
218 .name = "event_descs",
223 .name = "event_long_descs",
249 return (H24x7_DATA_BUFFER_SIZE - sizeof(struct hv_24x7_request_buffer)) in max_num_requests()
255 *len = be16_to_cpu(ev->event_name_len) - 2; in event_name()
256 return (char *)ev->remainder; in event_name()
261 unsigned nl = be16_to_cpu(ev->event_name_len); in event_desc()
262 __be16 *desc_len = (__be16 *)(ev->remainder + nl - 2); in event_desc()
264 *len = be16_to_cpu(*desc_len) - 2; in event_desc()
265 return (char *)ev->remainder + nl; in event_desc()
270 unsigned nl = be16_to_cpu(ev->event_name_len); in event_long_desc()
271 __be16 *desc_len_ = (__be16 *)(ev->remainder + nl - 2); in event_long_desc()
273 __be16 *long_desc_len = (__be16 *)(ev->remainder + nl + desc_len - 2); in event_long_desc()
275 *len = be16_to_cpu(*long_desc_len) - 2; in event_long_desc()
276 return (char *)ev->remainder + nl + desc_len; in event_long_desc()
289 * - padding for desc, name, and long/detailed desc is required to be '\0'
293 * Otherwise return the address of the byte just following the event.
300 unsigned nl = be16_to_cpu(ev->event_name_len); in event_end()
303 pr_debug("%s: name length too short: %d", __func__, nl); in event_end()
313 dl_ = (__be16 *)(ev->remainder + nl - 2); in event_end()
328 ldl_ = (__be16 *)(ev->remainder + nl + dl - 2); in event_end()
366 * Each event we find in the catalog, will have a sysfs entry. Format the
367 * data for this sysfs entry based on the event's domain.
375 * the Core events with 'domain=?' so the perf-tool can error check required
389 * perf stat -e hv_24x7/HPM_PCYC,offset=0x20/
396 * - Specifying values for parameters with "=?" is required.
398 * - Specifying (i.e overriding) values for other parameters
401 static char *event_fmt(struct hv_24x7_event_data *event, unsigned domain) in event_fmt() argument
429 be16_to_cpu(event->event_counter_offs) + in event_fmt()
430 be16_to_cpu(event->event_group_record_offs), in event_fmt()
448 return sprintf(buf, "%s\n", (char *)d->var); in device_show_string()
475 static struct attribute *device_str_attr_create_(char *name, char *str) in device_str_attr_create_() argument
482 sysfs_attr_init(&attr->attr.attr); in device_str_attr_create_()
484 attr->var = str; in device_str_attr_create_()
485 attr->attr.attr.name = name; in device_str_attr_create_()
486 attr->attr.attr.mode = 0444; in device_str_attr_create_()
487 attr->attr.show = device_show_string; in device_str_attr_create_()
489 return &attr->attr.attr; in device_str_attr_create_()
493 * Allocate and initialize strings representing event attributes.
501 static struct attribute *device_str_attr_create(char *name, int name_max, in device_str_attr_create() argument
513 n = kasprintf(GFP_KERNEL, "%.*s", name_max, name); in device_str_attr_create()
515 n = kasprintf(GFP_KERNEL, "%.*s__%d", name_max, name, in device_str_attr_create()
533 struct hv_24x7_event_data *event, in event_to_attr() argument
542 pr_warn("catalog event %u has invalid domain %u\n", in event_to_attr()
547 val = event_fmt(event, domain); in event_to_attr()
551 ev_name = event_name(event, &event_name_len); in event_to_attr()
574 static struct attribute *event_to_desc_attr(struct hv_24x7_event_data *event, in event_to_desc_attr() argument
578 char *name = event_name(event, &nl); in event_to_desc_attr() local
579 char *desc = event_desc(event, &dl); in event_to_desc_attr()
585 return device_str_attr_create(name, nl, nonce, desc, dl); in event_to_desc_attr()
589 event_to_long_desc_attr(struct hv_24x7_event_data *event, int nonce) in event_to_long_desc_attr() argument
592 char *name = event_name(event, &nl); in event_to_long_desc_attr() local
593 char *desc = event_long_desc(event, &dl); in event_to_long_desc_attr()
599 return device_str_attr_create(name, nl, nonce, desc, dl); in event_to_long_desc_attr()
603 struct hv_24x7_event_data *event, int nonce) in event_data_to_attrs() argument
605 *attrs = event_to_attr(ix, event, event->domain, nonce); in event_data_to_attrs()
607 return -1; in event_data_to_attrs()
615 const char *name; member
626 return -1; in memord()
641 return -1; in ev_uniq_ord()
645 static int event_uniq_add(struct rb_root *root, const char *name, int nl, in event_uniq_add() argument
648 struct rb_node **new = &(root->rb_node), *parent = NULL; in event_uniq_add()
657 result = ev_uniq_ord(name, nl, domain, it->name, it->nl, in event_uniq_add()
658 it->domain); in event_uniq_add()
662 new = &((*new)->rb_left); in event_uniq_add()
664 new = &((*new)->rb_right); in event_uniq_add()
666 it->ct++; in event_uniq_add()
667 pr_info("found a duplicate event %.*s, ct=%u\n", nl, in event_uniq_add()
668 name, it->ct); in event_uniq_add()
669 return it->ct; in event_uniq_add()
675 return -ENOMEM; in event_uniq_add()
678 .name = name, in event_uniq_add()
685 rb_link_node(&data->node, parent, new); in event_uniq_add()
686 rb_insert_color(&data->node, root); in event_uniq_add()
688 /* data->ct */ in event_uniq_add()
706 * ensure the event structure's sizes are self consistent and don't cause us to
707 * read outside of the event
709 * On success, return the event length in bytes.
710 * Otherwise, return -1 (and print as appropriate).
712 static ssize_t catalog_event_len_validate(struct hv_24x7_event_data *event, in catalog_event_len_validate() argument
722 return -1; in catalog_event_len_validate()
725 pr_devel("catalog event data has %zu bytes of padding after last event\n", in catalog_event_len_validate()
726 event_data_bytes - offset); in catalog_event_len_validate()
727 return -1; in catalog_event_len_validate()
730 if (!event_fixed_portion_is_within(event, end)) { in catalog_event_len_validate()
731 pr_warn("event %zu fixed portion is not within range\n", in catalog_event_len_validate()
733 return -1; in catalog_event_len_validate()
736 ev_len = be16_to_cpu(event->length); in catalog_event_len_validate()
739 pr_info("event %zu has length %zu not divisible by 16: event=%pK\n", in catalog_event_len_validate()
740 event_idx, ev_len, event); in catalog_event_len_validate()
742 ev_end = (__u8 *)event + ev_len; in catalog_event_len_validate()
744 pr_warn("event %zu has .length=%zu, ends after buffer end: ev_end=%pK > end=%pK, offset=%zu\n", in catalog_event_len_validate()
747 return -1; in catalog_event_len_validate()
750 calc_ev_end = event_end(event, end); in catalog_event_len_validate()
752 …pr_warn("event %zu has a calculated length which exceeds buffer length %zu: event=%pK end=%pK, off… in catalog_event_len_validate()
753 event_idx, event_data_bytes, event, end, in catalog_event_len_validate()
755 return -1; in catalog_event_len_validate()
759 pr_warn("event %zu exceeds it's own length: event=%pK, end=%pK, offset=%zu, calc_ev_end=%pK\n", in catalog_event_len_validate()
760 event_idx, event, ev_end, offset, calc_ev_end); in catalog_event_len_validate()
761 return -1; in catalog_event_len_validate()
770 static bool ignore_event(const char *name) in ignore_event() argument
772 return strncmp(name, "RESERVED", 8) == 0; in ignore_event()
793 struct hv_24x7_event_data *event; in create_events_from_catalog() local
798 ret = -ENOMEM; in create_events_from_catalog()
804 ret = -EIO; in create_events_from_catalog()
808 catalog_version_num = be64_to_cpu(page_0->version); in create_events_from_catalog()
809 catalog_page_len = be32_to_cpu(page_0->length); in create_events_from_catalog()
813 ret = -EIO; in create_events_from_catalog()
819 event_entry_count = be16_to_cpu(page_0->event_entry_count); in create_events_from_catalog()
820 event_data_offs = be16_to_cpu(page_0->event_data_offs); in create_events_from_catalog()
821 event_data_len = be16_to_cpu(page_0->event_data_len); in create_events_from_catalog()
829 || (MAX_4K - event_data_offs < event_data_len)) { in create_events_from_catalog()
830 pr_err("invalid event data offs %zu and/or len %zu\n", in create_events_from_catalog()
832 ret = -EIO; in create_events_from_catalog()
837 pr_err("event data %zu-%zu does not fit inside catalog 0-%zu\n", in create_events_from_catalog()
841 ret = -EIO; in create_events_from_catalog()
845 if (SIZE_MAX - 1 < event_entry_count) { in create_events_from_catalog()
847 ret = -EIO; in create_events_from_catalog()
854 * event data can span several pages, events can cross between these in create_events_from_catalog()
859 pr_err("could not allocate event data\n"); in create_events_from_catalog()
860 ret = -ENOMEM; in create_events_from_catalog()
878 pr_err("Failed to get event data in page %zu: rc=%ld\n", in create_events_from_catalog()
880 ret = -EIO; in create_events_from_catalog()
889 for (junk_events = 0, event = event_data, event_idx = 0, attr_max = 0; in create_events_from_catalog()
891 event_idx++, event = (void *)event + ev_len) { in create_events_from_catalog()
892 size_t offset = (void *)event - (void *)event_data; in create_events_from_catalog()
893 char *name; in create_events_from_catalog() local
896 ev_len = catalog_event_len_validate(event, event_idx, in create_events_from_catalog()
903 name = event_name(event, &nl); in create_events_from_catalog()
905 if (ignore_event(name)) { in create_events_from_catalog()
909 if (event->event_group_record_len == 0) { in create_events_from_catalog()
910 pr_devel("invalid event %zu (%.*s): group_record_len == 0, skipping\n", in create_events_from_catalog()
911 event_idx, nl, name); in create_events_from_catalog()
916 if (!catalog_entry_domain_is_valid(event->domain)) { in create_events_from_catalog()
917 pr_info("event %zu (%.*s) has invalid domain %d\n", in create_events_from_catalog()
918 event_idx, nl, name, event->domain); in create_events_from_catalog()
928 …pr_warn("event buffer ended before listed # of events were parsed (got %zu, wanted %zu, junk %zu)\… in create_events_from_catalog()
933 ret = -ENOMEM; in create_events_from_catalog()
940 ret = -ENOMEM; in create_events_from_catalog()
947 ret = -ENOMEM; in create_events_from_catalog()
953 event = event_data, event_idx = 0; in create_events_from_catalog()
955 event_idx++, ev_len = be16_to_cpu(event->length), in create_events_from_catalog()
956 event = (void *)event + ev_len) { in create_events_from_catalog()
957 char *name; in create_events_from_catalog() local
964 if (event->event_group_record_len == 0) in create_events_from_catalog()
966 if (!catalog_entry_domain_is_valid(event->domain)) in create_events_from_catalog()
969 name = event_name(event, &nl); in create_events_from_catalog()
970 if (ignore_event(name)) in create_events_from_catalog()
973 nonce = event_uniq_add(&ev_uniq, name, nl, event->domain); in create_events_from_catalog()
975 event, nonce); in create_events_from_catalog()
977 pr_warn("event %zu (%.*s) creation failure, skipping\n", in create_events_from_catalog()
978 event_idx, nl, name); in create_events_from_catalog()
982 event_descs[desc_ct] = event_to_desc_attr(event, nonce); in create_events_from_catalog()
986 event_to_long_desc_attr(event, nonce); in create_events_from_catalog()
992 pr_info("read %zu catalog entries, created %zu event attrs (%zu failures), %zu descs\n", in create_events_from_catalog()
1038 return -ENOMEM; in catalog_read()
1042 ret = -EIO; in catalog_read()
1046 catalog_version_num = be64_to_cpu(page_0->version); in catalog_read()
1047 catalog_page_len = be32_to_cpu(page_0->length); in catalog_read()
1060 ret = -EIO; in catalog_read()
1065 copy_len = 4096 - offset_in_page; in catalog_read()
1117 return -ENOMEM; \
1120 ret = -EIO; \
1131 (unsigned long long)be64_to_cpu(page_0->version));
1133 (unsigned long long)be32_to_cpu(page_0->length) * 4096);
1166 .name = "interface",
1191 request_buffer->interface_version = interface_version; in init_24x7_request()
1192 /* memset above set request_buffer->num_requests to 0 */ in init_24x7_request()
1216 req = request_buffer->requests; in make_24x7_request()
1218 req->performance_domain, req->data_offset, in make_24x7_request()
1219 req->starting_ix, req->starting_lpar_ix, in make_24x7_request()
1220 ret, ret, result_buffer->detailed_rc, in make_24x7_request()
1221 result_buffer->failing_request_ix); in make_24x7_request()
1222 return -EIO; in make_24x7_request()
1229 * Add the given @event to the next slot in the 24x7 request_buffer.
1235 static int add_event_to_24x7_request(struct perf_event *event, in add_event_to_24x7_request() argument
1243 if (request_buffer->num_requests >= in add_event_to_24x7_request()
1244 max_num_requests(request_buffer->interface_version)) { in add_event_to_24x7_request()
1246 request_buffer->num_requests); in add_event_to_24x7_request()
1247 return -EINVAL; in add_event_to_24x7_request()
1250 switch (event_get_domain(event)) { in add_event_to_24x7_request()
1252 idx = event_get_chip(event); in add_event_to_24x7_request()
1255 idx = event_get_core(event); in add_event_to_24x7_request()
1258 idx = event_get_vcpu(event); in add_event_to_24x7_request()
1261 req_size = H24x7_REQUEST_SIZE(request_buffer->interface_version); in add_event_to_24x7_request()
1263 i = request_buffer->num_requests++; in add_event_to_24x7_request()
1264 req = (void *) request_buffer->requests + i * req_size; in add_event_to_24x7_request()
1266 req->performance_domain = event_get_domain(event); in add_event_to_24x7_request()
1267 req->data_size = cpu_to_be16(8); in add_event_to_24x7_request()
1268 req->data_offset = cpu_to_be32(event_get_offset(event)); in add_event_to_24x7_request()
1269 req->starting_lpar_ix = cpu_to_be16(event_get_lpar(event)); in add_event_to_24x7_request()
1270 req->max_num_lpars = cpu_to_be16(1); in add_event_to_24x7_request()
1271 req->starting_ix = cpu_to_be16(idx); in add_event_to_24x7_request()
1272 req->max_ix = cpu_to_be16(1); in add_event_to_24x7_request()
1274 if (request_buffer->interface_version > 1) { in add_event_to_24x7_request()
1275 if (domain_needs_aggregation(req->performance_domain)) in add_event_to_24x7_request()
1276 req->max_num_thread_groups = -1; in add_event_to_24x7_request()
1277 else if (req->performance_domain != HV_PERF_DOMAIN_PHYS_CHIP) { in add_event_to_24x7_request()
1278 req->starting_thread_group_ix = idx % 2; in add_event_to_24x7_request()
1279 req->max_num_thread_groups = 1; in add_event_to_24x7_request()
1287 * get_count_from_result - get event count from all result elements in result
1289 * If the event corresponding to this result needs aggregation of the result
1292 * @event: Event associated with @res.
1295 * @countp: Output variable containing the event count.
1298 static int get_count_from_result(struct perf_event *event, in get_count_from_result() argument
1303 u16 num_elements = be16_to_cpu(res->num_elements_returned); in get_count_from_result()
1304 u16 data_size = be16_to_cpu(res->result_element_data_size); in get_count_from_result()
1315 res->result_ix); in get_count_from_result()
1318 *next = (struct hv_24x7_result *) res->elements; in get_count_from_result()
1320 return -ENODATA; in get_count_from_result()
1326 * Except when an event needs aggregation, in which case there are more. in get_count_from_result()
1329 !domain_needs_aggregation(event_get_domain(event))) { in get_count_from_result()
1331 res->result_ix, num_elements); in get_count_from_result()
1333 return -EIO; in get_count_from_result()
1338 res->result_ix, data_size); in get_count_from_result()
1340 return -ENOTSUPP; in get_count_from_result()
1343 if (resb->interface_version == 1) in get_count_from_result()
1351 for (i = count = 0, element_data = res->elements + data_offset; in get_count_from_result()
1360 *next = element_data - data_offset; in get_count_from_result()
1365 static int single_24x7_request(struct perf_event *event, u64 *count) in single_24x7_request() argument
1379 ret = add_event_to_24x7_request(event, request_buffer); in single_24x7_request()
1388 ret = get_count_from_result(event, result_buffer, in single_24x7_request()
1389 result_buffer->results, count, NULL); in single_24x7_request()
1398 static int h_24x7_event_init(struct perf_event *event) in h_24x7_event_init() argument
1405 /* Not our event */ in h_24x7_event_init()
1406 if (event->attr.type != event->pmu->type) in h_24x7_event_init()
1407 return -ENOENT; in h_24x7_event_init()
1410 if (event_get_reserved1(event) || in h_24x7_event_init()
1411 event_get_reserved2(event) || in h_24x7_event_init()
1412 event_get_reserved3(event)) { in h_24x7_event_init()
1414 event->attr.config, in h_24x7_event_init()
1415 event_get_reserved1(event), in h_24x7_event_init()
1416 event->attr.config1, in h_24x7_event_init()
1417 event_get_reserved2(event), in h_24x7_event_init()
1418 event->attr.config2, in h_24x7_event_init()
1419 event_get_reserved3(event)); in h_24x7_event_init()
1420 return -EINVAL; in h_24x7_event_init()
1424 if (has_branch_stack(event)) in h_24x7_event_init()
1425 return -EOPNOTSUPP; in h_24x7_event_init()
1428 if (event_get_offset(event) % 8) { in h_24x7_event_init()
1430 return -EINVAL; in h_24x7_event_init()
1433 domain = event_get_domain(event); in h_24x7_event_init()
1436 return -EINVAL; in h_24x7_event_init()
1442 return -EIO; in h_24x7_event_init()
1447 (event_get_lpar(event) != event_get_lpar_max()))) { in h_24x7_event_init()
1450 event_get_lpar(event)); in h_24x7_event_init()
1451 return -EACCES; in h_24x7_event_init()
1454 /* Get the initial value of the counter for this event */ in h_24x7_event_init()
1455 if (single_24x7_request(event, &ct)) { in h_24x7_event_init()
1457 return -EIO; in h_24x7_event_init()
1459 (void)local64_xchg(&event->hw.prev_count, ct); in h_24x7_event_init()
1464 static u64 h_24x7_get_value(struct perf_event *event) in h_24x7_get_value() argument
1468 if (single_24x7_request(event, &ct)) in h_24x7_get_value()
1469 /* We checked this in event init, shouldn't fail here... */ in h_24x7_get_value()
1475 static void update_event_count(struct perf_event *event, u64 now) in update_event_count() argument
1479 prev = local64_xchg(&event->hw.prev_count, now); in update_event_count()
1480 local64_add(now - prev, &event->count); in update_event_count()
1483 static void h_24x7_event_read(struct perf_event *event) in h_24x7_event_read() argument
1508 ret = add_event_to_24x7_request(event, request_buffer); in h_24x7_event_read()
1513 * Associate the event with the HCALL request index, in h_24x7_event_read()
1514 * so ->commit_txn() can quickly find/update count. in h_24x7_event_read()
1516 i = request_buffer->num_requests - 1; in h_24x7_event_read()
1519 h24x7hw->events[i] = event; in h_24x7_event_read()
1525 now = h_24x7_get_value(event); in h_24x7_event_read()
1526 update_event_count(event, now); in h_24x7_event_read()
1530 static void h_24x7_event_start(struct perf_event *event, int flags) in h_24x7_event_start() argument
1533 local64_set(&event->hw.prev_count, h_24x7_get_value(event)); in h_24x7_event_start()
1536 static void h_24x7_event_stop(struct perf_event *event, int flags) in h_24x7_event_stop() argument
1538 h_24x7_event_read(event); in h_24x7_event_stop()
1541 static int h_24x7_event_add(struct perf_event *event, int flags) in h_24x7_event_add() argument
1544 h_24x7_event_start(event, flags); in h_24x7_event_add()
1590 * and dont need/support ADD transactions. Clear ->txn_flags but otherwise
1595 * the event counts.
1626 /* Go through results in the result buffer to update event counts. */ in h_24x7_event_commit_txn()
1627 for (i = 0, res = result_buffer->results; in h_24x7_event_commit_txn()
1628 i < result_buffer->num_results; i++, res = next_res) { in h_24x7_event_commit_txn()
1629 struct perf_event *event = h24x7hw->events[res->result_ix]; in h_24x7_event_commit_txn() local
1631 ret = get_count_from_result(event, result_buffer, res, &count, in h_24x7_event_commit_txn()
1636 update_event_count(event, count); in h_24x7_event_commit_txn()
1664 .name = "hv_24x7",
1699 return -1; in ppc_hv_24x7_cpu_offline()
1725 return -ENODEV; in hv_24x7_init()
1726 } else if (!cur_cpu_spec->oprofile_cpu_type) in hv_24x7_init()
1727 return -ENODEV; in hv_24x7_init()
1730 if (!strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power8")) in hv_24x7_init()
1744 return -ENODEV; in hv_24x7_init()
1747 hv_page_cache = kmem_cache_create("hv-page-4096", 4096, 4096, 0, NULL); in hv_24x7_init()
1749 return -ENOMEM; in hv_24x7_init()
1766 r = perf_pmu_register(&h_24x7_pmu, h_24x7_pmu.name, -1); in hv_24x7_init()