1/* 2 * Hypervisor supplied "gpci" ("get performance counter info") performance 3 * counter support 4 * 5 * Author: Cody P Schafer <cody@linux.vnet.ibm.com> 6 * Copyright 2014 IBM Corporation. 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License 10 * as published by the Free Software Foundation; either version 11 * 2 of the License, or (at your option) any later version. 12 */ 13 14#define pr_fmt(fmt) "hv-gpci: " fmt 15 16#include <linux/init.h> 17#include <linux/perf_event.h> 18#include <asm/firmware.h> 19#include <asm/hvcall.h> 20#include <asm/io.h> 21 22#include "hv-gpci.h" 23#include "hv-common.h" 24 25/* 26 * Example usage: 27 * perf stat -e 'hv_gpci/counter_info_version=3,offset=0,length=8, 28 * secondary_index=0,starting_index=0xffffffff,request=0x10/' ... 29 */ 30 31/* u32 */ 32EVENT_DEFINE_RANGE_FORMAT(request, config, 0, 31); 33/* u32 */ 34/* 35 * Note that starting_index, phys_processor_idx, sibling_part_id, 36 * hw_chip_id, partition_id all refer to the same bit range. They 37 * are basically aliases for the starting_index. The specific alias 38 * used depends on the event. See REQUEST_IDX_KIND in hv-gpci-requests.h 39 */ 40EVENT_DEFINE_RANGE_FORMAT(starting_index, config, 32, 63); 41EVENT_DEFINE_RANGE_FORMAT_LITE(phys_processor_idx, config, 32, 63); 42EVENT_DEFINE_RANGE_FORMAT_LITE(sibling_part_id, config, 32, 63); 43EVENT_DEFINE_RANGE_FORMAT_LITE(hw_chip_id, config, 32, 63); 44EVENT_DEFINE_RANGE_FORMAT_LITE(partition_id, config, 32, 63); 45 46/* u16 */ 47EVENT_DEFINE_RANGE_FORMAT(secondary_index, config1, 0, 15); 48/* u8 */ 49EVENT_DEFINE_RANGE_FORMAT(counter_info_version, config1, 16, 23); 50/* u8, bytes of data (1-8) */ 51EVENT_DEFINE_RANGE_FORMAT(length, config1, 24, 31); 52/* u32, byte offset */ 53EVENT_DEFINE_RANGE_FORMAT(offset, config1, 32, 63); 54 55static struct attribute *format_attrs[] = { 56 &format_attr_request.attr, 57 &format_attr_starting_index.attr, 58 &format_attr_phys_processor_idx.attr, 59 &format_attr_sibling_part_id.attr, 60 &format_attr_hw_chip_id.attr, 61 &format_attr_partition_id.attr, 62 &format_attr_secondary_index.attr, 63 &format_attr_counter_info_version.attr, 64 65 &format_attr_offset.attr, 66 &format_attr_length.attr, 67 NULL, 68}; 69 70static struct attribute_group format_group = { 71 .name = "format", 72 .attrs = format_attrs, 73}; 74 75static struct attribute_group event_group = { 76 .name = "events", 77 .attrs = hv_gpci_event_attrs, 78}; 79 80#define HV_CAPS_ATTR(_name, _format) \ 81static ssize_t _name##_show(struct device *dev, \ 82 struct device_attribute *attr, \ 83 char *page) \ 84{ \ 85 struct hv_perf_caps caps; \ 86 unsigned long hret = hv_perf_caps_get(&caps); \ 87 if (hret) \ 88 return -EIO; \ 89 \ 90 return sprintf(page, _format, caps._name); \ 91} \ 92static struct device_attribute hv_caps_attr_##_name = __ATTR_RO(_name) 93 94static ssize_t kernel_version_show(struct device *dev, 95 struct device_attribute *attr, 96 char *page) 97{ 98 return sprintf(page, "0x%x\n", COUNTER_INFO_VERSION_CURRENT); 99} 100 101static DEVICE_ATTR_RO(kernel_version); 102HV_CAPS_ATTR(version, "0x%x\n"); 103HV_CAPS_ATTR(ga, "%d\n"); 104HV_CAPS_ATTR(expanded, "%d\n"); 105HV_CAPS_ATTR(lab, "%d\n"); 106HV_CAPS_ATTR(collect_privileged, "%d\n"); 107 108static struct attribute *interface_attrs[] = { 109 &dev_attr_kernel_version.attr, 110 &hv_caps_attr_version.attr, 111 &hv_caps_attr_ga.attr, 112 &hv_caps_attr_expanded.attr, 113 &hv_caps_attr_lab.attr, 114 &hv_caps_attr_collect_privileged.attr, 115 NULL, 116}; 117 118static struct attribute_group interface_group = { 119 .name = "interface", 120 .attrs = interface_attrs, 121}; 122 123static const struct attribute_group *attr_groups[] = { 124 &format_group, 125 &event_group, 126 &interface_group, 127 NULL, 128}; 129 130#define GPCI_MAX_DATA_BYTES \ 131 (1024 - sizeof(struct hv_get_perf_counter_info_params)) 132 133static unsigned long single_gpci_request(u32 req, u32 starting_index, 134 u16 secondary_index, u8 version_in, u32 offset, u8 length, 135 u64 *value) 136{ 137 unsigned long ret; 138 size_t i; 139 u64 count; 140 141 struct { 142 struct hv_get_perf_counter_info_params params; 143 uint8_t bytes[GPCI_MAX_DATA_BYTES]; 144 } __packed __aligned(sizeof(uint64_t)) arg = { 145 .params = { 146 .counter_request = cpu_to_be32(req), 147 .starting_index = cpu_to_be32(starting_index), 148 .secondary_index = cpu_to_be16(secondary_index), 149 .counter_info_version_in = version_in, 150 } 151 }; 152 153 ret = plpar_hcall_norets(H_GET_PERF_COUNTER_INFO, 154 virt_to_phys(&arg), sizeof(arg)); 155 if (ret) { 156 pr_devel("hcall failed: 0x%lx\n", ret); 157 return ret; 158 } 159 160 /* 161 * we verify offset and length are within the zeroed buffer at event 162 * init. 163 */ 164 count = 0; 165 for (i = offset; i < offset + length; i++) 166 count |= arg.bytes[i] << (i - offset); 167 168 *value = count; 169 return ret; 170} 171 172static u64 h_gpci_get_value(struct perf_event *event) 173{ 174 u64 count; 175 unsigned long ret = single_gpci_request(event_get_request(event), 176 event_get_starting_index(event), 177 event_get_secondary_index(event), 178 event_get_counter_info_version(event), 179 event_get_offset(event), 180 event_get_length(event), 181 &count); 182 if (ret) 183 return 0; 184 return count; 185} 186 187static void h_gpci_event_update(struct perf_event *event) 188{ 189 s64 prev; 190 u64 now = h_gpci_get_value(event); 191 prev = local64_xchg(&event->hw.prev_count, now); 192 local64_add(now - prev, &event->count); 193} 194 195static void h_gpci_event_start(struct perf_event *event, int flags) 196{ 197 local64_set(&event->hw.prev_count, h_gpci_get_value(event)); 198} 199 200static void h_gpci_event_stop(struct perf_event *event, int flags) 201{ 202 h_gpci_event_update(event); 203} 204 205static int h_gpci_event_add(struct perf_event *event, int flags) 206{ 207 if (flags & PERF_EF_START) 208 h_gpci_event_start(event, flags); 209 210 return 0; 211} 212 213static int h_gpci_event_init(struct perf_event *event) 214{ 215 u64 count; 216 u8 length; 217 218 /* Not our event */ 219 if (event->attr.type != event->pmu->type) 220 return -ENOENT; 221 222 /* config2 is unused */ 223 if (event->attr.config2) { 224 pr_devel("config2 set when reserved\n"); 225 return -EINVAL; 226 } 227 228 /* unsupported modes and filters */ 229 if (event->attr.exclude_user || 230 event->attr.exclude_kernel || 231 event->attr.exclude_hv || 232 event->attr.exclude_idle || 233 event->attr.exclude_host || 234 event->attr.exclude_guest) 235 return -EINVAL; 236 237 /* no branch sampling */ 238 if (has_branch_stack(event)) 239 return -EOPNOTSUPP; 240 241 length = event_get_length(event); 242 if (length < 1 || length > 8) { 243 pr_devel("length invalid\n"); 244 return -EINVAL; 245 } 246 247 /* last byte within the buffer? */ 248 if ((event_get_offset(event) + length) > GPCI_MAX_DATA_BYTES) { 249 pr_devel("request outside of buffer: %zu > %zu\n", 250 (size_t)event_get_offset(event) + length, 251 GPCI_MAX_DATA_BYTES); 252 return -EINVAL; 253 } 254 255 /* check if the request works... */ 256 if (single_gpci_request(event_get_request(event), 257 event_get_starting_index(event), 258 event_get_secondary_index(event), 259 event_get_counter_info_version(event), 260 event_get_offset(event), 261 length, 262 &count)) { 263 pr_devel("gpci hcall failed\n"); 264 return -EINVAL; 265 } 266 267 return 0; 268} 269 270static struct pmu h_gpci_pmu = { 271 .task_ctx_nr = perf_invalid_context, 272 273 .name = "hv_gpci", 274 .attr_groups = attr_groups, 275 .event_init = h_gpci_event_init, 276 .add = h_gpci_event_add, 277 .del = h_gpci_event_stop, 278 .start = h_gpci_event_start, 279 .stop = h_gpci_event_stop, 280 .read = h_gpci_event_update, 281}; 282 283static int hv_gpci_init(void) 284{ 285 int r; 286 unsigned long hret; 287 struct hv_perf_caps caps; 288 289 hv_gpci_assert_offsets_correct(); 290 291 if (!firmware_has_feature(FW_FEATURE_LPAR)) { 292 pr_debug("not a virtualized system, not enabling\n"); 293 return -ENODEV; 294 } 295 296 hret = hv_perf_caps_get(&caps); 297 if (hret) { 298 pr_debug("could not obtain capabilities, not enabling, rc=%ld\n", 299 hret); 300 return -ENODEV; 301 } 302 303 /* sampling not supported */ 304 h_gpci_pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT; 305 306 r = perf_pmu_register(&h_gpci_pmu, h_gpci_pmu.name, -1); 307 if (r) 308 return r; 309 310 return 0; 311} 312 313device_initcall(hv_gpci_init); 314