2 * Hypervisor supplied "gpci" ("get performance counter info") performance
5 * Author: Cody P Schafer <cody@linux.vnet.ibm.com>
6 * Copyright 2014 IBM Corporation.
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.
14 #define pr_fmt(fmt) "hv-gpci: " fmt
16 #include <linux/init.h>
17 #include <linux/perf_event.h>
18 #include <asm/firmware.h>
19 #include <asm/hvcall.h>
23 #include "hv-common.h"
27 * perf stat -e 'hv_gpci/counter_info_version=3,offset=0,length=8,
28 * secondary_index=0,starting_index=0xffffffff,request=0x10/' ...
32 EVENT_DEFINE_RANGE_FORMAT(request
, config
, 0, 31);
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
40 EVENT_DEFINE_RANGE_FORMAT(starting_index
, config
, 32, 63);
41 EVENT_DEFINE_RANGE_FORMAT_LITE(phys_processor_idx
, config
, 32, 63);
42 EVENT_DEFINE_RANGE_FORMAT_LITE(sibling_part_id
, config
, 32, 63);
43 EVENT_DEFINE_RANGE_FORMAT_LITE(hw_chip_id
, config
, 32, 63);
44 EVENT_DEFINE_RANGE_FORMAT_LITE(partition_id
, config
, 32, 63);
47 EVENT_DEFINE_RANGE_FORMAT(secondary_index
, config1
, 0, 15);
49 EVENT_DEFINE_RANGE_FORMAT(counter_info_version
, config1
, 16, 23);
50 /* u8, bytes of data (1-8) */
51 EVENT_DEFINE_RANGE_FORMAT(length
, config1
, 24, 31);
52 /* u32, byte offset */
53 EVENT_DEFINE_RANGE_FORMAT(offset
, config1
, 32, 63);
55 static 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
,
65 &format_attr_offset
.attr
,
66 &format_attr_length
.attr
,
70 static struct attribute_group format_group
= {
72 .attrs
= format_attrs
,
75 static struct attribute_group event_group
= {
77 .attrs
= hv_gpci_event_attrs
,
80 #define HV_CAPS_ATTR(_name, _format) \
81 static ssize_t _name##_show(struct device *dev, \
82 struct device_attribute *attr, \
85 struct hv_perf_caps caps; \
86 unsigned long hret = hv_perf_caps_get(&caps); \
90 return sprintf(page, _format, caps._name); \
92 static struct device_attribute hv_caps_attr_##_name = __ATTR_RO(_name)
94 static ssize_t
kernel_version_show(struct device
*dev
,
95 struct device_attribute
*attr
,
98 return sprintf(page
, "0x%x\n", COUNTER_INFO_VERSION_CURRENT
);
101 static DEVICE_ATTR_RO(kernel_version
);
102 HV_CAPS_ATTR(version
, "0x%x\n");
103 HV_CAPS_ATTR(ga
, "%d\n");
104 HV_CAPS_ATTR(expanded
, "%d\n");
105 HV_CAPS_ATTR(lab
, "%d\n");
106 HV_CAPS_ATTR(collect_privileged
, "%d\n");
108 static 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
,
118 static struct attribute_group interface_group
= {
120 .attrs
= interface_attrs
,
123 static const struct attribute_group
*attr_groups
[] = {
130 #define HGPCI_REQ_BUFFER_SIZE 4096
131 #define HGPCI_MAX_DATA_BYTES \
132 (HGPCI_REQ_BUFFER_SIZE - sizeof(struct hv_get_perf_counter_info_params))
134 static DEFINE_PER_CPU(char, hv_gpci_reqb
[HGPCI_REQ_BUFFER_SIZE
]) __aligned(sizeof(uint64_t));
136 struct hv_gpci_request_buffer
{
137 struct hv_get_perf_counter_info_params params
;
138 uint8_t bytes
[HGPCI_MAX_DATA_BYTES
];
141 static unsigned long single_gpci_request(u32 req
, u32 starting_index
,
142 u16 secondary_index
, u8 version_in
, u32 offset
, u8 length
,
148 struct hv_gpci_request_buffer
*arg
;
150 arg
= (void *)get_cpu_var(hv_gpci_reqb
);
151 memset(arg
, 0, HGPCI_REQ_BUFFER_SIZE
);
153 arg
->params
.counter_request
= cpu_to_be32(req
);
154 arg
->params
.starting_index
= cpu_to_be32(starting_index
);
155 arg
->params
.secondary_index
= cpu_to_be16(secondary_index
);
156 arg
->params
.counter_info_version_in
= version_in
;
158 ret
= plpar_hcall_norets(H_GET_PERF_COUNTER_INFO
,
159 virt_to_phys(arg
), HGPCI_REQ_BUFFER_SIZE
);
161 pr_devel("hcall failed: 0x%lx\n", ret
);
166 * we verify offset and length are within the zeroed buffer at event
170 for (i
= offset
; i
< offset
+ length
; i
++)
171 count
|= arg
->bytes
[i
] << (i
- offset
);
175 put_cpu_var(hv_gpci_reqb
);
179 static u64
h_gpci_get_value(struct perf_event
*event
)
182 unsigned long ret
= single_gpci_request(event_get_request(event
),
183 event_get_starting_index(event
),
184 event_get_secondary_index(event
),
185 event_get_counter_info_version(event
),
186 event_get_offset(event
),
187 event_get_length(event
),
194 static void h_gpci_event_update(struct perf_event
*event
)
197 u64 now
= h_gpci_get_value(event
);
198 prev
= local64_xchg(&event
->hw
.prev_count
, now
);
199 local64_add(now
- prev
, &event
->count
);
202 static void h_gpci_event_start(struct perf_event
*event
, int flags
)
204 local64_set(&event
->hw
.prev_count
, h_gpci_get_value(event
));
207 static void h_gpci_event_stop(struct perf_event
*event
, int flags
)
209 h_gpci_event_update(event
);
212 static int h_gpci_event_add(struct perf_event
*event
, int flags
)
214 if (flags
& PERF_EF_START
)
215 h_gpci_event_start(event
, flags
);
220 static int h_gpci_event_init(struct perf_event
*event
)
226 if (event
->attr
.type
!= event
->pmu
->type
)
229 /* config2 is unused */
230 if (event
->attr
.config2
) {
231 pr_devel("config2 set when reserved\n");
235 /* unsupported modes and filters */
236 if (event
->attr
.exclude_user
||
237 event
->attr
.exclude_kernel
||
238 event
->attr
.exclude_hv
||
239 event
->attr
.exclude_idle
||
240 event
->attr
.exclude_host
||
241 event
->attr
.exclude_guest
)
244 /* no branch sampling */
245 if (has_branch_stack(event
))
248 length
= event_get_length(event
);
249 if (length
< 1 || length
> 8) {
250 pr_devel("length invalid\n");
254 /* last byte within the buffer? */
255 if ((event_get_offset(event
) + length
) > HGPCI_MAX_DATA_BYTES
) {
256 pr_devel("request outside of buffer: %zu > %zu\n",
257 (size_t)event_get_offset(event
) + length
,
258 HGPCI_MAX_DATA_BYTES
);
262 /* check if the request works... */
263 if (single_gpci_request(event_get_request(event
),
264 event_get_starting_index(event
),
265 event_get_secondary_index(event
),
266 event_get_counter_info_version(event
),
267 event_get_offset(event
),
270 pr_devel("gpci hcall failed\n");
277 static struct pmu h_gpci_pmu
= {
278 .task_ctx_nr
= perf_invalid_context
,
281 .attr_groups
= attr_groups
,
282 .event_init
= h_gpci_event_init
,
283 .add
= h_gpci_event_add
,
284 .del
= h_gpci_event_stop
,
285 .start
= h_gpci_event_start
,
286 .stop
= h_gpci_event_stop
,
287 .read
= h_gpci_event_update
,
290 static int hv_gpci_init(void)
294 struct hv_perf_caps caps
;
296 hv_gpci_assert_offsets_correct();
298 if (!firmware_has_feature(FW_FEATURE_LPAR
)) {
299 pr_debug("not a virtualized system, not enabling\n");
303 hret
= hv_perf_caps_get(&caps
);
305 pr_debug("could not obtain capabilities, not enabling, rc=%ld\n",
310 /* sampling not supported */
311 h_gpci_pmu
.capabilities
|= PERF_PMU_CAP_NO_INTERRUPT
;
313 r
= perf_pmu_register(&h_gpci_pmu
, h_gpci_pmu
.name
, -1);
320 device_initcall(hv_gpci_init
);