]> git.saurik.com Git - apple/xnu.git/blob - osfmk/kperf/kperfbsd.c
xnu-2050.48.11.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 <libkern/libkern.h>
36
37 #include <kperf/context.h>
38 #include <kperf/action.h>
39 #include <kperf/timetrigger.h>
40 #include <kperf/pet.h>
41 #include <kperf/filter.h>
42 #include <kperf/kperfbsd.h>
43 #include <kperf/kperf.h>
44
45 #define REQ_SAMPLING (1)
46 #define REQ_ACTION_COUNT (2)
47 #define REQ_ACTION_SAMPLERS (3)
48 #define REQ_TIMER_COUNT (4)
49 #define REQ_TIMER_PERIOD (5)
50 #define REQ_TIMER_PET (6)
51
52
53 static int
54 sysctl_timer_period( __unused struct sysctl_oid *oidp, struct sysctl_req *req )
55 {
56 int error = 0;
57 uint64_t inputs[2], retval;
58 unsigned timer, set = 0;
59
60 /* get 2x 64-bit words */
61 error = SYSCTL_IN( req, inputs, 2*sizeof(inputs[0]) );
62 if(error)
63 {
64 printf( "error in\n" );
65 return (error);
66 }
67
68 /* setup inputs */
69 timer = (unsigned) inputs[0];
70 if( inputs[1] != ~0ULL )
71 set = 1;
72
73 printf( "%s timer: %u, inp[0] %llu\n", set ? "set" : "get",
74 timer, inputs[0] );
75
76 if( set )
77 {
78 printf( "timer set period\n" );
79 error = kperf_timer_set_period( timer, inputs[1] );
80 if( error )
81 return error;
82 }
83
84 error = kperf_timer_get_period(timer, &retval);
85 if(error)
86 {
87 printf( "error get period\n" );
88 return (error);
89 }
90
91 inputs[1] = retval;
92
93 if( error == 0 )
94 {
95 error = SYSCTL_OUT( req, inputs, 2*sizeof(inputs[0]) );
96 if( error )
97 printf( "error out\n" );
98 }
99
100 return error;
101 }
102
103 static int
104 sysctl_action_samplers( __unused struct sysctl_oid *oidp,
105 struct sysctl_req *req )
106 {
107 int error = 0;
108 uint64_t inputs[3];
109 uint32_t retval;
110 unsigned actionid, set = 0;
111
112 /* get 3x 64-bit words */
113 error = SYSCTL_IN( req, inputs, 3*sizeof(inputs[0]) );
114 if(error)
115 {
116 printf( "error in\n" );
117 return (error);
118 }
119
120 /* setup inputs */
121 set = (unsigned) inputs[0];
122 actionid = (unsigned) inputs[1];
123
124 if( set )
125 {
126 error = kperf_action_set_samplers( actionid, inputs[2] );
127 if( error )
128 return error;
129 }
130
131 printf("set %d actionid %u samplers val %u\n",
132 set, actionid, (unsigned) inputs[2] );
133
134 error = kperf_action_get_samplers(actionid, &retval);
135 if(error)
136 {
137 printf( "error get samplers\n" );
138 return (error);
139 }
140
141 inputs[2] = retval;
142
143 if( error == 0 )
144 {
145 error = SYSCTL_OUT( req, inputs, 3*sizeof(inputs[0]) );
146 if( error )
147 printf( "error out\n" );
148 }
149
150 return error;
151 }
152
153 static int
154 sysctl_sampling( struct sysctl_oid *oidp, struct sysctl_req *req )
155 {
156 int error = 0;
157 uint32_t value = 0;
158
159 /* get the old value and process it */
160 value = kperf_sampling_status();
161
162 /* copy out the old value, get the new value */
163 error = sysctl_handle_int(oidp, &value, 0, req);
164 if (error || !req->newptr)
165 return (error);
166
167 printf( "setting sampling to %d\n", value );
168
169 /* if that worked, and we're writing... */
170 if( value )
171 error = kperf_sampling_enable();
172 else
173 error = kperf_sampling_disable();
174
175 return error;
176 }
177
178 static int
179 sysctl_action_count( struct sysctl_oid *oidp, struct sysctl_req *req )
180 {
181 int error = 0;
182 uint32_t value = 0;
183
184 /* get the old value and process it */
185 value = kperf_action_get_count();
186
187 /* copy out the old value, get the new value */
188 error = sysctl_handle_int(oidp, &value, 0, req);
189 if (error || !req->newptr)
190 return (error);
191
192 printf( "setting action count to %d\n", value );
193
194 /* if that worked, and we're writing... */
195 return kperf_action_set_count(value);
196 }
197
198 static int
199 sysctl_timer_count( struct sysctl_oid *oidp, struct sysctl_req *req )
200 {
201 int error = 0;
202 uint32_t value = 0;
203
204 /* get the old value and process it */
205 value = kperf_timer_get_count();
206
207 /* copy out the old value, get the new value */
208 error = sysctl_handle_int(oidp, &value, 0, req);
209 if (error || !req->newptr)
210 return (error);
211
212 printf( "setting timer count to %d\n", value );
213
214 /* if that worked, and we're writing... */
215 return kperf_timer_set_count(value);
216 }
217
218 static int
219 sysctl_timer_pet( struct sysctl_oid *oidp, struct sysctl_req *req )
220 {
221 int error = 0;
222 uint32_t value = 0;
223
224 /* get the old value and process it */
225 value = kperf_timer_get_petid();
226
227 /* copy out the old value, get the new value */
228 error = sysctl_handle_int(oidp, &value, 0, req);
229 if (error || !req->newptr)
230 return (error);
231
232 printf( "setting timer petid to %d\n", value );
233
234 /* if that worked, and we're writing... */
235 return kperf_timer_set_petid(value);
236 }
237
238 /*
239 * #define SYSCTL_HANDLER_ARGS (struct sysctl_oid *oidp, \
240 * void *arg1, int arg2, \
241 * struct sysctl_req *req )
242 */
243 static int
244 kperf_sysctl SYSCTL_HANDLER_ARGS
245 {
246 // __unused struct sysctl_oid *unused_oidp = oidp;
247 (void)arg2;
248
249 /* which request */
250 switch( (uintptr_t) arg1 )
251 {
252 case REQ_ACTION_COUNT:
253 return sysctl_action_count( oidp, req );
254 case REQ_ACTION_SAMPLERS:
255 return sysctl_action_samplers( oidp, req );
256 case REQ_TIMER_COUNT:
257 return sysctl_timer_count( oidp, req );
258 case REQ_TIMER_PERIOD:
259 return sysctl_timer_period( oidp, req );
260 case REQ_TIMER_PET:
261 return sysctl_timer_pet( oidp, req );
262 case REQ_SAMPLING:
263 return sysctl_sampling( oidp, req );
264
265 #if 0
266 case REQ_TIMER:
267 return sysctl_timer_period( req );
268 case REQ_PET:
269 return sysctl_pet_period( req );
270 #endif
271 default:
272 return ENOENT;
273 }
274 }
275
276 /* root kperf node */
277 SYSCTL_NODE(, OID_AUTO, kperf, CTLFLAG_RW|CTLFLAG_LOCKED, 0,
278 "kperf");
279
280 /* action sub-section */
281 SYSCTL_NODE(_kperf, OID_AUTO, action, CTLFLAG_RW|CTLFLAG_LOCKED, 0,
282 "action");
283
284 SYSCTL_PROC(_kperf_action, OID_AUTO, count,
285 CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
286 (void*)REQ_ACTION_COUNT,
287 sizeof(int), kperf_sysctl, "I", "Number of actions");
288
289 SYSCTL_PROC(_kperf_action, OID_AUTO, samplers,
290 CTLFLAG_RW|CTLFLAG_ANYBODY,
291 (void*)REQ_ACTION_SAMPLERS,
292 3*sizeof(uint64_t), kperf_sysctl, "UQ",
293 "What to sample what a trigger fires an action");
294
295 /* timer sub-section */
296 SYSCTL_NODE(_kperf, OID_AUTO, timer, CTLFLAG_RW|CTLFLAG_LOCKED, 0,
297 "timer");
298
299 SYSCTL_PROC(_kperf_timer, OID_AUTO, count,
300 CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
301 (void*)REQ_TIMER_COUNT,
302 sizeof(int), kperf_sysctl, "I", "Number of time triggers");
303
304 SYSCTL_PROC(_kperf_timer, OID_AUTO, period,
305 CTLFLAG_RW|CTLFLAG_ANYBODY,
306 (void*)REQ_TIMER_PERIOD,
307 2*sizeof(uint64_t), kperf_sysctl, "UQ", "Timer number and period");
308
309 SYSCTL_PROC(_kperf_timer, OID_AUTO, pet_timer,
310 CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
311 (void*)REQ_TIMER_PET,
312 sizeof(int), kperf_sysctl, "I", "Which timer ID does PET");
313
314 /* misc */
315 SYSCTL_PROC(_kperf, OID_AUTO, sampling,
316 CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
317 (void*)REQ_SAMPLING,
318 sizeof(int), kperf_sysctl, "I", "Sampling running");
319
320 int legacy_mode = 1;
321 SYSCTL_INT(_kperf, OID_AUTO, legacy_mode, CTLFLAG_RW, &legacy_mode, 0, "legacy_mode");
322
323 #if 0
324 SYSCTL_PROC(_kperf, OID_AUTO, timer_period,
325 CTLFLAG_RW, (void*)REQ_TIMER,
326 sizeof(uint64_t), kperf_sysctl, "QU", "nanoseconds");
327
328 SYSCTL_PROC(_kperf, OID_AUTO, pet_period,
329 CTLFLAG_RW, (void*)REQ_PET,
330 sizeof(uint64_t), kperf_sysctl, "QU", "nanoseconds");
331
332 /* FIXME: do real stuff */
333 SYSCTL_INT(_kperf, OID_AUTO, filter_pid0,
334 CTLFLAG_RW, &pid_list[0], 0, "");
335 SYSCTL_INT(_kperf, OID_AUTO, filter_pid1,
336 CTLFLAG_RW, &pid_list[1], 0, "");
337 SYSCTL_INT(_kperf, OID_AUTO, filter_pid2,
338 CTLFLAG_RW, &pid_list[2], 0, "");
339 SYSCTL_INT(_kperf, OID_AUTO, filter_pid3,
340 CTLFLAG_RW, &pid_list[3], 0, "");
341
342 #endif