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