]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kperf/kperfbsd.c
xnu-7195.60.75.tar.gz
[apple/xnu.git] / osfmk / kperf / kperfbsd.c
CommitLineData
316670eb
A
1/*
2 * Copyright (c) 2011 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
39037602 5 *
316670eb
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
39037602 14 *
316670eb
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
39037602 17 *
316670eb
A
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
39037602 25 *
316670eb
A
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
f427ee49 29/* sysctl interface for parameters from user-land */
316670eb 30
39037602
A
31#include <kern/debug.h>
32#include <libkern/libkern.h>
33#include <pexpert/pexpert.h>
316670eb
A
34#include <sys/param.h>
35#include <sys/mman.h>
36#include <sys/stat.h>
37#include <sys/sysctl.h>
39236c6e 38#include <sys/kauth.h>
316670eb 39
316670eb 40#include <kperf/action.h>
39037602
A
41#include <kperf/context.h>
42#include <kperf/kdebug_trigger.h>
316670eb 43#include <kperf/kperf.h>
39037602 44#include <kperf/kperfbsd.h>
f427ee49 45#include <kperf/kptimer.h>
39037602 46#include <kperf/pet.h>
d9a64523 47#include <kperf/lazy.h>
316670eb 48
39037602 49#include <sys/ktrace.h>
39236c6e 50
d9a64523
A
51/* Requests from kperf sysctls. */
52enum kperf_request {
53 REQ_SAMPLING,
54 REQ_RESET,
55
56 REQ_ACTION_COUNT,
57 REQ_ACTION_SAMPLERS,
58 REQ_ACTION_USERDATA,
59 REQ_ACTION_FILTER_BY_TASK,
60 REQ_ACTION_FILTER_BY_PID,
61 REQ_ACTION_UCALLSTACK_DEPTH,
62 REQ_ACTION_KCALLSTACK_DEPTH,
63
64 REQ_TIMER_COUNT,
65 REQ_TIMER_PERIOD,
66 REQ_TIMER_PET,
67 REQ_TIMER_ACTION,
68
69 REQ_KDBG_CSWITCH,
70
71 REQ_BLESS,
72 REQ_BLESS_PREEMPT,
73
74 REQ_PET_IDLE_RATE,
75 REQ_LIGHTWEIGHT_PET,
76
77 REQ_KDEBUG_FILTER,
78 REQ_KDEBUG_ACTION,
79
80 REQ_LAZY_WAIT_TIME_THRESHOLD,
81 REQ_LAZY_WAIT_ACTION,
82 REQ_LAZY_CPU_TIME_THRESHOLD,
83 REQ_LAZY_CPU_ACTION,
84};
39236c6e 85
39037602 86int kperf_debug_level = 0;
39236c6e 87
39037602
A
88#if DEVELOPMENT || DEBUG
89_Atomic long long kperf_pending_ipis = 0;
90#endif /* DEVELOPMENT || DEBUG */
fe8ab488 91
39037602 92/*
d9a64523 93 * kperf has unique requirements from sysctl.
39037602
A
94 *
95 * For simple queries like the number of actions, the normal sysctl style
96 * of get/set works well.
39236c6e 97 *
39037602
A
98 * However, when requesting information about something specific, like an
99 * action, user space needs to provide some contextual information. This
100 * information is stored in a uint64_t array that includes the context, like
101 * the action ID it is interested in. If user space is getting the value from
102 * the kernel, then the get side of the sysctl is valid. If it is setting the
103 * value, then the get pointers are left NULL.
39236c6e 104 *
39037602
A
105 * These functions handle marshalling and unmarshalling data from sysctls.
106 */
39236c6e 107
39037602
A
108static int
109kperf_sysctl_get_set_uint32(struct sysctl_req *req,
0a7de745 110 uint32_t (*get)(void), int (*set)(uint32_t))
39236c6e 111{
39037602
A
112 assert(req != NULL);
113 assert(get != NULL);
114 assert(set != NULL);
39236c6e 115
39037602
A
116 uint32_t value = 0;
117 if (req->oldptr) {
118 value = get();
119 }
316670eb 120
39037602
A
121 int error = sysctl_io_number(req, value, sizeof(value), &value, NULL);
122
123 if (error || !req->newptr) {
124 return error;
125 }
126
127 return set(value);
128}
316670eb
A
129
130static int
39037602 131kperf_sysctl_get_set_int(struct sysctl_req *req,
0a7de745 132 int (*get)(void), int (*set)(int))
316670eb 133{
39037602
A
134 assert(req != NULL);
135 assert(get != NULL);
136 assert(set != NULL);
316670eb 137
39037602
A
138 int value = 0;
139 if (req->oldptr) {
140 value = get();
141 }
316670eb 142
39037602 143 int error = sysctl_io_number(req, value, sizeof(value), &value, NULL);
39236c6e 144
39037602
A
145 if (error || !req->newptr) {
146 return error;
147 }
148
149 return set(value);
39236c6e
A
150}
151
d9a64523
A
152static int
153kperf_sysctl_get_set_uint64(struct sysctl_req *req,
0a7de745 154 uint64_t (*get)(void), int (*set)(uint64_t))
d9a64523
A
155{
156 assert(req != NULL);
157 assert(get != NULL);
158 assert(set != NULL);
159
160 uint64_t value = 0;
161 if (req->oldptr) {
162 value = get();
163 }
164
f427ee49 165 int error = sysctl_io_number(req, (long long)value, sizeof(value), &value, NULL);
d9a64523
A
166
167 if (error || !req->newptr) {
168 return error;
169 }
170
171 return set(value);
172}
173
39236c6e 174static int
39037602 175kperf_sysctl_get_set_unsigned_uint32(struct sysctl_req *req,
0a7de745 176 int (*get)(unsigned int, uint32_t *), int (*set)(unsigned int, uint32_t))
39236c6e 177{
39037602
A
178 assert(req != NULL);
179 assert(get != NULL);
180 assert(set != NULL);
181
5ba3f43e
A
182 int error = 0;
183 uint64_t inputs[2] = {};
184
185 if (req->newptr == USER_ADDR_NULL) {
186 return EFAULT;
187 }
188
189 if ((error = copyin(req->newptr, inputs, sizeof(inputs)))) {
39037602
A
190 return error;
191 }
192
193 unsigned int action_id = (unsigned int)inputs[0];
194 uint32_t new_value = (uint32_t)inputs[1];
316670eb 195
39037602
A
196 if (req->oldptr != USER_ADDR_NULL) {
197 uint32_t value_out = 0;
198 if ((error = get(action_id, &value_out))) {
199 return error;
200 }
39236c6e 201
39037602 202 inputs[1] = value_out;
39236c6e 203
5ba3f43e 204 return copyout(inputs, req->oldptr, sizeof(inputs));
39037602 205 } else {
5ba3f43e 206 return set(action_id, new_value);
39037602 207 }
316670eb
A
208}
209
39037602
A
210/*
211 * These functions are essentially the same as the generic
212 * kperf_sysctl_get_set_unsigned_uint32, except they have unique input sizes.
213 */
214
316670eb 215static int
39037602 216sysctl_timer_period(struct sysctl_req *req)
316670eb 217{
5ba3f43e
A
218 uint64_t inputs[2] = {};
219
5ba3f43e
A
220 if (req->newptr == USER_ADDR_NULL) {
221 return EFAULT;
222 }
223
f427ee49 224 int error = 0;
5ba3f43e 225 if ((error = copyin(req->newptr, inputs, sizeof(inputs)))) {
39037602
A
226 return error;
227 }
39037602
A
228 unsigned int timer = (unsigned int)inputs[0];
229 uint64_t new_period = inputs[1];
316670eb 230
39037602
A
231 if (req->oldptr != USER_ADDR_NULL) {
232 uint64_t period_out = 0;
f427ee49 233 if ((error = kptimer_get_period(timer, &period_out))) {
39037602
A
234 return error;
235 }
236
237 inputs[1] = period_out;
5ba3f43e 238 return copyout(inputs, req->oldptr, sizeof(inputs));
39037602 239 } else {
f427ee49 240 return kptimer_set_period(timer, new_period);
39037602 241 }
39236c6e
A
242}
243
244static int
5ba3f43e 245sysctl_action_filter(struct sysctl_req *req, bool is_task_t)
39236c6e 246{
5ba3f43e
A
247 int error = 0;
248 uint64_t inputs[2] = {};
249
39037602
A
250 assert(req != NULL);
251
5ba3f43e
A
252 if (req->newptr == USER_ADDR_NULL) {
253 return EFAULT;
254 }
255
256 if ((error = copyin(req->newptr, inputs, sizeof(inputs)))) {
39037602
A
257 return error;
258 }
259
260 unsigned int actionid = (unsigned int)inputs[0];
261 int new_filter = (int)inputs[1];
39236c6e 262
39037602
A
263 if (req->oldptr != USER_ADDR_NULL) {
264 int filter_out;
265 if ((error = kperf_action_get_filter(actionid, &filter_out))) {
266 return error;
267 }
268
f427ee49 269 inputs[1] = (uint64_t)filter_out;
5ba3f43e 270 return copyout(inputs, req->oldptr, sizeof(inputs));
39037602
A
271 } else {
272 int pid = is_task_t ? kperf_port_to_pid((mach_port_name_t)new_filter)
0a7de745 273 : new_filter;
39236c6e 274
5ba3f43e 275 return kperf_action_set_filter(actionid, pid);
39037602 276 }
39236c6e
A
277}
278
279static int
39037602 280sysctl_bless(struct sysctl_req *req)
39236c6e 281{
39037602
A
282 int value = ktrace_get_owning_pid();
283 int error = sysctl_io_number(req, value, sizeof(value), &value, NULL);
39236c6e 284
39037602
A
285 if (error || !req->newptr) {
286 return error;
287 }
39236c6e 288
39037602 289 return ktrace_set_owning_pid(value);
316670eb
A
290}
291
39037602
A
292/* sysctl handlers that use the generic functions */
293
316670eb 294static int
39037602 295sysctl_action_samplers(struct sysctl_req *req)
316670eb 296{
39037602 297 return kperf_sysctl_get_set_unsigned_uint32(req,
0a7de745 298 kperf_action_get_samplers, kperf_action_set_samplers);
316670eb
A
299}
300
301static int
39037602 302sysctl_action_userdata(struct sysctl_req *req)
316670eb 303{
39037602 304 return kperf_sysctl_get_set_unsigned_uint32(req,
0a7de745 305 kperf_action_get_userdata, kperf_action_set_userdata);
316670eb
A
306}
307
308static int
39037602 309sysctl_action_ucallstack_depth(struct sysctl_req *req)
316670eb 310{
39037602 311 return kperf_sysctl_get_set_unsigned_uint32(req,
0a7de745 312 kperf_action_get_ucallstack_depth, kperf_action_set_ucallstack_depth);
316670eb
A
313}
314
315static int
39037602 316sysctl_action_kcallstack_depth(struct sysctl_req *req)
316670eb 317{
39037602 318 return kperf_sysctl_get_set_unsigned_uint32(req,
0a7de745 319 kperf_action_get_kcallstack_depth, kperf_action_set_kcallstack_depth);
316670eb
A
320}
321
39236c6e 322static int
39037602 323sysctl_kdebug_action(struct sysctl_req *req)
39236c6e 324{
39037602 325 return kperf_sysctl_get_set_int(req, kperf_kdebug_get_action,
0a7de745 326 kperf_kdebug_set_action);
39236c6e
A
327}
328
329static int
39037602 330sysctl_kdebug_filter(struct sysctl_req *req)
39236c6e 331{
39037602 332 assert(req != NULL);
39236c6e 333
39037602
A
334 if (req->oldptr != USER_ADDR_NULL) {
335 struct kperf_kdebug_filter *filter = NULL;
336 uint32_t n_debugids = kperf_kdebug_get_filter(&filter);
337 size_t filter_size = KPERF_KDEBUG_FILTER_SIZE(n_debugids);
39236c6e 338
39037602
A
339 if (n_debugids == 0) {
340 return EINVAL;
341 }
39236c6e 342
39037602 343 return SYSCTL_OUT(req, filter, filter_size);
d9a64523
A
344 } else if (req->newptr != USER_ADDR_NULL) {
345 return kperf_kdebug_set_filter(req->newptr, (uint32_t)req->newlen);
346 } else {
347 return EINVAL;
39037602 348 }
39236c6e
A
349}
350
f427ee49
A
351static uint32_t
352kperf_sampling_get(void)
353{
354 return kperf_is_sampling();
355}
356
39236c6e 357static int
39037602 358kperf_sampling_set(uint32_t sample_start)
39236c6e 359{
39037602 360 if (sample_start) {
f427ee49 361 return kperf_enable_sampling();
39037602 362 } else {
f427ee49 363 return kperf_disable_sampling();
39037602 364 }
39236c6e
A
365}
366
367static int
39037602 368sysctl_sampling(struct sysctl_req *req)
39236c6e 369{
f427ee49 370 return kperf_sysctl_get_set_uint32(req, kperf_sampling_get,
0a7de745 371 kperf_sampling_set);
39037602 372}
39236c6e 373
39037602
A
374static int
375sysctl_action_count(struct sysctl_req *req)
376{
377 return kperf_sysctl_get_set_uint32(req, kperf_action_get_count,
0a7de745 378 kperf_action_set_count);
39037602 379}
39236c6e 380
39037602
A
381static int
382sysctl_timer_count(struct sysctl_req *req)
383{
f427ee49
A
384 return kperf_sysctl_get_set_uint32(req, kptimer_get_count,
385 kptimer_set_count);
39236c6e
A
386}
387
3e170ce0 388static int
39037602 389sysctl_timer_action(struct sysctl_req *req)
3e170ce0 390{
f427ee49
A
391 return kperf_sysctl_get_set_unsigned_uint32(req, kptimer_get_action,
392 kptimer_set_action);
39037602 393}
3e170ce0 394
39037602
A
395static int
396sysctl_timer_pet(struct sysctl_req *req)
397{
f427ee49
A
398 return kperf_sysctl_get_set_uint32(req, kptimer_get_pet_timerid,
399 kptimer_set_pet_timerid);
39037602 400}
3e170ce0 401
39037602
A
402static int
403sysctl_bless_preempt(struct sysctl_req *req)
404{
405 return sysctl_io_number(req, ktrace_root_set_owner_allowed,
0a7de745
A
406 sizeof(ktrace_root_set_owner_allowed),
407 &ktrace_root_set_owner_allowed, NULL);
3e170ce0
A
408}
409
410static int
39037602 411sysctl_kperf_reset(struct sysctl_req *req)
3e170ce0 412{
39037602 413 int should_reset = 0;
3e170ce0 414
39037602 415 int error = sysctl_io_number(req, should_reset, sizeof(should_reset),
0a7de745 416 &should_reset, NULL);
39037602
A
417 if (error) {
418 return error;
419 }
3e170ce0 420
39037602
A
421 if (should_reset) {
422 ktrace_reset(KTRACE_KPERF);
423 }
424 return 0;
3e170ce0
A
425}
426
427static int
39037602 428sysctl_pet_idle_rate(struct sysctl_req *req)
3e170ce0 429{
f427ee49
A
430 return kperf_sysctl_get_set_int(req, kppet_get_idle_rate,
431 kppet_set_idle_rate);
39037602 432}
3e170ce0 433
39037602
A
434static int
435sysctl_lightweight_pet(struct sysctl_req *req)
436{
f427ee49
A
437 return kperf_sysctl_get_set_int(req, kppet_get_lightweight_pet,
438 kppet_set_lightweight_pet);
39037602 439}
3e170ce0 440
39037602
A
441static int
442sysctl_kdbg_cswitch(struct sysctl_req *req)
443{
444 return kperf_sysctl_get_set_int(req, kperf_kdbg_cswitch_get,
0a7de745 445 kperf_kdbg_cswitch_set);
3e170ce0
A
446}
447
d9a64523
A
448static int
449sysctl_lazy_wait_time_threshold(struct sysctl_req *req)
450{
451 return kperf_sysctl_get_set_uint64(req, kperf_lazy_get_wait_time_threshold,
0a7de745 452 kperf_lazy_set_wait_time_threshold);
d9a64523
A
453}
454
455static int
456sysctl_lazy_wait_action(struct sysctl_req *req)
457{
458 return kperf_sysctl_get_set_int(req, kperf_lazy_get_wait_action,
0a7de745 459 kperf_lazy_set_wait_action);
d9a64523
A
460}
461
462static int
463sysctl_lazy_cpu_time_threshold(struct sysctl_req *req)
464{
465 return kperf_sysctl_get_set_uint64(req, kperf_lazy_get_cpu_time_threshold,
0a7de745 466 kperf_lazy_set_cpu_time_threshold);
d9a64523
A
467}
468
469static int
470sysctl_lazy_cpu_action(struct sysctl_req *req)
471{
472 return kperf_sysctl_get_set_int(req, kperf_lazy_get_cpu_action,
0a7de745 473 kperf_lazy_set_cpu_action);
d9a64523
A
474}
475
316670eb
A
476static int
477kperf_sysctl SYSCTL_HANDLER_ARGS
478{
39037602 479#pragma unused(oidp, arg2)
39236c6e 480 int ret;
d9a64523 481 enum kperf_request type = (enum kperf_request)arg1;
39236c6e 482
5ba3f43e 483 ktrace_lock();
39236c6e 484
39037602
A
485 if (req->oldptr == USER_ADDR_NULL && req->newptr != USER_ADDR_NULL) {
486 if ((ret = ktrace_configure(KTRACE_KPERF))) {
5ba3f43e 487 ktrace_unlock();
39037602
A
488 return ret;
489 }
490 } else {
491 if ((ret = ktrace_read_check())) {
5ba3f43e 492 ktrace_unlock();
39037602
A
493 return ret;
494 }
39236c6e
A
495 }
496
316670eb 497 /* which request */
39037602 498 switch (type) {
316670eb 499 case REQ_ACTION_COUNT:
39037602 500 ret = sysctl_action_count(req);
39236c6e 501 break;
316670eb 502 case REQ_ACTION_SAMPLERS:
39037602 503 ret = sysctl_action_samplers(req);
39236c6e
A
504 break;
505 case REQ_ACTION_USERDATA:
39037602 506 ret = sysctl_action_userdata(req);
39236c6e 507 break;
316670eb 508 case REQ_TIMER_COUNT:
39037602 509 ret = sysctl_timer_count(req);
39236c6e 510 break;
316670eb 511 case REQ_TIMER_PERIOD:
39037602 512 ret = sysctl_timer_period(req);
39236c6e 513 break;
316670eb 514 case REQ_TIMER_PET:
39037602 515 ret = sysctl_timer_pet(req);
39236c6e
A
516 break;
517 case REQ_TIMER_ACTION:
39037602 518 ret = sysctl_timer_action(req);
39236c6e 519 break;
316670eb 520 case REQ_SAMPLING:
39037602 521 ret = sysctl_sampling(req);
39236c6e 522 break;
3e170ce0 523 case REQ_KDBG_CSWITCH:
39037602 524 ret = sysctl_kdbg_cswitch(req);
3e170ce0 525 break;
39236c6e 526 case REQ_ACTION_FILTER_BY_TASK:
5ba3f43e 527 ret = sysctl_action_filter(req, true);
39236c6e
A
528 break;
529 case REQ_ACTION_FILTER_BY_PID:
5ba3f43e 530 ret = sysctl_action_filter(req, false);
39037602
A
531 break;
532 case REQ_KDEBUG_ACTION:
533 ret = sysctl_kdebug_action(req);
534 break;
535 case REQ_KDEBUG_FILTER:
536 ret = sysctl_kdebug_filter(req);
39236c6e
A
537 break;
538 case REQ_PET_IDLE_RATE:
39037602 539 ret = sysctl_pet_idle_rate(req);
39236c6e
A
540 break;
541 case REQ_BLESS_PREEMPT:
39037602
A
542 ret = sysctl_bless_preempt(req);
543 break;
544 case REQ_RESET:
545 ret = sysctl_kperf_reset(req);
39236c6e 546 break;
39037602
A
547 case REQ_ACTION_UCALLSTACK_DEPTH:
548 ret = sysctl_action_ucallstack_depth(req);
3e170ce0 549 break;
39037602
A
550 case REQ_ACTION_KCALLSTACK_DEPTH:
551 ret = sysctl_action_kcallstack_depth(req);
3e170ce0 552 break;
39037602
A
553 case REQ_LIGHTWEIGHT_PET:
554 ret = sysctl_lightweight_pet(req);
0a7de745 555 break;
d9a64523
A
556 case REQ_LAZY_WAIT_TIME_THRESHOLD:
557 ret = sysctl_lazy_wait_time_threshold(req);
0a7de745 558 break;
d9a64523
A
559 case REQ_LAZY_WAIT_ACTION:
560 ret = sysctl_lazy_wait_action(req);
0a7de745 561 break;
d9a64523
A
562 case REQ_LAZY_CPU_TIME_THRESHOLD:
563 ret = sysctl_lazy_cpu_time_threshold(req);
0a7de745 564 break;
d9a64523
A
565 case REQ_LAZY_CPU_ACTION:
566 ret = sysctl_lazy_cpu_action(req);
0a7de745 567 break;
316670eb 568 default:
39236c6e
A
569 ret = ENOENT;
570 break;
571 }
572
5ba3f43e 573 ktrace_unlock();
39236c6e
A
574
575 return ret;
576}
577
578static int
579kperf_sysctl_bless_handler SYSCTL_HANDLER_ARGS
580{
39037602 581#pragma unused(oidp, arg2)
39236c6e 582 int ret;
39236c6e 583
5ba3f43e 584 ktrace_lock();
39037602
A
585
586 /* if setting a new "blessed pid" (ktrace owning pid) */
587 if (req->newptr != USER_ADDR_NULL) {
588 /*
589 * root can bypass the ktrace check when a flag is set (for
590 * backwards compatibility) or when ownership is maintained over
591 * subsystems resets (to allow the user space process that set
592 * ownership to unset it).
593 */
594 if (!((ktrace_root_set_owner_allowed ||
0a7de745
A
595 ktrace_keep_ownership_on_reset) &&
596 kauth_cred_issuser(kauth_cred_get()))) {
39037602 597 if ((ret = ktrace_configure(KTRACE_KPERF))) {
5ba3f43e 598 ktrace_unlock();
39037602
A
599 return ret;
600 }
601 }
602 } else {
603 if ((ret = ktrace_read_check())) {
5ba3f43e 604 ktrace_unlock();
39236c6e 605 return ret;
39236c6e
A
606 }
607 }
608
39037602
A
609 /* which request */
610 if ((uintptr_t)arg1 == REQ_BLESS) {
611 ret = sysctl_bless(req);
612 } else {
613 ret = ENOENT;
316670eb 614 }
39236c6e 615
5ba3f43e 616 ktrace_unlock();
fe8ab488 617
39037602 618 return ret;
316670eb
A
619}
620
621/* root kperf node */
39037602
A
622
623SYSCTL_NODE(, OID_AUTO, kperf, CTLFLAG_RW | CTLFLAG_LOCKED, 0,
0a7de745 624 "kperf");
316670eb 625
39037602
A
626/* actions */
627
628SYSCTL_NODE(_kperf, OID_AUTO, action, CTLFLAG_RW | CTLFLAG_LOCKED, 0,
0a7de745 629 "action");
316670eb
A
630
631SYSCTL_PROC(_kperf_action, OID_AUTO, count,
0a7de745
A
632 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_LOCKED |
633 CTLFLAG_MASKED,
634 (void *)REQ_ACTION_COUNT,
635 sizeof(int), kperf_sysctl, "I", "Number of actions");
316670eb
A
636
637SYSCTL_PROC(_kperf_action, OID_AUTO, samplers,
0a7de745
A
638 CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MASKED | CTLFLAG_LOCKED,
639 (void *)REQ_ACTION_SAMPLERS,
640 3 * sizeof(uint64_t), kperf_sysctl, "UQ",
641 "What to sample when a trigger fires an action");
316670eb 642
39236c6e 643SYSCTL_PROC(_kperf_action, OID_AUTO, userdata,
0a7de745
A
644 CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MASKED | CTLFLAG_LOCKED,
645 (void *)REQ_ACTION_USERDATA,
646 3 * sizeof(uint64_t), kperf_sysctl, "UQ",
647 "User data to attribute to action");
39236c6e
A
648
649SYSCTL_PROC(_kperf_action, OID_AUTO, filter_by_task,
0a7de745
A
650 CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MASKED | CTLFLAG_LOCKED,
651 (void *)REQ_ACTION_FILTER_BY_TASK,
652 3 * sizeof(uint64_t), kperf_sysctl, "UQ",
653 "Apply a task filter to the action");
39236c6e
A
654
655SYSCTL_PROC(_kperf_action, OID_AUTO, filter_by_pid,
0a7de745
A
656 CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MASKED | CTLFLAG_LOCKED,
657 (void *)REQ_ACTION_FILTER_BY_PID,
658 3 * sizeof(uint64_t), kperf_sysctl, "UQ",
659 "Apply a pid filter to the action");
39236c6e 660
39037602 661SYSCTL_PROC(_kperf_action, OID_AUTO, ucallstack_depth,
0a7de745
A
662 CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MASKED | CTLFLAG_LOCKED,
663 (void *)REQ_ACTION_UCALLSTACK_DEPTH,
664 sizeof(int), kperf_sysctl, "I",
665 "Maximum number of frames to include in user callstacks");
39037602
A
666
667SYSCTL_PROC(_kperf_action, OID_AUTO, kcallstack_depth,
0a7de745
A
668 CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MASKED | CTLFLAG_LOCKED,
669 (void *)REQ_ACTION_KCALLSTACK_DEPTH,
670 sizeof(int), kperf_sysctl, "I",
671 "Maximum number of frames to include in kernel callstacks");
39037602
A
672
673/* timers */
674
675SYSCTL_NODE(_kperf, OID_AUTO, timer, CTLFLAG_RW | CTLFLAG_LOCKED, 0,
0a7de745 676 "timer");
316670eb
A
677
678SYSCTL_PROC(_kperf_timer, OID_AUTO, count,
0a7de745
A
679 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_LOCKED
680 | CTLFLAG_MASKED,
681 (void *)REQ_TIMER_COUNT,
682 sizeof(int), kperf_sysctl, "I", "Number of time triggers");
316670eb
A
683
684SYSCTL_PROC(_kperf_timer, OID_AUTO, period,
0a7de745
A
685 CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MASKED | CTLFLAG_LOCKED,
686 (void *)REQ_TIMER_PERIOD,
687 2 * sizeof(uint64_t), kperf_sysctl, "UQ",
688 "Timer number and period");
316670eb 689
39236c6e 690SYSCTL_PROC(_kperf_timer, OID_AUTO, action,
0a7de745
A
691 CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MASKED | CTLFLAG_LOCKED,
692 (void *)REQ_TIMER_ACTION,
693 2 * sizeof(uint64_t), kperf_sysctl, "UQ",
694 "Timer number and actionid");
39236c6e 695
316670eb 696SYSCTL_PROC(_kperf_timer, OID_AUTO, pet_timer,
0a7de745
A
697 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_LOCKED
698 | CTLFLAG_MASKED,
699 (void *)REQ_TIMER_PET,
700 sizeof(int), kperf_sysctl, "I", "Which timer ID does PET");
316670eb 701
39037602
A
702/* kdebug trigger */
703
704SYSCTL_NODE(_kperf, OID_AUTO, kdebug, CTLFLAG_RW | CTLFLAG_LOCKED, 0,
0a7de745 705 "kdebug");
39037602
A
706
707SYSCTL_PROC(_kperf_kdebug, OID_AUTO, action,
0a7de745
A
708 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_LOCKED
709 | CTLFLAG_MASKED,
710 (void*)REQ_KDEBUG_ACTION,
711 sizeof(int), kperf_sysctl, "I", "ID of action to trigger on kdebug events");
39037602
A
712
713SYSCTL_PROC(_kperf_kdebug, OID_AUTO, filter,
0a7de745
A
714 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MASKED | CTLFLAG_LOCKED,
715 (void*)REQ_KDEBUG_FILTER,
716 sizeof(int), kperf_sysctl, "P", "The filter that determines which kdebug events trigger a sample");
39037602 717
d9a64523
A
718/* lazy sampling */
719
720SYSCTL_NODE(_kperf, OID_AUTO, lazy, CTLFLAG_RW | CTLFLAG_LOCKED, 0,
0a7de745 721 "lazy");
d9a64523
A
722
723SYSCTL_PROC(_kperf_lazy, OID_AUTO, wait_time_threshold,
0a7de745
A
724 CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MASKED | CTLFLAG_LOCKED,
725 (void *)REQ_LAZY_WAIT_TIME_THRESHOLD,
726 sizeof(uint64_t), kperf_sysctl, "UQ",
727 "How many ticks a thread must wait to take a sample");
d9a64523
A
728
729SYSCTL_PROC(_kperf_lazy, OID_AUTO, wait_action,
0a7de745
A
730 CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MASKED | CTLFLAG_LOCKED,
731 (void *)REQ_LAZY_WAIT_ACTION,
732 sizeof(uint64_t), kperf_sysctl, "UQ",
733 "Which action to fire when a thread waits longer than threshold");
d9a64523
A
734
735SYSCTL_PROC(_kperf_lazy, OID_AUTO, cpu_time_threshold,
0a7de745
A
736 CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MASKED | CTLFLAG_LOCKED,
737 (void *)REQ_LAZY_CPU_TIME_THRESHOLD,
738 sizeof(uint64_t), kperf_sysctl, "UQ",
739 "Minimum number of ticks a CPU must run between samples");
d9a64523
A
740
741SYSCTL_PROC(_kperf_lazy, OID_AUTO, cpu_action,
0a7de745
A
742 CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MASKED | CTLFLAG_LOCKED,
743 (void *)REQ_LAZY_CPU_ACTION,
744 sizeof(uint64_t), kperf_sysctl, "UQ",
745 "Which action to fire for lazy CPU samples");
d9a64523 746
316670eb 747/* misc */
39037602 748
316670eb 749SYSCTL_PROC(_kperf, OID_AUTO, sampling,
0a7de745
A
750 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_LOCKED
751 | CTLFLAG_MASKED,
752 (void *)REQ_SAMPLING,
753 sizeof(int), kperf_sysctl, "I", "Sampling running");
316670eb 754
39037602 755SYSCTL_PROC(_kperf, OID_AUTO, reset,
0a7de745
A
756 CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MASKED | CTLFLAG_LOCKED,
757 (void *)REQ_RESET,
758 0, kperf_sysctl, "-", "Reset kperf");
39037602 759
39236c6e 760SYSCTL_PROC(_kperf, OID_AUTO, blessed_pid,
0a7de745
A
761 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED /* must be root */
762 | CTLFLAG_MASKED,
763 (void *)REQ_BLESS,
764 sizeof(int), kperf_sysctl_bless_handler, "I", "Blessed pid");
39236c6e
A
765
766SYSCTL_PROC(_kperf, OID_AUTO, blessed_preempt,
0a7de745
A
767 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_LOCKED |
768 CTLFLAG_MASKED,
769 (void *)REQ_BLESS_PREEMPT,
770 sizeof(int), kperf_sysctl, "I", "Blessed preemption");
39236c6e 771
3e170ce0 772SYSCTL_PROC(_kperf, OID_AUTO, kdbg_cswitch,
0a7de745
A
773 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_LOCKED
774 | CTLFLAG_MASKED,
775 (void *)REQ_KDBG_CSWITCH,
776 sizeof(int), kperf_sysctl, "I", "Generate context switch info");
39236c6e
A
777
778SYSCTL_PROC(_kperf, OID_AUTO, pet_idle_rate,
0a7de745
A
779 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_LOCKED
780 | CTLFLAG_MASKED,
781 (void *)REQ_PET_IDLE_RATE,
782 sizeof(int), kperf_sysctl, "I",
783 "Rate at which unscheduled threads are forced to be sampled in "
784 "PET mode");
39037602
A
785
786SYSCTL_PROC(_kperf, OID_AUTO, lightweight_pet,
0a7de745
A
787 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_LOCKED
788 | CTLFLAG_MASKED,
789 (void *)REQ_LIGHTWEIGHT_PET,
790 sizeof(int), kperf_sysctl, "I",
791 "Status of lightweight PET mode");
3e170ce0 792
5ba3f43e
A
793/* limits */
794
795SYSCTL_NODE(_kperf, OID_AUTO, limits, CTLFLAG_RW | CTLFLAG_LOCKED, 0,
0a7de745 796 "limits");
5ba3f43e 797
d9a64523
A
798enum kperf_limit_request {
799 REQ_LIM_PERIOD_NS,
800 REQ_LIM_BG_PERIOD_NS,
801 REQ_LIM_PET_PERIOD_NS,
802 REQ_LIM_BG_PET_PERIOD_NS,
803};
5ba3f43e
A
804
805static int
806kperf_sysctl_limits SYSCTL_HANDLER_ARGS
807{
808#pragma unused(oidp, arg2)
f427ee49
A
809 enum kptimer_period_limit limit = (enum kptimer_period_limit)arg1;
810 if (limit >= KTPL_MAX) {
5ba3f43e
A
811 return ENOENT;
812 }
f427ee49
A
813 uint64_t period = kptimer_minperiods_ns[limit];
814 return sysctl_io_number(req, (long long)period, sizeof(period), &period,
815 NULL);
5ba3f43e
A
816}
817
818SYSCTL_PROC(_kperf_limits, OID_AUTO, timer_min_period_ns,
0a7de745
A
819 CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_ANYBODY | CTLFLAG_LOCKED,
820 (void *)REQ_LIM_PERIOD_NS, sizeof(uint64_t), kperf_sysctl_limits,
821 "Q", "Minimum timer period in nanoseconds");
5ba3f43e 822SYSCTL_PROC(_kperf_limits, OID_AUTO, timer_min_bg_period_ns,
0a7de745
A
823 CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_ANYBODY | CTLFLAG_LOCKED,
824 (void *)REQ_LIM_BG_PERIOD_NS, sizeof(uint64_t), kperf_sysctl_limits,
825 "Q", "Minimum background timer period in nanoseconds");
5ba3f43e 826SYSCTL_PROC(_kperf_limits, OID_AUTO, timer_min_pet_period_ns,
0a7de745
A
827 CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_ANYBODY | CTLFLAG_LOCKED,
828 (void *)REQ_LIM_PET_PERIOD_NS, sizeof(uint64_t), kperf_sysctl_limits,
829 "Q", "Minimum PET timer period in nanoseconds");
5ba3f43e 830SYSCTL_PROC(_kperf_limits, OID_AUTO, timer_min_bg_pet_period_ns,
0a7de745
A
831 CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_ANYBODY | CTLFLAG_LOCKED,
832 (void *)REQ_LIM_BG_PET_PERIOD_NS, sizeof(uint64_t), kperf_sysctl_limits,
833 "Q", "Minimum background PET timer period in nanoseconds");
5ba3f43e 834
39236c6e 835/* debug */
39037602 836SYSCTL_INT(_kperf, OID_AUTO, debug_level, CTLFLAG_RW | CTLFLAG_LOCKED,
0a7de745 837 &kperf_debug_level, 0, "debug level");
39236c6e 838
39037602
A
839#if DEVELOPMENT || DEBUG
840SYSCTL_QUAD(_kperf, OID_AUTO, already_pending_ipis,
0a7de745
A
841 CTLFLAG_RD | CTLFLAG_LOCKED,
842 &kperf_pending_ipis, "");
39037602 843#endif /* DEVELOPMENT || DEBUG */