]> git.saurik.com Git - apple/xnu.git/blob - osfmk/kperf/kperfbsd.c
xnu-2782.40.9.tar.gz
[apple/xnu.git] / osfmk / kperf / kperfbsd.c
1 /*
2 * Copyright (c) 2011 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 /* sysctl interface for paramters from user-land */
30
31 #include <sys/param.h>
32 #include <sys/mman.h>
33 #include <sys/stat.h>
34 #include <sys/sysctl.h>
35 #include <sys/kauth.h>
36 #include <libkern/libkern.h>
37 #include <kern/debug.h>
38 #include <pexpert/pexpert.h>
39
40 #include <kperf/context.h>
41 #include <kperf/action.h>
42 #include <kperf/timetrigger.h>
43 #include <kperf/pet.h>
44 #include <kperf/kperfbsd.h>
45 #include <kperf/kperf.h>
46
47
48 /* a pid which is allowed to control kperf without requiring root access */
49 static pid_t blessed_pid = -1;
50 static boolean_t blessed_preempt = FALSE;
51
52 /* IDs for dispatch from SYSCTL macros */
53 #define REQ_SAMPLING (1)
54 #define REQ_ACTION_COUNT (2)
55 #define REQ_ACTION_SAMPLERS (3)
56 #define REQ_TIMER_COUNT (4)
57 #define REQ_TIMER_PERIOD (5)
58 #define REQ_TIMER_PET (6)
59 #define REQ_TIMER_ACTION (7)
60 #define REQ_BLESS (8)
61 #define REQ_ACTION_USERDATA (9)
62 #define REQ_ACTION_FILTER_BY_TASK (10)
63 #define REQ_ACTION_FILTER_BY_PID (11)
64 #define REQ_KDBG_CALLSTACKS (12)
65 #define REQ_PET_IDLE_RATE (13)
66 #define REQ_BLESS_PREEMPT (14)
67
68 /* simple state variables */
69 int kperf_debug_level = 0;
70
71 static lck_grp_attr_t *kperf_cfg_lckgrp_attr = NULL;
72 static lck_grp_t *kperf_cfg_lckgrp = NULL;
73 static lck_mtx_t kperf_cfg_lock;
74 static boolean_t kperf_cfg_initted = FALSE;
75
76 void kdbg_swap_global_state_pid(pid_t old_pid, pid_t new_pid); /* bsd/kern/kdebug.c */
77
78 /***************************
79 *
80 * lock init
81 *
82 ***************************/
83
84 void
85 kperf_bootstrap(void)
86 {
87 kperf_cfg_lckgrp_attr = lck_grp_attr_alloc_init();
88 kperf_cfg_lckgrp = lck_grp_alloc_init("kperf cfg",
89 kperf_cfg_lckgrp_attr);
90 lck_mtx_init(&kperf_cfg_lock, kperf_cfg_lckgrp, LCK_ATTR_NULL);
91
92 kperf_cfg_initted = TRUE;
93 }
94
95 /***************************
96 *
97 * sysctl handlers
98 *
99 ***************************/
100
101 static int
102 sysctl_timer_period( __unused struct sysctl_oid *oidp, struct sysctl_req *req )
103 {
104 int error = 0;
105 uint64_t inputs[2], retval;
106 unsigned timer, set = 0;
107
108 /* get 2x 64-bit words */
109 error = SYSCTL_IN( req, inputs, 2*sizeof(inputs[0]) );
110 if(error)
111 return (error);
112
113 /* setup inputs */
114 timer = (unsigned) inputs[0];
115 if( inputs[1] != ~0ULL )
116 set = 1;
117
118 if( set )
119 {
120 error = kperf_timer_set_period( timer, inputs[1] );
121 if( error )
122 return error;
123 }
124
125 error = kperf_timer_get_period(timer, &retval);
126 if(error)
127 return (error);
128
129 inputs[1] = retval;
130
131 if( error == 0 )
132 error = SYSCTL_OUT( req, inputs, 2*sizeof(inputs[0]) );
133
134 return error;
135 }
136
137 static int
138 sysctl_timer_action( __unused struct sysctl_oid *oidp, struct sysctl_req *req )
139 {
140 int error = 0;
141 uint64_t inputs[2];
142 uint32_t retval;
143 unsigned timer, set = 0;
144
145 /* get 2x 64-bit words */
146 error = SYSCTL_IN( req, inputs, 2*sizeof(inputs[0]) );
147 if(error)
148 return (error);
149
150 /* setup inputs */
151 timer = (unsigned) inputs[0];
152 if( inputs[1] != ~0ULL )
153 set = 1;
154
155 if( set )
156 {
157 error = kperf_timer_set_action( timer, inputs[1] );
158 if( error )
159 return error;
160 }
161
162 error = kperf_timer_get_action(timer, &retval);
163 if(error)
164 return (error);
165
166 inputs[1] = retval;
167
168 if( error == 0 )
169 error = SYSCTL_OUT( req, inputs, 2*sizeof(inputs[0]) );
170
171 return error;
172 }
173
174 static int
175 sysctl_action_samplers( __unused struct sysctl_oid *oidp,
176 struct sysctl_req *req )
177 {
178 int error = 0;
179 uint64_t inputs[3];
180 uint32_t retval;
181 unsigned actionid, set = 0;
182
183 /* get 3x 64-bit words */
184 error = SYSCTL_IN( req, inputs, 3*sizeof(inputs[0]) );
185 if(error)
186 return (error);
187
188 /* setup inputs */
189 set = (unsigned) inputs[0];
190 actionid = (unsigned) inputs[1];
191
192 if( set )
193 {
194 error = kperf_action_set_samplers( actionid, inputs[2] );
195 if( error )
196 return error;
197 }
198
199 error = kperf_action_get_samplers(actionid, &retval);
200 if(error)
201 return (error);
202
203 inputs[2] = retval;
204
205 if( error == 0 )
206 error = SYSCTL_OUT( req, inputs, 3*sizeof(inputs[0]) );
207
208 return error;
209 }
210
211 static int
212 sysctl_action_userdata( __unused struct sysctl_oid *oidp,
213 struct sysctl_req *req )
214 {
215 int error = 0;
216 uint64_t inputs[3];
217 uint32_t retval;
218 unsigned actionid, set = 0;
219
220 /* get 3x 64-bit words */
221 error = SYSCTL_IN( req, inputs, 3*sizeof(inputs[0]) );
222 if(error)
223 return (error);
224
225 /* setup inputs */
226 set = (unsigned) inputs[0];
227 actionid = (unsigned) inputs[1];
228
229 if( set )
230 {
231 error = kperf_action_set_userdata( actionid, inputs[2] );
232 if( error )
233 return error;
234 }
235
236 error = kperf_action_get_userdata(actionid, &retval);
237 if(error)
238 return (error);
239
240 inputs[2] = retval;
241
242 if( error == 0 )
243 error = SYSCTL_OUT( req, inputs, 3*sizeof(inputs[0]) );
244
245 return error;
246 }
247
248 static int
249 sysctl_action_filter( __unused struct sysctl_oid *oidp,
250 struct sysctl_req *req, int is_task_t )
251 {
252 int error = 0;
253 uint64_t inputs[3];
254 int retval;
255 unsigned actionid, set = 0;
256 mach_port_name_t portname;
257 int pid;
258
259 /* get 3x 64-bit words */
260 error = SYSCTL_IN( req, inputs, 3*sizeof(inputs[0]) );
261 if(error)
262 return (error);
263
264 /* setup inputs */
265 set = (unsigned) inputs[0];
266 actionid = (unsigned) inputs[1];
267
268 if( set )
269 {
270 if( is_task_t )
271 {
272 portname = (mach_port_name_t) inputs[2];
273 pid = kperf_port_to_pid(portname);
274 }
275 else
276 pid = (int) inputs[2];
277
278 error = kperf_action_set_filter( actionid, pid );
279 if( error )
280 return error;
281 }
282
283 error = kperf_action_get_filter(actionid, &retval);
284 if(error)
285 return (error);
286
287 inputs[2] = retval;
288
289 if( error == 0 )
290 error = SYSCTL_OUT( req, inputs, 3*sizeof(inputs[0]) );
291
292 return error;
293 }
294
295 static int
296 sysctl_sampling( struct sysctl_oid *oidp, struct sysctl_req *req )
297 {
298 int error = 0;
299 uint32_t value = 0;
300
301 /* get the old value and process it */
302 value = kperf_sampling_status();
303
304 /* copy out the old value, get the new value */
305 error = sysctl_handle_int(oidp, &value, 0, req);
306 if (error || !req->newptr)
307 return (error);
308
309 /* if that worked, and we're writing... */
310 if( value )
311 error = kperf_sampling_enable();
312 else
313 error = kperf_sampling_disable();
314
315 return error;
316 }
317
318 static int
319 sysctl_action_count( struct sysctl_oid *oidp, struct sysctl_req *req )
320 {
321 int error = 0;
322 uint32_t value = 0;
323
324 /* get the old value and process it */
325 value = kperf_action_get_count();
326
327 /* copy out the old value, get the new value */
328 error = sysctl_handle_int(oidp, &value, 0, req);
329 if (error || !req->newptr)
330 return (error);
331
332 /* if that worked, and we're writing... */
333 return kperf_action_set_count(value);
334 }
335
336 static int
337 sysctl_timer_count( struct sysctl_oid *oidp, struct sysctl_req *req )
338 {
339 int error = 0;
340 uint32_t value = 0;
341
342 /* get the old value and process it */
343 value = kperf_timer_get_count();
344
345 /* copy out the old value, get the new value */
346 error = sysctl_handle_int(oidp, &value, 0, req);
347 if (error || !req->newptr)
348 return (error);
349
350 /* if that worked, and we're writing... */
351 return kperf_timer_set_count(value);
352 }
353
354 static int
355 sysctl_timer_pet( struct sysctl_oid *oidp, struct sysctl_req *req )
356 {
357 int error = 0;
358 uint32_t value = 0;
359
360 /* get the old value and process it */
361 value = kperf_timer_get_petid();
362
363 /* copy out the old value, get the new value */
364 error = sysctl_handle_int(oidp, &value, 0, req);
365 if (error || !req->newptr)
366 return (error);
367
368 /* if that worked, and we're writing... */
369 return kperf_timer_set_petid(value);
370 }
371
372 static int
373 sysctl_bless( struct sysctl_oid *oidp, struct sysctl_req *req )
374 {
375 int error = 0;
376 int value = 0;
377
378 /* get the old value and process it */
379 value = blessed_pid;
380
381 /* copy out the old value, get the new value */
382 error = sysctl_handle_int(oidp, &value, 0, req);
383 if (error || !req->newptr)
384 return (error);
385
386 /* if that worked, and we're writing... */
387 error = kperf_bless_pid(value);
388
389 return error;
390 }
391
392 static int
393 sysctl_bless_preempt( struct sysctl_oid *oidp, struct sysctl_req *req )
394 {
395 int error = 0;
396 int value = 0;
397
398 /* get the old value and process it */
399 value = blessed_preempt;
400
401 /* copy out the old value, get the new value */
402 error = sysctl_handle_int(oidp, &value, 0, req);
403 if (error || !req->newptr)
404 return (error);
405
406 /* if that worked, and we're writing... */
407 blessed_preempt = value ? TRUE : FALSE;
408
409 return 0;
410 }
411
412
413 static int
414 sysctl_kdbg_callstacks( struct sysctl_oid *oidp, struct sysctl_req *req )
415 {
416 int error = 0;
417 int value = 0;
418
419 /* get the old value and process it */
420 value = kperf_kdbg_get_stacks();
421
422 /* copy out the old value, get the new value */
423 error = sysctl_handle_int(oidp, &value, 0, req);
424 if (error || !req->newptr)
425 return (error);
426
427 /* if that worked, and we're writing... */
428 error = kperf_kdbg_set_stacks(value);
429
430 return error;
431 }
432
433 static int
434 sysctl_pet_idle_rate( struct sysctl_oid *oidp, struct sysctl_req *req )
435 {
436 int error = 0;
437 int value = 0;
438
439 /* get the old value and process it */
440 value = kperf_get_pet_idle_rate();
441
442 /* copy out the old value, get the new value */
443 error = sysctl_handle_int(oidp, &value, 0, req);
444 if (error || !req->newptr)
445 return (error);
446
447 /* if that worked, and we're writing... */
448 kperf_set_pet_idle_rate(value);
449
450 return error;
451 }
452
453 /*
454 * #define SYSCTL_HANDLER_ARGS (struct sysctl_oid *oidp, \
455 * void *arg1, int arg2, \
456 * struct sysctl_req *req )
457 */
458 static int
459 kperf_sysctl SYSCTL_HANDLER_ARGS
460 {
461 int ret;
462
463 // __unused struct sysctl_oid *unused_oidp = oidp;
464 (void)arg2;
465
466 if ( !kperf_cfg_initted )
467 panic("kperf_bootstrap not called");
468
469 ret = kperf_access_check();
470 if (ret) {
471 return ret;
472 }
473
474 lck_mtx_lock(&kperf_cfg_lock);
475
476 /* which request */
477 switch( (uintptr_t) arg1 )
478 {
479 case REQ_ACTION_COUNT:
480 ret = sysctl_action_count( oidp, req );
481 break;
482 case REQ_ACTION_SAMPLERS:
483 ret = sysctl_action_samplers( oidp, req );
484 break;
485 case REQ_ACTION_USERDATA:
486 ret = sysctl_action_userdata( oidp, req );
487 break;
488 case REQ_TIMER_COUNT:
489 ret = sysctl_timer_count( oidp, req );
490 break;
491 case REQ_TIMER_PERIOD:
492 ret = sysctl_timer_period( oidp, req );
493 break;
494 case REQ_TIMER_PET:
495 ret = sysctl_timer_pet( oidp, req );
496 break;
497 case REQ_TIMER_ACTION:
498 ret = sysctl_timer_action( oidp, req );
499 break;
500 case REQ_SAMPLING:
501 ret = sysctl_sampling( oidp, req );
502 break;
503 case REQ_KDBG_CALLSTACKS:
504 ret = sysctl_kdbg_callstacks( oidp, req );
505 break;
506 case REQ_ACTION_FILTER_BY_TASK:
507 ret = sysctl_action_filter( oidp, req, 1 );
508 break;
509 case REQ_ACTION_FILTER_BY_PID:
510 ret = sysctl_action_filter( oidp, req, 0 );
511 break;
512 case REQ_PET_IDLE_RATE:
513 ret = sysctl_pet_idle_rate( oidp, req );
514 break;
515 case REQ_BLESS_PREEMPT:
516 ret = sysctl_bless_preempt( oidp, req );
517 break;
518 default:
519 ret = ENOENT;
520 break;
521 }
522
523 lck_mtx_unlock(&kperf_cfg_lock);
524
525 return ret;
526 }
527
528 static int
529 kperf_sysctl_bless_handler SYSCTL_HANDLER_ARGS
530 {
531 int ret;
532 // __unused struct sysctl_oid *unused_oidp = oidp;
533 (void)arg2;
534
535 if ( !kperf_cfg_initted )
536 panic("kperf_bootstrap not called");
537
538 lck_mtx_lock(&kperf_cfg_lock);
539
540 /* which request */
541 if ( (uintptr_t) arg1 == REQ_BLESS )
542 ret = sysctl_bless( oidp, req );
543 else
544 ret = ENOENT;
545
546 lck_mtx_unlock(&kperf_cfg_lock);
547
548 return ret;
549 }
550
551
552 /***************************
553 *
554 * Access control
555 *
556 ***************************/
557
558 /* Validate whether the current process has priviledges to access
559 * kperf (and by extension, trace). Returns 0 if access is granted.
560 */
561 int
562 kperf_access_check(void)
563 {
564 proc_t p = current_proc();
565 proc_t blessed_p;
566 int ret = 0;
567 boolean_t pid_gone = FALSE;
568
569 /* check if the pid that held the lock is gone */
570 blessed_p = proc_find(blessed_pid);
571
572 if ( blessed_p != NULL )
573 proc_rele(blessed_p);
574 else
575 pid_gone = TRUE;
576
577 if ( blessed_pid == -1 || pid_gone ) {
578 /* check for root */
579 ret = suser(kauth_cred_get(), &p->p_acflag);
580 if( !ret )
581 return ret;
582 }
583
584 /* check against blessed pid */
585 if( p->p_pid != blessed_pid )
586 return EACCES;
587
588 /* access granted. */
589 return 0;
590 }
591
592 /* specify a pid as being able to access kperf/trace, depiste not
593 * being root
594 */
595 int
596 kperf_bless_pid(pid_t newpid)
597 {
598 proc_t p = NULL;
599 pid_t current_pid;
600
601 p = current_proc();
602 current_pid = p->p_pid;
603
604 /* are we allowed to preempt? */
605 if ( (newpid != -1) && (blessed_pid != -1) &&
606 (blessed_pid != current_pid) && !blessed_preempt ) {
607 /* check if the pid that held the lock is gone */
608 p = proc_find(blessed_pid);
609
610 if ( p != NULL ) {
611 proc_rele(p);
612 return EACCES;
613 }
614 }
615
616 /* validate new pid */
617 if ( newpid != -1 ) {
618 p = proc_find(newpid);
619
620 if ( p == NULL )
621 return EINVAL;
622
623 proc_rele(p);
624 }
625
626 /* take trace facility as well */
627 kdbg_swap_global_state_pid(blessed_pid, newpid);
628
629 blessed_pid = newpid;
630 blessed_preempt = FALSE;
631
632 return 0;
633 }
634
635 /***************************
636 *
637 * sysctl hooks
638 *
639 ***************************/
640
641 /* root kperf node */
642 SYSCTL_NODE(, OID_AUTO, kperf, CTLFLAG_RW|CTLFLAG_LOCKED, 0,
643 "kperf");
644
645 /* action sub-section */
646 SYSCTL_NODE(_kperf, OID_AUTO, action, CTLFLAG_RW|CTLFLAG_LOCKED, 0,
647 "action");
648
649 SYSCTL_PROC(_kperf_action, OID_AUTO, count,
650 CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
651 (void*)REQ_ACTION_COUNT,
652 sizeof(int), kperf_sysctl, "I", "Number of actions");
653
654 SYSCTL_PROC(_kperf_action, OID_AUTO, samplers,
655 CTLFLAG_RW|CTLFLAG_ANYBODY,
656 (void*)REQ_ACTION_SAMPLERS,
657 3*sizeof(uint64_t), kperf_sysctl, "UQ",
658 "What to sample what a trigger fires an action");
659
660 SYSCTL_PROC(_kperf_action, OID_AUTO, userdata,
661 CTLFLAG_RW|CTLFLAG_ANYBODY,
662 (void*)REQ_ACTION_USERDATA,
663 3*sizeof(uint64_t), kperf_sysctl, "UQ",
664 "User data to attribute to action");
665
666 SYSCTL_PROC(_kperf_action, OID_AUTO, filter_by_task,
667 CTLFLAG_RW|CTLFLAG_ANYBODY,
668 (void*)REQ_ACTION_FILTER_BY_TASK,
669 3*sizeof(uint64_t), kperf_sysctl, "UQ",
670 "Apply a task filter to the action");
671
672 SYSCTL_PROC(_kperf_action, OID_AUTO, filter_by_pid,
673 CTLFLAG_RW|CTLFLAG_ANYBODY,
674 (void*)REQ_ACTION_FILTER_BY_PID,
675 3*sizeof(uint64_t), kperf_sysctl, "UQ",
676 "Apply a pid filter to the action");
677
678 /* timer sub-section */
679 SYSCTL_NODE(_kperf, OID_AUTO, timer, CTLFLAG_RW|CTLFLAG_LOCKED, 0,
680 "timer");
681
682 SYSCTL_PROC(_kperf_timer, OID_AUTO, count,
683 CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
684 (void*)REQ_TIMER_COUNT,
685 sizeof(int), kperf_sysctl, "I", "Number of time triggers");
686
687 SYSCTL_PROC(_kperf_timer, OID_AUTO, period,
688 CTLFLAG_RW|CTLFLAG_ANYBODY,
689 (void*)REQ_TIMER_PERIOD,
690 2*sizeof(uint64_t), kperf_sysctl, "UQ", "Timer number and period");
691
692 SYSCTL_PROC(_kperf_timer, OID_AUTO, action,
693 CTLFLAG_RW|CTLFLAG_ANYBODY,
694 (void*)REQ_TIMER_ACTION,
695 2*sizeof(uint64_t), kperf_sysctl, "UQ", "Timer number and actionid");
696
697 SYSCTL_PROC(_kperf_timer, OID_AUTO, pet_timer,
698 CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
699 (void*)REQ_TIMER_PET,
700 sizeof(int), kperf_sysctl, "I", "Which timer ID does PET");
701
702 /* misc */
703 SYSCTL_PROC(_kperf, OID_AUTO, sampling,
704 CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
705 (void*)REQ_SAMPLING,
706 sizeof(int), kperf_sysctl, "I", "Sampling running");
707
708 SYSCTL_PROC(_kperf, OID_AUTO, blessed_pid,
709 CTLTYPE_INT|CTLFLAG_RW, /* must be root */
710 (void*)REQ_BLESS,
711 sizeof(int), kperf_sysctl_bless_handler, "I", "Blessed pid");
712
713 SYSCTL_PROC(_kperf, OID_AUTO, blessed_preempt,
714 CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
715 (void*)REQ_BLESS_PREEMPT,
716 sizeof(int), kperf_sysctl, "I", "Blessed preemption");
717
718
719 SYSCTL_PROC(_kperf, OID_AUTO, kdbg_callstacks,
720 CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
721 (void*)REQ_KDBG_CALLSTACKS,
722 sizeof(int), kperf_sysctl, "I", "Generate kdbg callstacks");
723
724 SYSCTL_INT(_kperf, OID_AUTO, kdbg_cswitch,
725 CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
726 &kperf_cswitch_hook, 0, "Generate context switch info");
727
728 SYSCTL_PROC(_kperf, OID_AUTO, pet_idle_rate,
729 CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
730 (void*)REQ_PET_IDLE_RATE,
731 sizeof(int), kperf_sysctl, "I", "Rate at which unscheduled threads are forced to be sampled in PET mode");
732
733 /* debug */
734 SYSCTL_INT(_kperf, OID_AUTO, debug_level, CTLFLAG_RW,
735 &kperf_debug_level, 0, "debug level");
736