blob: e4027ed2d164bee53f7fd64138f60eace5b17901 [file] [log] [blame]
subrata_modakd1791512009-04-02 06:46:36 +00001/******************************************************************************/
2/* */
Cyril Hrubisadedb782014-08-21 11:20:12 +02003/* Ingo Molnar <mingo@elte.hu>, 2009 */
subrata_modakd1791512009-04-02 06:46:36 +00004/* */
5/* This program is free software; you can redistribute it and/or modify */
6/* it under the terms of the GNU General Public License as published by */
7/* the Free Software Foundation; either version 2 of the License, or */
8/* (at your option) any later version. */
9/* */
10/* This program is distributed in the hope that it will be useful, */
11/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
12/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
13/* the GNU General Public License for more details. */
14/* */
15/* You should have received a copy of the GNU General Public License */
16/* along with this program; if not, write to the Free Software */
Wanlong Gao4548c6c2012-10-19 18:03:36 +080017/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
subrata_modakd1791512009-04-02 06:46:36 +000018/* */
19/******************************************************************************/
20
21/*
22 * Very simple performance counter testcase.
23 * Picked up from: http://lkml.org/lkml/2008/12/5/17
24 */
Xiaoguang Wang7e6be182014-04-10 12:08:45 +080025
subrata_modakd1791512009-04-02 06:46:36 +000026#include <sys/types.h>
27#include <sys/ioctl.h>
28#include <sys/stat.h>
29#include <sys/time.h>
30#include <sys/uio.h>
31#include <linux/unistd.h>
subrata_modakd1791512009-04-02 06:46:36 +000032#include <assert.h>
33#include <unistd.h>
34#include <stdlib.h>
35#include <unistd.h>
36#include <string.h>
37#include <stdio.h>
38#include <fcntl.h>
Cyril Hrubisadedb782014-08-21 11:20:12 +020039#include <stdint.h>
Xiaoguang Wang7e6be182014-04-10 12:08:45 +080040#include "config.h"
41#if HAVE_PERF_EVENT_ATTR
42# include <linux/perf_event.h>
43#endif
subrata_modakd1791512009-04-02 06:46:36 +000044
subrata_modakd1791512009-04-02 06:46:36 +000045#include "test.h"
subrata_modakd0762042009-06-23 14:21:32 +000046#include "linux_syscall_numbers.h"
Xiaoguang Wang7e6be182014-04-10 12:08:45 +080047#include "safe_macros.h"
subrata_modakd1791512009-04-02 06:46:36 +000048
Xing Gu166c45f2014-08-07 10:05:01 +080049char *TCID = "perf_event_open01";
subrata_modakd1791512009-04-02 06:46:36 +000050
Xiaoguang Wang7e6be182014-04-10 12:08:45 +080051#if HAVE_PERF_EVENT_ATTR
52static void setup(void);
53static void cleanup(void);
54
55static struct test_case_t {
Cyril Hrubisadedb782014-08-21 11:20:12 +020056 uint32_t type;
57 const char *config_name;
58 unsigned long long config;
59} event_types[] = {
60 { PERF_TYPE_HARDWARE, "PERF_COUNT_HW_INSTRUCTIONS",
61 PERF_COUNT_HW_INSTRUCTIONS },
62 { PERF_TYPE_HARDWARE, "PERF_COUNT_HW_CACHE_REFERENCES",
63 PERF_COUNT_HW_CACHE_REFERENCES },
64 { PERF_TYPE_HARDWARE, "PERF_COUNT_HW_CACHE_MISSES",
65 PERF_COUNT_HW_CACHE_MISSES },
66 { PERF_TYPE_HARDWARE, "PERF_COUNT_HW_BRANCH_INSTRUCTIONS",
Xiaoguang Wang7e6be182014-04-10 12:08:45 +080067 PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
Cyril Hrubisadedb782014-08-21 11:20:12 +020068 { PERF_TYPE_HARDWARE, "PERF_COUNT_HW_BRANCH_MISSES",
69 PERF_COUNT_HW_BRANCH_MISSES },
70 { PERF_TYPE_SOFTWARE, "PERF_COUNT_SW_CPU_CLOCK",
71 PERF_COUNT_SW_CPU_CLOCK },
72 { PERF_TYPE_SOFTWARE, "PERF_COUNT_SW_TASK_CLOCK",
73 PERF_COUNT_SW_TASK_CLOCK },
subrata_modakd1791512009-04-02 06:46:36 +000074};
75
Cyril Hrubisadedb782014-08-21 11:20:12 +020076int TST_TOTAL = ARRAY_SIZE(event_types);
77
Xiaoguang Wang7e6be182014-04-10 12:08:45 +080078static void verify(struct test_case_t *tc);
79static struct perf_event_attr pe;
80
81int main(int ac, char **av)
82{
83 int i, lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020084 const char *msg;
Xiaoguang Wang7e6be182014-04-10 12:08:45 +080085
86 msg = parse_opts(ac, av, NULL, NULL);
87 if (msg != NULL)
88 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
89
90 setup();
91
92 for (lc = 0; TEST_LOOPING(lc); lc++) {
93 tst_count = 0;
94
95 for (i = 0; i < TST_TOTAL; i++)
Cyril Hrubisadedb782014-08-21 11:20:12 +020096 verify(&event_types[i]);
Xiaoguang Wang7e6be182014-04-10 12:08:45 +080097 }
98
99 cleanup();
100 tst_exit();
Wanlong Gao354ebb42012-12-07 10:10:04 +0800101}
yaberauneya1a1b1fb2009-11-27 08:15:35 +0000102
Xiaoguang Wang7e6be182014-04-10 12:08:45 +0800103static void setup(void)
104{
105 /*
106 * According to perf_event_open's manpage, the official way of
107 * knowing if perf_event_open() support is enabled is checking for
108 * the existence of the file /proc/sys/kernel/perf_event_paranoid.
109 */
110 if (access("/proc/sys/kernel/perf_event_paranoid", F_OK) == -1)
111 tst_brkm(TCONF, NULL, "Kernel doesn't have perf_event support");
112
113 tst_sig(NOFORK, DEF_HANDLER, cleanup);
114
115 TEST_PAUSE;
116
Xiaoguang Wang7e6be182014-04-10 12:08:45 +0800117 pe.size = sizeof(struct perf_event_attr);
118 pe.disabled = 1;
119 pe.exclude_kernel = 1;
120 pe.exclude_hv = 1;
121}
122
123
124static int perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
125 int cpu, int group_fd, unsigned long flags)
126{
127 int ret;
128
129 ret = ltp_syscall(__NR_perf_event_open, hw_event, pid, cpu,
130 group_fd, flags);
131 return ret;
132}
133
134/* do_work() is copied form performance_counter02.c */
135#define LOOPS 1000000000
136
137static void do_work(void)
138{
139 int i;
140
141 for (i = 0; i < LOOPS; ++i)
142 asm volatile ("" : : "g" (i));
143}
144
145static void verify(struct test_case_t *tc)
146{
147 unsigned long long count;
148 int fd, ret;
149
Cyril Hrubisadedb782014-08-21 11:20:12 +0200150 pe.type = tc->type;
151 pe.config = tc->config;
Xiaoguang Wang7e6be182014-04-10 12:08:45 +0800152
153 TEST(perf_event_open(&pe, 0, -1, -1, 0));
154 if (TEST_RETURN == -1) {
Cyril Hrubisadedb782014-08-21 11:20:12 +0200155 if (TEST_ERRNO == ENOENT) {
156 tst_resm(TCONF,
157 "perf_event_open for %s not supported",
158 tc->config_name);
159 } else {
160 tst_brkm(TFAIL | TTERRNO, cleanup,
161 "perf_event_open failed unexpectedly");
162 }
Xiaoguang Wang7e6be182014-04-10 12:08:45 +0800163 return;
164 }
165
166 fd = TEST_RETURN;
167
168 if (ioctl(fd, PERF_EVENT_IOC_RESET, 0) == -1) {
169 tst_brkm(TFAIL | TTERRNO, cleanup,
170 "ioctl set PERF_EVENT_IOC_RESET failed");
171 }
172
173 if (ioctl(fd, PERF_EVENT_IOC_ENABLE, 0) == -1) {
174 tst_brkm(TFAIL | TTERRNO, cleanup,
175 "ioctl set PERF_EVENT_IOC_ENABLE failed");
176 }
177
178 do_work();
179
180 if (ioctl(fd, PERF_EVENT_IOC_DISABLE, 0) == -1) {
181 tst_brkm(TFAIL | TTERRNO, cleanup,
182 "ioctl set PERF_EVENT_IOC_RESET failed");
183 }
184
185 ret = read(fd, &count, sizeof(count));
186 if (ret == sizeof(count)) {
187 tst_resm(TINFO, "read event counter succeeded, "
188 "value: %llu", count);
189 tst_resm(TPASS, "test PERF_TYPE_HARDWARE: %s succeeded",
Cyril Hrubisadedb782014-08-21 11:20:12 +0200190 tc->config_name);
Xiaoguang Wang7e6be182014-04-10 12:08:45 +0800191 } else {
192 tst_resm(TFAIL | TERRNO, "read event counter failed");
193 }
194
195 SAFE_CLOSE(cleanup, fd);
196
197}
198
199static void cleanup(void)
200{
Xiaoguang Wang7e6be182014-04-10 12:08:45 +0800201}
202
203#else
204
Wanlong Gao354ebb42012-12-07 10:10:04 +0800205int main(void)
206{
Xiaoguang Wang7e6be182014-04-10 12:08:45 +0800207 tst_brkm(TCONF, NULL, "This system doesn't have "
208 "header file:<linux/perf_event.h> or "
209 "no struct perf_event_attr defined");
Garrett Cooper49f76222010-12-19 10:22:13 -0800210}
Xiaoguang Wang7e6be182014-04-10 12:08:45 +0800211#endif