1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Hypervisor supplied "gpci" ("get performance counter info") performance 4 * counter support 5 * 6 * Author: Cody P Schafer <cody@linux.vnet.ibm.com> 7 * Copyright 2014 IBM Corporation. 8 */ 9 10 #define pr_fmt(fmt) "hv-gpci: " fmt 11 12 #include <linux/init.h> 13 #include <linux/perf_event.h> 14 #include <linux/sysfs.h> 15 #include <asm/firmware.h> 16 #include <asm/hvcall.h> 17 #include <asm/io.h> 18 19 #include "hv-gpci.h" 20 #include "hv-common.h" 21 22 /* 23 * Example usage: 24 * perf stat -e 'hv_gpci/counter_info_version=3,offset=0,length=8, 25 * secondary_index=0,starting_index=0xffffffff,request=0x10/' ... 26 */ 27 28 /* u32 */ 29 EVENT_DEFINE_RANGE_FORMAT(request, config, 0, 31); 30 /* u32 */ 31 /* 32 * Note that starting_index, phys_processor_idx, sibling_part_id, 33 * hw_chip_id, partition_id all refer to the same bit range. They 34 * are basically aliases for the starting_index. The specific alias 35 * used depends on the event. See REQUEST_IDX_KIND in hv-gpci-requests.h 36 */ 37 EVENT_DEFINE_RANGE_FORMAT(starting_index, config, 32, 63); 38 EVENT_DEFINE_RANGE_FORMAT_LITE(phys_processor_idx, config, 32, 63); 39 EVENT_DEFINE_RANGE_FORMAT_LITE(sibling_part_id, config, 32, 63); 40 EVENT_DEFINE_RANGE_FORMAT_LITE(hw_chip_id, config, 32, 63); 41 EVENT_DEFINE_RANGE_FORMAT_LITE(partition_id, config, 32, 63); 42 43 /* u16 */ 44 EVENT_DEFINE_RANGE_FORMAT(secondary_index, config1, 0, 15); 45 /* u8 */ 46 EVENT_DEFINE_RANGE_FORMAT(counter_info_version, config1, 16, 23); 47 /* u8, bytes of data (1-8) */ 48 EVENT_DEFINE_RANGE_FORMAT(length, config1, 24, 31); 49 /* u32, byte offset */ 50 EVENT_DEFINE_RANGE_FORMAT(offset, config1, 32, 63); 51 52 static cpumask_t hv_gpci_cpumask; 53 54 static struct attribute *format_attrs[] = { 55 &format_attr_request.attr, 56 &format_attr_starting_index.attr, 57 &format_attr_phys_processor_idx.attr, 58 &format_attr_sibling_part_id.attr, 59 &format_attr_hw_chip_id.attr, 60 &format_attr_partition_id.attr, 61 &format_attr_secondary_index.attr, 62 &format_attr_counter_info_version.attr, 63 64 &format_attr_offset.attr, 65 &format_attr_length.attr, 66 NULL, 67 }; 68 69 static const struct attribute_group format_group = { 70 .name = "format", 71 .attrs = format_attrs, 72 }; 73 74 static struct attribute_group event_group = { 75 .name = "events", 76 /* .attrs is set in init */ 77 }; 78 79 #define HV_CAPS_ATTR(_name, _format) \ 80 static ssize_t _name##_show(struct device *dev, \ 81 struct device_attribute *attr, \ 82 char *page) \ 83 { \ 84 struct hv_perf_caps caps; \ 85 unsigned long hret = hv_perf_caps_get(&caps); \ 86 if (hret) \ 87 return -EIO; \ 88 \ 89 return sysfs_emit(page, _format, caps._name); \ 90 } \ 91 static struct device_attribute hv_caps_attr_##_name = __ATTR_RO(_name) 92 93 static ssize_t kernel_version_show(struct device *dev, 94 struct device_attribute *attr, 95 char *page) 96 { 97 return sysfs_emit(page, "0x%x\n", COUNTER_INFO_VERSION_CURRENT); 98 } 99 100 static ssize_t cpumask_show(struct device *dev, 101 struct device_attribute *attr, char *buf) 102 { 103 return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(&hv_gpci_cpumask)); 104 } 105 106 /* Interface attribute array index to store system information */ 107 #define INTERFACE_PROCESSOR_BUS_TOPOLOGY_ATTR 6 108 #define INTERFACE_PROCESSOR_CONFIG_ATTR 7 109 #define INTERFACE_AFFINITY_DOMAIN_VIA_VP_ATTR 8 110 #define INTERFACE_AFFINITY_DOMAIN_VIA_DOM_ATTR 9 111 #define INTERFACE_AFFINITY_DOMAIN_VIA_PAR_ATTR 10 112 #define INTERFACE_NULL_ATTR 11 113 114 /* Counter request value to retrieve system information */ 115 enum { 116 PROCESSOR_BUS_TOPOLOGY, 117 PROCESSOR_CONFIG, 118 AFFINITY_DOMAIN_VIA_VP, /* affinity domain via virtual processor */ 119 AFFINITY_DOMAIN_VIA_DOM, /* affinity domain via domain */ 120 AFFINITY_DOMAIN_VIA_PAR, /* affinity domain via partition */ 121 }; 122 123 static int sysinfo_counter_request[] = { 124 [PROCESSOR_BUS_TOPOLOGY] = 0xD0, 125 [PROCESSOR_CONFIG] = 0x90, 126 [AFFINITY_DOMAIN_VIA_VP] = 0xA0, 127 [AFFINITY_DOMAIN_VIA_DOM] = 0xB0, 128 [AFFINITY_DOMAIN_VIA_PAR] = 0xB1, 129 }; 130 131 static DEFINE_PER_CPU(char, hv_gpci_reqb[HGPCI_REQ_BUFFER_SIZE]) __aligned(sizeof(uint64_t)); 132 133 static unsigned long systeminfo_gpci_request(u32 req, u32 starting_index, 134 u16 secondary_index, char *buf, 135 size_t *n, struct hv_gpci_request_buffer *arg) 136 { 137 unsigned long ret; 138 size_t i, j; 139 140 arg->params.counter_request = cpu_to_be32(req); 141 arg->params.starting_index = cpu_to_be32(starting_index); 142 arg->params.secondary_index = cpu_to_be16(secondary_index); 143 144 ret = plpar_hcall_norets(H_GET_PERF_COUNTER_INFO, 145 virt_to_phys(arg), HGPCI_REQ_BUFFER_SIZE); 146 147 /* 148 * ret value as 'H_PARAMETER' corresponds to 'GEN_BUF_TOO_SMALL', 149 * which means that the current buffer size cannot accommodate 150 * all the information and a partial buffer returned. 151 * hcall fails incase of ret value other than H_SUCCESS or H_PARAMETER. 152 * 153 * ret value as H_AUTHORITY implies that partition is not permitted to retrieve 154 * performance information, and required to set 155 * "Enable Performance Information Collection" option. 156 */ 157 if (ret == H_AUTHORITY) 158 return -EPERM; 159 160 /* 161 * hcall can fail with other possible ret value like H_PRIVILEGE/H_HARDWARE 162 * because of invalid buffer-length/address or due to some hardware 163 * error. 164 */ 165 if (ret && (ret != H_PARAMETER)) 166 return -EIO; 167 168 /* 169 * hcall H_GET_PERF_COUNTER_INFO populates the 'returned_values' 170 * to show the total number of counter_value array elements 171 * returned via hcall. 172 * hcall also populates 'cv_element_size' corresponds to individual 173 * counter_value array element size. Below loop go through all 174 * counter_value array elements as per their size and add it to 175 * the output buffer. 176 */ 177 for (i = 0; i < be16_to_cpu(arg->params.returned_values); i++) { 178 j = i * be16_to_cpu(arg->params.cv_element_size); 179 180 for (; j < (i + 1) * be16_to_cpu(arg->params.cv_element_size); j++) 181 *n += sprintf(buf + *n, "%02x", (u8)arg->bytes[j]); 182 *n += sprintf(buf + *n, "\n"); 183 } 184 185 if (*n >= PAGE_SIZE) { 186 pr_info("System information exceeds PAGE_SIZE\n"); 187 return -EFBIG; 188 } 189 190 return ret; 191 } 192 193 static ssize_t processor_bus_topology_show(struct device *dev, struct device_attribute *attr, 194 char *buf) 195 { 196 struct hv_gpci_request_buffer *arg; 197 unsigned long ret; 198 size_t n = 0; 199 200 arg = (void *)get_cpu_var(hv_gpci_reqb); 201 memset(arg, 0, HGPCI_REQ_BUFFER_SIZE); 202 203 /* 204 * Pass the counter request value 0xD0 corresponds to request 205 * type 'Processor_bus_topology', to retrieve 206 * the system topology information. 207 * starting_index value implies the starting hardware 208 * chip id. 209 */ 210 ret = systeminfo_gpci_request(sysinfo_counter_request[PROCESSOR_BUS_TOPOLOGY], 211 0, 0, buf, &n, arg); 212 213 if (!ret) 214 goto out_success; 215 216 if (ret != H_PARAMETER) 217 goto out; 218 219 /* 220 * ret value as 'H_PARAMETER' corresponds to 'GEN_BUF_TOO_SMALL', which 221 * implies that buffer can't accommodate all information, and a partial buffer 222 * returned. To handle that, we need to make subsequent requests 223 * with next starting index to retrieve additional (missing) data. 224 * Below loop do subsequent hcalls with next starting index and add it 225 * to buffer util we get all the information. 226 */ 227 while (ret == H_PARAMETER) { 228 int returned_values = be16_to_cpu(arg->params.returned_values); 229 int elementsize = be16_to_cpu(arg->params.cv_element_size); 230 int last_element = (returned_values - 1) * elementsize; 231 232 /* 233 * Since the starting index value is part of counter_value 234 * buffer elements, use the starting index value in the last 235 * element and add 1 to make subsequent hcalls. 236 */ 237 u32 starting_index = arg->bytes[last_element + 3] + 238 (arg->bytes[last_element + 2] << 8) + 239 (arg->bytes[last_element + 1] << 16) + 240 (arg->bytes[last_element] << 24) + 1; 241 242 memset(arg, 0, HGPCI_REQ_BUFFER_SIZE); 243 244 ret = systeminfo_gpci_request(sysinfo_counter_request[PROCESSOR_BUS_TOPOLOGY], 245 starting_index, 0, buf, &n, arg); 246 247 if (!ret) 248 goto out_success; 249 250 if (ret != H_PARAMETER) 251 goto out; 252 } 253 254 out_success: 255 put_cpu_var(hv_gpci_reqb); 256 return n; 257 258 out: 259 put_cpu_var(hv_gpci_reqb); 260 return ret; 261 } 262 263 static ssize_t processor_config_show(struct device *dev, struct device_attribute *attr, 264 char *buf) 265 { 266 struct hv_gpci_request_buffer *arg; 267 unsigned long ret; 268 size_t n = 0; 269 270 arg = (void *)get_cpu_var(hv_gpci_reqb); 271 memset(arg, 0, HGPCI_REQ_BUFFER_SIZE); 272 273 /* 274 * Pass the counter request value 0x90 corresponds to request 275 * type 'Processor_config', to retrieve 276 * the system processor information. 277 * starting_index value implies the starting hardware 278 * processor index. 279 */ 280 ret = systeminfo_gpci_request(sysinfo_counter_request[PROCESSOR_CONFIG], 281 0, 0, buf, &n, arg); 282 283 if (!ret) 284 goto out_success; 285 286 if (ret != H_PARAMETER) 287 goto out; 288 289 /* 290 * ret value as 'H_PARAMETER' corresponds to 'GEN_BUF_TOO_SMALL', which 291 * implies that buffer can't accommodate all information, and a partial buffer 292 * returned. To handle that, we need to take subsequent requests 293 * with next starting index to retrieve additional (missing) data. 294 * Below loop do subsequent hcalls with next starting index and add it 295 * to buffer util we get all the information. 296 */ 297 while (ret == H_PARAMETER) { 298 int returned_values = be16_to_cpu(arg->params.returned_values); 299 int elementsize = be16_to_cpu(arg->params.cv_element_size); 300 int last_element = (returned_values - 1) * elementsize; 301 302 /* 303 * Since the starting index is part of counter_value 304 * buffer elements, use the starting index value in the last 305 * element and add 1 to subsequent hcalls. 306 */ 307 u32 starting_index = arg->bytes[last_element + 3] + 308 (arg->bytes[last_element + 2] << 8) + 309 (arg->bytes[last_element + 1] << 16) + 310 (arg->bytes[last_element] << 24) + 1; 311 312 memset(arg, 0, HGPCI_REQ_BUFFER_SIZE); 313 314 ret = systeminfo_gpci_request(sysinfo_counter_request[PROCESSOR_CONFIG], 315 starting_index, 0, buf, &n, arg); 316 317 if (!ret) 318 goto out_success; 319 320 if (ret != H_PARAMETER) 321 goto out; 322 } 323 324 out_success: 325 put_cpu_var(hv_gpci_reqb); 326 return n; 327 328 out: 329 put_cpu_var(hv_gpci_reqb); 330 return ret; 331 } 332 333 static ssize_t affinity_domain_via_virtual_processor_show(struct device *dev, 334 struct device_attribute *attr, char *buf) 335 { 336 struct hv_gpci_request_buffer *arg; 337 unsigned long ret; 338 size_t n = 0; 339 340 arg = (void *)get_cpu_var(hv_gpci_reqb); 341 memset(arg, 0, HGPCI_REQ_BUFFER_SIZE); 342 343 /* 344 * Pass the counter request 0xA0 corresponds to request 345 * type 'Affinity_domain_information_by_virutal_processor', 346 * to retrieve the system affinity domain information. 347 * starting_index value refers to the starting hardware 348 * processor index. 349 */ 350 ret = systeminfo_gpci_request(sysinfo_counter_request[AFFINITY_DOMAIN_VIA_VP], 351 0, 0, buf, &n, arg); 352 353 if (!ret) 354 goto out_success; 355 356 if (ret != H_PARAMETER) 357 goto out; 358 359 /* 360 * ret value as 'H_PARAMETER' corresponds to 'GEN_BUF_TOO_SMALL', which 361 * implies that buffer can't accommodate all information, and a partial buffer 362 * returned. To handle that, we need to take subsequent requests 363 * with next secondary index to retrieve additional (missing) data. 364 * Below loop do subsequent hcalls with next secondary index and add it 365 * to buffer util we get all the information. 366 */ 367 while (ret == H_PARAMETER) { 368 int returned_values = be16_to_cpu(arg->params.returned_values); 369 int elementsize = be16_to_cpu(arg->params.cv_element_size); 370 int last_element = (returned_values - 1) * elementsize; 371 372 /* 373 * Since the starting index and secondary index type is part of the 374 * counter_value buffer elements, use the starting index value in the 375 * last array element as subsequent starting index, and use secondary index 376 * value in the last array element plus 1 as subsequent secondary index. 377 * For counter request '0xA0', starting index points to partition id 378 * and secondary index points to corresponding virtual processor index. 379 */ 380 u32 starting_index = arg->bytes[last_element + 1] + (arg->bytes[last_element] << 8); 381 u16 secondary_index = arg->bytes[last_element + 3] + 382 (arg->bytes[last_element + 2] << 8) + 1; 383 384 memset(arg, 0, HGPCI_REQ_BUFFER_SIZE); 385 386 ret = systeminfo_gpci_request(sysinfo_counter_request[AFFINITY_DOMAIN_VIA_VP], 387 starting_index, secondary_index, buf, &n, arg); 388 389 if (!ret) 390 goto out_success; 391 392 if (ret != H_PARAMETER) 393 goto out; 394 } 395 396 out_success: 397 put_cpu_var(hv_gpci_reqb); 398 return n; 399 400 out: 401 put_cpu_var(hv_gpci_reqb); 402 return ret; 403 } 404 405 static ssize_t affinity_domain_via_domain_show(struct device *dev, struct device_attribute *attr, 406 char *buf) 407 { 408 struct hv_gpci_request_buffer *arg; 409 unsigned long ret; 410 size_t n = 0; 411 412 arg = (void *)get_cpu_var(hv_gpci_reqb); 413 memset(arg, 0, HGPCI_REQ_BUFFER_SIZE); 414 415 /* 416 * Pass the counter request 0xB0 corresponds to request 417 * type 'Affinity_domain_information_by_domain', 418 * to retrieve the system affinity domain information. 419 * starting_index value refers to the starting hardware 420 * processor index. 421 */ 422 ret = systeminfo_gpci_request(sysinfo_counter_request[AFFINITY_DOMAIN_VIA_DOM], 423 0, 0, buf, &n, arg); 424 425 if (!ret) 426 goto out_success; 427 428 if (ret != H_PARAMETER) 429 goto out; 430 431 /* 432 * ret value as 'H_PARAMETER' corresponds to 'GEN_BUF_TOO_SMALL', which 433 * implies that buffer can't accommodate all information, and a partial buffer 434 * returned. To handle that, we need to take subsequent requests 435 * with next starting index to retrieve additional (missing) data. 436 * Below loop do subsequent hcalls with next starting index and add it 437 * to buffer util we get all the information. 438 */ 439 while (ret == H_PARAMETER) { 440 int returned_values = be16_to_cpu(arg->params.returned_values); 441 int elementsize = be16_to_cpu(arg->params.cv_element_size); 442 int last_element = (returned_values - 1) * elementsize; 443 444 /* 445 * Since the starting index value is part of counter_value 446 * buffer elements, use the starting index value in the last 447 * element and add 1 to make subsequent hcalls. 448 */ 449 u32 starting_index = arg->bytes[last_element + 1] + 450 (arg->bytes[last_element] << 8) + 1; 451 452 memset(arg, 0, HGPCI_REQ_BUFFER_SIZE); 453 454 ret = systeminfo_gpci_request(sysinfo_counter_request[AFFINITY_DOMAIN_VIA_DOM], 455 starting_index, 0, buf, &n, arg); 456 457 if (!ret) 458 goto out_success; 459 460 if (ret != H_PARAMETER) 461 goto out; 462 } 463 464 out_success: 465 put_cpu_var(hv_gpci_reqb); 466 return n; 467 468 out: 469 put_cpu_var(hv_gpci_reqb); 470 return ret; 471 } 472 473 static void affinity_domain_via_partition_result_parse(int returned_values, 474 int element_size, char *buf, size_t *last_element, 475 size_t *n, struct hv_gpci_request_buffer *arg) 476 { 477 size_t i = 0, j = 0; 478 size_t k, l, m; 479 uint16_t total_affinity_domain_ele, size_of_each_affinity_domain_ele; 480 481 /* 482 * hcall H_GET_PERF_COUNTER_INFO populates the 'returned_values' 483 * to show the total number of counter_value array elements 484 * returned via hcall. 485 * Unlike other request types, the data structure returned by this 486 * request is variable-size. For this counter request type, 487 * hcall populates 'cv_element_size' corresponds to minimum size of 488 * the structure returned i.e; the size of the structure with no domain 489 * information. Below loop go through all counter_value array 490 * to determine the number and size of each domain array element and 491 * add it to the output buffer. 492 */ 493 while (i < returned_values) { 494 k = j; 495 for (; k < j + element_size; k++) 496 *n += sprintf(buf + *n, "%02x", (u8)arg->bytes[k]); 497 *n += sprintf(buf + *n, "\n"); 498 499 total_affinity_domain_ele = (u8)arg->bytes[k - 2] << 8 | (u8)arg->bytes[k - 3]; 500 size_of_each_affinity_domain_ele = (u8)arg->bytes[k] << 8 | (u8)arg->bytes[k - 1]; 501 502 for (l = 0; l < total_affinity_domain_ele; l++) { 503 for (m = 0; m < size_of_each_affinity_domain_ele; m++) { 504 *n += sprintf(buf + *n, "%02x", (u8)arg->bytes[k]); 505 k++; 506 } 507 *n += sprintf(buf + *n, "\n"); 508 } 509 510 *n += sprintf(buf + *n, "\n"); 511 i++; 512 j = k; 513 } 514 515 *last_element = k; 516 } 517 518 static ssize_t affinity_domain_via_partition_show(struct device *dev, struct device_attribute *attr, 519 char *buf) 520 { 521 struct hv_gpci_request_buffer *arg; 522 unsigned long ret; 523 size_t n = 0; 524 size_t last_element = 0; 525 u32 starting_index; 526 527 arg = (void *)get_cpu_var(hv_gpci_reqb); 528 memset(arg, 0, HGPCI_REQ_BUFFER_SIZE); 529 530 /* 531 * Pass the counter request value 0xB1 corresponds to counter request 532 * type 'Affinity_domain_information_by_partition', 533 * to retrieve the system affinity domain by partition information. 534 * starting_index value refers to the starting hardware 535 * processor index. 536 */ 537 arg->params.counter_request = cpu_to_be32(sysinfo_counter_request[AFFINITY_DOMAIN_VIA_PAR]); 538 arg->params.starting_index = cpu_to_be32(0); 539 540 ret = plpar_hcall_norets(H_GET_PERF_COUNTER_INFO, 541 virt_to_phys(arg), HGPCI_REQ_BUFFER_SIZE); 542 543 if (!ret) 544 goto parse_result; 545 546 if (ret && (ret != H_PARAMETER)) 547 goto out; 548 549 /* 550 * ret value as 'H_PARAMETER' implies that the current buffer size 551 * can't accommodate all the information, and a partial buffer 552 * returned. To handle that, we need to make subsequent requests 553 * with next starting index to retrieve additional (missing) data. 554 * Below loop do subsequent hcalls with next starting index and add it 555 * to buffer util we get all the information. 556 */ 557 while (ret == H_PARAMETER) { 558 affinity_domain_via_partition_result_parse( 559 be16_to_cpu(arg->params.returned_values) - 1, 560 be16_to_cpu(arg->params.cv_element_size), buf, 561 &last_element, &n, arg); 562 563 if (n >= PAGE_SIZE) { 564 put_cpu_var(hv_gpci_reqb); 565 pr_debug("System information exceeds PAGE_SIZE\n"); 566 return -EFBIG; 567 } 568 569 /* 570 * Since the starting index value is part of counter_value 571 * buffer elements, use the starting_index value in the last 572 * element and add 1 to make subsequent hcalls. 573 */ 574 starting_index = (u8)arg->bytes[last_element] << 8 | 575 (u8)arg->bytes[last_element + 1]; 576 577 memset(arg, 0, HGPCI_REQ_BUFFER_SIZE); 578 arg->params.counter_request = cpu_to_be32( 579 sysinfo_counter_request[AFFINITY_DOMAIN_VIA_PAR]); 580 arg->params.starting_index = cpu_to_be32(starting_index); 581 582 ret = plpar_hcall_norets(H_GET_PERF_COUNTER_INFO, 583 virt_to_phys(arg), HGPCI_REQ_BUFFER_SIZE); 584 585 if (ret && (ret != H_PARAMETER)) 586 goto out; 587 } 588 589 parse_result: 590 affinity_domain_via_partition_result_parse( 591 be16_to_cpu(arg->params.returned_values), 592 be16_to_cpu(arg->params.cv_element_size), 593 buf, &last_element, &n, arg); 594 595 put_cpu_var(hv_gpci_reqb); 596 return n; 597 598 out: 599 put_cpu_var(hv_gpci_reqb); 600 601 /* 602 * ret value as 'H_PARAMETER' corresponds to 'GEN_BUF_TOO_SMALL', 603 * which means that the current buffer size cannot accommodate 604 * all the information and a partial buffer returned. 605 * hcall fails incase of ret value other than H_SUCCESS or H_PARAMETER. 606 * 607 * ret value as H_AUTHORITY implies that partition is not permitted to retrieve 608 * performance information, and required to set 609 * "Enable Performance Information Collection" option. 610 */ 611 if (ret == H_AUTHORITY) 612 return -EPERM; 613 614 /* 615 * hcall can fail with other possible ret value like H_PRIVILEGE/H_HARDWARE 616 * because of invalid buffer-length/address or due to some hardware 617 * error. 618 */ 619 return -EIO; 620 } 621 622 static DEVICE_ATTR_RO(kernel_version); 623 static DEVICE_ATTR_RO(cpumask); 624 625 HV_CAPS_ATTR(version, "0x%x\n"); 626 HV_CAPS_ATTR(ga, "%d\n"); 627 HV_CAPS_ATTR(expanded, "%d\n"); 628 HV_CAPS_ATTR(lab, "%d\n"); 629 HV_CAPS_ATTR(collect_privileged, "%d\n"); 630 631 static struct attribute *interface_attrs[] = { 632 &dev_attr_kernel_version.attr, 633 &hv_caps_attr_version.attr, 634 &hv_caps_attr_ga.attr, 635 &hv_caps_attr_expanded.attr, 636 &hv_caps_attr_lab.attr, 637 &hv_caps_attr_collect_privileged.attr, 638 /* 639 * This NULL is a placeholder for the processor_bus_topology 640 * attribute, set in init function if applicable. 641 */ 642 NULL, 643 /* 644 * This NULL is a placeholder for the processor_config 645 * attribute, set in init function if applicable. 646 */ 647 NULL, 648 /* 649 * This NULL is a placeholder for the affinity_domain_via_virtual_processor 650 * attribute, set in init function if applicable. 651 */ 652 NULL, 653 /* 654 * This NULL is a placeholder for the affinity_domain_via_domain 655 * attribute, set in init function if applicable. 656 */ 657 NULL, 658 /* 659 * This NULL is a placeholder for the affinity_domain_via_partition 660 * attribute, set in init function if applicable. 661 */ 662 NULL, 663 NULL, 664 }; 665 666 static struct attribute *cpumask_attrs[] = { 667 &dev_attr_cpumask.attr, 668 NULL, 669 }; 670 671 static const struct attribute_group cpumask_attr_group = { 672 .attrs = cpumask_attrs, 673 }; 674 675 static const struct attribute_group interface_group = { 676 .name = "interface", 677 .attrs = interface_attrs, 678 }; 679 680 static const struct attribute_group *attr_groups[] = { 681 &format_group, 682 &event_group, 683 &interface_group, 684 &cpumask_attr_group, 685 NULL, 686 }; 687 688 static unsigned long single_gpci_request(u32 req, u32 starting_index, 689 u16 secondary_index, u8 version_in, u32 offset, u8 length, 690 u64 *value) 691 { 692 unsigned long ret; 693 size_t i; 694 u64 count; 695 struct hv_gpci_request_buffer *arg; 696 697 arg = (void *)get_cpu_var(hv_gpci_reqb); 698 memset(arg, 0, HGPCI_REQ_BUFFER_SIZE); 699 700 arg->params.counter_request = cpu_to_be32(req); 701 arg->params.starting_index = cpu_to_be32(starting_index); 702 arg->params.secondary_index = cpu_to_be16(secondary_index); 703 arg->params.counter_info_version_in = version_in; 704 705 ret = plpar_hcall_norets(H_GET_PERF_COUNTER_INFO, 706 virt_to_phys(arg), HGPCI_REQ_BUFFER_SIZE); 707 708 /* 709 * ret value as 'H_PARAMETER' with detail_rc as 'GEN_BUF_TOO_SMALL', 710 * specifies that the current buffer size cannot accommodate 711 * all the information and a partial buffer returned. 712 * Since in this function we are only accessing data for a given starting index, 713 * we don't need to accommodate whole data and can get required count by 714 * accessing first entry data. 715 * Hence hcall fails only incase the ret value is other than H_SUCCESS or 716 * H_PARAMETER with detail_rc value as GEN_BUF_TOO_SMALL(0x1B). 717 */ 718 if (ret == H_PARAMETER && be32_to_cpu(arg->params.detail_rc) == 0x1B) 719 ret = 0; 720 721 if (ret) { 722 pr_devel("hcall failed: 0x%lx\n", ret); 723 goto out; 724 } 725 726 /* 727 * we verify offset and length are within the zeroed buffer at event 728 * init. 729 */ 730 count = 0; 731 for (i = offset; i < offset + length; i++) 732 count |= (u64)(arg->bytes[i]) << ((length - 1 - (i - offset)) * 8); 733 734 *value = count; 735 out: 736 put_cpu_var(hv_gpci_reqb); 737 return ret; 738 } 739 740 static u64 h_gpci_get_value(struct perf_event *event) 741 { 742 u64 count; 743 unsigned long ret = single_gpci_request(event_get_request(event), 744 event_get_starting_index(event), 745 event_get_secondary_index(event), 746 event_get_counter_info_version(event), 747 event_get_offset(event), 748 event_get_length(event), 749 &count); 750 if (ret) 751 return 0; 752 return count; 753 } 754 755 static void h_gpci_event_update(struct perf_event *event) 756 { 757 s64 prev; 758 u64 now = h_gpci_get_value(event); 759 prev = local64_xchg(&event->hw.prev_count, now); 760 local64_add(now - prev, &event->count); 761 } 762 763 static void h_gpci_event_start(struct perf_event *event, int flags) 764 { 765 local64_set(&event->hw.prev_count, h_gpci_get_value(event)); 766 } 767 768 static void h_gpci_event_stop(struct perf_event *event, int flags) 769 { 770 h_gpci_event_update(event); 771 } 772 773 static int h_gpci_event_add(struct perf_event *event, int flags) 774 { 775 if (flags & PERF_EF_START) 776 h_gpci_event_start(event, flags); 777 778 return 0; 779 } 780 781 static int h_gpci_event_init(struct perf_event *event) 782 { 783 u64 count; 784 u8 length; 785 unsigned long ret; 786 787 /* Not our event */ 788 if (event->attr.type != event->pmu->type) 789 return -ENOENT; 790 791 /* config2 is unused */ 792 if (event->attr.config2) { 793 pr_devel("config2 set when reserved\n"); 794 return -EINVAL; 795 } 796 797 /* no branch sampling */ 798 if (has_branch_stack(event)) 799 return -EOPNOTSUPP; 800 801 length = event_get_length(event); 802 if (length < 1 || length > 8) { 803 pr_devel("length invalid\n"); 804 return -EINVAL; 805 } 806 807 /* last byte within the buffer? */ 808 if ((event_get_offset(event) + length) > HGPCI_MAX_DATA_BYTES) { 809 pr_devel("request outside of buffer: %zu > %zu\n", 810 (size_t)event_get_offset(event) + length, 811 HGPCI_MAX_DATA_BYTES); 812 return -EINVAL; 813 } 814 815 /* check if the request works... */ 816 ret = single_gpci_request(event_get_request(event), 817 event_get_starting_index(event), 818 event_get_secondary_index(event), 819 event_get_counter_info_version(event), 820 event_get_offset(event), 821 length, 822 &count); 823 824 /* 825 * ret value as H_AUTHORITY implies that partition is not permitted to retrieve 826 * performance information, and required to set 827 * "Enable Performance Information Collection" option. 828 */ 829 if (ret == H_AUTHORITY) 830 return -EPERM; 831 832 if (ret) { 833 pr_devel("gpci hcall failed\n"); 834 return -EINVAL; 835 } 836 837 return 0; 838 } 839 840 static struct pmu h_gpci_pmu = { 841 .task_ctx_nr = perf_invalid_context, 842 843 .name = "hv_gpci", 844 .attr_groups = attr_groups, 845 .event_init = h_gpci_event_init, 846 .add = h_gpci_event_add, 847 .del = h_gpci_event_stop, 848 .start = h_gpci_event_start, 849 .stop = h_gpci_event_stop, 850 .read = h_gpci_event_update, 851 .capabilities = PERF_PMU_CAP_NO_EXCLUDE, 852 }; 853 854 static int ppc_hv_gpci_cpu_online(unsigned int cpu) 855 { 856 if (cpumask_empty(&hv_gpci_cpumask)) 857 cpumask_set_cpu(cpu, &hv_gpci_cpumask); 858 859 return 0; 860 } 861 862 static int ppc_hv_gpci_cpu_offline(unsigned int cpu) 863 { 864 int target; 865 866 /* Check if exiting cpu is used for collecting gpci events */ 867 if (!cpumask_test_and_clear_cpu(cpu, &hv_gpci_cpumask)) 868 return 0; 869 870 /* Find a new cpu to collect gpci events */ 871 target = cpumask_last(cpu_active_mask); 872 873 if (target < 0 || target >= nr_cpu_ids) { 874 pr_err("hv_gpci: CPU hotplug init failed\n"); 875 return -1; 876 } 877 878 /* Migrate gpci events to the new target */ 879 cpumask_set_cpu(target, &hv_gpci_cpumask); 880 perf_pmu_migrate_context(&h_gpci_pmu, cpu, target); 881 882 return 0; 883 } 884 885 static int hv_gpci_cpu_hotplug_init(void) 886 { 887 return cpuhp_setup_state(CPUHP_AP_PERF_POWERPC_HV_GPCI_ONLINE, 888 "perf/powerpc/hv_gcpi:online", 889 ppc_hv_gpci_cpu_online, 890 ppc_hv_gpci_cpu_offline); 891 } 892 893 static struct device_attribute *sysinfo_device_attr_create(int 894 sysinfo_interface_group_index, u32 req) 895 { 896 struct device_attribute *attr = NULL; 897 unsigned long ret; 898 struct hv_gpci_request_buffer *arg; 899 900 if (sysinfo_interface_group_index < INTERFACE_PROCESSOR_BUS_TOPOLOGY_ATTR || 901 sysinfo_interface_group_index >= INTERFACE_NULL_ATTR) { 902 pr_info("Wrong interface group index for system information\n"); 903 return NULL; 904 } 905 906 /* Check for given counter request value support */ 907 arg = (void *)get_cpu_var(hv_gpci_reqb); 908 memset(arg, 0, HGPCI_REQ_BUFFER_SIZE); 909 910 arg->params.counter_request = cpu_to_be32(req); 911 912 ret = plpar_hcall_norets(H_GET_PERF_COUNTER_INFO, 913 virt_to_phys(arg), HGPCI_REQ_BUFFER_SIZE); 914 915 put_cpu_var(hv_gpci_reqb); 916 917 /* 918 * Add given counter request value attribute in the interface_attrs 919 * attribute array, only for valid return types. 920 */ 921 if (!ret || ret == H_AUTHORITY || ret == H_PARAMETER) { 922 attr = kzalloc_obj(*attr); 923 if (!attr) 924 return NULL; 925 926 sysfs_attr_init(&attr->attr); 927 attr->attr.mode = 0444; 928 929 switch (sysinfo_interface_group_index) { 930 case INTERFACE_PROCESSOR_BUS_TOPOLOGY_ATTR: 931 attr->attr.name = "processor_bus_topology"; 932 attr->show = processor_bus_topology_show; 933 break; 934 case INTERFACE_PROCESSOR_CONFIG_ATTR: 935 attr->attr.name = "processor_config"; 936 attr->show = processor_config_show; 937 break; 938 case INTERFACE_AFFINITY_DOMAIN_VIA_VP_ATTR: 939 attr->attr.name = "affinity_domain_via_virtual_processor"; 940 attr->show = affinity_domain_via_virtual_processor_show; 941 break; 942 case INTERFACE_AFFINITY_DOMAIN_VIA_DOM_ATTR: 943 attr->attr.name = "affinity_domain_via_domain"; 944 attr->show = affinity_domain_via_domain_show; 945 break; 946 case INTERFACE_AFFINITY_DOMAIN_VIA_PAR_ATTR: 947 attr->attr.name = "affinity_domain_via_partition"; 948 attr->show = affinity_domain_via_partition_show; 949 break; 950 } 951 } else 952 pr_devel("hcall failed, with error: 0x%lx\n", ret); 953 954 return attr; 955 } 956 957 static void add_sysinfo_interface_files(void) 958 { 959 int sysfs_count; 960 struct device_attribute *attr[INTERFACE_NULL_ATTR - INTERFACE_PROCESSOR_BUS_TOPOLOGY_ATTR]; 961 int i; 962 963 sysfs_count = INTERFACE_NULL_ATTR - INTERFACE_PROCESSOR_BUS_TOPOLOGY_ATTR; 964 965 /* Get device attribute for a given counter request value */ 966 for (i = 0; i < sysfs_count; i++) { 967 attr[i] = sysinfo_device_attr_create(i + INTERFACE_PROCESSOR_BUS_TOPOLOGY_ATTR, 968 sysinfo_counter_request[i]); 969 970 if (!attr[i]) 971 goto out; 972 } 973 974 /* Add sysinfo interface attributes in the interface_attrs attribute array */ 975 for (i = 0; i < sysfs_count; i++) 976 interface_attrs[i + INTERFACE_PROCESSOR_BUS_TOPOLOGY_ATTR] = &attr[i]->attr; 977 978 return; 979 980 out: 981 /* 982 * The sysinfo interface attributes will be added, only if hcall passed for 983 * all the counter request values. Free the device attribute array incase 984 * of any hcall failure. 985 */ 986 if (i > 0) { 987 while (i >= 0) { 988 kfree(attr[i]); 989 i--; 990 } 991 } 992 } 993 994 static int hv_gpci_init(void) 995 { 996 int r; 997 unsigned long hret; 998 struct hv_perf_caps caps; 999 struct hv_gpci_request_buffer *arg; 1000 1001 hv_gpci_assert_offsets_correct(); 1002 1003 if (!firmware_has_feature(FW_FEATURE_LPAR)) { 1004 pr_debug("not a virtualized system, not enabling\n"); 1005 return -ENODEV; 1006 } 1007 1008 hret = hv_perf_caps_get(&caps); 1009 if (hret) { 1010 pr_debug("could not obtain capabilities, not enabling, rc=%ld\n", 1011 hret); 1012 return -ENODEV; 1013 } 1014 1015 /* init cpuhotplug */ 1016 r = hv_gpci_cpu_hotplug_init(); 1017 if (r) 1018 return r; 1019 1020 /* sampling not supported */ 1021 h_gpci_pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT; 1022 1023 arg = (void *)get_cpu_var(hv_gpci_reqb); 1024 memset(arg, 0, HGPCI_REQ_BUFFER_SIZE); 1025 1026 /* 1027 * hcall H_GET_PERF_COUNTER_INFO populates the output 1028 * counter_info_version value based on the system hypervisor. 1029 * Pass the counter request 0x10 corresponds to request type 1030 * 'Dispatch_timebase_by_processor', to get the supported 1031 * counter_info_version. 1032 */ 1033 arg->params.counter_request = cpu_to_be32(0x10); 1034 1035 r = plpar_hcall_norets(H_GET_PERF_COUNTER_INFO, 1036 virt_to_phys(arg), HGPCI_REQ_BUFFER_SIZE); 1037 if (r) { 1038 pr_devel("hcall failed, can't get supported counter_info_version: 0x%x\n", r); 1039 arg->params.counter_info_version_out = 0x8; 1040 } 1041 1042 /* 1043 * Use counter_info_version_out value to assign 1044 * required hv-gpci event list. 1045 */ 1046 if (arg->params.counter_info_version_out >= 0x8) 1047 event_group.attrs = hv_gpci_event_attrs; 1048 else 1049 event_group.attrs = hv_gpci_event_attrs_v6; 1050 1051 put_cpu_var(hv_gpci_reqb); 1052 1053 r = perf_pmu_register(&h_gpci_pmu, h_gpci_pmu.name, -1); 1054 if (r) 1055 return r; 1056 1057 /* sysinfo interface files are only available for power10 and above platforms */ 1058 if (PVR_VER(mfspr(SPRN_PVR)) >= PVR_POWER10) 1059 add_sysinfo_interface_files(); 1060 1061 return 0; 1062 } 1063 1064 device_initcall(hv_gpci_init); 1065