1*d8b80295SApple OSS Distributions // Copyright (c) 2020 Apple Inc. All rights reserved.
2*d8b80295SApple OSS Distributions
3*d8b80295SApple OSS Distributions #include <darwintest.h>
4*d8b80295SApple OSS Distributions #include <darwintest_utils.h>
5*d8b80295SApple OSS Distributions #include <dispatch/dispatch.h>
6*d8b80295SApple OSS Distributions #include <inttypes.h>
7*d8b80295SApple OSS Distributions #include <ktrace/session.h>
8*d8b80295SApple OSS Distributions #include <ktrace/private.h>
9*d8b80295SApple OSS Distributions #include <kperf/kperf.h>
10*d8b80295SApple OSS Distributions #include <stdlib.h>
11*d8b80295SApple OSS Distributions #include <sys/kdebug.h>
12*d8b80295SApple OSS Distributions #include <sys/kdebug_private.h>
13*d8b80295SApple OSS Distributions #include <sys/sysctl.h>
14*d8b80295SApple OSS Distributions #include <stdint.h>
15*d8b80295SApple OSS Distributions
16*d8b80295SApple OSS Distributions #include "ktrace_helpers.h"
17*d8b80295SApple OSS Distributions #include "test_utils.h"
18*d8b80295SApple OSS Distributions #include "ktrace_meta.h"
19*d8b80295SApple OSS Distributions
20*d8b80295SApple OSS Distributions static const uint32_t frame_eventid = KDBG_EVENTID(DBG_BSD,
21*d8b80295SApple OSS Distributions DBG_BSD_KDEBUG_TEST, 1);
22*d8b80295SApple OSS Distributions
23*d8b80295SApple OSS Distributions static ktrace_session_t
future_events_session(void)24*d8b80295SApple OSS Distributions future_events_session(void)
25*d8b80295SApple OSS Distributions {
26*d8b80295SApple OSS Distributions ktrace_session_t ktsess = ktrace_session_create();
27*d8b80295SApple OSS Distributions T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(ktsess, "failed to create session");
28*d8b80295SApple OSS Distributions
29*d8b80295SApple OSS Distributions ktrace_events_single(ktsess, KDBG_EVENTID(DBG_BSD, DBG_BSD_KDEBUG_TEST, 0),
30*d8b80295SApple OSS Distributions ^(struct trace_point *tp __unused) {
31*d8b80295SApple OSS Distributions T_FAIL("saw future test event from IOP");
32*d8b80295SApple OSS Distributions });
33*d8b80295SApple OSS Distributions ktrace_events_single(ktsess, frame_eventid, ^(struct trace_point *tp) {
34*d8b80295SApple OSS Distributions if (tp->debugid & DBG_FUNC_START) {
35*d8b80295SApple OSS Distributions T_LOG("saw start event");
36*d8b80295SApple OSS Distributions } else {
37*d8b80295SApple OSS Distributions T_LOG("saw event traced after trying to trace future event, ending");
38*d8b80295SApple OSS Distributions ktrace_end(ktsess, 1);
39*d8b80295SApple OSS Distributions }
40*d8b80295SApple OSS Distributions });
41*d8b80295SApple OSS Distributions
42*d8b80295SApple OSS Distributions ktrace_set_collection_interval(ktsess, 100);
43*d8b80295SApple OSS Distributions return ktsess;
44*d8b80295SApple OSS Distributions }
45*d8b80295SApple OSS Distributions
46*d8b80295SApple OSS Distributions T_DECL(future_iop_events,
47*d8b80295SApple OSS Distributions "make sure IOPs cannot trace events in the future while live tracing")
48*d8b80295SApple OSS Distributions {
49*d8b80295SApple OSS Distributions start_controlling_ktrace();
50*d8b80295SApple OSS Distributions ktrace_session_t ktsess = future_events_session();
51*d8b80295SApple OSS Distributions ktrace_set_completion_handler(ktsess, ^{
52*d8b80295SApple OSS Distributions ktrace_session_destroy(ktsess);
53*d8b80295SApple OSS Distributions T_END;
54*d8b80295SApple OSS Distributions });
55*d8b80295SApple OSS Distributions
56*d8b80295SApple OSS Distributions T_ASSERT_POSIX_ZERO(ktrace_start(ktsess, dispatch_get_main_queue()),
57*d8b80295SApple OSS Distributions "start tracing");
58*d8b80295SApple OSS Distributions kdebug_trace(frame_eventid | DBG_FUNC_START, 0, 0, 0, 0);
59*d8b80295SApple OSS Distributions assert_kdebug_test(KDTEST_FUTURE_TIMESTAMP, "induce future times");
60*d8b80295SApple OSS Distributions kdebug_trace(frame_eventid | DBG_FUNC_END, 0, 0, 0, 0);
61*d8b80295SApple OSS Distributions
62*d8b80295SApple OSS Distributions dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC),
63*d8b80295SApple OSS Distributions dispatch_get_main_queue(), ^{
64*d8b80295SApple OSS Distributions T_FAIL("ending tracing after timeout");
65*d8b80295SApple OSS Distributions ktrace_end(ktsess, 0);
66*d8b80295SApple OSS Distributions });
67*d8b80295SApple OSS Distributions
68*d8b80295SApple OSS Distributions dispatch_main();
69*d8b80295SApple OSS Distributions }
70*d8b80295SApple OSS Distributions
71*d8b80295SApple OSS Distributions T_DECL(future_iop_events_disabled,
72*d8b80295SApple OSS Distributions "make sure IOPs cannot trace events in the future after disabling tracing")
73*d8b80295SApple OSS Distributions {
74*d8b80295SApple OSS Distributions start_controlling_ktrace();
75*d8b80295SApple OSS Distributions ktrace_session_t ktsess = future_events_session();
76*d8b80295SApple OSS Distributions T_ASSERT_POSIX_ZERO(ktrace_configure(ktsess), "configure tracing");
77*d8b80295SApple OSS Distributions
78*d8b80295SApple OSS Distributions kdebug_trace(frame_eventid | DBG_FUNC_START, 0, 0, 0, 0);
79*d8b80295SApple OSS Distributions assert_kdebug_test(KDTEST_FUTURE_TIMESTAMP, "induce future times");
80*d8b80295SApple OSS Distributions kdebug_trace(frame_eventid | DBG_FUNC_END, 0, 0, 0, 0);
81*d8b80295SApple OSS Distributions
82*d8b80295SApple OSS Distributions T_ASSERT_POSIX_ZERO(ktrace_disable_configured(ktsess),
83*d8b80295SApple OSS Distributions "disable tracing");
84*d8b80295SApple OSS Distributions ktrace_session_destroy(ktsess);
85*d8b80295SApple OSS Distributions
86*d8b80295SApple OSS Distributions ktsess = future_events_session();
87*d8b80295SApple OSS Distributions T_QUIET;
88*d8b80295SApple OSS Distributions T_ASSERT_POSIX_ZERO(ktrace_set_use_existing(ktsess), "use existing trace");
89*d8b80295SApple OSS Distributions ktrace_set_completion_handler(ktsess, ^{
90*d8b80295SApple OSS Distributions ktrace_session_destroy(ktsess);
91*d8b80295SApple OSS Distributions T_END;
92*d8b80295SApple OSS Distributions });
93*d8b80295SApple OSS Distributions
94*d8b80295SApple OSS Distributions T_ASSERT_POSIX_ZERO(ktrace_start(ktsess, dispatch_get_main_queue()),
95*d8b80295SApple OSS Distributions "start tracing existing session");
96*d8b80295SApple OSS Distributions
97*d8b80295SApple OSS Distributions dispatch_main();
98*d8b80295SApple OSS Distributions }
99*d8b80295SApple OSS Distributions
100*d8b80295SApple OSS Distributions T_DECL(iop_events_disable,
101*d8b80295SApple OSS Distributions "make sure IOP events are flushed before disabling trace")
102*d8b80295SApple OSS Distributions {
103*d8b80295SApple OSS Distributions start_controlling_ktrace();
104*d8b80295SApple OSS Distributions ktrace_session_t ktsess = future_events_session();
105*d8b80295SApple OSS Distributions
106*d8b80295SApple OSS Distributions assert_kdebug_test(KDTEST_SETUP_IOP, "setup sync flush IOP");
107*d8b80295SApple OSS Distributions T_ASSERT_POSIX_ZERO(ktrace_configure(ktsess), "configure tracing");
108*d8b80295SApple OSS Distributions
109*d8b80295SApple OSS Distributions kdebug_trace(frame_eventid | DBG_FUNC_START, 0, 0, 0, 0);
110*d8b80295SApple OSS Distributions
111*d8b80295SApple OSS Distributions T_ASSERT_POSIX_ZERO(ktrace_disable_configured(ktsess),
112*d8b80295SApple OSS Distributions "disable tracing");
113*d8b80295SApple OSS Distributions ktrace_session_destroy(ktsess);
114*d8b80295SApple OSS Distributions
115*d8b80295SApple OSS Distributions ktsess = ktrace_session_create();
116*d8b80295SApple OSS Distributions T_QUIET; T_WITH_ERRNO;
117*d8b80295SApple OSS Distributions T_ASSERT_NOTNULL(ktsess, "create session");
118*d8b80295SApple OSS Distributions
119*d8b80295SApple OSS Distributions ktrace_events_single(ktsess,
120*d8b80295SApple OSS Distributions KDBG_EVENTID(DBG_BSD, DBG_BSD_KDEBUG_TEST, 0xff),
121*d8b80295SApple OSS Distributions ^(struct trace_point *tp __unused) {
122*d8b80295SApple OSS Distributions T_PASS("saw IOP event from sync flush");
123*d8b80295SApple OSS Distributions });
124*d8b80295SApple OSS Distributions
125*d8b80295SApple OSS Distributions T_QUIET;
126*d8b80295SApple OSS Distributions T_ASSERT_POSIX_ZERO(ktrace_set_use_existing(ktsess), "use existing trace");
127*d8b80295SApple OSS Distributions ktrace_set_completion_handler(ktsess, ^{
128*d8b80295SApple OSS Distributions ktrace_session_destroy(ktsess);
129*d8b80295SApple OSS Distributions T_END;
130*d8b80295SApple OSS Distributions });
131*d8b80295SApple OSS Distributions
132*d8b80295SApple OSS Distributions T_ASSERT_POSIX_ZERO(ktrace_start(ktsess, dispatch_get_main_queue()),
133*d8b80295SApple OSS Distributions "start tracing existing session");
134*d8b80295SApple OSS Distributions
135*d8b80295SApple OSS Distributions dispatch_main();
136*d8b80295SApple OSS Distributions }
137*d8b80295SApple OSS Distributions
138*d8b80295SApple OSS Distributions T_DECL(past_coproc_events,
139*d8b80295SApple OSS Distributions "make sure past events from coprocessors log a TRACE_PAST_EVENTS event")
140*d8b80295SApple OSS Distributions {
141*d8b80295SApple OSS Distributions start_controlling_ktrace();
142*d8b80295SApple OSS Distributions ktrace_session_t ktsess = future_events_session();
143*d8b80295SApple OSS Distributions T_ASSERT_POSIX_ZERO(ktrace_configure(ktsess), "configure tracing");
144*d8b80295SApple OSS Distributions
145*d8b80295SApple OSS Distributions kdebug_trace(frame_eventid | DBG_FUNC_START, 0, 0, 0, 0);
146*d8b80295SApple OSS Distributions assert_kdebug_test(KDTEST_PAST_EVENT, "induce past events");
147*d8b80295SApple OSS Distributions kdebug_trace(frame_eventid | DBG_FUNC_END, 0, 0, 0, 0);
148*d8b80295SApple OSS Distributions
149*d8b80295SApple OSS Distributions T_ASSERT_POSIX_ZERO(ktrace_disable_configured(ktsess), "disable tracing");
150*d8b80295SApple OSS Distributions ktrace_session_destroy(ktsess);
151*d8b80295SApple OSS Distributions
152*d8b80295SApple OSS Distributions ktsess = future_events_session();
153*d8b80295SApple OSS Distributions T_QUIET;
154*d8b80295SApple OSS Distributions T_ASSERT_POSIX_ZERO(ktrace_set_use_existing(ktsess), "use existing trace");
155*d8b80295SApple OSS Distributions __block bool saw_past_event = false;
156*d8b80295SApple OSS Distributions ktrace_events_single(ktsess, TRACE_PAST_EVENTS,
157*d8b80295SApple OSS Distributions ^(__unused ktrace_event_t event) {
158*d8b80295SApple OSS Distributions saw_past_event = true;
159*d8b80295SApple OSS Distributions });
160*d8b80295SApple OSS Distributions ktrace_set_completion_handler(ktsess, ^{
161*d8b80295SApple OSS Distributions ktrace_session_destroy(ktsess);
162*d8b80295SApple OSS Distributions T_EXPECT_TRUE(saw_past_event, "saw past event");
163*d8b80295SApple OSS Distributions T_END;
164*d8b80295SApple OSS Distributions });
165*d8b80295SApple OSS Distributions
166*d8b80295SApple OSS Distributions T_ASSERT_POSIX_ZERO(ktrace_start(ktsess, dispatch_get_main_queue()),
167*d8b80295SApple OSS Distributions "start tracing existing session");
168*d8b80295SApple OSS Distributions
169*d8b80295SApple OSS Distributions dispatch_main();
170*d8b80295SApple OSS Distributions }
171*d8b80295SApple OSS Distributions
172*d8b80295SApple OSS Distributions static void
expect_convert_between_abs_cont(bool abs_to_cont)173*d8b80295SApple OSS Distributions expect_convert_between_abs_cont(bool abs_to_cont)
174*d8b80295SApple OSS Distributions {
175*d8b80295SApple OSS Distributions uint64_t cur_abs_time, cur_cont_time;
176*d8b80295SApple OSS Distributions kern_return_t kr = mach_get_times(&cur_abs_time, &cur_cont_time, NULL);
177*d8b80295SApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "mach_get_times");
178*d8b80295SApple OSS Distributions bool hasnt_slept = cur_abs_time == cur_cont_time;
179*d8b80295SApple OSS Distributions if (hasnt_slept) {
180*d8b80295SApple OSS Distributions T_LOG("system hasn't slept, so continuous and absolute times are equal");
181*d8b80295SApple OSS Distributions T_LOG("this test cannot ensure time conversions are done properly");
182*d8b80295SApple OSS Distributions } else {
183*d8b80295SApple OSS Distributions T_LOG("system has slept, times differ by %llu",
184*d8b80295SApple OSS Distributions cur_cont_time - cur_abs_time);
185*d8b80295SApple OSS Distributions }
186*d8b80295SApple OSS Distributions
187*d8b80295SApple OSS Distributions start_controlling_ktrace();
188*d8b80295SApple OSS Distributions ktrace_session_t ktsess = ktrace_session_create();
189*d8b80295SApple OSS Distributions ktrace_set_collection_interval(ktsess, 100);
190*d8b80295SApple OSS Distributions if (abs_to_cont) {
191*d8b80295SApple OSS Distributions ktrace_set_continuous_timestamps(ktsess, true);
192*d8b80295SApple OSS Distributions }
193*d8b80295SApple OSS Distributions
194*d8b80295SApple OSS Distributions __block bool found_abs_event = false;
195*d8b80295SApple OSS Distributions __block bool found_cont_event = false;
196*d8b80295SApple OSS Distributions const uint32_t abs_eventid = KDBG_EVENTID(DBG_BSD, DBG_BSD_KDEBUG_TEST, 0);
197*d8b80295SApple OSS Distributions ktrace_events_single(ktsess, abs_eventid, ^(struct trace_point *tp) {
198*d8b80295SApple OSS Distributions found_abs_event = true;
199*d8b80295SApple OSS Distributions uint64_t arg_timestamp = (tp->arg1 & UINT32_MAX) | (tp->arg2 << 32);
200*d8b80295SApple OSS Distributions if (abs_to_cont) {
201*d8b80295SApple OSS Distributions if (hasnt_slept) {
202*d8b80295SApple OSS Distributions T_MAYFAIL;
203*d8b80295SApple OSS Distributions }
204*d8b80295SApple OSS Distributions T_EXPECT_NE(tp->timestamp, arg_timestamp,
205*d8b80295SApple OSS Distributions "timestamp from absolute time IOP should be converted");
206*d8b80295SApple OSS Distributions } else {
207*d8b80295SApple OSS Distributions T_EXPECT_EQ(tp->timestamp, arg_timestamp,
208*d8b80295SApple OSS Distributions "timestamp from absolute time IOP should not be converted");
209*d8b80295SApple OSS Distributions }
210*d8b80295SApple OSS Distributions if (found_cont_event && found_abs_event) {
211*d8b80295SApple OSS Distributions ktrace_end(ktsess, 1);
212*d8b80295SApple OSS Distributions }
213*d8b80295SApple OSS Distributions });
214*d8b80295SApple OSS Distributions
215*d8b80295SApple OSS Distributions const uint32_t cont_eventid = KDBG_EVENTID(DBG_BSD, DBG_BSD_KDEBUG_TEST, 1);
216*d8b80295SApple OSS Distributions ktrace_events_single(ktsess, cont_eventid, ^(struct trace_point *tp) {
217*d8b80295SApple OSS Distributions found_cont_event = true;
218*d8b80295SApple OSS Distributions uint64_t arg_timestamp = (tp->arg1 & UINT32_MAX) | (tp->arg2 << 32);
219*d8b80295SApple OSS Distributions if (abs_to_cont) {
220*d8b80295SApple OSS Distributions T_EXPECT_EQ(tp->timestamp, arg_timestamp,
221*d8b80295SApple OSS Distributions "timestamp from continuous time coprocessor should not be "
222*d8b80295SApple OSS Distributions "converted");
223*d8b80295SApple OSS Distributions } else {
224*d8b80295SApple OSS Distributions if (hasnt_slept) {
225*d8b80295SApple OSS Distributions T_MAYFAIL;
226*d8b80295SApple OSS Distributions }
227*d8b80295SApple OSS Distributions T_EXPECT_NE(tp->timestamp, arg_timestamp,
228*d8b80295SApple OSS Distributions "timestamp from continuous time coprocessor should be "
229*d8b80295SApple OSS Distributions "converted");
230*d8b80295SApple OSS Distributions }
231*d8b80295SApple OSS Distributions if (found_cont_event && found_abs_event) {
232*d8b80295SApple OSS Distributions ktrace_end(ktsess, 1);
233*d8b80295SApple OSS Distributions }
234*d8b80295SApple OSS Distributions });
235*d8b80295SApple OSS Distributions
236*d8b80295SApple OSS Distributions ktrace_set_completion_handler(ktsess, ^{
237*d8b80295SApple OSS Distributions T_EXPECT_TRUE(found_abs_event, "absolute time event present");
238*d8b80295SApple OSS Distributions T_EXPECT_TRUE(found_cont_event, "continuous time event present");
239*d8b80295SApple OSS Distributions ktrace_session_destroy(ktsess);
240*d8b80295SApple OSS Distributions T_END;
241*d8b80295SApple OSS Distributions });
242*d8b80295SApple OSS Distributions
243*d8b80295SApple OSS Distributions assert_kdebug_test(KDTEST_SETUP_IOP, "setup sync flush IOP");
244*d8b80295SApple OSS Distributions assert_kdebug_test(KDTEST_SETUP_COPROCESSOR, "setup coprocessor");
245*d8b80295SApple OSS Distributions
246*d8b80295SApple OSS Distributions T_ASSERT_POSIX_ZERO(ktrace_start(ktsess, dispatch_get_main_queue()),
247*d8b80295SApple OSS Distributions "start tracing");
248*d8b80295SApple OSS Distributions assert_kdebug_test(KDTEST_ABSOLUTE_TIMESTAMP, "induce absolute times");
249*d8b80295SApple OSS Distributions assert_kdebug_test(KDTEST_CONTINUOUS_TIMESTAMP, "induce continuous times");
250*d8b80295SApple OSS Distributions T_QUIET;
251*d8b80295SApple OSS Distributions T_EXPECT_EQ(kdebug_using_continuous_time(), abs_to_cont,
252*d8b80295SApple OSS Distributions "should be using continuous time");
253*d8b80295SApple OSS Distributions
254*d8b80295SApple OSS Distributions dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC),
255*d8b80295SApple OSS Distributions dispatch_get_main_queue(), ^{
256*d8b80295SApple OSS Distributions T_LOG("ending tracing after timeout");
257*d8b80295SApple OSS Distributions ktrace_end(ktsess, 0);
258*d8b80295SApple OSS Distributions });
259*d8b80295SApple OSS Distributions }
260*d8b80295SApple OSS Distributions
261*d8b80295SApple OSS Distributions T_DECL(absolute_to_continuous_iop,
262*d8b80295SApple OSS Distributions "expect IOPs issuing absolute times show up as continuous in the stream")
263*d8b80295SApple OSS Distributions {
264*d8b80295SApple OSS Distributions expect_convert_between_abs_cont(true);
265*d8b80295SApple OSS Distributions dispatch_main();
266*d8b80295SApple OSS Distributions }
267*d8b80295SApple OSS Distributions
268*d8b80295SApple OSS Distributions T_DECL(continuous_to_absolute_coproc,
269*d8b80295SApple OSS Distributions "expect IOPs issuing absolute times show up as continuous in the stream")
270*d8b80295SApple OSS Distributions {
271*d8b80295SApple OSS Distributions expect_convert_between_abs_cont(false);
272*d8b80295SApple OSS Distributions dispatch_main();
273*d8b80295SApple OSS Distributions }
274