1*27b03b36SApple OSS Distributions /*
2*27b03b36SApple OSS Distributions * Must come before including darwintest.h
3*27b03b36SApple OSS Distributions */
4*27b03b36SApple OSS Distributions #ifdef T_NAMESPACE
5*27b03b36SApple OSS Distributions #undef T_NAMESPACE
6*27b03b36SApple OSS Distributions #endif /* defined(T_NAMESPACE) */
7*27b03b36SApple OSS Distributions
8*27b03b36SApple OSS Distributions #include <darwintest.h>
9*27b03b36SApple OSS Distributions #include <fcntl.h>
10*27b03b36SApple OSS Distributions #include <inttypes.h>
11*27b03b36SApple OSS Distributions #ifndef PRIVATE
12*27b03b36SApple OSS Distributions /*
13*27b03b36SApple OSS Distributions * Need new CPU families.
14*27b03b36SApple OSS Distributions */
15*27b03b36SApple OSS Distributions #define PRIVATE
16*27b03b36SApple OSS Distributions #include <mach/machine.h>
17*27b03b36SApple OSS Distributions #undef PRIVATE
18*27b03b36SApple OSS Distributions #else /* !defined(PRIVATE) */
19*27b03b36SApple OSS Distributions #include <mach/machine.h>
20*27b03b36SApple OSS Distributions #endif /* defined(PRIVATE) */
21*27b03b36SApple OSS Distributions #include <stdint.h>
22*27b03b36SApple OSS Distributions #include <System/sys/guarded.h>
23*27b03b36SApple OSS Distributions #include <System/sys/monotonic.h>
24*27b03b36SApple OSS Distributions #include <sys/ioctl.h>
25*27b03b36SApple OSS Distributions #include <sys/sysctl.h>
26*27b03b36SApple OSS Distributions #include <unistd.h>
27*27b03b36SApple OSS Distributions
28*27b03b36SApple OSS Distributions T_GLOBAL_META(
29*27b03b36SApple OSS Distributions T_META_NAMESPACE("xnu.monotonic"),
30*27b03b36SApple OSS Distributions T_META_CHECK_LEAKS(false)
31*27b03b36SApple OSS Distributions );
32*27b03b36SApple OSS Distributions
33*27b03b36SApple OSS Distributions static bool
device_supports_uncore(void)34*27b03b36SApple OSS Distributions device_supports_uncore(void)
35*27b03b36SApple OSS Distributions {
36*27b03b36SApple OSS Distributions int r;
37*27b03b36SApple OSS Distributions int type, subtype;
38*27b03b36SApple OSS Distributions unsigned int family;
39*27b03b36SApple OSS Distributions size_t size = sizeof(type);
40*27b03b36SApple OSS Distributions
41*27b03b36SApple OSS Distributions /*
42*27b03b36SApple OSS Distributions * Only arm64 Monsoon devices support uncore counters.
43*27b03b36SApple OSS Distributions */
44*27b03b36SApple OSS Distributions
45*27b03b36SApple OSS Distributions r = sysctlbyname("hw.cputype", &type, &size, NULL, 0);
46*27b03b36SApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(r, "sysctlbyname(\"hw.cputype\")");
47*27b03b36SApple OSS Distributions r = sysctlbyname("hw.cpusubtype", &subtype, &size, NULL, 0);
48*27b03b36SApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(r, "sysctlbyname(\"hw.cpusubtype\")");
49*27b03b36SApple OSS Distributions r = sysctlbyname("hw.cpufamily", &family, &size, NULL, 0);
50*27b03b36SApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(r, "sysctlbyname(\"hw.cpufamily\")");
51*27b03b36SApple OSS Distributions
52*27b03b36SApple OSS Distributions if (type == CPU_TYPE_ARM64 &&
53*27b03b36SApple OSS Distributions subtype == CPU_SUBTYPE_ARM64_V8 &&
54*27b03b36SApple OSS Distributions (family == CPUFAMILY_ARM_MONSOON_MISTRAL ||
55*27b03b36SApple OSS Distributions family == CPUFAMILY_ARM_VORTEX_TEMPEST)) {
56*27b03b36SApple OSS Distributions return true;
57*27b03b36SApple OSS Distributions }
58*27b03b36SApple OSS Distributions
59*27b03b36SApple OSS Distributions return false;
60*27b03b36SApple OSS Distributions }
61*27b03b36SApple OSS Distributions
62*27b03b36SApple OSS Distributions #define UNCORE_DEV_PATH "/dev/monotonic/uncore"
63*27b03b36SApple OSS Distributions
64*27b03b36SApple OSS Distributions static int
open_uncore_error(int * error)65*27b03b36SApple OSS Distributions open_uncore_error(int *error)
66*27b03b36SApple OSS Distributions {
67*27b03b36SApple OSS Distributions guardid_t guard;
68*27b03b36SApple OSS Distributions int fd;
69*27b03b36SApple OSS Distributions
70*27b03b36SApple OSS Distributions guard = 0xa5adcafe;
71*27b03b36SApple OSS Distributions
72*27b03b36SApple OSS Distributions T_SETUPBEGIN;
73*27b03b36SApple OSS Distributions
74*27b03b36SApple OSS Distributions fd = guarded_open_np(UNCORE_DEV_PATH, &guard,
75*27b03b36SApple OSS Distributions GUARD_CLOSE | GUARD_DUP | GUARD_WRITE, O_CLOEXEC | O_EXCL);
76*27b03b36SApple OSS Distributions if (fd < 0 && errno == ENOENT) {
77*27b03b36SApple OSS Distributions T_ASSERT_FALSE(device_supports_uncore(),
78*27b03b36SApple OSS Distributions "lack of dev node implies no uncore support");
79*27b03b36SApple OSS Distributions T_SKIP("uncore counters are unsupported");
80*27b03b36SApple OSS Distributions __builtin_unreachable();
81*27b03b36SApple OSS Distributions }
82*27b03b36SApple OSS Distributions
83*27b03b36SApple OSS Distributions if (error == NULL) {
84*27b03b36SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(fd, "open '%s'", UNCORE_DEV_PATH);
85*27b03b36SApple OSS Distributions } else {
86*27b03b36SApple OSS Distributions *error = errno;
87*27b03b36SApple OSS Distributions }
88*27b03b36SApple OSS Distributions
89*27b03b36SApple OSS Distributions T_SETUPEND;
90*27b03b36SApple OSS Distributions
91*27b03b36SApple OSS Distributions return fd;
92*27b03b36SApple OSS Distributions }
93*27b03b36SApple OSS Distributions
94*27b03b36SApple OSS Distributions static void
uncore_counts(int fd,uint64_t ctr_mask,uint64_t * counts)95*27b03b36SApple OSS Distributions uncore_counts(int fd, uint64_t ctr_mask, uint64_t *counts)
96*27b03b36SApple OSS Distributions {
97*27b03b36SApple OSS Distributions int r;
98*27b03b36SApple OSS Distributions union monotonic_ctl_counts *cts_ctl;
99*27b03b36SApple OSS Distributions
100*27b03b36SApple OSS Distributions cts_ctl = (union monotonic_ctl_counts *)counts;
101*27b03b36SApple OSS Distributions cts_ctl->in.ctr_mask = ctr_mask;
102*27b03b36SApple OSS Distributions
103*27b03b36SApple OSS Distributions r = ioctl(fd, MT_IOC_COUNTS, cts_ctl);
104*27b03b36SApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(r, "MT_IOC_COUNTS got counter values");
105*27b03b36SApple OSS Distributions }
106*27b03b36SApple OSS Distributions
107*27b03b36SApple OSS Distributions #define REF_TIMEBASE_EVENT 0x3
108*27b03b36SApple OSS Distributions #define CTRS_MAX 128
109*27b03b36SApple OSS Distributions
110*27b03b36SApple OSS Distributions T_DECL(uncore_max_counters,
111*27b03b36SApple OSS Distributions "ensure that the maximum number of uncore countes is sane",
112*27b03b36SApple OSS Distributions T_META_ASROOT(true))
113*27b03b36SApple OSS Distributions {
114*27b03b36SApple OSS Distributions int nctrs = 0;
115*27b03b36SApple OSS Distributions int fd;
116*27b03b36SApple OSS Distributions
117*27b03b36SApple OSS Distributions fd = open_uncore_error(NULL);
118*27b03b36SApple OSS Distributions
119*27b03b36SApple OSS Distributions do {
120*27b03b36SApple OSS Distributions union monotonic_ctl_add add_ctl;
121*27b03b36SApple OSS Distributions int r;
122*27b03b36SApple OSS Distributions
123*27b03b36SApple OSS Distributions add_ctl.in.config.event = REF_TIMEBASE_EVENT;
124*27b03b36SApple OSS Distributions add_ctl.in.config.allowed_ctr_mask = UINT64_MAX;
125*27b03b36SApple OSS Distributions
126*27b03b36SApple OSS Distributions r = ioctl(fd, MT_IOC_ADD, &add_ctl);
127*27b03b36SApple OSS Distributions if (r < 0 && errno == E2BIG) {
128*27b03b36SApple OSS Distributions break;
129*27b03b36SApple OSS Distributions }
130*27b03b36SApple OSS Distributions
131*27b03b36SApple OSS Distributions T_QUIET;
132*27b03b36SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(r, "added reference timebase event to counters");
133*27b03b36SApple OSS Distributions nctrs++;
134*27b03b36SApple OSS Distributions } while (nctrs < CTRS_MAX);
135*27b03b36SApple OSS Distributions
136*27b03b36SApple OSS Distributions T_EXPECT_LT(nctrs, CTRS_MAX, "able to allocate %d uncore PMCs", nctrs);
137*27b03b36SApple OSS Distributions }
138*27b03b36SApple OSS Distributions
139*27b03b36SApple OSS Distributions static uint32_t
uncore_add(int fd,uint64_t event,uint64_t allowed_ctrs,int error)140*27b03b36SApple OSS Distributions uncore_add(int fd, uint64_t event, uint64_t allowed_ctrs, int error)
141*27b03b36SApple OSS Distributions {
142*27b03b36SApple OSS Distributions int save_errno;
143*27b03b36SApple OSS Distributions int r;
144*27b03b36SApple OSS Distributions uint32_t ctr;
145*27b03b36SApple OSS Distributions union monotonic_ctl_add add_ctl;
146*27b03b36SApple OSS Distributions
147*27b03b36SApple OSS Distributions add_ctl.in.config.event = event;
148*27b03b36SApple OSS Distributions add_ctl.in.config.allowed_ctr_mask = allowed_ctrs;
149*27b03b36SApple OSS Distributions r = ioctl(fd, MT_IOC_ADD, &add_ctl);
150*27b03b36SApple OSS Distributions if (error) {
151*27b03b36SApple OSS Distributions save_errno = errno;
152*27b03b36SApple OSS Distributions T_EXPECT_LT(r, 0, "adding event to counter should fail");
153*27b03b36SApple OSS Distributions T_EXPECT_EQ(save_errno, error,
154*27b03b36SApple OSS Distributions "adding event to counter should fail with %d: %s",
155*27b03b36SApple OSS Distributions error, strerror(error));
156*27b03b36SApple OSS Distributions return UINT32_MAX;
157*27b03b36SApple OSS Distributions } else {
158*27b03b36SApple OSS Distributions T_QUIET;
159*27b03b36SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(r,
160*27b03b36SApple OSS Distributions "added event %#" PRIx64 " to counters", event);
161*27b03b36SApple OSS Distributions }
162*27b03b36SApple OSS Distributions
163*27b03b36SApple OSS Distributions ctr = add_ctl.out.ctr;
164*27b03b36SApple OSS Distributions T_QUIET; T_ASSERT_LT(ctr, (uint32_t)CTRS_MAX, "counter returned should be sane");
165*27b03b36SApple OSS Distributions return ctr;
166*27b03b36SApple OSS Distributions }
167*27b03b36SApple OSS Distributions
168*27b03b36SApple OSS Distributions T_DECL(uncore_collision,
169*27b03b36SApple OSS Distributions "ensure that trying to add an event on the same counter fails",
170*27b03b36SApple OSS Distributions T_META_ASROOT(true))
171*27b03b36SApple OSS Distributions {
172*27b03b36SApple OSS Distributions int fd;
173*27b03b36SApple OSS Distributions uint32_t ctr;
174*27b03b36SApple OSS Distributions
175*27b03b36SApple OSS Distributions fd = open_uncore_error(NULL);
176*27b03b36SApple OSS Distributions
177*27b03b36SApple OSS Distributions ctr = uncore_add(fd, REF_TIMEBASE_EVENT, UINT64_MAX, 0);
178*27b03b36SApple OSS Distributions T_LOG("added event to uncore counter %d\n", ctr);
179*27b03b36SApple OSS Distributions
180*27b03b36SApple OSS Distributions (void)uncore_add(fd, REF_TIMEBASE_EVENT, UINT64_C(1) << ctr, ENOSPC);
181*27b03b36SApple OSS Distributions }
182*27b03b36SApple OSS Distributions
183*27b03b36SApple OSS Distributions static void
uncore_enable(int fd)184*27b03b36SApple OSS Distributions uncore_enable(int fd)
185*27b03b36SApple OSS Distributions {
186*27b03b36SApple OSS Distributions union monotonic_ctl_enable en_ctl = {
187*27b03b36SApple OSS Distributions .in = { .enable = true }
188*27b03b36SApple OSS Distributions };
189*27b03b36SApple OSS Distributions
190*27b03b36SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(ioctl(fd, MT_IOC_ENABLE, &en_ctl),
191*27b03b36SApple OSS Distributions "enabling counters");
192*27b03b36SApple OSS Distributions }
193*27b03b36SApple OSS Distributions
194*27b03b36SApple OSS Distributions T_DECL(uncore_enabled_busy,
195*27b03b36SApple OSS Distributions "ensure that trying to add an event while enabled fails",
196*27b03b36SApple OSS Distributions T_META_ASROOT(true))
197*27b03b36SApple OSS Distributions {
198*27b03b36SApple OSS Distributions int fd;
199*27b03b36SApple OSS Distributions
200*27b03b36SApple OSS Distributions fd = open_uncore_error(NULL);
201*27b03b36SApple OSS Distributions
202*27b03b36SApple OSS Distributions (void)uncore_add(fd, REF_TIMEBASE_EVENT, UINT64_MAX, 0);
203*27b03b36SApple OSS Distributions
204*27b03b36SApple OSS Distributions uncore_enable(fd);
205*27b03b36SApple OSS Distributions (void)uncore_add(fd, REF_TIMEBASE_EVENT, UINT64_MAX, EBUSY);
206*27b03b36SApple OSS Distributions }
207*27b03b36SApple OSS Distributions
208*27b03b36SApple OSS Distributions T_DECL(uncore_reset,
209*27b03b36SApple OSS Distributions "ensure that resetting the counters works")
210*27b03b36SApple OSS Distributions {
211*27b03b36SApple OSS Distributions int fd;
212*27b03b36SApple OSS Distributions int r;
213*27b03b36SApple OSS Distributions
214*27b03b36SApple OSS Distributions fd = open_uncore_error(NULL);
215*27b03b36SApple OSS Distributions
216*27b03b36SApple OSS Distributions (void)uncore_add(fd, REF_TIMEBASE_EVENT, UINT64_C(1), 0);
217*27b03b36SApple OSS Distributions (void)uncore_add(fd, REF_TIMEBASE_EVENT, UINT64_C(1), ENOSPC);
218*27b03b36SApple OSS Distributions
219*27b03b36SApple OSS Distributions r = ioctl(fd, MT_IOC_RESET);
220*27b03b36SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(r, "resetting succeeds");
221*27b03b36SApple OSS Distributions
222*27b03b36SApple OSS Distributions T_LOG("adding event to same counter after reset");
223*27b03b36SApple OSS Distributions (void)uncore_add(fd, REF_TIMEBASE_EVENT, UINT64_C(1), 0);
224*27b03b36SApple OSS Distributions }
225*27b03b36SApple OSS Distributions
226*27b03b36SApple OSS Distributions #define SLEEP_USECS (500 * 1000)
227*27b03b36SApple OSS Distributions
228*27b03b36SApple OSS Distributions static int
uncore_add_all(int fd,uint64_t event,int * nmonitors)229*27b03b36SApple OSS Distributions uncore_add_all(int fd, uint64_t event, int *nmonitors)
230*27b03b36SApple OSS Distributions {
231*27b03b36SApple OSS Distributions int nctrs = 0;
232*27b03b36SApple OSS Distributions int r;
233*27b03b36SApple OSS Distributions
234*27b03b36SApple OSS Distributions do {
235*27b03b36SApple OSS Distributions union monotonic_ctl_add add_ctl;
236*27b03b36SApple OSS Distributions
237*27b03b36SApple OSS Distributions add_ctl.in.config.event = event;
238*27b03b36SApple OSS Distributions add_ctl.in.config.allowed_ctr_mask = UINT64_MAX;
239*27b03b36SApple OSS Distributions
240*27b03b36SApple OSS Distributions r = ioctl(fd, MT_IOC_ADD, &add_ctl);
241*27b03b36SApple OSS Distributions if (r < 0 && errno == E2BIG) {
242*27b03b36SApple OSS Distributions break;
243*27b03b36SApple OSS Distributions }
244*27b03b36SApple OSS Distributions
245*27b03b36SApple OSS Distributions T_QUIET;
246*27b03b36SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(r, "added event %#" PRIx64 " to counters",
247*27b03b36SApple OSS Distributions event);
248*27b03b36SApple OSS Distributions nctrs++;
249*27b03b36SApple OSS Distributions } while (nctrs < CTRS_MAX);
250*27b03b36SApple OSS Distributions
251*27b03b36SApple OSS Distributions if (nmonitors) {
252*27b03b36SApple OSS Distributions union monotonic_ctl_info info_ctl;
253*27b03b36SApple OSS Distributions r = ioctl(fd, MT_IOC_GET_INFO, &info_ctl);
254*27b03b36SApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(r, "got info about uncore counters");
255*27b03b36SApple OSS Distributions
256*27b03b36SApple OSS Distributions *nmonitors = (int)info_ctl.out.nmonitors;
257*27b03b36SApple OSS Distributions }
258*27b03b36SApple OSS Distributions
259*27b03b36SApple OSS Distributions return nctrs;
260*27b03b36SApple OSS Distributions }
261*27b03b36SApple OSS Distributions
262*27b03b36SApple OSS Distributions T_DECL(uncore_accuracy,
263*27b03b36SApple OSS Distributions "ensure that the uncore counters count accurately",
264*27b03b36SApple OSS Distributions T_META_ASROOT(true),
265*27b03b36SApple OSS Distributions T_META_MAYFAIL("rdar://88973518, threads need to be forced onto clusters"))
266*27b03b36SApple OSS Distributions {
267*27b03b36SApple OSS Distributions int fd;
268*27b03b36SApple OSS Distributions int nctrs = 0;
269*27b03b36SApple OSS Distributions int nmonitors = 0;
270*27b03b36SApple OSS Distributions uint64_t ctr_mask;
271*27b03b36SApple OSS Distributions uint64_t counts[2][CTRS_MAX];
272*27b03b36SApple OSS Distributions uint64_t times[2];
273*27b03b36SApple OSS Distributions
274*27b03b36SApple OSS Distributions fd = open_uncore_error(NULL);
275*27b03b36SApple OSS Distributions
276*27b03b36SApple OSS Distributions /*
277*27b03b36SApple OSS Distributions * The reference timebase event counts the same as mach_continuous_time
278*27b03b36SApple OSS Distributions * (on hardware supporting uncore counters). Make sure that the counter
279*27b03b36SApple OSS Distributions * is close to the values returned from the trap.
280*27b03b36SApple OSS Distributions *
281*27b03b36SApple OSS Distributions * Fill all the counters with this event.
282*27b03b36SApple OSS Distributions */
283*27b03b36SApple OSS Distributions nctrs = uncore_add_all(fd, REF_TIMEBASE_EVENT, &nmonitors);
284*27b03b36SApple OSS Distributions ctr_mask = (UINT64_C(1) << nctrs) - 1;
285*27b03b36SApple OSS Distributions
286*27b03b36SApple OSS Distributions T_LOG("added %d counters to check", nctrs);
287*27b03b36SApple OSS Distributions
288*27b03b36SApple OSS Distributions uncore_enable(fd);
289*27b03b36SApple OSS Distributions
290*27b03b36SApple OSS Distributions /*
291*27b03b36SApple OSS Distributions * First, make sure there's an upper bound on the counter -- take the
292*27b03b36SApple OSS Distributions * time around getting the counter values.
293*27b03b36SApple OSS Distributions */
294*27b03b36SApple OSS Distributions
295*27b03b36SApple OSS Distributions times[0] = mach_absolute_time();
296*27b03b36SApple OSS Distributions uncore_counts(fd, ctr_mask, counts[0]);
297*27b03b36SApple OSS Distributions
298*27b03b36SApple OSS Distributions usleep(SLEEP_USECS);
299*27b03b36SApple OSS Distributions
300*27b03b36SApple OSS Distributions uncore_counts(fd, ctr_mask, counts[1]);
301*27b03b36SApple OSS Distributions times[1] = mach_absolute_time();
302*27b03b36SApple OSS Distributions
303*27b03b36SApple OSS Distributions T_QUIET; T_EXPECT_GT(times[1], times[0],
304*27b03b36SApple OSS Distributions "mach_continuous_time is monotonically increasing");
305*27b03b36SApple OSS Distributions for (int i = 0; i < nctrs; i++) {
306*27b03b36SApple OSS Distributions T_EXPECT_GT(counts[1][i], counts[0][i],
307*27b03b36SApple OSS Distributions "uncore counter %d value is monotonically increasing", i);
308*27b03b36SApple OSS Distributions T_EXPECT_LT(counts[1][i] - counts[0][i], times[1] - times[0],
309*27b03b36SApple OSS Distributions "reference timebase on uncore counter %d satisfies upper bound "
310*27b03b36SApple OSS Distributions "from mach_absolute_time", i);
311*27b03b36SApple OSS Distributions }
312*27b03b36SApple OSS Distributions
313*27b03b36SApple OSS Distributions /*
314*27b03b36SApple OSS Distributions * Next, the lower bound -- put mach_absolute_time inside getting the
315*27b03b36SApple OSS Distributions * counter values.
316*27b03b36SApple OSS Distributions */
317*27b03b36SApple OSS Distributions
318*27b03b36SApple OSS Distributions uncore_counts(fd, ctr_mask, counts[0]);
319*27b03b36SApple OSS Distributions times[0] = mach_absolute_time();
320*27b03b36SApple OSS Distributions
321*27b03b36SApple OSS Distributions volatile int iterations = 100000;
322*27b03b36SApple OSS Distributions while (iterations--) {
323*27b03b36SApple OSS Distributions ;
324*27b03b36SApple OSS Distributions }
325*27b03b36SApple OSS Distributions
326*27b03b36SApple OSS Distributions times[1] = mach_absolute_time();
327*27b03b36SApple OSS Distributions uncore_counts(fd, ctr_mask, counts[1]);
328*27b03b36SApple OSS Distributions
329*27b03b36SApple OSS Distributions for (int mon = 0; mon < nmonitors; mon++) {
330*27b03b36SApple OSS Distributions for (int i = 0; i < nctrs; i++) {
331*27b03b36SApple OSS Distributions uint64_t after = counts[1][i * mon];
332*27b03b36SApple OSS Distributions uint64_t before = counts[0][i * mon];
333*27b03b36SApple OSS Distributions uint64_t delta = after - before;
334*27b03b36SApple OSS Distributions T_LOG("%d,%2d: %12" PRIu64 "%12" PRIu64 " = %10" PRIu64, mon, i,
335*27b03b36SApple OSS Distributions before, after, delta);
336*27b03b36SApple OSS Distributions T_QUIET;
337*27b03b36SApple OSS Distributions T_EXPECT_GT(after, before,
338*27b03b36SApple OSS Distributions "uncore %d counter %d value is monotonically increasing",
339*27b03b36SApple OSS Distributions mon, i);
340*27b03b36SApple OSS Distributions T_QUIET;
341*27b03b36SApple OSS Distributions T_EXPECT_GT(counts[1][i * mon] - counts[0][i * mon],
342*27b03b36SApple OSS Distributions times[1] - times[0],
343*27b03b36SApple OSS Distributions "reference timebase on uncore %d counter %d satisfies "
344*27b03b36SApple OSS Distributions "lower bound from mach_absolute_time", mon, i);
345*27b03b36SApple OSS Distributions }
346*27b03b36SApple OSS Distributions }
347*27b03b36SApple OSS Distributions }
348*27b03b36SApple OSS Distributions
349*27b03b36SApple OSS Distributions T_DECL(uncore_ownership,
350*27b03b36SApple OSS Distributions "ensure the dev node cannot be open in two places",
351*27b03b36SApple OSS Distributions T_META_ASROOT(true))
352*27b03b36SApple OSS Distributions {
353*27b03b36SApple OSS Distributions int fd;
354*27b03b36SApple OSS Distributions int other_fd;
355*27b03b36SApple OSS Distributions int error;
356*27b03b36SApple OSS Distributions
357*27b03b36SApple OSS Distributions fd = open_uncore_error(NULL);
358*27b03b36SApple OSS Distributions
359*27b03b36SApple OSS Distributions other_fd = open_uncore_error(&error);
360*27b03b36SApple OSS Distributions T_ASSERT_LT(other_fd, 0, "opening a second uncore fd should fail");
361*27b03b36SApple OSS Distributions }
362*27b03b36SApple OSS Distributions
363*27b03b36SApple OSS Distributions T_DECL(uncore_root_required,
364*27b03b36SApple OSS Distributions "ensure the dev node cannot be opened by non-root users",
365*27b03b36SApple OSS Distributions T_META_ASROOT(false))
366*27b03b36SApple OSS Distributions {
367*27b03b36SApple OSS Distributions int fd;
368*27b03b36SApple OSS Distributions int error = 0;
369*27b03b36SApple OSS Distributions
370*27b03b36SApple OSS Distributions T_SKIP("libdarwintest doesn't drop privileges properly");
371*27b03b36SApple OSS Distributions
372*27b03b36SApple OSS Distributions fd = open_uncore_error(&error);
373*27b03b36SApple OSS Distributions T_ASSERT_LT(fd, 0, "opening dev node should not return an fd");
374*27b03b36SApple OSS Distributions T_ASSERT_EQ(error, EPERM,
375*27b03b36SApple OSS Distributions "opening dev node as non-root user should fail with EPERM");
376*27b03b36SApple OSS Distributions }
377*27b03b36SApple OSS Distributions
378*27b03b36SApple OSS Distributions T_DECL(perf_uncore,
379*27b03b36SApple OSS Distributions "measure the latency of accessing the counters",
380*27b03b36SApple OSS Distributions T_META_TAG_PERF)
381*27b03b36SApple OSS Distributions {
382*27b03b36SApple OSS Distributions int fd;
383*27b03b36SApple OSS Distributions int nctrs;
384*27b03b36SApple OSS Distributions int nmonitors;
385*27b03b36SApple OSS Distributions int r;
386*27b03b36SApple OSS Distributions uint64_t ctr_mask;
387*27b03b36SApple OSS Distributions dt_stat_thread_instructions_t counts_instrs;
388*27b03b36SApple OSS Distributions dt_stat_t counter_deltas;
389*27b03b36SApple OSS Distributions
390*27b03b36SApple OSS Distributions counts_instrs = dt_stat_thread_instructions_create("ioctl_counts");
391*27b03b36SApple OSS Distributions counter_deltas = dt_stat_create("abs_time", "between_each_counter");
392*27b03b36SApple OSS Distributions
393*27b03b36SApple OSS Distributions fd = open_uncore_error(NULL);
394*27b03b36SApple OSS Distributions
395*27b03b36SApple OSS Distributions nctrs = uncore_add_all(fd, REF_TIMEBASE_EVENT, &nmonitors);
396*27b03b36SApple OSS Distributions ctr_mask = (UINT64_C(1) << nctrs) - 1;
397*27b03b36SApple OSS Distributions
398*27b03b36SApple OSS Distributions uncore_enable(fd);
399*27b03b36SApple OSS Distributions
400*27b03b36SApple OSS Distributions do {
401*27b03b36SApple OSS Distributions dt_stat_token token;
402*27b03b36SApple OSS Distributions uint64_t counts[nctrs * nmonitors];
403*27b03b36SApple OSS Distributions union monotonic_ctl_counts *cts_ctl;
404*27b03b36SApple OSS Distributions
405*27b03b36SApple OSS Distributions cts_ctl = (union monotonic_ctl_counts *)counts;
406*27b03b36SApple OSS Distributions cts_ctl->in.ctr_mask = ctr_mask;
407*27b03b36SApple OSS Distributions
408*27b03b36SApple OSS Distributions token = dt_stat_thread_instructions_begin(counts_instrs);
409*27b03b36SApple OSS Distributions r = ioctl(fd, MT_IOC_COUNTS, cts_ctl);
410*27b03b36SApple OSS Distributions dt_stat_thread_instructions_end(counts_instrs, token);
411*27b03b36SApple OSS Distributions T_QUIET;
412*27b03b36SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(r,
413*27b03b36SApple OSS Distributions "getting uncore counter values %#" PRIx64, ctr_mask);
414*27b03b36SApple OSS Distributions
415*27b03b36SApple OSS Distributions for (int i = 0; i < (nctrs - 1); i++) {
416*27b03b36SApple OSS Distributions dt_stat_add(counter_deltas, (double)(counts[i + 1] - counts[i]));
417*27b03b36SApple OSS Distributions }
418*27b03b36SApple OSS Distributions } while (!dt_stat_stable(counts_instrs) || !dt_stat_stable(counter_deltas));
419*27b03b36SApple OSS Distributions
420*27b03b36SApple OSS Distributions dt_stat_finalize(counts_instrs);
421*27b03b36SApple OSS Distributions dt_stat_finalize(counter_deltas);
422*27b03b36SApple OSS Distributions }
423