4 #include <darwintest.h>
6 #include <sys/kdebug.h>
7 #include <sys/sysctl.h>
13 T_META_NAMESPACE("xnu.perf.kdebug"),
15 T_META_CHECK_LEAKS(false),
20 // Helper functions for direct control over the kernel trace facility.
23 static void _sysctl_reset() {
24 int mib
[] = { CTL_KERN
, KERN_KDEBUG
, KERN_KDREMOVE
};
25 if(sysctl(mib
, 3, NULL
, NULL
, NULL
, 0)) {
26 T_FAIL("KERN_KDREMOVE sysctl failed");
30 static void _sysctl_setbuf(uint32_t capacity
) {
31 int mib
[] = { CTL_KERN
, KERN_KDEBUG
, KERN_KDSETBUF
, (int)capacity
};
32 if (sysctl(mib
, 4, NULL
, NULL
, NULL
, 0)) {
33 T_FAIL("KERN_KDSETBUF sysctl failed");
37 static void _sysctl_setup() {
38 int mib
[] = { CTL_KERN
, KERN_KDEBUG
, KERN_KDSETUP
};
39 if (sysctl(mib
, 3, NULL
, NULL
, NULL
, 0)) {
40 T_FAIL("KERN_KDSETUP sysctl failed");
44 static void _sysctl_enable(int value
)
46 int mib
[] = { CTL_KERN
, KERN_KDEBUG
, KERN_KDENABLE
, value
};
47 if (sysctl(mib
, 4, NULL
, NULL
, NULL
, 0) < 0) {
48 T_FAIL("KERN_KDENABLE sysctl failed");
52 static void _sysctl_enable_typefilter(uint8_t* type_filter_bitmap
) {
53 int mib
[] = { CTL_KERN
, KERN_KDEBUG
, KERN_KDSET_TYPEFILTER
};
54 size_t needed
= KDBG_TYPEFILTER_BITMAP_SIZE
;
55 if(sysctl(mib
, 3, type_filter_bitmap
, &needed
, NULL
, 0)) {
56 T_FAIL("KERN_KDSET_TYPEFILTER sysctl failed");
60 static void _sysctl_nowrap(bool is_nowrap
) {
61 int mib
[] = { CTL_KERN
, KERN_KDEBUG
, is_nowrap
? KERN_KDEFLAGS
: KERN_KDDFLAGS
, KDBG_NOWRAP
};
62 if (sysctl(mib
, 4, NULL
, NULL
, NULL
, 0)) {
63 T_FAIL("KDBG_NOWRAP sysctl failed");
67 static void enable_tracing(bool value
) {
68 _sysctl_enable(value
? KDEBUG_ENABLE_TRACE
: 0);
71 static void enable_typefilter_all_reject() {
72 uint8_t type_filter_bitmap
[KDBG_TYPEFILTER_BITMAP_SIZE
];
73 memset(type_filter_bitmap
, 0, sizeof(type_filter_bitmap
));
74 _sysctl_enable_typefilter(type_filter_bitmap
);
77 static void enable_typefilter_all_pass() {
78 uint8_t type_filter_bitmap
[KDBG_TYPEFILTER_BITMAP_SIZE
];
79 memset(type_filter_bitmap
, 0xff, sizeof(type_filter_bitmap
));
80 _sysctl_enable_typefilter(type_filter_bitmap
);
83 static void loop_kdebug_trace(dt_stat_time_t s
) {
85 dt_stat_token start
= dt_stat_time_begin(s
);
86 for (uint32_t i
= 0; i
<100; i
++) {
87 kdebug_trace(0x97000000 | DBG_FUNC_NONE
, i
, i
, i
, i
);
88 kdebug_trace(0x97000000 | DBG_FUNC_NONE
, i
, i
, i
, i
);
89 kdebug_trace(0x97000000 | DBG_FUNC_NONE
, i
, i
, i
, i
);
90 kdebug_trace(0x97000000 | DBG_FUNC_NONE
, i
, i
, i
, i
);
91 kdebug_trace(0x97000000 | DBG_FUNC_NONE
, i
, i
, i
, i
);
92 kdebug_trace(0x97000000 | DBG_FUNC_NONE
, i
, i
, i
, i
);
93 kdebug_trace(0x97000000 | DBG_FUNC_NONE
, i
, i
, i
, i
);
94 kdebug_trace(0x97000000 | DBG_FUNC_NONE
, i
, i
, i
, i
);
95 kdebug_trace(0x97000000 | DBG_FUNC_NONE
, i
, i
, i
, i
);
96 kdebug_trace(0x97000000 | DBG_FUNC_NONE
, i
, i
, i
, i
);
98 dt_stat_time_end_batch(s
, 1000, start
);
99 } while (!dt_stat_stable(s
));
102 static void loop_getppid(dt_stat_time_t s
) {
104 dt_stat_token start
= dt_stat_time_begin(s
);
105 for (uint32_t i
= 0; i
<100; i
++) {
117 dt_stat_time_end_batch(s
, 1000, start
);
118 } while (!dt_stat_stable(s
));
121 static void reset_kdebug_trace(void) {
125 static void test(const char* test_name
, void (^pretest_setup
)(void), void (*test
)(dt_stat_time_t s
)) {
126 T_ATEND(reset_kdebug_trace
);
128 _sysctl_setbuf(1000000);
129 _sysctl_nowrap(false);
134 dt_stat_time_t s
= dt_stat_time_create("%s", test_name
);
145 T_DECL(kdebug_trace_baseline_syscall
,
146 "Test the latency of a syscall while kernel tracing is disabled") {
147 test("kdebug_trace_baseline_syscall", ^{ enable_tracing(false); }, loop_getppid
);
150 T_DECL(kdebug_trace_kdbg_disabled
,
151 "Test the latency of kdebug_trace while kernel tracing is disabled") {
152 test("kdebug_trace_kdbg_disabled", ^{ enable_tracing(false); }, loop_kdebug_trace
);
155 T_DECL(kdebug_trace_kdbg_enabled
,
156 "Test the latency of kdebug_trace while kernel tracing is enabled with no typefilter") {
157 test("kdebug_trace_kdbg_enabled", ^{ enable_tracing(true); }, loop_kdebug_trace
);
160 T_DECL(kdebug_trace_kdbg_enabled_typefilter_pass
,
161 "Test the latency of kdebug_trace while kernel tracing is enabled with a typefilter that passes the event") {
162 test("kdebug_trace_kdbg_enabled_typefilter_pass", ^{ enable_tracing(true); enable_typefilter_all_pass(); }, loop_kdebug_trace
);
165 T_DECL(kdebug_trace_kdbg_enabled_typefilter_reject
,
166 "Test the latency of kdebug_trace while kernel tracing is enabled with a typefilter that rejects the event") {
167 test("kdebug_trace_kdbg_enabled_typefilter_reject", ^{ enable_tracing(true); enable_typefilter_all_reject(); }, loop_kdebug_trace
);