Skip to content

Commit bacf7e5

Browse files
Jiri Olsaacmel
authored andcommitted
perf tests: Move test__rdpmc into separate object
Separating test__rdpmc test from the builtin-test into rdpmc object. Signed-off-by: Jiri Olsa <[email protected]> Cc: Corey Ashford <[email protected]> Cc: Frederic Weisbecker <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Paul Mackerras <[email protected]> Cc: Peter Zijlstra <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent 16d00fe commit bacf7e5

File tree

4 files changed

+177
-168
lines changed

4 files changed

+177
-168
lines changed

tools/perf/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,7 @@ LIB_OBJS += $(OUTPUT)tests/open-syscall.o
436436
LIB_OBJS += $(OUTPUT)tests/open-syscall-all-cpus.o
437437
LIB_OBJS += $(OUTPUT)tests/mmap-basic.o
438438
LIB_OBJS += $(OUTPUT)tests/perf-record.o
439+
LIB_OBJS += $(OUTPUT)tests/rdpmc.o
439440
LIB_OBJS += $(OUTPUT)tests/util.o
440441

441442
BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o

tools/perf/tests/builtin-test.c

Lines changed: 0 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -30,174 +30,6 @@
3030
#include <sched.h>
3131

3232

33-
34-
#if defined(__x86_64__) || defined(__i386__)
35-
36-
#define barrier() asm volatile("" ::: "memory")
37-
38-
static u64 rdpmc(unsigned int counter)
39-
{
40-
unsigned int low, high;
41-
42-
asm volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (counter));
43-
44-
return low | ((u64)high) << 32;
45-
}
46-
47-
static u64 rdtsc(void)
48-
{
49-
unsigned int low, high;
50-
51-
asm volatile("rdtsc" : "=a" (low), "=d" (high));
52-
53-
return low | ((u64)high) << 32;
54-
}
55-
56-
static u64 mmap_read_self(void *addr)
57-
{
58-
struct perf_event_mmap_page *pc = addr;
59-
u32 seq, idx, time_mult = 0, time_shift = 0;
60-
u64 count, cyc = 0, time_offset = 0, enabled, running, delta;
61-
62-
do {
63-
seq = pc->lock;
64-
barrier();
65-
66-
enabled = pc->time_enabled;
67-
running = pc->time_running;
68-
69-
if (enabled != running) {
70-
cyc = rdtsc();
71-
time_mult = pc->time_mult;
72-
time_shift = pc->time_shift;
73-
time_offset = pc->time_offset;
74-
}
75-
76-
idx = pc->index;
77-
count = pc->offset;
78-
if (idx)
79-
count += rdpmc(idx - 1);
80-
81-
barrier();
82-
} while (pc->lock != seq);
83-
84-
if (enabled != running) {
85-
u64 quot, rem;
86-
87-
quot = (cyc >> time_shift);
88-
rem = cyc & ((1 << time_shift) - 1);
89-
delta = time_offset + quot * time_mult +
90-
((rem * time_mult) >> time_shift);
91-
92-
enabled += delta;
93-
if (idx)
94-
running += delta;
95-
96-
quot = count / running;
97-
rem = count % running;
98-
count = quot * enabled + (rem * enabled) / running;
99-
}
100-
101-
return count;
102-
}
103-
104-
/*
105-
* If the RDPMC instruction faults then signal this back to the test parent task:
106-
*/
107-
static void segfault_handler(int sig __maybe_unused,
108-
siginfo_t *info __maybe_unused,
109-
void *uc __maybe_unused)
110-
{
111-
exit(-1);
112-
}
113-
114-
static int __test__rdpmc(void)
115-
{
116-
volatile int tmp = 0;
117-
u64 i, loops = 1000;
118-
int n;
119-
int fd;
120-
void *addr;
121-
struct perf_event_attr attr = {
122-
.type = PERF_TYPE_HARDWARE,
123-
.config = PERF_COUNT_HW_INSTRUCTIONS,
124-
.exclude_kernel = 1,
125-
};
126-
u64 delta_sum = 0;
127-
struct sigaction sa;
128-
129-
sigfillset(&sa.sa_mask);
130-
sa.sa_sigaction = segfault_handler;
131-
sigaction(SIGSEGV, &sa, NULL);
132-
133-
fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
134-
if (fd < 0) {
135-
pr_err("Error: sys_perf_event_open() syscall returned "
136-
"with %d (%s)\n", fd, strerror(errno));
137-
return -1;
138-
}
139-
140-
addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0);
141-
if (addr == (void *)(-1)) {
142-
pr_err("Error: mmap() syscall returned with (%s)\n",
143-
strerror(errno));
144-
goto out_close;
145-
}
146-
147-
for (n = 0; n < 6; n++) {
148-
u64 stamp, now, delta;
149-
150-
stamp = mmap_read_self(addr);
151-
152-
for (i = 0; i < loops; i++)
153-
tmp++;
154-
155-
now = mmap_read_self(addr);
156-
loops *= 10;
157-
158-
delta = now - stamp;
159-
pr_debug("%14d: %14Lu\n", n, (long long)delta);
160-
161-
delta_sum += delta;
162-
}
163-
164-
munmap(addr, page_size);
165-
pr_debug(" ");
166-
out_close:
167-
close(fd);
168-
169-
if (!delta_sum)
170-
return -1;
171-
172-
return 0;
173-
}
174-
175-
static int test__rdpmc(void)
176-
{
177-
int status = 0;
178-
int wret = 0;
179-
int ret;
180-
int pid;
181-
182-
pid = fork();
183-
if (pid < 0)
184-
return -1;
185-
186-
if (!pid) {
187-
ret = __test__rdpmc();
188-
189-
exit(ret);
190-
}
191-
192-
wret = waitpid(pid, &status, 0);
193-
if (wret < 0 || status)
194-
return -1;
195-
196-
return 0;
197-
}
198-
199-
#endif
200-
20133
static int test__perf_pmu(void)
20234
{
20335
return perf_pmu__test();

tools/perf/tests/rdpmc.c

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
#include <unistd.h>
2+
#include <stdlib.h>
3+
#include <signal.h>
4+
#include <sys/mman.h>
5+
#include "types.h"
6+
#include "perf.h"
7+
#include "debug.h"
8+
#include "tests.h"
9+
10+
#if defined(__x86_64__) || defined(__i386__)
11+
12+
#define barrier() asm volatile("" ::: "memory")
13+
14+
static u64 rdpmc(unsigned int counter)
15+
{
16+
unsigned int low, high;
17+
18+
asm volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (counter));
19+
20+
return low | ((u64)high) << 32;
21+
}
22+
23+
static u64 rdtsc(void)
24+
{
25+
unsigned int low, high;
26+
27+
asm volatile("rdtsc" : "=a" (low), "=d" (high));
28+
29+
return low | ((u64)high) << 32;
30+
}
31+
32+
static u64 mmap_read_self(void *addr)
33+
{
34+
struct perf_event_mmap_page *pc = addr;
35+
u32 seq, idx, time_mult = 0, time_shift = 0;
36+
u64 count, cyc = 0, time_offset = 0, enabled, running, delta;
37+
38+
do {
39+
seq = pc->lock;
40+
barrier();
41+
42+
enabled = pc->time_enabled;
43+
running = pc->time_running;
44+
45+
if (enabled != running) {
46+
cyc = rdtsc();
47+
time_mult = pc->time_mult;
48+
time_shift = pc->time_shift;
49+
time_offset = pc->time_offset;
50+
}
51+
52+
idx = pc->index;
53+
count = pc->offset;
54+
if (idx)
55+
count += rdpmc(idx - 1);
56+
57+
barrier();
58+
} while (pc->lock != seq);
59+
60+
if (enabled != running) {
61+
u64 quot, rem;
62+
63+
quot = (cyc >> time_shift);
64+
rem = cyc & ((1 << time_shift) - 1);
65+
delta = time_offset + quot * time_mult +
66+
((rem * time_mult) >> time_shift);
67+
68+
enabled += delta;
69+
if (idx)
70+
running += delta;
71+
72+
quot = count / running;
73+
rem = count % running;
74+
count = quot * enabled + (rem * enabled) / running;
75+
}
76+
77+
return count;
78+
}
79+
80+
/*
81+
* If the RDPMC instruction faults then signal this back to the test parent task:
82+
*/
83+
static void segfault_handler(int sig __maybe_unused,
84+
siginfo_t *info __maybe_unused,
85+
void *uc __maybe_unused)
86+
{
87+
exit(-1);
88+
}
89+
90+
static int __test__rdpmc(void)
91+
{
92+
volatile int tmp = 0;
93+
u64 i, loops = 1000;
94+
int n;
95+
int fd;
96+
void *addr;
97+
struct perf_event_attr attr = {
98+
.type = PERF_TYPE_HARDWARE,
99+
.config = PERF_COUNT_HW_INSTRUCTIONS,
100+
.exclude_kernel = 1,
101+
};
102+
u64 delta_sum = 0;
103+
struct sigaction sa;
104+
105+
sigfillset(&sa.sa_mask);
106+
sa.sa_sigaction = segfault_handler;
107+
sigaction(SIGSEGV, &sa, NULL);
108+
109+
fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
110+
if (fd < 0) {
111+
pr_err("Error: sys_perf_event_open() syscall returned "
112+
"with %d (%s)\n", fd, strerror(errno));
113+
return -1;
114+
}
115+
116+
addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0);
117+
if (addr == (void *)(-1)) {
118+
pr_err("Error: mmap() syscall returned with (%s)\n",
119+
strerror(errno));
120+
goto out_close;
121+
}
122+
123+
for (n = 0; n < 6; n++) {
124+
u64 stamp, now, delta;
125+
126+
stamp = mmap_read_self(addr);
127+
128+
for (i = 0; i < loops; i++)
129+
tmp++;
130+
131+
now = mmap_read_self(addr);
132+
loops *= 10;
133+
134+
delta = now - stamp;
135+
pr_debug("%14d: %14Lu\n", n, (long long)delta);
136+
137+
delta_sum += delta;
138+
}
139+
140+
munmap(addr, page_size);
141+
pr_debug(" ");
142+
out_close:
143+
close(fd);
144+
145+
if (!delta_sum)
146+
return -1;
147+
148+
return 0;
149+
}
150+
151+
int test__rdpmc(void)
152+
{
153+
int status = 0;
154+
int wret = 0;
155+
int ret;
156+
int pid;
157+
158+
pid = fork();
159+
if (pid < 0)
160+
return -1;
161+
162+
if (!pid) {
163+
ret = __test__rdpmc();
164+
165+
exit(ret);
166+
}
167+
168+
wret = waitpid(pid, &status, 0);
169+
if (wret < 0 || status)
170+
return -1;
171+
172+
return 0;
173+
}
174+
175+
#endif

tools/perf/tests/tests.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ int test__open_syscall_event(void);
77
int test__open_syscall_event_on_all_cpus(void);
88
int test__basic_mmap(void);
99
int test__PERF_RECORD(void);
10+
int test__rdpmc(void);
1011

1112
/* Util */
1213
int trace_event__id(const char *evname);

0 commit comments

Comments
 (0)