0001
0002
0003
0004
0005
0006
0007
0008
0009 #define pr_fmt(fmt) "hv-24x7: " fmt
0010
0011 #include <linux/perf_event.h>
0012 #include <linux/rbtree.h>
0013 #include <linux/module.h>
0014 #include <linux/slab.h>
0015 #include <linux/vmalloc.h>
0016
0017 #include <asm/cputhreads.h>
0018 #include <asm/firmware.h>
0019 #include <asm/hvcall.h>
0020 #include <asm/io.h>
0021 #include <linux/byteorder/generic.h>
0022
0023 #include <asm/rtas.h>
0024 #include "hv-24x7.h"
0025 #include "hv-24x7-catalog.h"
0026 #include "hv-common.h"
0027
0028
0029 static int interface_version;
0030
0031
0032 static bool aggregate_result_elements;
0033
0034 static cpumask_t hv_24x7_cpumask;
0035
0036 static bool domain_is_valid(unsigned int domain)
0037 {
0038 switch (domain) {
0039 #define DOMAIN(n, v, x, c) \
0040 case HV_PERF_DOMAIN_##n: \
0041
0042 #include "hv-24x7-domains.h"
0043 #undef DOMAIN
0044 return true;
0045 default:
0046 return false;
0047 }
0048 }
0049
0050 static bool is_physical_domain(unsigned int domain)
0051 {
0052 switch (domain) {
0053 #define DOMAIN(n, v, x, c) \
0054 case HV_PERF_DOMAIN_##n: \
0055 return c;
0056 #include "hv-24x7-domains.h"
0057 #undef DOMAIN
0058 default:
0059 return false;
0060 }
0061 }
0062
0063
0064
0065
0066
0067
0068
0069 #define PROCESSOR_MODULE_INFO 43
0070
0071 static u32 phys_sockets;
0072 static u32 phys_chipspersocket;
0073 static u32 phys_coresperchip;
0074
0075
0076
0077
0078
0079
0080 void read_24x7_sys_info(void)
0081 {
0082 int call_status, len, ntypes;
0083
0084 spin_lock(&rtas_data_buf_lock);
0085
0086
0087
0088
0089
0090 phys_sockets = 1;
0091 phys_chipspersocket = 1;
0092 phys_coresperchip = 1;
0093
0094 call_status = rtas_call(rtas_token("ibm,get-system-parameter"), 3, 1,
0095 NULL,
0096 PROCESSOR_MODULE_INFO,
0097 __pa(rtas_data_buf),
0098 RTAS_DATA_BUF_SIZE);
0099
0100 if (call_status != 0) {
0101 pr_err("Error calling get-system-parameter %d\n",
0102 call_status);
0103 } else {
0104 len = be16_to_cpup((__be16 *)&rtas_data_buf[0]);
0105 if (len < 8)
0106 goto out;
0107
0108 ntypes = be16_to_cpup((__be16 *)&rtas_data_buf[2]);
0109
0110 if (!ntypes)
0111 goto out;
0112
0113 phys_sockets = be16_to_cpup((__be16 *)&rtas_data_buf[4]);
0114 phys_chipspersocket = be16_to_cpup((__be16 *)&rtas_data_buf[6]);
0115 phys_coresperchip = be16_to_cpup((__be16 *)&rtas_data_buf[8]);
0116 }
0117
0118 out:
0119 spin_unlock(&rtas_data_buf_lock);
0120 }
0121
0122
0123 static bool domain_needs_aggregation(unsigned int domain)
0124 {
0125 return aggregate_result_elements &&
0126 (domain == HV_PERF_DOMAIN_PHYS_CORE ||
0127 (domain >= HV_PERF_DOMAIN_VCPU_HOME_CORE &&
0128 domain <= HV_PERF_DOMAIN_VCPU_REMOTE_NODE));
0129 }
0130
0131 static const char *domain_name(unsigned int domain)
0132 {
0133 if (!domain_is_valid(domain))
0134 return NULL;
0135
0136 switch (domain) {
0137 case HV_PERF_DOMAIN_PHYS_CHIP: return "Physical Chip";
0138 case HV_PERF_DOMAIN_PHYS_CORE: return "Physical Core";
0139 case HV_PERF_DOMAIN_VCPU_HOME_CORE: return "VCPU Home Core";
0140 case HV_PERF_DOMAIN_VCPU_HOME_CHIP: return "VCPU Home Chip";
0141 case HV_PERF_DOMAIN_VCPU_HOME_NODE: return "VCPU Home Node";
0142 case HV_PERF_DOMAIN_VCPU_REMOTE_NODE: return "VCPU Remote Node";
0143 }
0144
0145 WARN_ON_ONCE(domain);
0146 return NULL;
0147 }
0148
0149 static bool catalog_entry_domain_is_valid(unsigned int domain)
0150 {
0151
0152 if (interface_version == 1)
0153 return is_physical_domain(domain);
0154 else
0155 return domain_is_valid(domain);
0156 }
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183 EVENT_DEFINE_RANGE_FORMAT(domain, config, 0, 3);
0184
0185 EVENT_DEFINE_RANGE_FORMAT(core, config, 16, 31);
0186 EVENT_DEFINE_RANGE_FORMAT(chip, config, 16, 31);
0187 EVENT_DEFINE_RANGE_FORMAT(vcpu, config, 16, 31);
0188
0189 EVENT_DEFINE_RANGE_FORMAT(offset, config, 32, 63);
0190
0191 EVENT_DEFINE_RANGE_FORMAT(lpar, config1, 0, 15);
0192
0193 EVENT_DEFINE_RANGE(reserved1, config, 4, 15);
0194 EVENT_DEFINE_RANGE(reserved2, config1, 16, 63);
0195 EVENT_DEFINE_RANGE(reserved3, config2, 0, 63);
0196
0197 static struct attribute *format_attrs[] = {
0198 &format_attr_domain.attr,
0199 &format_attr_offset.attr,
0200 &format_attr_core.attr,
0201 &format_attr_chip.attr,
0202 &format_attr_vcpu.attr,
0203 &format_attr_lpar.attr,
0204 NULL,
0205 };
0206
0207 static const struct attribute_group format_group = {
0208 .name = "format",
0209 .attrs = format_attrs,
0210 };
0211
0212 static struct attribute_group event_group = {
0213 .name = "events",
0214
0215 };
0216
0217 static struct attribute_group event_desc_group = {
0218 .name = "event_descs",
0219
0220 };
0221
0222 static struct attribute_group event_long_desc_group = {
0223 .name = "event_long_descs",
0224
0225 };
0226
0227 static struct kmem_cache *hv_page_cache;
0228
0229 static DEFINE_PER_CPU(int, hv_24x7_txn_flags);
0230 static DEFINE_PER_CPU(int, hv_24x7_txn_err);
0231
0232 struct hv_24x7_hw {
0233 struct perf_event *events[255];
0234 };
0235
0236 static DEFINE_PER_CPU(struct hv_24x7_hw, hv_24x7_hw);
0237
0238
0239
0240
0241
0242
0243 #define H24x7_DATA_BUFFER_SIZE 4096
0244 static DEFINE_PER_CPU(char, hv_24x7_reqb[H24x7_DATA_BUFFER_SIZE]) __aligned(4096);
0245 static DEFINE_PER_CPU(char, hv_24x7_resb[H24x7_DATA_BUFFER_SIZE]) __aligned(4096);
0246
0247 static unsigned int max_num_requests(int interface_version)
0248 {
0249 return (H24x7_DATA_BUFFER_SIZE - sizeof(struct hv_24x7_request_buffer))
0250 / H24x7_REQUEST_SIZE(interface_version);
0251 }
0252
0253 static char *event_name(struct hv_24x7_event_data *ev, int *len)
0254 {
0255 *len = be16_to_cpu(ev->event_name_len) - 2;
0256 return (char *)ev->remainder;
0257 }
0258
0259 static char *event_desc(struct hv_24x7_event_data *ev, int *len)
0260 {
0261 unsigned int nl = be16_to_cpu(ev->event_name_len);
0262 __be16 *desc_len = (__be16 *)(ev->remainder + nl - 2);
0263
0264 *len = be16_to_cpu(*desc_len) - 2;
0265 return (char *)ev->remainder + nl;
0266 }
0267
0268 static char *event_long_desc(struct hv_24x7_event_data *ev, int *len)
0269 {
0270 unsigned int nl = be16_to_cpu(ev->event_name_len);
0271 __be16 *desc_len_ = (__be16 *)(ev->remainder + nl - 2);
0272 unsigned int desc_len = be16_to_cpu(*desc_len_);
0273 __be16 *long_desc_len = (__be16 *)(ev->remainder + nl + desc_len - 2);
0274
0275 *len = be16_to_cpu(*long_desc_len) - 2;
0276 return (char *)ev->remainder + nl + desc_len;
0277 }
0278
0279 static bool event_fixed_portion_is_within(struct hv_24x7_event_data *ev,
0280 void *end)
0281 {
0282 void *start = ev;
0283
0284 return (start + offsetof(struct hv_24x7_event_data, remainder)) < end;
0285 }
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295 static void *event_end(struct hv_24x7_event_data *ev, void *end)
0296 {
0297 void *start = ev;
0298 __be16 *dl_, *ldl_;
0299 unsigned int dl, ldl;
0300 unsigned int nl = be16_to_cpu(ev->event_name_len);
0301
0302 if (nl < 2) {
0303 pr_debug("%s: name length too short: %d", __func__, nl);
0304 return NULL;
0305 }
0306
0307 if (start + nl > end) {
0308 pr_debug("%s: start=%p + nl=%u > end=%p",
0309 __func__, start, nl, end);
0310 return NULL;
0311 }
0312
0313 dl_ = (__be16 *)(ev->remainder + nl - 2);
0314 if (!IS_ALIGNED((uintptr_t)dl_, 2))
0315 pr_warn("desc len not aligned %p", dl_);
0316 dl = be16_to_cpu(*dl_);
0317 if (dl < 2) {
0318 pr_debug("%s: desc len too short: %d", __func__, dl);
0319 return NULL;
0320 }
0321
0322 if (start + nl + dl > end) {
0323 pr_debug("%s: (start=%p + nl=%u + dl=%u)=%p > end=%p",
0324 __func__, start, nl, dl, start + nl + dl, end);
0325 return NULL;
0326 }
0327
0328 ldl_ = (__be16 *)(ev->remainder + nl + dl - 2);
0329 if (!IS_ALIGNED((uintptr_t)ldl_, 2))
0330 pr_warn("long desc len not aligned %p", ldl_);
0331 ldl = be16_to_cpu(*ldl_);
0332 if (ldl < 2) {
0333 pr_debug("%s: long desc len too short (ldl=%u)",
0334 __func__, ldl);
0335 return NULL;
0336 }
0337
0338 if (start + nl + dl + ldl > end) {
0339 pr_debug("%s: start=%p + nl=%u + dl=%u + ldl=%u > end=%p",
0340 __func__, start, nl, dl, ldl, end);
0341 return NULL;
0342 }
0343
0344 return start + nl + dl + ldl;
0345 }
0346
0347 static long h_get_24x7_catalog_page_(unsigned long phys_4096,
0348 unsigned long version, unsigned long index)
0349 {
0350 pr_devel("h_get_24x7_catalog_page(0x%lx, %lu, %lu)",
0351 phys_4096, version, index);
0352
0353 WARN_ON(!IS_ALIGNED(phys_4096, 4096));
0354
0355 return plpar_hcall_norets(H_GET_24X7_CATALOG_PAGE,
0356 phys_4096, version, index);
0357 }
0358
0359 static long h_get_24x7_catalog_page(char page[], u64 version, u32 index)
0360 {
0361 return h_get_24x7_catalog_page_(virt_to_phys(page),
0362 version, index);
0363 }
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401 static char *event_fmt(struct hv_24x7_event_data *event, unsigned int domain)
0402 {
0403 const char *sindex;
0404 const char *lpar;
0405 const char *domain_str;
0406 char buf[8];
0407
0408 switch (domain) {
0409 case HV_PERF_DOMAIN_PHYS_CHIP:
0410 snprintf(buf, sizeof(buf), "%d", domain);
0411 domain_str = buf;
0412 lpar = "0x0";
0413 sindex = "chip";
0414 break;
0415 case HV_PERF_DOMAIN_PHYS_CORE:
0416 domain_str = "?";
0417 lpar = "0x0";
0418 sindex = "core";
0419 break;
0420 default:
0421 domain_str = "?";
0422 lpar = "?";
0423 sindex = "vcpu";
0424 }
0425
0426 return kasprintf(GFP_KERNEL,
0427 "domain=%s,offset=0x%x,%s=?,lpar=%s",
0428 domain_str,
0429 be16_to_cpu(event->event_counter_offs) +
0430 be16_to_cpu(event->event_group_record_offs),
0431 sindex,
0432 lpar);
0433 }
0434
0435
0436 static char *memdup_to_str(char *maybe_str, int max_len, gfp_t gfp)
0437 {
0438 return kasprintf(gfp, "%.*s", max_len, maybe_str);
0439 }
0440
0441 static ssize_t device_show_string(struct device *dev,
0442 struct device_attribute *attr, char *buf)
0443 {
0444 struct dev_ext_attribute *d;
0445
0446 d = container_of(attr, struct dev_ext_attribute, attr);
0447
0448 return sprintf(buf, "%s\n", (char *)d->var);
0449 }
0450
0451 static ssize_t cpumask_show(struct device *dev,
0452 struct device_attribute *attr, char *buf)
0453 {
0454 return cpumap_print_to_pagebuf(true, buf, &hv_24x7_cpumask);
0455 }
0456
0457 static ssize_t sockets_show(struct device *dev,
0458 struct device_attribute *attr, char *buf)
0459 {
0460 return sprintf(buf, "%d\n", phys_sockets);
0461 }
0462
0463 static ssize_t chipspersocket_show(struct device *dev,
0464 struct device_attribute *attr, char *buf)
0465 {
0466 return sprintf(buf, "%d\n", phys_chipspersocket);
0467 }
0468
0469 static ssize_t coresperchip_show(struct device *dev,
0470 struct device_attribute *attr, char *buf)
0471 {
0472 return sprintf(buf, "%d\n", phys_coresperchip);
0473 }
0474
0475 static struct attribute *device_str_attr_create_(char *name, char *str)
0476 {
0477 struct dev_ext_attribute *attr = kzalloc(sizeof(*attr), GFP_KERNEL);
0478
0479 if (!attr)
0480 return NULL;
0481
0482 sysfs_attr_init(&attr->attr.attr);
0483
0484 attr->var = str;
0485 attr->attr.attr.name = name;
0486 attr->attr.attr.mode = 0444;
0487 attr->attr.show = device_show_string;
0488
0489 return &attr->attr.attr;
0490 }
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500
0501 static struct attribute *device_str_attr_create(char *name, int name_max,
0502 int name_nonce,
0503 char *str, size_t str_max)
0504 {
0505 char *n;
0506 char *s = memdup_to_str(str, str_max, GFP_KERNEL);
0507 struct attribute *a;
0508
0509 if (!s)
0510 return NULL;
0511
0512 if (!name_nonce)
0513 n = kasprintf(GFP_KERNEL, "%.*s", name_max, name);
0514 else
0515 n = kasprintf(GFP_KERNEL, "%.*s__%d", name_max, name,
0516 name_nonce);
0517 if (!n)
0518 goto out_s;
0519
0520 a = device_str_attr_create_(n, s);
0521 if (!a)
0522 goto out_n;
0523
0524 return a;
0525 out_n:
0526 kfree(n);
0527 out_s:
0528 kfree(s);
0529 return NULL;
0530 }
0531
0532 static struct attribute *event_to_attr(unsigned int ix,
0533 struct hv_24x7_event_data *event,
0534 unsigned int domain,
0535 int nonce)
0536 {
0537 int event_name_len;
0538 char *ev_name, *a_ev_name, *val;
0539 struct attribute *attr;
0540
0541 if (!domain_is_valid(domain)) {
0542 pr_warn("catalog event %u has invalid domain %u\n",
0543 ix, domain);
0544 return NULL;
0545 }
0546
0547 val = event_fmt(event, domain);
0548 if (!val)
0549 return NULL;
0550
0551 ev_name = event_name(event, &event_name_len);
0552 if (!nonce)
0553 a_ev_name = kasprintf(GFP_KERNEL, "%.*s",
0554 (int)event_name_len, ev_name);
0555 else
0556 a_ev_name = kasprintf(GFP_KERNEL, "%.*s__%d",
0557 (int)event_name_len, ev_name, nonce);
0558
0559 if (!a_ev_name)
0560 goto out_val;
0561
0562 attr = device_str_attr_create_(a_ev_name, val);
0563 if (!attr)
0564 goto out_name;
0565
0566 return attr;
0567 out_name:
0568 kfree(a_ev_name);
0569 out_val:
0570 kfree(val);
0571 return NULL;
0572 }
0573
0574 static struct attribute *event_to_desc_attr(struct hv_24x7_event_data *event,
0575 int nonce)
0576 {
0577 int nl, dl;
0578 char *name = event_name(event, &nl);
0579 char *desc = event_desc(event, &dl);
0580
0581
0582 if (!dl)
0583 return NULL;
0584
0585 return device_str_attr_create(name, nl, nonce, desc, dl);
0586 }
0587
0588 static struct attribute *
0589 event_to_long_desc_attr(struct hv_24x7_event_data *event, int nonce)
0590 {
0591 int nl, dl;
0592 char *name = event_name(event, &nl);
0593 char *desc = event_long_desc(event, &dl);
0594
0595
0596 if (!dl)
0597 return NULL;
0598
0599 return device_str_attr_create(name, nl, nonce, desc, dl);
0600 }
0601
0602 static int event_data_to_attrs(unsigned int ix, struct attribute **attrs,
0603 struct hv_24x7_event_data *event, int nonce)
0604 {
0605 *attrs = event_to_attr(ix, event, event->domain, nonce);
0606 if (!*attrs)
0607 return -1;
0608
0609 return 0;
0610 }
0611
0612
0613 struct event_uniq {
0614 struct rb_node node;
0615 const char *name;
0616 int nl;
0617 unsigned int ct;
0618 unsigned int domain;
0619 };
0620
0621 static int memord(const void *d1, size_t s1, const void *d2, size_t s2)
0622 {
0623 if (s1 < s2)
0624 return 1;
0625 if (s1 > s2)
0626 return -1;
0627
0628 return memcmp(d1, d2, s1);
0629 }
0630
0631 static int ev_uniq_ord(const void *v1, size_t s1, unsigned int d1,
0632 const void *v2, size_t s2, unsigned int d2)
0633 {
0634 int r = memord(v1, s1, v2, s2);
0635
0636 if (r)
0637 return r;
0638 if (d1 > d2)
0639 return 1;
0640 if (d2 > d1)
0641 return -1;
0642 return 0;
0643 }
0644
0645 static int event_uniq_add(struct rb_root *root, const char *name, int nl,
0646 unsigned int domain)
0647 {
0648 struct rb_node **new = &(root->rb_node), *parent = NULL;
0649 struct event_uniq *data;
0650
0651
0652 while (*new) {
0653 struct event_uniq *it;
0654 int result;
0655
0656 it = rb_entry(*new, struct event_uniq, node);
0657 result = ev_uniq_ord(name, nl, domain, it->name, it->nl,
0658 it->domain);
0659
0660 parent = *new;
0661 if (result < 0)
0662 new = &((*new)->rb_left);
0663 else if (result > 0)
0664 new = &((*new)->rb_right);
0665 else {
0666 it->ct++;
0667 pr_info("found a duplicate event %.*s, ct=%u\n", nl,
0668 name, it->ct);
0669 return it->ct;
0670 }
0671 }
0672
0673 data = kmalloc(sizeof(*data), GFP_KERNEL);
0674 if (!data)
0675 return -ENOMEM;
0676
0677 *data = (struct event_uniq) {
0678 .name = name,
0679 .nl = nl,
0680 .ct = 0,
0681 .domain = domain,
0682 };
0683
0684
0685 rb_link_node(&data->node, parent, new);
0686 rb_insert_color(&data->node, root);
0687
0688
0689 return 0;
0690 }
0691
0692 static void event_uniq_destroy(struct rb_root *root)
0693 {
0694
0695
0696
0697
0698 struct event_uniq *pos, *n;
0699
0700 rbtree_postorder_for_each_entry_safe(pos, n, root, node)
0701 kfree(pos);
0702 }
0703
0704
0705
0706
0707
0708
0709
0710
0711
0712 static ssize_t catalog_event_len_validate(struct hv_24x7_event_data *event,
0713 size_t event_idx,
0714 size_t event_data_bytes,
0715 size_t event_entry_count,
0716 size_t offset, void *end)
0717 {
0718 ssize_t ev_len;
0719 void *ev_end, *calc_ev_end;
0720
0721 if (offset >= event_data_bytes)
0722 return -1;
0723
0724 if (event_idx >= event_entry_count) {
0725 pr_devel("catalog event data has %zu bytes of padding after last event\n",
0726 event_data_bytes - offset);
0727 return -1;
0728 }
0729
0730 if (!event_fixed_portion_is_within(event, end)) {
0731 pr_warn("event %zu fixed portion is not within range\n",
0732 event_idx);
0733 return -1;
0734 }
0735
0736 ev_len = be16_to_cpu(event->length);
0737
0738 if (ev_len % 16)
0739 pr_info("event %zu has length %zu not divisible by 16: event=%pK\n",
0740 event_idx, ev_len, event);
0741
0742 ev_end = (__u8 *)event + ev_len;
0743 if (ev_end > end) {
0744 pr_warn("event %zu has .length=%zu, ends after buffer end: ev_end=%pK > end=%pK, offset=%zu\n",
0745 event_idx, ev_len, ev_end, end,
0746 offset);
0747 return -1;
0748 }
0749
0750 calc_ev_end = event_end(event, end);
0751 if (!calc_ev_end) {
0752 pr_warn("event %zu has a calculated length which exceeds buffer length %zu: event=%pK end=%pK, offset=%zu\n",
0753 event_idx, event_data_bytes, event, end,
0754 offset);
0755 return -1;
0756 }
0757
0758 if (calc_ev_end > ev_end) {
0759 pr_warn("event %zu exceeds its own length: event=%pK, end=%pK, offset=%zu, calc_ev_end=%pK\n",
0760 event_idx, event, ev_end, offset, calc_ev_end);
0761 return -1;
0762 }
0763
0764 return ev_len;
0765 }
0766
0767
0768
0769
0770 static bool ignore_event(const char *name)
0771 {
0772 return strncmp(name, "RESERVED", 8) == 0;
0773 }
0774
0775 #define MAX_4K (SIZE_MAX / 4096)
0776
0777 static int create_events_from_catalog(struct attribute ***events_,
0778 struct attribute ***event_descs_,
0779 struct attribute ***event_long_descs_)
0780 {
0781 long hret;
0782 size_t catalog_len, catalog_page_len, event_entry_count,
0783 event_data_len, event_data_offs,
0784 event_data_bytes, junk_events, event_idx, event_attr_ct, i,
0785 attr_max, event_idx_last, desc_ct, long_desc_ct;
0786 ssize_t ct, ev_len;
0787 uint64_t catalog_version_num;
0788 struct attribute **events, **event_descs, **event_long_descs;
0789 struct hv_24x7_catalog_page_0 *page_0 =
0790 kmem_cache_alloc(hv_page_cache, GFP_KERNEL);
0791 void *page = page_0;
0792 void *event_data, *end;
0793 struct hv_24x7_event_data *event;
0794 struct rb_root ev_uniq = RB_ROOT;
0795 int ret = 0;
0796
0797 if (!page) {
0798 ret = -ENOMEM;
0799 goto e_out;
0800 }
0801
0802 hret = h_get_24x7_catalog_page(page, 0, 0);
0803 if (hret) {
0804 ret = -EIO;
0805 goto e_free;
0806 }
0807
0808 catalog_version_num = be64_to_cpu(page_0->version);
0809 catalog_page_len = be32_to_cpu(page_0->length);
0810
0811 if (MAX_4K < catalog_page_len) {
0812 pr_err("invalid page count: %zu\n", catalog_page_len);
0813 ret = -EIO;
0814 goto e_free;
0815 }
0816
0817 catalog_len = catalog_page_len * 4096;
0818
0819 event_entry_count = be16_to_cpu(page_0->event_entry_count);
0820 event_data_offs = be16_to_cpu(page_0->event_data_offs);
0821 event_data_len = be16_to_cpu(page_0->event_data_len);
0822
0823 pr_devel("cv %llu cl %zu eec %zu edo %zu edl %zu\n",
0824 catalog_version_num, catalog_len,
0825 event_entry_count, event_data_offs, event_data_len);
0826
0827 if ((MAX_4K < event_data_len)
0828 || (MAX_4K < event_data_offs)
0829 || (MAX_4K - event_data_offs < event_data_len)) {
0830 pr_err("invalid event data offs %zu and/or len %zu\n",
0831 event_data_offs, event_data_len);
0832 ret = -EIO;
0833 goto e_free;
0834 }
0835
0836 if ((event_data_offs + event_data_len) > catalog_page_len) {
0837 pr_err("event data %zu-%zu does not fit inside catalog 0-%zu\n",
0838 event_data_offs,
0839 event_data_offs + event_data_len,
0840 catalog_page_len);
0841 ret = -EIO;
0842 goto e_free;
0843 }
0844
0845 if (SIZE_MAX - 1 < event_entry_count) {
0846 pr_err("event_entry_count %zu is invalid\n", event_entry_count);
0847 ret = -EIO;
0848 goto e_free;
0849 }
0850
0851 event_data_bytes = event_data_len * 4096;
0852
0853
0854
0855
0856
0857 event_data = vmalloc(event_data_bytes);
0858 if (!event_data) {
0859 pr_err("could not allocate event data\n");
0860 ret = -ENOMEM;
0861 goto e_free;
0862 }
0863
0864 end = event_data + event_data_bytes;
0865
0866
0867
0868
0869
0870 BUILD_BUG_ON(PAGE_SIZE % 4096);
0871
0872 for (i = 0; i < event_data_len; i++) {
0873 hret = h_get_24x7_catalog_page_(
0874 vmalloc_to_phys(event_data + i * 4096),
0875 catalog_version_num,
0876 i + event_data_offs);
0877 if (hret) {
0878 pr_err("Failed to get event data in page %zu: rc=%ld\n",
0879 i + event_data_offs, hret);
0880 ret = -EIO;
0881 goto e_event_data;
0882 }
0883 }
0884
0885
0886
0887
0888
0889 for (junk_events = 0, event = event_data, event_idx = 0, attr_max = 0;
0890 ;
0891 event_idx++, event = (void *)event + ev_len) {
0892 size_t offset = (void *)event - (void *)event_data;
0893 char *name;
0894 int nl;
0895
0896 ev_len = catalog_event_len_validate(event, event_idx,
0897 event_data_bytes,
0898 event_entry_count,
0899 offset, end);
0900 if (ev_len < 0)
0901 break;
0902
0903 name = event_name(event, &nl);
0904
0905 if (ignore_event(name)) {
0906 junk_events++;
0907 continue;
0908 }
0909 if (event->event_group_record_len == 0) {
0910 pr_devel("invalid event %zu (%.*s): group_record_len == 0, skipping\n",
0911 event_idx, nl, name);
0912 junk_events++;
0913 continue;
0914 }
0915
0916 if (!catalog_entry_domain_is_valid(event->domain)) {
0917 pr_info("event %zu (%.*s) has invalid domain %d\n",
0918 event_idx, nl, name, event->domain);
0919 junk_events++;
0920 continue;
0921 }
0922
0923 attr_max++;
0924 }
0925
0926 event_idx_last = event_idx;
0927 if (event_idx_last != event_entry_count)
0928 pr_warn("event buffer ended before listed # of events were parsed (got %zu, wanted %zu, junk %zu)\n",
0929 event_idx_last, event_entry_count, junk_events);
0930
0931 events = kmalloc_array(attr_max + 1, sizeof(*events), GFP_KERNEL);
0932 if (!events) {
0933 ret = -ENOMEM;
0934 goto e_event_data;
0935 }
0936
0937 event_descs = kmalloc_array(event_idx + 1, sizeof(*event_descs),
0938 GFP_KERNEL);
0939 if (!event_descs) {
0940 ret = -ENOMEM;
0941 goto e_event_attrs;
0942 }
0943
0944 event_long_descs = kmalloc_array(event_idx + 1,
0945 sizeof(*event_long_descs), GFP_KERNEL);
0946 if (!event_long_descs) {
0947 ret = -ENOMEM;
0948 goto e_event_descs;
0949 }
0950
0951
0952 for (junk_events = 0, event_attr_ct = 0, desc_ct = 0, long_desc_ct = 0,
0953 event = event_data, event_idx = 0;
0954 event_idx < event_idx_last;
0955 event_idx++, ev_len = be16_to_cpu(event->length),
0956 event = (void *)event + ev_len) {
0957 char *name;
0958 int nl;
0959 int nonce;
0960
0961
0962
0963
0964 if (event->event_group_record_len == 0)
0965 continue;
0966 if (!catalog_entry_domain_is_valid(event->domain))
0967 continue;
0968
0969 name = event_name(event, &nl);
0970 if (ignore_event(name))
0971 continue;
0972
0973 nonce = event_uniq_add(&ev_uniq, name, nl, event->domain);
0974 ct = event_data_to_attrs(event_idx, events + event_attr_ct,
0975 event, nonce);
0976 if (ct < 0) {
0977 pr_warn("event %zu (%.*s) creation failure, skipping\n",
0978 event_idx, nl, name);
0979 junk_events++;
0980 } else {
0981 event_attr_ct++;
0982 event_descs[desc_ct] = event_to_desc_attr(event, nonce);
0983 if (event_descs[desc_ct])
0984 desc_ct++;
0985 event_long_descs[long_desc_ct] =
0986 event_to_long_desc_attr(event, nonce);
0987 if (event_long_descs[long_desc_ct])
0988 long_desc_ct++;
0989 }
0990 }
0991
0992 pr_info("read %zu catalog entries, created %zu event attrs (%zu failures), %zu descs\n",
0993 event_idx, event_attr_ct, junk_events, desc_ct);
0994
0995 events[event_attr_ct] = NULL;
0996 event_descs[desc_ct] = NULL;
0997 event_long_descs[long_desc_ct] = NULL;
0998
0999 event_uniq_destroy(&ev_uniq);
1000 vfree(event_data);
1001 kmem_cache_free(hv_page_cache, page);
1002
1003 *events_ = events;
1004 *event_descs_ = event_descs;
1005 *event_long_descs_ = event_long_descs;
1006 return 0;
1007
1008 e_event_descs:
1009 kfree(event_descs);
1010 e_event_attrs:
1011 kfree(events);
1012 e_event_data:
1013 vfree(event_data);
1014 e_free:
1015 kmem_cache_free(hv_page_cache, page);
1016 e_out:
1017 *events_ = NULL;
1018 *event_descs_ = NULL;
1019 *event_long_descs_ = NULL;
1020 return ret;
1021 }
1022
1023 static ssize_t catalog_read(struct file *filp, struct kobject *kobj,
1024 struct bin_attribute *bin_attr, char *buf,
1025 loff_t offset, size_t count)
1026 {
1027 long hret;
1028 ssize_t ret = 0;
1029 size_t catalog_len = 0, catalog_page_len = 0;
1030 loff_t page_offset = 0;
1031 loff_t offset_in_page;
1032 size_t copy_len;
1033 uint64_t catalog_version_num = 0;
1034 void *page = kmem_cache_alloc(hv_page_cache, GFP_USER);
1035 struct hv_24x7_catalog_page_0 *page_0 = page;
1036
1037 if (!page)
1038 return -ENOMEM;
1039
1040 hret = h_get_24x7_catalog_page(page, 0, 0);
1041 if (hret) {
1042 ret = -EIO;
1043 goto e_free;
1044 }
1045
1046 catalog_version_num = be64_to_cpu(page_0->version);
1047 catalog_page_len = be32_to_cpu(page_0->length);
1048 catalog_len = catalog_page_len * 4096;
1049
1050 page_offset = offset / 4096;
1051 offset_in_page = offset % 4096;
1052
1053 if (page_offset >= catalog_page_len)
1054 goto e_free;
1055
1056 if (page_offset != 0) {
1057 hret = h_get_24x7_catalog_page(page, catalog_version_num,
1058 page_offset);
1059 if (hret) {
1060 ret = -EIO;
1061 goto e_free;
1062 }
1063 }
1064
1065 copy_len = 4096 - offset_in_page;
1066 if (copy_len > count)
1067 copy_len = count;
1068
1069 memcpy(buf, page+offset_in_page, copy_len);
1070 ret = copy_len;
1071
1072 e_free:
1073 if (hret)
1074 pr_err("h_get_24x7_catalog_page(ver=%lld, page=%lld) failed:"
1075 " rc=%ld\n",
1076 catalog_version_num, page_offset, hret);
1077 kmem_cache_free(hv_page_cache, page);
1078
1079 pr_devel("catalog_read: offset=%lld(%lld) count=%zu "
1080 "catalog_len=%zu(%zu) => %zd\n", offset, page_offset,
1081 count, catalog_len, catalog_page_len, ret);
1082
1083 return ret;
1084 }
1085
1086 static ssize_t domains_show(struct device *dev, struct device_attribute *attr,
1087 char *page)
1088 {
1089 int d, n, count = 0;
1090 const char *str;
1091
1092 for (d = 0; d < HV_PERF_DOMAIN_MAX; d++) {
1093 str = domain_name(d);
1094 if (!str)
1095 continue;
1096
1097 n = sprintf(page, "%d: %s\n", d, str);
1098 if (n < 0)
1099 break;
1100
1101 count += n;
1102 page += n;
1103 }
1104 return count;
1105 }
1106
1107 #define PAGE_0_ATTR(_name, _fmt, _expr) \
1108 static ssize_t _name##_show(struct device *dev, \
1109 struct device_attribute *dev_attr, \
1110 char *buf) \
1111 { \
1112 long hret; \
1113 ssize_t ret = 0; \
1114 void *page = kmem_cache_alloc(hv_page_cache, GFP_USER); \
1115 struct hv_24x7_catalog_page_0 *page_0 = page; \
1116 if (!page) \
1117 return -ENOMEM; \
1118 hret = h_get_24x7_catalog_page(page, 0, 0); \
1119 if (hret) { \
1120 ret = -EIO; \
1121 goto e_free; \
1122 } \
1123 ret = sprintf(buf, _fmt, _expr); \
1124 e_free: \
1125 kmem_cache_free(hv_page_cache, page); \
1126 return ret; \
1127 } \
1128 static DEVICE_ATTR_RO(_name)
1129
1130 PAGE_0_ATTR(catalog_version, "%lld\n",
1131 (unsigned long long)be64_to_cpu(page_0->version));
1132 PAGE_0_ATTR(catalog_len, "%lld\n",
1133 (unsigned long long)be32_to_cpu(page_0->length) * 4096);
1134 static BIN_ATTR_RO(catalog, 0);
1135 static DEVICE_ATTR_RO(domains);
1136 static DEVICE_ATTR_RO(sockets);
1137 static DEVICE_ATTR_RO(chipspersocket);
1138 static DEVICE_ATTR_RO(coresperchip);
1139 static DEVICE_ATTR_RO(cpumask);
1140
1141 static struct bin_attribute *if_bin_attrs[] = {
1142 &bin_attr_catalog,
1143 NULL,
1144 };
1145
1146 static struct attribute *cpumask_attrs[] = {
1147 &dev_attr_cpumask.attr,
1148 NULL,
1149 };
1150
1151 static const struct attribute_group cpumask_attr_group = {
1152 .attrs = cpumask_attrs,
1153 };
1154
1155 static struct attribute *if_attrs[] = {
1156 &dev_attr_catalog_len.attr,
1157 &dev_attr_catalog_version.attr,
1158 &dev_attr_domains.attr,
1159 &dev_attr_sockets.attr,
1160 &dev_attr_chipspersocket.attr,
1161 &dev_attr_coresperchip.attr,
1162 NULL,
1163 };
1164
1165 static const struct attribute_group if_group = {
1166 .name = "interface",
1167 .bin_attrs = if_bin_attrs,
1168 .attrs = if_attrs,
1169 };
1170
1171 static const struct attribute_group *attr_groups[] = {
1172 &format_group,
1173 &event_group,
1174 &event_desc_group,
1175 &event_long_desc_group,
1176 &if_group,
1177 &cpumask_attr_group,
1178 NULL,
1179 };
1180
1181
1182
1183
1184 static void init_24x7_request(struct hv_24x7_request_buffer *request_buffer,
1185 struct hv_24x7_data_result_buffer *result_buffer)
1186 {
1187
1188 memset(request_buffer, 0, H24x7_DATA_BUFFER_SIZE);
1189 memset(result_buffer, 0, H24x7_DATA_BUFFER_SIZE);
1190
1191 request_buffer->interface_version = interface_version;
1192
1193 }
1194
1195
1196
1197
1198
1199 static int make_24x7_request(struct hv_24x7_request_buffer *request_buffer,
1200 struct hv_24x7_data_result_buffer *result_buffer)
1201 {
1202 long ret;
1203
1204
1205
1206
1207
1208
1209 ret = plpar_hcall_norets(H_GET_24X7_DATA,
1210 virt_to_phys(request_buffer), H24x7_DATA_BUFFER_SIZE,
1211 virt_to_phys(result_buffer), H24x7_DATA_BUFFER_SIZE);
1212
1213 if (ret) {
1214 struct hv_24x7_request *req;
1215
1216 req = request_buffer->requests;
1217 pr_notice_ratelimited("hcall failed: [%d %#x %#x %d] => ret 0x%lx (%ld) detail=0x%x failing ix=%x\n",
1218 req->performance_domain, req->data_offset,
1219 req->starting_ix, req->starting_lpar_ix,
1220 ret, ret, result_buffer->detailed_rc,
1221 result_buffer->failing_request_ix);
1222 return -EIO;
1223 }
1224
1225 return 0;
1226 }
1227
1228
1229
1230
1231
1232
1233
1234
1235 static int add_event_to_24x7_request(struct perf_event *event,
1236 struct hv_24x7_request_buffer *request_buffer)
1237 {
1238 u16 idx;
1239 int i;
1240 size_t req_size;
1241 struct hv_24x7_request *req;
1242
1243 if (request_buffer->num_requests >=
1244 max_num_requests(request_buffer->interface_version)) {
1245 pr_devel("Too many requests for 24x7 HCALL %d\n",
1246 request_buffer->num_requests);
1247 return -EINVAL;
1248 }
1249
1250 switch (event_get_domain(event)) {
1251 case HV_PERF_DOMAIN_PHYS_CHIP:
1252 idx = event_get_chip(event);
1253 break;
1254 case HV_PERF_DOMAIN_PHYS_CORE:
1255 idx = event_get_core(event);
1256 break;
1257 default:
1258 idx = event_get_vcpu(event);
1259 }
1260
1261 req_size = H24x7_REQUEST_SIZE(request_buffer->interface_version);
1262
1263 i = request_buffer->num_requests++;
1264 req = (void *) request_buffer->requests + i * req_size;
1265
1266 req->performance_domain = event_get_domain(event);
1267 req->data_size = cpu_to_be16(8);
1268 req->data_offset = cpu_to_be32(event_get_offset(event));
1269 req->starting_lpar_ix = cpu_to_be16(event_get_lpar(event));
1270 req->max_num_lpars = cpu_to_be16(1);
1271 req->starting_ix = cpu_to_be16(idx);
1272 req->max_ix = cpu_to_be16(1);
1273
1274 if (request_buffer->interface_version > 1) {
1275 if (domain_needs_aggregation(req->performance_domain))
1276 req->max_num_thread_groups = -1;
1277 else if (req->performance_domain != HV_PERF_DOMAIN_PHYS_CHIP) {
1278 req->starting_thread_group_ix = idx % 2;
1279 req->max_num_thread_groups = 1;
1280 }
1281 }
1282
1283 return 0;
1284 }
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298 static int get_count_from_result(struct perf_event *event,
1299 struct hv_24x7_data_result_buffer *resb,
1300 struct hv_24x7_result *res, u64 *countp,
1301 struct hv_24x7_result **next)
1302 {
1303 u16 num_elements = be16_to_cpu(res->num_elements_returned);
1304 u16 data_size = be16_to_cpu(res->result_element_data_size);
1305 unsigned int data_offset;
1306 void *element_data;
1307 int i;
1308 u64 count;
1309
1310
1311
1312
1313 if (!num_elements) {
1314 pr_debug("Result of request %hhu is empty, nothing to do\n",
1315 res->result_ix);
1316
1317 if (next)
1318 *next = (struct hv_24x7_result *) res->elements;
1319
1320 return -ENODATA;
1321 }
1322
1323
1324
1325
1326
1327
1328 if (num_elements != 1 &&
1329 !domain_needs_aggregation(event_get_domain(event))) {
1330 pr_err("Error: result of request %hhu has %hu elements\n",
1331 res->result_ix, num_elements);
1332
1333 return -EIO;
1334 }
1335
1336 if (data_size != sizeof(u64)) {
1337 pr_debug("Error: result of request %hhu has data of %hu bytes\n",
1338 res->result_ix, data_size);
1339
1340 return -ENOTSUPP;
1341 }
1342
1343 if (resb->interface_version == 1)
1344 data_offset = offsetof(struct hv_24x7_result_element_v1,
1345 element_data);
1346 else
1347 data_offset = offsetof(struct hv_24x7_result_element_v2,
1348 element_data);
1349
1350
1351 for (i = count = 0, element_data = res->elements + data_offset;
1352 i < num_elements;
1353 i++, element_data += data_size + data_offset)
1354 count += be64_to_cpu(*((u64 *) element_data));
1355
1356 *countp = count;
1357
1358
1359 if (next)
1360 *next = element_data - data_offset;
1361
1362 return 0;
1363 }
1364
1365 static int single_24x7_request(struct perf_event *event, u64 *count)
1366 {
1367 int ret;
1368 struct hv_24x7_request_buffer *request_buffer;
1369 struct hv_24x7_data_result_buffer *result_buffer;
1370
1371 BUILD_BUG_ON(sizeof(*request_buffer) > 4096);
1372 BUILD_BUG_ON(sizeof(*result_buffer) > 4096);
1373
1374 request_buffer = (void *)get_cpu_var(hv_24x7_reqb);
1375 result_buffer = (void *)get_cpu_var(hv_24x7_resb);
1376
1377 init_24x7_request(request_buffer, result_buffer);
1378
1379 ret = add_event_to_24x7_request(event, request_buffer);
1380 if (ret)
1381 goto out;
1382
1383 ret = make_24x7_request(request_buffer, result_buffer);
1384 if (ret)
1385 goto out;
1386
1387
1388 ret = get_count_from_result(event, result_buffer,
1389 result_buffer->results, count, NULL);
1390
1391 out:
1392 put_cpu_var(hv_24x7_reqb);
1393 put_cpu_var(hv_24x7_resb);
1394 return ret;
1395 }
1396
1397
1398 static int h_24x7_event_init(struct perf_event *event)
1399 {
1400 struct hv_perf_caps caps;
1401 unsigned int domain;
1402 unsigned long hret;
1403 u64 ct;
1404
1405
1406 if (event->attr.type != event->pmu->type)
1407 return -ENOENT;
1408
1409
1410 if (event_get_reserved1(event) ||
1411 event_get_reserved2(event) ||
1412 event_get_reserved3(event)) {
1413 pr_devel("reserved set when forbidden 0x%llx(0x%llx) 0x%llx(0x%llx) 0x%llx(0x%llx)\n",
1414 event->attr.config,
1415 event_get_reserved1(event),
1416 event->attr.config1,
1417 event_get_reserved2(event),
1418 event->attr.config2,
1419 event_get_reserved3(event));
1420 return -EINVAL;
1421 }
1422
1423
1424 if (has_branch_stack(event))
1425 return -EOPNOTSUPP;
1426
1427
1428 if (event_get_offset(event) % 8) {
1429 pr_devel("bad alignment\n");
1430 return -EINVAL;
1431 }
1432
1433 domain = event_get_domain(event);
1434 if (domain >= HV_PERF_DOMAIN_MAX) {
1435 pr_devel("invalid domain %d\n", domain);
1436 return -EINVAL;
1437 }
1438
1439 hret = hv_perf_caps_get(&caps);
1440 if (hret) {
1441 pr_devel("could not get capabilities: rc=%ld\n", hret);
1442 return -EIO;
1443 }
1444
1445
1446 if (!caps.collect_privileged && (is_physical_domain(domain) ||
1447 (event_get_lpar(event) != event_get_lpar_max()))) {
1448 pr_devel("hv permissions disallow: is_physical_domain:%d, lpar=0x%llx\n",
1449 is_physical_domain(domain),
1450 event_get_lpar(event));
1451 return -EACCES;
1452 }
1453
1454
1455 if (single_24x7_request(event, &ct)) {
1456 pr_devel("test hcall failed\n");
1457 return -EIO;
1458 }
1459 (void)local64_xchg(&event->hw.prev_count, ct);
1460
1461 return 0;
1462 }
1463
1464 static u64 h_24x7_get_value(struct perf_event *event)
1465 {
1466 u64 ct;
1467
1468 if (single_24x7_request(event, &ct))
1469
1470 return 0;
1471
1472 return ct;
1473 }
1474
1475 static void update_event_count(struct perf_event *event, u64 now)
1476 {
1477 s64 prev;
1478
1479 prev = local64_xchg(&event->hw.prev_count, now);
1480 local64_add(now - prev, &event->count);
1481 }
1482
1483 static void h_24x7_event_read(struct perf_event *event)
1484 {
1485 u64 now;
1486 struct hv_24x7_request_buffer *request_buffer;
1487 struct hv_24x7_hw *h24x7hw;
1488 int txn_flags;
1489
1490 txn_flags = __this_cpu_read(hv_24x7_txn_flags);
1491
1492
1493
1494
1495
1496
1497
1498
1499 if (txn_flags & PERF_PMU_TXN_READ) {
1500 int i;
1501 int ret;
1502
1503 if (__this_cpu_read(hv_24x7_txn_err))
1504 return;
1505
1506 request_buffer = (void *)get_cpu_var(hv_24x7_reqb);
1507
1508 ret = add_event_to_24x7_request(event, request_buffer);
1509 if (ret) {
1510 __this_cpu_write(hv_24x7_txn_err, ret);
1511 } else {
1512
1513
1514
1515
1516 i = request_buffer->num_requests - 1;
1517
1518 h24x7hw = &get_cpu_var(hv_24x7_hw);
1519 h24x7hw->events[i] = event;
1520 put_cpu_var(h24x7hw);
1521 }
1522
1523 put_cpu_var(hv_24x7_reqb);
1524 } else {
1525 now = h_24x7_get_value(event);
1526 update_event_count(event, now);
1527 }
1528 }
1529
1530 static void h_24x7_event_start(struct perf_event *event, int flags)
1531 {
1532 if (flags & PERF_EF_RELOAD)
1533 local64_set(&event->hw.prev_count, h_24x7_get_value(event));
1534 }
1535
1536 static void h_24x7_event_stop(struct perf_event *event, int flags)
1537 {
1538 h_24x7_event_read(event);
1539 }
1540
1541 static int h_24x7_event_add(struct perf_event *event, int flags)
1542 {
1543 if (flags & PERF_EF_START)
1544 h_24x7_event_start(event, flags);
1545
1546 return 0;
1547 }
1548
1549
1550
1551
1552
1553
1554
1555 static void h_24x7_event_start_txn(struct pmu *pmu, unsigned int flags)
1556 {
1557 struct hv_24x7_request_buffer *request_buffer;
1558 struct hv_24x7_data_result_buffer *result_buffer;
1559
1560
1561 WARN_ON_ONCE(__this_cpu_read(hv_24x7_txn_flags));
1562
1563 __this_cpu_write(hv_24x7_txn_flags, flags);
1564 if (flags & ~PERF_PMU_TXN_READ)
1565 return;
1566
1567 request_buffer = (void *)get_cpu_var(hv_24x7_reqb);
1568 result_buffer = (void *)get_cpu_var(hv_24x7_resb);
1569
1570 init_24x7_request(request_buffer, result_buffer);
1571
1572 put_cpu_var(hv_24x7_resb);
1573 put_cpu_var(hv_24x7_reqb);
1574 }
1575
1576
1577
1578
1579
1580
1581
1582 static void reset_txn(void)
1583 {
1584 __this_cpu_write(hv_24x7_txn_flags, 0);
1585 __this_cpu_write(hv_24x7_txn_err, 0);
1586 }
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597 static int h_24x7_event_commit_txn(struct pmu *pmu)
1598 {
1599 struct hv_24x7_request_buffer *request_buffer;
1600 struct hv_24x7_data_result_buffer *result_buffer;
1601 struct hv_24x7_result *res, *next_res;
1602 u64 count;
1603 int i, ret, txn_flags;
1604 struct hv_24x7_hw *h24x7hw;
1605
1606 txn_flags = __this_cpu_read(hv_24x7_txn_flags);
1607 WARN_ON_ONCE(!txn_flags);
1608
1609 ret = 0;
1610 if (txn_flags & ~PERF_PMU_TXN_READ)
1611 goto out;
1612
1613 ret = __this_cpu_read(hv_24x7_txn_err);
1614 if (ret)
1615 goto out;
1616
1617 request_buffer = (void *)get_cpu_var(hv_24x7_reqb);
1618 result_buffer = (void *)get_cpu_var(hv_24x7_resb);
1619
1620 ret = make_24x7_request(request_buffer, result_buffer);
1621 if (ret)
1622 goto put_reqb;
1623
1624 h24x7hw = &get_cpu_var(hv_24x7_hw);
1625
1626
1627 for (i = 0, res = result_buffer->results;
1628 i < result_buffer->num_results; i++, res = next_res) {
1629 struct perf_event *event = h24x7hw->events[res->result_ix];
1630
1631 ret = get_count_from_result(event, result_buffer, res, &count,
1632 &next_res);
1633 if (ret)
1634 break;
1635
1636 update_event_count(event, count);
1637 }
1638
1639 put_cpu_var(hv_24x7_hw);
1640
1641 put_reqb:
1642 put_cpu_var(hv_24x7_resb);
1643 put_cpu_var(hv_24x7_reqb);
1644 out:
1645 reset_txn();
1646 return ret;
1647 }
1648
1649
1650
1651
1652
1653
1654
1655 static void h_24x7_event_cancel_txn(struct pmu *pmu)
1656 {
1657 WARN_ON_ONCE(!__this_cpu_read(hv_24x7_txn_flags));
1658 reset_txn();
1659 }
1660
1661 static struct pmu h_24x7_pmu = {
1662 .task_ctx_nr = perf_invalid_context,
1663
1664 .name = "hv_24x7",
1665 .attr_groups = attr_groups,
1666 .event_init = h_24x7_event_init,
1667 .add = h_24x7_event_add,
1668 .del = h_24x7_event_stop,
1669 .start = h_24x7_event_start,
1670 .stop = h_24x7_event_stop,
1671 .read = h_24x7_event_read,
1672 .start_txn = h_24x7_event_start_txn,
1673 .commit_txn = h_24x7_event_commit_txn,
1674 .cancel_txn = h_24x7_event_cancel_txn,
1675 .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
1676 };
1677
1678 static int ppc_hv_24x7_cpu_online(unsigned int cpu)
1679 {
1680 if (cpumask_empty(&hv_24x7_cpumask))
1681 cpumask_set_cpu(cpu, &hv_24x7_cpumask);
1682
1683 return 0;
1684 }
1685
1686 static int ppc_hv_24x7_cpu_offline(unsigned int cpu)
1687 {
1688 int target;
1689
1690
1691 if (!cpumask_test_and_clear_cpu(cpu, &hv_24x7_cpumask))
1692 return 0;
1693
1694
1695 target = cpumask_last(cpu_active_mask);
1696
1697 if (target < 0 || target >= nr_cpu_ids) {
1698 pr_err("hv_24x7: CPU hotplug init failed\n");
1699 return -1;
1700 }
1701
1702
1703 cpumask_set_cpu(target, &hv_24x7_cpumask);
1704 perf_pmu_migrate_context(&h_24x7_pmu, cpu, target);
1705
1706 return 0;
1707 }
1708
1709 static int hv_24x7_cpu_hotplug_init(void)
1710 {
1711 return cpuhp_setup_state(CPUHP_AP_PERF_POWERPC_HV_24x7_ONLINE,
1712 "perf/powerpc/hv_24x7:online",
1713 ppc_hv_24x7_cpu_online,
1714 ppc_hv_24x7_cpu_offline);
1715 }
1716
1717 static int hv_24x7_init(void)
1718 {
1719 int r;
1720 unsigned long hret;
1721 unsigned int pvr = mfspr(SPRN_PVR);
1722 struct hv_perf_caps caps;
1723
1724 if (!firmware_has_feature(FW_FEATURE_LPAR)) {
1725 pr_debug("not a virtualized system, not enabling\n");
1726 return -ENODEV;
1727 }
1728
1729
1730 if (PVR_VER(pvr) == PVR_POWER8)
1731 interface_version = 1;
1732 else {
1733 interface_version = 2;
1734
1735
1736 if (threads_per_core == 8)
1737 aggregate_result_elements = true;
1738 }
1739
1740 hret = hv_perf_caps_get(&caps);
1741 if (hret) {
1742 pr_debug("could not obtain capabilities, not enabling, rc=%ld\n",
1743 hret);
1744 return -ENODEV;
1745 }
1746
1747 hv_page_cache = kmem_cache_create("hv-page-4096", 4096, 4096, 0, NULL);
1748 if (!hv_page_cache)
1749 return -ENOMEM;
1750
1751
1752 h_24x7_pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
1753
1754 r = create_events_from_catalog(&event_group.attrs,
1755 &event_desc_group.attrs,
1756 &event_long_desc_group.attrs);
1757
1758 if (r)
1759 return r;
1760
1761
1762 r = hv_24x7_cpu_hotplug_init();
1763 if (r)
1764 return r;
1765
1766 r = perf_pmu_register(&h_24x7_pmu, h_24x7_pmu.name, -1);
1767 if (r)
1768 return r;
1769
1770 read_24x7_sys_info();
1771
1772 return 0;
1773 }
1774
1775 device_initcall(hv_24x7_init);