]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kperf/kperfbsd.c
xnu-6153.41.3.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
29/* sysctl interface for paramters from user-land */
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
A
44#include <kperf/kperfbsd.h>
45#include <kperf/kperf_timer.h>
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
165 int error = sysctl_io_number(req, value, sizeof(value), &value, NULL);
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 int error;
219 uint64_t inputs[2] = {};
220
39037602 221 assert(req != NULL);
316670eb 222
5ba3f43e
A
223 if (req->newptr == USER_ADDR_NULL) {
224 return EFAULT;
225 }
226
227 if ((error = copyin(req->newptr, inputs, sizeof(inputs)))) {
39037602
A
228 return error;
229 }
230
231 unsigned int timer = (unsigned int)inputs[0];
232 uint64_t new_period = inputs[1];
316670eb 233
39037602
A
234 if (req->oldptr != USER_ADDR_NULL) {
235 uint64_t period_out = 0;
236 if ((error = kperf_timer_get_period(timer, &period_out))) {
237 return error;
238 }
239
240 inputs[1] = period_out;
5ba3f43e
A
241
242 return copyout(inputs, req->oldptr, sizeof(inputs));
39037602 243 } else {
5ba3f43e 244 return kperf_timer_set_period(timer, new_period);
39037602 245 }
39236c6e
A
246}
247
248static int
5ba3f43e 249sysctl_action_filter(struct sysctl_req *req, bool is_task_t)
39236c6e 250{
5ba3f43e
A
251 int error = 0;
252 uint64_t inputs[2] = {};
253
39037602
A
254 assert(req != NULL);
255
5ba3f43e
A
256 if (req->newptr == USER_ADDR_NULL) {
257 return EFAULT;
258 }
259
260 if ((error = copyin(req->newptr, inputs, sizeof(inputs)))) {
39037602
A
261 return error;
262 }
263
264 unsigned int actionid = (unsigned int)inputs[0];
265 int new_filter = (int)inputs[1];
39236c6e 266
39037602
A
267 if (req->oldptr != USER_ADDR_NULL) {
268 int filter_out;
269 if ((error = kperf_action_get_filter(actionid, &filter_out))) {
270 return error;
271 }
272
273 inputs[1] = filter_out;
5ba3f43e 274 return copyout(inputs, req->oldptr, sizeof(inputs));
39037602
A
275 } else {
276 int pid = is_task_t ? kperf_port_to_pid((mach_port_name_t)new_filter)
0a7de745 277 : new_filter;
39236c6e 278
5ba3f43e 279 return kperf_action_set_filter(actionid, pid);
39037602 280 }
39236c6e
A
281}
282
283static int
39037602 284sysctl_bless(struct sysctl_req *req)
39236c6e 285{
39037602
A
286 int value = ktrace_get_owning_pid();
287 int error = sysctl_io_number(req, value, sizeof(value), &value, NULL);
39236c6e 288
39037602
A
289 if (error || !req->newptr) {
290 return error;
291 }
39236c6e 292
39037602 293 return ktrace_set_owning_pid(value);
316670eb
A
294}
295
39037602
A
296/* sysctl handlers that use the generic functions */
297
316670eb 298static int
39037602 299sysctl_action_samplers(struct sysctl_req *req)
316670eb 300{
39037602 301 return kperf_sysctl_get_set_unsigned_uint32(req,
0a7de745 302 kperf_action_get_samplers, kperf_action_set_samplers);
316670eb
A
303}
304
305static int
39037602 306sysctl_action_userdata(struct sysctl_req *req)
316670eb 307{
39037602 308 return kperf_sysctl_get_set_unsigned_uint32(req,
0a7de745 309 kperf_action_get_userdata, kperf_action_set_userdata);
316670eb
A
310}
311
312static int
39037602 313sysctl_action_ucallstack_depth(struct sysctl_req *req)
316670eb 314{
39037602 315 return kperf_sysctl_get_set_unsigned_uint32(req,
0a7de745 316 kperf_action_get_ucallstack_depth, kperf_action_set_ucallstack_depth);
316670eb
A
317}
318
319static int
39037602 320sysctl_action_kcallstack_depth(struct sysctl_req *req)
316670eb 321{
39037602 322 return kperf_sysctl_get_set_unsigned_uint32(req,
0a7de745 323 kperf_action_get_kcallstack_depth, kperf_action_set_kcallstack_depth);
316670eb
A
324}
325
39236c6e 326static int
39037602 327sysctl_kdebug_action(struct sysctl_req *req)
39236c6e 328{
39037602 329 return kperf_sysctl_get_set_int(req, kperf_kdebug_get_action,
0a7de745 330 kperf_kdebug_set_action);
39236c6e
A
331}
332
333static int
39037602 334sysctl_kdebug_filter(struct sysctl_req *req)
39236c6e 335{
39037602 336 assert(req != NULL);
39236c6e 337
39037602
A
338 if (req->oldptr != USER_ADDR_NULL) {
339 struct kperf_kdebug_filter *filter = NULL;
340 uint32_t n_debugids = kperf_kdebug_get_filter(&filter);
341 size_t filter_size = KPERF_KDEBUG_FILTER_SIZE(n_debugids);
39236c6e 342
39037602
A
343 if (n_debugids == 0) {
344 return EINVAL;
345 }
39236c6e 346
39037602 347 return SYSCTL_OUT(req, filter, filter_size);
d9a64523
A
348 } else if (req->newptr != USER_ADDR_NULL) {
349 return kperf_kdebug_set_filter(req->newptr, (uint32_t)req->newlen);
350 } else {
351 return EINVAL;
39037602 352 }
39236c6e
A
353}
354
39236c6e 355static int
39037602 356kperf_sampling_set(uint32_t sample_start)
39236c6e 357{
39037602
A
358 if (sample_start) {
359 return kperf_sampling_enable();
360 } else {
361 return kperf_sampling_disable();
362 }
39236c6e
A
363}
364
365static int
39037602 366sysctl_sampling(struct sysctl_req *req)
39236c6e 367{
39037602 368 return kperf_sysctl_get_set_uint32(req, kperf_sampling_status,
0a7de745 369 kperf_sampling_set);
39037602 370}
39236c6e 371
39037602
A
372static int
373sysctl_action_count(struct sysctl_req *req)
374{
375 return kperf_sysctl_get_set_uint32(req, kperf_action_get_count,
0a7de745 376 kperf_action_set_count);
39037602 377}
39236c6e 378
39037602
A
379static int
380sysctl_timer_count(struct sysctl_req *req)
381{
382 return kperf_sysctl_get_set_uint32(req, kperf_timer_get_count,
0a7de745 383 kperf_timer_set_count);
39236c6e
A
384}
385
3e170ce0 386static int
39037602 387sysctl_timer_action(struct sysctl_req *req)
3e170ce0 388{
39037602 389 return kperf_sysctl_get_set_unsigned_uint32(req, kperf_timer_get_action,
0a7de745 390 kperf_timer_set_action);
39037602 391}
3e170ce0 392
39037602
A
393static int
394sysctl_timer_pet(struct sysctl_req *req)
395{
396 return kperf_sysctl_get_set_uint32(req, kperf_timer_get_petid,
0a7de745 397 kperf_timer_set_petid);
39037602 398}
3e170ce0 399
39037602
A
400static int
401sysctl_bless_preempt(struct sysctl_req *req)
402{
403 return sysctl_io_number(req, ktrace_root_set_owner_allowed,
0a7de745
A
404 sizeof(ktrace_root_set_owner_allowed),
405 &ktrace_root_set_owner_allowed, NULL);
3e170ce0
A
406}
407
408static int
39037602 409sysctl_kperf_reset(struct sysctl_req *req)
3e170ce0 410{
39037602 411 int should_reset = 0;
3e170ce0 412
39037602 413 int error = sysctl_io_number(req, should_reset, sizeof(should_reset),
0a7de745 414 &should_reset, NULL);
39037602
A
415 if (error) {
416 return error;
417 }
3e170ce0 418
39037602
A
419 if (should_reset) {
420 ktrace_reset(KTRACE_KPERF);
421 }
422 return 0;
3e170ce0
A
423}
424
425static int
39037602 426sysctl_pet_idle_rate(struct sysctl_req *req)
3e170ce0 427{
39037602 428 return kperf_sysctl_get_set_int(req, kperf_get_pet_idle_rate,
0a7de745 429 kperf_set_pet_idle_rate);
39037602 430}
3e170ce0 431
39037602
A
432static int
433sysctl_lightweight_pet(struct sysctl_req *req)
434{
435 return kperf_sysctl_get_set_int(req, kperf_get_lightweight_pet,
0a7de745 436 kperf_set_lightweight_pet);
39037602 437}
3e170ce0 438
39037602
A
439static int
440sysctl_kdbg_cswitch(struct sysctl_req *req)
441{
442 return kperf_sysctl_get_set_int(req, kperf_kdbg_cswitch_get,
0a7de745 443 kperf_kdbg_cswitch_set);
3e170ce0
A
444}
445
d9a64523
A
446static int
447sysctl_lazy_wait_time_threshold(struct sysctl_req *req)
448{
449 return kperf_sysctl_get_set_uint64(req, kperf_lazy_get_wait_time_threshold,
0a7de745 450 kperf_lazy_set_wait_time_threshold);
d9a64523
A
451}
452
453static int
454sysctl_lazy_wait_action(struct sysctl_req *req)
455{
456 return kperf_sysctl_get_set_int(req, kperf_lazy_get_wait_action,
0a7de745 457 kperf_lazy_set_wait_action);
d9a64523
A
458}
459
460static int
461sysctl_lazy_cpu_time_threshold(struct sysctl_req *req)
462{
463 return kperf_sysctl_get_set_uint64(req, kperf_lazy_get_cpu_time_threshold,
0a7de745 464 kperf_lazy_set_cpu_time_threshold);
d9a64523
A
465}
466
467static int
468sysctl_lazy_cpu_action(struct sysctl_req *req)
469{
470 return kperf_sysctl_get_set_int(req, kperf_lazy_get_cpu_action,
0a7de745 471 kperf_lazy_set_cpu_action);
d9a64523
A
472}
473
316670eb
A
474static int
475kperf_sysctl SYSCTL_HANDLER_ARGS
476{
39037602 477#pragma unused(oidp, arg2)
39236c6e 478 int ret;
d9a64523 479 enum kperf_request type = (enum kperf_request)arg1;
39236c6e 480
5ba3f43e 481 ktrace_lock();
39236c6e 482
39037602
A
483 if (req->oldptr == USER_ADDR_NULL && req->newptr != USER_ADDR_NULL) {
484 if ((ret = ktrace_configure(KTRACE_KPERF))) {
5ba3f43e 485 ktrace_unlock();
39037602
A
486 return ret;
487 }
488 } else {
489 if ((ret = ktrace_read_check())) {
5ba3f43e 490 ktrace_unlock();
39037602
A
491 return ret;
492 }
39236c6e
A
493 }
494
316670eb 495 /* which request */
39037602 496 switch (type) {
316670eb 497 case REQ_ACTION_COUNT:
39037602 498 ret = sysctl_action_count(req);
39236c6e 499 break;
316670eb 500 case REQ_ACTION_SAMPLERS:
39037602 501 ret = sysctl_action_samplers(req);
39236c6e
A
502 break;
503 case REQ_ACTION_USERDATA:
39037602 504 ret = sysctl_action_userdata(req);
39236c6e 505 break;
316670eb 506 case REQ_TIMER_COUNT:
39037602 507 ret = sysctl_timer_count(req);
39236c6e 508 break;
316670eb 509 case REQ_TIMER_PERIOD:
39037602 510 ret = sysctl_timer_period(req);
39236c6e 511 break;
316670eb 512 case REQ_TIMER_PET:
39037602 513 ret = sysctl_timer_pet(req);
39236c6e
A
514 break;
515 case REQ_TIMER_ACTION:
39037602 516 ret = sysctl_timer_action(req);
39236c6e 517 break;
316670eb 518 case REQ_SAMPLING:
39037602 519 ret = sysctl_sampling(req);
39236c6e 520 break;
3e170ce0 521 case REQ_KDBG_CSWITCH:
39037602 522 ret = sysctl_kdbg_cswitch(req);
3e170ce0 523 break;
39236c6e 524 case REQ_ACTION_FILTER_BY_TASK:
5ba3f43e 525 ret = sysctl_action_filter(req, true);
39236c6e
A
526 break;
527 case REQ_ACTION_FILTER_BY_PID:
5ba3f43e 528 ret = sysctl_action_filter(req, false);
39037602
A
529 break;
530 case REQ_KDEBUG_ACTION:
531 ret = sysctl_kdebug_action(req);
532 break;
533 case REQ_KDEBUG_FILTER:
534 ret = sysctl_kdebug_filter(req);
39236c6e
A
535 break;
536 case REQ_PET_IDLE_RATE:
39037602 537 ret = sysctl_pet_idle_rate(req);
39236c6e
A
538 break;
539 case REQ_BLESS_PREEMPT:
39037602
A
540 ret = sysctl_bless_preempt(req);
541 break;
542 case REQ_RESET:
543 ret = sysctl_kperf_reset(req);
39236c6e 544 break;
39037602
A
545 case REQ_ACTION_UCALLSTACK_DEPTH:
546 ret = sysctl_action_ucallstack_depth(req);
3e170ce0 547 break;
39037602
A
548 case REQ_ACTION_KCALLSTACK_DEPTH:
549 ret = sysctl_action_kcallstack_depth(req);
3e170ce0 550 break;
39037602
A
551 case REQ_LIGHTWEIGHT_PET:
552 ret = sysctl_lightweight_pet(req);
0a7de745 553 break;
d9a64523
A
554 case REQ_LAZY_WAIT_TIME_THRESHOLD:
555 ret = sysctl_lazy_wait_time_threshold(req);
0a7de745 556 break;
d9a64523
A
557 case REQ_LAZY_WAIT_ACTION:
558 ret = sysctl_lazy_wait_action(req);
0a7de745 559 break;
d9a64523
A
560 case REQ_LAZY_CPU_TIME_THRESHOLD:
561 ret = sysctl_lazy_cpu_time_threshold(req);
0a7de745 562 break;
d9a64523
A
563 case REQ_LAZY_CPU_ACTION:
564 ret = sysctl_lazy_cpu_action(req);
0a7de745 565 break;
316670eb 566 default:
39236c6e
A
567 ret = ENOENT;
568 break;
569 }
570
5ba3f43e 571 ktrace_unlock();
39236c6e
A
572
573 return ret;
574}
575
576static int
577kperf_sysctl_bless_handler SYSCTL_HANDLER_ARGS
578{
39037602 579#pragma unused(oidp, arg2)
39236c6e 580 int ret;
39236c6e 581
5ba3f43e 582 ktrace_lock();
39037602
A
583
584 /* if setting a new "blessed pid" (ktrace owning pid) */
585 if (req->newptr != USER_ADDR_NULL) {
586 /*
587 * root can bypass the ktrace check when a flag is set (for
588 * backwards compatibility) or when ownership is maintained over
589 * subsystems resets (to allow the user space process that set
590 * ownership to unset it).
591 */
592 if (!((ktrace_root_set_owner_allowed ||
0a7de745
A
593 ktrace_keep_ownership_on_reset) &&
594 kauth_cred_issuser(kauth_cred_get()))) {
39037602 595 if ((ret = ktrace_configure(KTRACE_KPERF))) {
5ba3f43e 596 ktrace_unlock();
39037602
A
597 return ret;
598 }
599 }
600 } else {
601 if ((ret = ktrace_read_check())) {
5ba3f43e 602 ktrace_unlock();
39236c6e 603 return ret;
39236c6e
A
604 }
605 }
606
39037602
A
607 /* which request */
608 if ((uintptr_t)arg1 == REQ_BLESS) {
609 ret = sysctl_bless(req);
610 } else {
611 ret = ENOENT;
316670eb 612 }
39236c6e 613
5ba3f43e 614 ktrace_unlock();
fe8ab488 615
39037602 616 return ret;
316670eb
A
617}
618
619/* root kperf node */
39037602
A
620
621SYSCTL_NODE(, OID_AUTO, kperf, CTLFLAG_RW | CTLFLAG_LOCKED, 0,
0a7de745 622 "kperf");
316670eb 623
39037602
A
624/* actions */
625
626SYSCTL_NODE(_kperf, OID_AUTO, action, CTLFLAG_RW | CTLFLAG_LOCKED, 0,
0a7de745 627 "action");
316670eb
A
628
629SYSCTL_PROC(_kperf_action, OID_AUTO, count,
0a7de745
A
630 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_LOCKED |
631 CTLFLAG_MASKED,
632 (void *)REQ_ACTION_COUNT,
633 sizeof(int), kperf_sysctl, "I", "Number of actions");
316670eb
A
634
635SYSCTL_PROC(_kperf_action, OID_AUTO, samplers,
0a7de745
A
636 CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MASKED | CTLFLAG_LOCKED,
637 (void *)REQ_ACTION_SAMPLERS,
638 3 * sizeof(uint64_t), kperf_sysctl, "UQ",
639 "What to sample when a trigger fires an action");
316670eb 640
39236c6e 641SYSCTL_PROC(_kperf_action, OID_AUTO, userdata,
0a7de745
A
642 CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MASKED | CTLFLAG_LOCKED,
643 (void *)REQ_ACTION_USERDATA,
644 3 * sizeof(uint64_t), kperf_sysctl, "UQ",
645 "User data to attribute to action");
39236c6e
A
646
647SYSCTL_PROC(_kperf_action, OID_AUTO, filter_by_task,
0a7de745
A
648 CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MASKED | CTLFLAG_LOCKED,
649 (void *)REQ_ACTION_FILTER_BY_TASK,
650 3 * sizeof(uint64_t), kperf_sysctl, "UQ",
651 "Apply a task filter to the action");
39236c6e
A
652
653SYSCTL_PROC(_kperf_action, OID_AUTO, filter_by_pid,
0a7de745
A
654 CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MASKED | CTLFLAG_LOCKED,
655 (void *)REQ_ACTION_FILTER_BY_PID,
656 3 * sizeof(uint64_t), kperf_sysctl, "UQ",
657 "Apply a pid filter to the action");
39236c6e 658
39037602 659SYSCTL_PROC(_kperf_action, OID_AUTO, ucallstack_depth,
0a7de745
A
660 CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MASKED | CTLFLAG_LOCKED,
661 (void *)REQ_ACTION_UCALLSTACK_DEPTH,
662 sizeof(int), kperf_sysctl, "I",
663 "Maximum number of frames to include in user callstacks");
39037602
A
664
665SYSCTL_PROC(_kperf_action, OID_AUTO, kcallstack_depth,
0a7de745
A
666 CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MASKED | CTLFLAG_LOCKED,
667 (void *)REQ_ACTION_KCALLSTACK_DEPTH,
668 sizeof(int), kperf_sysctl, "I",
669 "Maximum number of frames to include in kernel callstacks");
39037602
A
670
671/* timers */
672
673SYSCTL_NODE(_kperf, OID_AUTO, timer, CTLFLAG_RW | CTLFLAG_LOCKED, 0,
0a7de745 674 "timer");
316670eb
A
675
676SYSCTL_PROC(_kperf_timer, OID_AUTO, count,
0a7de745
A
677 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_LOCKED
678 | CTLFLAG_MASKED,
679 (void *)REQ_TIMER_COUNT,
680 sizeof(int), kperf_sysctl, "I", "Number of time triggers");
316670eb
A
681
682SYSCTL_PROC(_kperf_timer, OID_AUTO, period,
0a7de745
A
683 CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MASKED | CTLFLAG_LOCKED,
684 (void *)REQ_TIMER_PERIOD,
685 2 * sizeof(uint64_t), kperf_sysctl, "UQ",
686 "Timer number and period");
316670eb 687
39236c6e 688SYSCTL_PROC(_kperf_timer, OID_AUTO, action,
0a7de745
A
689 CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MASKED | CTLFLAG_LOCKED,
690 (void *)REQ_TIMER_ACTION,
691 2 * sizeof(uint64_t), kperf_sysctl, "UQ",
692 "Timer number and actionid");
39236c6e 693
316670eb 694SYSCTL_PROC(_kperf_timer, OID_AUTO, pet_timer,
0a7de745
A
695 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_LOCKED
696 | CTLFLAG_MASKED,
697 (void *)REQ_TIMER_PET,
698 sizeof(int), kperf_sysctl, "I", "Which timer ID does PET");
316670eb 699
39037602
A
700/* kdebug trigger */
701
702SYSCTL_NODE(_kperf, OID_AUTO, kdebug, CTLFLAG_RW | CTLFLAG_LOCKED, 0,
0a7de745 703 "kdebug");
39037602
A
704
705SYSCTL_PROC(_kperf_kdebug, OID_AUTO, action,
0a7de745
A
706 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_LOCKED
707 | CTLFLAG_MASKED,
708 (void*)REQ_KDEBUG_ACTION,
709 sizeof(int), kperf_sysctl, "I", "ID of action to trigger on kdebug events");
39037602
A
710
711SYSCTL_PROC(_kperf_kdebug, OID_AUTO, filter,
0a7de745
A
712 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MASKED | CTLFLAG_LOCKED,
713 (void*)REQ_KDEBUG_FILTER,
714 sizeof(int), kperf_sysctl, "P", "The filter that determines which kdebug events trigger a sample");
39037602 715
d9a64523
A
716/* lazy sampling */
717
718SYSCTL_NODE(_kperf, OID_AUTO, lazy, CTLFLAG_RW | CTLFLAG_LOCKED, 0,
0a7de745 719 "lazy");
d9a64523
A
720
721SYSCTL_PROC(_kperf_lazy, OID_AUTO, wait_time_threshold,
0a7de745
A
722 CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MASKED | CTLFLAG_LOCKED,
723 (void *)REQ_LAZY_WAIT_TIME_THRESHOLD,
724 sizeof(uint64_t), kperf_sysctl, "UQ",
725 "How many ticks a thread must wait to take a sample");
d9a64523
A
726
727SYSCTL_PROC(_kperf_lazy, OID_AUTO, wait_action,
0a7de745
A
728 CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MASKED | CTLFLAG_LOCKED,
729 (void *)REQ_LAZY_WAIT_ACTION,
730 sizeof(uint64_t), kperf_sysctl, "UQ",
731 "Which action to fire when a thread waits longer than threshold");
d9a64523
A
732
733SYSCTL_PROC(_kperf_lazy, OID_AUTO, cpu_time_threshold,
0a7de745
A
734 CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MASKED | CTLFLAG_LOCKED,
735 (void *)REQ_LAZY_CPU_TIME_THRESHOLD,
736 sizeof(uint64_t), kperf_sysctl, "UQ",
737 "Minimum number of ticks a CPU must run between samples");
d9a64523
A
738
739SYSCTL_PROC(_kperf_lazy, OID_AUTO, cpu_action,
0a7de745
A
740 CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MASKED | CTLFLAG_LOCKED,
741 (void *)REQ_LAZY_CPU_ACTION,
742 sizeof(uint64_t), kperf_sysctl, "UQ",
743 "Which action to fire for lazy CPU samples");
d9a64523 744
316670eb 745/* misc */
39037602 746
316670eb 747SYSCTL_PROC(_kperf, OID_AUTO, sampling,
0a7de745
A
748 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_LOCKED
749 | CTLFLAG_MASKED,
750 (void *)REQ_SAMPLING,
751 sizeof(int), kperf_sysctl, "I", "Sampling running");
316670eb 752
39037602 753SYSCTL_PROC(_kperf, OID_AUTO, reset,
0a7de745
A
754 CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MASKED | CTLFLAG_LOCKED,
755 (void *)REQ_RESET,
756 0, kperf_sysctl, "-", "Reset kperf");
39037602 757
39236c6e 758SYSCTL_PROC(_kperf, OID_AUTO, blessed_pid,
0a7de745
A
759 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED /* must be root */
760 | CTLFLAG_MASKED,
761 (void *)REQ_BLESS,
762 sizeof(int), kperf_sysctl_bless_handler, "I", "Blessed pid");
39236c6e
A
763
764SYSCTL_PROC(_kperf, OID_AUTO, blessed_preempt,
0a7de745
A
765 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_LOCKED |
766 CTLFLAG_MASKED,
767 (void *)REQ_BLESS_PREEMPT,
768 sizeof(int), kperf_sysctl, "I", "Blessed preemption");
39236c6e 769
3e170ce0 770SYSCTL_PROC(_kperf, OID_AUTO, kdbg_cswitch,
0a7de745
A
771 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_LOCKED
772 | CTLFLAG_MASKED,
773 (void *)REQ_KDBG_CSWITCH,
774 sizeof(int), kperf_sysctl, "I", "Generate context switch info");
39236c6e
A
775
776SYSCTL_PROC(_kperf, OID_AUTO, pet_idle_rate,
0a7de745
A
777 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_LOCKED
778 | CTLFLAG_MASKED,
779 (void *)REQ_PET_IDLE_RATE,
780 sizeof(int), kperf_sysctl, "I",
781 "Rate at which unscheduled threads are forced to be sampled in "
782 "PET mode");
39037602
A
783
784SYSCTL_PROC(_kperf, OID_AUTO, lightweight_pet,
0a7de745
A
785 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_LOCKED
786 | CTLFLAG_MASKED,
787 (void *)REQ_LIGHTWEIGHT_PET,
788 sizeof(int), kperf_sysctl, "I",
789 "Status of lightweight PET mode");
3e170ce0 790
5ba3f43e
A
791/* limits */
792
793SYSCTL_NODE(_kperf, OID_AUTO, limits, CTLFLAG_RW | CTLFLAG_LOCKED, 0,
0a7de745 794 "limits");
5ba3f43e 795
d9a64523
A
796enum kperf_limit_request {
797 REQ_LIM_PERIOD_NS,
798 REQ_LIM_BG_PERIOD_NS,
799 REQ_LIM_PET_PERIOD_NS,
800 REQ_LIM_BG_PET_PERIOD_NS,
801};
5ba3f43e
A
802
803static int
804kperf_sysctl_limits SYSCTL_HANDLER_ARGS
805{
806#pragma unused(oidp, arg2)
d9a64523 807 enum kperf_limit_request type = (enum kperf_limit_request)arg1;
5ba3f43e
A
808 uint64_t limit = 0;
809
810 switch (type) {
811 case REQ_LIM_PERIOD_NS:
812 limit = KP_MIN_PERIOD_NS;
813 break;
814
815 case REQ_LIM_BG_PERIOD_NS:
816 limit = KP_MIN_PERIOD_BG_NS;
817 break;
818
819 case REQ_LIM_PET_PERIOD_NS:
820 limit = KP_MIN_PERIOD_PET_NS;
821 break;
822
823 case REQ_LIM_BG_PET_PERIOD_NS:
824 limit = KP_MIN_PERIOD_PET_BG_NS;
825 break;
826
827 default:
828 return ENOENT;
829 }
830
831 return sysctl_io_number(req, limit, sizeof(limit), &limit, NULL);
832}
833
834SYSCTL_PROC(_kperf_limits, OID_AUTO, timer_min_period_ns,
0a7de745
A
835 CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_ANYBODY | CTLFLAG_LOCKED,
836 (void *)REQ_LIM_PERIOD_NS, sizeof(uint64_t), kperf_sysctl_limits,
837 "Q", "Minimum timer period in nanoseconds");
5ba3f43e 838SYSCTL_PROC(_kperf_limits, OID_AUTO, timer_min_bg_period_ns,
0a7de745
A
839 CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_ANYBODY | CTLFLAG_LOCKED,
840 (void *)REQ_LIM_BG_PERIOD_NS, sizeof(uint64_t), kperf_sysctl_limits,
841 "Q", "Minimum background timer period in nanoseconds");
5ba3f43e 842SYSCTL_PROC(_kperf_limits, OID_AUTO, timer_min_pet_period_ns,
0a7de745
A
843 CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_ANYBODY | CTLFLAG_LOCKED,
844 (void *)REQ_LIM_PET_PERIOD_NS, sizeof(uint64_t), kperf_sysctl_limits,
845 "Q", "Minimum PET timer period in nanoseconds");
5ba3f43e 846SYSCTL_PROC(_kperf_limits, OID_AUTO, timer_min_bg_pet_period_ns,
0a7de745
A
847 CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_ANYBODY | CTLFLAG_LOCKED,
848 (void *)REQ_LIM_BG_PET_PERIOD_NS, sizeof(uint64_t), kperf_sysctl_limits,
849 "Q", "Minimum background PET timer period in nanoseconds");
5ba3f43e 850
39236c6e 851/* debug */
39037602 852SYSCTL_INT(_kperf, OID_AUTO, debug_level, CTLFLAG_RW | CTLFLAG_LOCKED,
0a7de745 853 &kperf_debug_level, 0, "debug level");
39236c6e 854
39037602
A
855#if DEVELOPMENT || DEBUG
856SYSCTL_QUAD(_kperf, OID_AUTO, already_pending_ipis,
0a7de745
A
857 CTLFLAG_RD | CTLFLAG_LOCKED,
858 &kperf_pending_ipis, "");
39037602 859#endif /* DEVELOPMENT || DEBUG */