2 * Copyright (c) 2011 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 /* sysctl interface for paramters from user-land */
31 #include <kern/debug.h>
32 #include <libkern/libkern.h>
33 #include <pexpert/pexpert.h>
34 #include <sys/param.h>
37 #include <sys/sysctl.h>
38 #include <sys/kauth.h>
40 #include <kperf/action.h>
41 #include <kperf/context.h>
42 #include <kperf/kdebug_trigger.h>
43 #include <kperf/kperf.h>
44 #include <kperf/kperfbsd.h>
45 #include <kperf/kperf_timer.h>
46 #include <kperf/pet.h>
48 #include <sys/ktrace.h>
50 /* IDs for dispatch from SYSCTL macros */
51 #define REQ_SAMPLING (1)
52 #define REQ_ACTION_COUNT (2)
53 #define REQ_ACTION_SAMPLERS (3)
54 #define REQ_TIMER_COUNT (4)
55 #define REQ_TIMER_PERIOD (5)
56 #define REQ_TIMER_PET (6)
57 #define REQ_TIMER_ACTION (7)
59 #define REQ_ACTION_USERDATA (9)
60 #define REQ_ACTION_FILTER_BY_TASK (10)
61 #define REQ_ACTION_FILTER_BY_PID (11)
63 #define REQ_PET_IDLE_RATE (13)
64 #define REQ_BLESS_PREEMPT (14)
65 #define REQ_KDBG_CSWITCH (15)
66 #define REQ_RESET (16)
68 #define REQ_ACTION_UCALLSTACK_DEPTH (18)
69 #define REQ_ACTION_KCALLSTACK_DEPTH (19)
70 #define REQ_LIGHTWEIGHT_PET (20)
71 #define REQ_KDEBUG_ACTION (21)
72 #define REQ_KDEBUG_FILTER (22)
74 int kperf_debug_level
= 0;
76 #if DEVELOPMENT || DEBUG
77 _Atomic
long long kperf_pending_ipis
= 0;
78 #endif /* DEVELOPMENT || DEBUG */
81 * kperf has a different sysctl model than others.
83 * For simple queries like the number of actions, the normal sysctl style
84 * of get/set works well.
86 * However, when requesting information about something specific, like an
87 * action, user space needs to provide some contextual information. This
88 * information is stored in a uint64_t array that includes the context, like
89 * the action ID it is interested in. If user space is getting the value from
90 * the kernel, then the get side of the sysctl is valid. If it is setting the
91 * value, then the get pointers are left NULL.
93 * These functions handle marshalling and unmarshalling data from sysctls.
97 kperf_sysctl_get_set_uint32(struct sysctl_req
*req
,
98 uint32_t (*get
)(void), int (*set
)(uint32_t))
109 int error
= sysctl_io_number(req
, value
, sizeof(value
), &value
, NULL
);
111 if (error
|| !req
->newptr
) {
119 kperf_sysctl_get_set_int(struct sysctl_req
*req
,
120 int (*get
)(void), int (*set
)(int))
131 int error
= sysctl_io_number(req
, value
, sizeof(value
), &value
, NULL
);
133 if (error
|| !req
->newptr
) {
141 kperf_sysctl_get_set_unsigned_uint32(struct sysctl_req
*req
,
142 int (*get
)(unsigned int, uint32_t *), int (*set
)(unsigned int, uint32_t))
150 if ((error
= SYSCTL_IN(req
, inputs
, sizeof(inputs
)))) {
154 unsigned int action_id
= (unsigned int)inputs
[0];
155 uint32_t new_value
= (uint32_t)inputs
[1];
157 if (req
->oldptr
!= USER_ADDR_NULL
) {
158 uint32_t value_out
= 0;
159 if ((error
= get(action_id
, &value_out
))) {
163 inputs
[1] = value_out
;
165 if ((error
= set(action_id
, new_value
))) {
170 if (req
->oldptr
!= USER_ADDR_NULL
) {
171 error
= SYSCTL_OUT(req
, inputs
, sizeof(inputs
));
179 * These functions are essentially the same as the generic
180 * kperf_sysctl_get_set_unsigned_uint32, except they have unique input sizes.
184 sysctl_timer_period(struct sysctl_req
*req
)
190 if ((error
= SYSCTL_IN(req
, inputs
, sizeof(inputs
)))) {
194 unsigned int timer
= (unsigned int)inputs
[0];
195 uint64_t new_period
= inputs
[1];
197 if (req
->oldptr
!= USER_ADDR_NULL
) {
198 uint64_t period_out
= 0;
199 if ((error
= kperf_timer_get_period(timer
, &period_out
))) {
203 inputs
[1] = period_out
;
205 if ((error
= kperf_timer_set_period(timer
, new_period
))) {
210 return SYSCTL_OUT(req
, inputs
, sizeof(inputs
));
214 sysctl_action_filter(struct sysctl_req
*req
, boolean_t is_task_t
)
220 if ((error
= SYSCTL_IN(req
, inputs
, sizeof(inputs
)))) {
224 unsigned int actionid
= (unsigned int)inputs
[0];
225 int new_filter
= (int)inputs
[1];
227 if (req
->oldptr
!= USER_ADDR_NULL
) {
229 if ((error
= kperf_action_get_filter(actionid
, &filter_out
))) {
233 inputs
[1] = filter_out
;
235 int pid
= is_task_t
? kperf_port_to_pid((mach_port_name_t
)new_filter
)
238 if ((error
= kperf_action_set_filter(actionid
, pid
))) {
243 return SYSCTL_OUT(req
, inputs
, sizeof(inputs
));
247 sysctl_bless(struct sysctl_req
*req
)
249 int value
= ktrace_get_owning_pid();
250 int error
= sysctl_io_number(req
, value
, sizeof(value
), &value
, NULL
);
252 if (error
|| !req
->newptr
) {
256 return ktrace_set_owning_pid(value
);
259 /* sysctl handlers that use the generic functions */
262 sysctl_action_samplers(struct sysctl_req
*req
)
264 return kperf_sysctl_get_set_unsigned_uint32(req
,
265 kperf_action_get_samplers
, kperf_action_set_samplers
);
269 sysctl_action_userdata(struct sysctl_req
*req
)
271 return kperf_sysctl_get_set_unsigned_uint32(req
,
272 kperf_action_get_userdata
, kperf_action_set_userdata
);
276 sysctl_action_ucallstack_depth(struct sysctl_req
*req
)
278 return kperf_sysctl_get_set_unsigned_uint32(req
,
279 kperf_action_get_ucallstack_depth
, kperf_action_set_ucallstack_depth
);
283 sysctl_action_kcallstack_depth(struct sysctl_req
*req
)
285 return kperf_sysctl_get_set_unsigned_uint32(req
,
286 kperf_action_get_kcallstack_depth
, kperf_action_set_kcallstack_depth
);
290 sysctl_kdebug_action(struct sysctl_req
*req
)
292 return kperf_sysctl_get_set_int(req
, kperf_kdebug_get_action
,
293 kperf_kdebug_set_action
);
297 sysctl_kdebug_filter(struct sysctl_req
*req
)
301 if (req
->oldptr
!= USER_ADDR_NULL
) {
302 struct kperf_kdebug_filter
*filter
= NULL
;
303 uint32_t n_debugids
= kperf_kdebug_get_filter(&filter
);
304 size_t filter_size
= KPERF_KDEBUG_FILTER_SIZE(n_debugids
);
306 if (n_debugids
== 0) {
310 return SYSCTL_OUT(req
, filter
, filter_size
);
313 return kperf_kdebug_set_filter(req
->newptr
, (uint32_t)req
->newlen
);
317 kperf_sampling_set(uint32_t sample_start
)
320 return kperf_sampling_enable();
322 return kperf_sampling_disable();
327 sysctl_sampling(struct sysctl_req
*req
)
329 return kperf_sysctl_get_set_uint32(req
, kperf_sampling_status
,
334 sysctl_action_count(struct sysctl_req
*req
)
336 return kperf_sysctl_get_set_uint32(req
, kperf_action_get_count
,
337 kperf_action_set_count
);
341 sysctl_timer_count(struct sysctl_req
*req
)
343 return kperf_sysctl_get_set_uint32(req
, kperf_timer_get_count
,
344 kperf_timer_set_count
);
348 sysctl_timer_action(struct sysctl_req
*req
)
350 return kperf_sysctl_get_set_unsigned_uint32(req
, kperf_timer_get_action
,
351 kperf_timer_set_action
);
355 sysctl_timer_pet(struct sysctl_req
*req
)
357 return kperf_sysctl_get_set_uint32(req
, kperf_timer_get_petid
,
358 kperf_timer_set_petid
);
362 sysctl_bless_preempt(struct sysctl_req
*req
)
364 return sysctl_io_number(req
, ktrace_root_set_owner_allowed
,
365 sizeof(ktrace_root_set_owner_allowed
),
366 &ktrace_root_set_owner_allowed
, NULL
);
370 sysctl_kperf_reset(struct sysctl_req
*req
)
372 int should_reset
= 0;
374 int error
= sysctl_io_number(req
, should_reset
, sizeof(should_reset
),
375 &should_reset
, NULL
);
381 ktrace_reset(KTRACE_KPERF
);
387 sysctl_pet_idle_rate(struct sysctl_req
*req
)
389 return kperf_sysctl_get_set_int(req
, kperf_get_pet_idle_rate
,
390 kperf_set_pet_idle_rate
);
394 sysctl_lightweight_pet(struct sysctl_req
*req
)
396 return kperf_sysctl_get_set_int(req
, kperf_get_lightweight_pet
,
397 kperf_set_lightweight_pet
);
401 sysctl_kdbg_cswitch(struct sysctl_req
*req
)
403 return kperf_sysctl_get_set_int(req
, kperf_kdbg_cswitch_get
,
404 kperf_kdbg_cswitch_set
);
408 kperf_sysctl SYSCTL_HANDLER_ARGS
410 #pragma unused(oidp, arg2)
412 uintptr_t type
= (uintptr_t)arg1
;
414 lck_mtx_lock(ktrace_lock
);
416 if (req
->oldptr
== USER_ADDR_NULL
&& req
->newptr
!= USER_ADDR_NULL
) {
417 if ((ret
= ktrace_configure(KTRACE_KPERF
))) {
418 lck_mtx_unlock(ktrace_lock
);
422 if ((ret
= ktrace_read_check())) {
423 lck_mtx_unlock(ktrace_lock
);
430 case REQ_ACTION_COUNT
:
431 ret
= sysctl_action_count(req
);
433 case REQ_ACTION_SAMPLERS
:
434 ret
= sysctl_action_samplers(req
);
436 case REQ_ACTION_USERDATA
:
437 ret
= sysctl_action_userdata(req
);
439 case REQ_TIMER_COUNT
:
440 ret
= sysctl_timer_count(req
);
442 case REQ_TIMER_PERIOD
:
443 ret
= sysctl_timer_period(req
);
446 ret
= sysctl_timer_pet(req
);
448 case REQ_TIMER_ACTION
:
449 ret
= sysctl_timer_action(req
);
452 ret
= sysctl_sampling(req
);
454 case REQ_KDBG_CSWITCH
:
455 ret
= sysctl_kdbg_cswitch(req
);
457 case REQ_ACTION_FILTER_BY_TASK
:
458 ret
= sysctl_action_filter(req
, TRUE
);
460 case REQ_ACTION_FILTER_BY_PID
:
461 ret
= sysctl_action_filter(req
, FALSE
);
463 case REQ_KDEBUG_ACTION
:
464 ret
= sysctl_kdebug_action(req
);
466 case REQ_KDEBUG_FILTER
:
467 ret
= sysctl_kdebug_filter(req
);
469 case REQ_PET_IDLE_RATE
:
470 ret
= sysctl_pet_idle_rate(req
);
472 case REQ_BLESS_PREEMPT
:
473 ret
= sysctl_bless_preempt(req
);
476 ret
= sysctl_kperf_reset(req
);
478 case REQ_ACTION_UCALLSTACK_DEPTH
:
479 ret
= sysctl_action_ucallstack_depth(req
);
481 case REQ_ACTION_KCALLSTACK_DEPTH
:
482 ret
= sysctl_action_kcallstack_depth(req
);
484 case REQ_LIGHTWEIGHT_PET
:
485 ret
= sysctl_lightweight_pet(req
);
492 lck_mtx_unlock(ktrace_lock
);
498 kperf_sysctl_bless_handler SYSCTL_HANDLER_ARGS
500 #pragma unused(oidp, arg2)
503 lck_mtx_lock(ktrace_lock
);
505 /* if setting a new "blessed pid" (ktrace owning pid) */
506 if (req
->newptr
!= USER_ADDR_NULL
) {
508 * root can bypass the ktrace check when a flag is set (for
509 * backwards compatibility) or when ownership is maintained over
510 * subsystems resets (to allow the user space process that set
511 * ownership to unset it).
513 if (!((ktrace_root_set_owner_allowed
||
514 ktrace_keep_ownership_on_reset
) &&
515 kauth_cred_issuser(kauth_cred_get())))
517 if ((ret
= ktrace_configure(KTRACE_KPERF
))) {
518 lck_mtx_unlock(ktrace_lock
);
523 if ((ret
= ktrace_read_check())) {
524 lck_mtx_unlock(ktrace_lock
);
530 if ((uintptr_t)arg1
== REQ_BLESS
) {
531 ret
= sysctl_bless(req
);
536 lck_mtx_unlock(ktrace_lock
);
541 /* root kperf node */
543 SYSCTL_NODE(, OID_AUTO
, kperf
, CTLFLAG_RW
| CTLFLAG_LOCKED
, 0,
548 SYSCTL_NODE(_kperf
, OID_AUTO
, action
, CTLFLAG_RW
| CTLFLAG_LOCKED
, 0,
551 SYSCTL_PROC(_kperf_action
, OID_AUTO
, count
,
552 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_ANYBODY
| CTLFLAG_LOCKED
,
553 (void *)REQ_ACTION_COUNT
,
554 sizeof(int), kperf_sysctl
, "I", "Number of actions");
556 SYSCTL_PROC(_kperf_action
, OID_AUTO
, samplers
,
557 CTLFLAG_RW
| CTLFLAG_ANYBODY
| CTLFLAG_MASKED
| CTLFLAG_LOCKED
,
558 (void *)REQ_ACTION_SAMPLERS
,
559 3 * sizeof(uint64_t), kperf_sysctl
, "UQ",
560 "What to sample when a trigger fires an action");
562 SYSCTL_PROC(_kperf_action
, OID_AUTO
, userdata
,
563 CTLFLAG_RW
| CTLFLAG_ANYBODY
| CTLFLAG_MASKED
| CTLFLAG_LOCKED
,
564 (void *)REQ_ACTION_USERDATA
,
565 3 * sizeof(uint64_t), kperf_sysctl
, "UQ",
566 "User data to attribute to action");
568 SYSCTL_PROC(_kperf_action
, OID_AUTO
, filter_by_task
,
569 CTLFLAG_RW
| CTLFLAG_ANYBODY
| CTLFLAG_MASKED
| CTLFLAG_LOCKED
,
570 (void *)REQ_ACTION_FILTER_BY_TASK
,
571 3 * sizeof(uint64_t), kperf_sysctl
, "UQ",
572 "Apply a task filter to the action");
574 SYSCTL_PROC(_kperf_action
, OID_AUTO
, filter_by_pid
,
575 CTLFLAG_RW
| CTLFLAG_ANYBODY
| CTLFLAG_MASKED
| CTLFLAG_LOCKED
,
576 (void *)REQ_ACTION_FILTER_BY_PID
,
577 3 * sizeof(uint64_t), kperf_sysctl
, "UQ",
578 "Apply a pid filter to the action");
580 SYSCTL_PROC(_kperf_action
, OID_AUTO
, ucallstack_depth
,
581 CTLFLAG_RW
| CTLFLAG_ANYBODY
| CTLFLAG_MASKED
| CTLFLAG_LOCKED
,
582 (void *)REQ_ACTION_UCALLSTACK_DEPTH
,
583 sizeof(int), kperf_sysctl
, "I",
584 "Maximum number of frames to include in user callstacks");
586 SYSCTL_PROC(_kperf_action
, OID_AUTO
, kcallstack_depth
,
587 CTLFLAG_RW
| CTLFLAG_ANYBODY
| CTLFLAG_MASKED
| CTLFLAG_LOCKED
,
588 (void *)REQ_ACTION_KCALLSTACK_DEPTH
,
589 sizeof(int), kperf_sysctl
, "I",
590 "Maximum number of frames to include in kernel callstacks");
594 SYSCTL_NODE(_kperf
, OID_AUTO
, timer
, CTLFLAG_RW
| CTLFLAG_LOCKED
, 0,
597 SYSCTL_PROC(_kperf_timer
, OID_AUTO
, count
,
598 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_ANYBODY
| CTLFLAG_LOCKED
,
599 (void *)REQ_TIMER_COUNT
,
600 sizeof(int), kperf_sysctl
, "I", "Number of time triggers");
602 SYSCTL_PROC(_kperf_timer
, OID_AUTO
, period
,
603 CTLFLAG_RW
| CTLFLAG_ANYBODY
| CTLFLAG_MASKED
| CTLFLAG_LOCKED
,
604 (void *)REQ_TIMER_PERIOD
,
605 2 * sizeof(uint64_t), kperf_sysctl
, "UQ",
606 "Timer number and period");
608 SYSCTL_PROC(_kperf_timer
, OID_AUTO
, action
,
609 CTLFLAG_RW
| CTLFLAG_ANYBODY
| CTLFLAG_MASKED
| CTLFLAG_LOCKED
,
610 (void *)REQ_TIMER_ACTION
,
611 2 * sizeof(uint64_t), kperf_sysctl
, "UQ",
612 "Timer number and actionid");
614 SYSCTL_PROC(_kperf_timer
, OID_AUTO
, pet_timer
,
615 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_ANYBODY
| CTLFLAG_LOCKED
,
616 (void *)REQ_TIMER_PET
,
617 sizeof(int), kperf_sysctl
, "I", "Which timer ID does PET");
621 SYSCTL_NODE(_kperf
, OID_AUTO
, kdebug
, CTLFLAG_RW
| CTLFLAG_LOCKED
, 0,
624 SYSCTL_PROC(_kperf_kdebug
, OID_AUTO
, action
,
625 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_ANYBODY
| CTLFLAG_LOCKED
,
626 (void*)REQ_KDEBUG_ACTION
,
627 sizeof(int), kperf_sysctl
, "I", "ID of action to trigger on kdebug events");
629 SYSCTL_PROC(_kperf_kdebug
, OID_AUTO
, filter
,
630 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_ANYBODY
| CTLFLAG_MASKED
| CTLFLAG_LOCKED
,
631 (void*)REQ_KDEBUG_FILTER
,
632 sizeof(int), kperf_sysctl
, "P", "The filter that determines which kdebug events trigger a sample");
636 SYSCTL_PROC(_kperf
, OID_AUTO
, sampling
,
637 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_ANYBODY
| CTLFLAG_LOCKED
,
638 (void *)REQ_SAMPLING
,
639 sizeof(int), kperf_sysctl
, "I", "Sampling running");
641 SYSCTL_PROC(_kperf
, OID_AUTO
, reset
,
642 CTLFLAG_RW
| CTLFLAG_ANYBODY
| CTLFLAG_MASKED
| CTLFLAG_LOCKED
,
644 0, kperf_sysctl
, "-", "Reset kperf");
646 SYSCTL_PROC(_kperf
, OID_AUTO
, blessed_pid
,
647 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_LOCKED
, /* must be root */
649 sizeof(int), kperf_sysctl_bless_handler
, "I", "Blessed pid");
651 SYSCTL_PROC(_kperf
, OID_AUTO
, blessed_preempt
,
652 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_ANYBODY
| CTLFLAG_LOCKED
,
653 (void *)REQ_BLESS_PREEMPT
,
654 sizeof(int), kperf_sysctl
, "I", "Blessed preemption");
656 SYSCTL_PROC(_kperf
, OID_AUTO
, kdbg_cswitch
,
657 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_ANYBODY
| CTLFLAG_LOCKED
,
658 (void *)REQ_KDBG_CSWITCH
,
659 sizeof(int), kperf_sysctl
, "I", "Generate context switch info");
661 SYSCTL_PROC(_kperf
, OID_AUTO
, pet_idle_rate
,
662 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_ANYBODY
| CTLFLAG_LOCKED
,
663 (void *)REQ_PET_IDLE_RATE
,
664 sizeof(int), kperf_sysctl
, "I",
665 "Rate at which unscheduled threads are forced to be sampled in "
668 SYSCTL_PROC(_kperf
, OID_AUTO
, lightweight_pet
,
669 CTLTYPE_INT
| CTLFLAG_RW
| CTLFLAG_ANYBODY
| CTLFLAG_LOCKED
,
670 (void *)REQ_LIGHTWEIGHT_PET
,
671 sizeof(int), kperf_sysctl
, "I",
672 "Status of lightweight PET mode");
675 SYSCTL_INT(_kperf
, OID_AUTO
, debug_level
, CTLFLAG_RW
| CTLFLAG_LOCKED
,
676 &kperf_debug_level
, 0, "debug level");
678 #if DEVELOPMENT || DEBUG
679 SYSCTL_QUAD(_kperf
, OID_AUTO
, already_pending_ipis
,
680 CTLFLAG_RD
| CTLFLAG_LOCKED
,
681 &kperf_pending_ipis
, "");
682 #endif /* DEVELOPMENT || DEBUG */