1/*
2 * Copyright 2014, Michael Ellerman, IBM Corp.
3 * Licensed under GPLv2.
4 */
5
6#define _GNU_SOURCE
7
8#include <elf.h>
9#include <limits.h>
10#include <stdio.h>
11#include <stdbool.h>
12#include <string.h>
13#include <sys/prctl.h>
14
15#include "event.h"
16#include "lib.h"
17#include "utils.h"
18
19/*
20 * Test that per-event excludes work.
21 */
22
23static int per_event_excludes(void)
24{
25	struct event *e, events[4];
26	char *platform;
27	int i;
28
29	platform = (char *)get_auxv_entry(AT_BASE_PLATFORM);
30	FAIL_IF(!platform);
31	SKIP_IF(strcmp(platform, "power8") != 0);
32
33	/*
34	 * We need to create the events disabled, otherwise the running/enabled
35	 * counts don't match up.
36	 */
37	e = &events[0];
38	event_init_opts(e, PERF_COUNT_HW_INSTRUCTIONS,
39			PERF_TYPE_HARDWARE, "instructions");
40	e->attr.disabled = 1;
41
42	e = &events[1];
43	event_init_opts(e, PERF_COUNT_HW_INSTRUCTIONS,
44			PERF_TYPE_HARDWARE, "instructions(k)");
45	e->attr.disabled = 1;
46	e->attr.exclude_user = 1;
47	e->attr.exclude_hv = 1;
48
49	e = &events[2];
50	event_init_opts(e, PERF_COUNT_HW_INSTRUCTIONS,
51			PERF_TYPE_HARDWARE, "instructions(h)");
52	e->attr.disabled = 1;
53	e->attr.exclude_user = 1;
54	e->attr.exclude_kernel = 1;
55
56	e = &events[3];
57	event_init_opts(e, PERF_COUNT_HW_INSTRUCTIONS,
58			PERF_TYPE_HARDWARE, "instructions(u)");
59	e->attr.disabled = 1;
60	e->attr.exclude_hv = 1;
61	e->attr.exclude_kernel = 1;
62
63	FAIL_IF(event_open(&events[0]));
64
65	/*
66	 * The open here will fail if we don't have per event exclude support,
67	 * because the second event has an incompatible set of exclude settings
68	 * and we're asking for the events to be in a group.
69	 */
70	for (i = 1; i < 4; i++)
71		FAIL_IF(event_open_with_group(&events[i], events[0].fd));
72
73	/*
74	 * Even though the above will fail without per-event excludes we keep
75	 * testing in order to be thorough.
76	 */
77	prctl(PR_TASK_PERF_EVENTS_ENABLE);
78
79	/* Spin for a while */
80	for (i = 0; i < INT_MAX; i++)
81		asm volatile("" : : : "memory");
82
83	prctl(PR_TASK_PERF_EVENTS_DISABLE);
84
85	for (i = 0; i < 4; i++) {
86		FAIL_IF(event_read(&events[i]));
87		event_report(&events[i]);
88	}
89
90	/*
91	 * We should see that all events have enabled == running. That
92	 * shows that they were all on the PMU at once.
93	 */
94	for (i = 0; i < 4; i++)
95		FAIL_IF(events[i].result.running != events[i].result.enabled);
96
97	/*
98	 * We can also check that the result for instructions is >= all the
99	 * other counts. That's because it is counting all instructions while
100	 * the others are counting a subset.
101	 */
102	for (i = 1; i < 4; i++)
103		FAIL_IF(events[0].result.value < events[i].result.value);
104
105	for (i = 0; i < 4; i++)
106		event_close(&events[i]);
107
108	return 0;
109}
110
111int main(void)
112{
113	return test_harness(per_event_excludes, "per_event_excludes");
114}
115